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 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1071 // concatenated quotient and normalized remainder. | 1071 // concatenated quotient and normalized remainder. |
1072 // Output: | 1072 // Output: |
1073 // r_digits[0..r_used-1]: positive remainder. | 1073 // r_digits[0..r_used-1]: positive remainder. |
1074 // Returns r_used. | 1074 // Returns r_used. |
1075 static int _remDigits(Uint32List x_digits, int x_used, | 1075 static int _remDigits(Uint32List x_digits, int x_used, |
1076 Uint32List y_digits, int y_used, Uint32List ny_digits, | 1076 Uint32List y_digits, int y_used, Uint32List ny_digits, |
1077 int nsh, | 1077 int nsh, |
1078 Uint32List yt_qd, | 1078 Uint32List yt_qd, |
1079 Uint32List t_digits, | 1079 Uint32List t_digits, |
1080 Uint32List r_digits) { | 1080 Uint32List r_digits) { |
1081 assert(y_used > 0 && x_used >= y_used); | |
1082 // Initialize r_digits to normalized positive dividend. | 1081 // Initialize r_digits to normalized positive dividend. |
1083 var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits); | 1082 var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits); |
1084 // For 64-bit processing, make sure y_used, i, and j are even. | 1083 // For 64-bit processing, make sure y_used, i, and j are even. |
1085 assert(y_used.isEven); | 1084 assert(y_used.isEven); |
1086 var i = r_used + (r_used & 1); | 1085 var i = r_used + (r_used & 1); |
1087 var j = i - y_used; | 1086 var j = i - y_used; |
1088 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); | 1087 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); |
1089 // Explicit first division step in case normalized dividend is larger or | 1088 // Explicit first division step in case normalized dividend is larger or |
1090 // equal to shifted normalized divisor. | 1089 // equal to shifted normalized divisor. |
1091 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { | 1090 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1338 return other._toBigint()._compare(this) == 0; | 1337 return other._toBigint()._compare(this) == 0; |
1339 } | 1338 } |
1340 | 1339 |
1341 // Returns pow(this, e) % m, with e >= 0, m > 0. | 1340 // Returns pow(this, e) % m, with e >= 0, m > 0. |
1342 int modPow(int e, int m) { | 1341 int modPow(int e, int m) { |
1343 if (e is! int) throw new ArgumentError(e); | 1342 if (e is! int) throw new ArgumentError(e); |
1344 if (m is! int) throw new ArgumentError(m); | 1343 if (m is! int) throw new ArgumentError(m); |
1345 if (e < 0) throw new RangeError(e); | 1344 if (e < 0) throw new RangeError(e); |
1346 if (m <= 0) throw new RangeError(m); | 1345 if (m <= 0) throw new RangeError(m); |
1347 if (e == 0) return 1; | 1346 if (e == 0) return 1; |
1348 e = e._toBigint(); | |
1349 m = m._toBigint(); | 1347 m = m._toBigint(); |
1350 final m_used = m._used; | 1348 final m_used = m._used; |
1351 final m_used2p2 = 2*m_used + 2; | 1349 final m_used2p2 = 2*m_used + 2; |
1352 final e_bitlen = e.bitLength; | 1350 final e_bitlen = e.bitLength; |
1353 if (e_bitlen <= 0) return 1; | 1351 if (e_bitlen <= 0) return 1; |
1354 if ((e is! _Bigint) || m.isEven) { | 1352 final bool cannotUseMontgomery = m.isEven || _abs() >= m; |
1355 _Reduction z = (e_bitlen < 8 || m.isEven) ? | 1353 if (cannotUseMontgomery || e_bitlen < 64) { |
| 1354 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) ? |
1356 new _Classic(m) : new _Montgomery(m); | 1355 new _Classic(m) : new _Montgomery(m); |
1357 // TODO(regis): Should we use Barrett reduction for an even modulus? | 1356 // TODO(regis): Should we use Barrett reduction for an even modulus and a |
| 1357 // large exponent? |
1358 var r_digits = new Uint32List(m_used2p2); | 1358 var r_digits = new Uint32List(m_used2p2); |
1359 var r2_digits = new Uint32List(m_used2p2); | 1359 var r2_digits = new Uint32List(m_used2p2); |
1360 var g_digits = new Uint32List(m_used + (m_used & 1)); | 1360 var g_digits = new Uint32List(m_used + (m_used & 1)); |
1361 var g_used = z._convert(this, g_digits); | 1361 var g_used = z._convert(this, g_digits); |
1362 // Initialize r with g. | 1362 // Initialize r with g. |
1363 var j = g_used + (g_used & 1); // Copy leading zero if any. | 1363 var j = g_used + (g_used & 1); // Copy leading zero if any. |
1364 while (--j >= 0) { | 1364 while (--j >= 0) { |
1365 r_digits[j] = g_digits[j]; | 1365 r_digits[j] = g_digits[j]; |
1366 } | 1366 } |
1367 var r_used = g_used; | 1367 var r_used = g_used; |
1368 var r2_used; | 1368 var r2_used; |
1369 var i = e_bitlen - 1; | 1369 var i = e_bitlen - 1; |
1370 while (--i >= 0) { | 1370 while (--i >= 0) { |
1371 r2_used = z._sqr(r_digits, r_used, r2_digits); | 1371 r2_used = z._sqr(r_digits, r_used, r2_digits); |
1372 if ((e & (1 << i)) != 0) { | 1372 if ((e & (1 << i)) != 0) { |
1373 r_used = z._mul(r2_digits, r2_used, g_digits, g_used, r_digits); | 1373 r_used = z._mul(r2_digits, r2_used, g_digits, g_used, r_digits); |
1374 } else { | 1374 } else { |
1375 var t_digits = r_digits; | 1375 var t_digits = r_digits; |
1376 var t_used = r_used; | 1376 var t_used = r_used; |
1377 r_digits = r2_digits; | 1377 r_digits = r2_digits; |
1378 r_used = r2_used; | 1378 r_used = r2_used; |
1379 r2_digits = t_digits; | 1379 r2_digits = t_digits; |
1380 r2_used = t_used; | 1380 r2_used = t_used; |
1381 } | 1381 } |
1382 } | 1382 } |
1383 return z._revert(r_digits, r_used)._toValidInt(); | 1383 return z._revert(r_digits, r_used)._toValidInt(); |
1384 } | 1384 } |
| 1385 e = e._toBigint(); |
1385 var k; | 1386 var k; |
1386 if (e_bitlen < 18) k = 1; | 1387 if (e_bitlen < 18) k = 1; |
1387 else if (e_bitlen < 48) k = 3; | 1388 else if (e_bitlen < 48) k = 3; |
1388 else if (e_bitlen < 144) k = 4; | 1389 else if (e_bitlen < 144) k = 4; |
1389 else if (e_bitlen < 768) k = 5; | 1390 else if (e_bitlen < 768) k = 5; |
1390 else k = 6; | 1391 else k = 6; |
1391 _Reduction z = new _Montgomery(m); | 1392 _Reduction z = new _Montgomery(m); |
1392 var n = 3; | 1393 var n = 3; |
1393 final k1 = k - 1; | 1394 final k1 = k - 1; |
1394 final km = (1 << k) - 1; | 1395 final km = (1 << k) - 1; |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1581 var dl = digits[i] & _Bigint._DIGIT2_MASK; | 1582 var dl = digits[i] & _Bigint._DIGIT2_MASK; |
1582 args[_MU] = | 1583 args[_MU] = |
1583 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint._DIGIT2_BITS)) | 1584 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint._DIGIT2_BITS)) |
1584 & _Bigint._DIGIT_MASK; | 1585 & _Bigint._DIGIT_MASK; |
1585 return 1; | 1586 return 1; |
1586 } | 1587 } |
1587 | 1588 |
1588 // r = x*R mod _m. | 1589 // r = x*R mod _m. |
1589 // Return r_used. | 1590 // Return r_used. |
1590 int _convert(_Bigint x, Uint32List r_digits) { | 1591 int _convert(_Bigint x, Uint32List r_digits) { |
| 1592 // Montgomery reduction only works if abs(x) < _m. |
| 1593 assert(x._abs() < _m); |
1591 var r = x._abs()._dlShift(_m._used)._rem(_m); | 1594 var r = x._abs()._dlShift(_m._used)._rem(_m); |
1592 if (x._neg && !r._neg && r._used > 0) { | 1595 if (x._neg && !r._neg && r._used > 0) { |
1593 r = _m._sub(r); | 1596 r = _m._sub(r); |
1594 } | 1597 } |
1595 var used = r._used; | 1598 var used = r._used; |
1596 var digits = r._digits; | 1599 var digits = r._digits; |
1597 var i = used + (used & 1); | 1600 var i = used + (used & 1); |
1598 while (--i >= 0) { | 1601 while (--i >= 0) { |
1599 r_digits[i] = digits[i]; | 1602 r_digits[i] = digits[i]; |
1600 } | 1603 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1688 var neg_norm_m = _Bigint._ONE._dlShift(nm_used)._sub(_norm_m); | 1691 var neg_norm_m = _Bigint._ONE._dlShift(nm_used)._sub(_norm_m); |
1689 if (neg_norm_m._used < nm_used) { | 1692 if (neg_norm_m._used < nm_used) { |
1690 _neg_norm_m_digits = | 1693 _neg_norm_m_digits = |
1691 _Bigint._cloneDigits(neg_norm_m._digits, 0, nm_used, nm_used); | 1694 _Bigint._cloneDigits(neg_norm_m._digits, 0, nm_used, nm_used); |
1692 } else { | 1695 } else { |
1693 _neg_norm_m_digits = neg_norm_m._digits; | 1696 _neg_norm_m_digits = neg_norm_m._digits; |
1694 } | 1697 } |
1695 // _neg_norm_m_digits is read-only and has nm_used digits (possibly | 1698 // _neg_norm_m_digits is read-only and has nm_used digits (possibly |
1696 // including several leading zeros) plus a leading zero for 64-bit | 1699 // including several leading zeros) plus a leading zero for 64-bit |
1697 // processing. | 1700 // processing. |
1698 _t_digits = new Uint32List(2*nm_used); | 1701 _t_digits = new Uint32List(2*nm_used + 2); |
1699 } | 1702 } |
1700 | 1703 |
1701 int _convert(_Bigint x, Uint32List r_digits) { | 1704 int _convert(_Bigint x, Uint32List r_digits) { |
1702 var digits; | 1705 var digits; |
1703 var used; | 1706 var used; |
1704 if (x._neg || x._compare(_m) >= 0) { | 1707 if (x._neg || x._compare(_m) >= 0) { |
1705 var r = x._rem(_m); | 1708 var r = x._rem(_m); |
1706 if (x._neg && !r._neg && r._used > 0) { | 1709 if (x._neg && !r._neg && r._used > 0) { |
1707 r = _m._sub(r); | 1710 r = _m._sub(r); |
1708 } | 1711 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1743 | 1746 |
1744 int _mul(Uint32List x_digits, int x_used, | 1747 int _mul(Uint32List x_digits, int x_used, |
1745 Uint32List y_digits, int y_used, | 1748 Uint32List y_digits, int y_used, |
1746 Uint32List r_digits) { | 1749 Uint32List r_digits) { |
1747 var r_used = _Bigint._mulDigits(x_digits, x_used, | 1750 var r_used = _Bigint._mulDigits(x_digits, x_used, |
1748 y_digits, y_used, | 1751 y_digits, y_used, |
1749 r_digits); | 1752 r_digits); |
1750 return _reduce(r_digits, r_used); | 1753 return _reduce(r_digits, r_used); |
1751 } | 1754 } |
1752 } | 1755 } |
OLD | NEW |