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 |