Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of fixnum; | 5 part of fixnum; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * An immutable 64-bit signed integer, in the range [-2^63, 2^63 - 1]. | 8 * An immutable 64-bit signed integer, in the range [-2^63, 2^63 - 1]. |
| 9 * Arithmetic operations may overflow in order to maintain this range. | 9 * Arithmetic operations may overflow in order to maintain this range. |
| 10 */ | 10 */ |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 97 d1 = d1 * radix + carry; | 97 d1 = d1 * radix + carry; |
| 98 carry = d1 >> _BITS; | 98 carry = d1 >> _BITS; |
| 99 d1 = _MASK & d1; | 99 d1 = _MASK & d1; |
| 100 | 100 |
| 101 d2 = d2 * radix + carry; | 101 d2 = d2 * radix + carry; |
| 102 d2 = _MASK2 & d2; | 102 d2 = _MASK2 & d2; |
| 103 } | 103 } |
| 104 | 104 |
| 105 if (negative) return _negate(d0, d1, d2); | 105 if (negative) return _negate(d0, d1, d2); |
| 106 | 106 |
| 107 return new Int64._bits(d0, d1, d2); | 107 //return new Int64._bits(d0, d1, d2); |
|
Chris Bracken
2015/12/11 20:32:05
delete
| |
| 108 return Int64._masked(d0, d1, d2); | |
| 108 } | 109 } |
| 109 | 110 |
| 110 /** | 111 /** |
| 111 * Parses a decimal [String] and returns an [Int64]. | 112 * Parses a decimal [String] and returns an [Int64]. |
| 112 */ | 113 */ |
| 113 static Int64 parseInt(String s) => _parseRadix(s, 10); | 114 static Int64 parseInt(String s) => _parseRadix(s, 10); |
| 114 | 115 |
| 115 /** | 116 /** |
| 116 * Parses a hexadecimal [String] and returns an [Int64]. | 117 * Parses a hexadecimal [String] and returns an [Int64]. |
| 117 */ | 118 */ |
| 118 static Int64 parseHex(String s) => _parseRadix(s, 16); | 119 static Int64 parseHex(String s) => _parseRadix(s, 16); |
| 119 | 120 |
| 120 // | 121 // |
| 121 // Public constructors | 122 // Public constructors |
| 122 // | 123 // |
| 123 | 124 |
| 124 /** | 125 /** |
| 125 * Constructs an [Int64] with a given [int] value; zero by default. | 126 * Constructs an [Int64] with a given [int] value; zero by default. |
| 126 */ | 127 */ |
| 127 factory Int64([int value=0]) { | 128 factory Int64([int value=0]) { |
| 128 int v0 = 0, v1 = 0, v2 = 0; | 129 int v0 = 0, v1 = 0, v2 = 0; |
| 129 bool negative = false; | 130 bool negative = false; |
| 130 if (value < 0) { | 131 if (value < 0) { |
| 131 negative = true; | 132 negative = true; |
| 132 value = -value - 1; | 133 value = -value - 1; |
| 133 } | 134 } |
| 134 if (_haveBigInts) { | 135 // Avoid using bitwise operations that in JavaScript coerce their input to |
| 135 v0 = _MASK & value; | 136 // 32 bits. |
| 136 v1 = _MASK & (value >> _BITS); | 137 v2 = value ~/ 17592186044416; // 2^44 |
| 137 v2 = _MASK2 & (value >> _BITS01); | 138 value -= v2 * 17592186044416; |
| 138 } else { | 139 v1 = value ~/ 4194304; // 2^22 |
| 139 // Avoid using bitwise operations that coerce their input to 32 bits. | 140 value -= v1 * 4194304; |
| 140 v2 = value ~/ 17592186044416; // 2^44 | 141 v0 = value; |
| 141 value -= v2 * 17592186044416; | |
| 142 v1 = value ~/ 4194304; // 2^22 | |
| 143 value -= v1 * 4194304; | |
| 144 v0 = value; | |
| 145 } | |
| 146 | 142 |
| 147 if (negative) { | 143 if (negative) { |
| 148 v0 = ~v0; | 144 v0 = ~v0; |
| 149 v1 = ~v1; | 145 v1 = ~v1; |
| 150 v2 = ~v2; | 146 v2 = ~v2; |
| 151 } | 147 } |
| 152 return Int64._masked(v0, v1, v2); | 148 return Int64._masked(v0, v1, v2); |
| 153 } | 149 } |
| 154 | 150 |
| 155 factory Int64.fromBytes(List<int> bytes) { | 151 factory Int64.fromBytes(List<int> bytes) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 195 /** | 191 /** |
| 196 * Constructs an [Int64] from a pair of 32-bit integers having the value | 192 * Constructs an [Int64] from a pair of 32-bit integers having the value |
| 197 * [:((top & 0xffffffff) << 32) | (bottom & 0xffffffff):]. | 193 * [:((top & 0xffffffff) << 32) | (bottom & 0xffffffff):]. |
| 198 */ | 194 */ |
| 199 factory Int64.fromInts(int top, int bottom) { | 195 factory Int64.fromInts(int top, int bottom) { |
| 200 top &= 0xffffffff; | 196 top &= 0xffffffff; |
| 201 bottom &= 0xffffffff; | 197 bottom &= 0xffffffff; |
| 202 int d0 = _MASK & bottom; | 198 int d0 = _MASK & bottom; |
| 203 int d1 = ((0xfff & top) << 10) | (0x3ff & (bottom >> _BITS)); | 199 int d1 = ((0xfff & top) << 10) | (0x3ff & (bottom >> _BITS)); |
| 204 int d2 = _MASK2 & (top >> 12); | 200 int d2 = _MASK2 & (top >> 12); |
| 205 return new Int64._bits(d0, d1, d2); | 201 //return new Int64._bits(d0, d1, d2); |
|
Chris Bracken
2015/12/11 20:32:05
delete
| |
| 202 return Int64._masked(d0, d1, d2); | |
| 206 } | 203 } |
| 207 | 204 |
| 208 // Returns the [Int64] representation of the specified value. Throws | 205 // Returns the [Int64] representation of the specified value. Throws |
| 209 // [ArgumentError] for non-integer arguments. | 206 // [ArgumentError] for non-integer arguments. |
| 210 static Int64 _promote(value) { | 207 static Int64 _promote(value) { |
| 211 if (value is Int64) { | 208 if (value is Int64) { |
| 212 return value; | 209 return value; |
| 213 } else if (value is int) { | 210 } else if (value is int) { |
| 214 return new Int64(value); | 211 return new Int64(value); |
| 215 } else if (value is Int32) { | 212 } else if (value is Int32) { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 318 | 315 |
| 319 Int64 operator ~/(other) => _divide(this, other, _RETURN_DIV); | 316 Int64 operator ~/(other) => _divide(this, other, _RETURN_DIV); |
| 320 | 317 |
| 321 Int64 remainder(other) => _divide(this, other, _RETURN_REM); | 318 Int64 remainder(other) => _divide(this, other, _RETURN_REM); |
| 322 | 319 |
| 323 Int64 operator &(other) { | 320 Int64 operator &(other) { |
| 324 Int64 o = _promote(other); | 321 Int64 o = _promote(other); |
| 325 int a0 = _l & o._l; | 322 int a0 = _l & o._l; |
| 326 int a1 = _m & o._m; | 323 int a1 = _m & o._m; |
| 327 int a2 = _h & o._h; | 324 int a2 = _h & o._h; |
| 328 return new Int64._bits(a0, a1, a2); | 325 return Int64._masked(a0, a1, a2); |
| 329 } | 326 } |
| 330 | 327 |
| 331 Int64 operator |(other) { | 328 Int64 operator |(other) { |
| 332 Int64 o = _promote(other); | 329 Int64 o = _promote(other); |
| 333 int a0 = _l | o._l; | 330 int a0 = _l | o._l; |
| 334 int a1 = _m | o._m; | 331 int a1 = _m | o._m; |
| 335 int a2 = _h | o._h; | 332 int a2 = _h | o._h; |
| 336 return new Int64._bits(a0, a1, a2); | 333 return Int64._masked(a0, a1, a2); |
| 337 } | 334 } |
| 338 | 335 |
| 339 Int64 operator ^(other) { | 336 Int64 operator ^(other) { |
| 340 Int64 o = _promote(other); | 337 Int64 o = _promote(other); |
| 341 int a0 = _l ^ o._l; | 338 int a0 = _l ^ o._l; |
| 342 int a1 = _m ^ o._m; | 339 int a1 = _m ^ o._m; |
| 343 int a2 = _h ^ o._h; | 340 int a2 = _h ^ o._h; |
| 344 return Int64._masked(a0, a1, a2); | 341 return Int64._masked(a0, a1, a2); |
| 345 } | 342 } |
| 346 | 343 |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 622 result[7] = (_h >> 12) & 0xff; | 619 result[7] = (_h >> 12) & 0xff; |
| 623 return result; | 620 return result; |
| 624 } | 621 } |
| 625 | 622 |
| 626 double toDouble() => toInt().toDouble(); | 623 double toDouble() => toInt().toDouble(); |
| 627 | 624 |
| 628 int toInt() { | 625 int toInt() { |
| 629 int l = _l; | 626 int l = _l; |
| 630 int m = _m; | 627 int m = _m; |
| 631 int h = _h; | 628 int h = _h; |
| 632 bool negative = false; | 629 // In the sum we add least significant to most significant so that in |
| 630 // JavaScript double arithmetic rounding occurs on only the last addition. | |
| 633 if ((_h & _SIGN_BIT_MASK) != 0) { | 631 if ((_h & _SIGN_BIT_MASK) != 0) { |
| 634 l = _MASK & ~_l; | 632 l = _MASK & ~_l; |
| 635 m = _MASK & ~_m; | 633 m = _MASK & ~_m; |
| 636 h = _MASK2 & ~_h; | 634 h = _MASK2 & ~_h; |
| 637 negative = true; | 635 return -((1 + l) + (4194304 * m) + (17592186044416 * h)); |
| 638 } | |
| 639 | |
| 640 if (_haveBigInts) { | |
| 641 int result = (h << _BITS01) | (m << _BITS) | l; | |
| 642 return negative ? -result - 1 : result; | |
| 643 } else { | 636 } else { |
| 644 if (negative) { | 637 return l + (4194304 * m) + (17592186044416 * h); |
| 645 return -((l + 1) + (m * 4194304) + (h * 17592186044416)); | |
| 646 } else { | |
| 647 return (l + (m * 4194304)) + (h * 17592186044416); | |
| 648 } | |
| 649 } | 638 } |
| 650 } | 639 } |
| 651 | 640 |
| 652 /** | 641 /** |
| 653 * Returns an [Int32] containing the low 32 bits of this [Int64]. | 642 * Returns an [Int32] containing the low 32 bits of this [Int64]. |
| 654 */ | 643 */ |
| 655 Int32 toInt32() { | 644 Int32 toInt32() { |
| 656 return new Int32(((_m & 0x3ff) << _BITS) | _l); | 645 return new Int32(((_m & 0x3ff) << _BITS) | _l); |
| 657 } | 646 } |
| 658 | 647 |
| 659 /** | 648 /** |
| 660 * Returns [this]. | 649 * Returns [this]. |
| 661 */ | 650 */ |
| 662 Int64 toInt64() => this; | 651 Int64 toInt64() => this; |
| 663 | 652 |
| 664 /** | 653 /** |
| 665 * Returns the value of this [Int64] as a decimal [String]. | 654 * Returns the value of this [Int64] as a decimal [String]. |
| 666 */ | 655 */ |
| 667 String toString() => _toRadixString(10); | 656 String toString() => _toRadixString(10); |
| 668 | 657 |
| 669 // TODO(rice) - Make this faster by avoiding arithmetic. | 658 // TODO(rice) - Make this faster by avoiding arithmetic. |
| 670 String toHexString() { | 659 String toHexString() { |
| 671 if (isZero) return "0"; | 660 if (isZero) return "0"; |
| 672 Int64 x = this; | 661 Int64 x = this; |
| 673 String hexStr = ""; | 662 String hexStr = ""; |
| 674 Int64 digit_f = new Int64(0xf); | |
| 675 while (!x.isZero) { | 663 while (!x.isZero) { |
| 676 int digit = x._l & 0xf; | 664 int digit = x._l & 0xf; |
| 677 hexStr = "${_hexDigit(digit)}$hexStr"; | 665 hexStr = "${_hexDigit(digit)}$hexStr"; |
| 678 x = x.shiftRightUnsigned(4); | 666 x = x.shiftRightUnsigned(4); |
| 679 } | 667 } |
| 680 return hexStr; | 668 return hexStr; |
| 681 } | 669 } |
| 682 | 670 |
| 683 String toRadixString(int radix) { | 671 String toRadixString(int radix) { |
| 684 return _toRadixString(Int32._validateRadix(radix)); | 672 return _toRadixString(Int32._validateRadix(radix)); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 836 int diff0 = a0 - b0; | 824 int diff0 = a0 - b0; |
| 837 int diff1 = a1 - b1 - ((diff0 >> _BITS) & 1); | 825 int diff1 = a1 - b1 - ((diff0 >> _BITS) & 1); |
| 838 int diff2 = a2 - b2 - ((diff1 >> _BITS) & 1); | 826 int diff2 = a2 - b2 - ((diff1 >> _BITS) & 1); |
| 839 return _masked(diff0, diff1, diff2); | 827 return _masked(diff0, diff1, diff2); |
| 840 } | 828 } |
| 841 | 829 |
| 842 static Int64 _negate(int b0, int b1, int b2) { | 830 static Int64 _negate(int b0, int b1, int b2) { |
| 843 return _sub(0, 0, 0, b0, b1, b2); | 831 return _sub(0, 0, 0, b0, b1, b2); |
| 844 } | 832 } |
| 845 | 833 |
| 846 // Determine whether the platform supports ints greater than 2^53 | |
| 847 // without loss of precision. | |
| 848 static bool _haveBigIntsCached = null; | |
| 849 | |
| 850 static bool get _haveBigInts { | |
| 851 if (_haveBigIntsCached == null) { | |
| 852 var x = 9007199254740992; | |
| 853 // Defeat compile-time constant folding. | |
| 854 if (2 + 2 != 4) { | |
| 855 x = 0; | |
| 856 } | |
| 857 var y = x + 1; | |
| 858 var same = y == x; | |
| 859 _haveBigIntsCached = !same; | |
| 860 } | |
| 861 return _haveBigIntsCached; | |
| 862 } | |
| 863 | |
| 864 String _hexDigit(int digit) => "0123456789ABCDEF"[digit]; | 834 String _hexDigit(int digit) => "0123456789ABCDEF"[digit]; |
| 865 | 835 |
| 866 | |
| 867 // Work around dart2js bugs with negative arguments to '>>' operator. | 836 // Work around dart2js bugs with negative arguments to '>>' operator. |
| 868 static int _shiftRight(int x, int n) { | 837 static int _shiftRight(int x, int n) { |
| 869 if (x >= 0) { | 838 if (x >= 0) { |
| 870 return x >> n; | 839 return x >> n; |
| 871 } else { | 840 } else { |
| 872 int shifted = x >> n; | 841 int shifted = x >> n; |
| 873 if (shifted >= 0x80000000) { | 842 if (shifted >= 0x80000000) { |
| 874 shifted -= 4294967296; | 843 shifted -= 4294967296; |
| 875 } | 844 } |
| 876 return shifted; | 845 return shifted; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1026 if (r0 == 0 && r1 == 0 && r2 == 0) { | 995 if (r0 == 0 && r1 == 0 && r2 == 0) { |
| 1027 return ZERO; | 996 return ZERO; |
| 1028 } else { | 997 } else { |
| 1029 return _sub(b0, b1, b2, r0, r1, r2); | 998 return _sub(b0, b1, b2, r0, r1, r2); |
| 1030 } | 999 } |
| 1031 } else { | 1000 } else { |
| 1032 return _negate(r0, r1, r2); | 1001 return _negate(r0, r1, r2); |
| 1033 } | 1002 } |
| 1034 } | 1003 } |
| 1035 } | 1004 } |
| OLD | NEW |