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 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 assert(r_digits.length >= r_used + (r_used & 1)); | 260 assert(r_digits.length >= r_used + (r_used & 1)); |
261 for (var i = n; i < x_used; i++) { | 261 for (var i = n; i < x_used; i++) { |
262 r_digits[i - n] = x_digits[i]; | 262 r_digits[i - n] = x_digits[i]; |
263 } | 263 } |
264 if (r_used.isOdd) { | 264 if (r_used.isOdd) { |
265 r_digits[r_used] = 0; | 265 r_digits[r_used] = 0; |
266 } | 266 } |
267 return r_used; | 267 return r_used; |
268 } | 268 } |
269 | 269 |
270 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n. | 270 // r_digits[ds..x_used+ds] = x_digits[0..x_used-1] << (n % _DIGIT_BITS) |
| 271 // where ds = ceil(n / _DIGIT_BITS) |
| 272 // Doesn't clear digits below ds. |
271 static void _lsh(Uint32List x_digits, int x_used, int n, | 273 static void _lsh(Uint32List x_digits, int x_used, int n, |
272 Uint32List r_digits) { | 274 Uint32List r_digits) { |
273 final ds = n ~/ _DIGIT_BITS; | 275 final ds = n ~/ _DIGIT_BITS; |
274 final bs = n % _DIGIT_BITS; | 276 final bs = n % _DIGIT_BITS; |
275 final cbs = _DIGIT_BITS - bs; | 277 final cbs = _DIGIT_BITS - bs; |
276 final bm = (1 << cbs) - 1; | 278 final bm = (1 << cbs) - 1; |
277 var c = 0; | 279 var c = 0; |
278 var i = x_used; | 280 var i = x_used; |
279 while (--i >= 0) { | 281 while (--i >= 0) { |
280 final d = x_digits[i]; | 282 final d = x_digits[i]; |
(...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 | 1399 |
1398 // Returns pow(this, e) % m, with e >= 0, m > 0. | 1400 // Returns pow(this, e) % m, with e >= 0, m > 0. |
1399 int modPow(int e, int m) { | 1401 int modPow(int e, int m) { |
1400 if (e is! int) throw new ArgumentError(e); | 1402 if (e is! int) throw new ArgumentError(e); |
1401 if (m is! int) throw new ArgumentError(m); | 1403 if (m is! int) throw new ArgumentError(m); |
1402 if (e < 0) throw new RangeError(e); | 1404 if (e < 0) throw new RangeError(e); |
1403 if (m <= 0) throw new RangeError(m); | 1405 if (m <= 0) throw new RangeError(m); |
1404 if (e == 0) return 1; | 1406 if (e == 0) return 1; |
1405 m = m._toBigint(); | 1407 m = m._toBigint(); |
1406 final m_used = m._used; | 1408 final m_used = m._used; |
1407 final m_used2p4 = 2*m_used + 4; | 1409 final m_used2p4 = 2 * m_used + 4; |
1408 final e_bitlen = e.bitLength; | 1410 final e_bitlen = e.bitLength; |
1409 if (e_bitlen <= 0) return 1; | 1411 if (e_bitlen <= 0) return 1; |
1410 final bool cannotUseMontgomery = m.isEven || _abs() >= m; | 1412 final bool cannotUseMontgomery = m.isEven || _abs() >= m; |
1411 if (cannotUseMontgomery || e_bitlen < 64) { | 1413 if (cannotUseMontgomery || e_bitlen < 64) { |
1412 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) ? | 1414 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) ? |
1413 new _Classic(m) : new _Montgomery(m); | 1415 new _Classic(m) : new _Montgomery(m); |
1414 // TODO(regis): Should we use Barrett reduction for an even modulus and a | 1416 // TODO(regis): Should we use Barrett reduction for an even modulus and a |
1415 // large exponent? | 1417 // large exponent? |
1416 var r_digits = new Uint32List(m_used2p4); | 1418 var r_digits = new Uint32List(m_used2p4); |
1417 var r2_digits = new Uint32List(m_used2p4); | 1419 var r2_digits = new Uint32List(m_used2p4); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1555 if (inv) { | 1557 if (inv) { |
1556 if ((y_used == 1) && (y_digits[0] == 1)) return 1; | 1558 if ((y_used == 1) && (y_digits[0] == 1)) return 1; |
1557 if ((y_used == 0) || (y_digits[0].isEven && x_digits[0].isEven)) { | 1559 if ((y_used == 0) || (y_digits[0].isEven && x_digits[0].isEven)) { |
1558 throw new RangeError("Not coprime"); | 1560 throw new RangeError("Not coprime"); |
1559 } | 1561 } |
1560 } else { | 1562 } else { |
1561 if ((x_used == 0) || (y_used == 0)) throw new RangeError(0); | 1563 if ((x_used == 0) || (y_used == 0)) throw new RangeError(0); |
1562 if (((x_used == 1) && (x_digits[0] == 1)) || | 1564 if (((x_used == 1) && (x_digits[0] == 1)) || |
1563 ((y_used == 1) && (y_digits[0] == 1))) return 1; | 1565 ((y_used == 1) && (y_digits[0] == 1))) return 1; |
1564 bool xy_cloned = false; | 1566 bool xy_cloned = false; |
1565 while (x.isEven && y.isEven) { | 1567 while (((x_digits[0] & 1) == 0) && ((y_digits[0] & 1) == 0)) { |
1566 _rsh(x_digits, x_used, 1, x_digits); | 1568 _rsh(x_digits, x_used, 1, x_digits); |
1567 _rsh(y_digits, y_used, 1, y_digits); | 1569 _rsh(y_digits, y_used, 1, y_digits); |
1568 s++; | 1570 s++; |
1569 } | 1571 } |
1570 if (s >= _DIGIT_BITS) { | 1572 if (s >= _DIGIT_BITS) { |
1571 var sd = s >> _LOG2_DIGIT_BITS; | 1573 var sd = s >> _LOG2_DIGIT_BITS; |
1572 x_used -= sd; | 1574 x_used -= sd; |
1573 y_used -= sd; | 1575 y_used -= sd; |
1574 m_used -= sd; | 1576 m_used -= sd; |
1575 } | 1577 } |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1739 } else { | 1741 } else { |
1740 _absAdd(d_digits, abcd_used, b_digits, abcd_used, d_digits); | 1742 _absAdd(d_digits, abcd_used, b_digits, abcd_used, d_digits); |
1741 } | 1743 } |
1742 } | 1744 } |
1743 // Exit loop if u == 0. | 1745 // Exit loop if u == 0. |
1744 var i = m_used; | 1746 var i = m_used; |
1745 while ((i > 0) && (u_digits[i - 1] == 0)) --i; | 1747 while ((i > 0) && (u_digits[i - 1] == 0)) --i; |
1746 if (i == 0) break; | 1748 if (i == 0) break; |
1747 } | 1749 } |
1748 if (!inv) { | 1750 if (!inv) { |
1749 if (s > 0) { | 1751 // TODO(regis): Make this work correctly: |
1750 _lsh(v_digits, m_used, s, v_digits); | 1752 // if (s > 0) { |
1751 } | 1753 // m_used = _dlShiftDigits(v_digits, m_used, s, v_digits); |
1752 return new _Bigint(false, m_used, v_digits)._toValidInt(); | 1754 // } |
| 1755 return new _Bigint(false, m_used, v_digits)._toValidInt() << s; |
1753 } | 1756 } |
1754 // No inverse if v != 1. | 1757 // No inverse if v != 1. |
1755 var i = m_used - 1; | 1758 var i = m_used - 1; |
1756 while ((i > 0) && (v_digits[i] == 0)) --i; | 1759 while ((i > 0) && (v_digits[i] == 0)) --i; |
1757 if ((i != 0) || (v_digits[0] != 1)) throw new RangeError("Not coprime"); | 1760 if ((i != 0) || (v_digits[0] != 1)) throw new RangeError("Not coprime"); |
1758 | 1761 |
1759 if (d_neg) { | 1762 if (d_neg) { |
1760 if ((d_digits[m_used] != 0) || | 1763 if ((d_digits[m_used] != 0) || |
1761 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1764 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
1762 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1765 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2070 | 2073 |
2071 int _mul(Uint32List x_digits, int x_used, | 2074 int _mul(Uint32List x_digits, int x_used, |
2072 Uint32List y_digits, int y_used, | 2075 Uint32List y_digits, int y_used, |
2073 Uint32List r_digits) { | 2076 Uint32List r_digits) { |
2074 var r_used = _Bigint._mulDigits(x_digits, x_used, | 2077 var r_used = _Bigint._mulDigits(x_digits, x_used, |
2075 y_digits, y_used, | 2078 y_digits, y_used, |
2076 r_digits); | 2079 r_digits); |
2077 return _reduce(r_digits, r_used); | 2080 return _reduce(r_digits, r_used); |
2078 } | 2081 } |
2079 } | 2082 } |
OLD | NEW |