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) throw new UnimplementedError(); |
| 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 |