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

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

Issue 1174513004: Implement modInverse (bigint version does not support even modulus yet). (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address review comments 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') | no next file with comments »
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 1247 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | runtime/lib/integers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698