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 |