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