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 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1213 | 1213 |
1214 int get bitLength { | 1214 int get bitLength { |
1215 if (_used == 0) return 0; | 1215 if (_used == 0) return 0; |
1216 if (_neg) return (~this).bitLength; | 1216 if (_neg) return (~this).bitLength; |
1217 return _DIGIT_BITS*(_used - 1) + _nbits(_digits[_used - 1]); | 1217 return _DIGIT_BITS*(_used - 1) + _nbits(_digits[_used - 1]); |
1218 } | 1218 } |
1219 | 1219 |
1220 // This method must support smi._toBigint()._shrFromInt(int). | 1220 // This method must support smi._toBigint()._shrFromInt(int). |
1221 int _shrFromInt(int other) { | 1221 int _shrFromInt(int other) { |
1222 if (_used == 0) return other; // Shift amount is zero. | 1222 if (_used == 0) return other; // Shift amount is zero. |
1223 if (_neg) throw new RangeError(this); | 1223 if (_neg) throw new RangeError.range(this, 0, null); |
1224 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 1224 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
1225 var shift; | 1225 var shift; |
1226 if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) { | 1226 if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) { |
1227 if (other < 0) { | 1227 if (other < 0) { |
1228 return -1; | 1228 return -1; |
1229 } else { | 1229 } else { |
1230 return 0; | 1230 return 0; |
1231 } | 1231 } |
1232 } else { | 1232 } else { |
1233 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; | 1233 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; |
1234 } | 1234 } |
1235 return other._toBigint()._rShift(shift)._toValidInt(); | 1235 return other._toBigint()._rShift(shift)._toValidInt(); |
1236 } | 1236 } |
1237 | 1237 |
1238 // This method must support smi._toBigint()._shlFromInt(int). | 1238 // This method must support smi._toBigint()._shlFromInt(int). |
1239 // An out of memory exception is thrown if the result cannot be allocated. | 1239 // An out of memory exception is thrown if the result cannot be allocated. |
1240 int _shlFromInt(int other) { | 1240 int _shlFromInt(int other) { |
1241 if (_used == 0) return other; // Shift amount is zero. | 1241 if (_used == 0) return other; // Shift amount is zero. |
1242 if (_neg) throw new RangeError(this); | 1242 if (_neg) throw new RangeError.range(this, 0, null); |
1243 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 1243 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
1244 var shift; | 1244 var shift; |
1245 if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) { | 1245 if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) { |
1246 if (other == 0) return 0; // Shifted value is zero. | 1246 if (other == 0) return 0; // Shifted value is zero. |
1247 throw new OutOfMemoryError(); | 1247 throw new OutOfMemoryError(); |
1248 } else { | 1248 } else { |
1249 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; | 1249 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; |
1250 } | 1250 } |
1251 return other._toBigint()._lShift(shift)._toValidInt(); | 1251 return other._toBigint()._lShift(shift)._toValidInt(); |
1252 } | 1252 } |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1390 } | 1390 } |
1391 bool _greaterThanFromInteger(int other) { | 1391 bool _greaterThanFromInteger(int other) { |
1392 return other._toBigint()._compare(this) > 0; | 1392 return other._toBigint()._compare(this) > 0; |
1393 } | 1393 } |
1394 bool _equalToInteger(int other) { | 1394 bool _equalToInteger(int other) { |
1395 return other._toBigint()._compare(this) == 0; | 1395 return other._toBigint()._compare(this) == 0; |
1396 } | 1396 } |
1397 | 1397 |
1398 // Returns pow(this, e) % m, with e >= 0, m > 0. | 1398 // Returns pow(this, e) % m, with e >= 0, m > 0. |
1399 int modPow(int e, int m) { | 1399 int modPow(int e, int m) { |
1400 if (e is! int) throw new ArgumentError(e); | 1400 if (e is! int) throw new ArgumentError.value(e, "exponent"); |
regis
2015/06/24 15:40:43
Below, you added "not an integer"
Lasse Reichstein Nielsen
2015/06/30 05:50:47
Done.
| |
1401 if (m is! int) throw new ArgumentError(m); | 1401 if (m is! int) throw new ArgumentError.value(m, "modulus"); |
regis
2015/06/24 15:40:43
ditto
Lasse Reichstein Nielsen
2015/06/30 05:50:47
Done.
| |
1402 if (e < 0) throw new RangeError(e); | 1402 if (e < 0) throw new RangeError.range(e, 0, null, "exponent"); |
1403 if (m <= 0) throw new RangeError(m); | 1403 if (m <= 0) throw new RangeError.range(m, 1, null, "modulus"); |
1404 if (e == 0) return 1; | 1404 if (e == 0) return 1; |
1405 m = m._toBigint(); | 1405 m = m._toBigint(); |
1406 final m_used = m._used; | 1406 final m_used = m._used; |
1407 final m_used2p4 = 2*m_used + 4; | 1407 final m_used2p4 = 2*m_used + 4; |
1408 final e_bitlen = e.bitLength; | 1408 final e_bitlen = e.bitLength; |
1409 if (e_bitlen <= 0) return 1; | 1409 if (e_bitlen <= 0) return 1; |
1410 final bool cannotUseMontgomery = m.isEven || _abs() >= m; | 1410 final bool cannotUseMontgomery = m.isEven || _abs() >= m; |
1411 if (cannotUseMontgomery || e_bitlen < 64) { | 1411 if (cannotUseMontgomery || e_bitlen < 64) { |
1412 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) ? | 1412 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) ? |
1413 new _Classic(m) : new _Montgomery(m); | 1413 new _Classic(m) : new _Montgomery(m); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1534 --j; | 1534 --j; |
1535 } | 1535 } |
1536 } | 1536 } |
1537 } | 1537 } |
1538 assert(!is1); | 1538 assert(!is1); |
1539 return z._revert(r_digits, r_used)._toValidInt(); | 1539 return z._revert(r_digits, r_used)._toValidInt(); |
1540 } | 1540 } |
1541 | 1541 |
1542 // If inv is false, returns gcd(x, y). | 1542 // If inv is false, returns gcd(x, y). |
1543 // If inv is true and gcd(x, y) = 1, returns d, so that c*x + d*y = 1. | 1543 // If inv is true and gcd(x, y) = 1, returns d, so that c*x + d*y = 1. |
1544 // If inv is true and gcd(x, y) != 1, throws RangeError("Not coprime"). | 1544 // If inv is true and gcd(x, y) != 1, throws UnsupportedError("Not coprime"). |
1545 static int _binaryGcd(_Bigint x, _Bigint y, bool inv) { | 1545 static int _binaryGcd(_Bigint x, _Bigint y, bool inv) { |
1546 var x_digits = x._digits; | 1546 var x_digits = x._digits; |
1547 var y_digits = y._digits; | 1547 var y_digits = y._digits; |
1548 var x_used = x._used; | 1548 var x_used = x._used; |
1549 var y_used = y._used; | 1549 var y_used = y._used; |
1550 var m_used = x_used > y_used ? x_used : y_used; | 1550 var m_used = x_used > y_used ? x_used : y_used; |
1551 final m_len = m_used + (m_used & 1); | 1551 final m_len = m_used + (m_used & 1); |
1552 x_digits = _cloneDigits(x_digits, 0, x_used, m_len); | 1552 x_digits = _cloneDigits(x_digits, 0, x_used, m_len); |
1553 y_digits = _cloneDigits(y_digits, 0, y_used, m_len); | 1553 y_digits = _cloneDigits(y_digits, 0, y_used, m_len); |
1554 int s = 0; | 1554 int s = 0; |
1555 if (inv) { | 1555 if (inv) { |
1556 if ((y_used == 1) && (y_digits[0] == 1)) return 1; | 1556 if ((y_used == 1) && (y_digits[0] == 1)) return 1; |
1557 if ((y_used == 0) || (y_digits[0].isEven && x_digits[0].isEven)) { | 1557 if ((y_used == 0) || (y_digits[0].isEven && x_digits[0].isEven)) { |
1558 throw new RangeError("Not coprime"); | 1558 throw new UnsupportedError("Not coprime"); |
1559 } | 1559 } |
1560 } else { | 1560 } else { |
1561 if ((x_used == 0) || (y_used == 0)) throw new RangeError(0); | 1561 if (x_used == 0) { |
1562 throw new ArgumentError.value(0, "first operand", "must not be zero"); | |
regis
2015/06/24 15:40:43
x is 'this' at this point, i.e. the receiver for g
Lasse Reichstein Nielsen
2015/06/25 07:22:21
I wasn't able to convince myself that this was alw
| |
1563 } | |
1564 if (y_used == 0) { | |
1565 throw new ArgumentError.value(0, "second operand", "must not be zero"); | |
regis
2015/06/24 15:40:43
y is the 'other' argument of gcd.
Lasse Reichstein Nielsen
2015/06/30 05:50:47
Done.
| |
1566 } | |
1562 if (((x_used == 1) && (x_digits[0] == 1)) || | 1567 if (((x_used == 1) && (x_digits[0] == 1)) || |
1563 ((y_used == 1) && (y_digits[0] == 1))) return 1; | 1568 ((y_used == 1) && (y_digits[0] == 1))) return 1; |
1564 bool xy_cloned = false; | 1569 bool xy_cloned = false; |
1565 while (x.isEven && y.isEven) { | 1570 while (x.isEven && y.isEven) { |
1566 _rsh(x_digits, x_used, 1, x_digits); | 1571 _rsh(x_digits, x_used, 1, x_digits); |
1567 _rsh(y_digits, y_used, 1, y_digits); | 1572 _rsh(y_digits, y_used, 1, y_digits); |
1568 s++; | 1573 s++; |
1569 } | 1574 } |
1570 if (s >= _DIGIT_BITS) { | 1575 if (s >= _DIGIT_BITS) { |
1571 var sd = s >> _LOG2_DIGIT_BITS; | 1576 var sd = s >> _LOG2_DIGIT_BITS; |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1747 } | 1752 } |
1748 if (!inv) { | 1753 if (!inv) { |
1749 if (s > 0) { | 1754 if (s > 0) { |
1750 _lsh(v_digits, m_used, s, v_digits); | 1755 _lsh(v_digits, m_used, s, v_digits); |
1751 } | 1756 } |
1752 return new _Bigint(false, m_used, v_digits)._toValidInt(); | 1757 return new _Bigint(false, m_used, v_digits)._toValidInt(); |
1753 } | 1758 } |
1754 // No inverse if v != 1. | 1759 // No inverse if v != 1. |
1755 var i = m_used - 1; | 1760 var i = m_used - 1; |
1756 while ((i > 0) && (v_digits[i] == 0)) --i; | 1761 while ((i > 0) && (v_digits[i] == 0)) --i; |
1757 if ((i != 0) || (v_digits[0] != 1)) throw new RangeError("Not coprime"); | 1762 if ((i != 0) || (v_digits[0] != 1)) { |
1763 throw new UnsupportedError("Not coprime"); | |
1764 } | |
1758 | 1765 |
1759 if (d_neg) { | 1766 if (d_neg) { |
1760 if ((d_digits[m_used] != 0) || | 1767 if ((d_digits[m_used] != 0) || |
1761 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1768 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
1762 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1769 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
1763 if ((d_digits[m_used] != 0) || | 1770 if ((d_digits[m_used] != 0) || |
1764 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1771 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
1765 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1772 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
1766 } else { | 1773 } else { |
1767 _absSub(x_digits, m_used, d_digits, m_used, d_digits); | 1774 _absSub(x_digits, m_used, d_digits, m_used, d_digits); |
1768 d_neg = false; | 1775 d_neg = false; |
1769 } | 1776 } |
1770 } else { | 1777 } else { |
1771 _absSub(x_digits, m_used, d_digits, m_used, d_digits); | 1778 _absSub(x_digits, m_used, d_digits, m_used, d_digits); |
1772 d_neg = false; | 1779 d_neg = false; |
1773 } | 1780 } |
1774 } else if ((d_digits[m_used] != 0) || | 1781 } else if ((d_digits[m_used] != 0) || |
1775 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1782 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
1776 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1783 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
1777 if ((d_digits[m_used] != 0) || | 1784 if ((d_digits[m_used] != 0) || |
1778 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1785 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
1779 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1786 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
1780 } | 1787 } |
1781 } | 1788 } |
1782 return new _Bigint(false, m_used, d_digits)._toValidInt(); | 1789 return new _Bigint(false, m_used, d_digits)._toValidInt(); |
1783 } | 1790 } |
1784 | 1791 |
1785 // Returns 1/this % m, with m > 0. | 1792 // Returns 1/this % m, with m > 0. |
1786 int modInverse(int m) { | 1793 int modInverse(int m) { |
1787 if (m is! int) throw new ArgumentError(m); | 1794 if (m is! int) { |
1788 if (m <= 0) throw new RangeError(m); | 1795 throw new ArgumentError.value(m, "modulus", "not an integer"); |
1796 } | |
1797 if (m <= 0) throw new RangeError.range(m, 1, null, "modulus"); | |
1789 if (m == 1) return 0; | 1798 if (m == 1) return 0; |
1790 m = m._toBigint(); | 1799 m = m._toBigint(); |
1791 var t = this; | 1800 var t = this; |
1792 if (t._neg || (t._absCompare(m) >= 0)) { | 1801 if (t._neg || (t._absCompare(m) >= 0)) { |
1793 t %= m; | 1802 t %= m; |
1794 t = t._toBigint(); | 1803 t = t._toBigint(); |
1795 } | 1804 } |
1796 return _binaryGcd(m, t, true); | 1805 return _binaryGcd(m, t, true); |
1797 } | 1806 } |
1798 | 1807 |
1799 // Returns gcd of abs(this) and abs(other), with this != 0 and other !=0. | 1808 // Returns gcd of abs(this) and abs(other), with this != 0 and other !=0. |
1800 int gcd(int other) { | 1809 int gcd(int other) { |
1801 if (other is! int) throw new ArgumentError(other); | 1810 if (other is! int) { |
1811 throw new ArgumentError.value(other, "other", "not an integer"); | |
1812 } | |
1802 return _binaryGcd(this, other._toBigint(), false); | 1813 return _binaryGcd(this, other._toBigint(), false); |
1803 } | 1814 } |
1804 } | 1815 } |
1805 | 1816 |
1806 // Interface for modular reduction. | 1817 // Interface for modular reduction. |
1807 class _Reduction { | 1818 class _Reduction { |
1808 // Return the number of digits used by r_digits. | 1819 // Return the number of digits used by r_digits. |
1809 int _convert(_Bigint x, Uint32List r_digits); | 1820 int _convert(_Bigint x, Uint32List r_digits); |
1810 int _mul(Uint32List x_digits, int x_used, | 1821 int _mul(Uint32List x_digits, int x_used, |
1811 Uint32List y_digits, int y_used, Uint32List r_digits); | 1822 Uint32List y_digits, int y_used, Uint32List r_digits); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2070 | 2081 |
2071 int _mul(Uint32List x_digits, int x_used, | 2082 int _mul(Uint32List x_digits, int x_used, |
2072 Uint32List y_digits, int y_used, | 2083 Uint32List y_digits, int y_used, |
2073 Uint32List r_digits) { | 2084 Uint32List r_digits) { |
2074 var r_used = _Bigint._mulDigits(x_digits, x_used, | 2085 var r_used = _Bigint._mulDigits(x_digits, x_used, |
2075 y_digits, y_used, | 2086 y_digits, y_used, |
2076 r_digits); | 2087 r_digits); |
2077 return _reduce(r_digits, r_used); | 2088 return _reduce(r_digits, r_used); |
2078 } | 2089 } |
2079 } | 2090 } |
OLD | NEW |