Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 // Copyright 2009 The Go Authors. All rights reserved. | 5 // Copyright 2009 The Go Authors. All rights reserved. |
| 6 // Use of this source code is governed by a BSD-style | 6 // Use of this source code is governed by a BSD-style |
| 7 // license that can be found in the LICENSE file. | 7 // license that can be found in the LICENSE file. |
| 8 | 8 |
| 9 /* | 9 /* |
| 10 * Copyright (c) 2003-2005 Tom Wu | 10 * Copyright (c) 2003-2005 Tom Wu |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 58 static const int _MIN_INT64 = (-1) << 63; | 58 static const int _MIN_INT64 = (-1) << 63; |
| 59 static const int _MAX_INT64 = 0x7fffffffffffffff; | 59 static const int _MAX_INT64 = 0x7fffffffffffffff; |
| 60 | 60 |
| 61 // Bigint constant values. | 61 // Bigint constant values. |
| 62 // Note: Not declared as final in order to satisfy optimizer, which expects | 62 // Note: Not declared as final in order to satisfy optimizer, which expects |
| 63 // constants to be in canonical form (Smi). | 63 // constants to be in canonical form (Smi). |
| 64 static _Bigint _MINUS_ONE = new _Bigint._fromInt(-1); | 64 static _Bigint _MINUS_ONE = new _Bigint._fromInt(-1); |
| 65 static _Bigint _ZERO = new _Bigint._fromInt(0); | 65 static _Bigint _ZERO = new _Bigint._fromInt(0); |
| 66 static _Bigint _ONE = new _Bigint._fromInt(1); | 66 static _Bigint _ONE = new _Bigint._fromInt(1); |
| 67 | 67 |
| 68 // Result cache for last _divRem call. | |
| 69 static Uint32List _lastDividend_digits; | |
| 70 static int _lastDividend_used; | |
| 71 static Uint32List _lastDivisor_digits; | |
| 72 static int _lastDivisor_used; | |
| 73 static Uint32List _lastQuoRem_digits; | |
| 74 static int _lastQuoRem_used; | |
| 75 static int _lastRem_used; | |
| 76 static int _lastRem_nsh; | |
| 77 | |
| 68 // Internal data structure. | 78 // Internal data structure. |
| 69 bool get _neg native "Bigint_getNeg"; | 79 bool get _neg native "Bigint_getNeg"; |
| 70 int get _used native "Bigint_getUsed"; | 80 int get _used native "Bigint_getUsed"; |
| 71 Uint32List get _digits native "Bigint_getDigits"; | 81 Uint32List get _digits native "Bigint_getDigits"; |
| 72 | 82 |
| 73 // Factory returning an instance initialized with the given field values. | 83 // Factory returning an instance initialized with the given field values. |
| 74 // The 'digits' array is first clamped and 'used' is reduced accordingly. | 84 // The 'digits' array is first clamped and 'used' is reduced accordingly. |
| 75 // A leading zero digit may be initialized to guarantee that digit pairs can | 85 // A leading zero digit may be initialized to guarantee that digit pairs can |
| 76 // be processed as 64-bit values on 64-bit platforms. | 86 // be processed as 64-bit values on 64-bit platforms. |
| 77 factory _Bigint(bool neg, int used, Uint32List digits) | 87 factory _Bigint(bool neg, int used, Uint32List digits) |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 return new _Bigint(_neg, r_used, r_digits); | 195 return new _Bigint(_neg, r_used, r_digits); |
| 186 } | 196 } |
| 187 | 197 |
| 188 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*_DIGIT_BITS. | 198 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*_DIGIT_BITS. |
| 189 // Return r_used. | 199 // Return r_used. |
| 190 static int _dlShiftDigits(Uint32List x_digits, int x_used, int n, | 200 static int _dlShiftDigits(Uint32List x_digits, int x_used, int n, |
| 191 Uint32List r_digits) { | 201 Uint32List r_digits) { |
| 192 if (x_used == 0) { | 202 if (x_used == 0) { |
| 193 return 0; | 203 return 0; |
| 194 } | 204 } |
| 195 if (n == 0 && r_digits == x_digits) { | 205 if (n == 0 && identical(r_digits, x_digits)) { |
| 196 return x_used; | 206 return x_used; |
| 197 } | 207 } |
| 198 final r_used = x_used + n; | 208 final r_used = x_used + n; |
| 199 assert(r_digits.length >= r_used + (r_used & 1)); | 209 assert(r_digits.length >= r_used + (r_used & 1)); |
| 200 var i = x_used; | 210 var i = x_used; |
| 201 while (--i >= 0) { | 211 while (--i >= 0) { |
| 202 r_digits[i + n] = x_digits[i]; | 212 r_digits[i + n] = x_digits[i]; |
| 203 } | 213 } |
| 204 i = n; | 214 i = n; |
| 205 while (--i >= 0) { | 215 while (--i >= 0) { |
| (...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 937 args[_QD] = _DIGIT_MASK; | 947 args[_QD] = _DIGIT_MASK; |
| 938 } else { | 948 } else { |
| 939 args[_QD] = qd; | 949 args[_QD] = qd; |
| 940 } | 950 } |
| 941 } | 951 } |
| 942 return 1; | 952 return 1; |
| 943 } | 953 } |
| 944 | 954 |
| 945 // Return trunc(this / a), a != 0. | 955 // Return trunc(this / a), a != 0. |
| 946 _Bigint _div(_Bigint a) { | 956 _Bigint _div(_Bigint a) { |
| 947 return _divRem(a, true); | 957 assert(a._used > 0); |
| 958 if (_used < a._used) { | |
| 959 return _ZERO; | |
| 960 } | |
| 961 // Check if result is cached (identical on Bigint is too expensive). | |
| 962 if (this._used != _lastDividend_used || | |
| 963 a._used != _lastDivisor_used || | |
| 964 !identical(this._digits, _lastDividend_digits) || | |
| 965 !identical(a._digits, _lastDivisor_digits)) { | |
| 966 _divRem(a); | |
| 967 } | |
| 968 // Return quotient, i.e. | |
| 969 // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign. | |
| 970 var lastQuo_used = _lastQuoRem_used - _lastRem_used; | |
| 971 var quo_digits = _cloneDigits(_lastQuoRem_digits, | |
| 972 _lastRem_used, | |
| 973 _lastQuoRem_used, | |
| 974 lastQuo_used); | |
| 975 var quo = new _Bigint(false, lastQuo_used, quo_digits); | |
| 976 if (_neg != a._neg && quo._used > 0) { | |
|
srdjan
2015/04/02 21:06:41
Use parentheses.
regis
2015/04/06 19:51:18
Done.
| |
| 977 quo = quo._negate(); | |
| 978 } | |
| 979 return quo; | |
| 948 } | 980 } |
| 949 | 981 |
| 950 // Return this - a * trunc(this / a), a != 0. | 982 // Return this - a * trunc(this / a), a != 0. |
| 951 _Bigint _rem(_Bigint a) { | 983 _Bigint _rem(_Bigint a) { |
| 952 return _divRem(a, false); | 984 assert(a._used > 0); |
| 985 if (_used < a._used) { | |
| 986 return this; | |
| 987 } | |
| 988 // Check if result is cached (identical on Bigint is too expensive). | |
| 989 if (this._used != _lastDividend_used || | |
| 990 a._used != _lastDivisor_used || | |
| 991 !identical(this._digits, _lastDividend_digits) || | |
| 992 !identical(a._digits, _lastDivisor_digits)) { | |
|
srdjan
2015/04/02 21:06:41
Factor out the test.
regis
2015/04/06 19:51:18
I moved the test to _divRem.
| |
| 993 _divRem(a); | |
| 994 } | |
| 995 // Return remainder, i.e. | |
| 996 // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign. | |
| 997 var rem_digits = _cloneDigits(_lastQuoRem_digits, | |
| 998 0, | |
| 999 _lastRem_used, | |
| 1000 _lastRem_used); | |
| 1001 var rem = new _Bigint(false, _lastRem_used, rem_digits); | |
| 1002 if (_lastRem_nsh > 0) { | |
| 1003 rem = rem._rShift(_lastRem_nsh); // Denormalize remainder. | |
| 1004 } | |
| 1005 if (_neg && rem._used > 0) { | |
|
srdjan
2015/04/02 21:06:42
Use parentheses please
regis
2015/04/06 19:51:18
Done.
| |
| 1006 rem = rem._negate(); | |
| 1007 } | |
| 1008 return rem; | |
| 953 } | 1009 } |
| 954 | 1010 |
| 955 // Return trunc(this / a), a != 0, if div == true. | 1011 // Cache concatenated positive quotient and normalized positive remainder. |
| 956 // Return this - a * trunc(this / a), a != 0, if div == false. | 1012 void _divRem(_Bigint a) { |
| 957 _Bigint _divRem(_Bigint a, bool div) { | |
| 958 assert(a._used > 0); | |
| 959 if (_used < a._used) { | |
| 960 return div ? _ZERO : this; | |
| 961 } | |
| 962 var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]); | 1013 var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]); |
| 963 // For 64-bit processing, make sure y has an even number of digits. | 1014 // For 64-bit processing, make sure y has an even number of digits. |
| 964 if (a._used.isOdd) { | 1015 if (a._used.isOdd) { |
| 965 nsh += _DIGIT_BITS; | 1016 nsh += _DIGIT_BITS; |
| 966 } | 1017 } |
| 967 // Concatenated positive quotient and normalized positive remainder. | 1018 // Concatenated positive quotient and normalized positive remainder. |
| 968 var r_digits; | 1019 var r_digits; |
| 969 var r_used; | 1020 var r_used; |
| 970 // Normalized positive divisor. | 1021 // Normalized positive divisor. |
| 971 var y_digits; | 1022 var y_digits; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1042 if (yt_qd[_QD] == 0) { | 1093 if (yt_qd[_QD] == 0) { |
| 1043 --yt_qd[_QD_HI]; | 1094 --yt_qd[_QD_HI]; |
| 1044 } | 1095 } |
| 1045 --yt_qd[_QD]; | 1096 --yt_qd[_QD]; |
| 1046 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1097 assert(r_digits[i] <= yt_qd[_QD_HI]); |
| 1047 } | 1098 } |
| 1048 } | 1099 } |
| 1049 } | 1100 } |
| 1050 i -= d0; | 1101 i -= d0; |
| 1051 } | 1102 } |
| 1052 if (div) { | 1103 // Cache result. |
| 1053 // Return quotient, i.e. r_digits[y_used..r_used-1] with proper sign. | 1104 _lastDividend_digits = _digits; |
| 1054 r_digits = _cloneDigits(r_digits, y_used, r_used, r_used - y_used); | 1105 _lastDividend_used = _used; |
| 1055 var r = new _Bigint(false, r_used - y_used, r_digits); | 1106 _lastDivisor_digits = a._digits; |
| 1056 if (_neg != a._neg && r._used > 0) { | 1107 _lastDivisor_used = a._used; |
| 1057 r = r._negate(); | 1108 _lastQuoRem_digits = r_digits; |
| 1058 } | 1109 _lastQuoRem_used = r_used; |
| 1059 return r; | 1110 _lastRem_used = y_used; |
| 1060 } | 1111 _lastRem_nsh = nsh; |
| 1061 // Return remainder, i.e. denormalized r_digits[0..y_used-1] with | |
| 1062 // proper sign. | |
| 1063 r_digits = _cloneDigits(r_digits, 0, y_used, y_used); | |
| 1064 var r = new _Bigint(false, y_used, r_digits); | |
| 1065 if (nsh > 0) { | |
| 1066 r = r._rShift(nsh); // Denormalize remainder. | |
| 1067 } | |
| 1068 if (_neg && r._used > 0) { | |
| 1069 r = r._negate(); | |
| 1070 } | |
| 1071 return r; | |
| 1072 } | 1112 } |
| 1073 | 1113 |
| 1074 // Customized version of _rem() minimizing allocations for use in reduction. | 1114 // Customized version of _rem() minimizing allocations for use in reduction. |
| 1075 // Input: | 1115 // Input: |
| 1076 // x_digits[0..x_used-1]: positive dividend. | 1116 // x_digits[0..x_used-1]: positive dividend. |
| 1077 // y_digits[0..y_used-1]: normalized positive divisor. | 1117 // y_digits[0..y_used-1]: normalized positive divisor. |
| 1078 // ny_digits[0..y_used-1]: negated y_digits. | 1118 // ny_digits[0..y_used-1]: negated y_digits. |
| 1079 // nsh: normalization shift amount. | 1119 // nsh: normalization shift amount. |
| 1080 // yt_qd: top y digit(s) and place holder for estimated quotient digit(s). | 1120 // yt_qd: top y digit(s) and place holder for estimated quotient digit(s). |
| 1081 // t_digits: temp array of 2*y_used digits. | 1121 // t_digits: temp array of 2*y_used digits. |
| (...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1762 | 1802 |
| 1763 int _mul(Uint32List x_digits, int x_used, | 1803 int _mul(Uint32List x_digits, int x_used, |
| 1764 Uint32List y_digits, int y_used, | 1804 Uint32List y_digits, int y_used, |
| 1765 Uint32List r_digits) { | 1805 Uint32List r_digits) { |
| 1766 var r_used = _Bigint._mulDigits(x_digits, x_used, | 1806 var r_used = _Bigint._mulDigits(x_digits, x_used, |
| 1767 y_digits, y_used, | 1807 y_digits, y_used, |
| 1768 r_digits); | 1808 r_digits); |
| 1769 return _reduce(r_digits, r_used); | 1809 return _reduce(r_digits, r_used); |
| 1770 } | 1810 } |
| 1771 } | 1811 } |
| OLD | NEW |