| 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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 r = -r; | 405 r = -r; |
| 406 } | 406 } |
| 407 } else if (_neg) { | 407 } else if (_neg) { |
| 408 r = -1; | 408 r = -1; |
| 409 } else { | 409 } else { |
| 410 r = 1; | 410 r = 1; |
| 411 } | 411 } |
| 412 return r; | 412 return r; |
| 413 } | 413 } |
| 414 | 414 |
| 415 // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1]. |
| 416 // used >= a_used > 0. |
| 417 static void _add(Uint32List digits, int used, |
| 418 Uint32List a_digits, int a_used, |
| 419 Uint32List r_digits) { |
| 420 var c = 0; |
| 421 for (var i = 0; i < a_used; i++) { |
| 422 c += digits[i] + a_digits[i]; |
| 423 r_digits[i] = c & DIGIT_MASK; |
| 424 c >>= DIGIT_BITS; |
| 425 } |
| 426 for (var i = a_used; i < used; i++) { |
| 427 c += digits[i]; |
| 428 r_digits[i] = c & DIGIT_MASK; |
| 429 c >>= DIGIT_BITS; |
| 430 } |
| 431 r_digits[used] = c; |
| 432 } |
| 433 |
| 434 // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1]. |
| 435 // used >= a_used > 0. |
| 436 static void _sub(Uint32List digits, int used, |
| 437 Uint32List a_digits, int a_used, |
| 438 Uint32List r_digits) { |
| 439 var c = 0; |
| 440 for (var i = 0; i < a_used; i++) { |
| 441 c += digits[i] - a_digits[i]; |
| 442 r_digits[i] = c & DIGIT_MASK; |
| 443 c >>= DIGIT_BITS; |
| 444 } |
| 445 for (var i = a_used; i < used; i++) { |
| 446 c += digits[i]; |
| 447 r_digits[i] = c & DIGIT_MASK; |
| 448 c >>= DIGIT_BITS; |
| 449 } |
| 450 } |
| 451 |
| 415 // r = abs(this) + abs(a). | 452 // r = abs(this) + abs(a). |
| 416 void _absAddTo(_Bigint a, _Bigint r) { | 453 void _absAddTo(_Bigint a, _Bigint r) { |
| 417 var used = _used; | 454 var used = _used; |
| 418 var a_used = a._used; | 455 var a_used = a._used; |
| 419 if (used < a_used) { | 456 if (used < a_used) { |
| 420 a._absAddTo(this, r); | 457 a._absAddTo(this, r); |
| 421 return; | 458 return; |
| 422 } | 459 } |
| 423 if (used == 0) { | 460 if (used == 0) { |
| 424 // Set r to 0. | 461 // Set r to 0. |
| 425 r._neg = false; | 462 r._neg = false; |
| 426 r._used = 0; | 463 r._used = 0; |
| 427 return; | 464 return; |
| 428 } | 465 } |
| 429 if (a_used == 0) { | 466 if (a_used == 0) { |
| 430 _copyTo(r); | 467 _copyTo(r); |
| 431 return; | 468 return; |
| 432 } | 469 } |
| 433 r._ensureLength(used + 1); | 470 r._ensureLength(used + 1); |
| 434 var digits = _digits; | 471 _add(_digits, used, a._digits, a_used, r._digits); |
| 435 var a_digits = a._digits; | |
| 436 var r_digits = r._digits; | |
| 437 var c = 0; | |
| 438 for (var i = 0; i < a_used; i++) { | |
| 439 c += digits[i] + a_digits[i]; | |
| 440 r_digits[i] = c & DIGIT_MASK; | |
| 441 c >>= DIGIT_BITS; | |
| 442 } | |
| 443 for (var i = a_used; i < used; i++) { | |
| 444 c += digits[i]; | |
| 445 r_digits[i] = c & DIGIT_MASK; | |
| 446 c >>= DIGIT_BITS; | |
| 447 } | |
| 448 r_digits[used] = c; | |
| 449 r._used = used + 1; | 472 r._used = used + 1; |
| 450 r._clamp(); | 473 r._clamp(); |
| 451 } | 474 } |
| 452 | 475 |
| 453 // r = abs(this) - abs(a), with abs(this) >= abs(a). | 476 // r = abs(this) - abs(a), with abs(this) >= abs(a). |
| 454 void _absSubTo(_Bigint a, _Bigint r) { | 477 void _absSubTo(_Bigint a, _Bigint r) { |
| 455 assert(_absCompareTo(a) >= 0); | 478 assert(_absCompareTo(a) >= 0); |
| 456 var used = _used; | 479 var used = _used; |
| 457 if (used == 0) { | 480 if (used == 0) { |
| 458 // Set r to 0. | 481 // Set r to 0. |
| 459 r._neg = false; | 482 r._neg = false; |
| 460 r._used = 0; | 483 r._used = 0; |
| 461 return; | 484 return; |
| 462 } | 485 } |
| 463 var a_used = a._used; | 486 var a_used = a._used; |
| 464 if (a_used == 0) { | 487 if (a_used == 0) { |
| 465 _copyTo(r); | 488 _copyTo(r); |
| 466 return; | 489 return; |
| 467 } | 490 } |
| 468 r._ensureLength(used); | 491 r._ensureLength(used); |
| 469 var digits = _digits; | 492 _sub(_digits, used, a._digits, a_used, r._digits); |
| 470 var a_digits = a._digits; | |
| 471 var r_digits = r._digits; | |
| 472 var c = 0; | |
| 473 for (var i = 0; i < a_used; i++) { | |
| 474 c += digits[i] - a_digits[i]; | |
| 475 r_digits[i] = c & DIGIT_MASK; | |
| 476 c >>= DIGIT_BITS; | |
| 477 } | |
| 478 for (var i = a_used; i < used; i++) { | |
| 479 c += digits[i]; | |
| 480 r_digits[i] = c & DIGIT_MASK; | |
| 481 c >>= DIGIT_BITS; | |
| 482 } | |
| 483 r._used = used; | 493 r._used = used; |
| 484 r._clamp(); | 494 r._clamp(); |
| 485 } | 495 } |
| 486 | 496 |
| 487 // r = abs(this) & abs(a). | 497 // r = abs(this) & abs(a). |
| 488 void _absAndTo(_Bigint a, _Bigint r) { | 498 void _absAndTo(_Bigint a, _Bigint r) { |
| 489 var r_used = (_used < a._used) ? _used : a._used; | 499 var r_used = (_used < a._used) ? _used : a._used; |
| 490 r._ensureLength(r_used); | 500 r._ensureLength(r_used); |
| 491 var digits = _digits; | 501 var digits = _digits; |
| 492 var a_digits = a._digits; | 502 var a_digits = a._digits; |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 889 _sqrAdd(digits, i, r_digits, used); | 899 _sqrAdd(digits, i, r_digits, used); |
| 890 } | 900 } |
| 891 if (r_used > 0) { | 901 if (r_used > 0) { |
| 892 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); | 902 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); |
| 893 } | 903 } |
| 894 r._used = r_used; | 904 r._used = r_used; |
| 895 r._neg = false; | 905 r._neg = false; |
| 896 r._clamp(); | 906 r._clamp(); |
| 897 } | 907 } |
| 898 | 908 |
| 909 // Indices of the arguments of _estQuotientDigit. |
| 910 static const int _YT = 0; // Index of top digit of divisor y in args array. |
| 911 static const int _QD = 1; // Index of estimated quotient digit in args array. |
| 912 |
| 913 // Estimate args[_QD] = digits[i]:digits[i-1] ~/ args[_YT]. |
| 914 static void _estQuotientDigit(Uint32List args, Uint32List digits, int i) { |
| 915 if (digits[i] == args[_YT]) { |
| 916 args[_QD] = DIGIT_MASK; |
| 917 } else { |
| 918 // Chop off one bit, since a Mint cannot hold 2 DIGITs. |
| 919 var qd = ((digits[i] << (DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) |
| 920 ~/ (args[_YT] >> 1); |
| 921 if (qd > DIGIT_MASK) { |
| 922 args[_QD] = DIGIT_MASK; |
| 923 } else { |
| 924 args[_QD] = qd; |
| 925 } |
| 926 } |
| 927 } |
| 928 |
| 929 |
| 899 // Truncating division and remainder. | 930 // Truncating division and remainder. |
| 900 // If q != null, q = trunc(this / a). | 931 // If q != null, q = trunc(this / a). |
| 901 // If r != null, r = this - a * trunc(this / a). | 932 // If r != null, r = this - a * trunc(this / a). |
| 902 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { | 933 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { |
| 903 if (a._used == 0) return; | 934 if (a._used == 0) return; |
| 904 if (_used < a._used) { | 935 if (_used < a._used) { |
| 905 if (q != null) { | 936 if (q != null) { |
| 906 // Set q to 0. | 937 // Set q to 0. |
| 907 q._neg = false; | 938 q._neg = false; |
| 908 q._used = 0; | 939 q._used = 0; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 923 } | 954 } |
| 924 else { | 955 else { |
| 925 a._copyTo(y); | 956 a._copyTo(y); |
| 926 _copyTo(r); | 957 _copyTo(r); |
| 927 } | 958 } |
| 928 // We consider this and a positive. Ignore the copied sign. | 959 // We consider this and a positive. Ignore the copied sign. |
| 929 y._neg = false; | 960 y._neg = false; |
| 930 r._neg = false; | 961 r._neg = false; |
| 931 var y_used = y._used; | 962 var y_used = y._used; |
| 932 var y_digits = y._digits; | 963 var y_digits = y._digits; |
| 933 var y0 = y_digits[y_used - 1]; | 964 var yt = y_digits[y_used - 1]; |
| 934 if (y0 == 0) return; | 965 if (yt == 0) return; |
| 935 var yt = y0 >> 1; // Chop off one bit, see below. y is normalized: yt != 0. | |
| 936 var i = r._used; | 966 var i = r._used; |
| 937 var j = i - y_used; | 967 var j = i - y_used; |
| 938 _Bigint t = (q == null) ? new _Bigint() : q; | 968 _Bigint t = (q == null) ? new _Bigint() : q; |
| 939 y._dlShiftTo(j, t); | 969 y._dlShiftTo(j, t); |
| 940 var r_digits = r._digits; | 970 var r_digits = r._digits; |
| 941 if (r._compareTo(t) >= 0) { | 971 if (r._compareTo(t) >= 0) { |
| 942 r_digits[r._used++] = 1; | 972 r_digits[r._used++] = 1; |
| 943 r._subTo(t, r); | 973 r._subTo(t, r); |
| 944 } | 974 } |
| 945 ONE._dlShiftTo(y_used, t); | 975 ONE._dlShiftTo(y_used, t); |
| 946 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. | 976 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. |
| 947 while (y._used < y_used) { | 977 while (y._used < y_used) { |
| 948 y_digits[y._used++] = 0; | 978 y_digits[y._used++] = 0; |
| 949 } | 979 } |
| 950 var qd_digit = new Uint32List(1); | 980 Uint32List args = new Uint32List(2); |
| 981 args[_YT] = yt; |
| 951 while (--j >= 0) { | 982 while (--j >= 0) { |
| 952 // Estimate quotient digit. | 983 _estQuotientDigit(args, r_digits, --i); |
| 953 // TODO(regis): Move the expensive mint division below to a function that | 984 _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used); |
| 954 // can be intrinsified using an uint64_t by uint32_t division instruction, | 985 if (r_digits[i] < args[_QD]) { |
| 955 // e.g. qd = _estqd(r_digits, --i, y0). | |
| 956 if (r_digits[--i] == y0) { | |
| 957 qd_digit[0] = DIGIT_MASK; | |
| 958 } else { | |
| 959 // Chop off one bit, since a Mint cannot hold 2 DIGITs. | |
| 960 var qd = | |
| 961 ((r_digits[i] << (DIGIT_BITS - 1)) | (r_digits[i - 1] >> 1)) ~/ yt; | |
| 962 if (qd > DIGIT_MASK) { | |
| 963 qd_digit[0] = DIGIT_MASK; | |
| 964 } else { | |
| 965 qd_digit[0] = qd; | |
| 966 } | |
| 967 } | |
| 968 _mulAdd(qd_digit, 0, y_digits, 0, r_digits, j, y_used); | |
| 969 if (r_digits[i] < qd_digit[0]) { | |
| 970 y._dlShiftTo(j, t); | 986 y._dlShiftTo(j, t); |
| 971 r._subTo(t, r); | 987 r._subTo(t, r); |
| 972 while (r_digits[i] < --qd_digit[0]) { | 988 while (r_digits[i] < --args[_QD]) { |
| 973 r._subTo(t, r); | 989 r._subTo(t, r); |
| 974 } | 990 } |
| 975 } | 991 } |
| 976 } | 992 } |
| 977 if (q != null) { | 993 if (q != null) { |
| 978 r._drShiftTo(y_used, q); | 994 r._drShiftTo(y_used, q); |
| 979 if (_neg != a._neg) { | 995 if (_neg != a._neg) { |
| 980 ZERO._subTo(q, q); | 996 ZERO._subTo(q, q); |
| 981 } | 997 } |
| 982 } | 998 } |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1311 class _Reduction { | 1327 class _Reduction { |
| 1312 _Bigint _convert(_Bigint x); | 1328 _Bigint _convert(_Bigint x); |
| 1313 _Bigint _revert(_Bigint x); | 1329 _Bigint _revert(_Bigint x); |
| 1314 void _mulTo(_Bigint x, _Bigint y, _Bigint r); | 1330 void _mulTo(_Bigint x, _Bigint y, _Bigint r); |
| 1315 void _sqrTo(_Bigint x, _Bigint r); | 1331 void _sqrTo(_Bigint x, _Bigint r); |
| 1316 } | 1332 } |
| 1317 | 1333 |
| 1318 // Montgomery reduction on _Bigint. | 1334 // Montgomery reduction on _Bigint. |
| 1319 class _Montgomery implements _Reduction { | 1335 class _Montgomery implements _Reduction { |
| 1320 _Bigint _m; | 1336 _Bigint _m; |
| 1321 int _mp; | |
| 1322 int _mpl; | |
| 1323 int _mph; | |
| 1324 int _um; | |
| 1325 int _mused2; | 1337 int _mused2; |
| 1326 Uint32List _u0digit; | 1338 Uint32List _rho_mu; |
| 1339 static const int _RHO = 0; // Index of rho in _rho_mu array. |
| 1340 static const int _MU = 1; // Index of mu in _rho_mu array. |
| 1327 | 1341 |
| 1328 _Montgomery(m) { | 1342 _Montgomery(m) { |
| 1329 _m = m._toBigint(); | 1343 _m = m._toBigint(); |
| 1330 _mp = _m._invDigit(); | |
| 1331 _mpl = _mp & _Bigint.DIGIT2_MASK; | |
| 1332 _mph = _mp >> _Bigint.DIGIT2_BITS; | |
| 1333 _um = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; | |
| 1334 _mused2 = 2*_m._used; | 1344 _mused2 = 2*_m._used; |
| 1335 _u0digit = new Uint32List(1); | 1345 _rho_mu = new Uint32List(2); |
| 1346 _rho_mu[_RHO] = _m._invDigit(); |
| 1347 } |
| 1348 |
| 1349 // args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE. |
| 1350 static void _mulMod(Uint32List args, Uint32List digits, int i) { |
| 1351 const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; |
| 1352 var rhol = args[_RHO] & _Bigint.DIGIT2_MASK; |
| 1353 var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS; |
| 1354 var dh = digits[i] >> _Bigint.DIGIT2_BITS; |
| 1355 var dl = digits[i] & _Bigint.DIGIT2_MASK; |
| 1356 args[_MU] = |
| 1357 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint.DIGIT2_BITS)) |
| 1358 & _Bigint.DIGIT_MASK; |
| 1336 } | 1359 } |
| 1337 | 1360 |
| 1338 // Return x*R mod _m | 1361 // Return x*R mod _m |
| 1339 _Bigint _convert(_Bigint x) { | 1362 _Bigint _convert(_Bigint x) { |
| 1340 var r = new _Bigint(); | 1363 var r = new _Bigint(); |
| 1341 x.abs()._dlShiftTo(_m._used, r); | 1364 x.abs()._dlShiftTo(_m._used, r); |
| 1342 r._divRemTo(_m, null, r); | 1365 r._divRemTo(_m, null, r); |
| 1343 if (x._neg && !r._neg && r._used > 0) { | 1366 if (x._neg && !r._neg && r._used > 0) { |
| 1344 _m._subTo(r, r); | 1367 _m._subTo(r, r); |
| 1345 } | 1368 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1357 // x = x/R mod _m | 1380 // x = x/R mod _m |
| 1358 void _reduce(_Bigint x) { | 1381 void _reduce(_Bigint x) { |
| 1359 x._ensureLength(_mused2 + 1); | 1382 x._ensureLength(_mused2 + 1); |
| 1360 var x_digits = x._digits; | 1383 var x_digits = x._digits; |
| 1361 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. | 1384 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. |
| 1362 x_digits[x._used++] = 0; | 1385 x_digits[x._used++] = 0; |
| 1363 } | 1386 } |
| 1364 var m_used = _m._used; | 1387 var m_used = _m._used; |
| 1365 var m_digits = _m._digits; | 1388 var m_digits = _m._digits; |
| 1366 for (var i = 0; i < m_used; ++i) { | 1389 for (var i = 0; i < m_used; ++i) { |
| 1367 // Faster way of calculating u0 = x[i]*mp mod DIGIT_BASE. | 1390 _mulMod(_rho_mu, x_digits, i); |
| 1368 var j = x_digits[i] & _Bigint.DIGIT2_MASK; | 1391 _Bigint._mulAdd(_rho_mu, _MU, m_digits, 0, x_digits, i, m_used); |
| 1369 _u0digit[0] = (j*_mpl + (((j*_mph + (x_digits[i] >> _Bigint.DIGIT2_BITS) | |
| 1370 *_mpl) & _um) << _Bigint.DIGIT2_BITS)) & _Bigint.DIGIT_MASK; | |
| 1371 // Use _mulAdd to combine the multiply-shift-add into one call. | |
| 1372 _Bigint._mulAdd(_u0digit, 0, m_digits, 0, x_digits, i, m_used); | |
| 1373 } | 1392 } |
| 1374 x._clamp(); | 1393 x._clamp(); |
| 1375 x._drShiftTo(m_used, x); | 1394 x._drShiftTo(m_used, x); |
| 1376 if (x._compareTo(_m) >= 0) { | 1395 if (x._compareTo(_m) >= 0) { |
| 1377 x._subTo(_m, x); | 1396 x._subTo(_m, x); |
| 1378 } | 1397 } |
| 1379 } | 1398 } |
| 1380 | 1399 |
| 1381 // r = x^2/R mod _m ; x != r | 1400 // r = x^2/R mod _m ; x != r |
| 1382 void _sqrTo(_Bigint x, _Bigint r) { | 1401 void _sqrTo(_Bigint x, _Bigint r) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1422 void _sqrTo(_Bigint x, _Bigint r) { | 1441 void _sqrTo(_Bigint x, _Bigint r) { |
| 1423 x._sqrTo(r); | 1442 x._sqrTo(r); |
| 1424 _reduce(r); | 1443 _reduce(r); |
| 1425 } | 1444 } |
| 1426 | 1445 |
| 1427 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { | 1446 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { |
| 1428 x._mulTo(y, r); | 1447 x._mulTo(y, r); |
| 1429 _reduce(r); | 1448 _reduce(r); |
| 1430 } | 1449 } |
| 1431 } | 1450 } |
| OLD | NEW |