Index: runtime/lib/bigint.dart |
=================================================================== |
--- runtime/lib/bigint.dart (revision 43814) |
+++ runtime/lib/bigint.dart (working copy) |
@@ -1078,7 +1078,6 @@ |
Uint32List yt_qd, |
Uint32List t_digits, |
Uint32List r_digits) { |
- assert(y_used > 0 && x_used >= y_used); |
// Initialize r_digits to normalized positive dividend. |
var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits); |
// For 64-bit processing, make sure y_used, i, and j are even. |
@@ -1345,16 +1344,17 @@ |
if (e < 0) throw new RangeError(e); |
if (m <= 0) throw new RangeError(m); |
if (e == 0) return 1; |
- e = e._toBigint(); |
m = m._toBigint(); |
final m_used = m._used; |
final m_used2p2 = 2*m_used + 2; |
final e_bitlen = e.bitLength; |
if (e_bitlen <= 0) return 1; |
- if ((e is! _Bigint) || m.isEven) { |
- _Reduction z = (e_bitlen < 8 || m.isEven) ? |
+ final bool cannotUseMontgomery = m.isEven || _abs() >= m; |
+ if (cannotUseMontgomery || e_bitlen < 64) { |
+ _Reduction z = (cannotUseMontgomery || e_bitlen < 8) ? |
new _Classic(m) : new _Montgomery(m); |
- // TODO(regis): Should we use Barrett reduction for an even modulus? |
+ // TODO(regis): Should we use Barrett reduction for an even modulus and a |
+ // large exponent? |
var r_digits = new Uint32List(m_used2p2); |
var r2_digits = new Uint32List(m_used2p2); |
var g_digits = new Uint32List(m_used + (m_used & 1)); |
@@ -1382,6 +1382,7 @@ |
} |
return z._revert(r_digits, r_used)._toValidInt(); |
} |
+ e = e._toBigint(); |
var k; |
if (e_bitlen < 18) k = 1; |
else if (e_bitlen < 48) k = 3; |
@@ -1588,6 +1589,8 @@ |
// r = x*R mod _m. |
// Return r_used. |
int _convert(_Bigint x, Uint32List r_digits) { |
+ // Montgomery reduction only works if abs(x) < _m. |
+ assert(x._abs() < _m); |
var r = x._abs()._dlShift(_m._used)._rem(_m); |
if (x._neg && !r._neg && r._used > 0) { |
r = _m._sub(r); |
@@ -1695,7 +1698,7 @@ |
// _neg_norm_m_digits is read-only and has nm_used digits (possibly |
// including several leading zeros) plus a leading zero for 64-bit |
// processing. |
- _t_digits = new Uint32List(2*nm_used); |
+ _t_digits = new Uint32List(2*nm_used + 2); |
} |
int _convert(_Bigint x, Uint32List r_digits) { |