Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(602)

Side by Side Diff: pkg/fixnum/lib/src/int64.dart

Issue 1520773002: Int64 improvements (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/fixnum/pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/fixnum/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698