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 20 matching lines...) Expand all Loading... | |
| 31 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF | 31 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF |
| 32 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT | 32 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT |
| 33 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 33 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 34 * | 34 * |
| 35 * In addition, the following condition applies: | 35 * In addition, the following condition applies: |
| 36 * | 36 * |
| 37 * All redistributions must retain an intact copy of this copyright notice | 37 * All redistributions must retain an intact copy of this copyright notice |
| 38 * and disclaimer. | 38 * and disclaimer. |
| 39 */ | 39 */ |
| 40 | 40 |
| 41 class _Bigint extends _IntegerImplementation implements int { | 41 class _Bigint extends _IntegerImplementation implements int { |
|
rmacnak
2015/02/04 19:24:53
It would be nice to have a comment saying Bigints
regis
2015/02/04 22:06:22
Done.
| |
| 42 // Bits per digit. | 42 // Bits per digit. |
| 43 static const int DIGIT_BITS = 32; | 43 static const int DIGIT_BITS = 32; |
| 44 static const int DIGIT_BASE = 1 << DIGIT_BITS; | 44 static const int DIGIT_BASE = 1 << DIGIT_BITS; |
| 45 static const int DIGIT_MASK = (1 << DIGIT_BITS) - 1; | 45 static const int DIGIT_MASK = (1 << DIGIT_BITS) - 1; |
| 46 | 46 |
| 47 // Bits per half digit. | 47 // Bits per half digit. |
| 48 static const int DIGIT2_BITS = DIGIT_BITS >> 1; | 48 static const int DIGIT2_BITS = DIGIT_BITS >> 1; |
| 49 static const int DIGIT2_MASK = (1 << DIGIT2_BITS) - 1; | 49 static const int DIGIT2_MASK = (1 << DIGIT2_BITS) - 1; |
| 50 | 50 |
| 51 // Allocate extra digits so the bigint can be reused. | |
| 52 static const int EXTRA_DIGITS = 4; | |
| 53 | |
| 54 // Min and max of non bigint values. | 51 // Min and max of non bigint values. |
| 55 static const int MIN_INT64 = (-1) << 63; | 52 static const int MIN_INT64 = (-1) << 63; |
| 56 static const int MAX_INT64 = 0x7fffffffffffffff; | 53 static const int MAX_INT64 = 0x7fffffffffffffff; |
| 57 | 54 |
| 58 // Bigint constant values. | 55 // Bigint constant values. |
| 59 // Note: Not declared as final in order to satisfy optimizer, which expects | 56 // Note: Not declared as final in order to satisfy optimizer, which expects |
|
rmacnak
2015/02/04 19:24:53
Optimizer is unhappy with final or just const? The
regis
2015/02/04 22:06:22
It's unhappy with final or const. I cannot make it
| |
| 60 // constants to be in canonical form (Smi). | 57 // constants to be in canonical form (Smi). |
| 58 static _Bigint MINUS_ONE = new _Bigint._fromInt(-1); | |
| 59 static _Bigint ZERO = new _Bigint._fromInt(0); | |
| 61 static _Bigint ONE = new _Bigint._fromInt(1); | 60 static _Bigint ONE = new _Bigint._fromInt(1); |
| 62 | 61 |
| 63 // Digit conversion table for parsing. | 62 // Internal data structure. |
| 64 static final Map<int, int> DIGIT_TABLE = _createDigitTable(); | 63 bool get _neg native "Bigint_getNeg"; |
| 64 int get _used native "Bigint_getUsed"; | |
| 65 Uint32List get _digits native "Bigint_getDigits"; | |
| 65 | 66 |
| 66 // Internal data structure. | 67 // Factory returning an instance initialized with the given field values. |
| 67 // TODO(regis): Remove the 3 native setters below and provide a constructor | 68 // The 'digits' array is first clamped and 'used' is reduced accordingly. |
| 68 // taking all 3 field values, which is equivalent to making the fields final. | 69 // The last digit is set to a leading zero for 64-bit processing. |
| 69 bool get _neg native "Bigint_getNeg"; | 70 factory _Bigint(bool neg, int used, Uint32List digits) |
| 70 void set _neg(bool value) native "Bigint_setNeg"; | 71 native "Bigint_allocate"; |
| 71 int get _used native "Bigint_getUsed"; | |
| 72 void set _used(int value) native "Bigint_setUsed"; | |
| 73 Uint32List get _digits native "Bigint_getDigits"; | |
| 74 void set _digits(Uint32List value) native "Bigint_setDigits"; | |
| 75 | |
| 76 // Factory returning an instance initialized to value 0. | |
| 77 factory _Bigint() native "Bigint_allocate"; | |
| 78 | 72 |
| 79 // Factory returning an instance initialized to an integer value no larger | 73 // Factory returning an instance initialized to an integer value no larger |
| 80 // than a Mint. | 74 // than a Mint. |
| 81 factory _Bigint._fromInt(int i) { | 75 factory _Bigint._fromInt(int i) { |
| 82 assert(i is! _Bigint); | 76 assert(i is! _Bigint); |
| 83 bool neg; | 77 var neg; |
| 84 var l, h; | 78 var l, h; |
| 85 if (i < 0) { | 79 if (i < 0) { |
| 86 neg = true; | 80 neg = true; |
| 87 if (i == MIN_INT64) { | 81 if (i == MIN_INT64) { |
| 88 l = 0; | 82 l = 0; |
| 89 h = 0x80000000; | 83 h = 0x80000000; |
| 90 } else { | 84 } else { |
| 91 l = (-i) & DIGIT_MASK; | 85 l = (-i) & DIGIT_MASK; |
| 92 h = (-i) >> DIGIT_BITS; | 86 h = (-i) >> DIGIT_BITS; |
| 93 } | 87 } |
| 94 } else { | 88 } else { |
| 95 neg = false; | 89 neg = false; |
| 96 l = i & DIGIT_MASK; | 90 l = i & DIGIT_MASK; |
| 97 h = i >> DIGIT_BITS; | 91 h = i >> DIGIT_BITS; |
| 98 } | 92 } |
| 99 var result = new _Bigint(); | 93 var digits = new Uint32List(2 + 1); // +1 for leading zero. |
| 100 result._ensureLength(2); | 94 digits[0] = l; |
| 101 result._neg = neg; | 95 digits[1] = h; |
| 102 result._used = 2; | 96 return new _Bigint(neg, 2, digits); |
| 103 result._digits[0] = l; | |
| 104 result._digits[1] = h; | |
| 105 result._clamp(); | |
| 106 return result; | |
| 107 } | 97 } |
| 108 | 98 |
| 109 // Create digit conversion table for parsing. | 99 // Allocate an array of the given length (+1 for at least one leading zero |
| 110 static Map<int, int> _createDigitTable() { | 100 // digit) and copy digits[from..to-1] starting at index 0, followed by |
| 111 Map table = new HashMap(); | 101 // leading zero digits. |
| 112 int digit, value; | 102 static Uint32List _cloneDigits(Uint32List digits, int from, int to, |
| 113 digit = "0".codeUnitAt(0); | 103 int length) { |
| 114 for(value = 0; value <= 9; ++value) table[digit++] = value; | 104 length++; // +1 for leading zero. |
| 115 digit = "a".codeUnitAt(0); | 105 var r_digits = new Uint32List(length); |
| 116 for(value = 10; value < 36; ++value) table[digit++] = value; | 106 var n = to - from; |
| 117 digit = "A".codeUnitAt(0); | 107 for (var i = 0; i < n; i++) { |
| 118 for(value = 10; value < 36; ++value) table[digit++] = value; | 108 r_digits[i] = digits[from + i]; |
| 119 return table; | 109 } |
| 110 while (n < length) { | |
|
rmacnak
2015/02/04 19:24:53
Typed data is zero initialized.
regis
2015/02/04 22:06:23
Good point. Removed initialization here and at oth
| |
| 111 r_digits[n++] = 0; | |
| 112 } | |
| 113 return r_digits; | |
| 120 } | 114 } |
| 121 | 115 |
| 122 // Return most compact integer (i.e. possibly Smi or Mint). | 116 // Return most compact integer (i.e. possibly Smi or Mint). |
| 123 // TODO(regis): Intrinsify. | |
| 124 int _toValidInt() { | 117 int _toValidInt() { |
| 125 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 118 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
| 126 var used = _used; | 119 var used = _used; |
| 127 if (used == 0) return 0; | 120 if (used == 0) return 0; |
| 128 var digits = _digits; | 121 var digits = _digits; |
| 129 if (used == 1) return _neg ? -digits[0] : digits[0]; | 122 if (used == 1) return _neg ? -digits[0] : digits[0]; |
| 130 if (used > 2) return this; | 123 if (used > 2) return this; |
| 131 if (_neg) { | 124 if (_neg) { |
| 132 if (digits[1] > 0x80000000) return this; | 125 if (digits[1] > 0x80000000) return this; |
| 133 if (digits[1] == 0x80000000) { | 126 if (digits[1] == 0x80000000) { |
| 134 if (digits[0] > 0) return this; | 127 if (digits[0] > 0) return this; |
| 135 return MIN_INT64; | 128 return MIN_INT64; |
| 136 } | 129 } |
| 137 return -((digits[1] << DIGIT_BITS) | digits[0]); | 130 return -((digits[1] << DIGIT_BITS) | digits[0]); |
| 138 } | 131 } |
| 139 if (digits[1] >= 0x80000000) return this; | 132 if (digits[1] >= 0x80000000) return this; |
| 140 return (digits[1] << DIGIT_BITS) | digits[0]; | 133 return (digits[1] << DIGIT_BITS) | digits[0]; |
| 141 } | 134 } |
| 142 | 135 |
| 143 // Conversion from int to bigint. | 136 // Conversion from int to bigint. |
| 144 _Bigint _toBigint() => this; | 137 _Bigint _toBigint() => this; |
| 145 | 138 |
| 146 // Make sure at least 'length' _digits are allocated. | 139 // Return -this. |
| 147 // Copy existing and used _digits if reallocation is necessary. | 140 _Bigint _negate() { |
| 148 // Avoid preserving _digits unnecessarily by calling this function with a | 141 var used = _used; |
| 149 // meaningful _used field. | 142 if (used == 0) { |
| 150 void _ensureLength(int length) { | 143 return this; |
| 151 length++; // Account for leading zero for 64-bit processing. | |
| 152 var digits = _digits; | |
| 153 if (length > digits.length) { | |
| 154 var new_digits = new Uint32List(length + EXTRA_DIGITS); | |
| 155 _digits = new_digits; | |
| 156 var used = _used; | |
| 157 if (used > 0) { | |
| 158 var i = used + 1; // Copy leading zero for 64-bit processing. | |
| 159 while (--i >= 0) { | |
| 160 new_digits[i] = digits[i]; | |
| 161 } | |
| 162 } | |
| 163 } | 144 } |
| 145 return new _Bigint(!_neg, used, _digits); | |
| 164 } | 146 } |
| 165 | 147 |
| 166 // Clamp off excess high _digits. | 148 // Return abs(this). |
| 167 void _clamp() { | 149 _Bigint _abs() { |
| 168 var used = _used; | 150 var neg = _neg; |
| 169 if (used > 0) { | 151 if (!neg) { |
| 170 var digits = _digits; | 152 return this; |
| 171 if (digits[used - 1] == 0) { | |
| 172 do { | |
| 173 --used; | |
| 174 } while (used > 0 && digits[used - 1] == 0); | |
| 175 _used = used; | |
| 176 } | |
| 177 digits[used] = 0; // Set leading zero for 64-bit processing. | |
| 178 } | 153 } |
| 179 } | 154 return new _Bigint(!neg, _used, _digits); |
| 180 | |
| 181 // Copy this to r. | |
| 182 void _copyTo(_Bigint r) { | |
| 183 var used = _used; | |
| 184 if (used > 0) { | |
| 185 // We could set r._used to 0 in order to avoid preserving digits. However, | |
| 186 // it would be wrong to do so if this === r. Checking is too expensive. | |
| 187 // This case does not occur in the current implementation, but we want to | |
| 188 // remain safe. | |
| 189 r._ensureLength(used); | |
| 190 var digits = _digits; | |
| 191 var r_digits = r._digits; | |
| 192 var i = used + 1; // Copy leading zero for 64-bit processing. | |
| 193 while (--i >= 0) { | |
| 194 r_digits[i] = digits[i]; | |
| 195 } | |
| 196 } | |
| 197 r._used = used; | |
| 198 r._neg = _neg; | |
| 199 } | 155 } |
| 200 | 156 |
| 201 // Return the bit length of digit x. | 157 // Return the bit length of digit x. |
| 202 int _nbits(int x) { | 158 static int _nbits(int x) { |
| 203 var r = 1, t; | 159 var r = 1, t; |
| 204 if ((t = x >> 16) != 0) { x = t; r += 16; } | 160 if ((t = x >> 16) != 0) { x = t; r += 16; } |
| 205 if ((t = x >> 8) != 0) { x = t; r += 8; } | 161 if ((t = x >> 8) != 0) { x = t; r += 8; } |
| 206 if ((t = x >> 4) != 0) { x = t; r += 4; } | 162 if ((t = x >> 4) != 0) { x = t; r += 4; } |
| 207 if ((t = x >> 2) != 0) { x = t; r += 2; } | 163 if ((t = x >> 2) != 0) { x = t; r += 2; } |
| 208 if ((x >> 1) != 0) { r += 1; } | 164 if ((x >> 1) != 0) { r += 1; } |
| 209 return r; | 165 return r; |
| 210 } | 166 } |
| 211 | 167 |
| 212 // r = this << n*DIGIT_BITS. | 168 // Return this << n*DIGIT_BITS. |
| 213 void _dlShiftTo(int n, _Bigint r) { | 169 _Bigint _dlShift(int n) { |
| 214 var used = _used; | 170 var used = _used; |
| 215 if (used == 0) { | 171 if (used == 0) { |
| 216 r._used = 0; | 172 return ZERO; |
| 217 r._neg = false; | |
| 218 return; | |
| 219 } | 173 } |
| 220 var r_used = used + n; | 174 var r_used = used + n; |
| 221 r._ensureLength(r_used); | |
| 222 var digits = _digits; | 175 var digits = _digits; |
| 223 var r_digits = r._digits; | 176 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. |
| 224 var i = used + 1; // Copy leading zero for 64-bit processing. | 177 var i = used; |
| 225 while (--i >= 0) { | 178 while (--i >= 0) { |
| 226 r_digits[i + n] = digits[i]; | 179 r_digits[i + n] = digits[i]; |
| 227 } | 180 } |
| 228 i = n; | 181 i = n; |
| 229 while (--i >= 0) { | 182 while (--i >= 0) { |
| 230 r_digits[i] = 0; | 183 r_digits[i] = 0; |
| 231 } | 184 } |
| 232 r._used = r_used; | 185 return new _Bigint(_neg, r_used, r_digits); |
| 233 r._neg = _neg; | |
| 234 } | 186 } |
| 235 | 187 |
| 236 // r = this >> n*DIGIT_BITS. | 188 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*DIGIT_BITS. |
| 237 void _drShiftTo(int n, _Bigint r) { | 189 // Return r_used. |
| 190 static int _dlShiftDigits(Uint32List x_digits, int x_used, int n, | |
| 191 Uint32List r_digits) { | |
| 192 if (x_used == 0) { | |
| 193 return 0; | |
| 194 } | |
| 195 if (n == 0 && r_digits == x_digits) { | |
| 196 return x_used; | |
| 197 } | |
| 198 var r_used = x_used + n; | |
| 199 assert(r_digits.length >= r_used + 1); // +1 for leading zero. | |
| 200 var i = x_used + 1; // +1 for leading zero. | |
| 201 while (--i >= 0) { | |
| 202 r_digits[i + n] = x_digits[i]; | |
| 203 } | |
| 204 i = n; | |
| 205 while (--i >= 0) { | |
| 206 r_digits[i] = 0; | |
| 207 } | |
| 208 return r_used; | |
| 209 } | |
| 210 | |
| 211 // Return this >> n*DIGIT_BITS. | |
| 212 _Bigint _drShift(int n) { | |
| 238 var used = _used; | 213 var used = _used; |
| 239 if (used == 0) { | 214 if (used == 0) { |
| 240 r._used = 0; | 215 return ZERO; |
| 241 r._neg = false; | |
| 242 return; | |
| 243 } | 216 } |
| 244 var r_used = used - n; | 217 var r_used = used - n; |
| 245 if (r_used <= 0) { | 218 if (r_used <= 0) { |
| 246 if (_neg) { | 219 return _neg ? MINUS_ONE : ZERO; |
| 247 // Set r to -1. | |
| 248 r._used = 0; // No digits to preserve. | |
| 249 r._ensureLength(1); | |
| 250 r._neg = true; | |
| 251 r._used = 1; | |
| 252 r._digits[0] = 1; | |
| 253 r._digits[1] = 0; // Set leading zero for 64-bit processing. | |
| 254 } else { | |
| 255 // Set r to 0. | |
| 256 r._neg = false; | |
| 257 r._used = 0; | |
| 258 } | |
| 259 return; | |
| 260 } | 220 } |
| 261 r._ensureLength(r_used); | |
| 262 var digits = _digits; | 221 var digits = _digits; |
| 263 var r_digits = r._digits; | 222 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. |
| 264 for (var i = n; i < used + 1; i++) { // Copy leading zero for 64-bit proc. | 223 for (var i = n; i < used; i++) { |
| 265 r_digits[i - n] = digits[i]; | 224 r_digits[i - n] = digits[i]; |
| 266 } | 225 } |
| 267 r._used = r_used; | 226 var r = new _Bigint(_neg, r_used, r_digits); |
| 268 r._neg = _neg; | |
| 269 if (_neg) { | 227 if (_neg) { |
| 270 // Round down if any bit was shifted out. | 228 // Round down if any bit was shifted out. |
| 271 for (var i = 0; i < n; i++) { | 229 for (var i = 0; i < n; i++) { |
| 272 if (digits[i] != 0) { | 230 if (digits[i] != 0) { |
| 273 r._subTo(ONE, r); | 231 return r._sub(ONE); |
| 274 break; | |
| 275 } | 232 } |
| 276 } | 233 } |
| 277 } | 234 } |
| 235 return r; | |
| 278 } | 236 } |
| 279 | 237 |
| 280 // r = this << n. | 238 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n*DIGIT_BITS. |
| 281 void _lShiftTo(int n, _Bigint r) { | 239 // Return r_used. |
| 240 static int _drShiftDigits(Uint32List x_digits, int x_used, int n, | |
| 241 Uint32List r_digits) { | |
| 242 var r_used = x_used - n; | |
| 243 if (r_used <= 0) { | |
| 244 return 0; | |
| 245 } | |
| 246 assert(r_digits.length >= r_used + 1); // +1 for leading zero. | |
| 247 for (var i = n; i < x_used + 1; i++) { // +1 for leading zero. | |
| 248 r_digits[i - n] = x_digits[i]; | |
| 249 } | |
| 250 return r_used; | |
| 251 } | |
| 252 | |
| 253 // Return this << n. | |
| 254 _Bigint _lShift(int n) { | |
| 282 var ds = n ~/ DIGIT_BITS; | 255 var ds = n ~/ DIGIT_BITS; |
| 283 var bs = n % DIGIT_BITS; | 256 var bs = n % DIGIT_BITS; |
| 284 if (bs == 0) { | 257 if (bs == 0) { |
| 285 _dlShiftTo(ds, r); | 258 return _dlShift(ds); |
| 286 return; | |
| 287 } | 259 } |
| 288 var cbs = DIGIT_BITS - bs; | 260 var cbs = DIGIT_BITS - bs; |
| 289 var bm = (1 << cbs) - 1; | 261 var bm = (1 << cbs) - 1; |
| 290 var r_used = _used + ds + 1; | 262 var r_used = _used + ds + 1; |
| 291 r._ensureLength(r_used); | |
| 292 var digits = _digits; | 263 var digits = _digits; |
| 293 var r_digits = r._digits; | 264 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. |
| 294 var c = 0; | 265 var c = 0; |
| 295 var i = _used; | 266 var i = _used; |
| 296 while (--i >= 0) { | 267 while (--i >= 0) { |
| 297 r_digits[i + ds + 1] = (digits[i] >> cbs) | c; | 268 r_digits[i + ds + 1] = (digits[i] >> cbs) | c; |
| 298 c = (digits[i] & bm) << bs; | 269 c = (digits[i] & bm) << bs; |
| 299 } | 270 } |
| 300 i = ds; | 271 i = ds; |
| 301 while (--i >= 0) { | 272 while (--i >= 0) { |
| 302 r_digits[i] = 0; | 273 r_digits[i] = 0; |
| 303 } | 274 } |
| 304 r_digits[ds] = c; | 275 r_digits[ds] = c; |
| 305 r._used = r_used; | 276 return new _Bigint(_neg, r_used, r_digits); |
| 306 r._neg = _neg; | |
| 307 r._clamp(); | |
| 308 } | 277 } |
| 309 | 278 |
| 310 // r = this >> n. | 279 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n. |
| 311 void _rShiftTo(int n, _Bigint r) { | 280 // Return r_used. |
| 281 static int _lShiftDigits(Uint32List x_digits, int x_used, int n, | |
| 282 Uint32List r_digits) { | |
| 312 var ds = n ~/ DIGIT_BITS; | 283 var ds = n ~/ DIGIT_BITS; |
| 313 var bs = n % DIGIT_BITS; | 284 var bs = n % DIGIT_BITS; |
| 314 if (bs == 0) { | 285 if (bs == 0) { |
| 315 _drShiftTo(ds, r); | 286 return _dlShiftDigits(x_digits, x_used, ds, r_digits); |
| 316 return; | 287 } |
| 288 var cbs = DIGIT_BITS - bs; | |
| 289 var bm = (1 << cbs) - 1; | |
| 290 var r_used = x_used + ds + 1; | |
| 291 assert(r_digits.length >= r_used + 1); // +1 for leading zero. | |
| 292 var c = 0; | |
| 293 var i = x_used; | |
| 294 while (--i >= 0) { | |
| 295 r_digits[i + ds + 1] = (x_digits[i] >> cbs) | c; | |
| 296 c = (x_digits[i] & bm) << bs; | |
| 297 } | |
| 298 i = ds; | |
| 299 while (--i >= 0) { | |
| 300 r_digits[i] = 0; | |
| 301 } | |
| 302 r_digits[ds] = c; | |
| 303 r_digits[r_used] = 0; // Set leading zero for 64-bit processing. | |
| 304 return r_used; | |
| 305 } | |
| 306 | |
| 307 // Return this >> n. | |
| 308 _Bigint _rShift(int n) { | |
| 309 var ds = n ~/ DIGIT_BITS; | |
| 310 var bs = n % DIGIT_BITS; | |
| 311 if (bs == 0) { | |
| 312 return _drShift(ds); | |
| 317 } | 313 } |
| 318 var r_used = _used - ds; | 314 var r_used = _used - ds; |
| 319 if (r_used <= 0) { | 315 if (r_used <= 0) { |
| 320 if (_neg) { | 316 return _neg ? MINUS_ONE : ZERO; |
| 321 // Set r to -1. | |
| 322 r._neg = true; | |
| 323 r._used = 0; // No digits to preserve. | |
| 324 r._ensureLength(1); | |
| 325 r._used = 1; | |
| 326 r._digits[0] = 1; | |
| 327 r._digits[1] = 0; // Set leading zero for 64-bit processing. | |
| 328 } else { | |
| 329 // Set r to 0. | |
| 330 r._neg = false; | |
| 331 r._used = 0; | |
| 332 } | |
| 333 return; | |
| 334 } | 317 } |
| 335 var cbs = DIGIT_BITS - bs; | 318 var cbs = DIGIT_BITS - bs; |
| 336 var bm = (1 << bs) - 1; | 319 var bm = (1 << bs) - 1; |
| 337 r._ensureLength(r_used); | |
| 338 var digits = _digits; | 320 var digits = _digits; |
| 339 var r_digits = r._digits; | 321 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. |
| 340 r_digits[0] = digits[ds] >> bs; | 322 r_digits[0] = digits[ds] >> bs; |
| 341 var used = _used; | 323 var used = _used; |
| 342 for (var i = ds + 1; i < used; i++) { | 324 for (var i = ds + 1; i < used; i++) { |
| 343 r_digits[i - ds - 1] |= (digits[i] & bm) << cbs; | 325 r_digits[i - ds - 1] |= (digits[i] & bm) << cbs; |
| 344 r_digits[i - ds] = digits[i] >> bs; | 326 r_digits[i - ds] = digits[i] >> bs; |
| 345 } | 327 } |
| 346 r._neg = _neg; | 328 var r = new _Bigint(_neg, r_used, r_digits); |
| 347 r._used = r_used; | |
| 348 r._clamp(); | |
| 349 if (_neg) { | 329 if (_neg) { |
| 350 // Round down if any bit was shifted out. | 330 // Round down if any bit was shifted out. |
| 351 if ((digits[ds] & bm) != 0) { | 331 if ((digits[ds] & bm) != 0) { |
| 352 r._subTo(ONE, r); | 332 return r._sub(ONE); |
| 353 return; | |
| 354 } | 333 } |
| 355 for (var i = 0; i < ds; i++) { | 334 for (var i = 0; i < ds; i++) { |
| 356 if (digits[i] != 0) { | 335 if (digits[i] != 0) { |
| 357 r._subTo(ONE, r); | 336 return r._sub(ONE); |
| 358 return; | |
| 359 } | 337 } |
| 360 } | 338 } |
| 361 } | 339 } |
| 340 return r; | |
| 341 } | |
| 342 | |
| 343 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. | |
| 344 // Return r_used. | |
| 345 static int _rShiftDigits(Uint32List x_digits, int x_used, int n, | |
| 346 Uint32List r_digits) { | |
| 347 var ds = n ~/ DIGIT_BITS; | |
| 348 var bs = n % DIGIT_BITS; | |
| 349 if (bs == 0) { | |
| 350 return _drShiftDigits(x_digits, x_used, ds, r_digits); | |
| 351 } | |
| 352 var r_used = x_used - ds; | |
| 353 if (r_used <= 0) { | |
| 354 return 0; | |
| 355 } | |
| 356 var cbs = DIGIT_BITS - bs; | |
| 357 var bm = (1 << bs) - 1; | |
| 358 assert(r_digits.length >= r_used + 1); // +1 for leading zero. | |
| 359 r_digits[0] = x_digits[ds] >> bs; | |
| 360 for (var i = ds + 1; i < x_used; i++) { | |
| 361 r_digits[i - ds - 1] |= (x_digits[i] & bm) << cbs; | |
| 362 r_digits[i - ds] = x_digits[i] >> bs; | |
| 363 } | |
| 364 r_digits[r_used] = 0; // Set leading zero for 64-bit processing. | |
| 365 return r_used; | |
| 362 } | 366 } |
| 363 | 367 |
| 364 // Return 0 if abs(this) == abs(a). | 368 // Return 0 if abs(this) == abs(a). |
| 365 // Return a positive number if abs(this) > abs(a). | 369 // Return a positive number if abs(this) > abs(a). |
| 366 // Return a negative number if abs(this) < abs(a). | 370 // Return a negative number if abs(this) < abs(a). |
| 367 int _absCompareTo(_Bigint a) { | 371 int _absCompare(_Bigint a) { |
| 368 var r = _used - a._used; | 372 var r = _used - a._used; |
| 369 if (r == 0) { | 373 if (r == 0) { |
| 370 var i = _used; | 374 var i = _used; |
| 371 var digits = _digits; | 375 var digits = _digits; |
| 372 var a_digits = a._digits; | 376 var a_digits = a._digits; |
| 373 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0); | 377 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0); |
| 374 } | 378 } |
| 375 return r; | 379 return r; |
| 376 } | 380 } |
| 377 | 381 |
| 378 // Return 0 if this == a. | 382 // Return 0 if this == a. |
| 379 // Return a positive number if this > a. | 383 // Return a positive number if this > a. |
| 380 // Return a negative number if this < a. | 384 // Return a negative number if this < a. |
| 381 int _compareTo(_Bigint a) { | 385 int _compare(_Bigint a) { |
| 382 var r; | |
| 383 if (_neg == a._neg) { | 386 if (_neg == a._neg) { |
| 384 r = _absCompareTo(a); | 387 var r = _absCompare(a); |
| 385 if (_neg) { | 388 return _neg ? -r : r; |
| 386 r = -r; | 389 } |
| 387 } | 390 return _neg ? -1 : 1; |
| 388 } else if (_neg) { | 391 } |
| 389 r = -1; | 392 |
| 390 } else { | 393 // Compare digits[0..used-1] with a_digits[0..a_used-1]. |
| 391 r = 1; | 394 // Return 0 if equal. |
| 395 // Return a positive number if larger. | |
| 396 // Return a negative number if smaller. | |
| 397 static int _compareDigits(Uint32List digits, int used, | |
| 398 Uint32List a_digits, int a_used) { | |
| 399 var r = used - a_used; | |
| 400 if (r == 0) { | |
| 401 var i = a_used; | |
| 402 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0); | |
| 392 } | 403 } |
| 393 return r; | 404 return r; |
| 394 } | 405 } |
| 395 | 406 |
| 396 // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1]. | 407 // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1]. |
| 397 // used >= a_used > 0. | 408 // used >= a_used > 0. |
| 409 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices. | |
| 398 static void _absAdd(Uint32List digits, int used, | 410 static void _absAdd(Uint32List digits, int used, |
| 399 Uint32List a_digits, int a_used, | 411 Uint32List a_digits, int a_used, |
| 400 Uint32List r_digits) { | 412 Uint32List r_digits) { |
| 413 assert(used >= a_used && a_used > 0); | |
| 414 // Verify that digit pairs are accessible for 64-bit processing. | |
| 415 assert(digits.length > ((used - 1) | 1)); | |
| 416 assert(a_digits.length > ((a_used - 1) | 1)); | |
| 417 assert(r_digits.length > (used | 1)); | |
| 401 var c = 0; | 418 var c = 0; |
| 402 for (var i = 0; i < a_used; i++) { | 419 for (var i = 0; i < a_used; i++) { |
| 403 c += digits[i] + a_digits[i]; | 420 c += digits[i] + a_digits[i]; |
| 404 r_digits[i] = c & DIGIT_MASK; | 421 r_digits[i] = c & DIGIT_MASK; |
| 405 c >>= DIGIT_BITS; | 422 c >>= DIGIT_BITS; |
| 406 } | 423 } |
| 407 for (var i = a_used; i < used; i++) { | 424 for (var i = a_used; i < used; i++) { |
| 408 c += digits[i]; | 425 c += digits[i]; |
| 409 r_digits[i] = c & DIGIT_MASK; | 426 r_digits[i] = c & DIGIT_MASK; |
| 410 c >>= DIGIT_BITS; | 427 c >>= DIGIT_BITS; |
| 411 } | 428 } |
| 412 r_digits[used] = c; | 429 r_digits[used] = c; |
| 413 } | 430 } |
| 414 | 431 |
| 415 // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1]. | 432 // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1]. |
| 416 // used >= a_used > 0. | 433 // used >= a_used > 0. |
| 434 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices. | |
| 417 static void _absSub(Uint32List digits, int used, | 435 static void _absSub(Uint32List digits, int used, |
| 418 Uint32List a_digits, int a_used, | 436 Uint32List a_digits, int a_used, |
| 419 Uint32List r_digits) { | 437 Uint32List r_digits) { |
| 438 assert(used >= a_used && a_used > 0); | |
| 439 // Verify that digit pairs are accessible for 64-bit processing. | |
| 440 assert(digits.length > ((used - 1) | 1)); | |
| 441 assert(a_digits.length > ((a_used - 1) | 1)); | |
| 442 assert(r_digits.length > ((used - 1) | 1)); | |
| 420 var c = 0; | 443 var c = 0; |
| 421 for (var i = 0; i < a_used; i++) { | 444 for (var i = 0; i < a_used; i++) { |
| 422 c += digits[i] - a_digits[i]; | 445 c += digits[i] - a_digits[i]; |
| 423 r_digits[i] = c & DIGIT_MASK; | 446 r_digits[i] = c & DIGIT_MASK; |
| 424 c >>= DIGIT_BITS; | 447 c >>= DIGIT_BITS; |
| 425 } | 448 } |
| 426 for (var i = a_used; i < used; i++) { | 449 for (var i = a_used; i < used; i++) { |
| 427 c += digits[i]; | 450 c += digits[i]; |
| 428 r_digits[i] = c & DIGIT_MASK; | 451 r_digits[i] = c & DIGIT_MASK; |
| 429 c >>= DIGIT_BITS; | 452 c >>= DIGIT_BITS; |
| 430 } | 453 } |
| 431 } | 454 } |
| 432 | 455 |
| 433 // r = abs(this) + abs(a). | 456 // Return abs(this) + abs(a) with sign set according to neg. |
| 434 void _absAddTo(_Bigint a, _Bigint r) { | 457 _Bigint _absAddSetSign(_Bigint a, bool neg) { |
| 435 var used = _used; | 458 var used = _used; |
| 436 var a_used = a._used; | 459 var a_used = a._used; |
| 437 if (used < a_used) { | 460 if (used < a_used) { |
| 438 a._absAddTo(this, r); | 461 return a._absAddSetSign(this, neg); |
| 439 return; | |
| 440 } | 462 } |
| 441 if (used == 0) { | 463 if (used == 0) { |
| 442 // Set r to 0. | 464 assert(!neg); |
| 443 r._neg = false; | 465 return ZERO; |
| 444 r._used = 0; | |
| 445 return; | |
| 446 } | 466 } |
| 447 if (a_used == 0) { | 467 if (a_used == 0) { |
| 448 _copyTo(r); | 468 return _neg == neg ? this : this._negate(); |
| 449 return; | |
| 450 } | 469 } |
| 451 r._ensureLength(used + 1); | 470 var r_used = used + 1; |
| 452 _absAdd(_digits, used, a._digits, a_used, r._digits); | 471 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. |
| 453 r._used = used + 1; | 472 _absAdd(_digits, used, a._digits, a_used, r_digits); |
| 454 r._clamp(); | 473 return new _Bigint(neg, r_used, r_digits); |
| 455 } | 474 } |
| 456 | 475 |
| 457 // r = abs(this) - abs(a), with abs(this) >= abs(a). | 476 // Return abs(this) - abs(a) with sign set according to neg. |
| 458 void _absSubTo(_Bigint a, _Bigint r) { | 477 // Requirement: abs(this) >= abs(a). |
| 459 assert(_absCompareTo(a) >= 0); | 478 _Bigint _absSubSetSign(_Bigint a, bool neg) { |
| 479 assert(_absCompare(a) >= 0); | |
| 460 var used = _used; | 480 var used = _used; |
| 461 if (used == 0) { | 481 if (used == 0) { |
| 462 // Set r to 0. | 482 assert(!neg); |
| 463 r._neg = false; | 483 return ZERO; |
| 464 r._used = 0; | |
| 465 return; | |
| 466 } | 484 } |
| 467 var a_used = a._used; | 485 var a_used = a._used; |
| 468 if (a_used == 0) { | 486 if (a_used == 0) { |
| 469 _copyTo(r); | 487 return _neg == neg ? this : this._negate(); |
| 470 return; | |
| 471 } | 488 } |
| 472 r._ensureLength(used); | 489 var r_digits = new Uint32List(used + 1); // +1 for leading zero. |
| 473 _absSub(_digits, used, a._digits, a_used, r._digits); | 490 _absSub(_digits, used, a._digits, a_used, r_digits); |
| 474 r._used = used; | 491 return new _Bigint(neg, used, r_digits); |
| 475 r._clamp(); | |
| 476 } | 492 } |
| 477 | 493 |
| 478 // r = abs(this) & abs(a). | 494 // Return abs(this) & abs(a) with sign set according to neg. |
| 479 void _absAndTo(_Bigint a, _Bigint r) { | 495 _Bigint _absAndSetSign(_Bigint a, bool neg) { |
| 480 var r_used = (_used < a._used) ? _used : a._used; | 496 var r_used = (_used < a._used) ? _used : a._used; |
| 481 r._ensureLength(r_used); | |
| 482 var digits = _digits; | 497 var digits = _digits; |
| 483 var a_digits = a._digits; | 498 var a_digits = a._digits; |
| 484 var r_digits = r._digits; | 499 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. |
| 485 for (var i = 0; i < r_used; i++) { | 500 for (var i = 0; i < r_used; i++) { |
| 486 r_digits[i] = digits[i] & a_digits[i]; | 501 r_digits[i] = digits[i] & a_digits[i]; |
| 487 } | 502 } |
| 488 r._used = r_used; | 503 return new _Bigint(neg, r_used, r_digits); |
| 489 r._clamp(); | |
| 490 } | 504 } |
| 491 | 505 |
| 492 // r = abs(this) &~ abs(a). | 506 // Return abs(this) &~ abs(a) with sign set according to neg. |
| 493 void _absAndNotTo(_Bigint a, _Bigint r) { | 507 _Bigint _absAndNotSetSign(_Bigint a, bool neg) { |
| 494 var r_used = _used; | 508 var r_used = _used; |
| 495 r._ensureLength(r_used); | |
| 496 var digits = _digits; | 509 var digits = _digits; |
| 497 var a_digits = a._digits; | 510 var a_digits = a._digits; |
| 498 var r_digits = r._digits; | 511 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. |
| 499 var m = (r_used < a._used) ? r_used : a._used; | 512 var m = (r_used < a._used) ? r_used : a._used; |
| 500 for (var i = 0; i < m; i++) { | 513 for (var i = 0; i < m; i++) { |
| 501 r_digits[i] = digits[i] &~ a_digits[i]; | 514 r_digits[i] = digits[i] &~ a_digits[i]; |
| 502 } | 515 } |
| 503 for (var i = m; i < r_used; i++) { | 516 for (var i = m; i < r_used; i++) { |
| 504 r_digits[i] = digits[i]; | 517 r_digits[i] = digits[i]; |
| 505 } | 518 } |
| 506 r._used = r_used; | 519 return new _Bigint(neg, r_used, r_digits); |
| 507 r._clamp(); | |
| 508 } | 520 } |
| 509 | 521 |
| 510 // r = abs(this) | abs(a). | 522 // Return abs(this) | abs(a) with sign set according to neg. |
| 511 void _absOrTo(_Bigint a, _Bigint r) { | 523 _Bigint _absOrSetSign(_Bigint a, bool neg) { |
| 512 var used = _used; | 524 var used = _used; |
| 513 var a_used = a._used; | 525 var a_used = a._used; |
| 514 var r_used = (used > a_used) ? used : a_used; | 526 var r_used = (used > a_used) ? used : a_used; |
| 515 r._ensureLength(r_used); | |
| 516 var digits = _digits; | 527 var digits = _digits; |
| 517 var a_digits = a._digits; | 528 var a_digits = a._digits; |
| 518 var r_digits = r._digits; | 529 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. |
| 519 var l, m; | 530 var l, m; |
| 520 if (used < a_used) { | 531 if (used < a_used) { |
| 521 l = a; | 532 l = a; |
| 522 m = used; | 533 m = used; |
| 523 } else { | 534 } else { |
| 524 l = this; | 535 l = this; |
| 525 m = a_used; | 536 m = a_used; |
| 526 } | 537 } |
| 527 for (var i = 0; i < m; i++) { | 538 for (var i = 0; i < m; i++) { |
| 528 r_digits[i] = digits[i] | a_digits[i]; | 539 r_digits[i] = digits[i] | a_digits[i]; |
| 529 } | 540 } |
| 530 var l_digits = l._digits; | 541 var l_digits = l._digits; |
| 531 for (var i = m; i < r_used; i++) { | 542 for (var i = m; i < r_used; i++) { |
| 532 r_digits[i] = l_digits[i]; | 543 r_digits[i] = l_digits[i]; |
| 533 } | 544 } |
| 534 r._used = r_used; | 545 return new _Bigint(neg, r_used, r_digits); |
| 535 r._clamp(); | |
| 536 } | 546 } |
| 537 | 547 |
| 538 // r = abs(this) ^ abs(a). | 548 // Return abs(this) ^ abs(a) with sign set according to neg. |
| 539 void _absXorTo(_Bigint a, _Bigint r) { | 549 _Bigint _absXorSetSign(_Bigint a, bool neg) { |
| 540 var used = _used; | 550 var used = _used; |
| 541 var a_used = a._used; | 551 var a_used = a._used; |
| 542 var r_used = (used > a_used) ? used : a_used; | 552 var r_used = (used > a_used) ? used : a_used; |
| 543 r._ensureLength(r_used); | |
| 544 var digits = _digits; | 553 var digits = _digits; |
| 545 var a_digits = a._digits; | 554 var a_digits = a._digits; |
| 546 var r_digits = r._digits; | 555 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. |
| 547 var l, m; | 556 var l, m; |
| 548 if (used < a_used) { | 557 if (used < a_used) { |
| 549 l = a; | 558 l = a; |
| 550 m = used; | 559 m = used; |
| 551 } else { | 560 } else { |
| 552 l = this; | 561 l = this; |
| 553 m = a_used; | 562 m = a_used; |
| 554 } | 563 } |
| 555 for (var i = 0; i < m; i++) { | 564 for (var i = 0; i < m; i++) { |
| 556 r_digits[i] = digits[i] ^ a_digits[i]; | 565 r_digits[i] = digits[i] ^ a_digits[i]; |
| 557 } | 566 } |
| 558 var l_digits = l._digits; | 567 var l_digits = l._digits; |
| 559 for (var i = m; i < r_used; i++) { | 568 for (var i = m; i < r_used; i++) { |
| 560 r_digits[i] = l_digits[i]; | 569 r_digits[i] = l_digits[i]; |
| 561 } | 570 } |
| 562 r._used = r_used; | 571 return new _Bigint(neg, r_used, r_digits); |
| 563 r._clamp(); | |
| 564 } | 572 } |
| 565 | 573 |
| 566 // Return r = this & a. | 574 // Return this & a. |
| 567 _Bigint _andTo(_Bigint a, _Bigint r) { | 575 _Bigint _and(_Bigint a) { |
| 568 if (_neg == a._neg) { | 576 if (_neg == a._neg) { |
| 569 if (_neg) { | 577 if (_neg) { |
| 570 // (-this) & (-a) == ~(this-1) & ~(a-1) | 578 // (-this) & (-a) == ~(this-1) & ~(a-1) |
| 571 // == ~((this-1) | (a-1)) | 579 // == ~((this-1) | (a-1)) |
| 572 // == -(((this-1) | (a-1)) + 1) | 580 // == -(((this-1) | (a-1)) + 1) |
| 573 _Bigint t1 = new _Bigint(); | 581 _Bigint t1 = _absSubSetSign(ONE, true); |
| 574 _absSubTo(ONE, t1); | 582 _Bigint a1 = a._absSubSetSign(ONE, true); |
| 575 _Bigint a1 = new _Bigint(); | 583 // Result cannot be zero if this and a are negative. |
| 576 a._absSubTo(ONE, a1); | 584 return t1._absOrSetSign(a1, true)._absAddSetSign(ONE, true); |
| 577 t1._absOrTo(a1, r); | |
| 578 r._absAddTo(ONE, r); | |
| 579 r._neg = true; // r cannot be zero if this and a are negative. | |
| 580 return r; | |
| 581 } | 585 } |
| 582 _absAndTo(a, r); | 586 return _absAndSetSign(a, false); |
| 583 r._neg = false; | |
| 584 return r; | |
| 585 } | 587 } |
| 586 // _neg != a._neg | 588 // _neg != a._neg |
| 587 var p, n; | 589 var p, n; |
| 588 if (_neg) { | 590 if (_neg) { |
| 589 p = a; | 591 p = a; |
| 590 n = this; | 592 n = this; |
| 591 } else { // & is symmetric. | 593 } else { // & is symmetric. |
| 592 p = this; | 594 p = this; |
| 593 n = a; | 595 n = a; |
| 594 } | 596 } |
| 595 // p & (-n) == p & ~(n-1) == p &~ (n-1) | 597 // p & (-n) == p & ~(n-1) == p &~ (n-1) |
| 596 _Bigint n1 = new _Bigint(); | 598 _Bigint n1 = n._absSubSetSign(ONE, false); |
| 597 n._absSubTo(ONE, n1); | 599 return p._absAndNotSetSign(n1, false); |
| 598 p._absAndNotTo(n1, r); | |
| 599 r._neg = false; | |
| 600 return r; | |
| 601 } | 600 } |
| 602 | 601 |
| 603 // Return r = this &~ a. | 602 // Return this &~ a. |
| 604 _Bigint _andNotTo(_Bigint a, _Bigint r) { | 603 _Bigint _andNot(_Bigint a) { |
| 605 if (_neg == a._neg) { | 604 if (_neg == a._neg) { |
| 606 if (_neg) { | 605 if (_neg) { |
| 607 // (-this) &~ (-a) == ~(this-1) &~ ~(a-1) | 606 // (-this) &~ (-a) == ~(this-1) &~ ~(a-1) |
| 608 // == ~(this-1) & (a-1) | 607 // == ~(this-1) & (a-1) |
| 609 // == (a-1) &~ (this-1) | 608 // == (a-1) &~ (this-1) |
| 610 _Bigint t1 = new _Bigint(); | 609 _Bigint t1 = _absSubSetSign(ONE, true); |
| 611 _absSubTo(ONE, t1); | 610 _Bigint a1 = a._absSubSetSign(ONE, true); |
| 612 _Bigint a1 = new _Bigint(); | 611 return a1._absAndNotSetSign(t1, false); |
| 613 a._absSubTo(ONE, a1); | |
| 614 a1._absAndNotTo(t1, r); | |
| 615 r._neg = false; | |
| 616 return r; | |
| 617 } | 612 } |
| 618 _absAndNotTo(a, r); | 613 return _absAndNotSetSign(a, false); |
| 619 r._neg = false; | |
| 620 return r; | |
| 621 } | 614 } |
| 622 if (_neg) { | 615 if (_neg) { |
| 623 // (-this) &~ a == ~(this-1) &~ a | 616 // (-this) &~ a == ~(this-1) &~ a |
| 624 // == ~(this-1) & ~a | 617 // == ~(this-1) & ~a |
| 625 // == ~((this-1) | a) | 618 // == ~((this-1) | a) |
| 626 // == -(((this-1) | a) + 1) | 619 // == -(((this-1) | a) + 1) |
| 627 _Bigint t1 = new _Bigint(); | 620 _Bigint t1 = _absSubSetSign(ONE, true); |
| 628 _absSubTo(ONE, t1); | 621 // Result cannot be zero if this is negative and a is positive. |
| 629 t1._absOrTo(a, r); | 622 return t1._absOrSetSign(a, true)._absAddSetSign(ONE, true); |
| 630 r._absAddTo(ONE, r); | |
| 631 r._neg = true; // r cannot be zero if this is negative and a is positive. | |
| 632 return r; | |
| 633 } | 623 } |
| 634 // this &~ (-a) == this &~ ~(a-1) == this & (a-1) | 624 // this &~ (-a) == this &~ ~(a-1) == this & (a-1) |
| 635 _Bigint a1 = new _Bigint(); | 625 _Bigint a1 = a._absSubSetSign(ONE, true); |
| 636 a._absSubTo(ONE, a1); | 626 return _absAndSetSign(a1, false); |
| 637 _absAndTo(a1, r); | |
| 638 r._neg = false; | |
| 639 return r; | |
| 640 } | 627 } |
| 641 | 628 |
| 642 // Return r = this | a. | 629 // Return this | a. |
| 643 _Bigint _orTo(_Bigint a, _Bigint r) { | 630 _Bigint _or(_Bigint a) { |
| 644 if (_neg == a._neg) { | 631 if (_neg == a._neg) { |
| 645 if (_neg) { | 632 if (_neg) { |
| 646 // (-this) | (-a) == ~(this-1) | ~(a-1) | 633 // (-this) | (-a) == ~(this-1) | ~(a-1) |
| 647 // == ~((this-1) & (a-1)) | 634 // == ~((this-1) & (a-1)) |
| 648 // == -(((this-1) & (a-1)) + 1) | 635 // == -(((this-1) & (a-1)) + 1) |
| 649 _Bigint t1 = new _Bigint(); | 636 _Bigint t1 = _absSubSetSign(ONE, true); |
| 650 _absSubTo(ONE, t1); | 637 _Bigint a1 = a._absSubSetSign(ONE, true); |
| 651 _Bigint a1 = new _Bigint(); | 638 // Result cannot be zero if this and a are negative. |
| 652 a._absSubTo(ONE, a1); | 639 return t1._absAndSetSign(a1, true)._absAddSetSign(ONE, true); |
| 653 t1._absAndTo(a1, r); | |
| 654 r._absAddTo(ONE, r); | |
| 655 r._neg = true; // r cannot be zero if this and a are negative. | |
| 656 return r; | |
| 657 } | 640 } |
| 658 _absOrTo(a, r); | 641 return _absOrSetSign(a, false); |
| 659 r._neg = false; | |
| 660 return r; | |
| 661 } | 642 } |
| 662 // _neg != a._neg | 643 // _neg != a._neg |
| 663 var p, n; | 644 var p, n; |
| 664 if (_neg) { | 645 if (_neg) { |
| 665 p = a; | 646 p = a; |
| 666 n = this; | 647 n = this; |
| 667 } else { // | is symmetric. | 648 } else { // | is symmetric. |
| 668 p = this; | 649 p = this; |
| 669 n = a; | 650 n = a; |
| 670 } | 651 } |
| 671 // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1) | 652 // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1) |
| 672 _Bigint n1 = new _Bigint(); | 653 _Bigint n1 = n._absSubSetSign(ONE, true); |
| 673 n._absSubTo(ONE, n1); | 654 // Result cannot be zero if only one of this or a is negative. |
| 674 n1._absAndNotTo(p, r); | 655 return n1._absAndNotSetSign(p, true)._absAddSetSign(ONE, true); |
| 675 r._absAddTo(ONE, r); | |
| 676 r._neg = true; // r cannot be zero if only one of this or a is negative. | |
| 677 return r; | |
| 678 } | 656 } |
| 679 | 657 |
| 680 // Return r = this ^ a. | 658 // Return this ^ a. |
| 681 _Bigint _xorTo(_Bigint a, _Bigint r) { | 659 _Bigint _xor(_Bigint a) { |
| 682 if (_neg == a._neg) { | 660 if (_neg == a._neg) { |
| 683 if (_neg) { | 661 if (_neg) { |
| 684 // (-this) ^ (-a) == ~(this-1) ^ ~(a-1) == (this-1) ^ (a-1) | 662 // (-this) ^ (-a) == ~(this-1) ^ ~(a-1) == (this-1) ^ (a-1) |
| 685 _Bigint t1 = new _Bigint(); | 663 _Bigint t1 = _absSubSetSign(ONE, true); |
| 686 _absSubTo(ONE, t1); | 664 _Bigint a1 = a._absSubSetSign(ONE, true); |
| 687 _Bigint a1 = new _Bigint(); | 665 return t1._absXorSetSign(a1, false); |
| 688 a._absSubTo(ONE, a1); | |
| 689 t1._absXorTo(a1, r); | |
| 690 r._neg = false; | |
| 691 return r; | |
| 692 } | 666 } |
| 693 _absXorTo(a, r); | 667 return _absXorSetSign(a, false); |
| 694 r._neg = false; | |
| 695 return r; | |
| 696 } | 668 } |
| 697 // _neg != a._neg | 669 // _neg != a._neg |
| 698 var p, n; | 670 var p, n; |
| 699 if (_neg) { | 671 if (_neg) { |
| 700 p = a; | 672 p = a; |
| 701 n = this; | 673 n = this; |
| 702 } else { // ^ is symmetric. | 674 } else { // ^ is symmetric. |
| 703 p = this; | 675 p = this; |
| 704 n = a; | 676 n = a; |
| 705 } | 677 } |
| 706 // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1) | 678 // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1) |
| 707 _Bigint n1 = new _Bigint(); | 679 _Bigint n1 = n._absSubSetSign(ONE, true); |
| 708 n._absSubTo(ONE, n1); | 680 // Result cannot be zero if only one of this or a is negative. |
| 709 p._absXorTo(n1, r); | 681 return p._absXorSetSign(n1, true)._absAddSetSign(ONE, true); |
| 710 r._absAddTo(ONE, r); | |
| 711 r._neg = true; // r cannot be zero if only one of this or a is negative. | |
| 712 return r; | |
| 713 } | 682 } |
| 714 | 683 |
| 715 // Return r = ~this. | 684 // Return ~this. |
| 716 _Bigint _notTo(_Bigint r) { | 685 _Bigint _not() { |
| 717 if (_neg) { | 686 if (_neg) { |
| 718 // ~(-this) == ~(~(this-1)) == this-1 | 687 // ~(-this) == ~(~(this-1)) == this-1 |
| 719 _absSubTo(ONE, r); | 688 return _absSubSetSign(ONE, false); |
| 720 r._neg = false; | |
| 721 return r; | |
| 722 } | 689 } |
| 723 // ~this == -this-1 == -(this+1) | 690 // ~this == -this-1 == -(this+1) |
| 724 _absAddTo(ONE, r); | 691 // Result cannot be zero if this is positive. |
| 725 r._neg = true; // r cannot be zero if this is positive. | 692 return _absAddSetSign(ONE, true); |
| 726 return r; | |
| 727 } | 693 } |
| 728 | 694 |
| 729 // Return r = this + a. | 695 // Return this + a. |
| 730 _Bigint _addTo(_Bigint a, _Bigint r) { | 696 _Bigint _add(_Bigint a) { |
| 731 var r_neg = _neg; | 697 var neg = _neg; |
| 732 if (_neg == a._neg) { | 698 if (neg == a._neg) { |
| 733 // this + a == this + a | 699 // this + a == this + a |
| 734 // (-this) + (-a) == -(this + a) | 700 // (-this) + (-a) == -(this + a) |
| 735 _absAddTo(a, r); | 701 return _absAddSetSign(a, neg); |
| 736 } else { | |
| 737 // this + (-a) == this - a == -(this - a) | |
| 738 // (-this) + a == a - this == -(this - a) | |
| 739 if (_absCompareTo(a) >= 0) { | |
| 740 _absSubTo(a, r); | |
| 741 } else { | |
| 742 r_neg = !r_neg; | |
| 743 a._absSubTo(this, r); | |
| 744 } | |
| 745 } | 702 } |
| 746 » r._neg = r_neg; | 703 // this + (-a) == this - a == -(this - a) |
| 747 return r; | 704 // (-this) + a == a - this == -(this - a) |
| 705 if (_absCompare(a) >= 0) { | |
| 706 return _absSubSetSign(a, neg); | |
| 707 } | |
| 708 return a._absSubSetSign(this, !neg); | |
| 748 } | 709 } |
| 749 | 710 |
| 750 // Return r = this - a. | 711 // Return this - a. |
| 751 _Bigint _subTo(_Bigint a, _Bigint r) { | 712 _Bigint _sub(_Bigint a) { |
| 752 » var r_neg = _neg; | 713 » var neg = _neg; |
|
rmacnak
2015/02/04 19:24:53
tabs
regis
2015/02/04 22:06:23
Done.
| |
| 753 if (_neg != a._neg) { | 714 if (neg != a._neg) { |
| 754 // this - (-a) == this + a | 715 // this - (-a) == this + a |
| 755 // (-this) - a == -(this + a) | 716 // (-this) - a == -(this + a) |
| 756 _absAddTo(a, r); | 717 return _absAddSetSign(a, neg); |
| 757 » } else { | 718 » } |
| 758 » » // this - a == this - a == -(this - a) | 719 // this - a == this - a == -(this - a) |
| 759 » » // (-this) - (-a) == a - this == -(this - a) | 720 // (-this) - (-a) == a - this == -(this - a) |
| 760 if (_absCompareTo(a) >= 0) { | 721 if (_absCompare(a) >= 0) { |
| 761 _absSubTo(a, r); | 722 return _absSubSetSign(a, neg); |
| 762 » » } else { | |
| 763 r_neg = !r_neg; | |
| 764 a._absSubTo(this, r); | |
| 765 } | |
| 766 } | 723 } |
| 767 » r._neg = r_neg; | 724 return a._absSubSetSign(this, !neg); |
| 768 return r; | |
| 769 } | 725 } |
| 770 | 726 |
| 771 // Multiply and accumulate. | 727 // Multiply and accumulate. |
| 772 // Input: | 728 // Input: |
| 773 // x_digits[xi]: multiplier digit x. | 729 // x_digits[xi]: multiplier digit x. |
| 774 // m_digits[i..i+n-1]: multiplicand digits. | 730 // m_digits[i..i+n-1]: multiplicand digits. |
| 775 // a_digits[j..j+n-1]: accumulator digits. | 731 // a_digits[j..j+n-1]: accumulator digits. |
| 776 // Operation: | 732 // Operation: |
| 777 // a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1]. | 733 // a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1]. |
| 778 // return 1. | 734 // return 1. |
| 779 // Note: intrinsics on 64-bit platform may process a digit pair: | 735 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices |
| 780 // a_digits[j..j+n] += x_digits[xi..xi+1]*m_digits[i..i+n-1]. | 736 // and return 2. |
| 781 // return 2. | |
| 782 static int _mulAdd(Uint32List x_digits, int xi, | 737 static int _mulAdd(Uint32List x_digits, int xi, |
| 783 Uint32List m_digits, int i, | 738 Uint32List m_digits, int i, |
| 784 Uint32List a_digits, int j, int n) { | 739 Uint32List a_digits, int j, int n) { |
| 740 // Verify that digit pairs are accessible for 64-bit processing. | |
| 741 assert(x_digits.length > (xi | 1)); | |
| 742 assert(m_digits.length > ((i + n - 1) | 1)); | |
| 743 assert(a_digits.length > ((j + n) | 1)); | |
| 785 int x = x_digits[xi]; | 744 int x = x_digits[xi]; |
| 786 if (x == 0) { | 745 if (x == 0) { |
| 787 // No-op if x is 0. | 746 // No-op if x is 0. |
| 788 return 1; | 747 return 1; |
| 789 } | 748 } |
| 790 int c = 0; | 749 int c = 0; |
| 791 int xl = x & DIGIT2_MASK; | 750 int xl = x & DIGIT2_MASK; |
| 792 int xh = x >> DIGIT2_BITS; | 751 int xh = x >> DIGIT2_BITS; |
| 793 while (--n >= 0) { | 752 while (--n >= 0) { |
| 794 int l = m_digits[i] & DIGIT2_MASK; | 753 int l = m_digits[i] & DIGIT2_MASK; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 807 } | 766 } |
| 808 | 767 |
| 809 // Square and accumulate. | 768 // Square and accumulate. |
| 810 // Input: | 769 // Input: |
| 811 // x_digits[i..used-1]: digits of operand being squared. | 770 // x_digits[i..used-1]: digits of operand being squared. |
| 812 // a_digits[2*i..i+used-1]: accumulator digits. | 771 // a_digits[2*i..i+used-1]: accumulator digits. |
| 813 // Operation: | 772 // Operation: |
| 814 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + | 773 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + |
| 815 // 2*x_digits[i]*x_digits[i+1..used-1]. | 774 // 2*x_digits[i]*x_digits[i+1..used-1]. |
| 816 // return 1. | 775 // return 1. |
| 817 // Note: intrinsics on 64-bit platform may process a digit pair: | 776 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices |
| 818 // a_digits[2*i..i+used-1] += x_digits[i..i+1]*x_digits[i..i+1] + | 777 // and return 2. |
| 819 // 2*x_digits[i..i+1]*x_digits[i+2..used-1]. | |
| 820 // return 2. | |
| 821 static int _sqrAdd(Uint32List x_digits, int i, | 778 static int _sqrAdd(Uint32List x_digits, int i, |
| 822 Uint32List a_digits, int used) { | 779 Uint32List a_digits, int used) { |
| 780 // Verify that digit pairs are accessible for 64-bit processing. | |
| 781 assert(x_digits.length > ((used - 1) | 1)); | |
| 782 assert(a_digits.length > ((i + used - 1) | 1)); | |
| 823 int x = x_digits[i]; | 783 int x = x_digits[i]; |
| 824 if (x == 0) return 1; | 784 if (x == 0) return 1; |
| 825 int j = 2*i; | 785 int j = 2*i; |
| 826 int c = 0; | 786 int c = 0; |
| 827 int xl = x & DIGIT2_MASK; | 787 int xl = x & DIGIT2_MASK; |
| 828 int xh = x >> DIGIT2_BITS; | 788 int xh = x >> DIGIT2_BITS; |
| 829 int m = 2*xh*xl; | 789 int m = 2*xh*xl; |
| 830 int l = xl*xl + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j]; | 790 int l = xl*xl + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j]; |
| 831 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*xh; | 791 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*xh; |
| 832 a_digits[j] = l & DIGIT_MASK; | 792 a_digits[j] = l & DIGIT_MASK; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 847 c += a_digits[i + used]; | 807 c += a_digits[i + used]; |
| 848 if (c >= DIGIT_BASE) { | 808 if (c >= DIGIT_BASE) { |
| 849 a_digits[i + used] = c - DIGIT_BASE; | 809 a_digits[i + used] = c - DIGIT_BASE; |
| 850 a_digits[i + used + 1] = 1; | 810 a_digits[i + used + 1] = 1; |
| 851 } else { | 811 } else { |
| 852 a_digits[i + used] = c; | 812 a_digits[i + used] = c; |
| 853 } | 813 } |
| 854 return 1; | 814 return 1; |
| 855 } | 815 } |
| 856 | 816 |
| 857 // r = this * a. | 817 // Return this * a. |
| 858 void _mulTo(_Bigint a, _Bigint r) { | 818 _Bigint _mul(_Bigint a) { |
| 859 // TODO(regis): Use karatsuba multiplication when appropriate. | 819 // TODO(regis): Use karatsuba multiplication when appropriate. |
| 860 var used = _used; | 820 var used = _used; |
| 861 var a_used = a._used; | 821 var a_used = a._used; |
| 862 if (used == 0 || a_used == 0) { | 822 if (used == 0 || a_used == 0) { |
| 863 r._used = 0; | 823 return ZERO; |
| 864 r._neg = false; | |
| 865 return; | |
| 866 } | 824 } |
| 867 var r_used = used + a_used; | 825 var r_used = used + a_used; |
| 868 r._ensureLength(r_used); | |
| 869 var digits = _digits; | 826 var digits = _digits; |
| 870 var a_digits = a._digits; | 827 var a_digits = a._digits; |
| 871 var r_digits = r._digits; | 828 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. |
| 872 r._used = r_used; | |
| 873 var i = r_used + 1; // Set leading zero for 64-bit processing. | 829 var i = r_used + 1; // Set leading zero for 64-bit processing. |
| 874 while (--i >= 0) { | 830 while (--i >= 0) { |
| 875 r_digits[i] = 0; | 831 r_digits[i] = 0; |
| 876 } | 832 } |
| 877 i = 0; | 833 i = 0; |
| 878 while (i < a_used) { | 834 while (i < a_used) { |
| 879 i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used); | 835 i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used); |
| 880 } | 836 } |
| 881 r._clamp(); | 837 return new _Bigint(_neg != a._neg, r_used, r_digits); |
| 882 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. | |
| 883 } | 838 } |
| 884 | 839 |
| 885 // r = this^2, r != this. | 840 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*a_digits[0..a_used-1]. |
| 886 void _sqrTo(_Bigint r) { | 841 // Return r_used = x_used + a_used. |
| 887 var used = _used; | 842 static int _mulDigits(Uint32List x_digits, int x_used, |
| 888 if (used == 0) { | 843 Uint32List a_digits, int a_used, |
| 889 r._used = 0; | 844 Uint32List r_digits) { |
| 890 r._neg = false; | 845 var r_used = x_used + a_used; |
| 891 return; | 846 assert(r_digits.length >= r_used + 1); // +1 for leading zero. |
| 892 } | |
| 893 var r_used = 2 * used; | |
| 894 r._ensureLength(r_used); | |
| 895 var digits = _digits; | |
| 896 var r_digits = r._digits; | |
| 897 var i = r_used + 1; // Set leading zero for 64-bit processing. | 847 var i = r_used + 1; // Set leading zero for 64-bit processing. |
| 898 while (--i >= 0) { | 848 while (--i >= 0) { |
| 899 r_digits[i] = 0; | 849 r_digits[i] = 0; |
| 850 } | |
| 851 i = 0; | |
| 852 while (i < a_used) { | |
| 853 i += _mulAdd(a_digits, i, x_digits, 0, r_digits, i, x_used); | |
| 854 } | |
| 855 return r_used; | |
| 856 } | |
| 857 | |
| 858 // Return this^2. | |
| 859 _Bigint _sqr() { | |
| 860 var used = _used; | |
| 861 if (used == 0) { | |
| 862 return ZERO; | |
| 863 } | |
| 864 var r_used = 2 * used; | |
| 865 var digits = _digits; | |
| 866 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero. | |
| 867 var i = r_used + 1; // Set leading zero for 64-bit processing. | |
| 868 while (--i >= 0) { | |
| 869 r_digits[i] = 0; | |
| 900 } | 870 } |
| 901 i = 0; | 871 i = 0; |
| 902 while (i < used - 1) { | 872 while (i < used - 1) { |
| 903 i += _sqrAdd(digits, i, r_digits, used); | 873 i += _sqrAdd(digits, i, r_digits, used); |
| 904 } | 874 } |
| 905 if (r_used > 0) { | 875 // The last step may not be required if digit pairs were processed above. |
| 876 if (i < used) { | |
| 906 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); | 877 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); |
| 907 } | 878 } |
| 908 r._used = r_used; | 879 return new _Bigint(false, r_used, r_digits); |
| 909 r._neg = false; | 880 } |
| 910 r._clamp(); | 881 |
| 882 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*x_digits[0..x_used-1]. | |
| 883 // Return r_used = 2*x_used. | |
| 884 static int _sqrDigits(Uint32List x_digits, int x_used, Uint32List r_digits) { | |
| 885 var r_used = 2 * x_used; | |
| 886 assert(r_digits.length >= r_used + 1); // +1 for leading zero. | |
| 887 var i = r_used + 1; // Set leading zero for 64-bit processing. | |
| 888 while (--i >= 0) { | |
| 889 r_digits[i] = 0; | |
| 890 } | |
| 891 i = 0; | |
| 892 while (i < x_used - 1) { | |
| 893 i += _sqrAdd(x_digits, i, r_digits, x_used); | |
| 894 } | |
| 895 // The last step may not be required if digit pairs were processed above. | |
| 896 if (i < x_used) { | |
| 897 _mulAdd(x_digits, i, x_digits, i, r_digits, 2*i, 1); | |
| 898 } | |
| 899 return r_used; | |
| 911 } | 900 } |
| 912 | 901 |
| 913 // Indices of the arguments of _estQuotientDigit. | 902 // Indices of the arguments of _estQuotientDigit. |
| 914 // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair | 903 // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair |
| 915 // of divisor y is provided in the args array, and a 64-bit estimated quotient | 904 // of divisor y is provided in the args array, and a 64-bit estimated quotient |
| 916 // is returned. However, on 32-bit platforms, the low 32-bit digit is ignored | 905 // is returned. However, on 32-bit platforms, the low 32-bit digit is ignored |
| 917 // and only one 32-bit digit is returned as the estimated quotient. | 906 // and only one 32-bit digit is returned as the estimated quotient. |
| 918 static const int _YT_LO = 0; // Low digit of top digit pair of y, for 64-bit. | 907 static const int _YT_LO = 0; // Low digit of top digit pair of y, for 64-bit. |
| 919 static const int _YT = 1; // Top digit of divisor y. | 908 static const int _YT = 1; // Top digit of divisor y. |
| 920 static const int _QD = 2; // Estimated quotient. | 909 static const int _QD = 2; // Estimated quotient. |
| 921 static const int _QD_HI = 3; // High digit of estimated quotient, for 64-bit. | 910 static const int _QD_HI = 3; // High digit of estimated quotient, for 64-bit. |
| 922 | 911 |
| 923 // Operation: | 912 // Operation: |
| 924 // Estimate args[_QD] = digits[i-1..i] ~/ args[_YT] | 913 // Estimate args[_QD] = digits[i-1..i] ~/ args[_YT] |
| 925 // return 1 | 914 // return 1 |
| 926 // Note: intrinsics on 64-bit platform may process a digit pair: | 915 // Note: Intrinsics on 64-bit platforms process a digit pair (i always odd): |
| 927 // Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT] | 916 // Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT] |
| 928 // return 2 | 917 // return 2 |
| 929 static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { | 918 static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { |
| 919 // Verify that digit pairs are accessible for 64-bit processing. | |
| 920 assert(digits.length >= 4 + 1); // +1 for leading zero. | |
| 930 if (digits[i] == args[_YT]) { | 921 if (digits[i] == args[_YT]) { |
| 931 args[_QD] = DIGIT_MASK; | 922 args[_QD] = DIGIT_MASK; |
| 932 } else { | 923 } else { |
| 933 // Chop off one bit, since a Mint cannot hold 2 DIGITs. | 924 // Chop off one bit, since a Mint cannot hold 2 DIGITs. |
| 934 var qd = ((digits[i] << (DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) | 925 var qd = ((digits[i] << (DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) |
| 935 ~/ (args[_YT] >> 1); | 926 ~/ (args[_YT] >> 1); |
| 936 if (qd > DIGIT_MASK) { | 927 if (qd > DIGIT_MASK) { |
| 937 args[_QD] = DIGIT_MASK; | 928 args[_QD] = DIGIT_MASK; |
| 938 } else { | 929 } else { |
| 939 args[_QD] = qd; | 930 args[_QD] = qd; |
| 940 } | 931 } |
| 941 } | 932 } |
| 942 return 1; | 933 return 1; |
| 943 } | 934 } |
| 944 | 935 |
| 936 // Return trunc(this / a), a != 0. | |
| 937 _Bigint _div(_Bigint a) { | |
| 938 return _divRem(a, true); | |
| 939 } | |
| 945 | 940 |
| 946 // Truncating division and remainder. | 941 // Return this - a * trunc(this / a), a != 0. |
| 947 // If q != null, q = trunc(this / a). | 942 _Bigint _rem(_Bigint a) { |
| 948 // If r != null, r = this - a * trunc(this / a). | 943 return _divRem(a, false); |
| 949 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { | 944 } |
| 950 if (a._used == 0) return; | 945 |
| 946 // Return trunc(this / a), a != 0, if div == true. | |
| 947 // Return this - a * trunc(this / a), a != 0, if div == false. | |
| 948 _Bigint _divRem(_Bigint a, bool div) { | |
| 949 assert(a._used > 0); | |
| 951 if (_used < a._used) { | 950 if (_used < a._used) { |
| 952 if (q != null) { | 951 return div ? ZERO : this; |
| 953 // Set q to 0. | |
| 954 q._neg = false; | |
| 955 q._used = 0; | |
| 956 } | |
| 957 if (r != null) { | |
| 958 _copyTo(r); | |
| 959 } | |
| 960 return; | |
| 961 } | 952 } |
| 962 if (r == null) { | |
| 963 r = new _Bigint(); | |
| 964 } | |
| 965 var y = new _Bigint(); // Normalized modulus. | |
| 966 var nsh = DIGIT_BITS - _nbits(a._digits[a._used - 1]); | 953 var nsh = DIGIT_BITS - _nbits(a._digits[a._used - 1]); |
| 967 // For 64-bit processing, make sure y has an even number of digits. | 954 // For 64-bit processing, make sure y has an even number of digits. |
| 968 if ((a._used & 1) == 1) { | 955 if (a._used.isOdd) { |
| 969 nsh += DIGIT_BITS; | 956 nsh += DIGIT_BITS; |
| 970 } | 957 } |
| 958 var y; // Normalized positive divisor. | |
| 959 var r; // Concatenated positive quotient and normalized positive remainder. | |
| 971 if (nsh > 0) { | 960 if (nsh > 0) { |
| 972 a._lShiftTo(nsh, y); | 961 y = a._lShift(nsh)._abs(); |
| 973 _lShiftTo(nsh, r); | 962 r = _lShift(nsh)._abs(); |
| 974 } | 963 } |
| 975 else { | 964 else { |
| 976 a._copyTo(y); | 965 y = a._abs(); |
| 977 _copyTo(r); | 966 r = _abs(); |
| 978 } | 967 } |
| 979 // We consider this and a positive. Ignore the copied sign. | |
| 980 y._neg = false; | |
| 981 r._neg = false; | |
| 982 var y_used = y._used; | 968 var y_used = y._used; |
| 983 assert((y_used & 1) == 0); | |
| 984 var y_digits = y._digits; | 969 var y_digits = y._digits; |
| 985 Uint32List args = new Uint32List(4); | 970 Uint32List args = new Uint32List(4); |
| 986 args[_YT_LO] = y_digits[y_used - 2]; | 971 args[_YT_LO] = y_digits[y_used - 2]; |
| 987 args[_YT] = y_digits[y_used - 1]; | 972 args[_YT] = y_digits[y_used - 1]; |
| 988 var r_digits = r._digits; | 973 var r_used = r._used; |
| 989 var i = r._used; | 974 // For 64-bit processing, make sure y_used, i, and j are even. |
| 990 if ((i & 1) == 1) { | 975 assert(y_used.isEven); |
| 991 // For 64-bit processing, make sure r has an even number of digits. | 976 var i = r_used + (r_used & 1); |
| 992 r_digits[i++] = 0; | 977 var j = i - y_used; |
| 978 var t = y._dlShift(j); | |
| 979 if (r._compare(t) >= 0) { | |
| 980 assert(i == r_used); | |
| 981 r = r._or(ONE._dlShift(r_used++))._sub(t); | |
| 982 assert(r._used == r_used); | |
| 993 } | 983 } |
| 994 var j = i - y_used; | 984 // Negate y so we can later use _mulAdd instead of non-existent _mulSub. |
| 995 _Bigint t = (q == null) ? new _Bigint() : q; | 985 y = ONE._dlShift(y_used)._sub(y); |
| 996 y._dlShiftTo(j, t); | 986 if (y._used < y_used) { |
| 997 if (r._compareTo(t) >= 0) { | 987 y_digits = _cloneDigits(y._digits, 0, y._used, y_used); |
| 998 r_digits[r._used++] = 1; | 988 } else { |
| 999 r_digits[r._used] = 0; // Set leading zero for 64-bit processing. | 989 y_digits = y._digits; |
| 1000 r._subTo(t, r); | |
| 1001 } | 990 } |
| 1002 ONE._dlShiftTo(y_used, t); | 991 // y_digits is read-only and has y_used digits (possibly including several |
| 1003 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. | 992 // leading zeros) plus a leading zero for 64-bit processing. |
| 1004 while (y._used < y_used) { | 993 var r_digits = _cloneDigits(r._digits, 0, r._used, i); |
| 1005 y_digits[y._used++] = 0; | 994 // r_digits is modified during iteration. |
| 1006 } | 995 // r_digits[0..y_used-1] is the current remainder. |
| 1007 y_digits[y._used] = 0; // Set leading zero for 64-bit processing. | 996 // r_digits[y_used..r_used-1] is the current quotient. |
| 997 --i; | |
| 1008 while (j > 0) { | 998 while (j > 0) { |
| 1009 var d0 = _estQuotientDigit(args, r_digits, --i); | 999 var d0 = _estQuotientDigit(args, r_digits, i); |
| 1010 j -= d0; | 1000 j -= d0; |
| 1011 var d1 = _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used); | 1001 var d1 = _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used); |
| 1012 // _estQuotientDigit and _mulAdd must agree on the number of digits to | 1002 // _estQuotientDigit and _mulAdd must agree on the number of digits to |
| 1013 // process. | 1003 // process. |
| 1014 assert(d0 == d1); | 1004 assert(d0 == d1); |
| 1015 if (d0 == 1) { | 1005 if (d0 == 1) { |
| 1016 if (r_digits[i] < args[_QD]) { | 1006 if (r_digits[i] < args[_QD]) { |
| 1017 y._dlShiftTo(j, t); | 1007 var t = y._dlShift(j); |
| 1018 r._subTo(t, r); | 1008 var t_digits = t._digits; |
| 1009 var t_used = t._used; | |
| 1010 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | |
| 1019 while (r_digits[i] < --args[_QD]) { | 1011 while (r_digits[i] < --args[_QD]) { |
| 1020 r._subTo(t, r); | 1012 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1021 } | 1013 } |
| 1022 } | 1014 } |
| 1023 } else { | 1015 } else { |
| 1024 assert(d0 == 2); | 1016 assert(d0 == 2); |
| 1025 assert(r_digits[i] <= args[_QD_HI]); | 1017 assert(r_digits[i] <= args[_QD_HI]); |
| 1026 if ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) { | 1018 if ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) { |
| 1027 y._dlShiftTo(j, t); | 1019 var t = y._dlShift(j); |
| 1028 r._subTo(t, r); | 1020 var t_digits = t._digits; |
| 1021 var t_used = t._used; | |
| 1022 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | |
| 1029 if (args[_QD] == 0) { | 1023 if (args[_QD] == 0) { |
| 1030 --args[_QD_HI]; | 1024 --args[_QD_HI]; |
| 1031 } | 1025 } |
| 1032 --args[_QD]; | 1026 --args[_QD]; |
| 1033 assert(r_digits[i] <= args[_QD_HI]); | 1027 assert(r_digits[i] <= args[_QD_HI]); |
| 1034 while ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) { | 1028 while ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) { |
| 1035 r._subTo(t, r); | 1029 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1036 if (args[_QD] == 0) { | 1030 if (args[_QD] == 0) { |
| 1037 --args[_QD_HI]; | 1031 --args[_QD_HI]; |
| 1038 } | 1032 } |
| 1039 --args[_QD]; | 1033 --args[_QD]; |
| 1040 assert(r_digits[i] <= args[_QD_HI]); | 1034 assert(r_digits[i] <= args[_QD_HI]); |
| 1041 } | 1035 } |
| 1042 } | 1036 } |
| 1043 --i; | |
| 1044 } | 1037 } |
| 1038 i -= d0; | |
| 1045 } | 1039 } |
| 1046 if (q != null) { | 1040 if (div) { |
| 1047 r._drShiftTo(y_used, q); | 1041 // Return quotient, i.e. r_digits[y_used..r_used-1] with proper sign. |
| 1048 if (_neg != a._neg && q._used > 0) { | 1042 r_digits = _cloneDigits(r_digits, y_used, r_used, r_used - y_used); |
| 1049 q._neg = !q._neg; | 1043 r = new _Bigint(false, r_used - y_used, r_digits); |
| 1044 if (_neg != a._neg && r._used > 0) { | |
| 1045 r = r._negate(); | |
| 1050 } | 1046 } |
| 1047 return r; | |
| 1051 } | 1048 } |
| 1052 r._used = y_used; | 1049 // Return remainder, i.e. denormalized r_digits[0..y_used-1] with |
| 1053 r._clamp(); | 1050 // proper sign. |
| 1051 r_digits = _cloneDigits(r_digits, 0, y_used, y_used); | |
| 1052 r = new _Bigint(false, y_used, r_digits); | |
| 1054 if (nsh > 0) { | 1053 if (nsh > 0) { |
| 1055 r._rShiftTo(nsh, r); // Denormalize remainder. | 1054 r = r._rShift(nsh); // Denormalize remainder. |
| 1056 } | 1055 } |
| 1057 if (_neg && r._used > 0) { | 1056 if (_neg && r._used > 0) { |
| 1058 r._neg = !r._neg; | 1057 r = r._negate(); |
| 1059 } | 1058 } |
| 1059 return r; | |
| 1060 } | |
| 1061 | |
| 1062 // Customized version of _rem() minimizing allocations for use in reduction. | |
| 1063 // Input: | |
| 1064 // x_digits[0..x_used-1]: positive dividend. | |
| 1065 // y_digits[0..y_used-1]: normalized positive divisor. | |
| 1066 // ny_digits[0..y_used-1]: negated y_digits. | |
| 1067 // nsh: normalization shift amount. | |
| 1068 // yt_qd: top y digit(s) and place holder for estimated quotient digit(s). | |
| 1069 // t_digits: temp array of 2*y_used digits. | |
| 1070 // r_digits: result digits array large enough to temporarily hold | |
| 1071 // concatenated quotient and normalized remainder. | |
| 1072 // Output: | |
| 1073 // r_digits[0..r_used-1]: positive remainder. | |
| 1074 // Returns r_used. | |
| 1075 static int _remDigits(Uint32List x_digits, int x_used, | |
| 1076 Uint32List y_digits, int y_used, Uint32List ny_digits, | |
| 1077 int nsh, | |
| 1078 Uint32List yt_qd, | |
| 1079 Uint32List t_digits, | |
| 1080 Uint32List r_digits) { | |
| 1081 assert(y_used > 0 && x_used >= y_used); | |
| 1082 // Initialize r_digits to normalized positive dividend. | |
| 1083 var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits); | |
| 1084 // For 64-bit processing, make sure y_used, i, and j are even. | |
| 1085 assert(y_used.isEven); | |
| 1086 var i = r_used + (r_used & 1); | |
| 1087 var j = i - y_used; | |
| 1088 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); | |
| 1089 // Explicit first division step in case normalized dividend is larger or | |
| 1090 // equal to shifted normalized divisor. | |
| 1091 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { | |
| 1092 assert(i == r_used); | |
| 1093 r_digits[r_used++] = 1; // Quotient = 1. | |
| 1094 r_digits[r_used] = 0; // Leading zero. | |
| 1095 // Subtract divisor from remainder. | |
| 1096 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | |
| 1097 } | |
| 1098 // Negated y_digits passed in ny_digits allow the use of _mulAdd instead of | |
| 1099 // unimplemented _mulSub. | |
| 1100 // ny_digits is read-only and has y_used digits (possibly including several | |
| 1101 // leading zeros) plus a leading zero for 64-bit processing. | |
| 1102 // r_digits is modified during iteration. | |
| 1103 // r_digits[0..y_used-1] is the current remainder. | |
| 1104 // r_digits[y_used..r_used-1] is the current quotient. | |
| 1105 --i; | |
| 1106 while (j > 0) { | |
| 1107 var d0 = _estQuotientDigit(yt_qd, r_digits, i); | |
| 1108 j -= d0; | |
| 1109 var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used); | |
| 1110 // _estQuotientDigit and _mulAdd must agree on the number of digits to | |
| 1111 // process. | |
| 1112 assert(d0 == d1); | |
| 1113 if (d0 == 1) { | |
| 1114 if (r_digits[i] < yt_qd[_QD]) { | |
| 1115 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); | |
| 1116 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | |
| 1117 while (r_digits[i] < --yt_qd[_QD]) { | |
| 1118 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | |
| 1119 } | |
| 1120 } | |
| 1121 } else { | |
| 1122 assert(d0 == 2); | |
| 1123 assert(r_digits[i] <= yt_qd[_QD_HI]); | |
| 1124 if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i-1] < yt_qd[_QD])) { | |
| 1125 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); | |
| 1126 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | |
| 1127 if (yt_qd[_QD] == 0) { | |
| 1128 --yt_qd[_QD_HI]; | |
| 1129 } | |
| 1130 --yt_qd[_QD]; | |
| 1131 assert(r_digits[i] <= yt_qd[_QD_HI]); | |
| 1132 while ((r_digits[i] < yt_qd[_QD_HI]) || | |
| 1133 (r_digits[i-1] < yt_qd[_QD])) { | |
| 1134 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | |
| 1135 if (yt_qd[_QD] == 0) { | |
| 1136 --yt_qd[_QD_HI]; | |
| 1137 } | |
| 1138 --yt_qd[_QD]; | |
| 1139 assert(r_digits[i] <= yt_qd[_QD_HI]); | |
| 1140 } | |
| 1141 } | |
| 1142 } | |
| 1143 i -= d0; | |
| 1144 } | |
| 1145 // Return remainder, i.e. denormalized r_digits[0..y_used-1]. | |
| 1146 r_used = y_used; | |
| 1147 if (nsh > 0) { | |
| 1148 // Denormalize remainder. | |
| 1149 r_used = _rShiftDigits(r_digits, r_used, nsh, r_digits); | |
| 1150 } | |
| 1151 return r_used; | |
| 1060 } | 1152 } |
| 1061 | 1153 |
| 1062 int get _identityHashCode { | 1154 int get _identityHashCode { |
| 1063 return this; | 1155 return this; |
| 1064 } | 1156 } |
| 1065 int operator ~() { | 1157 int operator ~() { |
| 1066 _Bigint result = new _Bigint(); | 1158 return _not()._toValidInt(); |
| 1067 _notTo(result); | |
| 1068 return result._toValidInt(); | |
| 1069 } | 1159 } |
| 1070 | 1160 |
| 1071 int get bitLength { | 1161 int get bitLength { |
| 1072 if (_used == 0) return 0; | 1162 if (_used == 0) return 0; |
| 1073 if (_neg) return (~this).bitLength; | 1163 if (_neg) return (~this).bitLength; |
| 1074 return DIGIT_BITS*(_used - 1) + _nbits(_digits[_used - 1]); | 1164 return DIGIT_BITS*(_used - 1) + _nbits(_digits[_used - 1]); |
| 1075 } | 1165 } |
| 1076 | 1166 |
| 1077 // This method must support smi._toBigint()._shrFromInt(int). | 1167 // This method must support smi._toBigint()._shrFromInt(int). |
| 1078 int _shrFromInt(int other) { | 1168 int _shrFromInt(int other) { |
| 1079 if (_used == 0) return other; // Shift amount is zero. | 1169 if (_used == 0) return other; // Shift amount is zero. |
| 1080 if (_neg) throw "negative shift amount"; // TODO(regis): What exception? | 1170 if (_neg) throw "negative shift amount"; // TODO(regis): What exception? |
| 1081 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 1171 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
| 1082 var shift; | 1172 var shift; |
| 1083 if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) { | 1173 if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) { |
| 1084 if (other < 0) { | 1174 if (other < 0) { |
| 1085 return -1; | 1175 return -1; |
| 1086 } else { | 1176 } else { |
| 1087 return 0; | 1177 return 0; |
| 1088 } | 1178 } |
| 1089 } else { | 1179 } else { |
| 1090 shift = ((_used == 2) ? (_digits[1] << DIGIT_BITS) : 0) + _digits[0]; | 1180 shift = ((_used == 2) ? (_digits[1] << DIGIT_BITS) : 0) + _digits[0]; |
| 1091 } | 1181 } |
| 1092 _Bigint result = new _Bigint(); | 1182 return other._toBigint()._rShift(shift)._toValidInt(); |
| 1093 other._toBigint()._rShiftTo(shift, result); | |
| 1094 return result._toValidInt(); | |
| 1095 } | 1183 } |
| 1096 | 1184 |
| 1097 // This method must support smi._toBigint()._shlFromInt(int). | 1185 // This method must support smi._toBigint()._shlFromInt(int). |
| 1098 // An out of memory exception is thrown if the result cannot be allocated. | 1186 // An out of memory exception is thrown if the result cannot be allocated. |
| 1099 int _shlFromInt(int other) { | 1187 int _shlFromInt(int other) { |
| 1100 if (_used == 0) return other; // Shift amount is zero. | 1188 if (_used == 0) return other; // Shift amount is zero. |
| 1101 if (_neg) throw "negative shift amount"; // TODO(regis): What exception? | 1189 if (_neg) throw "negative shift amount"; // TODO(regis): What exception? |
| 1102 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 1190 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
| 1103 var shift; | 1191 var shift; |
| 1104 if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) { | 1192 if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) { |
| 1105 throw new OutOfMemoryError(); | 1193 throw new OutOfMemoryError(); |
| 1106 } else { | 1194 } else { |
| 1107 shift = ((_used == 2) ? (_digits[1] << DIGIT_BITS) : 0) + _digits[0]; | 1195 shift = ((_used == 2) ? (_digits[1] << DIGIT_BITS) : 0) + _digits[0]; |
| 1108 } | 1196 } |
| 1109 _Bigint result = new _Bigint(); | 1197 return other._toBigint()._lShift(shift)._toValidInt(); |
| 1110 other._toBigint()._lShiftTo(shift, result); | |
| 1111 return result._toValidInt(); | |
| 1112 } | 1198 } |
| 1113 | 1199 |
| 1114 // Overriden operators and methods. | 1200 // Overriden operators and methods. |
| 1115 | 1201 |
| 1116 // The following operators override operators of _IntegerImplementation for | 1202 // The following operators override operators of _IntegerImplementation for |
| 1117 // efficiency, but are not necessary for correctness. They shortcut native | 1203 // efficiency, but are not necessary for correctness. They shortcut native |
| 1118 // calls that would return null because the receiver is _Bigint. | 1204 // calls that would return null because the receiver is _Bigint. |
| 1119 num operator +(num other) { | 1205 num operator +(num other) { |
| 1120 return other._toBigintOrDouble()._addFromInteger(this); | 1206 return other._toBigintOrDouble()._addFromInteger(this); |
| 1121 } | 1207 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1148 } | 1234 } |
| 1149 int operator >>(int other) { | 1235 int operator >>(int other) { |
| 1150 return other._toBigintOrDouble()._shrFromInt(this); | 1236 return other._toBigintOrDouble()._shrFromInt(this); |
| 1151 } | 1237 } |
| 1152 int operator <<(int other) { | 1238 int operator <<(int other) { |
| 1153 return other._toBigintOrDouble()._shlFromInt(this); | 1239 return other._toBigintOrDouble()._shlFromInt(this); |
| 1154 } | 1240 } |
| 1155 // End of operator shortcuts. | 1241 // End of operator shortcuts. |
| 1156 | 1242 |
| 1157 int operator -() { | 1243 int operator -() { |
| 1158 if (_used == 0) { | 1244 return _negate()._toValidInt(); |
| 1159 return this; | |
| 1160 } | |
| 1161 var r = new _Bigint(); | |
| 1162 _copyTo(r); | |
| 1163 r._neg = !_neg; | |
| 1164 return r._toValidInt(); | |
| 1165 } | 1245 } |
| 1166 | 1246 |
| 1167 int get sign { | 1247 int get sign { |
| 1168 return (_used == 0) ? 0 : _neg ? -1 : 1; | 1248 return (_used == 0) ? 0 : _neg ? -1 : 1; |
| 1169 } | 1249 } |
| 1170 | 1250 |
| 1171 bool get isEven => _used == 0 || (_digits[0] & 1) == 0; | 1251 bool get isEven => _used == 0 || (_digits[0] & 1) == 0; |
| 1172 bool get isNegative => _neg; | 1252 bool get isNegative => _neg; |
| 1173 | 1253 |
| 1174 String _toPow2String(int radix) { | 1254 String _toPow2String(int radix) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1210 if (_used == 0) return 0; | 1290 if (_used == 0) return 0; |
| 1211 if (count is! _Smi) { | 1291 if (count is! _Smi) { |
| 1212 _shlFromInt(count); // Throws out of memory exception. | 1292 _shlFromInt(count); // Throws out of memory exception. |
| 1213 } | 1293 } |
| 1214 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 1294 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
| 1215 if (count > 31) return 0; | 1295 if (count > 31) return 0; |
| 1216 return (_digits[0] << count) & mask; | 1296 return (_digits[0] << count) & mask; |
| 1217 } | 1297 } |
| 1218 | 1298 |
| 1219 int _bitAndFromInteger(int other) { | 1299 int _bitAndFromInteger(int other) { |
| 1220 _Bigint result = new _Bigint(); | 1300 return other._toBigint()._and(this)._toValidInt(); |
| 1221 other._toBigint()._andTo(this, result); | |
| 1222 return result._toValidInt(); | |
| 1223 } | 1301 } |
| 1224 int _bitOrFromInteger(int other) { | 1302 int _bitOrFromInteger(int other) { |
| 1225 _Bigint result = new _Bigint(); | 1303 return other._toBigint()._or(this)._toValidInt(); |
| 1226 other._toBigint()._orTo(this, result); | |
| 1227 return result._toValidInt(); | |
| 1228 } | 1304 } |
| 1229 int _bitXorFromInteger(int other) { | 1305 int _bitXorFromInteger(int other) { |
| 1230 _Bigint result = new _Bigint(); | 1306 return other._toBigint()._xor(this)._toValidInt(); |
| 1231 other._toBigint()._xorTo(this, result); | |
| 1232 return result._toValidInt(); | |
| 1233 } | 1307 } |
| 1234 int _addFromInteger(int other) { | 1308 int _addFromInteger(int other) { |
| 1235 _Bigint result = new _Bigint(); | 1309 return other._toBigint()._add(this)._toValidInt(); |
| 1236 other._toBigint()._addTo(this, result); | |
| 1237 return result._toValidInt(); | |
| 1238 } | 1310 } |
| 1239 int _subFromInteger(int other) { | 1311 int _subFromInteger(int other) { |
| 1240 _Bigint result = new _Bigint(); | 1312 return other._toBigint()._sub(this)._toValidInt(); |
| 1241 other._toBigint()._subTo(this, result); | |
| 1242 return result._toValidInt(); | |
| 1243 } | 1313 } |
| 1244 int _mulFromInteger(int other) { | 1314 int _mulFromInteger(int other) { |
| 1245 _Bigint result = new _Bigint(); | 1315 return other._toBigint()._mul(this)._toValidInt(); |
| 1246 other._toBigint()._mulTo(this, result); | |
| 1247 return result._toValidInt(); | |
| 1248 } | 1316 } |
| 1249 int _truncDivFromInteger(int other) { | 1317 int _truncDivFromInteger(int other) { |
| 1250 _Bigint result = new _Bigint(); | 1318 return other._toBigint()._div(this)._toValidInt(); |
| 1251 other._toBigint()._divRemTo(this, result, null); | |
| 1252 return result._toValidInt(); | |
| 1253 } | 1319 } |
| 1254 int _moduloFromInteger(int other) { | 1320 int _moduloFromInteger(int other) { |
| 1255 _Bigint result = new _Bigint(); | 1321 _Bigint result = other._toBigint()._rem(this); |
| 1256 other._toBigint()._divRemTo(this, null, result); | |
| 1257 if (result._neg) { | 1322 if (result._neg) { |
| 1258 if (_neg) { | 1323 if (_neg) { |
| 1259 result._subTo(this, result); | 1324 result = result._sub(this); |
| 1260 } else { | 1325 } else { |
| 1261 result._addTo(this, result); | 1326 result = result._add(this); |
| 1262 } | 1327 } |
| 1263 } | 1328 } |
| 1264 return result._toValidInt(); | 1329 return result._toValidInt(); |
| 1265 } | 1330 } |
| 1266 int _remainderFromInteger(int other) { | 1331 int _remainderFromInteger(int other) { |
| 1267 _Bigint result = new _Bigint(); | 1332 return other._toBigint()._rem(this)._toValidInt(); |
| 1268 other._toBigint()._divRemTo(this, null, result); | |
| 1269 return result._toValidInt(); | |
| 1270 } | 1333 } |
| 1271 bool _greaterThanFromInteger(int other) { | 1334 bool _greaterThanFromInteger(int other) { |
| 1272 return other._toBigint()._compareTo(this) > 0; | 1335 return other._toBigint()._compare(this) > 0; |
| 1273 } | 1336 } |
| 1274 bool _equalToInteger(int other) { | 1337 bool _equalToInteger(int other) { |
| 1275 return other._toBigint()._compareTo(this) == 0; | 1338 return other._toBigint()._compare(this) == 0; |
| 1276 } | 1339 } |
| 1277 | 1340 |
| 1278 // TODO(regis): Make this method private once the plumbing to invoke it from | 1341 // Return pow(this, e) % m, with e >= 0, m > 0. |
| 1279 // dart:math is in place. Move the argument checking to dart:math. | |
| 1280 // Return pow(this, e) % m. | |
| 1281 int modPow(int e, int m) { | 1342 int modPow(int e, int m) { |
| 1282 if (e is! int) throw new ArgumentError(e); | 1343 if (e is! int || e < 0) throw new ArgumentError(e); |
| 1283 if (m is! int) throw new ArgumentError(m); | 1344 if (m is! int || m <= 0) throw new ArgumentError(m); |
| 1284 int i = e.bitLength; | 1345 final m_used = m._used; |
| 1285 if (i <= 0) return 1; | 1346 final m_used2p1 = 2*m_used + 1; |
| 1347 final e_bitlen = e.bitLength; | |
| 1348 if (e_bitlen <= 0) return 1; | |
| 1286 if ((e is! _Bigint) || m.isEven) { | 1349 if ((e is! _Bigint) || m.isEven) { |
| 1287 _Reduction z = (i < 8 || m.isEven) ? new _Classic(m) : new _Montgomery(m); | 1350 _Reduction z = (e_bitlen < 8 || m.isEven) ? |
| 1351 new _Classic(m) : new _Montgomery(m); | |
| 1288 // TODO(regis): Should we use Barrett reduction for an even modulus? | 1352 // TODO(regis): Should we use Barrett reduction for an even modulus? |
| 1289 var r = new _Bigint(); | 1353 var m_used = m._used; |
| 1290 var r2 = new _Bigint(); | 1354 var r_digits = new Uint32List(m_used2p1 + 1); // +1 for leading zero. |
| 1291 var g = z._convert(this); | 1355 var r2_digits = new Uint32List(m_used2p1 + 1); // +1 for leading zero. |
| 1292 i--; | 1356 var g_digits = new Uint32List(m_used + 1); // +1 for leading zero. |
| 1293 g._copyTo(r); | 1357 var g_used = z._convert(this, g_digits); |
| 1358 // Initialize r with g. | |
| 1359 var j = g_used + 1; // Copy leading zero. | |
| 1360 while (--j >= 0) { | |
| 1361 r_digits[j] = g_digits[j]; | |
| 1362 } | |
| 1363 var r_used = g_used; | |
| 1364 var r2_used; | |
| 1365 var i = e_bitlen - 1; | |
| 1294 while (--i >= 0) { | 1366 while (--i >= 0) { |
| 1295 z._sqrTo(r, r2); | 1367 r2_used = z._sqr(r_digits, r_used, r2_digits); |
| 1296 if ((e & (1 << i)) != 0) { | 1368 if ((e & (1 << i)) != 0) { |
| 1297 z._mulTo(r2, g, r); | 1369 r_used = z._mul(r2_digits, r2_used, g_digits, g_used, r_digits); |
| 1298 } else { | 1370 } else { |
| 1299 var t = r; | 1371 var t_digits = r_digits; |
| 1300 r = r2; | 1372 var t_used = r_used; |
| 1301 r2 = t; | 1373 r_digits = r2_digits; |
| 1374 r_used = r2_used; | |
| 1375 r2_digits = t_digits; | |
| 1376 r2_used = t_used; | |
| 1302 } | 1377 } |
| 1303 } | 1378 } |
| 1304 return z._revert(r)._toValidInt(); | 1379 return z._revert(r_digits, r_used)._toValidInt(); |
| 1305 } | 1380 } |
| 1306 var k; | 1381 var k; |
| 1307 // TODO(regis): Are these values of k really optimal for our implementation? | 1382 if (e_bitlen < 18) k = 1; |
| 1308 if (i < 18) k = 1; | 1383 else if (e_bitlen < 48) k = 3; |
| 1309 else if (i < 48) k = 3; | 1384 else if (e_bitlen < 144) k = 4; |
| 1310 else if (i < 144) k = 4; | 1385 else if (e_bitlen < 768) k = 5; |
| 1311 else if (i < 768) k = 5; | |
| 1312 else k = 6; | 1386 else k = 6; |
| 1313 _Reduction z = new _Montgomery(m); | 1387 _Reduction z = new _Montgomery(m); |
| 1314 var n = 3; | 1388 var n = 3; |
| 1315 var k1 = k - 1; | 1389 final k1 = k - 1; |
| 1316 var km = (1 << k) - 1; | 1390 final km = (1 << k) - 1; |
| 1317 List g = new List(km + 1); | 1391 List g_digits = new List(km + 1); |
| 1318 g[1] = z._convert(this); | 1392 List g_used = new List(km + 1); |
| 1393 g_digits[1] = new Uint32List(m_used + 1); // +1 for leading zero. | |
| 1394 g_used[1] = z._convert(this, g_digits[1]); | |
| 1319 if (k > 1) { | 1395 if (k > 1) { |
| 1320 var g2 = new _Bigint(); | 1396 var g2_digits = new Uint32List(m_used2p1 + 1); // +1 for leading zero. |
| 1321 z._sqrTo(g[1], g2); | 1397 var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits); |
| 1322 while (n <= km) { | 1398 while (n <= km) { |
| 1323 g[n] = new _Bigint(); | 1399 g_digits[n] = new Uint32List(m_used2p1 + 1); // +1 for leading zero. |
| 1324 z._mulTo(g2, g[n - 2], g[n]); | 1400 g_used[n] = z._mul(g2_digits, g2_used, |
| 1401 g_digits[n - 2], g_used[n - 2], | |
| 1402 g_digits[n]); | |
| 1325 n += 2; | 1403 n += 2; |
| 1326 } | 1404 } |
| 1327 } | 1405 } |
| 1328 var j = e._used - 1; | |
| 1329 var w; | 1406 var w; |
| 1330 var is1 = true; | 1407 var is1 = true; |
| 1331 var r = new _Bigint._fromInt(1); | 1408 var r_digits = ONE._digits; |
| 1332 var r2 = new _Bigint(); | 1409 var r_used = ONE._used; |
| 1333 var t; | 1410 var r2_digits = new Uint32List(m_used2p1 + 1); // +1 for leading zero. |
| 1411 var r2_used; | |
| 1334 var e_digits = e._digits; | 1412 var e_digits = e._digits; |
| 1335 i = _nbits(e_digits[j]) - 1; | 1413 var j = e._used - 1; |
| 1414 var i = _nbits(e_digits[j]) - 1; | |
| 1336 while (j >= 0) { | 1415 while (j >= 0) { |
| 1337 if (i >= k1) { | 1416 if (i >= k1) { |
| 1338 w = (e_digits[j] >> (i - k1)) & km; | 1417 w = (e_digits[j] >> (i - k1)) & km; |
| 1339 } else { | 1418 } else { |
| 1340 w = (e_digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i); | 1419 w = (e_digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i); |
| 1341 if (j > 0) { | 1420 if (j > 0) { |
| 1342 w |= e_digits[j - 1] >> (DIGIT_BITS + i - k1); | 1421 w |= e_digits[j - 1] >> (DIGIT_BITS + i - k1); |
| 1343 } | 1422 } |
| 1344 } | 1423 } |
| 1345 n = k; | 1424 n = k; |
| 1346 while ((w & 1) == 0) { | 1425 while ((w & 1) == 0) { |
| 1347 w >>= 1; | 1426 w >>= 1; |
| 1348 --n; | 1427 --n; |
| 1349 } | 1428 } |
| 1350 if ((i -= n) < 0) { | 1429 if ((i -= n) < 0) { |
| 1351 i += DIGIT_BITS; | 1430 i += DIGIT_BITS; |
| 1352 --j; | 1431 --j; |
| 1353 } | 1432 } |
| 1354 if (is1) { // r == 1, don't bother squaring or multiplying it. | 1433 if (is1) { // r == 1, don't bother squaring or multiplying it. |
| 1355 g[w]._copyTo(r); | 1434 r_digits = new Uint32List(m_used2p1 + 1); // +1 for leading zero. |
| 1435 r_used = g_used[w]; | |
| 1436 var gw_digits = g_digits[w]; | |
| 1437 var ri = r_used + 1; // Copy leading zero. | |
| 1438 while (--ri >= 0) { | |
| 1439 r_digits[ri] = gw_digits[ri]; | |
| 1440 } | |
| 1356 is1 = false; | 1441 is1 = false; |
| 1357 } | 1442 } |
| 1358 else { | 1443 else { |
| 1359 while (n > 1) { | 1444 while (n > 1) { |
| 1360 z._sqrTo(r, r2); | 1445 r2_used = z._sqr(r_digits, r_used, r2_digits); |
| 1361 z._sqrTo(r2, r); | 1446 r_used = z._sqr(r2_digits, r2_used, r_digits); |
| 1362 n -= 2; | 1447 n -= 2; |
| 1363 } | 1448 } |
| 1364 if (n > 0) { | 1449 if (n > 0) { |
| 1365 z._sqrTo(r, r2); | 1450 r2_used = z._sqr(r_digits, r_used, r2_digits); |
| 1366 } else { | 1451 } else { |
| 1367 t = r; | 1452 var t_digits = r_digits; |
| 1368 r = r2; | 1453 var t_used = r_used; |
| 1369 r2 = t; | 1454 r_digits = r2_digits; |
| 1455 r_used = r2_used; | |
| 1456 r2_digits = t_digits; | |
| 1457 r2_used = t_used; | |
| 1370 } | 1458 } |
| 1371 z._mulTo(r2,g[w], r); | 1459 r_used = z._mul(r2_digits, r2_used, g_digits[w], g_used[w], r_digits); |
| 1372 } | 1460 } |
| 1373 | |
| 1374 while (j >= 0 && (e_digits[j] & (1 << i)) == 0) { | 1461 while (j >= 0 && (e_digits[j] & (1 << i)) == 0) { |
| 1375 z._sqrTo(r, r2); | 1462 r2_used = z._sqr(r_digits, r_used, r2_digits); |
| 1376 t = r; | 1463 var t_digits = r_digits; |
| 1377 r = r2; | 1464 var t_used = r_used; |
| 1378 r2 = t; | 1465 r_digits = r2_digits; |
| 1466 r_used = r2_used; | |
| 1467 r2_digits = t_digits; | |
| 1468 r2_used = t_used; | |
| 1379 if (--i < 0) { | 1469 if (--i < 0) { |
| 1380 i = DIGIT_BITS - 1; | 1470 i = DIGIT_BITS - 1; |
| 1381 --j; | 1471 --j; |
| 1382 } | 1472 } |
| 1383 } | 1473 } |
| 1384 } | 1474 } |
| 1385 return z._revert(r)._toValidInt(); | 1475 assert(!is1); |
| 1476 return z._revert(r_digits, r_used)._toValidInt(); | |
| 1386 } | 1477 } |
| 1387 } | 1478 } |
| 1388 | 1479 |
| 1389 // Interface for modular reduction. | 1480 // Interface for modular reduction. |
| 1390 class _Reduction { | 1481 class _Reduction { |
| 1391 _Bigint _convert(_Bigint x); | 1482 // Return the number of digits used by r_digits. |
| 1392 _Bigint _revert(_Bigint x); | 1483 int _convert(_Bigint x, Uint32List r_digits); |
| 1393 void _mulTo(_Bigint x, _Bigint y, _Bigint r); | 1484 int _mul(Uint32List x_digits, int x_used, |
| 1394 void _sqrTo(_Bigint x, _Bigint r); | 1485 Uint32List y_digits, int y_used, Uint32List r_digits); |
| 1486 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits); | |
| 1487 | |
| 1488 // Return x reverted to _Bigint. | |
| 1489 _Bigint _revert(Uint32List x_digits, int x_used); | |
| 1395 } | 1490 } |
| 1396 | 1491 |
| 1397 // Montgomery reduction on _Bigint. | 1492 // Montgomery reduction on _Bigint. |
| 1398 class _Montgomery implements _Reduction { | 1493 class _Montgomery implements _Reduction { |
| 1399 _Bigint _m; | 1494 _Bigint _m; // Modulus. |
| 1400 int _mused2; | 1495 int _mused2p1; |
| 1401 Uint32List _args; | 1496 Uint32List _args; |
| 1402 int _digits_per_step; // Number of digits processed in one step. 1 or 2. | 1497 int _digits_per_step; // Number of digits processed in one step. 1 or 2. |
| 1403 static const int _X = 0; // Index of x. | 1498 static const int _X = 0; // Index of x. |
| 1404 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only). | 1499 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only). |
| 1405 static const int _RHO = 2; // Index of rho. | 1500 static const int _RHO = 2; // Index of rho. |
| 1406 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only). | 1501 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only). |
| 1407 static const int _MU = 4; // Index of mu. | 1502 static const int _MU = 4; // Index of mu. |
| 1408 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only). | 1503 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only). |
| 1409 | 1504 |
| 1410 _Montgomery(m) { | 1505 _Montgomery(m) { |
| 1411 _m = m._toBigint(); | 1506 _m = m._toBigint(); |
| 1412 _mused2 = 2*_m._used; | 1507 _mused2p1 = 2*_m._used + 1; |
| 1413 _args = new Uint32List(6); | 1508 _args = new Uint32List(6); |
| 1414 // Determine if we can process digit pairs by calling an intrinsic. | 1509 // Determine if we can process digit pairs by calling an intrinsic. |
| 1415 _digits_per_step = _mulMod(_args, _args, 0); | 1510 _digits_per_step = _mulMod(_args, _args, 0); |
| 1416 _args[_X] = _m._digits[0]; | 1511 _args[_X] = _m._digits[0]; |
| 1417 if (_digits_per_step == 1) { | 1512 if (_digits_per_step == 1) { |
| 1418 _invDigit(_args); | 1513 _invDigit(_args); |
| 1419 } else { | 1514 } else { |
| 1420 assert(_digits_per_step == 2); | 1515 assert(_digits_per_step == 2); |
| 1421 _args[_X_HI] = _m._digits[1]; | 1516 _args[_X_HI] = _m._digits[1]; |
| 1422 _invDigitPair(_args); | 1517 _invDigitPair(_args); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1441 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 | 1536 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 |
| 1442 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 | 1537 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 |
| 1443 // Last step - calculate inverse mod DIGIT_BASE directly; | 1538 // Last step - calculate inverse mod DIGIT_BASE directly; |
| 1444 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. | 1539 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. |
| 1445 y = (y*(2 - x*y % _Bigint.DIGIT_BASE)) % _Bigint.DIGIT_BASE; | 1540 y = (y*(2 - x*y % _Bigint.DIGIT_BASE)) % _Bigint.DIGIT_BASE; |
| 1446 // y == 1/x mod DIGIT_BASE | 1541 // y == 1/x mod DIGIT_BASE |
| 1447 y = -y; // We really want the negative inverse. | 1542 y = -y; // We really want the negative inverse. |
| 1448 args[_RHO] = y & _Bigint.DIGIT_MASK; | 1543 args[_RHO] = y & _Bigint.DIGIT_MASK; |
| 1449 } | 1544 } |
| 1450 | 1545 |
| 1451 | |
| 1452 // Calculates -1/x % DIGIT_BASE^2, x is a pair of 32-bit digits. | 1546 // Calculates -1/x % DIGIT_BASE^2, x is a pair of 32-bit digits. |
| 1453 // Operation: | 1547 // Operation: |
| 1454 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod DIGIT_BASE^2. | 1548 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod DIGIT_BASE^2. |
| 1455 static void _invDigitPair(Uint32List args) { | 1549 static void _invDigitPair(Uint32List args) { |
| 1456 var xl = args[_X]; // Lower 32-bit digit of x. | 1550 var xl = args[_X]; // Lower 32-bit digit of x. |
| 1457 var y = xl & 3; // y == 1/x mod 2^2 | 1551 var y = xl & 3; // y == 1/x mod 2^2 |
| 1458 y = (y*(2 - (xl & 0xf)*y)) & 0xf; // y == 1/x mod 2^4 | 1552 y = (y*(2 - (xl & 0xf)*y)) & 0xf; // y == 1/x mod 2^4 |
| 1459 y = (y*(2 - (xl & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 | 1553 y = (y*(2 - (xl & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 |
| 1460 y = (y*(2 - (((xl & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 | 1554 y = (y*(2 - (((xl & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 |
| 1461 y = (y*(2 - ((xl*y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32 | 1555 y = (y*(2 - ((xl*y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32 |
| 1462 var x = (args[_X_HI] << _Bigint.DIGIT_BITS) | xl; | 1556 var x = (args[_X_HI] << _Bigint.DIGIT_BITS) | xl; |
| 1463 y = (y*(2 - ((x*y) & 0xffffffffffffffff))) & 0xffffffffffffffff; | 1557 y = (y*(2 - ((x*y) & 0xffffffffffffffff))) & 0xffffffffffffffff; |
| 1464 // y == 1/x mod DIGIT_BASE^2 | 1558 // y == 1/x mod DIGIT_BASE^2 |
| 1465 y = -y; // We really want the negative inverse. | 1559 y = -y; // We really want the negative inverse. |
| 1466 args[_RHO] = y & _Bigint.DIGIT_MASK; | 1560 args[_RHO] = y & _Bigint.DIGIT_MASK; |
| 1467 args[_RHO_HI] = (y >> _Bigint.DIGIT_BITS) & _Bigint.DIGIT_MASK; | 1561 args[_RHO_HI] = (y >> _Bigint.DIGIT_BITS) & _Bigint.DIGIT_MASK; |
| 1468 } | 1562 } |
| 1469 | 1563 |
| 1470 | |
| 1471 // Operation: | 1564 // Operation: |
| 1472 // args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE. | 1565 // args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE. |
| 1473 // return 1. | 1566 // return 1. |
| 1474 // Note: intrinsics on 64-bit platform may process a digit pair: | 1567 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices: |
| 1475 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod DIGIT_BASE^2. | 1568 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod DIGIT_BASE^2. |
| 1476 // return 2. | 1569 // return 2. |
| 1477 static int _mulMod(Uint32List args, Uint32List digits, int i) { | 1570 static int _mulMod(Uint32List args, Uint32List digits, int i) { |
| 1571 // Verify that digit pairs are accessible for 64-bit processing. | |
| 1572 assert(digits.length > (i | 1)); | |
| 1478 const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; | 1573 const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; |
| 1479 var rhol = args[_RHO] & _Bigint.DIGIT2_MASK; | 1574 var rhol = args[_RHO] & _Bigint.DIGIT2_MASK; |
| 1480 var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS; | 1575 var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS; |
| 1481 var dh = digits[i] >> _Bigint.DIGIT2_BITS; | 1576 var dh = digits[i] >> _Bigint.DIGIT2_BITS; |
| 1482 var dl = digits[i] & _Bigint.DIGIT2_MASK; | 1577 var dl = digits[i] & _Bigint.DIGIT2_MASK; |
| 1483 args[_MU] = | 1578 args[_MU] = |
| 1484 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint.DIGIT2_BITS)) | 1579 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint.DIGIT2_BITS)) |
| 1485 & _Bigint.DIGIT_MASK; | 1580 & _Bigint.DIGIT_MASK; |
| 1486 return 1; | 1581 return 1; |
| 1487 } | 1582 } |
| 1488 | 1583 |
| 1489 // Return x*R mod _m | 1584 // r = x*R mod _m. |
| 1490 _Bigint _convert(_Bigint x) { | 1585 // Return r_used. |
| 1491 var r = new _Bigint(); | 1586 int _convert(_Bigint x, Uint32List r_digits) { |
| 1492 x.abs()._dlShiftTo(_m._used, r); | 1587 var r = x._abs()._dlShift(_m._used)._rem(_m); |
| 1493 r._divRemTo(_m, null, r); | |
| 1494 if (x._neg && !r._neg && r._used > 0) { | 1588 if (x._neg && !r._neg && r._used > 0) { |
| 1495 _m._subTo(r, r); | 1589 r = _m._sub(r); |
| 1496 } | 1590 } |
| 1497 return r; | 1591 var used = r._used; |
| 1592 var digits = r._digits; | |
| 1593 var i = used + 1; // Copy leading zero. | |
| 1594 while (--i >= 0) { | |
| 1595 r_digits[i] = digits[i]; | |
| 1596 } | |
| 1597 return used; | |
| 1498 } | 1598 } |
| 1499 | 1599 |
| 1500 // Return x/R mod _m | 1600 _Bigint _revert(Uint32List x_digits, int x_used) { |
| 1501 _Bigint _revert(_Bigint x) { | 1601 var r_digits = new Uint32List(_mused2p1 + 1); // +1 for leading zero. |
| 1502 var r = new _Bigint(); | 1602 var i = x_used + 1; // Copy leading zero. |
| 1503 x._copyTo(r); | 1603 while (--i >= 0) { |
| 1504 _reduce(r); | 1604 r_digits[i] = x_digits[i]; |
| 1505 return r; | 1605 } |
| 1606 var r_used = _reduce(r_digits, x_used); | |
| 1607 return new _Bigint(false, r_used, r_digits); | |
| 1506 } | 1608 } |
| 1507 | 1609 |
| 1508 // x = x/R mod _m | 1610 // x = x/R mod _m. |
| 1509 void _reduce(_Bigint x) { | 1611 // Return x_used. |
| 1510 x._ensureLength(_mused2 + 1); | 1612 int _reduce(Uint32List x_digits, int x_used) { |
| 1511 var x_digits = x._digits; | 1613 while (x_used < _mused2p1) { // Pad x so _mulAdd has enough room later. |
| 1512 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. | 1614 x_digits[x_used++] = 0; |
| 1513 x_digits[x._used++] = 0; | |
| 1514 } | 1615 } |
| 1515 x_digits[x._used] = 0; // Set leading zero for 64-bit processing. | 1616 x_digits[x_used] = 0; // Set leading zero for 64-bit processing. |
| 1516 var m_used = _m._used; | 1617 var m_used = _m._used; |
| 1517 var m_digits = _m._digits; | 1618 var m_digits = _m._digits; |
| 1518 var i = 0; | 1619 var i = 0; |
| 1519 while (i < m_used) { | 1620 while (i < m_used) { |
| 1520 var d = _mulMod(_args, x_digits, i); | 1621 var d = _mulMod(_args, x_digits, i); |
| 1521 assert(d == _digits_per_step); | 1622 assert(d == _digits_per_step); |
| 1522 d = _Bigint._mulAdd(_args, _MU, m_digits, 0, x_digits, i, m_used); | 1623 d = _Bigint._mulAdd(_args, _MU, m_digits, 0, x_digits, i, m_used); |
| 1523 assert(d == _digits_per_step); | 1624 assert(d == _digits_per_step); |
| 1524 i += d; | 1625 i += d; |
| 1525 } | 1626 } |
| 1526 x._clamp(); | 1627 // Clamp x. |
| 1527 x._drShiftTo(m_used, x); | 1628 while (x_used > 0 && x_digits[x_used - 1] == 0) { |
| 1528 if (x._compareTo(_m) >= 0) { | 1629 --x_used; |
| 1529 x._subTo(_m, x); | |
| 1530 } | 1630 } |
| 1631 x_used = _Bigint._drShiftDigits(x_digits, x_used, m_used, x_digits); | |
| 1632 if (_Bigint._compareDigits(x_digits, x_used, m_digits, m_used) >= 0) { | |
| 1633 _Bigint._absSub(x_digits, x_used, m_digits, m_used, x_digits); | |
| 1634 } | |
| 1635 // Clamp x. | |
| 1636 while (x_used > 0 && x_digits[x_used - 1] == 0) { | |
| 1637 --x_used; | |
| 1638 } | |
| 1639 return x_used; | |
| 1531 } | 1640 } |
| 1532 | 1641 |
| 1533 // r = x^2/R mod _m ; x != r | 1642 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) { |
| 1534 void _sqrTo(_Bigint x, _Bigint r) { | 1643 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits); |
| 1535 x._sqrTo(r); | 1644 return _reduce(r_digits, r_used); |
| 1536 _reduce(r); | |
| 1537 } | 1645 } |
| 1538 | 1646 |
| 1539 // r = x*y/R mod _m ; x, y != r | 1647 int _mul(Uint32List x_digits, int x_used, |
| 1540 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { | 1648 Uint32List y_digits, int y_used, |
| 1541 x._mulTo(y, r); | 1649 Uint32List r_digits) { |
| 1542 _reduce(r); | 1650 var r_used = _Bigint._mulDigits(x_digits, x_used, |
| 1651 y_digits, y_used, | |
| 1652 r_digits); | |
| 1653 return _reduce(r_digits, r_used); | |
| 1543 } | 1654 } |
| 1544 } | 1655 } |
| 1545 | 1656 |
| 1546 // Modular reduction using "classic" algorithm. | 1657 // Modular reduction using "classic" algorithm. |
| 1547 class _Classic implements _Reduction { | 1658 class _Classic implements _Reduction { |
| 1548 _Bigint _m; | 1659 _Bigint _m; // Modulus. |
| 1660 _Bigint _norm_m; // Normalized _m. | |
| 1661 Uint32List _neg_norm_m_digits; // Negated _norm_m digits. | |
| 1662 int _m_nsh; // Normalization shift amount. | |
| 1663 Uint32List _mt_qd; // Top _norm_m digit(s) and place holder for | |
| 1664 // estimated quotient digit(s). | |
| 1665 Uint32List _t_digits; // Temporary digits used during reduction. | |
| 1549 | 1666 |
| 1550 _Classic(int m) { | 1667 _Classic(int m) { |
| 1551 _m = m._toBigint(); | 1668 _m = m._toBigint(); |
| 1669 // Preprocess arguments to _remDigits. | |
| 1670 var nsh = _Bigint.DIGIT_BITS - _Bigint._nbits(_m._digits[_m._used - 1]); | |
| 1671 // For 64-bit processing, make sure _norm_m_digits has an even number of | |
| 1672 // digits. | |
| 1673 if (_m._used.isOdd) { | |
| 1674 nsh += _Bigint.DIGIT_BITS; | |
| 1675 } | |
| 1676 _m_nsh = nsh; | |
| 1677 _norm_m = _m._lShift(nsh); | |
| 1678 var nm_used = _norm_m._used; | |
| 1679 assert(nm_used.isEven); | |
| 1680 _mt_qd = new Uint32List(4); | |
| 1681 _mt_qd[_Bigint._YT_LO] = _norm_m._digits[nm_used - 2]; | |
| 1682 _mt_qd[_Bigint._YT] = _norm_m._digits[nm_used - 1]; | |
| 1683 // Negate _norm_m so we can use _mulAdd instead of unimplemented _mulSub. | |
| 1684 var neg_norm_m = _Bigint.ONE._dlShift(nm_used)._sub(_norm_m); | |
| 1685 if (neg_norm_m._used < nm_used) { | |
| 1686 _neg_norm_m_digits = | |
| 1687 _Bigint._cloneDigits(neg_norm_m._digits, 0, nm_used, nm_used); | |
| 1688 } else { | |
| 1689 _neg_norm_m_digits = neg_norm_m._digits; | |
| 1690 } | |
| 1691 // _neg_norm_m_digits is read-only and has nm_used digits (possibly | |
| 1692 // including several leading zeros) plus a leading zero for 64-bit | |
| 1693 // processing. | |
| 1694 _t_digits = new Uint32List(2*nm_used + 1); // +1 for leading zero. | |
| 1552 } | 1695 } |
| 1553 | 1696 |
| 1554 _Bigint _convert(_Bigint x) { | 1697 int _convert(_Bigint x, Uint32List r_digits) { |
| 1555 if (x._neg || x._compareTo(_m) >= 0) { | 1698 var digits; |
| 1556 var r = new _Bigint(); | 1699 var used; |
| 1557 x._divRemTo(_m, null, r); | 1700 if (x._neg || x._compare(_m) >= 0) { |
| 1701 var r = x.rem(_m); | |
| 1558 if (x._neg && !r._neg && r._used > 0) { | 1702 if (x._neg && !r._neg && r._used > 0) { |
| 1559 _m._subTo(r, r); | 1703 r = _m._sub(r); |
| 1560 } | 1704 } |
| 1561 return r; | 1705 assert(!r._neg); |
| 1706 used = r._used; | |
| 1707 digits = r._digits; | |
| 1708 } else { | |
| 1709 used = x._used; | |
| 1710 digits = x._digits; | |
| 1562 } | 1711 } |
| 1563 return x; | 1712 var i = used + 1; // Copy leading zero. |
| 1713 while (--i >= 0) { | |
| 1714 r_digits[i] = digits[i]; | |
| 1715 } | |
| 1716 return used; | |
| 1564 } | 1717 } |
| 1565 | 1718 |
| 1566 _Bigint _revert(_Bigint x) { | 1719 _Bigint _revert(Uint32List x_digits, int x_used) { |
| 1567 return x; | 1720 return new _Bigint(false, x_used, x_digits); |
| 1568 } | 1721 } |
| 1569 | 1722 |
| 1570 void _reduce(_Bigint x) { | 1723 int _reduce(Uint32List x_digits, int x_used) { |
| 1571 x._divRemTo(_m, null, x); | 1724 // The function _remDigits(...) is optimized for reduction and equivalent to |
| 1725 // calling _convert(_revert(x_digits, x_used)._rem(_m), x_digits); | |
| 1726 return _Bigint._remDigits(x_digits, x_used, | |
| 1727 _norm_m._digits, _norm_m._used, | |
| 1728 _neg_norm_m_digits, | |
| 1729 _m_nsh, | |
| 1730 _mt_qd, | |
| 1731 _t_digits, | |
| 1732 x_digits); | |
| 1572 } | 1733 } |
| 1573 | 1734 |
| 1574 void _sqrTo(_Bigint x, _Bigint r) { | 1735 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) { |
| 1575 x._sqrTo(r); | 1736 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits); |
| 1576 _reduce(r); | 1737 return _reduce(r_digits, r_used); |
| 1577 } | 1738 } |
| 1578 | 1739 |
| 1579 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { | 1740 int _mul(Uint32List x_digits, int x_used, |
| 1580 x._mulTo(y, r); | 1741 Uint32List y_digits, int y_used, |
| 1581 _reduce(r); | 1742 Uint32List r_digits) { |
| 1743 var r_used = _Bigint._mulDigits(x_digits, x_used, | |
| 1744 y_digits, y_used, | |
| 1745 r_digits); | |
| 1746 return _reduce(r_digits, r_used); | |
| 1582 } | 1747 } |
| 1583 } | 1748 } |
| OLD | NEW |