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

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

Issue 842033005: Make Bigint instances immutable by removing all setters. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/lib/integers.cc » ('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 20 matching lines...) Expand all
31 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF 31 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
32 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT 32 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
33 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 33 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34 * 34 *
35 * In addition, the following condition applies: 35 * In addition, the following condition applies:
36 * 36 *
37 * All redistributions must retain an intact copy of this copyright notice 37 * All redistributions must retain an intact copy of this copyright notice
38 * and disclaimer. 38 * and disclaimer.
39 */ 39 */
40 40
41 class _Bigint extends _IntegerImplementation implements int { 41 class _Bigint extends _IntegerImplementation implements int {
rmacnak 2015/02/04 19:24:53 It would be nice to have a comment saying Bigints
regis 2015/02/04 22:06:22 Done.
42 // Bits per digit. 42 // Bits per digit.
43 static const int DIGIT_BITS = 32; 43 static const int DIGIT_BITS = 32;
44 static const int DIGIT_BASE = 1 << DIGIT_BITS; 44 static const int DIGIT_BASE = 1 << DIGIT_BITS;
45 static const int DIGIT_MASK = (1 << DIGIT_BITS) - 1; 45 static const int DIGIT_MASK = (1 << DIGIT_BITS) - 1;
46 46
47 // Bits per half digit. 47 // Bits per half digit.
48 static const int DIGIT2_BITS = DIGIT_BITS >> 1; 48 static const int DIGIT2_BITS = DIGIT_BITS >> 1;
49 static const int DIGIT2_MASK = (1 << DIGIT2_BITS) - 1; 49 static const int DIGIT2_MASK = (1 << DIGIT2_BITS) - 1;
50 50
51 // Allocate extra digits so the bigint can be reused.
52 static const int EXTRA_DIGITS = 4;
53
54 // Min and max of non bigint values. 51 // Min and max of non bigint values.
55 static const int MIN_INT64 = (-1) << 63; 52 static const int MIN_INT64 = (-1) << 63;
56 static const int MAX_INT64 = 0x7fffffffffffffff; 53 static const int MAX_INT64 = 0x7fffffffffffffff;
57 54
58 // Bigint constant values. 55 // Bigint constant values.
59 // Note: Not declared as final in order to satisfy optimizer, which expects 56 // Note: Not declared as final in order to satisfy optimizer, which expects
rmacnak 2015/02/04 19:24:53 Optimizer is unhappy with final or just const? The
regis 2015/02/04 22:06:22 It's unhappy with final or const. I cannot make it
60 // constants to be in canonical form (Smi). 57 // constants to be in canonical form (Smi).
58 static _Bigint MINUS_ONE = new _Bigint._fromInt(-1);
59 static _Bigint ZERO = new _Bigint._fromInt(0);
61 static _Bigint ONE = new _Bigint._fromInt(1); 60 static _Bigint ONE = new _Bigint._fromInt(1);
62 61
63 // Digit conversion table for parsing. 62 // Internal data structure.
64 static final Map<int, int> DIGIT_TABLE = _createDigitTable(); 63 bool get _neg native "Bigint_getNeg";
64 int get _used native "Bigint_getUsed";
65 Uint32List get _digits native "Bigint_getDigits";
65 66
66 // Internal data structure. 67 // Factory returning an instance initialized with the given field values.
67 // TODO(regis): Remove the 3 native setters below and provide a constructor 68 // The 'digits' array is first clamped and 'used' is reduced accordingly.
68 // taking all 3 field values, which is equivalent to making the fields final. 69 // The last digit is set to a leading zero for 64-bit processing.
69 bool get _neg native "Bigint_getNeg"; 70 factory _Bigint(bool neg, int used, Uint32List digits)
70 void set _neg(bool value) native "Bigint_setNeg"; 71 native "Bigint_allocate";
71 int get _used native "Bigint_getUsed";
72 void set _used(int value) native "Bigint_setUsed";
73 Uint32List get _digits native "Bigint_getDigits";
74 void set _digits(Uint32List value) native "Bigint_setDigits";
75
76 // Factory returning an instance initialized to value 0.
77 factory _Bigint() native "Bigint_allocate";
78 72
79 // Factory returning an instance initialized to an integer value no larger 73 // Factory returning an instance initialized to an integer value no larger
80 // than a Mint. 74 // than a Mint.
81 factory _Bigint._fromInt(int i) { 75 factory _Bigint._fromInt(int i) {
82 assert(i is! _Bigint); 76 assert(i is! _Bigint);
83 bool neg; 77 var neg;
84 var l, h; 78 var l, h;
85 if (i < 0) { 79 if (i < 0) {
86 neg = true; 80 neg = true;
87 if (i == MIN_INT64) { 81 if (i == MIN_INT64) {
88 l = 0; 82 l = 0;
89 h = 0x80000000; 83 h = 0x80000000;
90 } else { 84 } else {
91 l = (-i) & DIGIT_MASK; 85 l = (-i) & DIGIT_MASK;
92 h = (-i) >> DIGIT_BITS; 86 h = (-i) >> DIGIT_BITS;
93 } 87 }
94 } else { 88 } else {
95 neg = false; 89 neg = false;
96 l = i & DIGIT_MASK; 90 l = i & DIGIT_MASK;
97 h = i >> DIGIT_BITS; 91 h = i >> DIGIT_BITS;
98 } 92 }
99 var result = new _Bigint(); 93 var digits = new Uint32List(2 + 1); // +1 for leading zero.
100 result._ensureLength(2); 94 digits[0] = l;
101 result._neg = neg; 95 digits[1] = h;
102 result._used = 2; 96 return new _Bigint(neg, 2, digits);
103 result._digits[0] = l;
104 result._digits[1] = h;
105 result._clamp();
106 return result;
107 } 97 }
108 98
109 // Create digit conversion table for parsing. 99 // Allocate an array of the given length (+1 for at least one leading zero
110 static Map<int, int> _createDigitTable() { 100 // digit) and copy digits[from..to-1] starting at index 0, followed by
111 Map table = new HashMap(); 101 // leading zero digits.
112 int digit, value; 102 static Uint32List _cloneDigits(Uint32List digits, int from, int to,
113 digit = "0".codeUnitAt(0); 103 int length) {
114 for(value = 0; value <= 9; ++value) table[digit++] = value; 104 length++; // +1 for leading zero.
115 digit = "a".codeUnitAt(0); 105 var r_digits = new Uint32List(length);
116 for(value = 10; value < 36; ++value) table[digit++] = value; 106 var n = to - from;
117 digit = "A".codeUnitAt(0); 107 for (var i = 0; i < n; i++) {
118 for(value = 10; value < 36; ++value) table[digit++] = value; 108 r_digits[i] = digits[from + i];
119 return table; 109 }
110 while (n < length) {
rmacnak 2015/02/04 19:24:53 Typed data is zero initialized.
regis 2015/02/04 22:06:23 Good point. Removed initialization here and at oth
111 r_digits[n++] = 0;
112 }
113 return r_digits;
120 } 114 }
121 115
122 // Return most compact integer (i.e. possibly Smi or Mint). 116 // Return most compact integer (i.e. possibly Smi or Mint).
123 // TODO(regis): Intrinsify.
124 int _toValidInt() { 117 int _toValidInt() {
125 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. 118 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised.
126 var used = _used; 119 var used = _used;
127 if (used == 0) return 0; 120 if (used == 0) return 0;
128 var digits = _digits; 121 var digits = _digits;
129 if (used == 1) return _neg ? -digits[0] : digits[0]; 122 if (used == 1) return _neg ? -digits[0] : digits[0];
130 if (used > 2) return this; 123 if (used > 2) return this;
131 if (_neg) { 124 if (_neg) {
132 if (digits[1] > 0x80000000) return this; 125 if (digits[1] > 0x80000000) return this;
133 if (digits[1] == 0x80000000) { 126 if (digits[1] == 0x80000000) {
134 if (digits[0] > 0) return this; 127 if (digits[0] > 0) return this;
135 return MIN_INT64; 128 return MIN_INT64;
136 } 129 }
137 return -((digits[1] << DIGIT_BITS) | digits[0]); 130 return -((digits[1] << DIGIT_BITS) | digits[0]);
138 } 131 }
139 if (digits[1] >= 0x80000000) return this; 132 if (digits[1] >= 0x80000000) return this;
140 return (digits[1] << DIGIT_BITS) | digits[0]; 133 return (digits[1] << DIGIT_BITS) | digits[0];
141 } 134 }
142 135
143 // Conversion from int to bigint. 136 // Conversion from int to bigint.
144 _Bigint _toBigint() => this; 137 _Bigint _toBigint() => this;
145 138
146 // Make sure at least 'length' _digits are allocated. 139 // Return -this.
147 // Copy existing and used _digits if reallocation is necessary. 140 _Bigint _negate() {
148 // Avoid preserving _digits unnecessarily by calling this function with a 141 var used = _used;
149 // meaningful _used field. 142 if (used == 0) {
150 void _ensureLength(int length) { 143 return this;
151 length++; // Account for leading zero for 64-bit processing.
152 var digits = _digits;
153 if (length > digits.length) {
154 var new_digits = new Uint32List(length + EXTRA_DIGITS);
155 _digits = new_digits;
156 var used = _used;
157 if (used > 0) {
158 var i = used + 1; // Copy leading zero for 64-bit processing.
159 while (--i >= 0) {
160 new_digits[i] = digits[i];
161 }
162 }
163 } 144 }
145 return new _Bigint(!_neg, used, _digits);
164 } 146 }
165 147
166 // Clamp off excess high _digits. 148 // Return abs(this).
167 void _clamp() { 149 _Bigint _abs() {
168 var used = _used; 150 var neg = _neg;
169 if (used > 0) { 151 if (!neg) {
170 var digits = _digits; 152 return this;
171 if (digits[used - 1] == 0) {
172 do {
173 --used;
174 } while (used > 0 && digits[used - 1] == 0);
175 _used = used;
176 }
177 digits[used] = 0; // Set leading zero for 64-bit processing.
178 } 153 }
179 } 154 return new _Bigint(!neg, _used, _digits);
180
181 // Copy this to r.
182 void _copyTo(_Bigint r) {
183 var used = _used;
184 if (used > 0) {
185 // We could set r._used to 0 in order to avoid preserving digits. However,
186 // it would be wrong to do so if this === r. Checking is too expensive.
187 // This case does not occur in the current implementation, but we want to
188 // remain safe.
189 r._ensureLength(used);
190 var digits = _digits;
191 var r_digits = r._digits;
192 var i = used + 1; // Copy leading zero for 64-bit processing.
193 while (--i >= 0) {
194 r_digits[i] = digits[i];
195 }
196 }
197 r._used = used;
198 r._neg = _neg;
199 } 155 }
200 156
201 // Return the bit length of digit x. 157 // Return the bit length of digit x.
202 int _nbits(int x) { 158 static int _nbits(int x) {
203 var r = 1, t; 159 var r = 1, t;
204 if ((t = x >> 16) != 0) { x = t; r += 16; } 160 if ((t = x >> 16) != 0) { x = t; r += 16; }
205 if ((t = x >> 8) != 0) { x = t; r += 8; } 161 if ((t = x >> 8) != 0) { x = t; r += 8; }
206 if ((t = x >> 4) != 0) { x = t; r += 4; } 162 if ((t = x >> 4) != 0) { x = t; r += 4; }
207 if ((t = x >> 2) != 0) { x = t; r += 2; } 163 if ((t = x >> 2) != 0) { x = t; r += 2; }
208 if ((x >> 1) != 0) { r += 1; } 164 if ((x >> 1) != 0) { r += 1; }
209 return r; 165 return r;
210 } 166 }
211 167
212 // r = this << n*DIGIT_BITS. 168 // Return this << n*DIGIT_BITS.
213 void _dlShiftTo(int n, _Bigint r) { 169 _Bigint _dlShift(int n) {
214 var used = _used; 170 var used = _used;
215 if (used == 0) { 171 if (used == 0) {
216 r._used = 0; 172 return ZERO;
217 r._neg = false;
218 return;
219 } 173 }
220 var r_used = used + n; 174 var r_used = used + n;
221 r._ensureLength(r_used);
222 var digits = _digits; 175 var digits = _digits;
223 var r_digits = r._digits; 176 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
224 var i = used + 1; // Copy leading zero for 64-bit processing. 177 var i = used;
225 while (--i >= 0) { 178 while (--i >= 0) {
226 r_digits[i + n] = digits[i]; 179 r_digits[i + n] = digits[i];
227 } 180 }
228 i = n; 181 i = n;
229 while (--i >= 0) { 182 while (--i >= 0) {
230 r_digits[i] = 0; 183 r_digits[i] = 0;
231 } 184 }
232 r._used = r_used; 185 return new _Bigint(_neg, r_used, r_digits);
233 r._neg = _neg;
234 } 186 }
235 187
236 // r = this >> n*DIGIT_BITS. 188 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*DIGIT_BITS.
237 void _drShiftTo(int n, _Bigint r) { 189 // Return r_used.
190 static int _dlShiftDigits(Uint32List x_digits, int x_used, int n,
191 Uint32List r_digits) {
192 if (x_used == 0) {
193 return 0;
194 }
195 if (n == 0 && r_digits == x_digits) {
196 return x_used;
197 }
198 var r_used = x_used + n;
199 assert(r_digits.length >= r_used + 1); // +1 for leading zero.
200 var i = x_used + 1; // +1 for leading zero.
201 while (--i >= 0) {
202 r_digits[i + n] = x_digits[i];
203 }
204 i = n;
205 while (--i >= 0) {
206 r_digits[i] = 0;
207 }
208 return r_used;
209 }
210
211 // Return this >> n*DIGIT_BITS.
212 _Bigint _drShift(int n) {
238 var used = _used; 213 var used = _used;
239 if (used == 0) { 214 if (used == 0) {
240 r._used = 0; 215 return ZERO;
241 r._neg = false;
242 return;
243 } 216 }
244 var r_used = used - n; 217 var r_used = used - n;
245 if (r_used <= 0) { 218 if (r_used <= 0) {
246 if (_neg) { 219 return _neg ? MINUS_ONE : ZERO;
247 // Set r to -1.
248 r._used = 0; // No digits to preserve.
249 r._ensureLength(1);
250 r._neg = true;
251 r._used = 1;
252 r._digits[0] = 1;
253 r._digits[1] = 0; // Set leading zero for 64-bit processing.
254 } else {
255 // Set r to 0.
256 r._neg = false;
257 r._used = 0;
258 }
259 return;
260 } 220 }
261 r._ensureLength(r_used);
262 var digits = _digits; 221 var digits = _digits;
263 var r_digits = r._digits; 222 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
264 for (var i = n; i < used + 1; i++) { // Copy leading zero for 64-bit proc. 223 for (var i = n; i < used; i++) {
265 r_digits[i - n] = digits[i]; 224 r_digits[i - n] = digits[i];
266 } 225 }
267 r._used = r_used; 226 var r = new _Bigint(_neg, r_used, r_digits);
268 r._neg = _neg;
269 if (_neg) { 227 if (_neg) {
270 // Round down if any bit was shifted out. 228 // Round down if any bit was shifted out.
271 for (var i = 0; i < n; i++) { 229 for (var i = 0; i < n; i++) {
272 if (digits[i] != 0) { 230 if (digits[i] != 0) {
273 r._subTo(ONE, r); 231 return r._sub(ONE);
274 break;
275 } 232 }
276 } 233 }
277 } 234 }
235 return r;
278 } 236 }
279 237
280 // r = this << n. 238 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n*DIGIT_BITS.
281 void _lShiftTo(int n, _Bigint r) { 239 // Return r_used.
240 static int _drShiftDigits(Uint32List x_digits, int x_used, int n,
241 Uint32List r_digits) {
242 var r_used = x_used - n;
243 if (r_used <= 0) {
244 return 0;
245 }
246 assert(r_digits.length >= r_used + 1); // +1 for leading zero.
247 for (var i = n; i < x_used + 1; i++) { // +1 for leading zero.
248 r_digits[i - n] = x_digits[i];
249 }
250 return r_used;
251 }
252
253 // Return this << n.
254 _Bigint _lShift(int n) {
282 var ds = n ~/ DIGIT_BITS; 255 var ds = n ~/ DIGIT_BITS;
283 var bs = n % DIGIT_BITS; 256 var bs = n % DIGIT_BITS;
284 if (bs == 0) { 257 if (bs == 0) {
285 _dlShiftTo(ds, r); 258 return _dlShift(ds);
286 return;
287 } 259 }
288 var cbs = DIGIT_BITS - bs; 260 var cbs = DIGIT_BITS - bs;
289 var bm = (1 << cbs) - 1; 261 var bm = (1 << cbs) - 1;
290 var r_used = _used + ds + 1; 262 var r_used = _used + ds + 1;
291 r._ensureLength(r_used);
292 var digits = _digits; 263 var digits = _digits;
293 var r_digits = r._digits; 264 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
294 var c = 0; 265 var c = 0;
295 var i = _used; 266 var i = _used;
296 while (--i >= 0) { 267 while (--i >= 0) {
297 r_digits[i + ds + 1] = (digits[i] >> cbs) | c; 268 r_digits[i + ds + 1] = (digits[i] >> cbs) | c;
298 c = (digits[i] & bm) << bs; 269 c = (digits[i] & bm) << bs;
299 } 270 }
300 i = ds; 271 i = ds;
301 while (--i >= 0) { 272 while (--i >= 0) {
302 r_digits[i] = 0; 273 r_digits[i] = 0;
303 } 274 }
304 r_digits[ds] = c; 275 r_digits[ds] = c;
305 r._used = r_used; 276 return new _Bigint(_neg, r_used, r_digits);
306 r._neg = _neg;
307 r._clamp();
308 } 277 }
309 278
310 // r = this >> n. 279 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n.
311 void _rShiftTo(int n, _Bigint r) { 280 // Return r_used.
281 static int _lShiftDigits(Uint32List x_digits, int x_used, int n,
282 Uint32List r_digits) {
312 var ds = n ~/ DIGIT_BITS; 283 var ds = n ~/ DIGIT_BITS;
313 var bs = n % DIGIT_BITS; 284 var bs = n % DIGIT_BITS;
314 if (bs == 0) { 285 if (bs == 0) {
315 _drShiftTo(ds, r); 286 return _dlShiftDigits(x_digits, x_used, ds, r_digits);
316 return; 287 }
288 var cbs = DIGIT_BITS - bs;
289 var bm = (1 << cbs) - 1;
290 var r_used = x_used + ds + 1;
291 assert(r_digits.length >= r_used + 1); // +1 for leading zero.
292 var c = 0;
293 var i = x_used;
294 while (--i >= 0) {
295 r_digits[i + ds + 1] = (x_digits[i] >> cbs) | c;
296 c = (x_digits[i] & bm) << bs;
297 }
298 i = ds;
299 while (--i >= 0) {
300 r_digits[i] = 0;
301 }
302 r_digits[ds] = c;
303 r_digits[r_used] = 0; // Set leading zero for 64-bit processing.
304 return r_used;
305 }
306
307 // Return this >> n.
308 _Bigint _rShift(int n) {
309 var ds = n ~/ DIGIT_BITS;
310 var bs = n % DIGIT_BITS;
311 if (bs == 0) {
312 return _drShift(ds);
317 } 313 }
318 var r_used = _used - ds; 314 var r_used = _used - ds;
319 if (r_used <= 0) { 315 if (r_used <= 0) {
320 if (_neg) { 316 return _neg ? MINUS_ONE : ZERO;
321 // Set r to -1.
322 r._neg = true;
323 r._used = 0; // No digits to preserve.
324 r._ensureLength(1);
325 r._used = 1;
326 r._digits[0] = 1;
327 r._digits[1] = 0; // Set leading zero for 64-bit processing.
328 } else {
329 // Set r to 0.
330 r._neg = false;
331 r._used = 0;
332 }
333 return;
334 } 317 }
335 var cbs = DIGIT_BITS - bs; 318 var cbs = DIGIT_BITS - bs;
336 var bm = (1 << bs) - 1; 319 var bm = (1 << bs) - 1;
337 r._ensureLength(r_used);
338 var digits = _digits; 320 var digits = _digits;
339 var r_digits = r._digits; 321 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
340 r_digits[0] = digits[ds] >> bs; 322 r_digits[0] = digits[ds] >> bs;
341 var used = _used; 323 var used = _used;
342 for (var i = ds + 1; i < used; i++) { 324 for (var i = ds + 1; i < used; i++) {
343 r_digits[i - ds - 1] |= (digits[i] & bm) << cbs; 325 r_digits[i - ds - 1] |= (digits[i] & bm) << cbs;
344 r_digits[i - ds] = digits[i] >> bs; 326 r_digits[i - ds] = digits[i] >> bs;
345 } 327 }
346 r._neg = _neg; 328 var r = new _Bigint(_neg, r_used, r_digits);
347 r._used = r_used;
348 r._clamp();
349 if (_neg) { 329 if (_neg) {
350 // Round down if any bit was shifted out. 330 // Round down if any bit was shifted out.
351 if ((digits[ds] & bm) != 0) { 331 if ((digits[ds] & bm) != 0) {
352 r._subTo(ONE, r); 332 return r._sub(ONE);
353 return;
354 } 333 }
355 for (var i = 0; i < ds; i++) { 334 for (var i = 0; i < ds; i++) {
356 if (digits[i] != 0) { 335 if (digits[i] != 0) {
357 r._subTo(ONE, r); 336 return r._sub(ONE);
358 return;
359 } 337 }
360 } 338 }
361 } 339 }
340 return r;
341 }
342
343 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n.
344 // Return r_used.
345 static int _rShiftDigits(Uint32List x_digits, int x_used, int n,
346 Uint32List r_digits) {
347 var ds = n ~/ DIGIT_BITS;
348 var bs = n % DIGIT_BITS;
349 if (bs == 0) {
350 return _drShiftDigits(x_digits, x_used, ds, r_digits);
351 }
352 var r_used = x_used - ds;
353 if (r_used <= 0) {
354 return 0;
355 }
356 var cbs = DIGIT_BITS - bs;
357 var bm = (1 << bs) - 1;
358 assert(r_digits.length >= r_used + 1); // +1 for leading zero.
359 r_digits[0] = x_digits[ds] >> bs;
360 for (var i = ds + 1; i < x_used; i++) {
361 r_digits[i - ds - 1] |= (x_digits[i] & bm) << cbs;
362 r_digits[i - ds] = x_digits[i] >> bs;
363 }
364 r_digits[r_used] = 0; // Set leading zero for 64-bit processing.
365 return r_used;
362 } 366 }
363 367
364 // Return 0 if abs(this) == abs(a). 368 // Return 0 if abs(this) == abs(a).
365 // Return a positive number if abs(this) > abs(a). 369 // Return a positive number if abs(this) > abs(a).
366 // Return a negative number if abs(this) < abs(a). 370 // Return a negative number if abs(this) < abs(a).
367 int _absCompareTo(_Bigint a) { 371 int _absCompare(_Bigint a) {
368 var r = _used - a._used; 372 var r = _used - a._used;
369 if (r == 0) { 373 if (r == 0) {
370 var i = _used; 374 var i = _used;
371 var digits = _digits; 375 var digits = _digits;
372 var a_digits = a._digits; 376 var a_digits = a._digits;
373 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0); 377 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0);
374 } 378 }
375 return r; 379 return r;
376 } 380 }
377 381
378 // Return 0 if this == a. 382 // Return 0 if this == a.
379 // Return a positive number if this > a. 383 // Return a positive number if this > a.
380 // Return a negative number if this < a. 384 // Return a negative number if this < a.
381 int _compareTo(_Bigint a) { 385 int _compare(_Bigint a) {
382 var r;
383 if (_neg == a._neg) { 386 if (_neg == a._neg) {
384 r = _absCompareTo(a); 387 var r = _absCompare(a);
385 if (_neg) { 388 return _neg ? -r : r;
386 r = -r; 389 }
387 } 390 return _neg ? -1 : 1;
388 } else if (_neg) { 391 }
389 r = -1; 392
390 } else { 393 // Compare digits[0..used-1] with a_digits[0..a_used-1].
391 r = 1; 394 // Return 0 if equal.
395 // Return a positive number if larger.
396 // Return a negative number if smaller.
397 static int _compareDigits(Uint32List digits, int used,
398 Uint32List a_digits, int a_used) {
399 var r = used - a_used;
400 if (r == 0) {
401 var i = a_used;
402 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0);
392 } 403 }
393 return r; 404 return r;
394 } 405 }
395 406
396 // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1]. 407 // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1].
397 // used >= a_used > 0. 408 // used >= a_used > 0.
409 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices.
398 static void _absAdd(Uint32List digits, int used, 410 static void _absAdd(Uint32List digits, int used,
399 Uint32List a_digits, int a_used, 411 Uint32List a_digits, int a_used,
400 Uint32List r_digits) { 412 Uint32List r_digits) {
413 assert(used >= a_used && a_used > 0);
414 // Verify that digit pairs are accessible for 64-bit processing.
415 assert(digits.length > ((used - 1) | 1));
416 assert(a_digits.length > ((a_used - 1) | 1));
417 assert(r_digits.length > (used | 1));
401 var c = 0; 418 var c = 0;
402 for (var i = 0; i < a_used; i++) { 419 for (var i = 0; i < a_used; i++) {
403 c += digits[i] + a_digits[i]; 420 c += digits[i] + a_digits[i];
404 r_digits[i] = c & DIGIT_MASK; 421 r_digits[i] = c & DIGIT_MASK;
405 c >>= DIGIT_BITS; 422 c >>= DIGIT_BITS;
406 } 423 }
407 for (var i = a_used; i < used; i++) { 424 for (var i = a_used; i < used; i++) {
408 c += digits[i]; 425 c += digits[i];
409 r_digits[i] = c & DIGIT_MASK; 426 r_digits[i] = c & DIGIT_MASK;
410 c >>= DIGIT_BITS; 427 c >>= DIGIT_BITS;
411 } 428 }
412 r_digits[used] = c; 429 r_digits[used] = c;
413 } 430 }
414 431
415 // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1]. 432 // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1].
416 // used >= a_used > 0. 433 // used >= a_used > 0.
434 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices.
417 static void _absSub(Uint32List digits, int used, 435 static void _absSub(Uint32List digits, int used,
418 Uint32List a_digits, int a_used, 436 Uint32List a_digits, int a_used,
419 Uint32List r_digits) { 437 Uint32List r_digits) {
438 assert(used >= a_used && a_used > 0);
439 // Verify that digit pairs are accessible for 64-bit processing.
440 assert(digits.length > ((used - 1) | 1));
441 assert(a_digits.length > ((a_used - 1) | 1));
442 assert(r_digits.length > ((used - 1) | 1));
420 var c = 0; 443 var c = 0;
421 for (var i = 0; i < a_used; i++) { 444 for (var i = 0; i < a_used; i++) {
422 c += digits[i] - a_digits[i]; 445 c += digits[i] - a_digits[i];
423 r_digits[i] = c & DIGIT_MASK; 446 r_digits[i] = c & DIGIT_MASK;
424 c >>= DIGIT_BITS; 447 c >>= DIGIT_BITS;
425 } 448 }
426 for (var i = a_used; i < used; i++) { 449 for (var i = a_used; i < used; i++) {
427 c += digits[i]; 450 c += digits[i];
428 r_digits[i] = c & DIGIT_MASK; 451 r_digits[i] = c & DIGIT_MASK;
429 c >>= DIGIT_BITS; 452 c >>= DIGIT_BITS;
430 } 453 }
431 } 454 }
432 455
433 // r = abs(this) + abs(a). 456 // Return abs(this) + abs(a) with sign set according to neg.
434 void _absAddTo(_Bigint a, _Bigint r) { 457 _Bigint _absAddSetSign(_Bigint a, bool neg) {
435 var used = _used; 458 var used = _used;
436 var a_used = a._used; 459 var a_used = a._used;
437 if (used < a_used) { 460 if (used < a_used) {
438 a._absAddTo(this, r); 461 return a._absAddSetSign(this, neg);
439 return;
440 } 462 }
441 if (used == 0) { 463 if (used == 0) {
442 // Set r to 0. 464 assert(!neg);
443 r._neg = false; 465 return ZERO;
444 r._used = 0;
445 return;
446 } 466 }
447 if (a_used == 0) { 467 if (a_used == 0) {
448 _copyTo(r); 468 return _neg == neg ? this : this._negate();
449 return;
450 } 469 }
451 r._ensureLength(used + 1); 470 var r_used = used + 1;
452 _absAdd(_digits, used, a._digits, a_used, r._digits); 471 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
453 r._used = used + 1; 472 _absAdd(_digits, used, a._digits, a_used, r_digits);
454 r._clamp(); 473 return new _Bigint(neg, r_used, r_digits);
455 } 474 }
456 475
457 // r = abs(this) - abs(a), with abs(this) >= abs(a). 476 // Return abs(this) - abs(a) with sign set according to neg.
458 void _absSubTo(_Bigint a, _Bigint r) { 477 // Requirement: abs(this) >= abs(a).
459 assert(_absCompareTo(a) >= 0); 478 _Bigint _absSubSetSign(_Bigint a, bool neg) {
479 assert(_absCompare(a) >= 0);
460 var used = _used; 480 var used = _used;
461 if (used == 0) { 481 if (used == 0) {
462 // Set r to 0. 482 assert(!neg);
463 r._neg = false; 483 return ZERO;
464 r._used = 0;
465 return;
466 } 484 }
467 var a_used = a._used; 485 var a_used = a._used;
468 if (a_used == 0) { 486 if (a_used == 0) {
469 _copyTo(r); 487 return _neg == neg ? this : this._negate();
470 return;
471 } 488 }
472 r._ensureLength(used); 489 var r_digits = new Uint32List(used + 1); // +1 for leading zero.
473 _absSub(_digits, used, a._digits, a_used, r._digits); 490 _absSub(_digits, used, a._digits, a_used, r_digits);
474 r._used = used; 491 return new _Bigint(neg, used, r_digits);
475 r._clamp();
476 } 492 }
477 493
478 // r = abs(this) & abs(a). 494 // Return abs(this) & abs(a) with sign set according to neg.
479 void _absAndTo(_Bigint a, _Bigint r) { 495 _Bigint _absAndSetSign(_Bigint a, bool neg) {
480 var r_used = (_used < a._used) ? _used : a._used; 496 var r_used = (_used < a._used) ? _used : a._used;
481 r._ensureLength(r_used);
482 var digits = _digits; 497 var digits = _digits;
483 var a_digits = a._digits; 498 var a_digits = a._digits;
484 var r_digits = r._digits; 499 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
485 for (var i = 0; i < r_used; i++) { 500 for (var i = 0; i < r_used; i++) {
486 r_digits[i] = digits[i] & a_digits[i]; 501 r_digits[i] = digits[i] & a_digits[i];
487 } 502 }
488 r._used = r_used; 503 return new _Bigint(neg, r_used, r_digits);
489 r._clamp();
490 } 504 }
491 505
492 // r = abs(this) &~ abs(a). 506 // Return abs(this) &~ abs(a) with sign set according to neg.
493 void _absAndNotTo(_Bigint a, _Bigint r) { 507 _Bigint _absAndNotSetSign(_Bigint a, bool neg) {
494 var r_used = _used; 508 var r_used = _used;
495 r._ensureLength(r_used);
496 var digits = _digits; 509 var digits = _digits;
497 var a_digits = a._digits; 510 var a_digits = a._digits;
498 var r_digits = r._digits; 511 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
499 var m = (r_used < a._used) ? r_used : a._used; 512 var m = (r_used < a._used) ? r_used : a._used;
500 for (var i = 0; i < m; i++) { 513 for (var i = 0; i < m; i++) {
501 r_digits[i] = digits[i] &~ a_digits[i]; 514 r_digits[i] = digits[i] &~ a_digits[i];
502 } 515 }
503 for (var i = m; i < r_used; i++) { 516 for (var i = m; i < r_used; i++) {
504 r_digits[i] = digits[i]; 517 r_digits[i] = digits[i];
505 } 518 }
506 r._used = r_used; 519 return new _Bigint(neg, r_used, r_digits);
507 r._clamp();
508 } 520 }
509 521
510 // r = abs(this) | abs(a). 522 // Return abs(this) | abs(a) with sign set according to neg.
511 void _absOrTo(_Bigint a, _Bigint r) { 523 _Bigint _absOrSetSign(_Bigint a, bool neg) {
512 var used = _used; 524 var used = _used;
513 var a_used = a._used; 525 var a_used = a._used;
514 var r_used = (used > a_used) ? used : a_used; 526 var r_used = (used > a_used) ? used : a_used;
515 r._ensureLength(r_used);
516 var digits = _digits; 527 var digits = _digits;
517 var a_digits = a._digits; 528 var a_digits = a._digits;
518 var r_digits = r._digits; 529 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
519 var l, m; 530 var l, m;
520 if (used < a_used) { 531 if (used < a_used) {
521 l = a; 532 l = a;
522 m = used; 533 m = used;
523 } else { 534 } else {
524 l = this; 535 l = this;
525 m = a_used; 536 m = a_used;
526 } 537 }
527 for (var i = 0; i < m; i++) { 538 for (var i = 0; i < m; i++) {
528 r_digits[i] = digits[i] | a_digits[i]; 539 r_digits[i] = digits[i] | a_digits[i];
529 } 540 }
530 var l_digits = l._digits; 541 var l_digits = l._digits;
531 for (var i = m; i < r_used; i++) { 542 for (var i = m; i < r_used; i++) {
532 r_digits[i] = l_digits[i]; 543 r_digits[i] = l_digits[i];
533 } 544 }
534 r._used = r_used; 545 return new _Bigint(neg, r_used, r_digits);
535 r._clamp();
536 } 546 }
537 547
538 // r = abs(this) ^ abs(a). 548 // Return abs(this) ^ abs(a) with sign set according to neg.
539 void _absXorTo(_Bigint a, _Bigint r) { 549 _Bigint _absXorSetSign(_Bigint a, bool neg) {
540 var used = _used; 550 var used = _used;
541 var a_used = a._used; 551 var a_used = a._used;
542 var r_used = (used > a_used) ? used : a_used; 552 var r_used = (used > a_used) ? used : a_used;
543 r._ensureLength(r_used);
544 var digits = _digits; 553 var digits = _digits;
545 var a_digits = a._digits; 554 var a_digits = a._digits;
546 var r_digits = r._digits; 555 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
547 var l, m; 556 var l, m;
548 if (used < a_used) { 557 if (used < a_used) {
549 l = a; 558 l = a;
550 m = used; 559 m = used;
551 } else { 560 } else {
552 l = this; 561 l = this;
553 m = a_used; 562 m = a_used;
554 } 563 }
555 for (var i = 0; i < m; i++) { 564 for (var i = 0; i < m; i++) {
556 r_digits[i] = digits[i] ^ a_digits[i]; 565 r_digits[i] = digits[i] ^ a_digits[i];
557 } 566 }
558 var l_digits = l._digits; 567 var l_digits = l._digits;
559 for (var i = m; i < r_used; i++) { 568 for (var i = m; i < r_used; i++) {
560 r_digits[i] = l_digits[i]; 569 r_digits[i] = l_digits[i];
561 } 570 }
562 r._used = r_used; 571 return new _Bigint(neg, r_used, r_digits);
563 r._clamp();
564 } 572 }
565 573
566 // Return r = this & a. 574 // Return this & a.
567 _Bigint _andTo(_Bigint a, _Bigint r) { 575 _Bigint _and(_Bigint a) {
568 if (_neg == a._neg) { 576 if (_neg == a._neg) {
569 if (_neg) { 577 if (_neg) {
570 // (-this) & (-a) == ~(this-1) & ~(a-1) 578 // (-this) & (-a) == ~(this-1) & ~(a-1)
571 // == ~((this-1) | (a-1)) 579 // == ~((this-1) | (a-1))
572 // == -(((this-1) | (a-1)) + 1) 580 // == -(((this-1) | (a-1)) + 1)
573 _Bigint t1 = new _Bigint(); 581 _Bigint t1 = _absSubSetSign(ONE, true);
574 _absSubTo(ONE, t1); 582 _Bigint a1 = a._absSubSetSign(ONE, true);
575 _Bigint a1 = new _Bigint(); 583 // Result cannot be zero if this and a are negative.
576 a._absSubTo(ONE, a1); 584 return t1._absOrSetSign(a1, true)._absAddSetSign(ONE, true);
577 t1._absOrTo(a1, r);
578 r._absAddTo(ONE, r);
579 r._neg = true; // r cannot be zero if this and a are negative.
580 return r;
581 } 585 }
582 _absAndTo(a, r); 586 return _absAndSetSign(a, false);
583 r._neg = false;
584 return r;
585 } 587 }
586 // _neg != a._neg 588 // _neg != a._neg
587 var p, n; 589 var p, n;
588 if (_neg) { 590 if (_neg) {
589 p = a; 591 p = a;
590 n = this; 592 n = this;
591 } else { // & is symmetric. 593 } else { // & is symmetric.
592 p = this; 594 p = this;
593 n = a; 595 n = a;
594 } 596 }
595 // p & (-n) == p & ~(n-1) == p &~ (n-1) 597 // p & (-n) == p & ~(n-1) == p &~ (n-1)
596 _Bigint n1 = new _Bigint(); 598 _Bigint n1 = n._absSubSetSign(ONE, false);
597 n._absSubTo(ONE, n1); 599 return p._absAndNotSetSign(n1, false);
598 p._absAndNotTo(n1, r);
599 r._neg = false;
600 return r;
601 } 600 }
602 601
603 // Return r = this &~ a. 602 // Return this &~ a.
604 _Bigint _andNotTo(_Bigint a, _Bigint r) { 603 _Bigint _andNot(_Bigint a) {
605 if (_neg == a._neg) { 604 if (_neg == a._neg) {
606 if (_neg) { 605 if (_neg) {
607 // (-this) &~ (-a) == ~(this-1) &~ ~(a-1) 606 // (-this) &~ (-a) == ~(this-1) &~ ~(a-1)
608 // == ~(this-1) & (a-1) 607 // == ~(this-1) & (a-1)
609 // == (a-1) &~ (this-1) 608 // == (a-1) &~ (this-1)
610 _Bigint t1 = new _Bigint(); 609 _Bigint t1 = _absSubSetSign(ONE, true);
611 _absSubTo(ONE, t1); 610 _Bigint a1 = a._absSubSetSign(ONE, true);
612 _Bigint a1 = new _Bigint(); 611 return a1._absAndNotSetSign(t1, false);
613 a._absSubTo(ONE, a1);
614 a1._absAndNotTo(t1, r);
615 r._neg = false;
616 return r;
617 } 612 }
618 _absAndNotTo(a, r); 613 return _absAndNotSetSign(a, false);
619 r._neg = false;
620 return r;
621 } 614 }
622 if (_neg) { 615 if (_neg) {
623 // (-this) &~ a == ~(this-1) &~ a 616 // (-this) &~ a == ~(this-1) &~ a
624 // == ~(this-1) & ~a 617 // == ~(this-1) & ~a
625 // == ~((this-1) | a) 618 // == ~((this-1) | a)
626 // == -(((this-1) | a) + 1) 619 // == -(((this-1) | a) + 1)
627 _Bigint t1 = new _Bigint(); 620 _Bigint t1 = _absSubSetSign(ONE, true);
628 _absSubTo(ONE, t1); 621 // Result cannot be zero if this is negative and a is positive.
629 t1._absOrTo(a, r); 622 return t1._absOrSetSign(a, true)._absAddSetSign(ONE, true);
630 r._absAddTo(ONE, r);
631 r._neg = true; // r cannot be zero if this is negative and a is positive.
632 return r;
633 } 623 }
634 // this &~ (-a) == this &~ ~(a-1) == this & (a-1) 624 // this &~ (-a) == this &~ ~(a-1) == this & (a-1)
635 _Bigint a1 = new _Bigint(); 625 _Bigint a1 = a._absSubSetSign(ONE, true);
636 a._absSubTo(ONE, a1); 626 return _absAndSetSign(a1, false);
637 _absAndTo(a1, r);
638 r._neg = false;
639 return r;
640 } 627 }
641 628
642 // Return r = this | a. 629 // Return this | a.
643 _Bigint _orTo(_Bigint a, _Bigint r) { 630 _Bigint _or(_Bigint a) {
644 if (_neg == a._neg) { 631 if (_neg == a._neg) {
645 if (_neg) { 632 if (_neg) {
646 // (-this) | (-a) == ~(this-1) | ~(a-1) 633 // (-this) | (-a) == ~(this-1) | ~(a-1)
647 // == ~((this-1) & (a-1)) 634 // == ~((this-1) & (a-1))
648 // == -(((this-1) & (a-1)) + 1) 635 // == -(((this-1) & (a-1)) + 1)
649 _Bigint t1 = new _Bigint(); 636 _Bigint t1 = _absSubSetSign(ONE, true);
650 _absSubTo(ONE, t1); 637 _Bigint a1 = a._absSubSetSign(ONE, true);
651 _Bigint a1 = new _Bigint(); 638 // Result cannot be zero if this and a are negative.
652 a._absSubTo(ONE, a1); 639 return t1._absAndSetSign(a1, true)._absAddSetSign(ONE, true);
653 t1._absAndTo(a1, r);
654 r._absAddTo(ONE, r);
655 r._neg = true; // r cannot be zero if this and a are negative.
656 return r;
657 } 640 }
658 _absOrTo(a, r); 641 return _absOrSetSign(a, false);
659 r._neg = false;
660 return r;
661 } 642 }
662 // _neg != a._neg 643 // _neg != a._neg
663 var p, n; 644 var p, n;
664 if (_neg) { 645 if (_neg) {
665 p = a; 646 p = a;
666 n = this; 647 n = this;
667 } else { // | is symmetric. 648 } else { // | is symmetric.
668 p = this; 649 p = this;
669 n = a; 650 n = a;
670 } 651 }
671 // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1) 652 // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1)
672 _Bigint n1 = new _Bigint(); 653 _Bigint n1 = n._absSubSetSign(ONE, true);
673 n._absSubTo(ONE, n1); 654 // Result cannot be zero if only one of this or a is negative.
674 n1._absAndNotTo(p, r); 655 return n1._absAndNotSetSign(p, true)._absAddSetSign(ONE, true);
675 r._absAddTo(ONE, r);
676 r._neg = true; // r cannot be zero if only one of this or a is negative.
677 return r;
678 } 656 }
679 657
680 // Return r = this ^ a. 658 // Return this ^ a.
681 _Bigint _xorTo(_Bigint a, _Bigint r) { 659 _Bigint _xor(_Bigint a) {
682 if (_neg == a._neg) { 660 if (_neg == a._neg) {
683 if (_neg) { 661 if (_neg) {
684 // (-this) ^ (-a) == ~(this-1) ^ ~(a-1) == (this-1) ^ (a-1) 662 // (-this) ^ (-a) == ~(this-1) ^ ~(a-1) == (this-1) ^ (a-1)
685 _Bigint t1 = new _Bigint(); 663 _Bigint t1 = _absSubSetSign(ONE, true);
686 _absSubTo(ONE, t1); 664 _Bigint a1 = a._absSubSetSign(ONE, true);
687 _Bigint a1 = new _Bigint(); 665 return t1._absXorSetSign(a1, false);
688 a._absSubTo(ONE, a1);
689 t1._absXorTo(a1, r);
690 r._neg = false;
691 return r;
692 } 666 }
693 _absXorTo(a, r); 667 return _absXorSetSign(a, false);
694 r._neg = false;
695 return r;
696 } 668 }
697 // _neg != a._neg 669 // _neg != a._neg
698 var p, n; 670 var p, n;
699 if (_neg) { 671 if (_neg) {
700 p = a; 672 p = a;
701 n = this; 673 n = this;
702 } else { // ^ is symmetric. 674 } else { // ^ is symmetric.
703 p = this; 675 p = this;
704 n = a; 676 n = a;
705 } 677 }
706 // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1) 678 // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1)
707 _Bigint n1 = new _Bigint(); 679 _Bigint n1 = n._absSubSetSign(ONE, true);
708 n._absSubTo(ONE, n1); 680 // Result cannot be zero if only one of this or a is negative.
709 p._absXorTo(n1, r); 681 return p._absXorSetSign(n1, true)._absAddSetSign(ONE, true);
710 r._absAddTo(ONE, r);
711 r._neg = true; // r cannot be zero if only one of this or a is negative.
712 return r;
713 } 682 }
714 683
715 // Return r = ~this. 684 // Return ~this.
716 _Bigint _notTo(_Bigint r) { 685 _Bigint _not() {
717 if (_neg) { 686 if (_neg) {
718 // ~(-this) == ~(~(this-1)) == this-1 687 // ~(-this) == ~(~(this-1)) == this-1
719 _absSubTo(ONE, r); 688 return _absSubSetSign(ONE, false);
720 r._neg = false;
721 return r;
722 } 689 }
723 // ~this == -this-1 == -(this+1) 690 // ~this == -this-1 == -(this+1)
724 _absAddTo(ONE, r); 691 // Result cannot be zero if this is positive.
725 r._neg = true; // r cannot be zero if this is positive. 692 return _absAddSetSign(ONE, true);
726 return r;
727 } 693 }
728 694
729 // Return r = this + a. 695 // Return this + a.
730 _Bigint _addTo(_Bigint a, _Bigint r) { 696 _Bigint _add(_Bigint a) {
731 var r_neg = _neg; 697 var neg = _neg;
732 if (_neg == a._neg) { 698 if (neg == a._neg) {
733 // this + a == this + a 699 // this + a == this + a
734 // (-this) + (-a) == -(this + a) 700 // (-this) + (-a) == -(this + a)
735 _absAddTo(a, r); 701 return _absAddSetSign(a, neg);
736 } else {
737 // this + (-a) == this - a == -(this - a)
738 // (-this) + a == a - this == -(this - a)
739 if (_absCompareTo(a) >= 0) {
740 _absSubTo(a, r);
741 } else {
742 r_neg = !r_neg;
743 a._absSubTo(this, r);
744 }
745 } 702 }
746 » r._neg = r_neg; 703 // this + (-a) == this - a == -(this - a)
747 return r; 704 // (-this) + a == a - this == -(this - a)
705 if (_absCompare(a) >= 0) {
706 return _absSubSetSign(a, neg);
707 }
708 return a._absSubSetSign(this, !neg);
748 } 709 }
749 710
750 // Return r = this - a. 711 // Return this - a.
751 _Bigint _subTo(_Bigint a, _Bigint r) { 712 _Bigint _sub(_Bigint a) {
752 » var r_neg = _neg; 713 » var neg = _neg;
rmacnak 2015/02/04 19:24:53 tabs
regis 2015/02/04 22:06:23 Done.
753 if (_neg != a._neg) { 714 if (neg != a._neg) {
754 // this - (-a) == this + a 715 // this - (-a) == this + a
755 // (-this) - a == -(this + a) 716 // (-this) - a == -(this + a)
756 _absAddTo(a, r); 717 return _absAddSetSign(a, neg);
757 » } else { 718 » }
758 » » // this - a == this - a == -(this - a) 719 // this - a == this - a == -(this - a)
759 » » // (-this) - (-a) == a - this == -(this - a) 720 // (-this) - (-a) == a - this == -(this - a)
760 if (_absCompareTo(a) >= 0) { 721 if (_absCompare(a) >= 0) {
761 _absSubTo(a, r); 722 return _absSubSetSign(a, neg);
762 » » } else {
763 r_neg = !r_neg;
764 a._absSubTo(this, r);
765 }
766 } 723 }
767 » r._neg = r_neg; 724 return a._absSubSetSign(this, !neg);
768 return r;
769 } 725 }
770 726
771 // Multiply and accumulate. 727 // Multiply and accumulate.
772 // Input: 728 // Input:
773 // x_digits[xi]: multiplier digit x. 729 // x_digits[xi]: multiplier digit x.
774 // m_digits[i..i+n-1]: multiplicand digits. 730 // m_digits[i..i+n-1]: multiplicand digits.
775 // a_digits[j..j+n-1]: accumulator digits. 731 // a_digits[j..j+n-1]: accumulator digits.
776 // Operation: 732 // Operation:
777 // a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1]. 733 // a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1].
778 // return 1. 734 // return 1.
779 // Note: intrinsics on 64-bit platform may process a digit pair: 735 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices
780 // a_digits[j..j+n] += x_digits[xi..xi+1]*m_digits[i..i+n-1]. 736 // and return 2.
781 // return 2.
782 static int _mulAdd(Uint32List x_digits, int xi, 737 static int _mulAdd(Uint32List x_digits, int xi,
783 Uint32List m_digits, int i, 738 Uint32List m_digits, int i,
784 Uint32List a_digits, int j, int n) { 739 Uint32List a_digits, int j, int n) {
740 // Verify that digit pairs are accessible for 64-bit processing.
741 assert(x_digits.length > (xi | 1));
742 assert(m_digits.length > ((i + n - 1) | 1));
743 assert(a_digits.length > ((j + n) | 1));
785 int x = x_digits[xi]; 744 int x = x_digits[xi];
786 if (x == 0) { 745 if (x == 0) {
787 // No-op if x is 0. 746 // No-op if x is 0.
788 return 1; 747 return 1;
789 } 748 }
790 int c = 0; 749 int c = 0;
791 int xl = x & DIGIT2_MASK; 750 int xl = x & DIGIT2_MASK;
792 int xh = x >> DIGIT2_BITS; 751 int xh = x >> DIGIT2_BITS;
793 while (--n >= 0) { 752 while (--n >= 0) {
794 int l = m_digits[i] & DIGIT2_MASK; 753 int l = m_digits[i] & DIGIT2_MASK;
(...skipping 12 matching lines...) Expand all
807 } 766 }
808 767
809 // Square and accumulate. 768 // Square and accumulate.
810 // Input: 769 // Input:
811 // x_digits[i..used-1]: digits of operand being squared. 770 // x_digits[i..used-1]: digits of operand being squared.
812 // a_digits[2*i..i+used-1]: accumulator digits. 771 // a_digits[2*i..i+used-1]: accumulator digits.
813 // Operation: 772 // Operation:
814 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + 773 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] +
815 // 2*x_digits[i]*x_digits[i+1..used-1]. 774 // 2*x_digits[i]*x_digits[i+1..used-1].
816 // return 1. 775 // return 1.
817 // Note: intrinsics on 64-bit platform may process a digit pair: 776 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices
818 // a_digits[2*i..i+used-1] += x_digits[i..i+1]*x_digits[i..i+1] + 777 // and return 2.
819 // 2*x_digits[i..i+1]*x_digits[i+2..used-1].
820 // return 2.
821 static int _sqrAdd(Uint32List x_digits, int i, 778 static int _sqrAdd(Uint32List x_digits, int i,
822 Uint32List a_digits, int used) { 779 Uint32List a_digits, int used) {
780 // Verify that digit pairs are accessible for 64-bit processing.
781 assert(x_digits.length > ((used - 1) | 1));
782 assert(a_digits.length > ((i + used - 1) | 1));
823 int x = x_digits[i]; 783 int x = x_digits[i];
824 if (x == 0) return 1; 784 if (x == 0) return 1;
825 int j = 2*i; 785 int j = 2*i;
826 int c = 0; 786 int c = 0;
827 int xl = x & DIGIT2_MASK; 787 int xl = x & DIGIT2_MASK;
828 int xh = x >> DIGIT2_BITS; 788 int xh = x >> DIGIT2_BITS;
829 int m = 2*xh*xl; 789 int m = 2*xh*xl;
830 int l = xl*xl + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j]; 790 int l = xl*xl + ((m & DIGIT2_MASK) << DIGIT2_BITS) + a_digits[j];
831 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*xh; 791 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*xh;
832 a_digits[j] = l & DIGIT_MASK; 792 a_digits[j] = l & DIGIT_MASK;
(...skipping 14 matching lines...) Expand all
847 c += a_digits[i + used]; 807 c += a_digits[i + used];
848 if (c >= DIGIT_BASE) { 808 if (c >= DIGIT_BASE) {
849 a_digits[i + used] = c - DIGIT_BASE; 809 a_digits[i + used] = c - DIGIT_BASE;
850 a_digits[i + used + 1] = 1; 810 a_digits[i + used + 1] = 1;
851 } else { 811 } else {
852 a_digits[i + used] = c; 812 a_digits[i + used] = c;
853 } 813 }
854 return 1; 814 return 1;
855 } 815 }
856 816
857 // r = this * a. 817 // Return this * a.
858 void _mulTo(_Bigint a, _Bigint r) { 818 _Bigint _mul(_Bigint a) {
859 // TODO(regis): Use karatsuba multiplication when appropriate. 819 // TODO(regis): Use karatsuba multiplication when appropriate.
860 var used = _used; 820 var used = _used;
861 var a_used = a._used; 821 var a_used = a._used;
862 if (used == 0 || a_used == 0) { 822 if (used == 0 || a_used == 0) {
863 r._used = 0; 823 return ZERO;
864 r._neg = false;
865 return;
866 } 824 }
867 var r_used = used + a_used; 825 var r_used = used + a_used;
868 r._ensureLength(r_used);
869 var digits = _digits; 826 var digits = _digits;
870 var a_digits = a._digits; 827 var a_digits = a._digits;
871 var r_digits = r._digits; 828 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
872 r._used = r_used;
873 var i = r_used + 1; // Set leading zero for 64-bit processing. 829 var i = r_used + 1; // Set leading zero for 64-bit processing.
874 while (--i >= 0) { 830 while (--i >= 0) {
875 r_digits[i] = 0; 831 r_digits[i] = 0;
876 } 832 }
877 i = 0; 833 i = 0;
878 while (i < a_used) { 834 while (i < a_used) {
879 i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used); 835 i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used);
880 } 836 }
881 r._clamp(); 837 return new _Bigint(_neg != a._neg, r_used, r_digits);
882 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative.
883 } 838 }
884 839
885 // r = this^2, r != this. 840 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*a_digits[0..a_used-1].
886 void _sqrTo(_Bigint r) { 841 // Return r_used = x_used + a_used.
887 var used = _used; 842 static int _mulDigits(Uint32List x_digits, int x_used,
888 if (used == 0) { 843 Uint32List a_digits, int a_used,
889 r._used = 0; 844 Uint32List r_digits) {
890 r._neg = false; 845 var r_used = x_used + a_used;
891 return; 846 assert(r_digits.length >= r_used + 1); // +1 for leading zero.
892 }
893 var r_used = 2 * used;
894 r._ensureLength(r_used);
895 var digits = _digits;
896 var r_digits = r._digits;
897 var i = r_used + 1; // Set leading zero for 64-bit processing. 847 var i = r_used + 1; // Set leading zero for 64-bit processing.
898 while (--i >= 0) { 848 while (--i >= 0) {
899 r_digits[i] = 0; 849 r_digits[i] = 0;
850 }
851 i = 0;
852 while (i < a_used) {
853 i += _mulAdd(a_digits, i, x_digits, 0, r_digits, i, x_used);
854 }
855 return r_used;
856 }
857
858 // Return this^2.
859 _Bigint _sqr() {
860 var used = _used;
861 if (used == 0) {
862 return ZERO;
863 }
864 var r_used = 2 * used;
865 var digits = _digits;
866 var r_digits = new Uint32List(r_used + 1); // +1 for leading zero.
867 var i = r_used + 1; // Set leading zero for 64-bit processing.
868 while (--i >= 0) {
869 r_digits[i] = 0;
900 } 870 }
901 i = 0; 871 i = 0;
902 while (i < used - 1) { 872 while (i < used - 1) {
903 i += _sqrAdd(digits, i, r_digits, used); 873 i += _sqrAdd(digits, i, r_digits, used);
904 } 874 }
905 if (r_used > 0) { 875 // The last step may not be required if digit pairs were processed above.
876 if (i < used) {
906 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); 877 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1);
907 } 878 }
908 r._used = r_used; 879 return new _Bigint(false, r_used, r_digits);
909 r._neg = false; 880 }
910 r._clamp(); 881
882 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*x_digits[0..x_used-1].
883 // Return r_used = 2*x_used.
884 static int _sqrDigits(Uint32List x_digits, int x_used, Uint32List r_digits) {
885 var r_used = 2 * x_used;
886 assert(r_digits.length >= r_used + 1); // +1 for leading zero.
887 var i = r_used + 1; // Set leading zero for 64-bit processing.
888 while (--i >= 0) {
889 r_digits[i] = 0;
890 }
891 i = 0;
892 while (i < x_used - 1) {
893 i += _sqrAdd(x_digits, i, r_digits, x_used);
894 }
895 // The last step may not be required if digit pairs were processed above.
896 if (i < x_used) {
897 _mulAdd(x_digits, i, x_digits, i, r_digits, 2*i, 1);
898 }
899 return r_used;
911 } 900 }
912 901
913 // Indices of the arguments of _estQuotientDigit. 902 // Indices of the arguments of _estQuotientDigit.
914 // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair 903 // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair
915 // of divisor y is provided in the args array, and a 64-bit estimated quotient 904 // of divisor y is provided in the args array, and a 64-bit estimated quotient
916 // is returned. However, on 32-bit platforms, the low 32-bit digit is ignored 905 // is returned. However, on 32-bit platforms, the low 32-bit digit is ignored
917 // and only one 32-bit digit is returned as the estimated quotient. 906 // and only one 32-bit digit is returned as the estimated quotient.
918 static const int _YT_LO = 0; // Low digit of top digit pair of y, for 64-bit. 907 static const int _YT_LO = 0; // Low digit of top digit pair of y, for 64-bit.
919 static const int _YT = 1; // Top digit of divisor y. 908 static const int _YT = 1; // Top digit of divisor y.
920 static const int _QD = 2; // Estimated quotient. 909 static const int _QD = 2; // Estimated quotient.
921 static const int _QD_HI = 3; // High digit of estimated quotient, for 64-bit. 910 static const int _QD_HI = 3; // High digit of estimated quotient, for 64-bit.
922 911
923 // Operation: 912 // Operation:
924 // Estimate args[_QD] = digits[i-1..i] ~/ args[_YT] 913 // Estimate args[_QD] = digits[i-1..i] ~/ args[_YT]
925 // return 1 914 // return 1
926 // Note: intrinsics on 64-bit platform may process a digit pair: 915 // Note: Intrinsics on 64-bit platforms process a digit pair (i always odd):
927 // Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT] 916 // Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT]
928 // return 2 917 // return 2
929 static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { 918 static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) {
919 // Verify that digit pairs are accessible for 64-bit processing.
920 assert(digits.length >= 4 + 1); // +1 for leading zero.
930 if (digits[i] == args[_YT]) { 921 if (digits[i] == args[_YT]) {
931 args[_QD] = DIGIT_MASK; 922 args[_QD] = DIGIT_MASK;
932 } else { 923 } else {
933 // Chop off one bit, since a Mint cannot hold 2 DIGITs. 924 // Chop off one bit, since a Mint cannot hold 2 DIGITs.
934 var qd = ((digits[i] << (DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) 925 var qd = ((digits[i] << (DIGIT_BITS - 1)) | (digits[i - 1] >> 1))
935 ~/ (args[_YT] >> 1); 926 ~/ (args[_YT] >> 1);
936 if (qd > DIGIT_MASK) { 927 if (qd > DIGIT_MASK) {
937 args[_QD] = DIGIT_MASK; 928 args[_QD] = DIGIT_MASK;
938 } else { 929 } else {
939 args[_QD] = qd; 930 args[_QD] = qd;
940 } 931 }
941 } 932 }
942 return 1; 933 return 1;
943 } 934 }
944 935
936 // Return trunc(this / a), a != 0.
937 _Bigint _div(_Bigint a) {
938 return _divRem(a, true);
939 }
945 940
946 // Truncating division and remainder. 941 // Return this - a * trunc(this / a), a != 0.
947 // If q != null, q = trunc(this / a). 942 _Bigint _rem(_Bigint a) {
948 // If r != null, r = this - a * trunc(this / a). 943 return _divRem(a, false);
949 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { 944 }
950 if (a._used == 0) return; 945
946 // Return trunc(this / a), a != 0, if div == true.
947 // Return this - a * trunc(this / a), a != 0, if div == false.
948 _Bigint _divRem(_Bigint a, bool div) {
949 assert(a._used > 0);
951 if (_used < a._used) { 950 if (_used < a._used) {
952 if (q != null) { 951 return div ? ZERO : this;
953 // Set q to 0.
954 q._neg = false;
955 q._used = 0;
956 }
957 if (r != null) {
958 _copyTo(r);
959 }
960 return;
961 } 952 }
962 if (r == null) {
963 r = new _Bigint();
964 }
965 var y = new _Bigint(); // Normalized modulus.
966 var nsh = DIGIT_BITS - _nbits(a._digits[a._used - 1]); 953 var nsh = DIGIT_BITS - _nbits(a._digits[a._used - 1]);
967 // For 64-bit processing, make sure y has an even number of digits. 954 // For 64-bit processing, make sure y has an even number of digits.
968 if ((a._used & 1) == 1) { 955 if (a._used.isOdd) {
969 nsh += DIGIT_BITS; 956 nsh += DIGIT_BITS;
970 } 957 }
958 var y; // Normalized positive divisor.
959 var r; // Concatenated positive quotient and normalized positive remainder.
971 if (nsh > 0) { 960 if (nsh > 0) {
972 a._lShiftTo(nsh, y); 961 y = a._lShift(nsh)._abs();
973 _lShiftTo(nsh, r); 962 r = _lShift(nsh)._abs();
974 } 963 }
975 else { 964 else {
976 a._copyTo(y); 965 y = a._abs();
977 _copyTo(r); 966 r = _abs();
978 } 967 }
979 // We consider this and a positive. Ignore the copied sign.
980 y._neg = false;
981 r._neg = false;
982 var y_used = y._used; 968 var y_used = y._used;
983 assert((y_used & 1) == 0);
984 var y_digits = y._digits; 969 var y_digits = y._digits;
985 Uint32List args = new Uint32List(4); 970 Uint32List args = new Uint32List(4);
986 args[_YT_LO] = y_digits[y_used - 2]; 971 args[_YT_LO] = y_digits[y_used - 2];
987 args[_YT] = y_digits[y_used - 1]; 972 args[_YT] = y_digits[y_used - 1];
988 var r_digits = r._digits; 973 var r_used = r._used;
989 var i = r._used; 974 // For 64-bit processing, make sure y_used, i, and j are even.
990 if ((i & 1) == 1) { 975 assert(y_used.isEven);
991 // For 64-bit processing, make sure r has an even number of digits. 976 var i = r_used + (r_used & 1);
992 r_digits[i++] = 0; 977 var j = i - y_used;
978 var t = y._dlShift(j);
979 if (r._compare(t) >= 0) {
980 assert(i == r_used);
981 r = r._or(ONE._dlShift(r_used++))._sub(t);
982 assert(r._used == r_used);
993 } 983 }
994 var j = i - y_used; 984 // Negate y so we can later use _mulAdd instead of non-existent _mulSub.
995 _Bigint t = (q == null) ? new _Bigint() : q; 985 y = ONE._dlShift(y_used)._sub(y);
996 y._dlShiftTo(j, t); 986 if (y._used < y_used) {
997 if (r._compareTo(t) >= 0) { 987 y_digits = _cloneDigits(y._digits, 0, y._used, y_used);
998 r_digits[r._used++] = 1; 988 } else {
999 r_digits[r._used] = 0; // Set leading zero for 64-bit processing. 989 y_digits = y._digits;
1000 r._subTo(t, r);
1001 } 990 }
1002 ONE._dlShiftTo(y_used, t); 991 // y_digits is read-only and has y_used digits (possibly including several
1003 t._subTo(y, y); // Negate y so we can replace sub with _mulAdd later. 992 // leading zeros) plus a leading zero for 64-bit processing.
1004 while (y._used < y_used) { 993 var r_digits = _cloneDigits(r._digits, 0, r._used, i);
1005 y_digits[y._used++] = 0; 994 // r_digits is modified during iteration.
1006 } 995 // r_digits[0..y_used-1] is the current remainder.
1007 y_digits[y._used] = 0; // Set leading zero for 64-bit processing. 996 // r_digits[y_used..r_used-1] is the current quotient.
997 --i;
1008 while (j > 0) { 998 while (j > 0) {
1009 var d0 = _estQuotientDigit(args, r_digits, --i); 999 var d0 = _estQuotientDigit(args, r_digits, i);
1010 j -= d0; 1000 j -= d0;
1011 var d1 = _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used); 1001 var d1 = _mulAdd(args, _QD, y_digits, 0, r_digits, j, y_used);
1012 // _estQuotientDigit and _mulAdd must agree on the number of digits to 1002 // _estQuotientDigit and _mulAdd must agree on the number of digits to
1013 // process. 1003 // process.
1014 assert(d0 == d1); 1004 assert(d0 == d1);
1015 if (d0 == 1) { 1005 if (d0 == 1) {
1016 if (r_digits[i] < args[_QD]) { 1006 if (r_digits[i] < args[_QD]) {
1017 y._dlShiftTo(j, t); 1007 var t = y._dlShift(j);
1018 r._subTo(t, r); 1008 var t_digits = t._digits;
1009 var t_used = t._used;
1010 _absSub(r_digits, r_used, t_digits, t_used, r_digits);
1019 while (r_digits[i] < --args[_QD]) { 1011 while (r_digits[i] < --args[_QD]) {
1020 r._subTo(t, r); 1012 _absSub(r_digits, r_used, t_digits, t_used, r_digits);
1021 } 1013 }
1022 } 1014 }
1023 } else { 1015 } else {
1024 assert(d0 == 2); 1016 assert(d0 == 2);
1025 assert(r_digits[i] <= args[_QD_HI]); 1017 assert(r_digits[i] <= args[_QD_HI]);
1026 if ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) { 1018 if ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) {
1027 y._dlShiftTo(j, t); 1019 var t = y._dlShift(j);
1028 r._subTo(t, r); 1020 var t_digits = t._digits;
1021 var t_used = t._used;
1022 _absSub(r_digits, r_used, t_digits, t_used, r_digits);
1029 if (args[_QD] == 0) { 1023 if (args[_QD] == 0) {
1030 --args[_QD_HI]; 1024 --args[_QD_HI];
1031 } 1025 }
1032 --args[_QD]; 1026 --args[_QD];
1033 assert(r_digits[i] <= args[_QD_HI]); 1027 assert(r_digits[i] <= args[_QD_HI]);
1034 while ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) { 1028 while ((r_digits[i] < args[_QD_HI]) || (r_digits[i-1] < args[_QD])) {
1035 r._subTo(t, r); 1029 _absSub(r_digits, r_used, t_digits, t_used, r_digits);
1036 if (args[_QD] == 0) { 1030 if (args[_QD] == 0) {
1037 --args[_QD_HI]; 1031 --args[_QD_HI];
1038 } 1032 }
1039 --args[_QD]; 1033 --args[_QD];
1040 assert(r_digits[i] <= args[_QD_HI]); 1034 assert(r_digits[i] <= args[_QD_HI]);
1041 } 1035 }
1042 } 1036 }
1043 --i;
1044 } 1037 }
1038 i -= d0;
1045 } 1039 }
1046 if (q != null) { 1040 if (div) {
1047 r._drShiftTo(y_used, q); 1041 // Return quotient, i.e. r_digits[y_used..r_used-1] with proper sign.
1048 if (_neg != a._neg && q._used > 0) { 1042 r_digits = _cloneDigits(r_digits, y_used, r_used, r_used - y_used);
1049 q._neg = !q._neg; 1043 r = new _Bigint(false, r_used - y_used, r_digits);
1044 if (_neg != a._neg && r._used > 0) {
1045 r = r._negate();
1050 } 1046 }
1047 return r;
1051 } 1048 }
1052 r._used = y_used; 1049 // Return remainder, i.e. denormalized r_digits[0..y_used-1] with
1053 r._clamp(); 1050 // proper sign.
1051 r_digits = _cloneDigits(r_digits, 0, y_used, y_used);
1052 r = new _Bigint(false, y_used, r_digits);
1054 if (nsh > 0) { 1053 if (nsh > 0) {
1055 r._rShiftTo(nsh, r); // Denormalize remainder. 1054 r = r._rShift(nsh); // Denormalize remainder.
1056 } 1055 }
1057 if (_neg && r._used > 0) { 1056 if (_neg && r._used > 0) {
1058 r._neg = !r._neg; 1057 r = r._negate();
1059 } 1058 }
1059 return r;
1060 }
1061
1062 // Customized version of _rem() minimizing allocations for use in reduction.
1063 // Input:
1064 // x_digits[0..x_used-1]: positive dividend.
1065 // y_digits[0..y_used-1]: normalized positive divisor.
1066 // ny_digits[0..y_used-1]: negated y_digits.
1067 // nsh: normalization shift amount.
1068 // yt_qd: top y digit(s) and place holder for estimated quotient digit(s).
1069 // t_digits: temp array of 2*y_used digits.
1070 // r_digits: result digits array large enough to temporarily hold
1071 // concatenated quotient and normalized remainder.
1072 // Output:
1073 // r_digits[0..r_used-1]: positive remainder.
1074 // Returns r_used.
1075 static int _remDigits(Uint32List x_digits, int x_used,
1076 Uint32List y_digits, int y_used, Uint32List ny_digits,
1077 int nsh,
1078 Uint32List yt_qd,
1079 Uint32List t_digits,
1080 Uint32List r_digits) {
1081 assert(y_used > 0 && x_used >= y_used);
1082 // Initialize r_digits to normalized positive dividend.
1083 var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits);
1084 // For 64-bit processing, make sure y_used, i, and j are even.
1085 assert(y_used.isEven);
1086 var i = r_used + (r_used & 1);
1087 var j = i - y_used;
1088 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits);
1089 // Explicit first division step in case normalized dividend is larger or
1090 // equal to shifted normalized divisor.
1091 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) {
1092 assert(i == r_used);
1093 r_digits[r_used++] = 1; // Quotient = 1.
1094 r_digits[r_used] = 0; // Leading zero.
1095 // Subtract divisor from remainder.
1096 _absSub(r_digits, r_used, t_digits, t_used, r_digits);
1097 }
1098 // Negated y_digits passed in ny_digits allow the use of _mulAdd instead of
1099 // unimplemented _mulSub.
1100 // ny_digits is read-only and has y_used digits (possibly including several
1101 // leading zeros) plus a leading zero for 64-bit processing.
1102 // r_digits is modified during iteration.
1103 // r_digits[0..y_used-1] is the current remainder.
1104 // r_digits[y_used..r_used-1] is the current quotient.
1105 --i;
1106 while (j > 0) {
1107 var d0 = _estQuotientDigit(yt_qd, r_digits, i);
1108 j -= d0;
1109 var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used);
1110 // _estQuotientDigit and _mulAdd must agree on the number of digits to
1111 // process.
1112 assert(d0 == d1);
1113 if (d0 == 1) {
1114 if (r_digits[i] < yt_qd[_QD]) {
1115 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits);
1116 _absSub(r_digits, r_used, t_digits, t_used, r_digits);
1117 while (r_digits[i] < --yt_qd[_QD]) {
1118 _absSub(r_digits, r_used, t_digits, t_used, r_digits);
1119 }
1120 }
1121 } else {
1122 assert(d0 == 2);
1123 assert(r_digits[i] <= yt_qd[_QD_HI]);
1124 if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i-1] < yt_qd[_QD])) {
1125 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits);
1126 _absSub(r_digits, r_used, t_digits, t_used, r_digits);
1127 if (yt_qd[_QD] == 0) {
1128 --yt_qd[_QD_HI];
1129 }
1130 --yt_qd[_QD];
1131 assert(r_digits[i] <= yt_qd[_QD_HI]);
1132 while ((r_digits[i] < yt_qd[_QD_HI]) ||
1133 (r_digits[i-1] < yt_qd[_QD])) {
1134 _absSub(r_digits, r_used, t_digits, t_used, r_digits);
1135 if (yt_qd[_QD] == 0) {
1136 --yt_qd[_QD_HI];
1137 }
1138 --yt_qd[_QD];
1139 assert(r_digits[i] <= yt_qd[_QD_HI]);
1140 }
1141 }
1142 }
1143 i -= d0;
1144 }
1145 // Return remainder, i.e. denormalized r_digits[0..y_used-1].
1146 r_used = y_used;
1147 if (nsh > 0) {
1148 // Denormalize remainder.
1149 r_used = _rShiftDigits(r_digits, r_used, nsh, r_digits);
1150 }
1151 return r_used;
1060 } 1152 }
1061 1153
1062 int get _identityHashCode { 1154 int get _identityHashCode {
1063 return this; 1155 return this;
1064 } 1156 }
1065 int operator ~() { 1157 int operator ~() {
1066 _Bigint result = new _Bigint(); 1158 return _not()._toValidInt();
1067 _notTo(result);
1068 return result._toValidInt();
1069 } 1159 }
1070 1160
1071 int get bitLength { 1161 int get bitLength {
1072 if (_used == 0) return 0; 1162 if (_used == 0) return 0;
1073 if (_neg) return (~this).bitLength; 1163 if (_neg) return (~this).bitLength;
1074 return DIGIT_BITS*(_used - 1) + _nbits(_digits[_used - 1]); 1164 return DIGIT_BITS*(_used - 1) + _nbits(_digits[_used - 1]);
1075 } 1165 }
1076 1166
1077 // This method must support smi._toBigint()._shrFromInt(int). 1167 // This method must support smi._toBigint()._shrFromInt(int).
1078 int _shrFromInt(int other) { 1168 int _shrFromInt(int other) {
1079 if (_used == 0) return other; // Shift amount is zero. 1169 if (_used == 0) return other; // Shift amount is zero.
1080 if (_neg) throw "negative shift amount"; // TODO(regis): What exception? 1170 if (_neg) throw "negative shift amount"; // TODO(regis): What exception?
1081 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. 1171 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised.
1082 var shift; 1172 var shift;
1083 if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) { 1173 if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) {
1084 if (other < 0) { 1174 if (other < 0) {
1085 return -1; 1175 return -1;
1086 } else { 1176 } else {
1087 return 0; 1177 return 0;
1088 } 1178 }
1089 } else { 1179 } else {
1090 shift = ((_used == 2) ? (_digits[1] << DIGIT_BITS) : 0) + _digits[0]; 1180 shift = ((_used == 2) ? (_digits[1] << DIGIT_BITS) : 0) + _digits[0];
1091 } 1181 }
1092 _Bigint result = new _Bigint(); 1182 return other._toBigint()._rShift(shift)._toValidInt();
1093 other._toBigint()._rShiftTo(shift, result);
1094 return result._toValidInt();
1095 } 1183 }
1096 1184
1097 // This method must support smi._toBigint()._shlFromInt(int). 1185 // This method must support smi._toBigint()._shlFromInt(int).
1098 // An out of memory exception is thrown if the result cannot be allocated. 1186 // An out of memory exception is thrown if the result cannot be allocated.
1099 int _shlFromInt(int other) { 1187 int _shlFromInt(int other) {
1100 if (_used == 0) return other; // Shift amount is zero. 1188 if (_used == 0) return other; // Shift amount is zero.
1101 if (_neg) throw "negative shift amount"; // TODO(regis): What exception? 1189 if (_neg) throw "negative shift amount"; // TODO(regis): What exception?
1102 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. 1190 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised.
1103 var shift; 1191 var shift;
1104 if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) { 1192 if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) {
1105 throw new OutOfMemoryError(); 1193 throw new OutOfMemoryError();
1106 } else { 1194 } else {
1107 shift = ((_used == 2) ? (_digits[1] << DIGIT_BITS) : 0) + _digits[0]; 1195 shift = ((_used == 2) ? (_digits[1] << DIGIT_BITS) : 0) + _digits[0];
1108 } 1196 }
1109 _Bigint result = new _Bigint(); 1197 return other._toBigint()._lShift(shift)._toValidInt();
1110 other._toBigint()._lShiftTo(shift, result);
1111 return result._toValidInt();
1112 } 1198 }
1113 1199
1114 // Overriden operators and methods. 1200 // Overriden operators and methods.
1115 1201
1116 // The following operators override operators of _IntegerImplementation for 1202 // The following operators override operators of _IntegerImplementation for
1117 // efficiency, but are not necessary for correctness. They shortcut native 1203 // efficiency, but are not necessary for correctness. They shortcut native
1118 // calls that would return null because the receiver is _Bigint. 1204 // calls that would return null because the receiver is _Bigint.
1119 num operator +(num other) { 1205 num operator +(num other) {
1120 return other._toBigintOrDouble()._addFromInteger(this); 1206 return other._toBigintOrDouble()._addFromInteger(this);
1121 } 1207 }
(...skipping 26 matching lines...) Expand all
1148 } 1234 }
1149 int operator >>(int other) { 1235 int operator >>(int other) {
1150 return other._toBigintOrDouble()._shrFromInt(this); 1236 return other._toBigintOrDouble()._shrFromInt(this);
1151 } 1237 }
1152 int operator <<(int other) { 1238 int operator <<(int other) {
1153 return other._toBigintOrDouble()._shlFromInt(this); 1239 return other._toBigintOrDouble()._shlFromInt(this);
1154 } 1240 }
1155 // End of operator shortcuts. 1241 // End of operator shortcuts.
1156 1242
1157 int operator -() { 1243 int operator -() {
1158 if (_used == 0) { 1244 return _negate()._toValidInt();
1159 return this;
1160 }
1161 var r = new _Bigint();
1162 _copyTo(r);
1163 r._neg = !_neg;
1164 return r._toValidInt();
1165 } 1245 }
1166 1246
1167 int get sign { 1247 int get sign {
1168 return (_used == 0) ? 0 : _neg ? -1 : 1; 1248 return (_used == 0) ? 0 : _neg ? -1 : 1;
1169 } 1249 }
1170 1250
1171 bool get isEven => _used == 0 || (_digits[0] & 1) == 0; 1251 bool get isEven => _used == 0 || (_digits[0] & 1) == 0;
1172 bool get isNegative => _neg; 1252 bool get isNegative => _neg;
1173 1253
1174 String _toPow2String(int radix) { 1254 String _toPow2String(int radix) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1210 if (_used == 0) return 0; 1290 if (_used == 0) return 0;
1211 if (count is! _Smi) { 1291 if (count is! _Smi) {
1212 _shlFromInt(count); // Throws out of memory exception. 1292 _shlFromInt(count); // Throws out of memory exception.
1213 } 1293 }
1214 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. 1294 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised.
1215 if (count > 31) return 0; 1295 if (count > 31) return 0;
1216 return (_digits[0] << count) & mask; 1296 return (_digits[0] << count) & mask;
1217 } 1297 }
1218 1298
1219 int _bitAndFromInteger(int other) { 1299 int _bitAndFromInteger(int other) {
1220 _Bigint result = new _Bigint(); 1300 return other._toBigint()._and(this)._toValidInt();
1221 other._toBigint()._andTo(this, result);
1222 return result._toValidInt();
1223 } 1301 }
1224 int _bitOrFromInteger(int other) { 1302 int _bitOrFromInteger(int other) {
1225 _Bigint result = new _Bigint(); 1303 return other._toBigint()._or(this)._toValidInt();
1226 other._toBigint()._orTo(this, result);
1227 return result._toValidInt();
1228 } 1304 }
1229 int _bitXorFromInteger(int other) { 1305 int _bitXorFromInteger(int other) {
1230 _Bigint result = new _Bigint(); 1306 return other._toBigint()._xor(this)._toValidInt();
1231 other._toBigint()._xorTo(this, result);
1232 return result._toValidInt();
1233 } 1307 }
1234 int _addFromInteger(int other) { 1308 int _addFromInteger(int other) {
1235 _Bigint result = new _Bigint(); 1309 return other._toBigint()._add(this)._toValidInt();
1236 other._toBigint()._addTo(this, result);
1237 return result._toValidInt();
1238 } 1310 }
1239 int _subFromInteger(int other) { 1311 int _subFromInteger(int other) {
1240 _Bigint result = new _Bigint(); 1312 return other._toBigint()._sub(this)._toValidInt();
1241 other._toBigint()._subTo(this, result);
1242 return result._toValidInt();
1243 } 1313 }
1244 int _mulFromInteger(int other) { 1314 int _mulFromInteger(int other) {
1245 _Bigint result = new _Bigint(); 1315 return other._toBigint()._mul(this)._toValidInt();
1246 other._toBigint()._mulTo(this, result);
1247 return result._toValidInt();
1248 } 1316 }
1249 int _truncDivFromInteger(int other) { 1317 int _truncDivFromInteger(int other) {
1250 _Bigint result = new _Bigint(); 1318 return other._toBigint()._div(this)._toValidInt();
1251 other._toBigint()._divRemTo(this, result, null);
1252 return result._toValidInt();
1253 } 1319 }
1254 int _moduloFromInteger(int other) { 1320 int _moduloFromInteger(int other) {
1255 _Bigint result = new _Bigint(); 1321 _Bigint result = other._toBigint()._rem(this);
1256 other._toBigint()._divRemTo(this, null, result);
1257 if (result._neg) { 1322 if (result._neg) {
1258 if (_neg) { 1323 if (_neg) {
1259 result._subTo(this, result); 1324 result = result._sub(this);
1260 } else { 1325 } else {
1261 result._addTo(this, result); 1326 result = result._add(this);
1262 } 1327 }
1263 } 1328 }
1264 return result._toValidInt(); 1329 return result._toValidInt();
1265 } 1330 }
1266 int _remainderFromInteger(int other) { 1331 int _remainderFromInteger(int other) {
1267 _Bigint result = new _Bigint(); 1332 return other._toBigint()._rem(this)._toValidInt();
1268 other._toBigint()._divRemTo(this, null, result);
1269 return result._toValidInt();
1270 } 1333 }
1271 bool _greaterThanFromInteger(int other) { 1334 bool _greaterThanFromInteger(int other) {
1272 return other._toBigint()._compareTo(this) > 0; 1335 return other._toBigint()._compare(this) > 0;
1273 } 1336 }
1274 bool _equalToInteger(int other) { 1337 bool _equalToInteger(int other) {
1275 return other._toBigint()._compareTo(this) == 0; 1338 return other._toBigint()._compare(this) == 0;
1276 } 1339 }
1277 1340
1278 // TODO(regis): Make this method private once the plumbing to invoke it from 1341 // Return pow(this, e) % m, with e >= 0, m > 0.
1279 // dart:math is in place. Move the argument checking to dart:math.
1280 // Return pow(this, e) % m.
1281 int modPow(int e, int m) { 1342 int modPow(int e, int m) {
1282 if (e is! int) throw new ArgumentError(e); 1343 if (e is! int || e < 0) throw new ArgumentError(e);
1283 if (m is! int) throw new ArgumentError(m); 1344 if (m is! int || m <= 0) throw new ArgumentError(m);
1284 int i = e.bitLength; 1345 final m_used = m._used;
1285 if (i <= 0) return 1; 1346 final m_used2p1 = 2*m_used + 1;
1347 final e_bitlen = e.bitLength;
1348 if (e_bitlen <= 0) return 1;
1286 if ((e is! _Bigint) || m.isEven) { 1349 if ((e is! _Bigint) || m.isEven) {
1287 _Reduction z = (i < 8 || m.isEven) ? new _Classic(m) : new _Montgomery(m); 1350 _Reduction z = (e_bitlen < 8 || m.isEven) ?
1351 new _Classic(m) : new _Montgomery(m);
1288 // TODO(regis): Should we use Barrett reduction for an even modulus? 1352 // TODO(regis): Should we use Barrett reduction for an even modulus?
1289 var r = new _Bigint(); 1353 var m_used = m._used;
1290 var r2 = new _Bigint(); 1354 var r_digits = new Uint32List(m_used2p1 + 1); // +1 for leading zero.
1291 var g = z._convert(this); 1355 var r2_digits = new Uint32List(m_used2p1 + 1); // +1 for leading zero.
1292 i--; 1356 var g_digits = new Uint32List(m_used + 1); // +1 for leading zero.
1293 g._copyTo(r); 1357 var g_used = z._convert(this, g_digits);
1358 // Initialize r with g.
1359 var j = g_used + 1; // Copy leading zero.
1360 while (--j >= 0) {
1361 r_digits[j] = g_digits[j];
1362 }
1363 var r_used = g_used;
1364 var r2_used;
1365 var i = e_bitlen - 1;
1294 while (--i >= 0) { 1366 while (--i >= 0) {
1295 z._sqrTo(r, r2); 1367 r2_used = z._sqr(r_digits, r_used, r2_digits);
1296 if ((e & (1 << i)) != 0) { 1368 if ((e & (1 << i)) != 0) {
1297 z._mulTo(r2, g, r); 1369 r_used = z._mul(r2_digits, r2_used, g_digits, g_used, r_digits);
1298 } else { 1370 } else {
1299 var t = r; 1371 var t_digits = r_digits;
1300 r = r2; 1372 var t_used = r_used;
1301 r2 = t; 1373 r_digits = r2_digits;
1374 r_used = r2_used;
1375 r2_digits = t_digits;
1376 r2_used = t_used;
1302 } 1377 }
1303 } 1378 }
1304 return z._revert(r)._toValidInt(); 1379 return z._revert(r_digits, r_used)._toValidInt();
1305 } 1380 }
1306 var k; 1381 var k;
1307 // TODO(regis): Are these values of k really optimal for our implementation? 1382 if (e_bitlen < 18) k = 1;
1308 if (i < 18) k = 1; 1383 else if (e_bitlen < 48) k = 3;
1309 else if (i < 48) k = 3; 1384 else if (e_bitlen < 144) k = 4;
1310 else if (i < 144) k = 4; 1385 else if (e_bitlen < 768) k = 5;
1311 else if (i < 768) k = 5;
1312 else k = 6; 1386 else k = 6;
1313 _Reduction z = new _Montgomery(m); 1387 _Reduction z = new _Montgomery(m);
1314 var n = 3; 1388 var n = 3;
1315 var k1 = k - 1; 1389 final k1 = k - 1;
1316 var km = (1 << k) - 1; 1390 final km = (1 << k) - 1;
1317 List g = new List(km + 1); 1391 List g_digits = new List(km + 1);
1318 g[1] = z._convert(this); 1392 List g_used = new List(km + 1);
1393 g_digits[1] = new Uint32List(m_used + 1); // +1 for leading zero.
1394 g_used[1] = z._convert(this, g_digits[1]);
1319 if (k > 1) { 1395 if (k > 1) {
1320 var g2 = new _Bigint(); 1396 var g2_digits = new Uint32List(m_used2p1 + 1); // +1 for leading zero.
1321 z._sqrTo(g[1], g2); 1397 var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits);
1322 while (n <= km) { 1398 while (n <= km) {
1323 g[n] = new _Bigint(); 1399 g_digits[n] = new Uint32List(m_used2p1 + 1); // +1 for leading zero.
1324 z._mulTo(g2, g[n - 2], g[n]); 1400 g_used[n] = z._mul(g2_digits, g2_used,
1401 g_digits[n - 2], g_used[n - 2],
1402 g_digits[n]);
1325 n += 2; 1403 n += 2;
1326 } 1404 }
1327 } 1405 }
1328 var j = e._used - 1;
1329 var w; 1406 var w;
1330 var is1 = true; 1407 var is1 = true;
1331 var r = new _Bigint._fromInt(1); 1408 var r_digits = ONE._digits;
1332 var r2 = new _Bigint(); 1409 var r_used = ONE._used;
1333 var t; 1410 var r2_digits = new Uint32List(m_used2p1 + 1); // +1 for leading zero.
1411 var r2_used;
1334 var e_digits = e._digits; 1412 var e_digits = e._digits;
1335 i = _nbits(e_digits[j]) - 1; 1413 var j = e._used - 1;
1414 var i = _nbits(e_digits[j]) - 1;
1336 while (j >= 0) { 1415 while (j >= 0) {
1337 if (i >= k1) { 1416 if (i >= k1) {
1338 w = (e_digits[j] >> (i - k1)) & km; 1417 w = (e_digits[j] >> (i - k1)) & km;
1339 } else { 1418 } else {
1340 w = (e_digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i); 1419 w = (e_digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
1341 if (j > 0) { 1420 if (j > 0) {
1342 w |= e_digits[j - 1] >> (DIGIT_BITS + i - k1); 1421 w |= e_digits[j - 1] >> (DIGIT_BITS + i - k1);
1343 } 1422 }
1344 } 1423 }
1345 n = k; 1424 n = k;
1346 while ((w & 1) == 0) { 1425 while ((w & 1) == 0) {
1347 w >>= 1; 1426 w >>= 1;
1348 --n; 1427 --n;
1349 } 1428 }
1350 if ((i -= n) < 0) { 1429 if ((i -= n) < 0) {
1351 i += DIGIT_BITS; 1430 i += DIGIT_BITS;
1352 --j; 1431 --j;
1353 } 1432 }
1354 if (is1) { // r == 1, don't bother squaring or multiplying it. 1433 if (is1) { // r == 1, don't bother squaring or multiplying it.
1355 g[w]._copyTo(r); 1434 r_digits = new Uint32List(m_used2p1 + 1); // +1 for leading zero.
1435 r_used = g_used[w];
1436 var gw_digits = g_digits[w];
1437 var ri = r_used + 1; // Copy leading zero.
1438 while (--ri >= 0) {
1439 r_digits[ri] = gw_digits[ri];
1440 }
1356 is1 = false; 1441 is1 = false;
1357 } 1442 }
1358 else { 1443 else {
1359 while (n > 1) { 1444 while (n > 1) {
1360 z._sqrTo(r, r2); 1445 r2_used = z._sqr(r_digits, r_used, r2_digits);
1361 z._sqrTo(r2, r); 1446 r_used = z._sqr(r2_digits, r2_used, r_digits);
1362 n -= 2; 1447 n -= 2;
1363 } 1448 }
1364 if (n > 0) { 1449 if (n > 0) {
1365 z._sqrTo(r, r2); 1450 r2_used = z._sqr(r_digits, r_used, r2_digits);
1366 } else { 1451 } else {
1367 t = r; 1452 var t_digits = r_digits;
1368 r = r2; 1453 var t_used = r_used;
1369 r2 = t; 1454 r_digits = r2_digits;
1455 r_used = r2_used;
1456 r2_digits = t_digits;
1457 r2_used = t_used;
1370 } 1458 }
1371 z._mulTo(r2,g[w], r); 1459 r_used = z._mul(r2_digits, r2_used, g_digits[w], g_used[w], r_digits);
1372 } 1460 }
1373
1374 while (j >= 0 && (e_digits[j] & (1 << i)) == 0) { 1461 while (j >= 0 && (e_digits[j] & (1 << i)) == 0) {
1375 z._sqrTo(r, r2); 1462 r2_used = z._sqr(r_digits, r_used, r2_digits);
1376 t = r; 1463 var t_digits = r_digits;
1377 r = r2; 1464 var t_used = r_used;
1378 r2 = t; 1465 r_digits = r2_digits;
1466 r_used = r2_used;
1467 r2_digits = t_digits;
1468 r2_used = t_used;
1379 if (--i < 0) { 1469 if (--i < 0) {
1380 i = DIGIT_BITS - 1; 1470 i = DIGIT_BITS - 1;
1381 --j; 1471 --j;
1382 } 1472 }
1383 } 1473 }
1384 } 1474 }
1385 return z._revert(r)._toValidInt(); 1475 assert(!is1);
1476 return z._revert(r_digits, r_used)._toValidInt();
1386 } 1477 }
1387 } 1478 }
1388 1479
1389 // Interface for modular reduction. 1480 // Interface for modular reduction.
1390 class _Reduction { 1481 class _Reduction {
1391 _Bigint _convert(_Bigint x); 1482 // Return the number of digits used by r_digits.
1392 _Bigint _revert(_Bigint x); 1483 int _convert(_Bigint x, Uint32List r_digits);
1393 void _mulTo(_Bigint x, _Bigint y, _Bigint r); 1484 int _mul(Uint32List x_digits, int x_used,
1394 void _sqrTo(_Bigint x, _Bigint r); 1485 Uint32List y_digits, int y_used, Uint32List r_digits);
1486 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits);
1487
1488 // Return x reverted to _Bigint.
1489 _Bigint _revert(Uint32List x_digits, int x_used);
1395 } 1490 }
1396 1491
1397 // Montgomery reduction on _Bigint. 1492 // Montgomery reduction on _Bigint.
1398 class _Montgomery implements _Reduction { 1493 class _Montgomery implements _Reduction {
1399 _Bigint _m; 1494 _Bigint _m; // Modulus.
1400 int _mused2; 1495 int _mused2p1;
1401 Uint32List _args; 1496 Uint32List _args;
1402 int _digits_per_step; // Number of digits processed in one step. 1 or 2. 1497 int _digits_per_step; // Number of digits processed in one step. 1 or 2.
1403 static const int _X = 0; // Index of x. 1498 static const int _X = 0; // Index of x.
1404 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only). 1499 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only).
1405 static const int _RHO = 2; // Index of rho. 1500 static const int _RHO = 2; // Index of rho.
1406 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only). 1501 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only).
1407 static const int _MU = 4; // Index of mu. 1502 static const int _MU = 4; // Index of mu.
1408 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only). 1503 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only).
1409 1504
1410 _Montgomery(m) { 1505 _Montgomery(m) {
1411 _m = m._toBigint(); 1506 _m = m._toBigint();
1412 _mused2 = 2*_m._used; 1507 _mused2p1 = 2*_m._used + 1;
1413 _args = new Uint32List(6); 1508 _args = new Uint32List(6);
1414 // Determine if we can process digit pairs by calling an intrinsic. 1509 // Determine if we can process digit pairs by calling an intrinsic.
1415 _digits_per_step = _mulMod(_args, _args, 0); 1510 _digits_per_step = _mulMod(_args, _args, 0);
1416 _args[_X] = _m._digits[0]; 1511 _args[_X] = _m._digits[0];
1417 if (_digits_per_step == 1) { 1512 if (_digits_per_step == 1) {
1418 _invDigit(_args); 1513 _invDigit(_args);
1419 } else { 1514 } else {
1420 assert(_digits_per_step == 2); 1515 assert(_digits_per_step == 2);
1421 _args[_X_HI] = _m._digits[1]; 1516 _args[_X_HI] = _m._digits[1];
1422 _invDigitPair(_args); 1517 _invDigitPair(_args);
(...skipping 18 matching lines...) Expand all
1441 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 1536 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8
1442 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 1537 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
1443 // Last step - calculate inverse mod DIGIT_BASE directly; 1538 // Last step - calculate inverse mod DIGIT_BASE directly;
1444 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. 1539 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints.
1445 y = (y*(2 - x*y % _Bigint.DIGIT_BASE)) % _Bigint.DIGIT_BASE; 1540 y = (y*(2 - x*y % _Bigint.DIGIT_BASE)) % _Bigint.DIGIT_BASE;
1446 // y == 1/x mod DIGIT_BASE 1541 // y == 1/x mod DIGIT_BASE
1447 y = -y; // We really want the negative inverse. 1542 y = -y; // We really want the negative inverse.
1448 args[_RHO] = y & _Bigint.DIGIT_MASK; 1543 args[_RHO] = y & _Bigint.DIGIT_MASK;
1449 } 1544 }
1450 1545
1451
1452 // Calculates -1/x % DIGIT_BASE^2, x is a pair of 32-bit digits. 1546 // Calculates -1/x % DIGIT_BASE^2, x is a pair of 32-bit digits.
1453 // Operation: 1547 // Operation:
1454 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod DIGIT_BASE^2. 1548 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod DIGIT_BASE^2.
1455 static void _invDigitPair(Uint32List args) { 1549 static void _invDigitPair(Uint32List args) {
1456 var xl = args[_X]; // Lower 32-bit digit of x. 1550 var xl = args[_X]; // Lower 32-bit digit of x.
1457 var y = xl & 3; // y == 1/x mod 2^2 1551 var y = xl & 3; // y == 1/x mod 2^2
1458 y = (y*(2 - (xl & 0xf)*y)) & 0xf; // y == 1/x mod 2^4 1552 y = (y*(2 - (xl & 0xf)*y)) & 0xf; // y == 1/x mod 2^4
1459 y = (y*(2 - (xl & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 1553 y = (y*(2 - (xl & 0xff)*y)) & 0xff; // y == 1/x mod 2^8
1460 y = (y*(2 - (((xl & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 1554 y = (y*(2 - (((xl & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
1461 y = (y*(2 - ((xl*y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32 1555 y = (y*(2 - ((xl*y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32
1462 var x = (args[_X_HI] << _Bigint.DIGIT_BITS) | xl; 1556 var x = (args[_X_HI] << _Bigint.DIGIT_BITS) | xl;
1463 y = (y*(2 - ((x*y) & 0xffffffffffffffff))) & 0xffffffffffffffff; 1557 y = (y*(2 - ((x*y) & 0xffffffffffffffff))) & 0xffffffffffffffff;
1464 // y == 1/x mod DIGIT_BASE^2 1558 // y == 1/x mod DIGIT_BASE^2
1465 y = -y; // We really want the negative inverse. 1559 y = -y; // We really want the negative inverse.
1466 args[_RHO] = y & _Bigint.DIGIT_MASK; 1560 args[_RHO] = y & _Bigint.DIGIT_MASK;
1467 args[_RHO_HI] = (y >> _Bigint.DIGIT_BITS) & _Bigint.DIGIT_MASK; 1561 args[_RHO_HI] = (y >> _Bigint.DIGIT_BITS) & _Bigint.DIGIT_MASK;
1468 } 1562 }
1469 1563
1470
1471 // Operation: 1564 // Operation:
1472 // args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE. 1565 // args[_MU] = args[_RHO]*digits[i] mod DIGIT_BASE.
1473 // return 1. 1566 // return 1.
1474 // Note: intrinsics on 64-bit platform may process a digit pair: 1567 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices:
1475 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod DIGIT_BASE^2. 1568 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod DIGIT_BASE^2.
1476 // return 2. 1569 // return 2.
1477 static int _mulMod(Uint32List args, Uint32List digits, int i) { 1570 static int _mulMod(Uint32List args, Uint32List digits, int i) {
1571 // Verify that digit pairs are accessible for 64-bit processing.
1572 assert(digits.length > (i | 1));
1478 const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; 1573 const int MU_MASK = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1;
1479 var rhol = args[_RHO] & _Bigint.DIGIT2_MASK; 1574 var rhol = args[_RHO] & _Bigint.DIGIT2_MASK;
1480 var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS; 1575 var rhoh = args[_RHO] >> _Bigint.DIGIT2_BITS;
1481 var dh = digits[i] >> _Bigint.DIGIT2_BITS; 1576 var dh = digits[i] >> _Bigint.DIGIT2_BITS;
1482 var dl = digits[i] & _Bigint.DIGIT2_MASK; 1577 var dl = digits[i] & _Bigint.DIGIT2_MASK;
1483 args[_MU] = 1578 args[_MU] =
1484 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint.DIGIT2_BITS)) 1579 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint.DIGIT2_BITS))
1485 & _Bigint.DIGIT_MASK; 1580 & _Bigint.DIGIT_MASK;
1486 return 1; 1581 return 1;
1487 } 1582 }
1488 1583
1489 // Return x*R mod _m 1584 // r = x*R mod _m.
1490 _Bigint _convert(_Bigint x) { 1585 // Return r_used.
1491 var r = new _Bigint(); 1586 int _convert(_Bigint x, Uint32List r_digits) {
1492 x.abs()._dlShiftTo(_m._used, r); 1587 var r = x._abs()._dlShift(_m._used)._rem(_m);
1493 r._divRemTo(_m, null, r);
1494 if (x._neg && !r._neg && r._used > 0) { 1588 if (x._neg && !r._neg && r._used > 0) {
1495 _m._subTo(r, r); 1589 r = _m._sub(r);
1496 } 1590 }
1497 return r; 1591 var used = r._used;
1592 var digits = r._digits;
1593 var i = used + 1; // Copy leading zero.
1594 while (--i >= 0) {
1595 r_digits[i] = digits[i];
1596 }
1597 return used;
1498 } 1598 }
1499 1599
1500 // Return x/R mod _m 1600 _Bigint _revert(Uint32List x_digits, int x_used) {
1501 _Bigint _revert(_Bigint x) { 1601 var r_digits = new Uint32List(_mused2p1 + 1); // +1 for leading zero.
1502 var r = new _Bigint(); 1602 var i = x_used + 1; // Copy leading zero.
1503 x._copyTo(r); 1603 while (--i >= 0) {
1504 _reduce(r); 1604 r_digits[i] = x_digits[i];
1505 return r; 1605 }
1606 var r_used = _reduce(r_digits, x_used);
1607 return new _Bigint(false, r_used, r_digits);
1506 } 1608 }
1507 1609
1508 // x = x/R mod _m 1610 // x = x/R mod _m.
1509 void _reduce(_Bigint x) { 1611 // Return x_used.
1510 x._ensureLength(_mused2 + 1); 1612 int _reduce(Uint32List x_digits, int x_used) {
1511 var x_digits = x._digits; 1613 while (x_used < _mused2p1) { // Pad x so _mulAdd has enough room later.
1512 while (x._used <= _mused2) { // Pad x so _mulAdd has enough room later. 1614 x_digits[x_used++] = 0;
1513 x_digits[x._used++] = 0;
1514 } 1615 }
1515 x_digits[x._used] = 0; // Set leading zero for 64-bit processing. 1616 x_digits[x_used] = 0; // Set leading zero for 64-bit processing.
1516 var m_used = _m._used; 1617 var m_used = _m._used;
1517 var m_digits = _m._digits; 1618 var m_digits = _m._digits;
1518 var i = 0; 1619 var i = 0;
1519 while (i < m_used) { 1620 while (i < m_used) {
1520 var d = _mulMod(_args, x_digits, i); 1621 var d = _mulMod(_args, x_digits, i);
1521 assert(d == _digits_per_step); 1622 assert(d == _digits_per_step);
1522 d = _Bigint._mulAdd(_args, _MU, m_digits, 0, x_digits, i, m_used); 1623 d = _Bigint._mulAdd(_args, _MU, m_digits, 0, x_digits, i, m_used);
1523 assert(d == _digits_per_step); 1624 assert(d == _digits_per_step);
1524 i += d; 1625 i += d;
1525 } 1626 }
1526 x._clamp(); 1627 // Clamp x.
1527 x._drShiftTo(m_used, x); 1628 while (x_used > 0 && x_digits[x_used - 1] == 0) {
1528 if (x._compareTo(_m) >= 0) { 1629 --x_used;
1529 x._subTo(_m, x);
1530 } 1630 }
1631 x_used = _Bigint._drShiftDigits(x_digits, x_used, m_used, x_digits);
1632 if (_Bigint._compareDigits(x_digits, x_used, m_digits, m_used) >= 0) {
1633 _Bigint._absSub(x_digits, x_used, m_digits, m_used, x_digits);
1634 }
1635 // Clamp x.
1636 while (x_used > 0 && x_digits[x_used - 1] == 0) {
1637 --x_used;
1638 }
1639 return x_used;
1531 } 1640 }
1532 1641
1533 // r = x^2/R mod _m ; x != r 1642 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) {
1534 void _sqrTo(_Bigint x, _Bigint r) { 1643 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits);
1535 x._sqrTo(r); 1644 return _reduce(r_digits, r_used);
1536 _reduce(r);
1537 } 1645 }
1538 1646
1539 // r = x*y/R mod _m ; x, y != r 1647 int _mul(Uint32List x_digits, int x_used,
1540 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { 1648 Uint32List y_digits, int y_used,
1541 x._mulTo(y, r); 1649 Uint32List r_digits) {
1542 _reduce(r); 1650 var r_used = _Bigint._mulDigits(x_digits, x_used,
1651 y_digits, y_used,
1652 r_digits);
1653 return _reduce(r_digits, r_used);
1543 } 1654 }
1544 } 1655 }
1545 1656
1546 // Modular reduction using "classic" algorithm. 1657 // Modular reduction using "classic" algorithm.
1547 class _Classic implements _Reduction { 1658 class _Classic implements _Reduction {
1548 _Bigint _m; 1659 _Bigint _m; // Modulus.
1660 _Bigint _norm_m; // Normalized _m.
1661 Uint32List _neg_norm_m_digits; // Negated _norm_m digits.
1662 int _m_nsh; // Normalization shift amount.
1663 Uint32List _mt_qd; // Top _norm_m digit(s) and place holder for
1664 // estimated quotient digit(s).
1665 Uint32List _t_digits; // Temporary digits used during reduction.
1549 1666
1550 _Classic(int m) { 1667 _Classic(int m) {
1551 _m = m._toBigint(); 1668 _m = m._toBigint();
1669 // Preprocess arguments to _remDigits.
1670 var nsh = _Bigint.DIGIT_BITS - _Bigint._nbits(_m._digits[_m._used - 1]);
1671 // For 64-bit processing, make sure _norm_m_digits has an even number of
1672 // digits.
1673 if (_m._used.isOdd) {
1674 nsh += _Bigint.DIGIT_BITS;
1675 }
1676 _m_nsh = nsh;
1677 _norm_m = _m._lShift(nsh);
1678 var nm_used = _norm_m._used;
1679 assert(nm_used.isEven);
1680 _mt_qd = new Uint32List(4);
1681 _mt_qd[_Bigint._YT_LO] = _norm_m._digits[nm_used - 2];
1682 _mt_qd[_Bigint._YT] = _norm_m._digits[nm_used - 1];
1683 // Negate _norm_m so we can use _mulAdd instead of unimplemented _mulSub.
1684 var neg_norm_m = _Bigint.ONE._dlShift(nm_used)._sub(_norm_m);
1685 if (neg_norm_m._used < nm_used) {
1686 _neg_norm_m_digits =
1687 _Bigint._cloneDigits(neg_norm_m._digits, 0, nm_used, nm_used);
1688 } else {
1689 _neg_norm_m_digits = neg_norm_m._digits;
1690 }
1691 // _neg_norm_m_digits is read-only and has nm_used digits (possibly
1692 // including several leading zeros) plus a leading zero for 64-bit
1693 // processing.
1694 _t_digits = new Uint32List(2*nm_used + 1); // +1 for leading zero.
1552 } 1695 }
1553 1696
1554 _Bigint _convert(_Bigint x) { 1697 int _convert(_Bigint x, Uint32List r_digits) {
1555 if (x._neg || x._compareTo(_m) >= 0) { 1698 var digits;
1556 var r = new _Bigint(); 1699 var used;
1557 x._divRemTo(_m, null, r); 1700 if (x._neg || x._compare(_m) >= 0) {
1701 var r = x.rem(_m);
1558 if (x._neg && !r._neg && r._used > 0) { 1702 if (x._neg && !r._neg && r._used > 0) {
1559 _m._subTo(r, r); 1703 r = _m._sub(r);
1560 } 1704 }
1561 return r; 1705 assert(!r._neg);
1706 used = r._used;
1707 digits = r._digits;
1708 } else {
1709 used = x._used;
1710 digits = x._digits;
1562 } 1711 }
1563 return x; 1712 var i = used + 1; // Copy leading zero.
1713 while (--i >= 0) {
1714 r_digits[i] = digits[i];
1715 }
1716 return used;
1564 } 1717 }
1565 1718
1566 _Bigint _revert(_Bigint x) { 1719 _Bigint _revert(Uint32List x_digits, int x_used) {
1567 return x; 1720 return new _Bigint(false, x_used, x_digits);
1568 } 1721 }
1569 1722
1570 void _reduce(_Bigint x) { 1723 int _reduce(Uint32List x_digits, int x_used) {
1571 x._divRemTo(_m, null, x); 1724 // The function _remDigits(...) is optimized for reduction and equivalent to
1725 // calling _convert(_revert(x_digits, x_used)._rem(_m), x_digits);
1726 return _Bigint._remDigits(x_digits, x_used,
1727 _norm_m._digits, _norm_m._used,
1728 _neg_norm_m_digits,
1729 _m_nsh,
1730 _mt_qd,
1731 _t_digits,
1732 x_digits);
1572 } 1733 }
1573 1734
1574 void _sqrTo(_Bigint x, _Bigint r) { 1735 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) {
1575 x._sqrTo(r); 1736 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits);
1576 _reduce(r); 1737 return _reduce(r_digits, r_used);
1577 } 1738 }
1578 1739
1579 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { 1740 int _mul(Uint32List x_digits, int x_used,
1580 x._mulTo(y, r); 1741 Uint32List y_digits, int y_used,
1581 _reduce(r); 1742 Uint32List r_digits) {
1743 var r_used = _Bigint._mulDigits(x_digits, x_used,
1744 y_digits, y_used,
1745 r_digits);
1746 return _reduce(r_digits, r_used);
1582 } 1747 }
1583 } 1748 }
OLDNEW
« no previous file with comments | « no previous file | runtime/lib/integers.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698