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

Unified Diff: runtime/lib/bigint.dart

Issue 747483002: Resubmit bigint changes of r41817 that were later reverted. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/vm/intrinsifier_x64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/lib/bigint.dart
===================================================================
--- runtime/lib/bigint.dart (revision 41860)
+++ runtime/lib/bigint.dart (working copy)
@@ -58,7 +58,6 @@
// Bigint constant values.
// Note: Not declared as final in order to satisfy optimizer, which expects
// constants to be in canonical form (Smi).
- static _Bigint ZERO = new _Bigint();
static _Bigint ONE = new _Bigint()._setInt(1);
zra 2014/11/20 22:56:16 final?
regis 2014/11/20 23:17:40 No. See comment above.
// Digit conversion table for parsing.
@@ -203,36 +202,57 @@
_Bigint _toBigint() => this;
// Make sure at least 'length' _digits are allocated.
- // Copy existing _digits if reallocation is necessary.
- // TODO(regis): Check that we are not preserving _digits unnecessarily.
+ // Copy existing and used _digits if reallocation is necessary.
+ // Avoid preserving _digits unnecessarily by calling this function with a
+ // meaningful _used field.
void _ensureLength(int length) {
+ length++; // Account for leading zero for 64-bit processing.
var digits = _digits;
- if (length > 0 && (length > digits.length)) {
+ if (length > digits.length) {
var new_digits = new Uint32List(length + EXTRA_DIGITS);
- for (var i = _used; --i >= 0; ) {
- new_digits[i] = digits[i];
+ _digits = new_digits;
+ var used = _used;
+ if (used > 0) {
+ var i = used + 1; // Copy leading zero for 64-bit processing.
+ while (--i >= 0) {
+ new_digits[i] = digits[i];
+ }
}
- _digits = new_digits;
}
}
// Clamp off excess high _digits.
void _clamp() {
- var digits = _digits;
- while (_used > 0 && digits[_used - 1] == 0) {
- --_used;
+ var used = _used;
+ if (used > 0) {
+ var digits = _digits;
+ if (digits[used - 1] == 0) {
+ do {
+ --used;
+ } while (used > 0 && digits[used - 1] == 0);
+ _used = used;
+ }
+ digits[used] = 0; // Set leading zero for 64-bit processing.
}
}
// Copy this to r.
void _copyTo(_Bigint r) {
- r._ensureLength(_used);
- var digits = _digits;
- var r_digits = r._digits;
- for (var i = _used - 1; i >= 0; --i) {
- r_digits[i] = digits[i];
+ var used = _used;
+ if (used > 0) {
+ // We could set r._used to 0 in order to avoid preserving digits. However,
+ // it would be wrong to do so if this === r. Checking is too expensive.
+ // This case does not occur in the current implementation, but we want to
+ // remain safe.
+ r._ensureLength(used);
+ var digits = _digits;
+ var r_digits = r._digits;
+ var i = used + 1; // Copy leading zero for 64-bit processing.
+ while (--i >= 0) {
+ r_digits[i] = digits[i];
+ }
}
- r._used = _used;
+ r._used = used;
r._neg = _neg;
}
@@ -249,14 +269,22 @@
// r = this << n*DIGIT_BITS.
void _dlShiftTo(int n, _Bigint r) {
- var r_used = _used + n;
+ var used = _used;
+ if (used == 0) {
+ r._used = 0;
+ r._neg = false;
+ return;
+ }
+ var r_used = used + n;
r._ensureLength(r_used);
var digits = _digits;
var r_digits = r._digits;
- for (var i = _used - 1; i >= 0; --i) {
+ var i = used + 1; // Copy leading zero for 64-bit processing.
+ while (--i >= 0) {
r_digits[i + n] = digits[i];
}
- for (var i = n - 1; i >= 0; --i) {
+ i = n;
+ while (--i >= 0) {
r_digits[i] = 0;
}
r._used = r_used;
@@ -265,14 +293,22 @@
// r = this >> n*DIGIT_BITS.
void _drShiftTo(int n, _Bigint r) {
- var r_used = _used - n;
- if (r_used < 0) {
+ var used = _used;
+ if (used == 0) {
+ r._used = 0;
+ r._neg = false;
+ return;
+ }
+ var r_used = used - n;
+ if (r_used <= 0) {
if (_neg) {
// Set r to -1.
+ r._used = 0; // No digits to preserve.
+ r._ensureLength(1);
r._neg = true;
- r._ensureLength(1);
r._used = 1;
r._digits[0] = 1;
+ r._digits[1] = 0; // Set leading zero for 64-bit processing.
} else {
// Set r to 0.
r._neg = false;
@@ -283,8 +319,7 @@
r._ensureLength(r_used);
var digits = _digits;
var r_digits = r._digits;
- var used = _used;
- for (var i = n; i < used; ++i) {
+ for (var i = n; i < used + 1; i++) { // Copy leading zero for 64-bit proc.
r_digits[i - n] = digits[i];
}
r._used = r_used;
@@ -315,11 +350,13 @@
var digits = _digits;
var r_digits = r._digits;
var c = 0;
- for (var i = _used - 1; i >= 0; --i) {
+ var i = _used;
+ while (--i >= 0) {
r_digits[i + ds + 1] = (digits[i] >> cbs) | c;
c = (digits[i] & bm) << bs;
}
- for (var i = ds - 1; i >= 0; --i) {
+ i = ds;
+ while (--i >= 0) {
r_digits[i] = 0;
}
r_digits[ds] = c;
@@ -341,9 +378,11 @@
if (_neg) {
// Set r to -1.
r._neg = true;
+ r._used = 0; // No digits to preserve.
r._ensureLength(1);
r._used = 1;
r._digits[0] = 1;
+ r._digits[1] = 0; // Set leading zero for 64-bit processing.
} else {
// Set r to 0.
r._neg = false;
@@ -358,7 +397,7 @@
var r_digits = r._digits;
r_digits[0] = digits[ds] >> bs;
var used = _used;
- for (var i = ds + 1; i < used; ++i) {
+ for (var i = ds + 1; i < used; i++) {
r_digits[i - ds - 1] |= (digits[i] & bm) << cbs;
r_digits[i - ds] = digits[i] >> bs;
}
@@ -867,6 +906,11 @@
// TODO(regis): Use karatsuba multiplication when appropriate.
var used = _used;
var a_used = a._used;
+ if (used == 0 || a_used == 0) {
+ r._used = 0;
+ r._neg = false;
+ return;
+ }
var r_used = used + a_used;
r._ensureLength(r_used);
var digits = _digits;
@@ -873,7 +917,7 @@
var a_digits = a._digits;
var r_digits = r._digits;
r._used = r_used;
- var i = r_used;
+ var i = r_used + 1; // Set leading zero for 64-bit processing.
while (--i >= 0) {
r_digits[i] = 0;
}
@@ -887,11 +931,16 @@
// r = this^2, r != this.
void _sqrTo(_Bigint r) {
var used = _used;
+ if (used == 0) {
+ r._used = 0;
+ r._neg = false;
+ return;
+ }
var r_used = 2 * used;
r._ensureLength(r_used);
var digits = _digits;
var r_digits = r._digits;
- var i = r_used;
+ var i = r_used + 1; // Set leading zero for 64-bit processing.
while (--i >= 0) {
r_digits[i] = 0;
}
@@ -970,6 +1019,7 @@
var r_digits = r._digits;
if (r._compareTo(t) >= 0) {
r_digits[r._used++] = 1;
+ r_digits[r._used] = 0; // Set leading zero for 64-bit processing.
r._subTo(t, r);
}
ONE._dlShiftTo(y_used, t);
@@ -977,6 +1027,7 @@
while (y._used < y_used) {
y_digits[y._used++] = 0;
}
+ y_digits[y._used] = 0; // Set leading zero for 64-bit processing.
Uint32List args = new Uint32List(2);
args[_YT] = yt;
while (--j >= 0) {
@@ -992,8 +1043,8 @@
}
if (q != null) {
r._drShiftTo(y_used, q);
- if (_neg != a._neg) {
- ZERO._subTo(q, q);
+ if (_neg != a._neg && q._used > 0) {
+ q._neg = !q._neg;
}
}
r._used = y_used;
@@ -1001,8 +1052,8 @@
if (nsh > 0) {
r._rShiftTo(nsh, r); // Denormalize remainder.
}
- if (_neg) {
- ZERO._subTo(r, r);
+ if (_neg && r._used > 0) {
+ r._neg = !r._neg;
}
}
@@ -1419,9 +1470,10 @@
while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later.
x_digits[x._used++] = 0;
}
+ x_digits[x._used] = 0; // Set leading zero for 64-bit processing.
var m_used = _m._used;
var m_digits = _m._digits;
- for (var i = 0; i < m_used; ++i) {
+ for (var i = 0; i < m_used; i++) {
_mulMod(_rho_mu, x_digits, i);
_Bigint._mulAdd(_rho_mu, _MU, m_digits, 0, x_digits, i, m_used);
}
« no previous file with comments | « no previous file | runtime/vm/intrinsifier_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698