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 import 'dart:typed_data' show Uint32List; | 5 import 'dart:typed_data' show Uint32List; |
6 | 6 |
7 // Copyright 2009 The Go Authors. All rights reserved. | 7 // Copyright 2009 The Go Authors. All rights reserved. |
8 // Use of this source code is governed by a BSD-style | 8 // Use of this source code is governed by a BSD-style |
9 // license that can be found in the LICENSE file. | 9 // license that can be found in the LICENSE file. |
10 | 10 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 } | 112 } |
113 var digits = new Uint32List(2); | 113 var digits = new Uint32List(2); |
114 digits[0] = l; | 114 digits[0] = l; |
115 digits[1] = h; | 115 digits[1] = h; |
116 return new _Bigint(neg, 2, digits); | 116 return new _Bigint(neg, 2, digits); |
117 } | 117 } |
118 | 118 |
119 // Allocate an array of the given length (+1 for at least one leading zero | 119 // Allocate an array of the given length (+1 for at least one leading zero |
120 // digit if odd) and copy digits[from..to-1] starting at index 0, followed by | 120 // digit if odd) and copy digits[from..to-1] starting at index 0, followed by |
121 // leading zero digits. | 121 // leading zero digits. |
122 static Uint32List _cloneDigits( | 122 static Uint32List _cloneDigits(Uint32List digits, int from, int to, |
123 Uint32List digits, int from, int to, int length) { | 123 int length) { |
124 length += length & 1; // Even number of digits. | 124 length += length & 1; // Even number of digits. |
125 var r_digits = new Uint32List(length); | 125 var r_digits = new Uint32List(length); |
126 var n = to - from; | 126 var n = to - from; |
127 for (var i = 0; i < n; i++) { | 127 for (var i = 0; i < n; i++) { |
128 r_digits[i] = digits[from + i]; | 128 r_digits[i] = digits[from + i]; |
129 } | 129 } |
130 return r_digits; | 130 return r_digits; |
131 } | 131 } |
132 | 132 |
133 // Return most compact integer (i.e. possibly Smi or Mint). | 133 // Return most compact integer (i.e. possibly Smi or Mint). |
134 int _toValidInt() { | 134 int _toValidInt() { |
135 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 135 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
136 var used = _used; | 136 var used = _used; |
137 if (used == 0) return 0; | 137 if (used == 0) return 0; |
138 var digits = _digits; | 138 var digits = _digits; |
139 if (used == 1) return _neg ? -digits[0] : digits[0]; | 139 if (used == 1) return _neg ? -digits[0] : digits[0]; |
140 if (used > 2) return this; | 140 if (used > 2) return this; |
141 if (_neg) { | 141 if (_neg) { |
142 if (digits[1] > 0x80000000) return this; | 142 if (digits[1] > 0x80000000) return this; |
143 if (digits[1] == 0x80000000) { | 143 if (digits[1] == 0x80000000) { |
144 if (digits[0] > 0) return this; | 144 if (digits[0] > 0) return this; |
145 return _MIN_INT64; | 145 return _MIN_INT64; |
(...skipping 21 matching lines...) Expand all Loading... |
167 var neg = _neg; | 167 var neg = _neg; |
168 if (!neg) { | 168 if (!neg) { |
169 return this; | 169 return this; |
170 } | 170 } |
171 return new _Bigint(!neg, _used, _digits); | 171 return new _Bigint(!neg, _used, _digits); |
172 } | 172 } |
173 | 173 |
174 // Return the bit length of digit x. | 174 // Return the bit length of digit x. |
175 static int _nbits(int x) { | 175 static int _nbits(int x) { |
176 var r = 1, t; | 176 var r = 1, t; |
177 if ((t = x >> 16) != 0) { | 177 if ((t = x >> 16) != 0) { x = t; r += 16; } |
178 x = t; | 178 if ((t = x >> 8) != 0) { x = t; r += 8; } |
179 r += 16; | 179 if ((t = x >> 4) != 0) { x = t; r += 4; } |
180 } | 180 if ((t = x >> 2) != 0) { x = t; r += 2; } |
181 if ((t = x >> 8) != 0) { | 181 if ((x >> 1) != 0) { r += 1; } |
182 x = t; | |
183 r += 8; | |
184 } | |
185 if ((t = x >> 4) != 0) { | |
186 x = t; | |
187 r += 4; | |
188 } | |
189 if ((t = x >> 2) != 0) { | |
190 x = t; | |
191 r += 2; | |
192 } | |
193 if ((x >> 1) != 0) { | |
194 r += 1; | |
195 } | |
196 return r; | 182 return r; |
197 } | 183 } |
198 | 184 |
199 // Return this << n*_DIGIT_BITS. | 185 // Return this << n*_DIGIT_BITS. |
200 _Bigint _dlShift(int n) { | 186 _Bigint _dlShift(int n) { |
201 final used = _used; | 187 final used = _used; |
202 if (used == 0) { | 188 if (used == 0) { |
203 return _ZERO; | 189 return _ZERO; |
204 } | 190 } |
205 final r_used = used + n; | 191 final r_used = used + n; |
206 final digits = _digits; | 192 final digits = _digits; |
207 final r_digits = new Uint32List(r_used + (r_used & 1)); | 193 final r_digits = new Uint32List(r_used + (r_used & 1)); |
208 var i = used; | 194 var i = used; |
209 while (--i >= 0) { | 195 while (--i >= 0) { |
210 r_digits[i + n] = digits[i]; | 196 r_digits[i + n] = digits[i]; |
211 } | 197 } |
212 return new _Bigint(_neg, r_used, r_digits); | 198 return new _Bigint(_neg, r_used, r_digits); |
213 } | 199 } |
214 | 200 |
215 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*_DIGIT_BITS. | 201 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*_DIGIT_BITS. |
216 // Return r_used. | 202 // Return r_used. |
217 static int _dlShiftDigits( | 203 static int _dlShiftDigits(Uint32List x_digits, int x_used, int n, |
218 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { | 204 Uint32List r_digits) { |
219 if (x_used == 0) { | 205 if (x_used == 0) { |
220 return 0; | 206 return 0; |
221 } | 207 } |
222 if (n == 0 && identical(r_digits, x_digits)) { | 208 if (n == 0 && identical(r_digits, x_digits)) { |
223 return x_used; | 209 return x_used; |
224 } | 210 } |
225 final r_used = x_used + n; | 211 final r_used = x_used + n; |
226 assert(r_digits.length >= r_used + (r_used & 1)); | 212 assert(r_digits.length >= r_used + (r_used & 1)); |
227 var i = x_used; | 213 var i = x_used; |
228 while (--i >= 0) { | 214 while (--i >= 0) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 if (digits[i] != 0) { | 246 if (digits[i] != 0) { |
261 return r._sub(_ONE); | 247 return r._sub(_ONE); |
262 } | 248 } |
263 } | 249 } |
264 } | 250 } |
265 return r; | 251 return r; |
266 } | 252 } |
267 | 253 |
268 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n*_DIGIT_BITS. | 254 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n*_DIGIT_BITS. |
269 // Return r_used. | 255 // Return r_used. |
270 static int _drShiftDigits( | 256 static int _drShiftDigits(Uint32List x_digits, int x_used, int n, |
271 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { | 257 Uint32List r_digits) { |
272 final r_used = x_used - n; | 258 final r_used = x_used - n; |
273 if (r_used <= 0) { | 259 if (r_used <= 0) { |
274 return 0; | 260 return 0; |
275 } | 261 } |
276 assert(r_digits.length >= r_used + (r_used & 1)); | 262 assert(r_digits.length >= r_used + (r_used & 1)); |
277 for (var i = n; i < x_used; i++) { | 263 for (var i = n; i < x_used; i++) { |
278 r_digits[i - n] = x_digits[i]; | 264 r_digits[i - n] = x_digits[i]; |
279 } | 265 } |
280 if (r_used.isOdd) { | 266 if (r_used.isOdd) { |
281 r_digits[r_used] = 0; | 267 r_digits[r_used] = 0; |
282 } | 268 } |
283 return r_used; | 269 return r_used; |
284 } | 270 } |
285 | 271 |
286 // r_digits[ds..x_used+ds] = x_digits[0..x_used-1] << (n % _DIGIT_BITS) | 272 // r_digits[ds..x_used+ds] = x_digits[0..x_used-1] << (n % _DIGIT_BITS) |
287 // where ds = ceil(n / _DIGIT_BITS) | 273 // where ds = ceil(n / _DIGIT_BITS) |
288 // Doesn't clear digits below ds. | 274 // Doesn't clear digits below ds. |
289 static void _lsh( | 275 static void _lsh(Uint32List x_digits, int x_used, int n, |
290 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { | 276 Uint32List r_digits) { |
291 final ds = n ~/ _DIGIT_BITS; | 277 final ds = n ~/ _DIGIT_BITS; |
292 final bs = n % _DIGIT_BITS; | 278 final bs = n % _DIGIT_BITS; |
293 final cbs = _DIGIT_BITS - bs; | 279 final cbs = _DIGIT_BITS - bs; |
294 final bm = (1 << cbs) - 1; | 280 final bm = (1 << cbs) - 1; |
295 var c = 0; | 281 var c = 0; |
296 var i = x_used; | 282 var i = x_used; |
297 while (--i >= 0) { | 283 while (--i >= 0) { |
298 final d = x_digits[i]; | 284 final d = x_digits[i]; |
299 r_digits[i + ds + 1] = (d >> cbs) | c; | 285 r_digits[i + ds + 1] = (d >> cbs) | c; |
300 c = (d & bm) << bs; | 286 c = (d & bm) << bs; |
301 } | 287 } |
302 r_digits[ds] = c; | 288 r_digits[ds] = c; |
303 } | 289 } |
304 | 290 |
305 // Return this << n. | 291 // Return this << n. |
306 _Bigint _lShift(int n) { | 292 _Bigint _lShift(int n) { |
307 final ds = n ~/ _DIGIT_BITS; | 293 final ds = n ~/ _DIGIT_BITS; |
308 final bs = n % _DIGIT_BITS; | 294 final bs = n % _DIGIT_BITS; |
309 if (bs == 0) { | 295 if (bs == 0) { |
310 return _dlShift(ds); | 296 return _dlShift(ds); |
311 } | 297 } |
312 var r_used = _used + ds + 1; | 298 var r_used = _used + ds + 1; |
313 var r_digits = new Uint32List(r_used + 2 - (r_used & 1)); // for 64-bit. | 299 var r_digits = new Uint32List(r_used + 2 - (r_used & 1)); // for 64-bit. |
314 _lsh(_digits, _used, n, r_digits); | 300 _lsh(_digits, _used, n, r_digits); |
315 return new _Bigint(_neg, r_used, r_digits); | 301 return new _Bigint(_neg, r_used, r_digits); |
316 } | 302 } |
317 | 303 |
318 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n. | 304 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n. |
319 // Return r_used. | 305 // Return r_used. |
320 static int _lShiftDigits( | 306 static int _lShiftDigits(Uint32List x_digits, int x_used, int n, |
321 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { | 307 Uint32List r_digits) { |
322 final ds = n ~/ _DIGIT_BITS; | 308 final ds = n ~/ _DIGIT_BITS; |
323 final bs = n % _DIGIT_BITS; | 309 final bs = n % _DIGIT_BITS; |
324 if (bs == 0) { | 310 if (bs == 0) { |
325 return _dlShiftDigits(x_digits, x_used, ds, r_digits); | 311 return _dlShiftDigits(x_digits, x_used, ds, r_digits); |
326 } | 312 } |
327 var r_used = x_used + ds + 1; | 313 var r_used = x_used + ds + 1; |
328 assert(r_digits.length >= r_used + 2 - (r_used & 1)); // for 64-bit. | 314 assert(r_digits.length >= r_used + 2 - (r_used & 1)); // for 64-bit. |
329 _lsh(x_digits, x_used, n, r_digits); | 315 _lsh(x_digits, x_used, n, r_digits); |
330 var i = ds; | 316 var i = ds; |
331 while (--i >= 0) { | 317 while (--i >= 0) { |
332 r_digits[i] = 0; | 318 r_digits[i] = 0; |
333 } | 319 } |
334 if (r_digits[r_used - 1] == 0) { | 320 if (r_digits[r_used - 1] == 0) { |
335 r_used--; // Clamp result. | 321 r_used--; // Clamp result. |
336 } else if (r_used.isOdd) { | 322 } else if (r_used.isOdd) { |
337 r_digits[r_used] = 0; | 323 r_digits[r_used] = 0; |
338 } | 324 } |
339 return r_used; | 325 return r_used; |
340 } | 326 } |
341 | 327 |
342 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. | 328 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. |
343 static void _rsh( | 329 static void _rsh(Uint32List x_digits, int x_used, int n, |
344 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { | 330 Uint32List r_digits) { |
345 final ds = n ~/ _DIGIT_BITS; | 331 final ds = n ~/ _DIGIT_BITS; |
346 final bs = n % _DIGIT_BITS; | 332 final bs = n % _DIGIT_BITS; |
347 final cbs = _DIGIT_BITS - bs; | 333 final cbs = _DIGIT_BITS - bs; |
348 final bm = (1 << bs) - 1; | 334 final bm = (1 << bs) - 1; |
349 var c = x_digits[ds] >> bs; | 335 var c = x_digits[ds] >> bs; |
350 final last = x_used - ds - 1; | 336 final last = x_used - ds - 1; |
351 for (var i = 0; i < last; i++) { | 337 for (var i = 0; i < last; i++) { |
352 final d = x_digits[i + ds + 1]; | 338 final d = x_digits[i + ds + 1]; |
353 r_digits[i] = ((d & bm) << cbs) | c; | 339 r_digits[i] = ((d & bm) << cbs) | c; |
354 c = d >> bs; | 340 c = d >> bs; |
(...skipping 26 matching lines...) Expand all Loading... |
381 if (digits[i] != 0) { | 367 if (digits[i] != 0) { |
382 return r._sub(_ONE); | 368 return r._sub(_ONE); |
383 } | 369 } |
384 } | 370 } |
385 } | 371 } |
386 return r; | 372 return r; |
387 } | 373 } |
388 | 374 |
389 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. | 375 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. |
390 // Return r_used. | 376 // Return r_used. |
391 static int _rShiftDigits( | 377 static int _rShiftDigits(Uint32List x_digits, int x_used, int n, |
392 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { | 378 Uint32List r_digits) { |
393 final ds = n ~/ _DIGIT_BITS; | 379 final ds = n ~/ _DIGIT_BITS; |
394 final bs = n % _DIGIT_BITS; | 380 final bs = n % _DIGIT_BITS; |
395 if (bs == 0) { | 381 if (bs == 0) { |
396 return _drShiftDigits(x_digits, x_used, ds, r_digits); | 382 return _drShiftDigits(x_digits, x_used, ds, r_digits); |
397 } | 383 } |
398 var r_used = x_used - ds; | 384 var r_used = x_used - ds; |
399 if (r_used <= 0) { | 385 if (r_used <= 0) { |
400 return 0; | 386 return 0; |
401 } | 387 } |
402 assert(r_digits.length >= r_used + (r_used & 1)); | 388 assert(r_digits.length >= r_used + (r_used & 1)); |
403 _rsh(x_digits, x_used, n, r_digits); | 389 _rsh(x_digits, x_used, n, r_digits); |
404 if (r_digits[r_used - 1] == 0) { | 390 if (r_digits[r_used - 1] == 0) { |
405 r_used--; // Clamp result. | 391 r_used--; // Clamp result. |
406 } else if (r_used.isOdd) { | 392 } else if (r_used.isOdd) { |
407 r_digits[r_used] = 0; | 393 r_digits[r_used] = 0; |
408 } | 394 } |
409 return r_used; | 395 return r_used; |
410 } | 396 } |
411 | 397 |
412 // Return 0 if abs(this) == abs(a). | 398 // Return 0 if abs(this) == abs(a). |
413 // Return a positive number if abs(this) > abs(a). | 399 // Return a positive number if abs(this) > abs(a). |
414 // Return a negative number if abs(this) < abs(a). | 400 // Return a negative number if abs(this) < abs(a). |
415 int _absCompare(_Bigint a) { | 401 int _absCompare(_Bigint a) { |
(...skipping 15 matching lines...) Expand all Loading... |
431 var r = _absCompare(a); | 417 var r = _absCompare(a); |
432 return _neg ? -r : r; | 418 return _neg ? -r : r; |
433 } | 419 } |
434 return _neg ? -1 : 1; | 420 return _neg ? -1 : 1; |
435 } | 421 } |
436 | 422 |
437 // Compare digits[0..used-1] with a_digits[0..a_used-1]. | 423 // Compare digits[0..used-1] with a_digits[0..a_used-1]. |
438 // Return 0 if equal. | 424 // Return 0 if equal. |
439 // Return a positive number if larger. | 425 // Return a positive number if larger. |
440 // Return a negative number if smaller. | 426 // Return a negative number if smaller. |
441 static int _compareDigits( | 427 static int _compareDigits(Uint32List digits, int used, |
442 Uint32List digits, int used, Uint32List a_digits, int a_used) { | 428 Uint32List a_digits, int a_used) { |
443 var r = used - a_used; | 429 var r = used - a_used; |
444 if (r == 0) { | 430 if (r == 0) { |
445 var i = a_used; | 431 var i = a_used; |
446 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0); | 432 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0); |
447 } | 433 } |
448 return r; | 434 return r; |
449 } | 435 } |
450 | 436 |
451 // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1]. | 437 // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1]. |
452 // used >= a_used > 0. | 438 // used >= a_used > 0. |
453 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices. | 439 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices. |
454 static void _absAdd(Uint32List digits, int used, Uint32List a_digits, | 440 static void _absAdd(Uint32List digits, int used, |
455 int a_used, Uint32List r_digits) { | 441 Uint32List a_digits, int a_used, |
| 442 Uint32List r_digits) { |
456 assert(used >= a_used && a_used > 0); | 443 assert(used >= a_used && a_used > 0); |
457 // Verify that digit pairs are accessible for 64-bit processing. | 444 // Verify that digit pairs are accessible for 64-bit processing. |
458 assert(digits.length > ((used - 1) | 1)); | 445 assert(digits.length > ((used - 1) | 1)); |
459 assert(a_digits.length > ((a_used - 1) | 1)); | 446 assert(a_digits.length > ((a_used - 1) | 1)); |
460 assert(r_digits.length > (used | 1)); | 447 assert(r_digits.length > (used | 1)); |
461 var c = 0; | 448 var c = 0; |
462 for (var i = 0; i < a_used; i++) { | 449 for (var i = 0; i < a_used; i++) { |
463 c += digits[i] + a_digits[i]; | 450 c += digits[i] + a_digits[i]; |
464 r_digits[i] = c & _DIGIT_MASK; | 451 r_digits[i] = c & _DIGIT_MASK; |
465 c >>= _DIGIT_BITS; | 452 c >>= _DIGIT_BITS; |
466 } | 453 } |
467 for (var i = a_used; i < used; i++) { | 454 for (var i = a_used; i < used; i++) { |
468 c += digits[i]; | 455 c += digits[i]; |
469 r_digits[i] = c & _DIGIT_MASK; | 456 r_digits[i] = c & _DIGIT_MASK; |
470 c >>= _DIGIT_BITS; | 457 c >>= _DIGIT_BITS; |
471 } | 458 } |
472 r_digits[used] = c; | 459 r_digits[used] = c; |
473 } | 460 } |
474 | 461 |
475 // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1]. | 462 // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1]. |
476 // used >= a_used > 0. | 463 // used >= a_used > 0. |
477 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices. | 464 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices. |
478 static void _absSub(Uint32List digits, int used, Uint32List a_digits, | 465 static void _absSub(Uint32List digits, int used, |
479 int a_used, Uint32List r_digits) { | 466 Uint32List a_digits, int a_used, |
| 467 Uint32List r_digits) { |
480 assert(used >= a_used && a_used > 0); | 468 assert(used >= a_used && a_used > 0); |
481 // Verify that digit pairs are accessible for 64-bit processing. | 469 // Verify that digit pairs are accessible for 64-bit processing. |
482 assert(digits.length > ((used - 1) | 1)); | 470 assert(digits.length > ((used - 1) | 1)); |
483 assert(a_digits.length > ((a_used - 1) | 1)); | 471 assert(a_digits.length > ((a_used - 1) | 1)); |
484 assert(r_digits.length > ((used - 1) | 1)); | 472 assert(r_digits.length > ((used - 1) | 1)); |
485 var c = 0; | 473 var c = 0; |
486 for (var i = 0; i < a_used; i++) { | 474 for (var i = 0; i < a_used; i++) { |
487 c += digits[i] - a_digits[i]; | 475 c += digits[i] - a_digits[i]; |
488 r_digits[i] = c & _DIGIT_MASK; | 476 r_digits[i] = c & _DIGIT_MASK; |
489 c >>= _DIGIT_BITS; | 477 c >>= _DIGIT_BITS; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 } | 534 } |
547 | 535 |
548 // Return abs(this) &~ abs(a) with sign set according to neg. | 536 // Return abs(this) &~ abs(a) with sign set according to neg. |
549 _Bigint _absAndNotSetSign(_Bigint a, bool neg) { | 537 _Bigint _absAndNotSetSign(_Bigint a, bool neg) { |
550 var r_used = _used; | 538 var r_used = _used; |
551 var digits = _digits; | 539 var digits = _digits; |
552 var a_digits = a._digits; | 540 var a_digits = a._digits; |
553 var r_digits = new Uint32List(r_used + (r_used & 1)); | 541 var r_digits = new Uint32List(r_used + (r_used & 1)); |
554 var m = (r_used < a._used) ? r_used : a._used; | 542 var m = (r_used < a._used) ? r_used : a._used; |
555 for (var i = 0; i < m; i++) { | 543 for (var i = 0; i < m; i++) { |
556 r_digits[i] = digits[i] & ~a_digits[i]; | 544 r_digits[i] = digits[i] &~ a_digits[i]; |
557 } | 545 } |
558 for (var i = m; i < r_used; i++) { | 546 for (var i = m; i < r_used; i++) { |
559 r_digits[i] = digits[i]; | 547 r_digits[i] = digits[i]; |
560 } | 548 } |
561 return new _Bigint(neg, r_used, r_digits); | 549 return new _Bigint(neg, r_used, r_digits); |
562 } | 550 } |
563 | 551 |
564 // Return abs(this) | abs(a) with sign set according to neg. | 552 // Return abs(this) | abs(a) with sign set according to neg. |
565 _Bigint _absOrSetSign(_Bigint a, bool neg) { | 553 _Bigint _absOrSetSign(_Bigint a, bool neg) { |
566 var used = _used; | 554 var used = _used; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 // Result cannot be zero if this and a are negative. | 613 // Result cannot be zero if this and a are negative. |
626 return t1._absOrSetSign(a1, true)._absAddSetSign(_ONE, true); | 614 return t1._absOrSetSign(a1, true)._absAddSetSign(_ONE, true); |
627 } | 615 } |
628 return _absAndSetSign(a, false); | 616 return _absAndSetSign(a, false); |
629 } | 617 } |
630 // _neg != a._neg | 618 // _neg != a._neg |
631 var p, n; | 619 var p, n; |
632 if (_neg) { | 620 if (_neg) { |
633 p = a; | 621 p = a; |
634 n = this; | 622 n = this; |
635 } else { | 623 } else { // & is symmetric. |
636 // & is symmetric. | |
637 p = this; | 624 p = this; |
638 n = a; | 625 n = a; |
639 } | 626 } |
640 // p & (-n) == p & ~(n-1) == p &~ (n-1) | 627 // p & (-n) == p & ~(n-1) == p &~ (n-1) |
641 _Bigint n1 = n._absSubSetSign(_ONE, false); | 628 _Bigint n1 = n._absSubSetSign(_ONE, false); |
642 return p._absAndNotSetSign(n1, false); | 629 return p._absAndNotSetSign(n1, false); |
643 } | 630 } |
644 | 631 |
645 // Return this &~ a. | 632 // Return this &~ a. |
646 _Bigint _andNot(_Bigint a) { | 633 _Bigint _andNot(_Bigint a) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 // Result cannot be zero if this and a are negative. | 668 // Result cannot be zero if this and a are negative. |
682 return t1._absAndSetSign(a1, true)._absAddSetSign(_ONE, true); | 669 return t1._absAndSetSign(a1, true)._absAddSetSign(_ONE, true); |
683 } | 670 } |
684 return _absOrSetSign(a, false); | 671 return _absOrSetSign(a, false); |
685 } | 672 } |
686 // _neg != a._neg | 673 // _neg != a._neg |
687 var p, n; | 674 var p, n; |
688 if (_neg) { | 675 if (_neg) { |
689 p = a; | 676 p = a; |
690 n = this; | 677 n = this; |
691 } else { | 678 } else { // | is symmetric. |
692 // | is symmetric. | |
693 p = this; | 679 p = this; |
694 n = a; | 680 n = a; |
695 } | 681 } |
696 // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1) | 682 // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1) |
697 _Bigint n1 = n._absSubSetSign(_ONE, true); | 683 _Bigint n1 = n._absSubSetSign(_ONE, true); |
698 // Result cannot be zero if only one of this or a is negative. | 684 // Result cannot be zero if only one of this or a is negative. |
699 return n1._absAndNotSetSign(p, true)._absAddSetSign(_ONE, true); | 685 return n1._absAndNotSetSign(p, true)._absAddSetSign(_ONE, true); |
700 } | 686 } |
701 | 687 |
702 // Return this ^ a. | 688 // Return this ^ a. |
703 _Bigint _xor(_Bigint a) { | 689 _Bigint _xor(_Bigint a) { |
704 if (_neg == a._neg) { | 690 if (_neg == a._neg) { |
705 if (_neg) { | 691 if (_neg) { |
706 // (-this) ^ (-a) == ~(this-1) ^ ~(a-1) == (this-1) ^ (a-1) | 692 // (-this) ^ (-a) == ~(this-1) ^ ~(a-1) == (this-1) ^ (a-1) |
707 _Bigint t1 = _absSubSetSign(_ONE, true); | 693 _Bigint t1 = _absSubSetSign(_ONE, true); |
708 _Bigint a1 = a._absSubSetSign(_ONE, true); | 694 _Bigint a1 = a._absSubSetSign(_ONE, true); |
709 return t1._absXorSetSign(a1, false); | 695 return t1._absXorSetSign(a1, false); |
710 } | 696 } |
711 return _absXorSetSign(a, false); | 697 return _absXorSetSign(a, false); |
712 } | 698 } |
713 // _neg != a._neg | 699 // _neg != a._neg |
714 var p, n; | 700 var p, n; |
715 if (_neg) { | 701 if (_neg) { |
716 p = a; | 702 p = a; |
717 n = this; | 703 n = this; |
718 } else { | 704 } else { // ^ is symmetric. |
719 // ^ is symmetric. | |
720 p = this; | 705 p = this; |
721 n = a; | 706 n = a; |
722 } | 707 } |
723 // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1) | 708 // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1) |
724 _Bigint n1 = n._absSubSetSign(_ONE, true); | 709 _Bigint n1 = n._absSubSetSign(_ONE, true); |
725 // Result cannot be zero if only one of this or a is negative. | 710 // Result cannot be zero if only one of this or a is negative. |
726 return p._absXorSetSign(n1, true)._absAddSetSign(_ONE, true); | 711 return p._absXorSetSign(n1, true)._absAddSetSign(_ONE, true); |
727 } | 712 } |
728 | 713 |
729 // Return ~this. | 714 // Return ~this. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 // Multiply and accumulate. | 757 // Multiply and accumulate. |
773 // Input: | 758 // Input: |
774 // x_digits[xi]: multiplier digit x. | 759 // x_digits[xi]: multiplier digit x. |
775 // m_digits[i..i+n-1]: multiplicand digits. | 760 // m_digits[i..i+n-1]: multiplicand digits. |
776 // a_digits[j..j+n-1]: accumulator digits. | 761 // a_digits[j..j+n-1]: accumulator digits. |
777 // Operation: | 762 // Operation: |
778 // a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1]. | 763 // a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1]. |
779 // return 1. | 764 // return 1. |
780 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices | 765 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices |
781 // and return 2. | 766 // and return 2. |
782 static int _mulAdd(Uint32List x_digits, int xi, Uint32List m_digits, int i, | 767 static int _mulAdd(Uint32List x_digits, int xi, |
783 Uint32List a_digits, int j, int n) { | 768 Uint32List m_digits, int i, |
| 769 Uint32List a_digits, int j, int n) { |
784 // Verify that digit pairs are accessible for 64-bit processing. | 770 // Verify that digit pairs are accessible for 64-bit processing. |
785 assert(x_digits.length > (xi | 1)); | 771 assert(x_digits.length > (xi | 1)); |
786 assert(m_digits.length > ((i + n - 1) | 1)); | 772 assert(m_digits.length > ((i + n - 1) | 1)); |
787 assert(a_digits.length > ((j + n) | 1)); | 773 assert(a_digits.length > ((j + n) | 1)); |
788 int x = x_digits[xi]; | 774 int x = x_digits[xi]; |
789 if (x == 0) { | 775 if (x == 0) { |
790 // No-op if x is 0. | 776 // No-op if x is 0. |
791 return 1; | 777 return 1; |
792 } | 778 } |
793 int c = 0; | 779 int c = 0; |
794 int xl = x & _DIGIT2_MASK; | 780 int xl = x & _DIGIT2_MASK; |
795 int xh = x >> _DIGIT2_BITS; | 781 int xh = x >> _DIGIT2_BITS; |
796 while (--n >= 0) { | 782 while (--n >= 0) { |
797 int l = m_digits[i] & _DIGIT2_MASK; | 783 int l = m_digits[i] & _DIGIT2_MASK; |
798 int h = m_digits[i++] >> _DIGIT2_BITS; | 784 int h = m_digits[i++] >> _DIGIT2_BITS; |
799 int m = xh * l + h * xl; | 785 int m = xh*l + h*xl; |
800 l = xl * l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c; | 786 l = xl*l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c; |
801 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh * h; | 787 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh*h; |
802 a_digits[j++] = l & _DIGIT_MASK; | 788 a_digits[j++] = l & _DIGIT_MASK; |
803 } | 789 } |
804 while (c != 0) { | 790 while (c != 0) { |
805 int l = a_digits[j] + c; | 791 int l = a_digits[j] + c; |
806 c = l >> _DIGIT_BITS; | 792 c = l >> _DIGIT_BITS; |
807 a_digits[j++] = l & _DIGIT_MASK; | 793 a_digits[j++] = l & _DIGIT_MASK; |
808 } | 794 } |
809 return 1; | 795 return 1; |
810 } | 796 } |
811 | 797 |
812 // Square and accumulate. | 798 // Square and accumulate. |
813 // Input: | 799 // Input: |
814 // x_digits[i..used-1]: digits of operand being squared. | 800 // x_digits[i..used-1]: digits of operand being squared. |
815 // a_digits[2*i..i+used-1]: accumulator digits. | 801 // a_digits[2*i..i+used-1]: accumulator digits. |
816 // Operation: | 802 // Operation: |
817 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + | 803 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + |
818 // 2*x_digits[i]*x_digits[i+1..used-1]. | 804 // 2*x_digits[i]*x_digits[i+1..used-1]. |
819 // return 1. | 805 // return 1. |
820 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices | 806 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices |
821 // and return 2. | 807 // and return 2. |
822 static int _sqrAdd( | 808 static int _sqrAdd(Uint32List x_digits, int i, |
823 Uint32List x_digits, int i, Uint32List a_digits, int used) { | 809 Uint32List a_digits, int used) { |
824 // Verify that digit pairs are accessible for 64-bit processing. | 810 // Verify that digit pairs are accessible for 64-bit processing. |
825 assert(x_digits.length > ((used - 1) | 1)); | 811 assert(x_digits.length > ((used - 1) | 1)); |
826 assert(a_digits.length > ((i + used - 1) | 1)); | 812 assert(a_digits.length > ((i + used - 1) | 1)); |
827 int x = x_digits[i]; | 813 int x = x_digits[i]; |
828 if (x == 0) return 1; | 814 if (x == 0) return 1; |
829 int j = 2 * i; | 815 int j = 2*i; |
830 int c = 0; | 816 int c = 0; |
831 int xl = x & _DIGIT2_MASK; | 817 int xl = x & _DIGIT2_MASK; |
832 int xh = x >> _DIGIT2_BITS; | 818 int xh = x >> _DIGIT2_BITS; |
833 int m = 2 * xh * xl; | 819 int m = 2*xh*xl; |
834 int l = xl * xl + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j]; | 820 int l = xl*xl + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j]; |
835 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh * xh; | 821 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh*xh; |
836 a_digits[j] = l & _DIGIT_MASK; | 822 a_digits[j] = l & _DIGIT_MASK; |
837 x <<= 1; | 823 x <<= 1; |
838 xl = x & _DIGIT2_MASK; | 824 xl = x & _DIGIT2_MASK; |
839 xh = x >> _DIGIT2_BITS; | 825 xh = x >> _DIGIT2_BITS; |
840 int n = used - i - 1; | 826 int n = used - i - 1; |
841 int k = i + 1; | 827 int k = i + 1; |
842 j++; | 828 j++; |
843 while (--n >= 0) { | 829 while (--n >= 0) { |
844 int l = x_digits[k] & _DIGIT2_MASK; | 830 int l = x_digits[k] & _DIGIT2_MASK; |
845 int h = x_digits[k++] >> _DIGIT2_BITS; | 831 int h = x_digits[k++] >> _DIGIT2_BITS; |
846 int m = xh * l + h * xl; | 832 int m = xh*l + h*xl; |
847 l = xl * l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c; | 833 l = xl*l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c; |
848 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh * h; | 834 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh*h; |
849 a_digits[j++] = l & _DIGIT_MASK; | 835 a_digits[j++] = l & _DIGIT_MASK; |
850 } | 836 } |
851 c += a_digits[i + used]; | 837 c += a_digits[i + used]; |
852 if (c >= _DIGIT_BASE) { | 838 if (c >= _DIGIT_BASE) { |
853 a_digits[i + used] = c - _DIGIT_BASE; | 839 a_digits[i + used] = c - _DIGIT_BASE; |
854 a_digits[i + used + 1] = 1; | 840 a_digits[i + used + 1] = 1; |
855 } else { | 841 } else { |
856 a_digits[i + used] = c; | 842 a_digits[i + used] = c; |
857 } | 843 } |
858 return 1; | 844 return 1; |
(...skipping 13 matching lines...) Expand all Loading... |
872 var r_digits = new Uint32List(r_used + (r_used & 1)); | 858 var r_digits = new Uint32List(r_used + (r_used & 1)); |
873 var i = 0; | 859 var i = 0; |
874 while (i < a_used) { | 860 while (i < a_used) { |
875 i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used); | 861 i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used); |
876 } | 862 } |
877 return new _Bigint(_neg != a._neg, r_used, r_digits); | 863 return new _Bigint(_neg != a._neg, r_used, r_digits); |
878 } | 864 } |
879 | 865 |
880 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*a_digits[0..a_used-1]. | 866 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*a_digits[0..a_used-1]. |
881 // Return r_used = x_used + a_used. | 867 // Return r_used = x_used + a_used. |
882 static int _mulDigits(Uint32List x_digits, int x_used, Uint32List a_digits, | 868 static int _mulDigits(Uint32List x_digits, int x_used, |
883 int a_used, Uint32List r_digits) { | 869 Uint32List a_digits, int a_used, |
| 870 Uint32List r_digits) { |
884 var r_used = x_used + a_used; | 871 var r_used = x_used + a_used; |
885 var i = r_used + (r_used & 1); | 872 var i = r_used + (r_used & 1); |
886 assert(r_digits.length >= i); | 873 assert(r_digits.length >= i); |
887 while (--i >= 0) { | 874 while (--i >= 0) { |
888 r_digits[i] = 0; | 875 r_digits[i] = 0; |
889 } | 876 } |
890 i = 0; | 877 i = 0; |
891 while (i < a_used) { | 878 while (i < a_used) { |
892 i += _mulAdd(a_digits, i, x_digits, 0, r_digits, i, x_used); | 879 i += _mulAdd(a_digits, i, x_digits, 0, r_digits, i, x_used); |
893 } | 880 } |
894 return r_used; | 881 return r_used; |
895 } | 882 } |
896 | 883 |
897 // Return this^2. | 884 // Return this^2. |
898 _Bigint _sqr() { | 885 _Bigint _sqr() { |
899 var used = _used; | 886 var used = _used; |
900 if (used == 0) { | 887 if (used == 0) { |
901 return _ZERO; | 888 return _ZERO; |
902 } | 889 } |
903 var r_used = 2 * used; | 890 var r_used = 2 * used; |
904 var digits = _digits; | 891 var digits = _digits; |
905 var r_digits = new Uint32List(r_used); | 892 var r_digits = new Uint32List(r_used); |
906 // Since r_used is even, no need for a leading zero for 64-bit processing. | 893 // Since r_used is even, no need for a leading zero for 64-bit processing. |
907 var i = 0; | 894 var i = 0; |
908 while (i < used - 1) { | 895 while (i < used - 1) { |
909 i += _sqrAdd(digits, i, r_digits, used); | 896 i += _sqrAdd(digits, i, r_digits, used); |
910 } | 897 } |
911 // The last step is already done if digit pairs were processed above. | 898 // The last step is already done if digit pairs were processed above. |
912 if (i < used) { | 899 if (i < used) { |
913 _mulAdd(digits, i, digits, i, r_digits, 2 * i, 1); | 900 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); |
914 } | 901 } |
915 return new _Bigint(false, r_used, r_digits); | 902 return new _Bigint(false, r_used, r_digits); |
916 } | 903 } |
917 | 904 |
918 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*x_digits[0..x_used-1]. | 905 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*x_digits[0..x_used-1]. |
919 // Return r_used = 2*x_used. | 906 // Return r_used = 2*x_used. |
920 static int _sqrDigits(Uint32List x_digits, int x_used, Uint32List r_digits) { | 907 static int _sqrDigits(Uint32List x_digits, int x_used, Uint32List r_digits) { |
921 var r_used = 2 * x_used; | 908 var r_used = 2 * x_used; |
922 assert(r_digits.length >= r_used); | 909 assert(r_digits.length >= r_used); |
923 // Since r_used is even, no need for a leading zero for 64-bit processing. | 910 // Since r_used is even, no need for a leading zero for 64-bit processing. |
924 var i = r_used; | 911 var i = r_used; |
925 while (--i >= 0) { | 912 while (--i >= 0) { |
926 r_digits[i] = 0; | 913 r_digits[i] = 0; |
927 } | 914 } |
928 i = 0; | 915 i = 0; |
929 while (i < x_used - 1) { | 916 while (i < x_used - 1) { |
930 i += _sqrAdd(x_digits, i, r_digits, x_used); | 917 i += _sqrAdd(x_digits, i, r_digits, x_used); |
931 } | 918 } |
932 // The last step is already done if digit pairs were processed above. | 919 // The last step is already done if digit pairs were processed above. |
933 if (i < x_used) { | 920 if (i < x_used) { |
934 _mulAdd(x_digits, i, x_digits, i, r_digits, 2 * i, 1); | 921 _mulAdd(x_digits, i, x_digits, i, r_digits, 2*i, 1); |
935 } | 922 } |
936 return r_used; | 923 return r_used; |
937 } | 924 } |
938 | 925 |
939 // Indices of the arguments of _estQuotientDigit. | 926 // Indices of the arguments of _estQuotientDigit. |
940 // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair | 927 // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair |
941 // of divisor y is provided in the args array, and a 64-bit estimated quotient | 928 // of divisor y is provided in the args array, and a 64-bit estimated quotient |
942 // is returned. However, on 32-bit platforms, the low 32-bit digit is ignored | 929 // is returned. However, on 32-bit platforms, the low 32-bit digit is ignored |
943 // and only one 32-bit digit is returned as the estimated quotient. | 930 // and only one 32-bit digit is returned as the estimated quotient. |
944 static const int _YT_LO = 0; // Low digit of top digit pair of y, for 64-bit. | 931 static const int _YT_LO = 0; // Low digit of top digit pair of y, for 64-bit. |
945 static const int _YT = 1; // Top digit of divisor y. | 932 static const int _YT = 1; // Top digit of divisor y. |
946 static const int _QD = 2; // Estimated quotient. | 933 static const int _QD = 2; // Estimated quotient. |
947 static const int _QD_HI = 3; // High digit of estimated quotient, for 64-bit. | 934 static const int _QD_HI = 3; // High digit of estimated quotient, for 64-bit. |
948 | 935 |
949 // Operation: | 936 // Operation: |
950 // Estimate args[_QD] = digits[i-1..i] ~/ args[_YT] | 937 // Estimate args[_QD] = digits[i-1..i] ~/ args[_YT] |
951 // return 1 | 938 // return 1 |
952 // Note: Intrinsics on 64-bit platforms process a digit pair (i always odd): | 939 // Note: Intrinsics on 64-bit platforms process a digit pair (i always odd): |
953 // Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT] | 940 // Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT] |
954 // return 2 | 941 // return 2 |
955 static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { | 942 static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { |
956 // Verify that digit pairs are accessible for 64-bit processing. | 943 // Verify that digit pairs are accessible for 64-bit processing. |
957 assert(digits.length >= 4); | 944 assert(digits.length >= 4); |
958 if (digits[i] == args[_YT]) { | 945 if (digits[i] == args[_YT]) { |
959 args[_QD] = _DIGIT_MASK; | 946 args[_QD] = _DIGIT_MASK; |
960 } else { | 947 } else { |
961 // Chop off one bit, since a Mint cannot hold 2 DIGITs. | 948 // Chop off one bit, since a Mint cannot hold 2 DIGITs. |
962 var qd = ((digits[i] << (_DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) ~/ | 949 var qd = ((digits[i] << (_DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) |
963 (args[_YT] >> 1); | 950 ~/ (args[_YT] >> 1); |
964 if (qd > _DIGIT_MASK) { | 951 if (qd > _DIGIT_MASK) { |
965 args[_QD] = _DIGIT_MASK; | 952 args[_QD] = _DIGIT_MASK; |
966 } else { | 953 } else { |
967 args[_QD] = qd; | 954 args[_QD] = qd; |
968 } | 955 } |
969 } | 956 } |
970 return 1; | 957 return 1; |
971 } | 958 } |
972 | 959 |
973 // Return trunc(this / a), a != 0. | 960 // Return trunc(this / a), a != 0. |
974 _Bigint _div(_Bigint a) { | 961 _Bigint _div(_Bigint a) { |
975 assert(a._used > 0); | 962 assert(a._used > 0); |
976 if (_used < a._used) { | 963 if (_used < a._used) { |
977 return _ZERO; | 964 return _ZERO; |
978 } | 965 } |
979 _divRem(a); | 966 _divRem(a); |
980 // Return quotient, i.e. | 967 // Return quotient, i.e. |
981 // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign. | 968 // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign. |
982 var lastQuo_used = _lastQuoRem_used - _lastRem_used; | 969 var lastQuo_used = _lastQuoRem_used - _lastRem_used; |
983 var quo_digits = _cloneDigits( | 970 var quo_digits = _cloneDigits(_lastQuoRem_digits, |
984 _lastQuoRem_digits, _lastRem_used, _lastQuoRem_used, lastQuo_used); | 971 _lastRem_used, |
| 972 _lastQuoRem_used, |
| 973 lastQuo_used); |
985 var quo = new _Bigint(false, lastQuo_used, quo_digits); | 974 var quo = new _Bigint(false, lastQuo_used, quo_digits); |
986 if ((_neg != a._neg) && (quo._used > 0)) { | 975 if ((_neg != a._neg) && (quo._used > 0)) { |
987 quo = quo._negate(); | 976 quo = quo._negate(); |
988 } | 977 } |
989 return quo; | 978 return quo; |
990 } | 979 } |
991 | 980 |
992 // Return this - a * trunc(this / a), a != 0. | 981 // Return this - a * trunc(this / a), a != 0. |
993 _Bigint _rem(_Bigint a) { | 982 _Bigint _rem(_Bigint a) { |
994 assert(a._used > 0); | 983 assert(a._used > 0); |
995 if (_used < a._used) { | 984 if (_used < a._used) { |
996 return this; | 985 return this; |
997 } | 986 } |
998 _divRem(a); | 987 _divRem(a); |
999 // Return remainder, i.e. | 988 // Return remainder, i.e. |
1000 // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign. | 989 // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign. |
1001 var rem_digits = | 990 var rem_digits = _cloneDigits(_lastQuoRem_digits, |
1002 _cloneDigits(_lastQuoRem_digits, 0, _lastRem_used, _lastRem_used); | 991 0, |
| 992 _lastRem_used, |
| 993 _lastRem_used); |
1003 var rem = new _Bigint(false, _lastRem_used, rem_digits); | 994 var rem = new _Bigint(false, _lastRem_used, rem_digits); |
1004 if (_lastRem_nsh > 0) { | 995 if (_lastRem_nsh > 0) { |
1005 rem = rem._rShift(_lastRem_nsh); // Denormalize remainder. | 996 rem = rem._rShift(_lastRem_nsh); // Denormalize remainder. |
1006 } | 997 } |
1007 if (_neg && (rem._used > 0)) { | 998 if (_neg && (rem._used > 0)) { |
1008 rem = rem._negate(); | 999 rem = rem._negate(); |
1009 } | 1000 } |
1010 return rem; | 1001 return rem; |
1011 } | 1002 } |
1012 | 1003 |
1013 // Cache concatenated positive quotient and normalized positive remainder. | 1004 // Cache concatenated positive quotient and normalized positive remainder. |
1014 void _divRem(_Bigint a) { | 1005 void _divRem(_Bigint a) { |
1015 // Check if result is already cached (identical on Bigint is too expensive). | 1006 // Check if result is already cached (identical on Bigint is too expensive). |
1016 if ((this._used == _lastDividend_used) && | 1007 if ((this._used == _lastDividend_used) && |
1017 (a._used == _lastDivisor_used) && | 1008 (a._used == _lastDivisor_used) && |
1018 identical(this._digits, _lastDividend_digits) && | 1009 identical(this._digits, _lastDividend_digits) && |
1019 identical(a._digits, _lastDivisor_digits)) { | 1010 identical(a._digits, _lastDivisor_digits)) { |
1020 return; | 1011 return; |
1021 } | 1012 } |
1022 var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]); | 1013 var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]); |
1023 // For 64-bit processing, make sure y has an even number of digits. | 1014 // For 64-bit processing, make sure y has an even number of digits. |
1024 if (a._used.isOdd) { | 1015 if (a._used.isOdd) { |
1025 nsh += _DIGIT_BITS; | 1016 nsh += _DIGIT_BITS; |
1026 } | 1017 } |
1027 // Concatenated positive quotient and normalized positive remainder. | 1018 // Concatenated positive quotient and normalized positive remainder. |
1028 var r_digits; | 1019 var r_digits; |
1029 var r_used; | 1020 var r_used; |
1030 // Normalized positive divisor. | 1021 // Normalized positive divisor. |
1031 var y_digits; | 1022 var y_digits; |
1032 var y_used; | 1023 var y_used; |
1033 if (nsh > 0) { | 1024 if (nsh > 0) { |
1034 y_digits = new Uint32List(a._used + 5); // +5 for norm. and 64-bit. | 1025 y_digits = new Uint32List(a._used + 5); // +5 for norm. and 64-bit. |
1035 y_used = _lShiftDigits(a._digits, a._used, nsh, y_digits); | 1026 y_used = _lShiftDigits(a._digits, a._used, nsh, y_digits); |
1036 r_digits = new Uint32List(_used + 5); // +5 for normalization and 64-bit. | 1027 r_digits = new Uint32List(_used + 5); // +5 for normalization and 64-bit. |
1037 r_used = _lShiftDigits(_digits, _used, nsh, r_digits); | 1028 r_used = _lShiftDigits(_digits, _used, nsh, r_digits); |
1038 } else { | 1029 } else { |
1039 y_digits = a._digits; | 1030 y_digits = a._digits; |
1040 y_used = a._used; | 1031 y_used = a._used; |
1041 r_digits = _cloneDigits(_digits, 0, _used, _used + 2); | 1032 r_digits = _cloneDigits(_digits, 0, _used, _used + 2); |
1042 r_used = _used; | 1033 r_used = _used; |
1043 } | 1034 } |
1044 Uint32List yt_qd = new Uint32List(4); | 1035 Uint32List yt_qd = new Uint32List(4); |
1045 yt_qd[_YT_LO] = y_digits[y_used - 2]; | 1036 yt_qd[_YT_LO] = y_digits[y_used - 2]; |
1046 yt_qd[_YT] = y_digits[y_used - 1]; | 1037 yt_qd[_YT] = y_digits[y_used - 1]; |
1047 // For 64-bit processing, make sure y_used, i, and j are even. | 1038 // For 64-bit processing, make sure y_used, i, and j are even. |
1048 assert(y_used.isEven); | 1039 assert(y_used.isEven); |
1049 var i = r_used + (r_used & 1); | 1040 var i = r_used + (r_used & 1); |
1050 var j = i - y_used; | 1041 var j = i - y_used; |
1051 // t_digits is a temporary array of i digits. | 1042 // t_digits is a temporary array of i digits. |
1052 var t_digits = new Uint32List(i); | 1043 var t_digits = new Uint32List(i); |
1053 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); | 1044 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); |
1054 // Explicit first division step in case normalized dividend is larger or | 1045 // Explicit first division step in case normalized dividend is larger or |
1055 // equal to shifted normalized divisor. | 1046 // equal to shifted normalized divisor. |
1056 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { | 1047 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { |
1057 assert(i == r_used); | 1048 assert(i == r_used); |
1058 r_digits[r_used++] = 1; // Quotient = 1. | 1049 r_digits[r_used++] = 1; // Quotient = 1. |
1059 // Subtract divisor from remainder. | 1050 // Subtract divisor from remainder. |
1060 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1051 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
1061 } else { | 1052 } else { |
1062 // Account for possible carry in _mulAdd step. | 1053 // Account for possible carry in _mulAdd step. |
1063 r_digits[r_used++] = 0; | 1054 r_digits[r_used++] = 0; |
1064 } | 1055 } |
1065 r_digits[r_used] = 0; // Leading zero for 64-bit processing. | 1056 r_digits[r_used] = 0; // Leading zero for 64-bit processing. |
1066 // Negate y so we can later use _mulAdd instead of non-existent _mulSub. | 1057 // Negate y so we can later use _mulAdd instead of non-existent _mulSub. |
1067 var ny_digits = new Uint32List(y_used + 2); | 1058 var ny_digits = new Uint32List(y_used + 2); |
1068 ny_digits[y_used] = 1; | 1059 ny_digits[y_used] = 1; |
1069 _absSub(ny_digits, y_used + 1, y_digits, y_used, ny_digits); | 1060 _absSub(ny_digits, y_used + 1, y_digits, y_used, ny_digits); |
1070 // ny_digits is read-only and has y_used digits (possibly including several | 1061 // ny_digits is read-only and has y_used digits (possibly including several |
1071 // leading zeros) plus a leading zero for 64-bit processing. | 1062 // leading zeros) plus a leading zero for 64-bit processing. |
1072 // r_digits is modified during iteration. | 1063 // r_digits is modified during iteration. |
1073 // r_digits[0..y_used-1] is the current remainder. | 1064 // r_digits[0..y_used-1] is the current remainder. |
1074 // r_digits[y_used..r_used-1] is the current quotient. | 1065 // r_digits[y_used..r_used-1] is the current quotient. |
1075 --i; | 1066 --i; |
1076 while (j > 0) { | 1067 while (j > 0) { |
1077 var d0 = _estQuotientDigit(yt_qd, r_digits, i); | 1068 var d0 = _estQuotientDigit(yt_qd, r_digits, i); |
1078 j -= d0; | 1069 j -= d0; |
1079 var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used); | 1070 var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used); |
1080 // _estQuotientDigit and _mulAdd must agree on the number of digits to | 1071 // _estQuotientDigit and _mulAdd must agree on the number of digits to |
1081 // process. | 1072 // process. |
1082 assert(d0 == d1); | 1073 assert(d0 == d1); |
1083 if (d0 == 1) { | 1074 if (d0 == 1) { |
1084 if (r_digits[i] < yt_qd[_QD]) { | 1075 if (r_digits[i] < yt_qd[_QD]) { |
1085 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); | 1076 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); |
1086 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1077 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
1087 while (r_digits[i] < --yt_qd[_QD]) { | 1078 while (r_digits[i] < --yt_qd[_QD]) { |
1088 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1079 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
1089 } | 1080 } |
1090 } | 1081 } |
1091 } else { | 1082 } else { |
1092 assert(d0 == 2); | 1083 assert(d0 == 2); |
1093 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1084 assert(r_digits[i] <= yt_qd[_QD_HI]); |
1094 if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) { | 1085 if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i-1] < yt_qd[_QD])) { |
1095 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); | 1086 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); |
1096 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1087 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
1097 if (yt_qd[_QD] == 0) { | 1088 if (yt_qd[_QD] == 0) { |
1098 --yt_qd[_QD_HI]; | 1089 --yt_qd[_QD_HI]; |
1099 } | 1090 } |
1100 --yt_qd[_QD]; | 1091 --yt_qd[_QD]; |
1101 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1092 assert(r_digits[i] <= yt_qd[_QD_HI]); |
1102 while ( | 1093 while ((r_digits[i] < yt_qd[_QD_HI]) || |
1103 (r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) { | 1094 (r_digits[i-1] < yt_qd[_QD])) { |
1104 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1095 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
1105 if (yt_qd[_QD] == 0) { | 1096 if (yt_qd[_QD] == 0) { |
1106 --yt_qd[_QD_HI]; | 1097 --yt_qd[_QD_HI]; |
1107 } | 1098 } |
1108 --yt_qd[_QD]; | 1099 --yt_qd[_QD]; |
1109 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1100 assert(r_digits[i] <= yt_qd[_QD_HI]); |
1110 } | 1101 } |
1111 } | 1102 } |
1112 } | 1103 } |
1113 i -= d0; | 1104 i -= d0; |
(...skipping 15 matching lines...) Expand all Loading... |
1129 // y_digits[0..y_used-1]: normalized positive divisor. | 1120 // y_digits[0..y_used-1]: normalized positive divisor. |
1130 // ny_digits[0..y_used-1]: negated y_digits. | 1121 // ny_digits[0..y_used-1]: negated y_digits. |
1131 // nsh: normalization shift amount. | 1122 // nsh: normalization shift amount. |
1132 // yt_qd: top y digit(s) and place holder for estimated quotient digit(s). | 1123 // yt_qd: top y digit(s) and place holder for estimated quotient digit(s). |
1133 // t_digits: temp array of 2*y_used digits. | 1124 // t_digits: temp array of 2*y_used digits. |
1134 // r_digits: result digits array large enough to temporarily hold | 1125 // r_digits: result digits array large enough to temporarily hold |
1135 // concatenated quotient and normalized remainder. | 1126 // concatenated quotient and normalized remainder. |
1136 // Output: | 1127 // Output: |
1137 // r_digits[0..r_used-1]: positive remainder. | 1128 // r_digits[0..r_used-1]: positive remainder. |
1138 // Returns r_used. | 1129 // Returns r_used. |
1139 static int _remDigits( | 1130 static int _remDigits(Uint32List x_digits, int x_used, |
1140 Uint32List x_digits, | 1131 Uint32List y_digits, int y_used, Uint32List ny_digits, |
1141 int x_used, | 1132 int nsh, |
1142 Uint32List y_digits, | 1133 Uint32List yt_qd, |
1143 int y_used, | 1134 Uint32List t_digits, |
1144 Uint32List ny_digits, | 1135 Uint32List r_digits) { |
1145 int nsh, | |
1146 Uint32List yt_qd, | |
1147 Uint32List t_digits, | |
1148 Uint32List r_digits) { | |
1149 // Initialize r_digits to normalized positive dividend. | 1136 // Initialize r_digits to normalized positive dividend. |
1150 var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits); | 1137 var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits); |
1151 // For 64-bit processing, make sure y_used, i, and j are even. | 1138 // For 64-bit processing, make sure y_used, i, and j are even. |
1152 assert(y_used.isEven); | 1139 assert(y_used.isEven); |
1153 var i = r_used + (r_used & 1); | 1140 var i = r_used + (r_used & 1); |
1154 var j = i - y_used; | 1141 var j = i - y_used; |
1155 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); | 1142 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); |
1156 // Explicit first division step in case normalized dividend is larger or | 1143 // Explicit first division step in case normalized dividend is larger or |
1157 // equal to shifted normalized divisor. | 1144 // equal to shifted normalized divisor. |
1158 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { | 1145 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { |
1159 assert(i == r_used); | 1146 assert(i == r_used); |
1160 r_digits[r_used++] = 1; // Quotient = 1. | 1147 r_digits[r_used++] = 1; // Quotient = 1. |
1161 // Subtract divisor from remainder. | 1148 // Subtract divisor from remainder. |
1162 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1149 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
1163 } else { | 1150 } else { |
1164 // Account for possible carry in _mulAdd step. | 1151 // Account for possible carry in _mulAdd step. |
1165 r_digits[r_used++] = 0; | 1152 r_digits[r_used++] = 0; |
1166 } | 1153 } |
1167 r_digits[r_used] = 0; // Leading zero for 64-bit processing. | 1154 r_digits[r_used] = 0; // Leading zero for 64-bit processing. |
1168 // Negated y_digits passed in ny_digits allow the use of _mulAdd instead of | 1155 // Negated y_digits passed in ny_digits allow the use of _mulAdd instead of |
1169 // unimplemented _mulSub. | 1156 // unimplemented _mulSub. |
1170 // ny_digits is read-only and has y_used digits (possibly including several | 1157 // ny_digits is read-only and has y_used digits (possibly including several |
1171 // leading zeros) plus a leading zero for 64-bit processing. | 1158 // leading zeros) plus a leading zero for 64-bit processing. |
1172 // r_digits is modified during iteration. | 1159 // r_digits is modified during iteration. |
1173 // r_digits[0..y_used-1] is the current remainder. | 1160 // r_digits[0..y_used-1] is the current remainder. |
1174 // r_digits[y_used..r_used-1] is the current quotient. | 1161 // r_digits[y_used..r_used-1] is the current quotient. |
1175 --i; | 1162 --i; |
1176 while (j > 0) { | 1163 while (j > 0) { |
1177 var d0 = _estQuotientDigit(yt_qd, r_digits, i); | 1164 var d0 = _estQuotientDigit(yt_qd, r_digits, i); |
1178 j -= d0; | 1165 j -= d0; |
1179 var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used); | 1166 var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used); |
1180 // _estQuotientDigit and _mulAdd must agree on the number of digits to | 1167 // _estQuotientDigit and _mulAdd must agree on the number of digits to |
1181 // process. | 1168 // process. |
1182 assert(d0 == d1); | 1169 assert(d0 == d1); |
1183 if (d0 == 1) { | 1170 if (d0 == 1) { |
1184 if (r_digits[i] < yt_qd[_QD]) { | 1171 if (r_digits[i] < yt_qd[_QD]) { |
1185 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); | 1172 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); |
1186 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1173 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
1187 while (r_digits[i] < --yt_qd[_QD]) { | 1174 while (r_digits[i] < --yt_qd[_QD]) { |
1188 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1175 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
1189 } | 1176 } |
1190 } | 1177 } |
1191 } else { | 1178 } else { |
1192 assert(d0 == 2); | 1179 assert(d0 == 2); |
1193 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1180 assert(r_digits[i] <= yt_qd[_QD_HI]); |
1194 if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) { | 1181 if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i-1] < yt_qd[_QD])) { |
1195 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); | 1182 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); |
1196 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1183 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
1197 if (yt_qd[_QD] == 0) { | 1184 if (yt_qd[_QD] == 0) { |
1198 --yt_qd[_QD_HI]; | 1185 --yt_qd[_QD_HI]; |
1199 } | 1186 } |
1200 --yt_qd[_QD]; | 1187 --yt_qd[_QD]; |
1201 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1188 assert(r_digits[i] <= yt_qd[_QD_HI]); |
1202 while ( | 1189 while ((r_digits[i] < yt_qd[_QD_HI]) || |
1203 (r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) { | 1190 (r_digits[i-1] < yt_qd[_QD])) { |
1204 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1191 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
1205 if (yt_qd[_QD] == 0) { | 1192 if (yt_qd[_QD] == 0) { |
1206 --yt_qd[_QD_HI]; | 1193 --yt_qd[_QD_HI]; |
1207 } | 1194 } |
1208 --yt_qd[_QD]; | 1195 --yt_qd[_QD]; |
1209 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1196 assert(r_digits[i] <= yt_qd[_QD_HI]); |
1210 } | 1197 } |
1211 } | 1198 } |
1212 } | 1199 } |
1213 i -= d0; | 1200 i -= d0; |
(...skipping 10 matching lines...) Expand all Loading... |
1224 int get hashCode => this; | 1211 int get hashCode => this; |
1225 int get _identityHashCode => this; | 1212 int get _identityHashCode => this; |
1226 | 1213 |
1227 int operator ~() { | 1214 int operator ~() { |
1228 return _not()._toValidInt(); | 1215 return _not()._toValidInt(); |
1229 } | 1216 } |
1230 | 1217 |
1231 int get bitLength { | 1218 int get bitLength { |
1232 if (_used == 0) return 0; | 1219 if (_used == 0) return 0; |
1233 if (_neg) return (~this).bitLength; | 1220 if (_neg) return (~this).bitLength; |
1234 return _DIGIT_BITS * (_used - 1) + _nbits(_digits[_used - 1]); | 1221 return _DIGIT_BITS*(_used - 1) + _nbits(_digits[_used - 1]); |
1235 } | 1222 } |
1236 | 1223 |
1237 // This method must support smi._toBigint()._shrFromInt(int). | 1224 // This method must support smi._toBigint()._shrFromInt(int). |
1238 int _shrFromInt(int other) { | 1225 int _shrFromInt(int other) { |
1239 if (_used == 0) return other; // Shift amount is zero. | 1226 if (_used == 0) return other; // Shift amount is zero. |
1240 if (_neg) throw new RangeError.range(this, 0, null); | 1227 if (_neg) throw new RangeError.range(this, 0, null); |
1241 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 1228 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
1242 var shift; | 1229 var shift; |
1243 if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) { | 1230 if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) { |
1244 if (other < 0) { | 1231 if (other < 0) { |
1245 return -1; | 1232 return -1; |
1246 } else { | 1233 } else { |
1247 return 0; | 1234 return 0; |
1248 } | 1235 } |
1249 } else { | 1236 } else { |
1250 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; | 1237 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; |
1251 } | 1238 } |
1252 return other._toBigint()._rShift(shift)._toValidInt(); | 1239 return other._toBigint()._rShift(shift)._toValidInt(); |
1253 } | 1240 } |
1254 | 1241 |
1255 // This method must support smi._toBigint()._shlFromInt(int). | 1242 // This method must support smi._toBigint()._shlFromInt(int). |
1256 // An out of memory exception is thrown if the result cannot be allocated. | 1243 // An out of memory exception is thrown if the result cannot be allocated. |
1257 int _shlFromInt(int other) { | 1244 int _shlFromInt(int other) { |
1258 if (_used == 0) return other; // Shift amount is zero. | 1245 if (_used == 0) return other; // Shift amount is zero. |
1259 if (_neg) throw new RangeError.range(this, 0, null); | 1246 if (_neg) throw new RangeError.range(this, 0, null); |
1260 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 1247 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
1261 var shift; | 1248 var shift; |
1262 if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) { | 1249 if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) { |
1263 if (other == 0) return 0; // Shifted value is zero. | 1250 if (other == 0) return 0; // Shifted value is zero. |
1264 throw new OutOfMemoryError(); | 1251 throw new OutOfMemoryError(); |
1265 } else { | 1252 } else { |
1266 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; | 1253 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; |
1267 } | 1254 } |
1268 return other._toBigint()._lShift(shift)._toValidInt(); | 1255 return other._toBigint()._lShift(shift)._toValidInt(); |
1269 } | 1256 } |
1270 | 1257 |
1271 // Overriden operators and methods. | 1258 // Overriden operators and methods. |
1272 | 1259 |
1273 // The following operators override operators of _IntegerImplementation for | 1260 // The following operators override operators of _IntegerImplementation for |
1274 // efficiency, but are not necessary for correctness. They shortcut native | 1261 // efficiency, but are not necessary for correctness. They shortcut native |
1275 // calls that would return null because the receiver is _Bigint. | 1262 // calls that would return null because the receiver is _Bigint. |
1276 num operator +(num other) { | 1263 num operator +(num other) { |
1277 return other._toBigintOrDouble()._addFromInteger(this); | 1264 return other._toBigintOrDouble()._addFromInteger(this); |
1278 } | 1265 } |
1279 | |
1280 num operator -(num other) { | 1266 num operator -(num other) { |
1281 return other._toBigintOrDouble()._subFromInteger(this); | 1267 return other._toBigintOrDouble()._subFromInteger(this); |
1282 } | 1268 } |
1283 | |
1284 num operator *(num other) { | 1269 num operator *(num other) { |
1285 return other._toBigintOrDouble()._mulFromInteger(this); | 1270 return other._toBigintOrDouble()._mulFromInteger(this); |
1286 } | 1271 } |
1287 | |
1288 num operator ~/(num other) { | 1272 num operator ~/(num other) { |
1289 return other._toBigintOrDouble()._truncDivFromInteger(this); | 1273 return other._toBigintOrDouble()._truncDivFromInteger(this); |
1290 } | 1274 } |
1291 | |
1292 num operator %(num other) { | 1275 num operator %(num other) { |
1293 return other._toBigintOrDouble()._moduloFromInteger(this); | 1276 return other._toBigintOrDouble()._moduloFromInteger(this); |
1294 } | 1277 } |
1295 | |
1296 int operator &(int other) { | 1278 int operator &(int other) { |
1297 return other._toBigintOrDouble()._bitAndFromInteger(this); | 1279 return other._toBigintOrDouble()._bitAndFromInteger(this); |
1298 } | 1280 } |
1299 | |
1300 int operator |(int other) { | 1281 int operator |(int other) { |
1301 return other._toBigintOrDouble()._bitOrFromInteger(this); | 1282 return other._toBigintOrDouble()._bitOrFromInteger(this); |
1302 } | 1283 } |
1303 | |
1304 int operator ^(int other) { | 1284 int operator ^(int other) { |
1305 return other._toBigintOrDouble()._bitXorFromInteger(this); | 1285 return other._toBigintOrDouble()._bitXorFromInteger(this); |
1306 } | 1286 } |
1307 | |
1308 int operator >>(int other) { | 1287 int operator >>(int other) { |
1309 return other._toBigintOrDouble()._shrFromInt(this); | 1288 return other._toBigintOrDouble()._shrFromInt(this); |
1310 } | 1289 } |
1311 | |
1312 int operator <<(int other) { | 1290 int operator <<(int other) { |
1313 return other._toBigintOrDouble()._shlFromInt(this); | 1291 return other._toBigintOrDouble()._shlFromInt(this); |
1314 } | 1292 } |
1315 // End of operator shortcuts. | 1293 // End of operator shortcuts. |
1316 | 1294 |
1317 int operator -() { | 1295 int operator -() { |
1318 return _negate()._toValidInt(); | 1296 return _negate()._toValidInt(); |
1319 } | 1297 } |
1320 | 1298 |
1321 int get sign { | 1299 int get sign { |
1322 return (_used == 0) ? 0 : _neg ? -1 : 1; | 1300 return (_used == 0) ? 0 : _neg ? -1 : 1; |
1323 } | 1301 } |
1324 | 1302 |
1325 bool get isEven => _used == 0 || (_digits[0] & 1) == 0; | 1303 bool get isEven => _used == 0 || (_digits[0] & 1) == 0; |
1326 bool get isNegative => _neg; | 1304 bool get isNegative => _neg; |
1327 | 1305 |
1328 String _toPow2String(int radix) { | 1306 String _toPow2String(int radix) { |
1329 if (_used == 0) return "0"; | 1307 if (_used == 0) return "0"; |
1330 assert(radix & (radix - 1) == 0); | 1308 assert(radix & (radix - 1) == 0); |
1331 final bitsPerChar = radix.bitLength - 1; | 1309 final bitsPerChar = radix.bitLength - 1; |
1332 final firstcx = _neg ? 1 : 0; // Index of first char in str after the sign. | 1310 final firstcx = _neg ? 1 : 0; // Index of first char in str after the sign. |
1333 final lastdx = _used - 1; // Index of last digit in bigint. | 1311 final lastdx = _used - 1; // Index of last digit in bigint. |
1334 final bitLength = lastdx * _DIGIT_BITS + _nbits(_digits[lastdx]); | 1312 final bitLength = lastdx*_DIGIT_BITS + _nbits(_digits[lastdx]); |
1335 // Index of char in str. Initialize with str length. | 1313 // Index of char in str. Initialize with str length. |
1336 var cx = firstcx + (bitLength + bitsPerChar - 1) ~/ bitsPerChar; | 1314 var cx = firstcx + (bitLength + bitsPerChar - 1) ~/ bitsPerChar; |
1337 _OneByteString str = _OneByteString._allocate(cx); | 1315 _OneByteString str = _OneByteString._allocate(cx); |
1338 str._setAt(0, 0x2d); // '-'. Is overwritten if not negative. | 1316 str._setAt(0, 0x2d); // '-'. Is overwritten if not negative. |
1339 final mask = radix - 1; | 1317 final mask = radix - 1; |
1340 var dx = 0; // Digit index in bigint. | 1318 var dx = 0; // Digit index in bigint. |
1341 var bx = 0; // Bit index in bigint digit. | 1319 var bx = 0; // Bit index in bigint digit. |
1342 do { | 1320 do { |
1343 var ch; | 1321 var ch; |
1344 if (bx > (_DIGIT_BITS - bitsPerChar)) { | 1322 if (bx > (_DIGIT_BITS - bitsPerChar)) { |
1345 ch = _digits[dx++] >> bx; | 1323 ch = _digits[dx++] >> bx; |
1346 bx += bitsPerChar - _DIGIT_BITS; | 1324 bx += bitsPerChar - _DIGIT_BITS; |
1347 if (dx <= lastdx) { | 1325 if (dx <= lastdx) { |
1348 ch |= (_digits[dx] & ((1 << bx) - 1)) << (bitsPerChar - bx); | 1326 ch |= (_digits[dx] & ((1 << bx) - 1)) << (bitsPerChar - bx); |
1349 } | 1327 } |
1350 } else { | 1328 } else { |
1351 ch = (_digits[dx] >> bx) & mask; | 1329 ch = (_digits[dx] >> bx) & mask; |
1352 bx += bitsPerChar; | 1330 bx += bitsPerChar; |
1353 if (bx >= _DIGIT_BITS) { | 1331 if (bx >= _DIGIT_BITS) { |
1354 bx -= _DIGIT_BITS; | 1332 bx -= _DIGIT_BITS; |
1355 dx++; | 1333 dx++; |
1356 } | 1334 } |
1357 } | 1335 } |
1358 str._setAt(--cx, _IntegerImplementation._digits.codeUnitAt(ch)); | 1336 str._setAt(--cx, _IntegerImplementation._digits.codeUnitAt(ch)); |
1359 } while (cx > firstcx); | 1337 } while (cx > firstcx); |
1360 return str; | 1338 return str; |
1361 } | 1339 } |
1362 | 1340 |
1363 int _bitAndFromSmi(int other) => _bitAndFromInteger(other); | 1341 int _bitAndFromSmi(int other) => _bitAndFromInteger(other); |
1364 | 1342 |
1365 int _bitAndFromInteger(int other) { | 1343 int _bitAndFromInteger(int other) { |
1366 return other._toBigint()._and(this)._toValidInt(); | 1344 return other._toBigint()._and(this)._toValidInt(); |
1367 } | 1345 } |
1368 | |
1369 int _bitOrFromInteger(int other) { | 1346 int _bitOrFromInteger(int other) { |
1370 return other._toBigint()._or(this)._toValidInt(); | 1347 return other._toBigint()._or(this)._toValidInt(); |
1371 } | 1348 } |
1372 | |
1373 int _bitXorFromInteger(int other) { | 1349 int _bitXorFromInteger(int other) { |
1374 return other._toBigint()._xor(this)._toValidInt(); | 1350 return other._toBigint()._xor(this)._toValidInt(); |
1375 } | 1351 } |
1376 | |
1377 int _addFromInteger(int other) { | 1352 int _addFromInteger(int other) { |
1378 return other._toBigint()._add(this)._toValidInt(); | 1353 return other._toBigint()._add(this)._toValidInt(); |
1379 } | 1354 } |
1380 | |
1381 int _subFromInteger(int other) { | 1355 int _subFromInteger(int other) { |
1382 return other._toBigint()._sub(this)._toValidInt(); | 1356 return other._toBigint()._sub(this)._toValidInt(); |
1383 } | 1357 } |
1384 | |
1385 int _mulFromInteger(int other) { | 1358 int _mulFromInteger(int other) { |
1386 return other._toBigint()._mul(this)._toValidInt(); | 1359 return other._toBigint()._mul(this)._toValidInt(); |
1387 } | 1360 } |
1388 | |
1389 int _truncDivFromInteger(int other) { | 1361 int _truncDivFromInteger(int other) { |
1390 if (_used == 0) { | 1362 if (_used == 0) { |
1391 throw const IntegerDivisionByZeroException(); | 1363 throw const IntegerDivisionByZeroException(); |
1392 } | 1364 } |
1393 return other._toBigint()._div(this)._toValidInt(); | 1365 return other._toBigint()._div(this)._toValidInt(); |
1394 } | 1366 } |
1395 | |
1396 int _moduloFromInteger(int other) { | 1367 int _moduloFromInteger(int other) { |
1397 if (_used == 0) { | 1368 if (_used == 0) { |
1398 throw const IntegerDivisionByZeroException(); | 1369 throw const IntegerDivisionByZeroException(); |
1399 } | 1370 } |
1400 _Bigint result = other._toBigint()._rem(this); | 1371 _Bigint result = other._toBigint()._rem(this); |
1401 if (result._neg) { | 1372 if (result._neg) { |
1402 if (_neg) { | 1373 if (_neg) { |
1403 result = result._sub(this); | 1374 result = result._sub(this); |
1404 } else { | 1375 } else { |
1405 result = result._add(this); | 1376 result = result._add(this); |
1406 } | 1377 } |
1407 } | 1378 } |
1408 return result._toValidInt(); | 1379 return result._toValidInt(); |
1409 } | 1380 } |
1410 | |
1411 int _remainderFromInteger(int other) { | 1381 int _remainderFromInteger(int other) { |
1412 if (_used == 0) { | 1382 if (_used == 0) { |
1413 throw const IntegerDivisionByZeroException(); | 1383 throw const IntegerDivisionByZeroException(); |
1414 } | 1384 } |
1415 return other._toBigint()._rem(this)._toValidInt(); | 1385 return other._toBigint()._rem(this)._toValidInt(); |
1416 } | 1386 } |
1417 | |
1418 bool _greaterThanFromInteger(int other) { | 1387 bool _greaterThanFromInteger(int other) { |
1419 return other._toBigint()._compare(this) > 0; | 1388 return other._toBigint()._compare(this) > 0; |
1420 } | 1389 } |
1421 | |
1422 bool _equalToInteger(int other) { | 1390 bool _equalToInteger(int other) { |
1423 return other._toBigint()._compare(this) == 0; | 1391 return other._toBigint()._compare(this) == 0; |
1424 } | 1392 } |
1425 | 1393 |
1426 // Returns pow(this, e) % m, with e >= 0, m > 0. | 1394 // Returns pow(this, e) % m, with e >= 0, m > 0. |
1427 int modPow(int e, int m) { | 1395 int modPow(int e, int m) { |
1428 if (e is! int) { | 1396 if (e is! int) { |
1429 throw new ArgumentError.value(e, "exponent", "not an integer"); | 1397 throw new ArgumentError.value(e, "exponent", "not an integer"); |
1430 } | 1398 } |
1431 if (m is! int) { | 1399 if (m is! int) { |
1432 throw new ArgumentError.value(m, "modulus", "not an integer"); | 1400 throw new ArgumentError.value(m, "modulus", "not an integer"); |
1433 } | 1401 } |
1434 if (e < 0) throw new RangeError.range(e, 0, null, "exponent"); | 1402 if (e < 0) throw new RangeError.range(e, 0, null, "exponent"); |
1435 if (m <= 0) throw new RangeError.range(m, 1, null, "modulus"); | 1403 if (m <= 0) throw new RangeError.range(m, 1, null, "modulus"); |
1436 if (e == 0) return 1; | 1404 if (e == 0) return 1; |
1437 m = m._toBigint(); | 1405 m = m._toBigint(); |
1438 final m_used = m._used; | 1406 final m_used = m._used; |
1439 final m_used2p4 = 2 * m_used + 4; | 1407 final m_used2p4 = 2 * m_used + 4; |
1440 final e_bitlen = e.bitLength; | 1408 final e_bitlen = e.bitLength; |
1441 if (e_bitlen <= 0) return 1; | 1409 if (e_bitlen <= 0) return 1; |
1442 final bool cannotUseMontgomery = m.isEven || _abs() >= m; | 1410 final bool cannotUseMontgomery = m.isEven || _abs() >= m; |
1443 if (cannotUseMontgomery || e_bitlen < 64) { | 1411 if (cannotUseMontgomery || e_bitlen < 64) { |
1444 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) | 1412 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) ? |
1445 ? new _Classic(m) | 1413 new _Classic(m) : new _Montgomery(m); |
1446 : new _Montgomery(m); | |
1447 // TODO(regis): Should we use Barrett reduction for an even modulus and a | 1414 // TODO(regis): Should we use Barrett reduction for an even modulus and a |
1448 // large exponent? | 1415 // large exponent? |
1449 var r_digits = new Uint32List(m_used2p4); | 1416 var r_digits = new Uint32List(m_used2p4); |
1450 var r2_digits = new Uint32List(m_used2p4); | 1417 var r2_digits = new Uint32List(m_used2p4); |
1451 var g_digits = new Uint32List(m_used + (m_used & 1)); | 1418 var g_digits = new Uint32List(m_used + (m_used & 1)); |
1452 var g_used = z._convert(this, g_digits); | 1419 var g_used = z._convert(this, g_digits); |
1453 // Initialize r with g. | 1420 // Initialize r with g. |
1454 var j = g_used + (g_used & 1); // Copy leading zero if any. | 1421 var j = g_used + (g_used & 1); // Copy leading zero if any. |
1455 while (--j >= 0) { | 1422 while (--j >= 0) { |
1456 r_digits[j] = g_digits[j]; | 1423 r_digits[j] = g_digits[j]; |
1457 } | 1424 } |
1458 var r_used = g_used; | 1425 var r_used = g_used; |
1459 var r2_used; | 1426 var r2_used; |
1460 var i = e_bitlen - 1; | 1427 var i = e_bitlen - 1; |
1461 while (--i >= 0) { | 1428 while (--i >= 0) { |
1462 r2_used = z._sqr(r_digits, r_used, r2_digits); | 1429 r2_used = z._sqr(r_digits, r_used, r2_digits); |
1463 if ((e & (1 << i)) != 0) { | 1430 if ((e & (1 << i)) != 0) { |
1464 r_used = z._mul(r2_digits, r2_used, g_digits, g_used, r_digits); | 1431 r_used = z._mul(r2_digits, r2_used, g_digits, g_used, r_digits); |
1465 } else { | 1432 } else { |
1466 var t_digits = r_digits; | 1433 var t_digits = r_digits; |
1467 var t_used = r_used; | 1434 var t_used = r_used; |
1468 r_digits = r2_digits; | 1435 r_digits = r2_digits; |
1469 r_used = r2_used; | 1436 r_used = r2_used; |
1470 r2_digits = t_digits; | 1437 r2_digits = t_digits; |
1471 r2_used = t_used; | 1438 r2_used = t_used; |
1472 } | 1439 } |
1473 } | 1440 } |
1474 return z._revert(r_digits, r_used)._toValidInt(); | 1441 return z._revert(r_digits, r_used)._toValidInt(); |
1475 } | 1442 } |
1476 e = e._toBigint(); | 1443 e = e._toBigint(); |
1477 var k; | 1444 var k; |
1478 if (e_bitlen < 18) | 1445 if (e_bitlen < 18) k = 1; |
1479 k = 1; | 1446 else if (e_bitlen < 48) k = 3; |
1480 else if (e_bitlen < 48) | 1447 else if (e_bitlen < 144) k = 4; |
1481 k = 3; | 1448 else if (e_bitlen < 768) k = 5; |
1482 else if (e_bitlen < 144) | 1449 else k = 6; |
1483 k = 4; | |
1484 else if (e_bitlen < 768) | |
1485 k = 5; | |
1486 else | |
1487 k = 6; | |
1488 _Reduction z = new _Montgomery(m); | 1450 _Reduction z = new _Montgomery(m); |
1489 var n = 3; | 1451 var n = 3; |
1490 final k1 = k - 1; | 1452 final k1 = k - 1; |
1491 final km = (1 << k) - 1; | 1453 final km = (1 << k) - 1; |
1492 List g_digits = new List(km + 1); | 1454 List g_digits = new List(km + 1); |
1493 List g_used = new List(km + 1); | 1455 List g_used = new List(km + 1); |
1494 g_digits[1] = new Uint32List(m_used + (m_used & 1)); | 1456 g_digits[1] = new Uint32List(m_used + (m_used & 1)); |
1495 g_used[1] = z._convert(this, g_digits[1]); | 1457 g_used[1] = z._convert(this, g_digits[1]); |
1496 if (k > 1) { | 1458 if (k > 1) { |
1497 var g2_digits = new Uint32List(m_used2p4); | 1459 var g2_digits = new Uint32List(m_used2p4); |
1498 var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits); | 1460 var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits); |
1499 while (n <= km) { | 1461 while (n <= km) { |
1500 g_digits[n] = new Uint32List(m_used2p4); | 1462 g_digits[n] = new Uint32List(m_used2p4); |
1501 g_used[n] = z._mul( | 1463 g_used[n] = z._mul(g2_digits, g2_used, |
1502 g2_digits, g2_used, g_digits[n - 2], g_used[n - 2], g_digits[n]); | 1464 g_digits[n - 2], g_used[n - 2], |
| 1465 g_digits[n]); |
1503 n += 2; | 1466 n += 2; |
1504 } | 1467 } |
1505 } | 1468 } |
1506 var w; | 1469 var w; |
1507 var is1 = true; | 1470 var is1 = true; |
1508 var r_digits = _ONE._digits; | 1471 var r_digits = _ONE._digits; |
1509 var r_used = _ONE._used; | 1472 var r_used = _ONE._used; |
1510 var r2_digits = new Uint32List(m_used2p4); | 1473 var r2_digits = new Uint32List(m_used2p4); |
1511 var r2_used; | 1474 var r2_used; |
1512 var e_digits = e._digits; | 1475 var e_digits = e._digits; |
(...skipping 10 matching lines...) Expand all Loading... |
1523 } | 1486 } |
1524 n = k; | 1487 n = k; |
1525 while ((w & 1) == 0) { | 1488 while ((w & 1) == 0) { |
1526 w >>= 1; | 1489 w >>= 1; |
1527 --n; | 1490 --n; |
1528 } | 1491 } |
1529 if ((i -= n) < 0) { | 1492 if ((i -= n) < 0) { |
1530 i += _DIGIT_BITS; | 1493 i += _DIGIT_BITS; |
1531 --j; | 1494 --j; |
1532 } | 1495 } |
1533 if (is1) { | 1496 if (is1) { // r == 1, don't bother squaring or multiplying it. |
1534 // r == 1, don't bother squaring or multiplying it. | |
1535 r_digits = new Uint32List(m_used2p4); | 1497 r_digits = new Uint32List(m_used2p4); |
1536 r_used = g_used[w]; | 1498 r_used = g_used[w]; |
1537 var gw_digits = g_digits[w]; | 1499 var gw_digits = g_digits[w]; |
1538 var ri = r_used + (r_used & 1); // Copy leading zero if any. | 1500 var ri = r_used + (r_used & 1); // Copy leading zero if any. |
1539 while (--ri >= 0) { | 1501 while (--ri >= 0) { |
1540 r_digits[ri] = gw_digits[ri]; | 1502 r_digits[ri] = gw_digits[ri]; |
1541 } | 1503 } |
1542 is1 = false; | 1504 is1 = false; |
1543 } else { | 1505 } |
| 1506 else { |
1544 while (n > 1) { | 1507 while (n > 1) { |
1545 r2_used = z._sqr(r_digits, r_used, r2_digits); | 1508 r2_used = z._sqr(r_digits, r_used, r2_digits); |
1546 r_used = z._sqr(r2_digits, r2_used, r_digits); | 1509 r_used = z._sqr(r2_digits, r2_used, r_digits); |
1547 n -= 2; | 1510 n -= 2; |
1548 } | 1511 } |
1549 if (n > 0) { | 1512 if (n > 0) { |
1550 r2_used = z._sqr(r_digits, r_used, r2_digits); | 1513 r2_used = z._sqr(r_digits, r_used, r2_digits); |
1551 } else { | 1514 } else { |
1552 var t_digits = r_digits; | 1515 var t_digits = r_digits; |
1553 var t_used = r_used; | 1516 var t_used = r_used; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1618 if ((y_digits[0] & 1) == 1) { | 1581 if ((y_digits[0] & 1) == 1) { |
1619 var t_digits = x_digits; | 1582 var t_digits = x_digits; |
1620 var t_used = x_used; | 1583 var t_used = x_used; |
1621 x_digits = y_digits; | 1584 x_digits = y_digits; |
1622 x_used = y_used; | 1585 x_used = y_used; |
1623 y_digits = t_digits; | 1586 y_digits = t_digits; |
1624 y_used = t_used; | 1587 y_used = t_used; |
1625 } | 1588 } |
1626 } | 1589 } |
1627 var u_digits = _cloneDigits(x_digits, 0, x_used, m_len); | 1590 var u_digits = _cloneDigits(x_digits, 0, x_used, m_len); |
1628 var v_digits = _cloneDigits(y_digits, 0, y_used, m_len + 2); // +2 for lsh. | 1591 var v_digits = _cloneDigits(y_digits, 0, y_used, m_len + 2); // +2 for lsh. |
1629 final bool ac = (x_digits[0] & 1) == 0; | 1592 final bool ac = (x_digits[0] & 1) == 0; |
1630 | 1593 |
1631 // Variables a, b, c, and d require one more digit. | 1594 // Variables a, b, c, and d require one more digit. |
1632 final abcd_used = m_used + 1; | 1595 final abcd_used = m_used + 1; |
1633 final abcd_len = abcd_used + (abcd_used & 1) + 2; // +2 to satisfy _absAdd. | 1596 final abcd_len = abcd_used + (abcd_used & 1) + 2; // +2 to satisfy _absAdd. |
1634 var a_digits, b_digits, c_digits, d_digits; | 1597 var a_digits, b_digits, c_digits, d_digits; |
1635 bool a_neg, b_neg, c_neg, d_neg; | 1598 bool a_neg, b_neg, c_neg, d_neg; |
1636 if (ac) { | 1599 if (ac) { |
1637 a_digits = new Uint32List(abcd_len); | 1600 a_digits = new Uint32List(abcd_len); |
1638 a_neg = false; | 1601 a_neg = false; |
1639 a_digits[0] = 1; | 1602 a_digits[0] = 1; |
1640 c_digits = new Uint32List(abcd_len); | 1603 c_digits = new Uint32List(abcd_len); |
1641 c_neg = false; | 1604 c_neg = false; |
1642 } | 1605 } |
1643 b_digits = new Uint32List(abcd_len); | 1606 b_digits = new Uint32List(abcd_len); |
(...skipping 26 matching lines...) Expand all Loading... |
1670 } else { | 1633 } else { |
1671 _absSub(x_digits, m_used, b_digits, m_used, b_digits); | 1634 _absSub(x_digits, m_used, b_digits, m_used, b_digits); |
1672 b_neg = true; | 1635 b_neg = true; |
1673 } | 1636 } |
1674 } | 1637 } |
1675 _rsh(a_digits, abcd_used, 1, a_digits); | 1638 _rsh(a_digits, abcd_used, 1, a_digits); |
1676 } else if ((b_digits[0] & 1) == 1) { | 1639 } else if ((b_digits[0] & 1) == 1) { |
1677 if (b_neg) { | 1640 if (b_neg) { |
1678 _absAdd(b_digits, abcd_used, x_digits, m_used, b_digits); | 1641 _absAdd(b_digits, abcd_used, x_digits, m_used, b_digits); |
1679 } else if ((b_digits[m_used] != 0) || | 1642 } else if ((b_digits[m_used] != 0) || |
1680 (_compareDigits(b_digits, m_used, x_digits, m_used) > 0)) { | 1643 (_compareDigits(b_digits, m_used, x_digits, m_used) > 0)) { |
1681 _absSub(b_digits, abcd_used, x_digits, m_used, b_digits); | 1644 _absSub(b_digits, abcd_used, x_digits, m_used, b_digits); |
1682 } else { | 1645 } else { |
1683 _absSub(x_digits, m_used, b_digits, m_used, b_digits); | 1646 _absSub(x_digits, m_used, b_digits, m_used, b_digits); |
1684 b_neg = true; | 1647 b_neg = true; |
1685 } | 1648 } |
1686 } | 1649 } |
1687 _rsh(b_digits, abcd_used, 1, b_digits); | 1650 _rsh(b_digits, abcd_used, 1, b_digits); |
1688 } | 1651 } |
1689 while ((v_digits[0] & 1) == 0) { | 1652 while ((v_digits[0] & 1) == 0) { |
1690 _rsh(v_digits, m_used, 1, v_digits); | 1653 _rsh(v_digits, m_used, 1, v_digits); |
(...skipping 18 matching lines...) Expand all Loading... |
1709 } else { | 1672 } else { |
1710 _absSub(x_digits, m_used, d_digits, m_used, d_digits); | 1673 _absSub(x_digits, m_used, d_digits, m_used, d_digits); |
1711 d_neg = true; | 1674 d_neg = true; |
1712 } | 1675 } |
1713 } | 1676 } |
1714 _rsh(c_digits, abcd_used, 1, c_digits); | 1677 _rsh(c_digits, abcd_used, 1, c_digits); |
1715 } else if ((d_digits[0] & 1) == 1) { | 1678 } else if ((d_digits[0] & 1) == 1) { |
1716 if (d_neg) { | 1679 if (d_neg) { |
1717 _absAdd(d_digits, abcd_used, x_digits, m_used, d_digits); | 1680 _absAdd(d_digits, abcd_used, x_digits, m_used, d_digits); |
1718 } else if ((d_digits[m_used] != 0) || | 1681 } else if ((d_digits[m_used] != 0) || |
1719 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1682 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
1720 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1683 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
1721 } else { | 1684 } else { |
1722 _absSub(x_digits, m_used, d_digits, m_used, d_digits); | 1685 _absSub(x_digits, m_used, d_digits, m_used, d_digits); |
1723 d_neg = true; | 1686 d_neg = true; |
1724 } | 1687 } |
1725 } | 1688 } |
1726 _rsh(d_digits, abcd_used, 1, d_digits); | 1689 _rsh(d_digits, abcd_used, 1, d_digits); |
1727 } | 1690 } |
1728 if (_compareDigits(u_digits, m_used, v_digits, m_used) >= 0) { | 1691 if (_compareDigits(u_digits, m_used, v_digits, m_used) >= 0) { |
1729 _absSub(u_digits, m_used, v_digits, m_used, u_digits); | 1692 _absSub(u_digits, m_used, v_digits, m_used, u_digits); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1809 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1772 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
1810 } else { | 1773 } else { |
1811 _absSub(x_digits, m_used, d_digits, m_used, d_digits); | 1774 _absSub(x_digits, m_used, d_digits, m_used, d_digits); |
1812 d_neg = false; | 1775 d_neg = false; |
1813 } | 1776 } |
1814 } else { | 1777 } else { |
1815 _absSub(x_digits, m_used, d_digits, m_used, d_digits); | 1778 _absSub(x_digits, m_used, d_digits, m_used, d_digits); |
1816 d_neg = false; | 1779 d_neg = false; |
1817 } | 1780 } |
1818 } else if ((d_digits[m_used] != 0) || | 1781 } else if ((d_digits[m_used] != 0) || |
1819 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1782 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
1820 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1783 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
1821 if ((d_digits[m_used] != 0) || | 1784 if ((d_digits[m_used] != 0) || |
1822 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1785 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
1823 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1786 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
1824 } | 1787 } |
1825 } | 1788 } |
1826 return new _Bigint(false, m_used, d_digits)._toValidInt(); | 1789 return new _Bigint(false, m_used, d_digits)._toValidInt(); |
1827 } | 1790 } |
1828 | 1791 |
1829 // Returns 1/this % m, with m > 0. | 1792 // Returns 1/this % m, with m > 0. |
(...skipping 21 matching lines...) Expand all Loading... |
1851 return this.abs(); | 1814 return this.abs(); |
1852 } | 1815 } |
1853 return _binaryGcd(this, other._toBigint(), false); | 1816 return _binaryGcd(this, other._toBigint(), false); |
1854 } | 1817 } |
1855 } | 1818 } |
1856 | 1819 |
1857 // Interface for modular reduction. | 1820 // Interface for modular reduction. |
1858 class _Reduction { | 1821 class _Reduction { |
1859 // Return the number of digits used by r_digits. | 1822 // Return the number of digits used by r_digits. |
1860 int _convert(_Bigint x, Uint32List r_digits); | 1823 int _convert(_Bigint x, Uint32List r_digits); |
1861 int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used, | 1824 int _mul(Uint32List x_digits, int x_used, |
1862 Uint32List r_digits); | 1825 Uint32List y_digits, int y_used, Uint32List r_digits); |
1863 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits); | 1826 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits); |
1864 | 1827 |
1865 // Return x reverted to _Bigint. | 1828 // Return x reverted to _Bigint. |
1866 _Bigint _revert(Uint32List x_digits, int x_used); | 1829 _Bigint _revert(Uint32List x_digits, int x_used); |
1867 } | 1830 } |
1868 | 1831 |
1869 // Montgomery reduction on _Bigint. | 1832 // Montgomery reduction on _Bigint. |
1870 class _Montgomery implements _Reduction { | 1833 class _Montgomery implements _Reduction { |
1871 _Bigint _m; // Modulus. | 1834 _Bigint _m; // Modulus. |
1872 int _mused2p2; | 1835 int _mused2p2; |
1873 Uint32List _args; | 1836 Uint32List _args; |
1874 int _digits_per_step; // Number of digits processed in one step. 1 or 2. | 1837 int _digits_per_step; // Number of digits processed in one step. 1 or 2. |
1875 static const int _X = 0; // Index of x. | 1838 static const int _X = 0; // Index of x. |
1876 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only). | 1839 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only). |
1877 static const int _RHO = 2; // Index of rho. | 1840 static const int _RHO = 2; // Index of rho. |
1878 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only). | 1841 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only). |
1879 static const int _MU = 4; // Index of mu. | 1842 static const int _MU = 4; // Index of mu. |
1880 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only). | 1843 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only). |
1881 | 1844 |
1882 _Montgomery(m) { | 1845 _Montgomery(m) { |
1883 _m = m._toBigint(); | 1846 _m = m._toBigint(); |
1884 _mused2p2 = 2 * _m._used + 2; | 1847 _mused2p2 = 2*_m._used + 2; |
1885 _args = new Uint32List(6); | 1848 _args = new Uint32List(6); |
1886 // Determine if we can process digit pairs by calling an intrinsic. | 1849 // Determine if we can process digit pairs by calling an intrinsic. |
1887 _digits_per_step = _mulMod(_args, _args, 0); | 1850 _digits_per_step = _mulMod(_args, _args, 0); |
1888 _args[_X] = _m._digits[0]; | 1851 _args[_X] = _m._digits[0]; |
1889 if (_digits_per_step == 1) { | 1852 if (_digits_per_step == 1) { |
1890 _invDigit(_args); | 1853 _invDigit(_args); |
1891 } else { | 1854 } else { |
1892 assert(_digits_per_step == 2); | 1855 assert(_digits_per_step == 2); |
1893 _args[_X_HI] = _m._digits[1]; | 1856 _args[_X_HI] = _m._digits[1]; |
1894 _invDigitPair(_args); | 1857 _invDigitPair(_args); |
1895 } | 1858 } |
1896 } | 1859 } |
1897 | 1860 |
1898 // Calculates -1/x % _DIGIT_BASE, x is 32-bit digit. | 1861 // Calculates -1/x % _DIGIT_BASE, x is 32-bit digit. |
1899 // xy == 1 (mod m) | 1862 // xy == 1 (mod m) |
1900 // xy = 1+km | 1863 // xy = 1+km |
1901 // xy(2-xy) = (1+km)(1-km) | 1864 // xy(2-xy) = (1+km)(1-km) |
1902 // x(y(2-xy)) = 1-k^2 m^2 | 1865 // x(y(2-xy)) = 1-k^2 m^2 |
1903 // x(y(2-xy)) == 1 (mod m^2) | 1866 // x(y(2-xy)) == 1 (mod m^2) |
1904 // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 | 1867 // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 |
1905 // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded. | 1868 // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded. |
1906 // | 1869 // |
1907 // Operation: | 1870 // Operation: |
1908 // args[_RHO] = 1/args[_X] mod _DIGIT_BASE. | 1871 // args[_RHO] = 1/args[_X] mod _DIGIT_BASE. |
1909 static void _invDigit(Uint32List args) { | 1872 static void _invDigit(Uint32List args) { |
1910 var x = args[_X]; | 1873 var x = args[_X]; |
1911 var y = x & 3; // y == 1/x mod 2^2 | 1874 var y = x & 3; // y == 1/x mod 2^2 |
1912 y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4 | 1875 y = (y*(2 - (x & 0xf)*y)) & 0xf; // y == 1/x mod 2^4 |
1913 y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8 | 1876 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 |
1914 y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 | 1877 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 |
1915 // Last step - calculate inverse mod _DIGIT_BASE directly; | 1878 // Last step - calculate inverse mod _DIGIT_BASE directly; |
1916 // Assumes 16 < _DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. | 1879 // Assumes 16 < _DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. |
1917 y = (y * (2 - x * y % _Bigint._DIGIT_BASE)) % _Bigint._DIGIT_BASE; | 1880 y = (y*(2 - x*y % _Bigint._DIGIT_BASE)) % _Bigint._DIGIT_BASE; |
1918 // y == 1/x mod _DIGIT_BASE | 1881 // y == 1/x mod _DIGIT_BASE |
1919 y = -y; // We really want the negative inverse. | 1882 y = -y; // We really want the negative inverse. |
1920 args[_RHO] = y & _Bigint._DIGIT_MASK; | 1883 args[_RHO] = y & _Bigint._DIGIT_MASK; |
1921 } | 1884 } |
1922 | 1885 |
1923 // Calculates -1/x % _DIGIT_BASE^2, x is a pair of 32-bit digits. | 1886 // Calculates -1/x % _DIGIT_BASE^2, x is a pair of 32-bit digits. |
1924 // Operation: | 1887 // Operation: |
1925 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod _DIGIT_BASE^2. | 1888 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod _DIGIT_BASE^2. |
1926 static void _invDigitPair(Uint32List args) { | 1889 static void _invDigitPair(Uint32List args) { |
1927 var xl = args[_X]; // Lower 32-bit digit of x. | 1890 var xl = args[_X]; // Lower 32-bit digit of x. |
1928 var y = xl & 3; // y == 1/x mod 2^2 | 1891 var y = xl & 3; // y == 1/x mod 2^2 |
1929 y = (y * (2 - (xl & 0xf) * y)) & 0xf; // y == 1/x mod 2^4 | 1892 y = (y*(2 - (xl & 0xf)*y)) & 0xf; // y == 1/x mod 2^4 |
1930 y = (y * (2 - (xl & 0xff) * y)) & 0xff; // y == 1/x mod 2^8 | 1893 y = (y*(2 - (xl & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 |
1931 y = (y * (2 - (((xl & 0xffff) * y) & 0xffff))) & | 1894 y = (y*(2 - (((xl & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 |
1932 0xffff; // y == 1/x mod 2^16 | 1895 y = (y*(2 - ((xl*y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32 |
1933 y = (y * (2 - ((xl * y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32 | |
1934 var x = (args[_X_HI] << _Bigint._DIGIT_BITS) | xl; | 1896 var x = (args[_X_HI] << _Bigint._DIGIT_BITS) | xl; |
1935 y = (y * (2 - ((x * y) & 0xffffffffffffffff))) & 0xffffffffffffffff; | 1897 y = (y*(2 - ((x*y) & 0xffffffffffffffff))) & 0xffffffffffffffff; |
1936 // y == 1/x mod _DIGIT_BASE^2 | 1898 // y == 1/x mod _DIGIT_BASE^2 |
1937 y = -y; // We really want the negative inverse. | 1899 y = -y; // We really want the negative inverse. |
1938 args[_RHO] = y & _Bigint._DIGIT_MASK; | 1900 args[_RHO] = y & _Bigint._DIGIT_MASK; |
1939 args[_RHO_HI] = (y >> _Bigint._DIGIT_BITS) & _Bigint._DIGIT_MASK; | 1901 args[_RHO_HI] = (y >> _Bigint._DIGIT_BITS) & _Bigint._DIGIT_MASK; |
1940 } | 1902 } |
1941 | 1903 |
1942 // Operation: | 1904 // Operation: |
1943 // args[_MU] = args[_RHO]*digits[i] mod _DIGIT_BASE. | 1905 // args[_MU] = args[_RHO]*digits[i] mod _DIGIT_BASE. |
1944 // return 1. | 1906 // return 1. |
1945 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices: | 1907 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices: |
1946 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod _DIGIT_BASE^2. | 1908 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod _DIGIT_BASE^2. |
1947 // return 2. | 1909 // return 2. |
1948 static int _mulMod(Uint32List args, Uint32List digits, int i) { | 1910 static int _mulMod(Uint32List args, Uint32List digits, int i) { |
1949 // Verify that digit pairs are accessible for 64-bit processing. | 1911 // Verify that digit pairs are accessible for 64-bit processing. |
1950 assert(digits.length > (i | 1)); | 1912 assert(digits.length > (i | 1)); |
1951 const int MU_MASK = (1 << (_Bigint._DIGIT_BITS - _Bigint._DIGIT2_BITS)) - 1; | 1913 const int MU_MASK = (1 << (_Bigint._DIGIT_BITS - _Bigint._DIGIT2_BITS)) - 1; |
1952 var rhol = args[_RHO] & _Bigint._DIGIT2_MASK; | 1914 var rhol = args[_RHO] & _Bigint._DIGIT2_MASK; |
1953 var rhoh = args[_RHO] >> _Bigint._DIGIT2_BITS; | 1915 var rhoh = args[_RHO] >> _Bigint._DIGIT2_BITS; |
1954 var dh = digits[i] >> _Bigint._DIGIT2_BITS; | 1916 var dh = digits[i] >> _Bigint._DIGIT2_BITS; |
1955 var dl = digits[i] & _Bigint._DIGIT2_MASK; | 1917 var dl = digits[i] & _Bigint._DIGIT2_MASK; |
1956 args[_MU] = (dl * rhol + | 1918 args[_MU] = |
1957 (((dl * rhoh + dh * rhol) & MU_MASK) << _Bigint._DIGIT2_BITS)) & | 1919 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint._DIGIT2_BITS)) |
1958 _Bigint._DIGIT_MASK; | 1920 & _Bigint._DIGIT_MASK; |
1959 return 1; | 1921 return 1; |
1960 } | 1922 } |
1961 | 1923 |
1962 // r = x*R mod _m. | 1924 // r = x*R mod _m. |
1963 // Return r_used. | 1925 // Return r_used. |
1964 int _convert(_Bigint x, Uint32List r_digits) { | 1926 int _convert(_Bigint x, Uint32List r_digits) { |
1965 // Montgomery reduction only works if abs(x) < _m. | 1927 // Montgomery reduction only works if abs(x) < _m. |
1966 assert(x._abs() < _m); | 1928 assert(x._abs() < _m); |
1967 var r = x._abs()._dlShift(_m._used)._rem(_m); | 1929 var r = x._abs()._dlShift(_m._used)._rem(_m); |
1968 if (x._neg && !r._neg && r._used > 0) { | 1930 if (x._neg && !r._neg && r._used > 0) { |
(...skipping 14 matching lines...) Expand all Loading... |
1983 while (--i >= 0) { | 1945 while (--i >= 0) { |
1984 r_digits[i] = x_digits[i]; | 1946 r_digits[i] = x_digits[i]; |
1985 } | 1947 } |
1986 var r_used = _reduce(r_digits, x_used); | 1948 var r_used = _reduce(r_digits, x_used); |
1987 return new _Bigint(false, r_used, r_digits); | 1949 return new _Bigint(false, r_used, r_digits); |
1988 } | 1950 } |
1989 | 1951 |
1990 // x = x/R mod _m. | 1952 // x = x/R mod _m. |
1991 // Return x_used. | 1953 // Return x_used. |
1992 int _reduce(Uint32List x_digits, int x_used) { | 1954 int _reduce(Uint32List x_digits, int x_used) { |
1993 while (x_used < _mused2p2) { | 1955 while (x_used < _mused2p2) { // Pad x so _mulAdd has enough room later. |
1994 // Pad x so _mulAdd has enough room later. | |
1995 x_digits[x_used++] = 0; | 1956 x_digits[x_used++] = 0; |
1996 } | 1957 } |
1997 var m_used = _m._used; | 1958 var m_used = _m._used; |
1998 var m_digits = _m._digits; | 1959 var m_digits = _m._digits; |
1999 var i = 0; | 1960 var i = 0; |
2000 while (i < m_used) { | 1961 while (i < m_used) { |
2001 var d = _mulMod(_args, x_digits, i); | 1962 var d = _mulMod(_args, x_digits, i); |
2002 assert(d == _digits_per_step); | 1963 assert(d == _digits_per_step); |
2003 d = _Bigint._mulAdd(_args, _MU, m_digits, 0, x_digits, i, m_used); | 1964 d = _Bigint._mulAdd(_args, _MU, m_digits, 0, x_digits, i, m_used); |
2004 assert(d == _digits_per_step); | 1965 assert(d == _digits_per_step); |
(...skipping 13 matching lines...) Expand all Loading... |
2018 --x_used; | 1979 --x_used; |
2019 } | 1980 } |
2020 return x_used; | 1981 return x_used; |
2021 } | 1982 } |
2022 | 1983 |
2023 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) { | 1984 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) { |
2024 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits); | 1985 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits); |
2025 return _reduce(r_digits, r_used); | 1986 return _reduce(r_digits, r_used); |
2026 } | 1987 } |
2027 | 1988 |
2028 int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used, | 1989 int _mul(Uint32List x_digits, int x_used, |
2029 Uint32List r_digits) { | 1990 Uint32List y_digits, int y_used, |
2030 var r_used = | 1991 Uint32List r_digits) { |
2031 _Bigint._mulDigits(x_digits, x_used, y_digits, y_used, r_digits); | 1992 var r_used = _Bigint._mulDigits(x_digits, x_used, |
| 1993 y_digits, y_used, |
| 1994 r_digits); |
2032 return _reduce(r_digits, r_used); | 1995 return _reduce(r_digits, r_used); |
2033 } | 1996 } |
2034 } | 1997 } |
2035 | 1998 |
2036 // Modular reduction using "classic" algorithm. | 1999 // Modular reduction using "classic" algorithm. |
2037 class _Classic implements _Reduction { | 2000 class _Classic implements _Reduction { |
2038 _Bigint _m; // Modulus. | 2001 _Bigint _m; // Modulus. |
2039 _Bigint _norm_m; // Normalized _m. | 2002 _Bigint _norm_m; // Normalized _m. |
2040 Uint32List _neg_norm_m_digits; // Negated _norm_m digits. | 2003 Uint32List _neg_norm_m_digits; // Negated _norm_m digits. |
2041 int _m_nsh; // Normalization shift amount. | 2004 int _m_nsh; // Normalization shift amount. |
2042 Uint32List _mt_qd; // Top _norm_m digit(s) and place holder for | 2005 Uint32List _mt_qd; // Top _norm_m digit(s) and place holder for |
2043 // estimated quotient digit(s). | 2006 // estimated quotient digit(s). |
2044 Uint32List _t_digits; // Temporary digits used during reduction. | 2007 Uint32List _t_digits; // Temporary digits used during reduction. |
2045 | 2008 |
2046 _Classic(int m) { | 2009 _Classic(int m) { |
2047 _m = m._toBigint(); | 2010 _m = m._toBigint(); |
2048 // Preprocess arguments to _remDigits. | 2011 // Preprocess arguments to _remDigits. |
2049 var nsh = _Bigint._DIGIT_BITS - _Bigint._nbits(_m._digits[_m._used - 1]); | 2012 var nsh = _Bigint._DIGIT_BITS - _Bigint._nbits(_m._digits[_m._used - 1]); |
2050 // For 64-bit processing, make sure _norm_m_digits has an even number of | 2013 // For 64-bit processing, make sure _norm_m_digits has an even number of |
2051 // digits. | 2014 // digits. |
2052 if (_m._used.isOdd) { | 2015 if (_m._used.isOdd) { |
2053 nsh += _Bigint._DIGIT_BITS; | 2016 nsh += _Bigint._DIGIT_BITS; |
2054 } | 2017 } |
2055 _m_nsh = nsh; | 2018 _m_nsh = nsh; |
2056 _norm_m = _m._lShift(nsh); | 2019 _norm_m = _m._lShift(nsh); |
2057 var nm_used = _norm_m._used; | 2020 var nm_used = _norm_m._used; |
2058 assert(nm_used.isEven); | 2021 assert(nm_used.isEven); |
2059 _mt_qd = new Uint32List(4); | 2022 _mt_qd = new Uint32List(4); |
2060 _mt_qd[_Bigint._YT_LO] = _norm_m._digits[nm_used - 2]; | 2023 _mt_qd[_Bigint._YT_LO] = _norm_m._digits[nm_used - 2]; |
2061 _mt_qd[_Bigint._YT] = _norm_m._digits[nm_used - 1]; | 2024 _mt_qd[_Bigint._YT] = _norm_m._digits[nm_used - 1]; |
2062 // Negate _norm_m so we can use _mulAdd instead of unimplemented _mulSub. | 2025 // Negate _norm_m so we can use _mulAdd instead of unimplemented _mulSub. |
2063 var neg_norm_m = _Bigint._ONE._dlShift(nm_used)._sub(_norm_m); | 2026 var neg_norm_m = _Bigint._ONE._dlShift(nm_used)._sub(_norm_m); |
2064 if (neg_norm_m._used < nm_used) { | 2027 if (neg_norm_m._used < nm_used) { |
2065 _neg_norm_m_digits = | 2028 _neg_norm_m_digits = |
2066 _Bigint._cloneDigits(neg_norm_m._digits, 0, nm_used, nm_used); | 2029 _Bigint._cloneDigits(neg_norm_m._digits, 0, nm_used, nm_used); |
2067 } else { | 2030 } else { |
2068 _neg_norm_m_digits = neg_norm_m._digits; | 2031 _neg_norm_m_digits = neg_norm_m._digits; |
2069 } | 2032 } |
2070 // _neg_norm_m_digits is read-only and has nm_used digits (possibly | 2033 // _neg_norm_m_digits is read-only and has nm_used digits (possibly |
2071 // including several leading zeros) plus a leading zero for 64-bit | 2034 // including several leading zeros) plus a leading zero for 64-bit |
2072 // processing. | 2035 // processing. |
2073 _t_digits = new Uint32List(2 * nm_used); | 2036 _t_digits = new Uint32List(2*nm_used); |
2074 } | 2037 } |
2075 | 2038 |
2076 int _convert(_Bigint x, Uint32List r_digits) { | 2039 int _convert(_Bigint x, Uint32List r_digits) { |
2077 var digits; | 2040 var digits; |
2078 var used; | 2041 var used; |
2079 if (x._neg || x._compare(_m) >= 0) { | 2042 if (x._neg || x._compare(_m) >= 0) { |
2080 var r = x._rem(_m); | 2043 var r = x._rem(_m); |
2081 if (x._neg && !r._neg && r._used > 0) { | 2044 if (x._neg && !r._neg && r._used > 0) { |
2082 r = _m._sub(r); | 2045 r = _m._sub(r); |
2083 } | 2046 } |
2084 assert(!r._neg); | 2047 assert(!r._neg); |
2085 used = r._used; | 2048 used = r._used; |
2086 digits = r._digits; | 2049 digits = r._digits; |
2087 } else { | 2050 } else { |
2088 used = x._used; | 2051 used = x._used; |
2089 digits = x._digits; | 2052 digits = x._digits; |
2090 } | 2053 } |
2091 var i = used + (used & 1); // Copy leading zero if any. | 2054 var i = used + (used & 1); // Copy leading zero if any. |
2092 while (--i >= 0) { | 2055 while (--i >= 0) { |
2093 r_digits[i] = digits[i]; | 2056 r_digits[i] = digits[i]; |
2094 } | 2057 } |
2095 return used; | 2058 return used; |
2096 } | 2059 } |
2097 | 2060 |
2098 _Bigint _revert(Uint32List x_digits, int x_used) { | 2061 _Bigint _revert(Uint32List x_digits, int x_used) { |
2099 return new _Bigint(false, x_used, x_digits); | 2062 return new _Bigint(false, x_used, x_digits); |
2100 } | 2063 } |
2101 | 2064 |
2102 int _reduce(Uint32List x_digits, int x_used) { | 2065 int _reduce(Uint32List x_digits, int x_used) { |
2103 if (x_used < _m._used) { | 2066 if (x_used < _m._used) { |
2104 return x_used; | 2067 return x_used; |
2105 } | 2068 } |
2106 // The function _remDigits(...) is optimized for reduction and equivalent to | 2069 // The function _remDigits(...) is optimized for reduction and equivalent to |
2107 // calling _convert(_revert(x_digits, x_used)._rem(_m), x_digits); | 2070 // calling _convert(_revert(x_digits, x_used)._rem(_m), x_digits); |
2108 return _Bigint._remDigits(x_digits, x_used, _norm_m._digits, _norm_m._used, | 2071 return _Bigint._remDigits(x_digits, x_used, |
2109 _neg_norm_m_digits, _m_nsh, _mt_qd, _t_digits, x_digits); | 2072 _norm_m._digits, _norm_m._used, |
| 2073 _neg_norm_m_digits, |
| 2074 _m_nsh, |
| 2075 _mt_qd, |
| 2076 _t_digits, |
| 2077 x_digits); |
2110 } | 2078 } |
2111 | 2079 |
2112 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) { | 2080 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) { |
2113 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits); | 2081 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits); |
2114 return _reduce(r_digits, r_used); | 2082 return _reduce(r_digits, r_used); |
2115 } | 2083 } |
2116 | 2084 |
2117 int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used, | 2085 int _mul(Uint32List x_digits, int x_used, |
2118 Uint32List r_digits) { | 2086 Uint32List y_digits, int y_used, |
2119 var r_used = | 2087 Uint32List r_digits) { |
2120 _Bigint._mulDigits(x_digits, x_used, y_digits, y_used, r_digits); | 2088 var r_used = _Bigint._mulDigits(x_digits, x_used, |
| 2089 y_digits, y_used, |
| 2090 r_digits); |
2121 return _reduce(r_digits, r_used); | 2091 return _reduce(r_digits, r_used); |
2122 } | 2092 } |
2123 } | 2093 } |
OLD | NEW |