| 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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 } | 278 } |
| 279 | 279 |
| 280 // Return this << n. | 280 // Return this << n. |
| 281 _Bigint _lShift(int n) { | 281 _Bigint _lShift(int n) { |
| 282 final ds = n ~/ _DIGIT_BITS; | 282 final ds = n ~/ _DIGIT_BITS; |
| 283 final bs = n % _DIGIT_BITS; | 283 final bs = n % _DIGIT_BITS; |
| 284 if (bs == 0) { | 284 if (bs == 0) { |
| 285 return _dlShift(ds); | 285 return _dlShift(ds); |
| 286 } | 286 } |
| 287 var r_used = _used + ds + 1; | 287 var r_used = _used + ds + 1; |
| 288 var r_digits = new Uint32List(r_used + (r_used & 1)); | 288 var r_digits = new Uint32List(r_used + 2 + (r_used & 1)); // +2 for 64-bit. |
| 289 _lsh(_digits, _used, n, r_digits); | 289 _lsh(_digits, _used, n, r_digits); |
| 290 return new _Bigint(_neg, r_used, r_digits); | 290 return new _Bigint(_neg, r_used, r_digits); |
| 291 } | 291 } |
| 292 | 292 |
| 293 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n. | 293 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n. |
| 294 // Return r_used. | 294 // Return r_used. |
| 295 static int _lShiftDigits(Uint32List x_digits, int x_used, int n, | 295 static int _lShiftDigits(Uint32List x_digits, int x_used, int n, |
| 296 Uint32List r_digits) { | 296 Uint32List r_digits) { |
| 297 final ds = n ~/ _DIGIT_BITS; | 297 final ds = n ~/ _DIGIT_BITS; |
| 298 final bs = n % _DIGIT_BITS; | 298 final bs = n % _DIGIT_BITS; |
| 299 if (bs == 0) { | 299 if (bs == 0) { |
| 300 return _dlShiftDigits(x_digits, x_used, ds, r_digits); | 300 return _dlShiftDigits(x_digits, x_used, ds, r_digits); |
| 301 } | 301 } |
| 302 var r_used = x_used + ds + 1; | 302 var r_used = x_used + ds + 1; |
| 303 assert(r_digits.length >= r_used + (r_used & 1)); | 303 assert(r_digits.length >= r_used + 2 + (r_used & 1)); // +2 for 64-bit. |
| 304 _lsh(x_digits, x_used, n, r_digits); | 304 _lsh(x_digits, x_used, n, r_digits); |
| 305 if (r_digits[r_used - 1] == 0) { | 305 if (r_digits[r_used - 1] == 0) { |
| 306 r_used--; // Clamp result. | 306 r_used--; // Clamp result. |
| 307 } else if (r_used.isOdd) { | 307 } else if (r_used.isOdd) { |
| 308 r_digits[r_used] = 0; | 308 r_digits[r_used] = 0; |
| 309 } | 309 } |
| 310 return r_used; | 310 return r_used; |
| 311 } | 311 } |
| 312 | 312 |
| 313 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. | 313 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. |
| (...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 964 if (a._used.isOdd) { | 964 if (a._used.isOdd) { |
| 965 nsh += _DIGIT_BITS; | 965 nsh += _DIGIT_BITS; |
| 966 } | 966 } |
| 967 // Concatenated positive quotient and normalized positive remainder. | 967 // Concatenated positive quotient and normalized positive remainder. |
| 968 var r_digits; | 968 var r_digits; |
| 969 var r_used; | 969 var r_used; |
| 970 // Normalized positive divisor. | 970 // Normalized positive divisor. |
| 971 var y_digits; | 971 var y_digits; |
| 972 var y_used; | 972 var y_used; |
| 973 if (nsh > 0) { | 973 if (nsh > 0) { |
| 974 y_digits = new Uint32List(a._used + 3); // +3 for normalization. | 974 y_digits = new Uint32List(a._used + 5); // +5 for norm. and 64-bit. |
| 975 y_used = _lShiftDigits(a._digits, a._used, nsh, y_digits); | 975 y_used = _lShiftDigits(a._digits, a._used, nsh, y_digits); |
| 976 r_digits = new Uint32List(_used + 3); // +3 for normalization. | 976 r_digits = new Uint32List(_used + 5); // +5 for normalization and 64-bit. |
| 977 r_used = _lShiftDigits(_digits, _used, nsh, r_digits); | 977 r_used = _lShiftDigits(_digits, _used, nsh, r_digits); |
| 978 } else { | 978 } else { |
| 979 y_digits = a._digits; | 979 y_digits = a._digits; |
| 980 y_used = a._used; | 980 y_used = a._used; |
| 981 r_digits = _cloneDigits(_digits, 0, _used, _used + 2); | 981 r_digits = _cloneDigits(_digits, 0, _used, _used + 2); |
| 982 r_used = _used; | 982 r_used = _used; |
| 983 } | 983 } |
| 984 Uint32List yt_qd = new Uint32List(4); | 984 Uint32List yt_qd = new Uint32List(4); |
| 985 yt_qd[_YT_LO] = y_digits[y_used - 2]; | 985 yt_qd[_YT_LO] = y_digits[y_used - 2]; |
| 986 yt_qd[_YT] = y_digits[y_used - 1]; | 986 yt_qd[_YT] = y_digits[y_used - 1]; |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1352 | 1352 |
| 1353 // Returns pow(this, e) % m, with e >= 0, m > 0. | 1353 // Returns pow(this, e) % m, with e >= 0, m > 0. |
| 1354 int modPow(int e, int m) { | 1354 int modPow(int e, int m) { |
| 1355 if (e is! int) throw new ArgumentError(e); | 1355 if (e is! int) throw new ArgumentError(e); |
| 1356 if (m is! int) throw new ArgumentError(m); | 1356 if (m is! int) throw new ArgumentError(m); |
| 1357 if (e < 0) throw new RangeError(e); | 1357 if (e < 0) throw new RangeError(e); |
| 1358 if (m <= 0) throw new RangeError(m); | 1358 if (m <= 0) throw new RangeError(m); |
| 1359 if (e == 0) return 1; | 1359 if (e == 0) return 1; |
| 1360 m = m._toBigint(); | 1360 m = m._toBigint(); |
| 1361 final m_used = m._used; | 1361 final m_used = m._used; |
| 1362 final m_used2p2 = 2*m_used + 2; | 1362 final m_used2p4 = 2*m_used + 4; |
| 1363 final e_bitlen = e.bitLength; | 1363 final e_bitlen = e.bitLength; |
| 1364 if (e_bitlen <= 0) return 1; | 1364 if (e_bitlen <= 0) return 1; |
| 1365 final bool cannotUseMontgomery = m.isEven || _abs() >= m; | 1365 final bool cannotUseMontgomery = m.isEven || _abs() >= m; |
| 1366 if (cannotUseMontgomery || e_bitlen < 64) { | 1366 if (cannotUseMontgomery || e_bitlen < 64) { |
| 1367 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) ? | 1367 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) ? |
| 1368 new _Classic(m) : new _Montgomery(m); | 1368 new _Classic(m) : new _Montgomery(m); |
| 1369 // TODO(regis): Should we use Barrett reduction for an even modulus and a | 1369 // TODO(regis): Should we use Barrett reduction for an even modulus and a |
| 1370 // large exponent? | 1370 // large exponent? |
| 1371 var r_digits = new Uint32List(m_used2p2); | 1371 var r_digits = new Uint32List(m_used2p4); |
| 1372 var r2_digits = new Uint32List(m_used2p2); | 1372 var r2_digits = new Uint32List(m_used2p4); |
| 1373 var g_digits = new Uint32List(m_used + (m_used & 1)); | 1373 var g_digits = new Uint32List(m_used + (m_used & 1)); |
| 1374 var g_used = z._convert(this, g_digits); | 1374 var g_used = z._convert(this, g_digits); |
| 1375 // Initialize r with g. | 1375 // Initialize r with g. |
| 1376 var j = g_used + (g_used & 1); // Copy leading zero if any. | 1376 var j = g_used + (g_used & 1); // Copy leading zero if any. |
| 1377 while (--j >= 0) { | 1377 while (--j >= 0) { |
| 1378 r_digits[j] = g_digits[j]; | 1378 r_digits[j] = g_digits[j]; |
| 1379 } | 1379 } |
| 1380 var r_used = g_used; | 1380 var r_used = g_used; |
| 1381 var r2_used; | 1381 var r2_used; |
| 1382 var i = e_bitlen - 1; | 1382 var i = e_bitlen - 1; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1404 else k = 6; | 1404 else k = 6; |
| 1405 _Reduction z = new _Montgomery(m); | 1405 _Reduction z = new _Montgomery(m); |
| 1406 var n = 3; | 1406 var n = 3; |
| 1407 final k1 = k - 1; | 1407 final k1 = k - 1; |
| 1408 final km = (1 << k) - 1; | 1408 final km = (1 << k) - 1; |
| 1409 List g_digits = new List(km + 1); | 1409 List g_digits = new List(km + 1); |
| 1410 List g_used = new List(km + 1); | 1410 List g_used = new List(km + 1); |
| 1411 g_digits[1] = new Uint32List(m_used + (m_used & 1)); | 1411 g_digits[1] = new Uint32List(m_used + (m_used & 1)); |
| 1412 g_used[1] = z._convert(this, g_digits[1]); | 1412 g_used[1] = z._convert(this, g_digits[1]); |
| 1413 if (k > 1) { | 1413 if (k > 1) { |
| 1414 var g2_digits = new Uint32List(m_used2p2); | 1414 var g2_digits = new Uint32List(m_used2p4); |
| 1415 var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits); | 1415 var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits); |
| 1416 while (n <= km) { | 1416 while (n <= km) { |
| 1417 g_digits[n] = new Uint32List(m_used2p2); | 1417 g_digits[n] = new Uint32List(m_used2p4); |
| 1418 g_used[n] = z._mul(g2_digits, g2_used, | 1418 g_used[n] = z._mul(g2_digits, g2_used, |
| 1419 g_digits[n - 2], g_used[n - 2], | 1419 g_digits[n - 2], g_used[n - 2], |
| 1420 g_digits[n]); | 1420 g_digits[n]); |
| 1421 n += 2; | 1421 n += 2; |
| 1422 } | 1422 } |
| 1423 } | 1423 } |
| 1424 var w; | 1424 var w; |
| 1425 var is1 = true; | 1425 var is1 = true; |
| 1426 var r_digits = _ONE._digits; | 1426 var r_digits = _ONE._digits; |
| 1427 var r_used = _ONE._used; | 1427 var r_used = _ONE._used; |
| 1428 var r2_digits = new Uint32List(m_used2p2); | 1428 var r2_digits = new Uint32List(m_used2p4); |
| 1429 var r2_used; | 1429 var r2_used; |
| 1430 var e_digits = e._digits; | 1430 var e_digits = e._digits; |
| 1431 var j = e._used - 1; | 1431 var j = e._used - 1; |
| 1432 var i = _nbits(e_digits[j]) - 1; | 1432 var i = _nbits(e_digits[j]) - 1; |
| 1433 while (j >= 0) { | 1433 while (j >= 0) { |
| 1434 if (i >= k1) { | 1434 if (i >= k1) { |
| 1435 w = (e_digits[j] >> (i - k1)) & km; | 1435 w = (e_digits[j] >> (i - k1)) & km; |
| 1436 } else { | 1436 } else { |
| 1437 w = (e_digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i); | 1437 w = (e_digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i); |
| 1438 if (j > 0) { | 1438 if (j > 0) { |
| 1439 w |= e_digits[j - 1] >> (_DIGIT_BITS + i - k1); | 1439 w |= e_digits[j - 1] >> (_DIGIT_BITS + i - k1); |
| 1440 } | 1440 } |
| 1441 } | 1441 } |
| 1442 n = k; | 1442 n = k; |
| 1443 while ((w & 1) == 0) { | 1443 while ((w & 1) == 0) { |
| 1444 w >>= 1; | 1444 w >>= 1; |
| 1445 --n; | 1445 --n; |
| 1446 } | 1446 } |
| 1447 if ((i -= n) < 0) { | 1447 if ((i -= n) < 0) { |
| 1448 i += _DIGIT_BITS; | 1448 i += _DIGIT_BITS; |
| 1449 --j; | 1449 --j; |
| 1450 } | 1450 } |
| 1451 if (is1) { // r == 1, don't bother squaring or multiplying it. | 1451 if (is1) { // r == 1, don't bother squaring or multiplying it. |
| 1452 r_digits = new Uint32List(m_used2p2); | 1452 r_digits = new Uint32List(m_used2p4); |
| 1453 r_used = g_used[w]; | 1453 r_used = g_used[w]; |
| 1454 var gw_digits = g_digits[w]; | 1454 var gw_digits = g_digits[w]; |
| 1455 var ri = r_used + (r_used & 1); // Copy leading zero if any. | 1455 var ri = r_used + (r_used & 1); // Copy leading zero if any. |
| 1456 while (--ri >= 0) { | 1456 while (--ri >= 0) { |
| 1457 r_digits[ri] = gw_digits[ri]; | 1457 r_digits[ri] = gw_digits[ri]; |
| 1458 } | 1458 } |
| 1459 is1 = false; | 1459 is1 = false; |
| 1460 } | 1460 } |
| 1461 else { | 1461 else { |
| 1462 while (n > 1) { | 1462 while (n > 1) { |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1762 | 1762 |
| 1763 int _mul(Uint32List x_digits, int x_used, | 1763 int _mul(Uint32List x_digits, int x_used, |
| 1764 Uint32List y_digits, int y_used, | 1764 Uint32List y_digits, int y_used, |
| 1765 Uint32List r_digits) { | 1765 Uint32List r_digits) { |
| 1766 var r_used = _Bigint._mulDigits(x_digits, x_used, | 1766 var r_used = _Bigint._mulDigits(x_digits, x_used, |
| 1767 y_digits, y_used, | 1767 y_digits, y_used, |
| 1768 r_digits); | 1768 r_digits); |
| 1769 return _reduce(r_digits, r_used); | 1769 return _reduce(r_digits, r_used); |
| 1770 } | 1770 } |
| 1771 } | 1771 } |
| OLD | NEW |