-
Notifications
You must be signed in to change notification settings - Fork 207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementation issue for unsigned/triple-shift >>> operator #478
Comments
waiting for this operator to be in release |
@lrhn what's the story with this? @aadilmaan @mit-mit – are we tracking this somewhere? Related: https://stackoverflow.com/questions/57190508/does-dart-have-operator/57210971 |
This is now tracked in #120. Closing the present historical issue. |
Transferring and re-purposing to be the implementation issue for this feature. Please note that this isn't currently being implemented, it's just ready for implementation. |
Is there a status on this? It would be massively helpful for cryptography. |
I don't think this would be too difficult. I haven't tried forking dart's internals, but I'm using a utility extension function. Converted to an operator, it would look like. (EDIT: JS is hard) int operator >>> (int n) {
return ((this >= 0) ? this >> (n) : ~(~this >> (n)));
} |
The code snippet I posted was wrong. I fixed it. It's tested and works on the VM, but does not work when trans-piled to JS. |
New code snippet, which works both on the VM and when trans-piled to JS. (EDIT: it doesn't; it's broken for JS for negative numbers; see below) int operator >>> (int count) {
if (!isJS) {
return (this >= 0) ? this >> count : ~(~this >> count);
} else {
count &= 0x1f;
if (this >= 0) {
return (this >> count + 1);
} else {
var mask = 1 << (31 - count);
return (~this >> count) | mask;
}
}
}
bool get isJS {
// Some definition here...
} I dunno about performance, but I use only bitwise operators, so it should be decent. It's tested on the VM and DartPad. All cases (negative, zero, positive) check out for both. If someone could guide me through the process, I'd be happy to try and implement the >>> operator as a language feature. |
@AKushWarrior what is |
Nothing. It was a remnant from me testing the function in a different setup than the extension method presented here. It should be fixed now. |
Neither quite works for me. This is the code I'm testing: (3185753779 * 3185753779).tripleShift(32) On DartPad, I get |
@mpfaff I'll review at some point. I'm kinda swamped and I didn't really test it super extensively, just with 10 or so test cases. |
@mpfaff new DartPad code is below and seems to work fine on DartPad. If you could try to break it with more cases, that would be great. All test cases have been generated using TypeScript. void main() {
//positive
print((3185753779 * 3185753779).tripleShift(32) == 2417635328);
print(25.tripleShift(25) == 0);
print(13123423.tripleShift(5) == 410106);
//zero
print(0.tripleShift(23) == 0);
//negative
print((-12245234).tripleShift(11) == 2091172);
print((-2938648).tripleShift(4) == 268251790);
}
extension tripShift on int {
int tripleShift (int count) {
if (false) {
return (this >= 0) ? this >> count : ~(~this >> count);
} else {
// assumes this > -4294967295, or -(2^32 -1)
count &= 0x1f;
if (this >= 0) {
return (this >> count);
} else {
return (this >> count) ^ ((0xFFFFFFFF) ^ ((1 << (32-count)) - 1));
}
}
}
} |
There should be a difference between how zero-fill right shift works on the web and on the VM: 64-bit numbers which have been zero-fill right shifted are very different from 32-bit numbers which have been zero-fill right shifted. |
It is on a shortlist of small, useful features: #1077. |
Neither of your implementations work properly. Many of your tests also expects the wrong result: (3185753779 * 3185753779) == -8297716933296770775;
// 1000110011011000100101100110100110010000000110100011000100101001
(3185753779 * 3185753779) >>> 32 == 2363004521;
// 10001100110110001001011001101001
(3185753779 * 3185753779) >>> 32 != 2417635328;
// 10010000000110100011000000000000 This is the correct implementation for Dart Native: extension TripleShift on int {
int tripleShift(int count) {
return (this >> count) & ~(-1 << (64 - count));
}
} |
I'm matching the JS version. While you are mathematically right, a programmer is likely to be confused that using >>> in dart2js results in a different value than pure js. |
JavaScript only defines bitwise operations on 32-bit unsigned integers, so even when you do You would need something like Int64 to emulate 64-bit values and operations: BigInt would be another solution, but Dart is yet to support it. |
Dart integers, when translated to JS, are 32 bit, not 53 bit. While I agree that we should have clearer types (or just standardize the fixnum types), that would break all existing code. When using Dart for JS, you have to assume that all your integers are 32 bit, or just use https://pub.dev/packages/fixnum. Dart integers, to the best of my knowledge, are not meant to emulate 64 bit integers when transpiled to JS. Instead of trying to create a solution that produces the same results on both Native and JS, which doesn't make sense given the nature of both platforms, I created a separate version which matches the ES6 results for >>>. All those test cases were designed to be run on DartPad, which transpiles code to JS before running it. EDIT: In fact, your native code is not platform agnostic either. If you evaluate that code after transpilation to JS, it will result in incorrect shifts (due to 32 bit truncation). |
Not quite: Dart numbers are represented as JavaScript numbers when compiled to JavaScript. A number However, bitwise operations work on 32 bits and treat them as an unsigned number (cf. this comment). So |
Interesting. The only time I considered the bit length of integers was when doing bitwise ops, so I guess it never occurred to me.
This is in line with my example. My newest DartPad example works with expected results from the target language (JS). |
Note: added analyzer subtask above dart-lang/sdk#44908 |
Closing: This feature was enabled by default in 2.14. |
The unsigned right shift was [implemented](dart-lang/language#478 (comment)) Closes #47227 #47227 GitOrigin-RevId: ec84d68 Change-Id: Iafc195c8df212c8f78330f6ebef230daa6a6d280 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/213560 Reviewed-by: Kevin Moore <[email protected]> Commit-Queue: Kevin Moore <[email protected]>
This is the implementation issue for the triple-shift
>>>
operator (unsigned shift), see language feature #120The operator has the same precedence as
>>
.The expression
e1 >>> e2
is a compile-time constant expression if bothe1
ande2
are compile-time constant expressions evaluating to integers (andint
will implement the operator).The symbol
#>>>
is valid (along withconst Symbol(">>>")
), as isx >>>= e
as an expression.Adding the new operator is non-breaking.
The text was updated successfully, but these errors were encountered: