Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: runtime/lib/bigint.dart

Issue 1209523002: Make modInv throw Exception on incompatible operands. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | runtime/lib/integers.dart » ('j') | runtime/lib/integers.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | runtime/lib/integers.dart » ('j') | runtime/lib/integers.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698