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

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

Issue 577093003: Cache value of '_digits' and '_used' fields in a local variable as appropriate. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 3 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 | no next file » | 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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 119
120 // Initialize instance to the given hex string. 120 // Initialize instance to the given hex string.
121 // TODO(regis): Copy Bigint::NewFromHexCString, fewer digit accesses. 121 // TODO(regis): Copy Bigint::NewFromHexCString, fewer digit accesses.
122 // TODO(regis): Unused. 122 // TODO(regis): Unused.
123 _Bigint _setHex(String s) { 123 _Bigint _setHex(String s) {
124 const int HEX_BITS = 4; 124 const int HEX_BITS = 4;
125 const int HEX_DIGITS_PER_DIGIT = 8; 125 const int HEX_DIGITS_PER_DIGIT = 8;
126 var hexDigitIndex = s.length; 126 var hexDigitIndex = s.length;
127 _ensureLength((hexDigitIndex + HEX_DIGITS_PER_DIGIT - 1) ~/ HEX_DIGITS_PER_D IGIT); 127 _ensureLength((hexDigitIndex + HEX_DIGITS_PER_DIGIT - 1) ~/ HEX_DIGITS_PER_D IGIT);
128 var bitIndex = 0; 128 var bitIndex = 0;
129 var digits = _digits;
129 while (--hexDigitIndex >= 0) { 130 while (--hexDigitIndex >= 0) {
130 var digit = DIGIT_TABLE[s.codeUnitAt(hexDigitIndex)]; 131 var digit = DIGIT_TABLE[s.codeUnitAt(hexDigitIndex)];
131 if (digit = null) { 132 if (digit = null) {
132 if (s[hexDigitIndex] == "-") _neg = true; 133 if (s[hexDigitIndex] == "-") _neg = true;
133 continue; // Ignore invalid digits. 134 continue; // Ignore invalid digits.
134 } 135 }
135 _neg = false; // Ignore "-" if not at index 0. 136 _neg = false; // Ignore "-" if not at index 0.
136 if (bitIndex == 0) { 137 if (bitIndex == 0) {
137 _digits[_used++] = digit; 138 digits[_used++] = digit;
138 // TODO(regis): What if too many bad digits were ignored and 139 // TODO(regis): What if too many bad digits were ignored and
139 // _used becomes larger than _digits.length? error or reallocate? 140 // _used becomes larger than _digits.length? error or reallocate?
140 } else { 141 } else {
141 _digits[_used - 1] |= digit << bitIndex; 142 digits[_used - 1] |= digit << bitIndex;
142 } 143 }
143 bitIndex = (bitIndex + HEX_BITS) % DIGIT_BITS; 144 bitIndex = (bitIndex + HEX_BITS) % DIGIT_BITS;
144 } 145 }
145 _clamp(); 146 _clamp();
146 return this; 147 return this;
147 } 148 }
148 149
149 // Initialize instance to the given double value. 150 // Initialize instance to the given double value.
150 _Bigint _setDouble(int sign, int significand, int exponent) { 151 _Bigint _setDouble(int sign, int significand, int exponent) {
151 assert(significand >= 0); 152 assert(significand >= 0);
(...skipping 16 matching lines...) Expand all
168 for(value = 10; value < 36; ++value) table[digit++] = value; 169 for(value = 10; value < 36; ++value) table[digit++] = value;
169 digit = "A".codeUnitAt(0); 170 digit = "A".codeUnitAt(0);
170 for(value = 10; value < 36; ++value) table[digit++] = value; 171 for(value = 10; value < 36; ++value) table[digit++] = value;
171 return table; 172 return table;
172 } 173 }
173 174
174 // Return most compact integer (i.e. possibly Smi or Mint). 175 // Return most compact integer (i.e. possibly Smi or Mint).
175 // TODO(regis): Intrinsify. 176 // TODO(regis): Intrinsify.
176 int _toValidInt() { 177 int _toValidInt() {
177 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised. 178 assert(DIGIT_BITS == 32); // Otherwise this code needs to be revised.
178 if (_used == 0) return 0; 179 var used = _used;
179 if (_used == 1) return _neg ? -_digits[0] : _digits[0]; 180 if (used == 0) return 0;
180 if (_used > 2) return this; 181 var digits = _digits;
182 if (used == 1) return _neg ? -digits[0] : digits[0];
183 if (used > 2) return this;
181 if (_neg) { 184 if (_neg) {
182 if (_digits[1] > 0x80000000) return this; 185 if (digits[1] > 0x80000000) return this;
183 if (_digits[1] == 0x80000000) { 186 if (digits[1] == 0x80000000) {
184 if (_digits[0] > 0) return this; 187 if (digits[0] > 0) return this;
185 return MIN_INT64; 188 return MIN_INT64;
186 } 189 }
187 return -((_digits[1] << DIGIT_BITS) | _digits[0]); 190 return -((digits[1] << DIGIT_BITS) | digits[0]);
188 } 191 }
189 if (_digits[1] >= 0x80000000) return this; 192 if (digits[1] >= 0x80000000) return this;
190 return (_digits[1] << DIGIT_BITS) | _digits[0]; 193 return (digits[1] << DIGIT_BITS) | digits[0];
191 } 194 }
192 195
193 // Conversion from int to bigint. 196 // Conversion from int to bigint.
194 _Bigint _toBigint() => this; 197 _Bigint _toBigint() => this;
195 198
196 // Make sure at least 'length' _digits are allocated. 199 // Make sure at least 'length' _digits are allocated.
197 // Copy existing _digits if reallocation is necessary. 200 // Copy existing _digits if reallocation is necessary.
198 // TODO(regis): Check that we are not preserving _digits unnecessarily. 201 // TODO(regis): Check that we are not preserving _digits unnecessarily.
199 void _ensureLength(int length) { 202 void _ensureLength(int length) {
200 if (length > 0 && (_digits == null || length > _digits.length)) { 203 var digits = _digits;
204 if (length > 0 && (digits == null || length > digits.length)) {
201 var new_digits = new Uint32List(length + EXTRA_DIGITS); 205 var new_digits = new Uint32List(length + EXTRA_DIGITS);
202 if (_digits != null) { 206 if (digits != null) {
203 for (var i = _used; --i >= 0; ) { 207 for (var i = _used; --i >= 0; ) {
204 new_digits[i] = _digits[i]; 208 new_digits[i] = digits[i];
205 } 209 }
206 } 210 }
207 _digits = new_digits; 211 _digits = new_digits;
208 } 212 }
209 } 213 }
210 214
211 // Clamp off excess high _digits. 215 // Clamp off excess high _digits.
212 void _clamp() { 216 void _clamp() {
213 while (_used > 0 && _digits[_used - 1] == 0) { 217 var digits = _digits;
218 while (_used > 0 && digits[_used - 1] == 0) {
214 --_used; 219 --_used;
215 } 220 }
216 assert(_used > 0 || !_neg);
217 } 221 }
218 222
219 // Copy this to r. 223 // Copy this to r.
220 void _copyTo(_Bigint r) { 224 void _copyTo(_Bigint r) {
221 r._ensureLength(_used); 225 r._ensureLength(_used);
226 var digits = _digits;
227 var r_digits = r._digits;
222 for (var i = _used - 1; i >= 0; --i) { 228 for (var i = _used - 1; i >= 0; --i) {
223 r._digits[i] = _digits[i]; 229 r_digits[i] = digits[i];
224 } 230 }
225 r._used = _used; 231 r._used = _used;
226 r._neg = _neg; 232 r._neg = _neg;
227 } 233 }
228 234
229 // Return the bit length of digit x. 235 // Return the bit length of digit x.
230 int _nbits(int x) { 236 int _nbits(int x) {
231 var r = 1, t; 237 var r = 1, t;
232 if ((t = x >> 16) != 0) { x = t; r += 16; } 238 if ((t = x >> 16) != 0) { x = t; r += 16; }
233 if ((t = x >> 8) != 0) { x = t; r += 8; } 239 if ((t = x >> 8) != 0) { x = t; r += 8; }
234 if ((t = x >> 4) != 0) { x = t; r += 4; } 240 if ((t = x >> 4) != 0) { x = t; r += 4; }
235 if ((t = x >> 2) != 0) { x = t; r += 2; } 241 if ((t = x >> 2) != 0) { x = t; r += 2; }
236 if ((x >> 1) != 0) { r += 1; } 242 if ((x >> 1) != 0) { r += 1; }
237 return r; 243 return r;
238 } 244 }
239 245
240 // r = this << n*DIGIT_BITS. 246 // r = this << n*DIGIT_BITS.
241 void _dlShiftTo(int n, _Bigint r) { 247 void _dlShiftTo(int n, _Bigint r) {
242 var r_used = _used + n; 248 var r_used = _used + n;
243 r._ensureLength(r_used); 249 r._ensureLength(r_used);
250 var digits = _digits;
251 var r_digits = r._digits;
244 for (var i = _used - 1; i >= 0; --i) { 252 for (var i = _used - 1; i >= 0; --i) {
245 r._digits[i + n] = _digits[i]; 253 r_digits[i + n] = digits[i];
246 } 254 }
247 for (var i = n - 1; i >= 0; --i) { 255 for (var i = n - 1; i >= 0; --i) {
248 r._digits[i] = 0; 256 r_digits[i] = 0;
249 } 257 }
250 r._used = r_used; 258 r._used = r_used;
251 r._neg = _neg; 259 r._neg = _neg;
252 } 260 }
253 261
254 // r = this >> n*DIGIT_BITS. 262 // r = this >> n*DIGIT_BITS.
255 void _drShiftTo(int n, _Bigint r) { 263 void _drShiftTo(int n, _Bigint r) {
256 var r_used = _used - n; 264 var r_used = _used - n;
257 if (r_used < 0) { 265 if (r_used < 0) {
258 if (_neg) { 266 if (_neg) {
259 // Set r to -1. 267 // Set r to -1.
260 r._neg = true; 268 r._neg = true;
261 r._ensureLength(1); 269 r._ensureLength(1);
262 r._used = 1; 270 r._used = 1;
263 r._digits[0] = 1; 271 r._digits[0] = 1;
264 } else { 272 } else {
265 // Set r to 0. 273 // Set r to 0.
266 r._neg = false; 274 r._neg = false;
267 r._used = 0; 275 r._used = 0;
268 } 276 }
269 return; 277 return;
270 } 278 }
271 r._ensureLength(r_used); 279 r._ensureLength(r_used);
272 for (var i = n; i < _used; ++i) { 280 var digits = _digits;
273 r._digits[i - n] = _digits[i]; 281 var r_digits = r._digits;
282 var used = _used;
283 for (var i = n; i < used; ++i) {
284 r_digits[i - n] = digits[i];
274 } 285 }
275 r._used = r_used; 286 r._used = r_used;
276 r._neg = _neg; 287 r._neg = _neg;
277 if (_neg) { 288 if (_neg) {
278 // Round down if any bit was shifted out. 289 // Round down if any bit was shifted out.
279 for (var i = 0; i < n; i++) { 290 for (var i = 0; i < n; i++) {
280 if (_digits[i] != 0) { 291 if (digits[i] != 0) {
281 r._subTo(ONE, r); 292 r._subTo(ONE, r);
282 break; 293 break;
283 } 294 }
284 } 295 }
285 } 296 }
286 } 297 }
287 298
288 // r = this << n. 299 // r = this << n.
289 void _lShiftTo(int n, _Bigint r) { 300 void _lShiftTo(int n, _Bigint r) {
290 var ds = n ~/ DIGIT_BITS; 301 var ds = n ~/ DIGIT_BITS;
291 var bs = n % DIGIT_BITS; 302 var bs = n % DIGIT_BITS;
292 if (bs == 0) { 303 if (bs == 0) {
293 _dlShiftTo(ds, r); 304 _dlShiftTo(ds, r);
294 return; 305 return;
295 } 306 }
296 var cbs = DIGIT_BITS - bs; 307 var cbs = DIGIT_BITS - bs;
297 var bm = (1 << cbs) - 1; 308 var bm = (1 << cbs) - 1;
298 var r_used = _used + ds + 1; 309 var r_used = _used + ds + 1;
299 r._ensureLength(r_used); 310 r._ensureLength(r_used);
311 var digits = _digits;
312 var r_digits = r._digits;
300 var c = 0; 313 var c = 0;
301 for (var i = _used - 1; i >= 0; --i) { 314 for (var i = _used - 1; i >= 0; --i) {
302 r._digits[i + ds + 1] = (_digits[i] >> cbs) | c; 315 r_digits[i + ds + 1] = (digits[i] >> cbs) | c;
303 c = (_digits[i] & bm) << bs; 316 c = (digits[i] & bm) << bs;
304 } 317 }
305 for (var i = ds - 1; i >= 0; --i) { 318 for (var i = ds - 1; i >= 0; --i) {
306 r._digits[i] = 0; 319 r_digits[i] = 0;
307 } 320 }
308 r._digits[ds] = c; 321 r_digits[ds] = c;
309 r._used = r_used; 322 r._used = r_used;
310 r._neg = _neg; 323 r._neg = _neg;
311 r._clamp(); 324 r._clamp();
312 } 325 }
313 326
314 // r = this >> n. 327 // r = this >> n.
315 void _rShiftTo(int n, _Bigint r) { 328 void _rShiftTo(int n, _Bigint r) {
316 var ds = n ~/ DIGIT_BITS; 329 var ds = n ~/ DIGIT_BITS;
317 var bs = n % DIGIT_BITS; 330 var bs = n % DIGIT_BITS;
318 if (bs == 0) { 331 if (bs == 0) {
(...skipping 11 matching lines...) Expand all
330 } else { 343 } else {
331 // Set r to 0. 344 // Set r to 0.
332 r._neg = false; 345 r._neg = false;
333 r._used = 0; 346 r._used = 0;
334 } 347 }
335 return; 348 return;
336 } 349 }
337 var cbs = DIGIT_BITS - bs; 350 var cbs = DIGIT_BITS - bs;
338 var bm = (1 << bs) - 1; 351 var bm = (1 << bs) - 1;
339 r._ensureLength(r_used); 352 r._ensureLength(r_used);
340 r._digits[0] = _digits[ds] >> bs; 353 var digits = _digits;
341 for (var i = ds + 1; i < _used; ++i) { 354 var r_digits = r._digits;
342 r._digits[i - ds - 1] |= (_digits[i] & bm) << cbs; 355 r_digits[0] = digits[ds] >> bs;
343 r._digits[i - ds] = _digits[i] >> bs; 356 var used = _used;
357 for (var i = ds + 1; i < used; ++i) {
358 r_digits[i - ds - 1] |= (digits[i] & bm) << cbs;
359 r_digits[i - ds] = digits[i] >> bs;
344 } 360 }
345 r._neg = _neg; 361 r._neg = _neg;
346 r._used = r_used; 362 r._used = r_used;
347 r._clamp(); 363 r._clamp();
348 if (_neg) { 364 if (_neg) {
349 // Round down if any bit was shifted out. 365 // Round down if any bit was shifted out.
350 if ((_digits[ds] & bm) != 0) { 366 if ((digits[ds] & bm) != 0) {
351 r._subTo(ONE, r); 367 r._subTo(ONE, r);
352 return; 368 return;
353 } 369 }
354 for (var i = 0; i < ds; i++) { 370 for (var i = 0; i < ds; i++) {
355 if (_digits[i] != 0) { 371 if (digits[i] != 0) {
356 r._subTo(ONE, r); 372 r._subTo(ONE, r);
357 return; 373 return;
358 } 374 }
359 } 375 }
360 } 376 }
361 } 377 }
362 378
363 // Return 0 if abs(this) == abs(a). 379 // Return 0 if abs(this) == abs(a).
364 // Return a positive number if abs(this) > abs(a). 380 // Return a positive number if abs(this) > abs(a).
365 // Return a negative number if abs(this) < abs(a). 381 // Return a negative number if abs(this) < abs(a).
366 int _absCompareTo(_Bigint a) { 382 int _absCompareTo(_Bigint a) {
367 var r = _used - a._used; 383 var r = _used - a._used;
368 if (r == 0) { 384 if (r == 0) {
369 var i = _used; 385 var i = _used;
370 while (--i >= 0 && (r = _digits[i] - a._digits[i]) == 0); 386 var digits = _digits;
387 var a_digits = a._digits;
388 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0);
371 } 389 }
372 return r; 390 return r;
373 } 391 }
374 392
375 // Return 0 if this == a. 393 // Return 0 if this == a.
376 // Return a positive number if this > a. 394 // Return a positive number if this > a.
377 // Return a negative number if this < a. 395 // Return a negative number if this < a.
378 int _compareTo(_Bigint a) { 396 int _compareTo(_Bigint a) {
379 var r; 397 var r;
380 if (_neg == a._neg) { 398 if (_neg == a._neg) {
381 r = _absCompareTo(a); 399 r = _absCompareTo(a);
382 if (_neg) { 400 if (_neg) {
383 r = -r; 401 r = -r;
384 } 402 }
385 } else if (_neg) { 403 } else if (_neg) {
386 r = -1; 404 r = -1;
387 } else { 405 } else {
388 r = 1; 406 r = 1;
389 } 407 }
390 return r; 408 return r;
391 } 409 }
392 410
393 // r = abs(this) + abs(a). 411 // r = abs(this) + abs(a).
394 void _absAddTo(_Bigint a, _Bigint r) { 412 void _absAddTo(_Bigint a, _Bigint r) {
395 if (_used < a._used) { 413 var used = _used;
414 var a_used = a._used;
415 if (used < a_used) {
396 a._absAddTo(this, r); 416 a._absAddTo(this, r);
397 return; 417 return;
398 } 418 }
399 if (_used == 0) { 419 if (used == 0) {
400 // Set r to 0. 420 // Set r to 0.
401 r._neg = false; 421 r._neg = false;
402 r._used = 0; 422 r._used = 0;
403 return; 423 return;
404 } 424 }
405 if (a._used == 0) { 425 if (a_used == 0) {
406 _copyTo(r); 426 _copyTo(r);
407 return; 427 return;
408 } 428 }
409 r._ensureLength(_used + 1); 429 r._ensureLength(used + 1);
430 var digits = _digits;
431 var a_digits = a._digits;
432 var r_digits = r._digits;
410 var c = 0; 433 var c = 0;
411 for (var i = 0; i < a._used; i++) { 434 for (var i = 0; i < a_used; i++) {
412 c += _digits[i] + a._digits[i]; 435 c += digits[i] + a_digits[i];
413 r._digits[i] = c & DIGIT_MASK; 436 r_digits[i] = c & DIGIT_MASK;
414 c >>= DIGIT_BITS; 437 c >>= DIGIT_BITS;
415 } 438 }
416 for (var i = a._used; i < _used; i++) { 439 for (var i = a_used; i < used; i++) {
417 c += _digits[i]; 440 c += digits[i];
418 r._digits[i] = c & DIGIT_MASK; 441 r_digits[i] = c & DIGIT_MASK;
419 c >>= DIGIT_BITS; 442 c >>= DIGIT_BITS;
420 } 443 }
421 r._digits[_used] = c; 444 r_digits[used] = c;
422 r._used = _used + 1; 445 r._used = used + 1;
423 r._clamp(); 446 r._clamp();
424 } 447 }
425 448
426 // r = abs(this) - abs(a), with abs(this) >= abs(a). 449 // r = abs(this) - abs(a), with abs(this) >= abs(a).
427 void _absSubTo(_Bigint a, _Bigint r) { 450 void _absSubTo(_Bigint a, _Bigint r) {
428 assert(_absCompareTo(a) >= 0); 451 assert(_absCompareTo(a) >= 0);
429 if (_used == 0) { 452 var used = _used;
453 if (used == 0) {
430 // Set r to 0. 454 // Set r to 0.
431 r._neg = false; 455 r._neg = false;
432 r._used = 0; 456 r._used = 0;
433 return; 457 return;
434 } 458 }
435 if (a._used == 0) { 459 var a_used = a._used;
460 if (a_used == 0) {
436 _copyTo(r); 461 _copyTo(r);
437 return; 462 return;
438 } 463 }
439 r._ensureLength(_used); 464 r._ensureLength(used);
465 var digits = _digits;
466 var a_digits = a._digits;
467 var r_digits = r._digits;
440 var c = 0; 468 var c = 0;
441 for (var i = 0; i < a._used; i++) { 469 for (var i = 0; i < a_used; i++) {
442 c += _digits[i] - a._digits[i]; 470 c += digits[i] - a_digits[i];
443 r._digits[i] = c & DIGIT_MASK; 471 r_digits[i] = c & DIGIT_MASK;
444 c >>= DIGIT_BITS; 472 c >>= DIGIT_BITS;
445 } 473 }
446 for (var i = a._used; i < _used; i++) { 474 for (var i = a_used; i < used; i++) {
447 c += _digits[i]; 475 c += digits[i];
448 r._digits[i] = c & DIGIT_MASK; 476 r_digits[i] = c & DIGIT_MASK;
449 c >>= DIGIT_BITS; 477 c >>= DIGIT_BITS;
450 } 478 }
451 r._used = _used; 479 r._used = used;
452 r._clamp(); 480 r._clamp();
453 } 481 }
454 482
455 // r = abs(this) & abs(a). 483 // r = abs(this) & abs(a).
456 void _absAndTo(_Bigint a, _Bigint r) { 484 void _absAndTo(_Bigint a, _Bigint r) {
457 var r_used = (_used < a._used) ? _used : a._used; 485 var r_used = (_used < a._used) ? _used : a._used;
458 r._ensureLength(r_used); 486 r._ensureLength(r_used);
487 var digits = _digits;
488 var a_digits = a._digits;
489 var r_digits = r._digits;
459 for (var i = 0; i < r_used; i++) { 490 for (var i = 0; i < r_used; i++) {
460 r._digits[i] = _digits[i] & a._digits[i]; 491 r_digits[i] = digits[i] & a_digits[i];
461 } 492 }
462 r._used = r_used; 493 r._used = r_used;
463 r._clamp(); 494 r._clamp();
464 } 495 }
465 496
466 // r = abs(this) &~ abs(a). 497 // r = abs(this) &~ abs(a).
467 void _absAndNotTo(_Bigint a, _Bigint r) { 498 void _absAndNotTo(_Bigint a, _Bigint r) {
468 var r_used = _used; 499 var r_used = _used;
469 r._ensureLength(r_used); 500 r._ensureLength(r_used);
501 var digits = _digits;
502 var a_digits = a._digits;
503 var r_digits = r._digits;
470 var m = (r_used < a._used) ? r_used : a._used; 504 var m = (r_used < a._used) ? r_used : a._used;
471 for (var i = 0; i < m; i++) { 505 for (var i = 0; i < m; i++) {
472 r._digits[i] = _digits[i] &~ a._digits[i]; 506 r_digits[i] = digits[i] &~ a_digits[i];
473 } 507 }
474 for (var i = m; i < r_used; i++) { 508 for (var i = m; i < r_used; i++) {
475 r._digits[i] = _digits[i]; 509 r_digits[i] = digits[i];
476 } 510 }
477 r._used = r_used; 511 r._used = r_used;
478 r._clamp(); 512 r._clamp();
479 } 513 }
480 514
481 // r = abs(this) | abs(a). 515 // r = abs(this) | abs(a).
482 void _absOrTo(_Bigint a, _Bigint r) { 516 void _absOrTo(_Bigint a, _Bigint r) {
483 var r_used = (_used > a._used) ? _used : a._used; 517 var used = _used;
518 var a_used = a._used;
519 var r_used = (used > a_used) ? used : a_used;
484 r._ensureLength(r_used); 520 r._ensureLength(r_used);
521 var digits = _digits;
522 var a_digits = a._digits;
523 var r_digits = r._digits;
485 var l, m; 524 var l, m;
486 if (_used < a._used) { 525 if (used < a_used) {
487 l = a; 526 l = a;
488 m = _used; 527 m = used;
489 } else { 528 } else {
490 l = this; 529 l = this;
491 m = a._used; 530 m = a_used;
492 } 531 }
493 for (var i = 0; i < m; i++) { 532 for (var i = 0; i < m; i++) {
494 r._digits[i] = _digits[i] | a._digits[i]; 533 r_digits[i] = digits[i] | a_digits[i];
495 } 534 }
535 var l_digits = l._digits;
496 for (var i = m; i < r_used; i++) { 536 for (var i = m; i < r_used; i++) {
497 r._digits[i] = l._digits[i]; 537 r_digits[i] = l_digits[i];
498 } 538 }
499 r._used = r_used; 539 r._used = r_used;
500 r._clamp(); 540 r._clamp();
501 } 541 }
502 542
503 // r = abs(this) ^ abs(a). 543 // r = abs(this) ^ abs(a).
504 void _absXorTo(_Bigint a, _Bigint r) { 544 void _absXorTo(_Bigint a, _Bigint r) {
505 var r_used = (_used > a._used) ? _used : a._used; 545 var used = _used;
546 var a_used = a._used;
547 var r_used = (used > a_used) ? used : a_used;
506 r._ensureLength(r_used); 548 r._ensureLength(r_used);
549 var digits = _digits;
550 var a_digits = a._digits;
551 var r_digits = r._digits;
507 var l, m; 552 var l, m;
508 if (_used < a._used) { 553 if (used < a_used) {
509 l = a; 554 l = a;
510 m = _used; 555 m = used;
511 } else { 556 } else {
512 l = this; 557 l = this;
513 m = a._used; 558 m = a_used;
514 } 559 }
515 for (var i = 0; i < m; i++) { 560 for (var i = 0; i < m; i++) {
516 r._digits[i] = _digits[i] ^ a._digits[i]; 561 r_digits[i] = digits[i] ^ a_digits[i];
517 } 562 }
563 var l_digits = l._digits;
518 for (var i = m; i < r_used; i++) { 564 for (var i = m; i < r_used; i++) {
519 r._digits[i] = l._digits[i]; 565 r_digits[i] = l_digits[i];
520 } 566 }
521 r._used = r_used; 567 r._used = r_used;
522 r._clamp(); 568 r._clamp();
523 } 569 }
524 570
525 // Return r = this & a. 571 // Return r = this & a.
526 _Bigint _andTo(_Bigint a, _Bigint r) { 572 _Bigint _andTo(_Bigint a, _Bigint r) {
527 if (_neg == a._neg) { 573 if (_neg == a._neg) {
528 if (_neg) { 574 if (_neg) {
529 // (-this) & (-a) == ~(this-1) & ~(a-1) 575 // (-this) & (-a) == ~(this-1) & ~(a-1)
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 // w[j..j+n-1] += this[i..i+n-1] * x. 781 // w[j..j+n-1] += this[i..i+n-1] * x.
736 // Returns carry out. 782 // Returns carry out.
737 int _am(int i, int x, _Bigint w, int j, int n) { 783 int _am(int i, int x, _Bigint w, int j, int n) {
738 if (x == 0) { 784 if (x == 0) {
739 // No-op if x is 0. 785 // No-op if x is 0.
740 return 0; 786 return 0;
741 } 787 }
742 int c = 0; 788 int c = 0;
743 int xl = x & DIGIT2_MASK; 789 int xl = x & DIGIT2_MASK;
744 int xh = x >> DIGIT2_BITS; 790 int xh = x >> DIGIT2_BITS;
791 var digits = _digits;
792 var w_digits = w._digits;
745 while (--n >= 0) { 793 while (--n >= 0) {
746 int l = _digits[i] & DIGIT2_MASK; 794 int l = digits[i] & DIGIT2_MASK;
747 int h = _digits[i++] >> DIGIT2_BITS; 795 int h = digits[i++] >> DIGIT2_BITS;
748 int m = xh*l + h*xl; 796 int m = xh*l + h*xl;
749 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + w._digits[j] + c; 797 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + w_digits[j] + c;
750 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; 798 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h;
751 w._digits[j++] = l & DIGIT_MASK; 799 w_digits[j++] = l & DIGIT_MASK;
752 } 800 }
753 return c; 801 return c;
754 } 802 }
755 803
756 // Accumulate multiply with carry. 804 // Accumulate multiply with carry.
757 // this[i..i+n-1]: bigint multiplicand. 805 // this[i..i+n-1]: bigint multiplicand.
758 // x: digit multiplier, 0 <= x < 2*DIGIT_BASE (i.e. 33-bit multiplier). 806 // x: digit multiplier, 0 <= x < 2*DIGIT_BASE (i.e. 33-bit multiplier).
759 // w[j..j+n-1]: bigint accumulator. 807 // w[j..j+n-1]: bigint accumulator.
760 // c: int carry in. 808 // c: int carry in.
761 // Returns carry out. 809 // Returns carry out.
762 // w[j..j+n-1] += this[i..i+n-1] * x + c. 810 // w[j..j+n-1] += this[i..i+n-1] * x + c.
763 // Returns carry out. 811 // Returns carry out.
764 int _amc(int i, int x, _Bigint w, int j, int c, int n) { 812 int _amc(int i, int x, _Bigint w, int j, int c, int n) {
765 if (x == 0 && c == 0) { 813 if (x == 0 && c == 0) {
766 // No-op if both x and c are 0. 814 // No-op if both x and c are 0.
767 return 0; 815 return 0;
768 } 816 }
769 int xl = x & DIGIT2_MASK; 817 int xl = x & DIGIT2_MASK;
770 int xh = x >> DIGIT2_BITS; 818 int xh = x >> DIGIT2_BITS;
819 var digits = _digits;
820 var w_digits = w._digits;
771 while (--n >= 0) { 821 while (--n >= 0) {
772 int l = _digits[i] & DIGIT2_MASK; 822 int l = digits[i] & DIGIT2_MASK;
773 int h = _digits[i++] >> DIGIT2_BITS; 823 int h = digits[i++] >> DIGIT2_BITS;
774 int m = xh*l + h*xl; 824 int m = xh*l + h*xl;
775 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + w._digits[j] + c; 825 l = xl*l + ((m & DIGIT2_MASK) << DIGIT2_BITS) + w_digits[j] + c;
776 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h; 826 c = (l >> DIGIT_BITS) + (m >> DIGIT2_BITS) + xh*h;
777 w._digits[j++] = l & DIGIT_MASK; 827 w_digits[j++] = l & DIGIT_MASK;
778 } 828 }
779 return c; 829 return c;
780 } 830 }
781 831
782 // r = this * a. 832 // r = this * a.
783 void _mulTo(_Bigint a, _Bigint r) { 833 void _mulTo(_Bigint a, _Bigint r) {
784 // TODO(regis): Use karatsuba multiplication when appropriate. 834 // TODO(regis): Use karatsuba multiplication when appropriate.
785 var i = _used; 835 var used = _used;
786 r._ensureLength(i + a._used); 836 var a_used = a._used;
787 r._used = i + a._used; 837 var i = used;
838 r._ensureLength(i + a_used);
839 var a_digits = a._digits;
840 var r_digits = r._digits;
841 r._used = i + a_used;
788 while (--i >= 0) { 842 while (--i >= 0) {
789 r._digits[i] = 0; 843 r_digits[i] = 0;
790 } 844 }
791 for (i = 0; i < a._used; ++i) { 845 for (i = 0; i < a_used; ++i) {
792 r._digits[i + _used] = _am(0, a._digits[i], r, i, _used); 846 r_digits[i + used] = _am(0, a_digits[i], r, i, used);
793 } 847 }
794 r._clamp(); 848 r._clamp();
795 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative. 849 r._neg = r._used > 0 && _neg != a._neg; // Zero cannot be negative.
796 } 850 }
797 851
798 // r = this^2, r != this. 852 // r = this^2, r != this.
799 void _sqrTo(_Bigint r) { 853 void _sqrTo(_Bigint r) {
800 var i = 2 * _used; 854 var used = _used;
801 r._ensureLength(i); 855 var r_used = 2 * used;
802 r._used = i; 856 r._ensureLength(r_used);
857 var digits = _digits;
858 var r_digits = r._digits;
859 var i = r_used;
803 while (--i >= 0) { 860 while (--i >= 0) {
804 r._digits[i] = 0; 861 r_digits[i] = 0;
805 } 862 }
806 for (i = 0; i < _used - 1; ++i) { 863 for (i = 0; i < used - 1; ++i) {
807 var c = _am(i, _digits[i], r, 2*i, 1); 864 var c = _am(i, digits[i], r, 2*i, 1);
808 var d = r._digits[i + _used]; 865 var d = r_digits[i + used];
809 d += _amc(i + 1, _digits[i] << 1, r, 2*i + 1, c, _used - i - 1); 866 d += _amc(i + 1, digits[i] << 1, r, 2*i + 1, c, used - i - 1);
810 if (d >= DIGIT_BASE) { 867 if (d >= DIGIT_BASE) {
811 r._digits[i + _used] = d - DIGIT_BASE; 868 r_digits[i + used] = d - DIGIT_BASE;
812 r._digits[i + _used + 1] = 1; 869 r_digits[i + used + 1] = 1;
813 } else { 870 } else {
814 r._digits[i + _used] = d; 871 r_digits[i + used] = d;
815 } 872 }
816 } 873 }
817 if (r._used > 0) { 874 if (r_used > 0) {
818 r._digits[r._used - 1] += _am(i, _digits[i], r, 2*i, 1); 875 r_digits[r_used - 1] += _am(i, digits[i], r, 2*i, 1);
819 } 876 }
877 r._used = r_used;
820 r._neg = false; 878 r._neg = false;
821 r._clamp(); 879 r._clamp();
822 } 880 }
823 881
824 // Truncating division and remainder. 882 // Truncating division and remainder.
825 // If q != null, q = trunc(this / a). 883 // If q != null, q = trunc(this / a).
826 // If r != null, r = this - a * trunc(this / a). 884 // If r != null, r = this - a * trunc(this / a).
827 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) { 885 void _divRemTo(_Bigint a, _Bigint q, _Bigint r) {
828 if (a._used == 0) return; 886 if (a._used == 0) return;
829 if (_used < a._used) { 887 if (_used < a._used) {
(...skipping 17 matching lines...) Expand all
847 _lShiftTo(nsh, r); 905 _lShiftTo(nsh, r);
848 } 906 }
849 else { 907 else {
850 a._copyTo(y); 908 a._copyTo(y);
851 _copyTo(r); 909 _copyTo(r);
852 } 910 }
853 // We consider this and a positive. Ignore the copied sign. 911 // We consider this and a positive. Ignore the copied sign.
854 y._neg = false; 912 y._neg = false;
855 r._neg = false; 913 r._neg = false;
856 var y_used = y._used; 914 var y_used = y._used;
857 var y0 = y._digits[y_used - 1]; 915 var y_digits = y._digits;
916 var y0 = y_digits[y_used - 1];
858 if (y0 == 0) return; 917 if (y0 == 0) return;
859 var yt = y0 >> 1; // Chop off one bit, see below. y is normalized: yt != 0. 918 var yt = y0 >> 1; // Chop off one bit, see below. y is normalized: yt != 0.
860 var i = r._used; 919 var i = r._used;
861 var j = i - y_used; 920 var j = i - y_used;
862 _Bigint t = (q == null) ? new _Bigint() : q; 921 _Bigint t = (q == null) ? new _Bigint() : q;
863
864 y._dlShiftTo(j, t); 922 y._dlShiftTo(j, t);
865 923 var r_digits = r._digits;
866 if (r._compareTo(t) >= 0) { 924 if (r._compareTo(t) >= 0) {
867 r._digits[r._used++] = 1; 925 r_digits[r._used++] = 1;
868 r._subTo(t, r); 926 r._subTo(t, r);
869 } 927 }
870 ONE._dlShiftTo(y_used, t); 928 ONE._dlShiftTo(y_used, t);
871 t._subTo(y, y); // Negate y so we can replace sub with _am later. 929 t._subTo(y, y); // Negate y so we can replace sub with _am later.
872 while (y._used < y_used) { 930 while (y._used < y_used) {
873 y._digits[y._used++] = 0; 931 y_digits[y._used++] = 0;
874 } 932 }
875 while (--j >= 0) { 933 while (--j >= 0) {
876 // Estimate quotient digit. 934 // Estimate quotient digit.
935 // TODO(regis): Move the expensive mint division below to a function that
936 // can be intrinsified using an uint64_t by uint32_t division instruction,
937 // e.g. qd = _estqd(r_digits, --i, y0).
877 var qd; 938 var qd;
878 if (r._digits[--i] == y0) { 939 if (r_digits[--i] == y0) {
879 qd = DIGIT_MASK; 940 qd = DIGIT_MASK;
880 } else { 941 } else {
881 // Chop off one bit, since a Mint cannot hold 2 DIGITs. 942 // Chop off one bit, since a Mint cannot hold 2 DIGITs.
882 qd = ((r._digits[i] << (DIGIT_BITS - 1)) | 943 qd = ((r_digits[i] << (DIGIT_BITS - 1)) | (r_digits[i - 1] >> 1)) ~/ yt;
883 (r._digits[i - 1] >> 1)) ~/ yt;
884 } 944 }
885 if ((r._digits[i] += y._am(0, qd, r, j, y_used)) < qd) { // Try it out. 945 if ((r_digits[i] += y._am(0, qd, r, j, y_used)) < qd) { // Try it out.
886 y._dlShiftTo(j, t); 946 y._dlShiftTo(j, t);
887 r._subTo(t, r); 947 r._subTo(t, r);
888 while (r._digits[i] < --qd) { 948 while (r_digits[i] < --qd) {
889 r._subTo(t, r); 949 r._subTo(t, r);
890 } 950 }
891 } 951 }
892 } 952 }
893 if (q != null) { 953 if (q != null) {
894 r._drShiftTo(y_used, q); 954 r._drShiftTo(y_used, q);
895 if (_neg != a._neg) { 955 if (_neg != a._neg) {
896 ZERO._subTo(q, q); 956 ZERO._subTo(q, q);
897 } 957 }
898 } 958 }
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
1161 z._mulTo(g2, g[n - 2], g[n]); 1221 z._mulTo(g2, g[n - 2], g[n]);
1162 n += 2; 1222 n += 2;
1163 } 1223 }
1164 } 1224 }
1165 var j = e._used - 1; 1225 var j = e._used - 1;
1166 var w; 1226 var w;
1167 var is1 = true; 1227 var is1 = true;
1168 var r = new _Bigint()._setInt(1); 1228 var r = new _Bigint()._setInt(1);
1169 var r2 = new _Bigint(); 1229 var r2 = new _Bigint();
1170 var t; 1230 var t;
1171 i = _nbits(e._digits[j]) - 1; 1231 var e_digits = e._digits;
1232 i = _nbits(e_digits[j]) - 1;
1172 while (j >= 0) { 1233 while (j >= 0) {
1173 if (i >= k1) { 1234 if (i >= k1) {
1174 w = (e._digits[j] >> (i - k1)) & km; 1235 w = (e_digits[j] >> (i - k1)) & km;
1175 } else { 1236 } else {
1176 w = (e._digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i); 1237 w = (e_digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
1177 if (j > 0) { 1238 if (j > 0) {
1178 w |= e._digits[j - 1] >> (DIGIT_BITS + i - k1); 1239 w |= e_digits[j - 1] >> (DIGIT_BITS + i - k1);
1179 } 1240 }
1180 } 1241 }
1181 n = k; 1242 n = k;
1182 while ((w & 1) == 0) { 1243 while ((w & 1) == 0) {
1183 w >>= 1; 1244 w >>= 1;
1184 --n; 1245 --n;
1185 } 1246 }
1186 if ((i -= n) < 0) { 1247 if ((i -= n) < 0) {
1187 i += DIGIT_BITS; 1248 i += DIGIT_BITS;
1188 --j; 1249 --j;
(...skipping 11 matching lines...) Expand all
1200 if (n > 0) { 1261 if (n > 0) {
1201 z._sqrTo(r, r2); 1262 z._sqrTo(r, r2);
1202 } else { 1263 } else {
1203 t = r; 1264 t = r;
1204 r = r2; 1265 r = r2;
1205 r2 = t; 1266 r2 = t;
1206 } 1267 }
1207 z._mulTo(r2,g[w], r); 1268 z._mulTo(r2,g[w], r);
1208 } 1269 }
1209 1270
1210 while (j >= 0 && (e._digits[j] & (1 << i)) == 0) { 1271 while (j >= 0 && (e_digits[j] & (1 << i)) == 0) {
1211 z._sqrTo(r, r2); 1272 z._sqrTo(r, r2);
1212 t = r; 1273 t = r;
1213 r = r2; 1274 r = r2;
1214 r2 = t; 1275 r2 = t;
1215 if (--i < 0) { 1276 if (--i < 0) {
1216 i = DIGIT_BITS - 1; 1277 i = DIGIT_BITS - 1;
1217 --j; 1278 --j;
1218 } 1279 }
1219 } 1280 }
1220 } 1281 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 _Bigint _revert(_Bigint x) { 1324 _Bigint _revert(_Bigint x) {
1264 var r = new _Bigint(); 1325 var r = new _Bigint();
1265 x._copyTo(r); 1326 x._copyTo(r);
1266 _reduce(r); 1327 _reduce(r);
1267 return r; 1328 return r;
1268 } 1329 }
1269 1330
1270 // x = x/R mod _m 1331 // x = x/R mod _m
1271 void _reduce(_Bigint x) { 1332 void _reduce(_Bigint x) {
1272 x._ensureLength(_mused2 + 1); 1333 x._ensureLength(_mused2 + 1);
1334 var x_digits = x._digits;
1273 while (x._used <= _mused2) { // Pad x so _am has enough room later. 1335 while (x._used <= _mused2) { // Pad x so _am has enough room later.
1274 x._digits[x._used++] = 0; 1336 x_digits[x._used++] = 0;
1275 } 1337 }
1276 for (var i = 0; i < _m._used; ++i) { 1338 var m_used = _m._used;
1339 for (var i = 0; i < m_used; ++i) {
1277 // Faster way of calculating u0 = x[i]*mp mod DIGIT_BASE. 1340 // Faster way of calculating u0 = x[i]*mp mod DIGIT_BASE.
1278 var j = x._digits[i] & _Bigint.DIGIT2_MASK; 1341 var j = x_digits[i] & _Bigint.DIGIT2_MASK;
1279 var u0 = (j*_mpl + (((j*_mph + (x._digits[i] >> _Bigint.DIGIT2_BITS) 1342 var u0 = (j*_mpl + (((j*_mph + (x_digits[i] >> _Bigint.DIGIT2_BITS)
1280 *_mpl) & _um) << _Bigint.DIGIT2_BITS)) & _Bigint.DIGIT_MASK; 1343 *_mpl) & _um) << _Bigint.DIGIT2_BITS)) & _Bigint.DIGIT_MASK;
1281 // Use _am to combine the multiply-shift-add into one call. 1344 // Use _am to combine the multiply-shift-add into one call.
1282 j = i + _m._used; 1345 j = i + m_used;
1283 var digit = x._digits[j]; 1346 var digit = x_digits[j];
1284 digit += _m ._am(0, u0, x, i, _m._used); 1347 digit += _m ._am(0, u0, x, i, m_used);
1285 // Propagate carry. 1348 // Propagate carry.
1286 while (digit >= _Bigint.DIGIT_BASE) { 1349 while (digit >= _Bigint.DIGIT_BASE) {
1287 digit -= _Bigint.DIGIT_BASE; 1350 digit -= _Bigint.DIGIT_BASE;
1288 x._digits[j++] = digit; 1351 x_digits[j++] = digit;
1289 digit = x._digits[j]; 1352 digit = x_digits[j];
1290 digit++; 1353 digit++;
1291 } 1354 }
1292 x._digits[j] = digit; 1355 x_digits[j] = digit;
1293 } 1356 }
1294 x._clamp(); 1357 x._clamp();
1295 x._drShiftTo(_m ._used, x); 1358 x._drShiftTo(m_used, x);
1296 if (x._compareTo(_m ) >= 0) { 1359 if (x._compareTo(_m) >= 0) {
1297 x._subTo(_m , x); 1360 x._subTo(_m, x);
1298 } 1361 }
1299 } 1362 }
1300 1363
1301 // r = x^2/R mod _m ; x != r 1364 // r = x^2/R mod _m ; x != r
1302 void _sqrTo(_Bigint x, _Bigint r) { 1365 void _sqrTo(_Bigint x, _Bigint r) {
1303 x._sqrTo(r); 1366 x._sqrTo(r);
1304 _reduce(r); 1367 _reduce(r);
1305 } 1368 }
1306 1369
1307 // r = x*y/R mod _m ; x, y != r 1370 // r = x*y/R mod _m ; x, y != r
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1342 void _sqrTo(_Bigint x, _Bigint r) { 1405 void _sqrTo(_Bigint x, _Bigint r) {
1343 x._sqrTo(r); 1406 x._sqrTo(r);
1344 _reduce(r); 1407 _reduce(r);
1345 } 1408 }
1346 1409
1347 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { 1410 void _mulTo(_Bigint x, _Bigint y, _Bigint r) {
1348 x._mulTo(y, r); 1411 x._mulTo(y, r);
1349 _reduce(r); 1412 _reduce(r);
1350 } 1413 }
1351 } 1414 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698