Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Copyright 2009 The Go Authors. All rights reserved. | 5 // Copyright 2009 The Go Authors. All rights reserved. |
| 6 // Use of this source code is governed by a BSD-style | 6 // Use of this source code is governed by a BSD-style |
| 7 // license that can be found in the LICENSE file. | 7 // license that can be found in the LICENSE file. |
| 8 | 8 |
| 9 /* | 9 /* |
| 10 * Copyright (c) 2003-2005 Tom Wu | 10 * Copyright (c) 2003-2005 Tom Wu |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 return -((digits[1] << DIGIT_BITS) | digits[0]); | 196 return -((digits[1] << DIGIT_BITS) | digits[0]); |
| 197 } | 197 } |
| 198 if (digits[1] >= 0x80000000) return this; | 198 if (digits[1] >= 0x80000000) return this; |
| 199 return (digits[1] << DIGIT_BITS) | digits[0]; | 199 return (digits[1] << DIGIT_BITS) | digits[0]; |
| 200 } | 200 } |
| 201 | 201 |
| 202 // Conversion from int to bigint. | 202 // Conversion from int to bigint. |
| 203 _Bigint _toBigint() => this; | 203 _Bigint _toBigint() => this; |
| 204 | 204 |
| 205 // Make sure at least 'length' _digits are allocated. | 205 // Make sure at least 'length' _digits are allocated. |
| 206 // Copy existing _digits if reallocation is necessary. | 206 // Copy existing and used _digits if reallocation is necessary. |
| 207 // TODO(regis): Check that we are not preserving _digits unnecessarily. | 207 // Avoid preserving _digits unnecessarily by calling this function with a |
| 208 // meaningful _used field. | |
| 208 void _ensureLength(int length) { | 209 void _ensureLength(int length) { |
| 209 var digits = _digits; | 210 var digits = _digits; |
| 210 if (length > 0 && (length > digits.length)) { | 211 if (length > digits.length) { |
| 211 var new_digits = new Uint32List(length + EXTRA_DIGITS); | 212 var new_digits = new Uint32List(length + EXTRA_DIGITS); |
| 212 for (var i = _used; --i >= 0; ) { | 213 _digits = new_digits; |
| 213 new_digits[i] = digits[i]; | 214 if (_used > 0) { |
| 215 for (var i = _used + 1; --i >= 0; ) { // Copy leading zero. | |
|
zra
2014/11/18 19:04:45
So, every number has a leading zero? Even those wi
regis
2014/11/18 23:19:54
Yes, I figured that the _mulAdd intrinsic (among o
| |
| 216 new_digits[i] = digits[i]; | |
| 217 } | |
| 214 } | 218 } |
| 215 _digits = new_digits; | |
| 216 } | 219 } |
| 217 } | 220 } |
| 218 | 221 |
| 219 // Clamp off excess high _digits. | 222 // Clamp off excess high _digits. |
| 220 void _clamp() { | 223 void _clamp() { |
| 221 var digits = _digits; | 224 var used = _used; |
| 222 while (_used > 0 && digits[_used - 1] == 0) { | 225 if (used > 0) { |
| 223 --_used; | 226 var digits = _digits; |
| 227 if (digits[used - 1] == 0) { | |
| 228 do { | |
| 229 --used; | |
| 230 } while (used > 0 && digits[used - 1] == 0); | |
| 231 _used = used; | |
| 232 } | |
| 233 digits[used] = 0; // Set leading zero for 64-bit processing. | |
| 224 } | 234 } |
| 225 } | 235 } |
| 226 | 236 |
| 227 // Copy this to r. | 237 // Copy this to r. |
| 228 void _copyTo(_Bigint r) { | 238 void _copyTo(_Bigint r) { |
| 229 r._ensureLength(_used); | 239 var used = _used; |
| 230 var digits = _digits; | 240 if (used > 0) { |
| 231 var r_digits = r._digits; | 241 r._used = 0; // No digits to preserve. |
| 232 for (var i = _used - 1; i >= 0; --i) { | 242 r._ensureLength(used); |
| 233 r_digits[i] = digits[i]; | 243 var digits = _digits; |
| 244 var r_digits = r._digits; | |
| 245 // Copy leading zero for 64-bit processing. | |
| 246 for (var i = used + 1; --i >= 0; ) { | |
|
zra
2014/11/18 19:04:45
Would a while loop improve readability here?
regis
2014/11/18 23:19:54
Done.
| |
| 247 r_digits[i] = digits[i]; | |
| 248 } | |
| 234 } | 249 } |
| 235 r._used = _used; | 250 r._used = used; |
| 236 r._neg = _neg; | 251 r._neg = _neg; |
| 237 } | 252 } |
| 238 | 253 |
| 239 // Return the bit length of digit x. | 254 // Return the bit length of digit x. |
| 240 int _nbits(int x) { | 255 int _nbits(int x) { |
| 241 var r = 1, t; | 256 var r = 1, t; |
| 242 if ((t = x >> 16) != 0) { x = t; r += 16; } | 257 if ((t = x >> 16) != 0) { x = t; r += 16; } |
| 243 if ((t = x >> 8) != 0) { x = t; r += 8; } | 258 if ((t = x >> 8) != 0) { x = t; r += 8; } |
| 244 if ((t = x >> 4) != 0) { x = t; r += 4; } | 259 if ((t = x >> 4) != 0) { x = t; r += 4; } |
| 245 if ((t = x >> 2) != 0) { x = t; r += 2; } | 260 if ((t = x >> 2) != 0) { x = t; r += 2; } |
| 246 if ((x >> 1) != 0) { r += 1; } | 261 if ((x >> 1) != 0) { r += 1; } |
| 247 return r; | 262 return r; |
| 248 } | 263 } |
| 249 | 264 |
| 250 // r = this << n*DIGIT_BITS. | 265 // r = this << n*DIGIT_BITS. |
| 251 void _dlShiftTo(int n, _Bigint r) { | 266 void _dlShiftTo(int n, _Bigint r) { |
| 252 var r_used = _used + n; | 267 var r_used = _used + n; |
| 253 r._ensureLength(r_used); | 268 r._ensureLength(r_used); |
| 254 var digits = _digits; | 269 var digits = _digits; |
| 255 var r_digits = r._digits; | 270 var r_digits = r._digits; |
| 256 for (var i = _used - 1; i >= 0; --i) { | 271 for (var i = _used; --i >= 0; ) { |
|
zra
2014/11/18 19:04:45
Same comment
regis
2014/11/18 23:19:54
Done.
| |
| 257 r_digits[i + n] = digits[i]; | 272 r_digits[i + n] = digits[i]; |
| 258 } | 273 } |
| 259 for (var i = n - 1; i >= 0; --i) { | 274 for (var i = n - 1; i >= 0; --i) { |
| 260 r_digits[i] = 0; | 275 r_digits[i] = 0; |
| 261 } | 276 } |
| 262 r._used = r_used; | 277 r._used = r_used; |
| 263 r._neg = _neg; | 278 r._neg = _neg; |
| 279 // Set leading zero for 64-bit processing. | |
| 280 if (r_used > 0) { | |
| 281 r_digits[r_used] = 0; | |
| 282 } | |
| 264 } | 283 } |
| 265 | 284 |
| 266 // r = this >> n*DIGIT_BITS. | 285 // r = this >> n*DIGIT_BITS. |
| 267 void _drShiftTo(int n, _Bigint r) { | 286 void _drShiftTo(int n, _Bigint r) { |
| 268 var r_used = _used - n; | 287 var r_used = _used - n; |
| 269 if (r_used < 0) { | 288 if (r_used < 0) { |
| 270 if (_neg) { | 289 if (_neg) { |
| 271 // Set r to -1. | 290 // Set r to -1. |
| 291 r._used = 0; // No digits to preserve. | |
| 292 r._ensureLength(1); | |
| 272 r._neg = true; | 293 r._neg = true; |
| 273 r._ensureLength(1); | |
| 274 r._used = 1; | 294 r._used = 1; |
| 275 r._digits[0] = 1; | 295 r._digits[0] = 1; |
| 296 r._digits[1] = 0; // Set leading zero for 64-bit processing. | |
| 276 } else { | 297 } else { |
| 277 // Set r to 0. | 298 // Set r to 0. |
| 278 r._neg = false; | 299 r._neg = false; |
| 279 r._used = 0; | 300 r._used = 0; |
| 280 } | 301 } |
| 281 return; | 302 return; |
| 282 } | 303 } |
| 283 r._ensureLength(r_used); | 304 r._ensureLength(r_used); |
| 284 var digits = _digits; | 305 var digits = _digits; |
| 285 var r_digits = r._digits; | 306 var r_digits = r._digits; |
| 286 var used = _used; | 307 var used = _used; |
| 287 for (var i = n; i < used; ++i) { | 308 for (var i = n; i < used; ++i) { |
| 288 r_digits[i - n] = digits[i]; | 309 r_digits[i - n] = digits[i]; |
| 289 } | 310 } |
| 290 r._used = r_used; | 311 r._used = r_used; |
| 291 r._neg = _neg; | 312 r._neg = _neg; |
| 313 // Set leading zero for 64-bit processing. | |
| 314 if (r_used > 0) { | |
| 315 r_digits[r_used] = 0; | |
| 316 } | |
| 292 if (_neg) { | 317 if (_neg) { |
| 293 // Round down if any bit was shifted out. | 318 // Round down if any bit was shifted out. |
| 294 for (var i = 0; i < n; i++) { | 319 for (var i = 0; i < n; i++) { |
| 295 if (digits[i] != 0) { | 320 if (digits[i] != 0) { |
| 296 r._subTo(ONE, r); | 321 r._subTo(ONE, r); |
| 297 break; | 322 break; |
| 298 } | 323 } |
| 299 } | 324 } |
| 300 } | 325 } |
| 301 } | 326 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 334 var bs = n % DIGIT_BITS; | 359 var bs = n % DIGIT_BITS; |
| 335 if (bs == 0) { | 360 if (bs == 0) { |
| 336 _drShiftTo(ds, r); | 361 _drShiftTo(ds, r); |
| 337 return; | 362 return; |
| 338 } | 363 } |
| 339 var r_used = _used - ds; | 364 var r_used = _used - ds; |
| 340 if (r_used <= 0) { | 365 if (r_used <= 0) { |
| 341 if (_neg) { | 366 if (_neg) { |
| 342 // Set r to -1. | 367 // Set r to -1. |
| 343 r._neg = true; | 368 r._neg = true; |
| 369 r._used = 0; // No digits to preserve. | |
| 344 r._ensureLength(1); | 370 r._ensureLength(1); |
| 345 r._used = 1; | 371 r._used = 1; |
| 346 r._digits[0] = 1; | 372 r._digits[0] = 1; |
| 373 r._digits[1] = 0; // Set leading zero for 64-bit processing. | |
| 347 } else { | 374 } else { |
| 348 // Set r to 0. | 375 // Set r to 0. |
| 349 r._neg = false; | 376 r._neg = false; |
| 350 r._used = 0; | 377 r._used = 0; |
| 351 } | 378 } |
| 352 return; | 379 return; |
| 353 } | 380 } |
| 354 var cbs = DIGIT_BITS - bs; | 381 var cbs = DIGIT_BITS - bs; |
| 355 var bm = (1 << bs) - 1; | 382 var bm = (1 << bs) - 1; |
| 356 r._ensureLength(r_used); | 383 r._ensureLength(r_used); |
| (...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 860 } else { | 887 } else { |
| 861 a_digits[i + used] = c; | 888 a_digits[i + used] = c; |
| 862 } | 889 } |
| 863 } | 890 } |
| 864 | 891 |
| 865 // r = this * a. | 892 // r = this * a. |
| 866 void _mulTo(_Bigint a, _Bigint r) { | 893 void _mulTo(_Bigint a, _Bigint r) { |
| 867 // TODO(regis): Use karatsuba multiplication when appropriate. | 894 // TODO(regis): Use karatsuba multiplication when appropriate. |
| 868 var used = _used; | 895 var used = _used; |
| 869 var a_used = a._used; | 896 var a_used = a._used; |
| 897 if (used == 0 || a_used == 0) { | |
| 898 r._used = 0; | |
| 899 r._neg = false; | |
| 900 return; | |
| 901 } | |
| 870 var r_used = used + a_used; | 902 var r_used = used + a_used; |
| 871 r._ensureLength(r_used); | 903 r._ensureLength(r_used); |
| 872 var digits = _digits; | 904 var digits = _digits; |
| 873 var a_digits = a._digits; | 905 var a_digits = a._digits; |
| 874 var r_digits = r._digits; | 906 var r_digits = r._digits; |
| 875 r._used = r_used; | 907 r._used = r_used; |
| 876 var i = r_used; | 908 var i = r_used + 1; // Set leading zero for 64-bit processing. |
| 877 while (--i >= 0) { | 909 while (--i >= 0) { |
| 878 r_digits[i] = 0; | 910 r_digits[i] = 0; |
| 879 } | 911 } |
| 880 for (i = 0; i < a_used; ++i) { | 912 for (i = 0; i < a_used; ++i) { |
| 881 _mulAdd(a_digits, i, digits, 0, r_digits, i, used); | 913 _mulAdd(a_digits, i, digits, 0, r_digits, i, used); |
| 882 } | 914 } |
| 883 r._clamp(); | 915 r._clamp(); |
| 884 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. | 916 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. |
| 885 } | 917 } |
| 886 | 918 |
| 887 // r = this^2, r != this. | 919 // r = this^2, r != this. |
| 888 void _sqrTo(_Bigint r) { | 920 void _sqrTo(_Bigint r) { |
| 889 var used = _used; | 921 var used = _used; |
| 922 if (used == 0) { | |
| 923 r._used = 0; | |
| 924 r._neg = false; | |
| 925 return; | |
| 926 } | |
| 890 var r_used = 2 * used; | 927 var r_used = 2 * used; |
| 891 r._ensureLength(r_used); | 928 r._ensureLength(r_used); |
| 892 var digits = _digits; | 929 var digits = _digits; |
| 893 var r_digits = r._digits; | 930 var r_digits = r._digits; |
| 894 var i = r_used; | 931 var i = r_used + 1; // Set leading zero for 64-bit processing. |
| 895 while (--i >= 0) { | 932 while (--i >= 0) { |
| 896 r_digits[i] = 0; | 933 r_digits[i] = 0; |
| 897 } | 934 } |
| 898 for (i = 0; i < used - 1; ++i) { | 935 for (i = 0; i < used - 1; ++i) { |
| 899 _sqrAdd(digits, i, r_digits, used); | 936 _sqrAdd(digits, i, r_digits, used); |
| 900 } | 937 } |
| 901 if (r_used > 0) { | 938 if (r_used > 0) { |
| 902 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); | 939 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); |
| 903 } | 940 } |
| 904 r._used = r_used; | 941 r._used = r_used; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 963 var y_digits = y._digits; | 1000 var y_digits = y._digits; |
| 964 var yt = y_digits[y_used - 1]; | 1001 var yt = y_digits[y_used - 1]; |
| 965 if (yt == 0) return; | 1002 if (yt == 0) return; |
| 966 var i = r._used; | 1003 var i = r._used; |
| 967 var j = i - y_used; | 1004 var j = i - y_used; |
| 968 _Bigint t = (q == null) ? new _Bigint() : q; | 1005 _Bigint t = (q == null) ? new _Bigint() : q; |
| 969 y._dlShiftTo(j, t); | 1006 y._dlShiftTo(j, t); |
| 970 var r_digits = r._digits; | 1007 var r_digits = r._digits; |
| 971 if (r._compareTo(t) >= 0) { | 1008 if (r._compareTo(t) >= 0) { |
| 972 r_digits[r._used++] = 1; | 1009 r_digits[r._used++] = 1; |
| 1010 r_digits[r._used] = 0; // Set leading zero for 64-bit processing. | |
| 973 r._subTo(t, r); | 1011 r._subTo(t, r); |
| 974 } | 1012 } |
| 975 ONE._dlShiftTo(y_used, t); | 1013 ONE._dlShiftTo(y_used, t); |
| 976 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. | 1014 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. |
| 977 while (y._used < y_used) { | 1015 while (y._used < y_used) { |
| 978 y_digits[y._used++] = 0; | 1016 y_digits[y._used++] = 0; |
| 979 } | 1017 } |
| 1018 y_digits[y._used] = 0; // Set leading zero for 64-bit processing. | |
| 980 Uint32List args = new Uint32List(2); | 1019 Uint32List args = new Uint32List(2); |
| 981 args[_YT] = yt; | 1020 args[_YT] = yt; |
| 982 while (--j >= 0) { | 1021 while (--j >= 0) { |
| 983 _estQuotientDigit(args, r_digits, --i); | 1022 _estQuotientDigit(args, r_digits, --i); |
| 984 _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used); | 1023 _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used); |
| 985 if (r_digits[i] < args[_QD]) { | 1024 if (r_digits[i] < args[_QD]) { |
| 986 y._dlShiftTo(j, t); | 1025 y._dlShiftTo(j, t); |
| 987 r._subTo(t, r); | 1026 r._subTo(t, r); |
| 988 while (r_digits[i] < --args[_QD]) { | 1027 while (r_digits[i] < --args[_QD]) { |
| 989 r._subTo(t, r); | 1028 r._subTo(t, r); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1412 return r; | 1451 return r; |
| 1413 } | 1452 } |
| 1414 | 1453 |
| 1415 // x = x/R mod _m | 1454 // x = x/R mod _m |
| 1416 void _reduce(_Bigint x) { | 1455 void _reduce(_Bigint x) { |
| 1417 x._ensureLength(_mused2 + 1); | 1456 x._ensureLength(_mused2 + 1); |
| 1418 var x_digits = x._digits; | 1457 var x_digits = x._digits; |
| 1419 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. | 1458 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. |
| 1420 x_digits[x._used++] = 0; | 1459 x_digits[x._used++] = 0; |
| 1421 } | 1460 } |
| 1461 x_digits[x._used] = 0; // Set leading zero for 64-bit processing. | |
| 1422 var m_used = _m._used; | 1462 var m_used = _m._used; |
| 1423 var m_digits = _m._digits; | 1463 var m_digits = _m._digits; |
| 1424 for (var i = 0; i < m_used; ++i) { | 1464 for (var i = 0; i < m_used; ++i) { |
| 1425 _mulMod(_rho_mu, x_digits, i); | 1465 _mulMod(_rho_mu, x_digits, i); |
| 1426 _Bigint._mulAdd(_rho_mu, _MU, m_digits, 0, x_digits, i, m_used); | 1466 _Bigint._mulAdd(_rho_mu, _MU, m_digits, 0, x_digits, i, m_used); |
| 1427 } | 1467 } |
| 1428 x._clamp(); | 1468 x._clamp(); |
| 1429 x._drShiftTo(m_used, x); | 1469 x._drShiftTo(m_used, x); |
| 1430 if (x._compareTo(_m) >= 0) { | 1470 if (x._compareTo(_m) >= 0) { |
| 1431 x._subTo(_m, x); | 1471 x._subTo(_m, x); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1476 void _sqrTo(_Bigint x, _Bigint r) { | 1516 void _sqrTo(_Bigint x, _Bigint r) { |
| 1477 x._sqrTo(r); | 1517 x._sqrTo(r); |
| 1478 _reduce(r); | 1518 _reduce(r); |
| 1479 } | 1519 } |
| 1480 | 1520 |
| 1481 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { | 1521 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { |
| 1482 x._mulTo(y, r); | 1522 x._mulTo(y, r); |
| 1483 _reduce(r); | 1523 _reduce(r); |
| 1484 } | 1524 } |
| 1485 } | 1525 } |
| OLD | NEW |