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 1247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1258 num operator +(num other) { | 1258 num operator +(num other) { |
1259 return other._toBigintOrDouble()._addFromInteger(this); | 1259 return other._toBigintOrDouble()._addFromInteger(this); |
1260 } | 1260 } |
1261 num operator -(num other) { | 1261 num operator -(num other) { |
1262 return other._toBigintOrDouble()._subFromInteger(this); | 1262 return other._toBigintOrDouble()._subFromInteger(this); |
1263 } | 1263 } |
1264 num operator *(num other) { | 1264 num operator *(num other) { |
1265 return other._toBigintOrDouble()._mulFromInteger(this); | 1265 return other._toBigintOrDouble()._mulFromInteger(this); |
1266 } | 1266 } |
1267 num operator ~/(num other) { | 1267 num operator ~/(num other) { |
1268 if ((other is int) && (other == 0)) { | |
1269 throw const IntegerDivisionByZeroException(); | |
1270 } | |
1271 return other._toBigintOrDouble()._truncDivFromInteger(this); | 1268 return other._toBigintOrDouble()._truncDivFromInteger(this); |
1272 } | 1269 } |
1273 num operator %(num other) { | 1270 num operator %(num other) { |
1274 if ((other is int) && (other == 0)) { | |
1275 throw const IntegerDivisionByZeroException(); | |
1276 } | |
1277 return other._toBigintOrDouble()._moduloFromInteger(this); | 1271 return other._toBigintOrDouble()._moduloFromInteger(this); |
1278 } | 1272 } |
1279 int operator &(int other) { | 1273 int operator &(int other) { |
1280 return other._toBigintOrDouble()._bitAndFromInteger(this); | 1274 return other._toBigintOrDouble()._bitAndFromInteger(this); |
1281 } | 1275 } |
1282 int operator |(int other) { | 1276 int operator |(int other) { |
1283 return other._toBigintOrDouble()._bitOrFromInteger(this); | 1277 return other._toBigintOrDouble()._bitOrFromInteger(this); |
1284 } | 1278 } |
1285 int operator ^(int other) { | 1279 int operator ^(int other) { |
1286 return other._toBigintOrDouble()._bitXorFromInteger(this); | 1280 return other._toBigintOrDouble()._bitXorFromInteger(this); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1361 int _addFromInteger(int other) { | 1355 int _addFromInteger(int other) { |
1362 return other._toBigint()._add(this)._toValidInt(); | 1356 return other._toBigint()._add(this)._toValidInt(); |
1363 } | 1357 } |
1364 int _subFromInteger(int other) { | 1358 int _subFromInteger(int other) { |
1365 return other._toBigint()._sub(this)._toValidInt(); | 1359 return other._toBigint()._sub(this)._toValidInt(); |
1366 } | 1360 } |
1367 int _mulFromInteger(int other) { | 1361 int _mulFromInteger(int other) { |
1368 return other._toBigint()._mul(this)._toValidInt(); | 1362 return other._toBigint()._mul(this)._toValidInt(); |
1369 } | 1363 } |
1370 int _truncDivFromInteger(int other) { | 1364 int _truncDivFromInteger(int other) { |
1365 if (_used == 0) { | |
1366 throw const IntegerDivisionByZeroException(); | |
1367 } | |
1371 return other._toBigint()._div(this)._toValidInt(); | 1368 return other._toBigint()._div(this)._toValidInt(); |
1372 } | 1369 } |
1373 int _moduloFromInteger(int other) { | 1370 int _moduloFromInteger(int other) { |
1371 if (_used == 0) { | |
1372 throw const IntegerDivisionByZeroException(); | |
1373 } | |
1374 _Bigint result = other._toBigint()._rem(this); | 1374 _Bigint result = other._toBigint()._rem(this); |
1375 if (result._neg) { | 1375 if (result._neg) { |
1376 if (_neg) { | 1376 if (_neg) { |
1377 result = result._sub(this); | 1377 result = result._sub(this); |
1378 } else { | 1378 } else { |
1379 result = result._add(this); | 1379 result = result._add(this); |
1380 } | 1380 } |
1381 } | 1381 } |
1382 return result._toValidInt(); | 1382 return result._toValidInt(); |
1383 } | 1383 } |
1384 int _remainderFromInteger(int other) { | 1384 int _remainderFromInteger(int other) { |
1385 if (_used == 0) { | |
1386 throw const IntegerDivisionByZeroException(); | |
1387 } | |
1385 return other._toBigint()._rem(this)._toValidInt(); | 1388 return other._toBigint()._rem(this)._toValidInt(); |
1386 } | 1389 } |
1387 bool _greaterThanFromInteger(int other) { | 1390 bool _greaterThanFromInteger(int other) { |
1388 return other._toBigint()._compare(this) > 0; | 1391 return other._toBigint()._compare(this) > 0; |
1389 } | 1392 } |
1390 bool _equalToInteger(int other) { | 1393 bool _equalToInteger(int other) { |
1391 return other._toBigint()._compare(this) == 0; | 1394 return other._toBigint()._compare(this) == 0; |
1392 } | 1395 } |
1393 | 1396 |
1394 // Returns pow(this, e) % m, with e >= 0, m > 0. | 1397 // Returns pow(this, e) % m, with e >= 0, m > 0. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1527 r2_used = t_used; | 1530 r2_used = t_used; |
1528 if (--i < 0) { | 1531 if (--i < 0) { |
1529 i = _DIGIT_BITS - 1; | 1532 i = _DIGIT_BITS - 1; |
1530 --j; | 1533 --j; |
1531 } | 1534 } |
1532 } | 1535 } |
1533 } | 1536 } |
1534 assert(!is1); | 1537 assert(!is1); |
1535 return z._revert(r_digits, r_used)._toValidInt(); | 1538 return z._revert(r_digits, r_used)._toValidInt(); |
1536 } | 1539 } |
1540 | |
1541 // Returns 1/this % m, with m > 0. | |
1542 int modInverse(int m) { | |
1543 if (m is! int) throw new ArgumentError(m); | |
1544 if (m <= 0) throw new RangeError(m); | |
1545 m = m._toBigint(); | |
1546 // TODO(regis): Implement modInverse for an even modulus. | |
1547 if (m.isEven) return 0; | |
srdjan
2015/06/10 16:51:52
Maybe throw unimplemented instead of returning 0.
regis
2015/06/10 20:25:56
Done.
| |
1548 var t = this; | |
1549 if ((t._compare(m) >= 0) || t._neg) { | |
1550 t %= m; | |
1551 t = t._toBigint(); | |
1552 } | |
1553 final t_used = t._used; | |
1554 if (t_used == 0) { | |
1555 return 0; // No inverse. | |
1556 } | |
1557 final m_digits = m._digits; | |
1558 final m_used = m._used; | |
1559 final uv_len = m_used + (m_used & 1); | |
1560 var v_digits = _cloneDigits(t._digits, 0, t_used, uv_len); | |
1561 var u_digits = _cloneDigits(m_digits, 0, m_used, uv_len); | |
1562 | |
1563 // Variables b and d require one more digit for carry. | |
1564 final bd_used = m_used + 1; | |
1565 final bd_len = bd_used + (bd_used & 1); | |
1566 var b_digits = new Uint32List(bd_len); | |
1567 var d_digits = new Uint32List(bd_len); | |
1568 bool b_neg = false; | |
1569 bool d_neg = false; | |
1570 | |
1571 d_digits[0] = 1; | |
1572 | |
1573 while (true) { | |
1574 while ((u_digits[0] & 1) == 0) { | |
1575 _rsh(u_digits, m_used, 1, u_digits); | |
1576 if ((b_digits[0] & 1) == 1) { | |
1577 _absSub(m_digits, m_used, b_digits, m_used, b_digits); | |
1578 b_neg = !b_neg; | |
1579 } | |
1580 _rsh(b_digits, m_used, 1, b_digits); | |
1581 } | |
1582 while ((v_digits[0] & 1) == 0) { | |
1583 _rsh(v_digits, m_used, 1, v_digits); | |
1584 if ((d_digits[0] & 1) == 1) { | |
1585 _absSub(m_digits, m_used, d_digits, m_used, d_digits); | |
1586 d_neg = !d_neg; | |
1587 } | |
1588 _rsh(d_digits, m_used, 1, d_digits); | |
1589 } | |
1590 if (_compareDigits(u_digits, m_used, v_digits, m_used) >= 0) { | |
1591 _absSub(u_digits, m_used, v_digits, m_used, u_digits); | |
1592 if (b_neg == d_neg) { | |
1593 if (_compareDigits(b_digits, m_used, d_digits, m_used) >= 0) { | |
1594 _absSub(b_digits, m_used, d_digits, m_used, b_digits); | |
1595 } else { | |
1596 _absSub(d_digits, m_used, b_digits, m_used, b_digits); | |
1597 b_neg = !b_neg; | |
1598 } | |
1599 } else { | |
1600 _absAdd(b_digits, m_used, d_digits, m_used, b_digits); | |
1601 if ((b_digits[m_used] > 0) || | |
1602 (_compareDigits(b_digits, m_used, m_digits, m_used) > 0)) { | |
1603 _absSub(b_digits, bd_used, m_digits, m_used, b_digits); | |
1604 } | |
1605 } | |
1606 } else { | |
1607 _absSub(v_digits, m_used, u_digits, m_used, v_digits); | |
1608 if (b_neg == d_neg) { | |
1609 if (_compareDigits(d_digits, m_used, b_digits, m_used) >= 0) { | |
1610 _absSub(d_digits, m_used, b_digits, m_used, d_digits); | |
1611 } else { | |
1612 _absSub(b_digits, m_used, d_digits, m_used, d_digits); | |
1613 d_neg = !d_neg; | |
1614 } | |
1615 } else { | |
1616 _absAdd(d_digits, m_used, b_digits, m_used, d_digits); | |
1617 if ((d_digits[m_used] > 0) || | |
1618 (_compareDigits(d_digits, m_used, m_digits, m_used) > 0)) { | |
1619 _absSub(d_digits, bd_used, m_digits, m_used, d_digits); | |
1620 } | |
1621 } | |
1622 } | |
1623 // Exit loop if u == 0. | |
1624 var i = m_used; | |
1625 while ((i > 0) && (u_digits[i - 1] == 0)) { | |
1626 --i; | |
1627 } | |
1628 if (i == 0) break; | |
1629 } | |
1630 // No inverse if v != 1. | |
1631 for (var i = m_used - 1; i > 0; --i) { | |
1632 if (v_digits[i] != 0) return 0; // No inverse. | |
1633 } | |
1634 if (v_digits[0] != 1) return 0; // No inverse. | |
1635 | |
1636 if (d_neg) { | |
1637 _absSub(m_digits, m_used, d_digits, m_used, d_digits); | |
1638 } | |
1639 return new _Bigint(false, m_used, d_digits)._toValidInt(); | |
1640 } | |
1537 } | 1641 } |
1538 | 1642 |
1539 // Interface for modular reduction. | 1643 // Interface for modular reduction. |
1540 class _Reduction { | 1644 class _Reduction { |
1541 // Return the number of digits used by r_digits. | 1645 // Return the number of digits used by r_digits. |
1542 int _convert(_Bigint x, Uint32List r_digits); | 1646 int _convert(_Bigint x, Uint32List r_digits); |
1543 int _mul(Uint32List x_digits, int x_used, | 1647 int _mul(Uint32List x_digits, int x_used, |
1544 Uint32List y_digits, int y_used, Uint32List r_digits); | 1648 Uint32List y_digits, int y_used, Uint32List r_digits); |
1545 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits); | 1649 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits); |
1546 | 1650 |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1803 | 1907 |
1804 int _mul(Uint32List x_digits, int x_used, | 1908 int _mul(Uint32List x_digits, int x_used, |
1805 Uint32List y_digits, int y_used, | 1909 Uint32List y_digits, int y_used, |
1806 Uint32List r_digits) { | 1910 Uint32List r_digits) { |
1807 var r_used = _Bigint._mulDigits(x_digits, x_used, | 1911 var r_used = _Bigint._mulDigits(x_digits, x_used, |
1808 y_digits, y_used, | 1912 y_digits, y_used, |
1809 r_digits); | 1913 r_digits); |
1810 return _reduce(r_digits, r_used); | 1914 return _reduce(r_digits, r_used); |
1811 } | 1915 } |
1812 } | 1916 } |
OLD | NEW |