Index: lib/src/int64.dart |
diff --git a/lib/src/int64.dart b/lib/src/int64.dart |
index 641bf71e139600fe39a0057d09f33b93c5ad1e7b..2ff48229a97845f13998a6a04c8d0a99e76af582 100644 |
--- a/lib/src/int64.dart |
+++ b/lib/src/int64.dart |
@@ -30,7 +30,7 @@ class Int64 implements IntX { |
static const int _MASK = 4194303; // (1 << _BITS) - 1 |
static const int _MASK2 = 1048575; // (1 << _BITS2) - 1 |
static const int _SIGN_BIT = 19; // _BITS2 - 1 |
- static const int _SIGN_BIT_MASK = 524288; // 1 << _SIGN_BIT |
+ static const int _SIGN_BIT_MASK = 1 << _SIGN_BIT; |
/** |
* The maximum positive value attainable by an [Int64], namely |
@@ -70,10 +70,7 @@ class Int64 implements IntX { |
* [Int64]. |
*/ |
static Int64 parseRadix(String s, int radix) { |
- if ((radix <= 1) || (radix > 36)) { |
- throw new ArgumentError("Bad radix: $radix"); |
- } |
- return _parseRadix(s, radix); |
+ return _parseRadix(s, Int32._validateRadix(radix)); |
} |
static Int64 _parseRadix(String s, int radix) { |
@@ -83,9 +80,7 @@ class Int64 implements IntX { |
negative = true; |
i++; |
} |
- int d0 = 0, |
- d1 = 0, |
- d2 = 0; // low, middle, high components. |
+ int d0 = 0, d1 = 0, d2 = 0; // low, middle, high components. |
for (; i < s.length; i++) { |
int c = s.codeUnitAt(i); |
int digit = Int32._decodeDigit(c); |
@@ -109,7 +104,7 @@ class Int64 implements IntX { |
if (negative) return _negate(d0, d1, d2); |
- return new Int64._bits(d0, d1, d2); |
+ return Int64._masked(d0, d1, d2); |
} |
/** |
@@ -129,27 +124,20 @@ class Int64 implements IntX { |
/** |
* Constructs an [Int64] with a given [int] value; zero by default. |
*/ |
- factory Int64([int value = 0]) { |
- int v0 = 0, |
- v1 = 0, |
- v2 = 0; |
+ factory Int64([int value=0]) { |
+ int v0 = 0, v1 = 0, v2 = 0; |
bool negative = false; |
if (value < 0) { |
negative = true; |
value = -value - 1; |
} |
- if (_haveBigInts) { |
- v0 = _MASK & value; |
- v1 = _MASK & (value >> _BITS); |
- v2 = _MASK2 & (value >> _BITS01); |
- } else { |
- // Avoid using bitwise operations that coerce their input to 32 bits. |
- v2 = value ~/ 17592186044416; // 2^44 |
- value -= v2 * 17592186044416; |
- v1 = value ~/ 4194304; // 2^22 |
- value -= v1 * 4194304; |
- v0 = value; |
- } |
+ // Avoid using bitwise operations that in JavaScript coerce their input to |
+ // 32 bits. |
+ v2 = value ~/ 17592186044416; // 2^44 |
+ value -= v2 * 17592186044416; |
+ v1 = value ~/ 4194304; // 2^22 |
+ value -= v1 * 4194304; |
+ v0 = value; |
if (negative) { |
v0 = ~v0; |
@@ -197,7 +185,7 @@ class Int64 implements IntX { |
bottom |= bytes[7] & 0xff; |
return new Int64.fromInts(top, bottom); |
- } |
+ } |
/** |
* Constructs an [Int64] from a pair of 32-bit integers having the value |
@@ -206,23 +194,23 @@ class Int64 implements IntX { |
factory Int64.fromInts(int top, int bottom) { |
top &= 0xffffffff; |
bottom &= 0xffffffff; |
- int d0 = bottom & _MASK; |
- int d1 = ((top & 0xfff) << 10) | ((bottom >> _BITS) & 0x3ff); |
- int d2 = (top >> 12) & _MASK2; |
- return new Int64._bits(d0, d1, d2); |
+ int d0 = _MASK & bottom; |
+ int d1 = ((0xfff & top) << 10) | (0x3ff & (bottom >> _BITS)); |
+ int d2 = _MASK2 & (top >> 12); |
+ return Int64._masked(d0, d1, d2); |
} |
// Returns the [Int64] representation of the specified value. Throws |
// [ArgumentError] for non-integer arguments. |
- static Int64 _promote(val) { |
- if (val is Int64) { |
- return val; |
- } else if (val is int) { |
- return new Int64(val); |
- } else if (val is Int32) { |
- return val.toInt64(); |
+ static Int64 _promote(value) { |
+ if (value is Int64) { |
+ return value; |
+ } else if (value is int) { |
+ return new Int64(value); |
+ } else if (value is Int32) { |
+ return value.toInt64(); |
} |
- throw new ArgumentError(val); |
+ throw new ArgumentError.value(value); |
} |
Int64 operator +(other) { |
@@ -316,12 +304,9 @@ class Int64 implements IntX { |
// Propagate high bits from c0 -> c1, c1 -> c2. |
c1 += c0 >> _BITS; |
- c0 &= _MASK; |
c2 += c1 >> _BITS; |
- c1 &= _MASK; |
- c2 &= _MASK2; |
- return new Int64._bits(c0, c1, c2); |
+ return Int64._masked(c0, c1, c2); |
} |
Int64 operator %(other) => _divide(this, other, _RETURN_MOD); |
@@ -335,7 +320,7 @@ class Int64 implements IntX { |
int a0 = _l & o._l; |
int a1 = _m & o._m; |
int a2 = _h & o._h; |
- return new Int64._bits(a0, a1, a2); |
+ return Int64._masked(a0, a1, a2); |
} |
Int64 operator |(other) { |
@@ -343,7 +328,7 @@ class Int64 implements IntX { |
int a0 = _l | o._l; |
int a1 = _m | o._m; |
int a2 = _h | o._h; |
- return new Int64._bits(a0, a1, a2); |
+ return Int64._masked(a0, a1, a2); |
} |
Int64 operator ^(other) { |
@@ -351,7 +336,7 @@ class Int64 implements IntX { |
int a0 = _l ^ o._l; |
int a1 = _m ^ o._m; |
int a2 = _h ^ o._h; |
- return new Int64._bits(a0, a1, a2); |
+ return Int64._masked(a0, a1, a2); |
} |
Int64 operator ~() { |
@@ -360,7 +345,7 @@ class Int64 implements IntX { |
Int64 operator <<(int n) { |
if (n < 0) { |
- throw new ArgumentError(n); |
+ throw new ArgumentError.value(n); |
} |
n &= 63; |
@@ -384,7 +369,7 @@ class Int64 implements IntX { |
Int64 operator >>(int n) { |
if (n < 0) { |
- throw new ArgumentError(n); |
+ throw new ArgumentError.value(n); |
} |
n &= 63; |
@@ -427,7 +412,7 @@ class Int64 implements IntX { |
Int64 shiftRightUnsigned(int n) { |
if (n < 0) { |
- throw new ArgumentError(n); |
+ throw new ArgumentError.value(n); |
} |
n &= 63; |
@@ -473,7 +458,9 @@ class Int64 implements IntX { |
return false; |
} |
- int compareTo(Comparable other) { |
+ int compareTo(Comparable other) =>_compareTo(other); |
+ |
+ int _compareTo(other) { |
Int64 o = _promote(other); |
int signa = _h >> (_BITS2 - 1); |
int signb = o._h >> (_BITS2 - 1); |
@@ -498,21 +485,10 @@ class Int64 implements IntX { |
return 0; |
} |
- bool operator <(other) { |
- return this.compareTo(other) < 0; |
- } |
- |
- bool operator <=(other) { |
- return this.compareTo(other) <= 0; |
- } |
- |
- bool operator >(other) { |
- return this.compareTo(other) > 0; |
- } |
- |
- bool operator >=(other) { |
- return this.compareTo(other) >= 0; |
- } |
+ bool operator <(other) => _compareTo(other) < 0; |
+ bool operator <=(other) => _compareTo(other) <= 0; |
+ bool operator >(other) => this._compareTo(other) > 0; |
+ bool operator >=(other) => _compareTo(other) >= 0; |
bool get isEven => (_l & 0x1) == 0; |
bool get isMaxValue => (_h == _MASK2 >> 1) && _m == _MASK && _l == _MASK; |
@@ -523,9 +499,7 @@ class Int64 implements IntX { |
int get bitLength { |
if (isZero) return 0; |
- int a0 = _l, |
- a1 = _m, |
- a2 = _h; |
+ int a0 = _l, a1 = _m, a2 = _h; |
if (isNegative) { |
a0 = _MASK & ~a0; |
a1 = _MASK & ~a1; |
@@ -601,24 +575,24 @@ class Int64 implements IntX { |
} |
Int64 toSigned(int width) { |
- if (width < 1 || width > 64) throw new ArgumentError(width); |
+ if (width < 1 || width > 64) throw new RangeError.range(width, 1, 64); |
if (width > _BITS01) { |
return Int64._masked(_l, _m, _h.toSigned(width - _BITS01)); |
} else if (width > _BITS) { |
int m = _m.toSigned(width - _BITS); |
return m.isNegative |
? Int64._masked(_l, m, _MASK2) |
- : Int64._masked(_l, m, 0); // Masking for type inferrer. |
+ : Int64._masked(_l, m, 0); // Masking for type inferrer. |
} else { |
int l = _l.toSigned(width); |
return l.isNegative |
? Int64._masked(l, _MASK, _MASK2) |
- : Int64._masked(l, 0, 0); // Masking for type inferrer. |
+ : Int64._masked(l, 0, 0); // Masking for type inferrer. |
} |
} |
Int64 toUnsigned(int width) { |
- if (width < 0 || width > 64) throw new ArgumentError(width); |
+ if (width < 0 || width > 64) throw new RangeError.range(width, 0, 64); |
if (width > _BITS01) { |
int h = _h.toUnsigned(width - _BITS01); |
return Int64._masked(_l, _m, h); |
@@ -650,23 +624,15 @@ class Int64 implements IntX { |
int l = _l; |
int m = _m; |
int h = _h; |
- bool negative = false; |
+ // In the sum we add least significant to most significant so that in |
+ // JavaScript double arithmetic rounding occurs on only the last addition. |
if ((_h & _SIGN_BIT_MASK) != 0) { |
l = _MASK & ~_l; |
m = _MASK & ~_m; |
h = _MASK2 & ~_h; |
- negative = true; |
- } |
- |
- if (_haveBigInts) { |
- int result = (h << _BITS01) | (m << _BITS) | l; |
- return negative ? -result - 1 : result; |
+ return -((1 + l) + (4194304 * m) + (17592186044416 * h)); |
} else { |
- if (negative) { |
- return -((l + 1) + (m * 4194304) + (h * 17592186044416)); |
- } else { |
- return (l + (m * 4194304)) + (h * 17592186044416); |
- } |
+ return l + (4194304 * m) + (17592186044416 * h); |
} |
} |
@@ -692,7 +658,6 @@ class Int64 implements IntX { |
if (isZero) return "0"; |
Int64 x = this; |
String hexStr = ""; |
- Int64 digit_f = new Int64(0xf); |
while (!x.isZero) { |
int digit = x._l & 0xf; |
hexStr = "${_hexDigit(digit)}$hexStr"; |
@@ -702,10 +667,7 @@ class Int64 implements IntX { |
} |
String toRadixString(int radix) { |
- if ((radix <= 1) || (radix > 36)) { |
- throw new ArgumentError("Bad radix: $radix"); |
- } |
- return _toRadixString(radix); |
+ return _toRadixString(Int32._validateRadix(radix)); |
} |
String _toRadixString(int radix) { |
@@ -764,9 +726,7 @@ class Int64 implements IntX { |
// need only two chunks, but radix values 17-19 and 33-36 generate only 15 |
// or 16 bits per iteration, so sometimes the third chunk is needed. |
- String chunk1 = "", |
- chunk2 = "", |
- chunk3 = ""; |
+ String chunk1 = "", chunk2 = "", chunk3 = ""; |
while (!(d4 == 0 && d3 == 0)) { |
int q = d4 ~/ fatRadix; |
@@ -867,24 +827,6 @@ class Int64 implements IntX { |
return _sub(0, 0, 0, b0, b1, b2); |
} |
- // Determine whether the platform supports ints greater than 2^53 |
- // without loss of precision. |
- static bool _haveBigIntsCached = null; |
- |
- static bool get _haveBigInts { |
- if (_haveBigIntsCached == null) { |
- var x = 9007199254740992; |
- // Defeat compile-time constant folding. |
- if (2 + 2 != 4) { |
- x = 0; |
- } |
- var y = x + 1; |
- var same = y == x; |
- _haveBigIntsCached = !same; |
- } |
- return _haveBigIntsCached; |
- } |
- |
String _hexDigit(int digit) => "0123456789ABCDEF"[digit]; |
// Work around dart2js bugs with negative arguments to '>>' operator. |
@@ -930,15 +872,11 @@ class Int64 implements IntX { |
static _divideHelper( |
// up to 64 bits unsigned in a2/a1/a0 and b2/b1/b0 |
- int a0, int a1, int a2, bool aNeg, // input A. |
- int b0, int b1, int b2, bool bNeg, // input B. |
+ int a0, int a1, int a2, bool aNeg, // input A. |
+ int b0, int b1, int b2, bool bNeg, // input B. |
int what) { |
- int q0 = 0, |
- q1 = 0, |
- q2 = 0; // result Q. |
- int r0 = 0, |
- r1 = 0, |
- r2 = 0; // result R. |
+ int q0 = 0, q1 = 0, q2 = 0; // result Q. |
+ int r0 = 0, r1 = 0, r2 = 0; // result R. |
if (b2 == 0 && b1 == 0 && b0 < (1 << (30 - _BITS))) { |
// Small divisor can be handled by single-digit division within Smi range. |
@@ -986,7 +924,7 @@ class Int64 implements IntX { |
q0 = q0d.toInt(); |
assert(q0 + K1 * q1 + K2 * q2 == (ad / bd).floorToDouble()); |
- assert(q2 == 0 || b2 == 0); // Q and B can't both be big since Q*B <= A. |
+ assert(q2 == 0 || b2 == 0); // Q and B can't both be big since Q*B <= A. |
// P = Q * B, using doubles to hold intermediates. |
// We don't need all partial sums since Q*B <= A. |
@@ -997,7 +935,7 @@ class Int64 implements IntX { |
double p1carry = (p1d / K1).floorToDouble(); |
p1d = p1d - p1carry * K1; |
double p2d = q2d * b0 + q1d * b1 + q0d * b2 + p1carry; |
- assert(p2d <= _MASK2); // No partial sum overflow. |
+ assert(p2d <= _MASK2); // No partial sum overflow. |
// R = A - P |
int diff0 = a0 - p0d.toInt(); |
@@ -1009,7 +947,8 @@ class Int64 implements IntX { |
// while (R < 0 || R >= B) |
// adjust R towards [0, B) |
- while (r2 >= _SIGN_BIT_MASK || |
+ while ( |
+ r2 >= _SIGN_BIT_MASK || |
r2 > b2 || |
(r2 == b2 && (r1 > b1 || (r1 == b1 && r0 >= b0)))) { |
// Direction multiplier for adjustment. |
@@ -1034,17 +973,17 @@ class Int64 implements IntX { |
// 0 <= R < B |
assert(Int64.ZERO <= new Int64._bits(r0, r1, r2)); |
- assert(r2 < b2 || // Handles case where B = -(MIN_VALUE) |
+ assert(r2 < b2 || // Handles case where B = -(MIN_VALUE) |
new Int64._bits(r0, r1, r2) < new Int64._bits(b0, b1, b2)); |
assert(what == _RETURN_DIV || what == _RETURN_MOD || what == _RETURN_REM); |
if (what == _RETURN_DIV) { |
if (aNeg != bNeg) return _negate(q0, q1, q2); |
- return Int64._masked(q0, q1, q2); // Masking for type inferrer. |
+ return Int64._masked(q0, q1, q2); // Masking for type inferrer. |
} |
if (!aNeg) { |
- return new Int64._bits(_MASK & r0, r1, r2); // Masking for type inferrer. |
+ return Int64._masked(r0, r1, r2); // Masking for type inferrer. |
} |
if (what == _RETURN_MOD) { |