| OLD | NEW |
| 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 import 'dart:typed_data' show Uint32List; | 5 import 'dart:typed_data' show Uint32List; |
| 6 | 6 |
| 7 // Copyright 2009 The Go Authors. All rights reserved. | 7 // Copyright 2009 The Go Authors. All rights reserved. |
| 8 // Use of this source code is governed by a BSD-style | 8 // Use of this source code is governed by a BSD-style |
| 9 // license that can be found in the LICENSE file. | 9 // license that can be found in the LICENSE file. |
| 10 | 10 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 } | 112 } |
| 113 var digits = new Uint32List(2); | 113 var digits = new Uint32List(2); |
| 114 digits[0] = l; | 114 digits[0] = l; |
| 115 digits[1] = h; | 115 digits[1] = h; |
| 116 return new _Bigint(neg, 2, digits); | 116 return new _Bigint(neg, 2, digits); |
| 117 } | 117 } |
| 118 | 118 |
| 119 // Allocate an array of the given length (+1 for at least one leading zero | 119 // Allocate an array of the given length (+1 for at least one leading zero |
| 120 // digit if odd) and copy digits[from..to-1] starting at index 0, followed by | 120 // digit if odd) and copy digits[from..to-1] starting at index 0, followed by |
| 121 // leading zero digits. | 121 // leading zero digits. |
| 122 static Uint32List _cloneDigits(Uint32List digits, int from, int to, | 122 static Uint32List _cloneDigits( |
| 123 int length) { | 123 Uint32List digits, int from, int to, int length) { |
| 124 length += length & 1; // Even number of digits. | 124 length += length & 1; // Even number of digits. |
| 125 var r_digits = new Uint32List(length); | 125 var r_digits = new Uint32List(length); |
| 126 var n = to - from; | 126 var n = to - from; |
| 127 for (var i = 0; i < n; i++) { | 127 for (var i = 0; i < n; i++) { |
| 128 r_digits[i] = digits[from + i]; | 128 r_digits[i] = digits[from + i]; |
| 129 } | 129 } |
| 130 return r_digits; | 130 return r_digits; |
| 131 } | 131 } |
| 132 | 132 |
| 133 // Return most compact integer (i.e. possibly Smi or Mint). | 133 // Return most compact integer (i.e. possibly Smi or Mint). |
| 134 int _toValidInt() { | 134 int _toValidInt() { |
| 135 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 135 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
| 136 var used = _used; | 136 var used = _used; |
| 137 if (used == 0) return 0; | 137 if (used == 0) return 0; |
| 138 var digits = _digits; | 138 var digits = _digits; |
| 139 if (used == 1) return _neg ? -digits[0] : digits[0]; | 139 if (used == 1) return _neg ? -digits[0] : digits[0]; |
| 140 if (used > 2) return this; | 140 if (used > 2) return this; |
| 141 if (_neg) { | 141 if (_neg) { |
| 142 if (digits[1] > 0x80000000) return this; | 142 if (digits[1] > 0x80000000) return this; |
| 143 if (digits[1] == 0x80000000) { | 143 if (digits[1] == 0x80000000) { |
| 144 if (digits[0] > 0) return this; | 144 if (digits[0] > 0) return this; |
| 145 return _MIN_INT64; | 145 return _MIN_INT64; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 167 var neg = _neg; | 167 var neg = _neg; |
| 168 if (!neg) { | 168 if (!neg) { |
| 169 return this; | 169 return this; |
| 170 } | 170 } |
| 171 return new _Bigint(!neg, _used, _digits); | 171 return new _Bigint(!neg, _used, _digits); |
| 172 } | 172 } |
| 173 | 173 |
| 174 // Return the bit length of digit x. | 174 // Return the bit length of digit x. |
| 175 static int _nbits(int x) { | 175 static int _nbits(int x) { |
| 176 var r = 1, t; | 176 var r = 1, t; |
| 177 if ((t = x >> 16) != 0) { x = t; r += 16; } | 177 if ((t = x >> 16) != 0) { |
| 178 if ((t = x >> 8) != 0) { x = t; r += 8; } | 178 x = t; |
| 179 if ((t = x >> 4) != 0) { x = t; r += 4; } | 179 r += 16; |
| 180 if ((t = x >> 2) != 0) { x = t; r += 2; } | 180 } |
| 181 if ((x >> 1) != 0) { r += 1; } | 181 if ((t = x >> 8) != 0) { |
| 182 x = t; |
| 183 r += 8; |
| 184 } |
| 185 if ((t = x >> 4) != 0) { |
| 186 x = t; |
| 187 r += 4; |
| 188 } |
| 189 if ((t = x >> 2) != 0) { |
| 190 x = t; |
| 191 r += 2; |
| 192 } |
| 193 if ((x >> 1) != 0) { |
| 194 r += 1; |
| 195 } |
| 182 return r; | 196 return r; |
| 183 } | 197 } |
| 184 | 198 |
| 185 // Return this << n*_DIGIT_BITS. | 199 // Return this << n*_DIGIT_BITS. |
| 186 _Bigint _dlShift(int n) { | 200 _Bigint _dlShift(int n) { |
| 187 final used = _used; | 201 final used = _used; |
| 188 if (used == 0) { | 202 if (used == 0) { |
| 189 return _ZERO; | 203 return _ZERO; |
| 190 } | 204 } |
| 191 final r_used = used + n; | 205 final r_used = used + n; |
| 192 final digits = _digits; | 206 final digits = _digits; |
| 193 final r_digits = new Uint32List(r_used + (r_used & 1)); | 207 final r_digits = new Uint32List(r_used + (r_used & 1)); |
| 194 var i = used; | 208 var i = used; |
| 195 while (--i >= 0) { | 209 while (--i >= 0) { |
| 196 r_digits[i + n] = digits[i]; | 210 r_digits[i + n] = digits[i]; |
| 197 } | 211 } |
| 198 return new _Bigint(_neg, r_used, r_digits); | 212 return new _Bigint(_neg, r_used, r_digits); |
| 199 } | 213 } |
| 200 | 214 |
| 201 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*_DIGIT_BITS. | 215 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*_DIGIT_BITS. |
| 202 // Return r_used. | 216 // Return r_used. |
| 203 static int _dlShiftDigits(Uint32List x_digits, int x_used, int n, | 217 static int _dlShiftDigits( |
| 204 Uint32List r_digits) { | 218 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { |
| 205 if (x_used == 0) { | 219 if (x_used == 0) { |
| 206 return 0; | 220 return 0; |
| 207 } | 221 } |
| 208 if (n == 0 && identical(r_digits, x_digits)) { | 222 if (n == 0 && identical(r_digits, x_digits)) { |
| 209 return x_used; | 223 return x_used; |
| 210 } | 224 } |
| 211 final r_used = x_used + n; | 225 final r_used = x_used + n; |
| 212 assert(r_digits.length >= r_used + (r_used & 1)); | 226 assert(r_digits.length >= r_used + (r_used & 1)); |
| 213 var i = x_used; | 227 var i = x_used; |
| 214 while (--i >= 0) { | 228 while (--i >= 0) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 if (digits[i] != 0) { | 260 if (digits[i] != 0) { |
| 247 return r._sub(_ONE); | 261 return r._sub(_ONE); |
| 248 } | 262 } |
| 249 } | 263 } |
| 250 } | 264 } |
| 251 return r; | 265 return r; |
| 252 } | 266 } |
| 253 | 267 |
| 254 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n*_DIGIT_BITS. | 268 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n*_DIGIT_BITS. |
| 255 // Return r_used. | 269 // Return r_used. |
| 256 static int _drShiftDigits(Uint32List x_digits, int x_used, int n, | 270 static int _drShiftDigits( |
| 257 Uint32List r_digits) { | 271 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { |
| 258 final r_used = x_used - n; | 272 final r_used = x_used - n; |
| 259 if (r_used <= 0) { | 273 if (r_used <= 0) { |
| 260 return 0; | 274 return 0; |
| 261 } | 275 } |
| 262 assert(r_digits.length >= r_used + (r_used & 1)); | 276 assert(r_digits.length >= r_used + (r_used & 1)); |
| 263 for (var i = n; i < x_used; i++) { | 277 for (var i = n; i < x_used; i++) { |
| 264 r_digits[i - n] = x_digits[i]; | 278 r_digits[i - n] = x_digits[i]; |
| 265 } | 279 } |
| 266 if (r_used.isOdd) { | 280 if (r_used.isOdd) { |
| 267 r_digits[r_used] = 0; | 281 r_digits[r_used] = 0; |
| 268 } | 282 } |
| 269 return r_used; | 283 return r_used; |
| 270 } | 284 } |
| 271 | 285 |
| 272 // r_digits[ds..x_used+ds] = x_digits[0..x_used-1] << (n % _DIGIT_BITS) | 286 // r_digits[ds..x_used+ds] = x_digits[0..x_used-1] << (n % _DIGIT_BITS) |
| 273 // where ds = ceil(n / _DIGIT_BITS) | 287 // where ds = ceil(n / _DIGIT_BITS) |
| 274 // Doesn't clear digits below ds. | 288 // Doesn't clear digits below ds. |
| 275 static void _lsh(Uint32List x_digits, int x_used, int n, | 289 static void _lsh( |
| 276 Uint32List r_digits) { | 290 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { |
| 277 final ds = n ~/ _DIGIT_BITS; | 291 final ds = n ~/ _DIGIT_BITS; |
| 278 final bs = n % _DIGIT_BITS; | 292 final bs = n % _DIGIT_BITS; |
| 279 final cbs = _DIGIT_BITS - bs; | 293 final cbs = _DIGIT_BITS - bs; |
| 280 final bm = (1 << cbs) - 1; | 294 final bm = (1 << cbs) - 1; |
| 281 var c = 0; | 295 var c = 0; |
| 282 var i = x_used; | 296 var i = x_used; |
| 283 while (--i >= 0) { | 297 while (--i >= 0) { |
| 284 final d = x_digits[i]; | 298 final d = x_digits[i]; |
| 285 r_digits[i + ds + 1] = (d >> cbs) | c; | 299 r_digits[i + ds + 1] = (d >> cbs) | c; |
| 286 c = (d & bm) << bs; | 300 c = (d & bm) << bs; |
| 287 } | 301 } |
| 288 r_digits[ds] = c; | 302 r_digits[ds] = c; |
| 289 } | 303 } |
| 290 | 304 |
| 291 // Return this << n. | 305 // Return this << n. |
| 292 _Bigint _lShift(int n) { | 306 _Bigint _lShift(int n) { |
| 293 final ds = n ~/ _DIGIT_BITS; | 307 final ds = n ~/ _DIGIT_BITS; |
| 294 final bs = n % _DIGIT_BITS; | 308 final bs = n % _DIGIT_BITS; |
| 295 if (bs == 0) { | 309 if (bs == 0) { |
| 296 return _dlShift(ds); | 310 return _dlShift(ds); |
| 297 } | 311 } |
| 298 var r_used = _used + ds + 1; | 312 var r_used = _used + ds + 1; |
| 299 var r_digits = new Uint32List(r_used + 2 - (r_used & 1)); // for 64-bit. | 313 var r_digits = new Uint32List(r_used + 2 - (r_used & 1)); // for 64-bit. |
| 300 _lsh(_digits, _used, n, r_digits); | 314 _lsh(_digits, _used, n, r_digits); |
| 301 return new _Bigint(_neg, r_used, r_digits); | 315 return new _Bigint(_neg, r_used, r_digits); |
| 302 } | 316 } |
| 303 | 317 |
| 304 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n. | 318 // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n. |
| 305 // Return r_used. | 319 // Return r_used. |
| 306 static int _lShiftDigits(Uint32List x_digits, int x_used, int n, | 320 static int _lShiftDigits( |
| 307 Uint32List r_digits) { | 321 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { |
| 308 final ds = n ~/ _DIGIT_BITS; | 322 final ds = n ~/ _DIGIT_BITS; |
| 309 final bs = n % _DIGIT_BITS; | 323 final bs = n % _DIGIT_BITS; |
| 310 if (bs == 0) { | 324 if (bs == 0) { |
| 311 return _dlShiftDigits(x_digits, x_used, ds, r_digits); | 325 return _dlShiftDigits(x_digits, x_used, ds, r_digits); |
| 312 } | 326 } |
| 313 var r_used = x_used + ds + 1; | 327 var r_used = x_used + ds + 1; |
| 314 assert(r_digits.length >= r_used + 2 - (r_used & 1)); // for 64-bit. | 328 assert(r_digits.length >= r_used + 2 - (r_used & 1)); // for 64-bit. |
| 315 _lsh(x_digits, x_used, n, r_digits); | 329 _lsh(x_digits, x_used, n, r_digits); |
| 316 var i = ds; | 330 var i = ds; |
| 317 while (--i >= 0) { | 331 while (--i >= 0) { |
| 318 r_digits[i] = 0; | 332 r_digits[i] = 0; |
| 319 } | 333 } |
| 320 if (r_digits[r_used - 1] == 0) { | 334 if (r_digits[r_used - 1] == 0) { |
| 321 r_used--; // Clamp result. | 335 r_used--; // Clamp result. |
| 322 } else if (r_used.isOdd) { | 336 } else if (r_used.isOdd) { |
| 323 r_digits[r_used] = 0; | 337 r_digits[r_used] = 0; |
| 324 } | 338 } |
| 325 return r_used; | 339 return r_used; |
| 326 } | 340 } |
| 327 | 341 |
| 328 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. | 342 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. |
| 329 static void _rsh(Uint32List x_digits, int x_used, int n, | 343 static void _rsh( |
| 330 Uint32List r_digits) { | 344 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { |
| 331 final ds = n ~/ _DIGIT_BITS; | 345 final ds = n ~/ _DIGIT_BITS; |
| 332 final bs = n % _DIGIT_BITS; | 346 final bs = n % _DIGIT_BITS; |
| 333 final cbs = _DIGIT_BITS - bs; | 347 final cbs = _DIGIT_BITS - bs; |
| 334 final bm = (1 << bs) - 1; | 348 final bm = (1 << bs) - 1; |
| 335 var c = x_digits[ds] >> bs; | 349 var c = x_digits[ds] >> bs; |
| 336 final last = x_used - ds - 1; | 350 final last = x_used - ds - 1; |
| 337 for (var i = 0; i < last; i++) { | 351 for (var i = 0; i < last; i++) { |
| 338 final d = x_digits[i + ds + 1]; | 352 final d = x_digits[i + ds + 1]; |
| 339 r_digits[i] = ((d & bm) << cbs) | c; | 353 r_digits[i] = ((d & bm) << cbs) | c; |
| 340 c = d >> bs; | 354 c = d >> bs; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 367 if (digits[i] != 0) { | 381 if (digits[i] != 0) { |
| 368 return r._sub(_ONE); | 382 return r._sub(_ONE); |
| 369 } | 383 } |
| 370 } | 384 } |
| 371 } | 385 } |
| 372 return r; | 386 return r; |
| 373 } | 387 } |
| 374 | 388 |
| 375 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. | 389 // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n. |
| 376 // Return r_used. | 390 // Return r_used. |
| 377 static int _rShiftDigits(Uint32List x_digits, int x_used, int n, | 391 static int _rShiftDigits( |
| 378 Uint32List r_digits) { | 392 Uint32List x_digits, int x_used, int n, Uint32List r_digits) { |
| 379 final ds = n ~/ _DIGIT_BITS; | 393 final ds = n ~/ _DIGIT_BITS; |
| 380 final bs = n % _DIGIT_BITS; | 394 final bs = n % _DIGIT_BITS; |
| 381 if (bs == 0) { | 395 if (bs == 0) { |
| 382 return _drShiftDigits(x_digits, x_used, ds, r_digits); | 396 return _drShiftDigits(x_digits, x_used, ds, r_digits); |
| 383 } | 397 } |
| 384 var r_used = x_used - ds; | 398 var r_used = x_used - ds; |
| 385 if (r_used <= 0) { | 399 if (r_used <= 0) { |
| 386 return 0; | 400 return 0; |
| 387 } | 401 } |
| 388 assert(r_digits.length >= r_used + (r_used & 1)); | 402 assert(r_digits.length >= r_used + (r_used & 1)); |
| 389 _rsh(x_digits, x_used, n, r_digits); | 403 _rsh(x_digits, x_used, n, r_digits); |
| 390 if (r_digits[r_used - 1] == 0) { | 404 if (r_digits[r_used - 1] == 0) { |
| 391 r_used--; // Clamp result. | 405 r_used--; // Clamp result. |
| 392 } else if (r_used.isOdd) { | 406 } else if (r_used.isOdd) { |
| 393 r_digits[r_used] = 0; | 407 r_digits[r_used] = 0; |
| 394 } | 408 } |
| 395 return r_used; | 409 return r_used; |
| 396 } | 410 } |
| 397 | 411 |
| 398 // Return 0 if abs(this) == abs(a). | 412 // Return 0 if abs(this) == abs(a). |
| 399 // Return a positive number if abs(this) > abs(a). | 413 // Return a positive number if abs(this) > abs(a). |
| 400 // Return a negative number if abs(this) < abs(a). | 414 // Return a negative number if abs(this) < abs(a). |
| 401 int _absCompare(_Bigint a) { | 415 int _absCompare(_Bigint a) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 417 var r = _absCompare(a); | 431 var r = _absCompare(a); |
| 418 return _neg ? -r : r; | 432 return _neg ? -r : r; |
| 419 } | 433 } |
| 420 return _neg ? -1 : 1; | 434 return _neg ? -1 : 1; |
| 421 } | 435 } |
| 422 | 436 |
| 423 // Compare digits[0..used-1] with a_digits[0..a_used-1]. | 437 // Compare digits[0..used-1] with a_digits[0..a_used-1]. |
| 424 // Return 0 if equal. | 438 // Return 0 if equal. |
| 425 // Return a positive number if larger. | 439 // Return a positive number if larger. |
| 426 // Return a negative number if smaller. | 440 // Return a negative number if smaller. |
| 427 static int _compareDigits(Uint32List digits, int used, | 441 static int _compareDigits( |
| 428 Uint32List a_digits, int a_used) { | 442 Uint32List digits, int used, Uint32List a_digits, int a_used) { |
| 429 var r = used - a_used; | 443 var r = used - a_used; |
| 430 if (r == 0) { | 444 if (r == 0) { |
| 431 var i = a_used; | 445 var i = a_used; |
| 432 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0); | 446 while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0); |
| 433 } | 447 } |
| 434 return r; | 448 return r; |
| 435 } | 449 } |
| 436 | 450 |
| 437 // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1]. | 451 // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1]. |
| 438 // used >= a_used > 0. | 452 // used >= a_used > 0. |
| 439 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices. | 453 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices. |
| 440 static void _absAdd(Uint32List digits, int used, | 454 static void _absAdd(Uint32List digits, int used, Uint32List a_digits, |
| 441 Uint32List a_digits, int a_used, | 455 int a_used, Uint32List r_digits) { |
| 442 Uint32List r_digits) { | |
| 443 assert(used >= a_used && a_used > 0); | 456 assert(used >= a_used && a_used > 0); |
| 444 // Verify that digit pairs are accessible for 64-bit processing. | 457 // Verify that digit pairs are accessible for 64-bit processing. |
| 445 assert(digits.length > ((used - 1) | 1)); | 458 assert(digits.length > ((used - 1) | 1)); |
| 446 assert(a_digits.length > ((a_used - 1) | 1)); | 459 assert(a_digits.length > ((a_used - 1) | 1)); |
| 447 assert(r_digits.length > (used | 1)); | 460 assert(r_digits.length > (used | 1)); |
| 448 var c = 0; | 461 var c = 0; |
| 449 for (var i = 0; i < a_used; i++) { | 462 for (var i = 0; i < a_used; i++) { |
| 450 c += digits[i] + a_digits[i]; | 463 c += digits[i] + a_digits[i]; |
| 451 r_digits[i] = c & _DIGIT_MASK; | 464 r_digits[i] = c & _DIGIT_MASK; |
| 452 c >>= _DIGIT_BITS; | 465 c >>= _DIGIT_BITS; |
| 453 } | 466 } |
| 454 for (var i = a_used; i < used; i++) { | 467 for (var i = a_used; i < used; i++) { |
| 455 c += digits[i]; | 468 c += digits[i]; |
| 456 r_digits[i] = c & _DIGIT_MASK; | 469 r_digits[i] = c & _DIGIT_MASK; |
| 457 c >>= _DIGIT_BITS; | 470 c >>= _DIGIT_BITS; |
| 458 } | 471 } |
| 459 r_digits[used] = c; | 472 r_digits[used] = c; |
| 460 } | 473 } |
| 461 | 474 |
| 462 // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1]. | 475 // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1]. |
| 463 // used >= a_used > 0. | 476 // used >= a_used > 0. |
| 464 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices. | 477 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices. |
| 465 static void _absSub(Uint32List digits, int used, | 478 static void _absSub(Uint32List digits, int used, Uint32List a_digits, |
| 466 Uint32List a_digits, int a_used, | 479 int a_used, Uint32List r_digits) { |
| 467 Uint32List r_digits) { | |
| 468 assert(used >= a_used && a_used > 0); | 480 assert(used >= a_used && a_used > 0); |
| 469 // Verify that digit pairs are accessible for 64-bit processing. | 481 // Verify that digit pairs are accessible for 64-bit processing. |
| 470 assert(digits.length > ((used - 1) | 1)); | 482 assert(digits.length > ((used - 1) | 1)); |
| 471 assert(a_digits.length > ((a_used - 1) | 1)); | 483 assert(a_digits.length > ((a_used - 1) | 1)); |
| 472 assert(r_digits.length > ((used - 1) | 1)); | 484 assert(r_digits.length > ((used - 1) | 1)); |
| 473 var c = 0; | 485 var c = 0; |
| 474 for (var i = 0; i < a_used; i++) { | 486 for (var i = 0; i < a_used; i++) { |
| 475 c += digits[i] - a_digits[i]; | 487 c += digits[i] - a_digits[i]; |
| 476 r_digits[i] = c & _DIGIT_MASK; | 488 r_digits[i] = c & _DIGIT_MASK; |
| 477 c >>= _DIGIT_BITS; | 489 c >>= _DIGIT_BITS; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 } | 546 } |
| 535 | 547 |
| 536 // Return abs(this) &~ abs(a) with sign set according to neg. | 548 // Return abs(this) &~ abs(a) with sign set according to neg. |
| 537 _Bigint _absAndNotSetSign(_Bigint a, bool neg) { | 549 _Bigint _absAndNotSetSign(_Bigint a, bool neg) { |
| 538 var r_used = _used; | 550 var r_used = _used; |
| 539 var digits = _digits; | 551 var digits = _digits; |
| 540 var a_digits = a._digits; | 552 var a_digits = a._digits; |
| 541 var r_digits = new Uint32List(r_used + (r_used & 1)); | 553 var r_digits = new Uint32List(r_used + (r_used & 1)); |
| 542 var m = (r_used < a._used) ? r_used : a._used; | 554 var m = (r_used < a._used) ? r_used : a._used; |
| 543 for (var i = 0; i < m; i++) { | 555 for (var i = 0; i < m; i++) { |
| 544 r_digits[i] = digits[i] &~ a_digits[i]; | 556 r_digits[i] = digits[i] & ~a_digits[i]; |
| 545 } | 557 } |
| 546 for (var i = m; i < r_used; i++) { | 558 for (var i = m; i < r_used; i++) { |
| 547 r_digits[i] = digits[i]; | 559 r_digits[i] = digits[i]; |
| 548 } | 560 } |
| 549 return new _Bigint(neg, r_used, r_digits); | 561 return new _Bigint(neg, r_used, r_digits); |
| 550 } | 562 } |
| 551 | 563 |
| 552 // Return abs(this) | abs(a) with sign set according to neg. | 564 // Return abs(this) | abs(a) with sign set according to neg. |
| 553 _Bigint _absOrSetSign(_Bigint a, bool neg) { | 565 _Bigint _absOrSetSign(_Bigint a, bool neg) { |
| 554 var used = _used; | 566 var used = _used; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 // Result cannot be zero if this and a are negative. | 625 // Result cannot be zero if this and a are negative. |
| 614 return t1._absOrSetSign(a1, true)._absAddSetSign(_ONE, true); | 626 return t1._absOrSetSign(a1, true)._absAddSetSign(_ONE, true); |
| 615 } | 627 } |
| 616 return _absAndSetSign(a, false); | 628 return _absAndSetSign(a, false); |
| 617 } | 629 } |
| 618 // _neg != a._neg | 630 // _neg != a._neg |
| 619 var p, n; | 631 var p, n; |
| 620 if (_neg) { | 632 if (_neg) { |
| 621 p = a; | 633 p = a; |
| 622 n = this; | 634 n = this; |
| 623 } else { // & is symmetric. | 635 } else { |
| 636 // & is symmetric. |
| 624 p = this; | 637 p = this; |
| 625 n = a; | 638 n = a; |
| 626 } | 639 } |
| 627 // p & (-n) == p & ~(n-1) == p &~ (n-1) | 640 // p & (-n) == p & ~(n-1) == p &~ (n-1) |
| 628 _Bigint n1 = n._absSubSetSign(_ONE, false); | 641 _Bigint n1 = n._absSubSetSign(_ONE, false); |
| 629 return p._absAndNotSetSign(n1, false); | 642 return p._absAndNotSetSign(n1, false); |
| 630 } | 643 } |
| 631 | 644 |
| 632 // Return this &~ a. | 645 // Return this &~ a. |
| 633 _Bigint _andNot(_Bigint a) { | 646 _Bigint _andNot(_Bigint a) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 // Result cannot be zero if this and a are negative. | 681 // Result cannot be zero if this and a are negative. |
| 669 return t1._absAndSetSign(a1, true)._absAddSetSign(_ONE, true); | 682 return t1._absAndSetSign(a1, true)._absAddSetSign(_ONE, true); |
| 670 } | 683 } |
| 671 return _absOrSetSign(a, false); | 684 return _absOrSetSign(a, false); |
| 672 } | 685 } |
| 673 // _neg != a._neg | 686 // _neg != a._neg |
| 674 var p, n; | 687 var p, n; |
| 675 if (_neg) { | 688 if (_neg) { |
| 676 p = a; | 689 p = a; |
| 677 n = this; | 690 n = this; |
| 678 } else { // | is symmetric. | 691 } else { |
| 692 // | is symmetric. |
| 679 p = this; | 693 p = this; |
| 680 n = a; | 694 n = a; |
| 681 } | 695 } |
| 682 // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1) | 696 // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1) |
| 683 _Bigint n1 = n._absSubSetSign(_ONE, true); | 697 _Bigint n1 = n._absSubSetSign(_ONE, true); |
| 684 // Result cannot be zero if only one of this or a is negative. | 698 // Result cannot be zero if only one of this or a is negative. |
| 685 return n1._absAndNotSetSign(p, true)._absAddSetSign(_ONE, true); | 699 return n1._absAndNotSetSign(p, true)._absAddSetSign(_ONE, true); |
| 686 } | 700 } |
| 687 | 701 |
| 688 // Return this ^ a. | 702 // Return this ^ a. |
| 689 _Bigint _xor(_Bigint a) { | 703 _Bigint _xor(_Bigint a) { |
| 690 if (_neg == a._neg) { | 704 if (_neg == a._neg) { |
| 691 if (_neg) { | 705 if (_neg) { |
| 692 // (-this) ^ (-a) == ~(this-1) ^ ~(a-1) == (this-1) ^ (a-1) | 706 // (-this) ^ (-a) == ~(this-1) ^ ~(a-1) == (this-1) ^ (a-1) |
| 693 _Bigint t1 = _absSubSetSign(_ONE, true); | 707 _Bigint t1 = _absSubSetSign(_ONE, true); |
| 694 _Bigint a1 = a._absSubSetSign(_ONE, true); | 708 _Bigint a1 = a._absSubSetSign(_ONE, true); |
| 695 return t1._absXorSetSign(a1, false); | 709 return t1._absXorSetSign(a1, false); |
| 696 } | 710 } |
| 697 return _absXorSetSign(a, false); | 711 return _absXorSetSign(a, false); |
| 698 } | 712 } |
| 699 // _neg != a._neg | 713 // _neg != a._neg |
| 700 var p, n; | 714 var p, n; |
| 701 if (_neg) { | 715 if (_neg) { |
| 702 p = a; | 716 p = a; |
| 703 n = this; | 717 n = this; |
| 704 } else { // ^ is symmetric. | 718 } else { |
| 719 // ^ is symmetric. |
| 705 p = this; | 720 p = this; |
| 706 n = a; | 721 n = a; |
| 707 } | 722 } |
| 708 // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1) | 723 // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1) |
| 709 _Bigint n1 = n._absSubSetSign(_ONE, true); | 724 _Bigint n1 = n._absSubSetSign(_ONE, true); |
| 710 // Result cannot be zero if only one of this or a is negative. | 725 // Result cannot be zero if only one of this or a is negative. |
| 711 return p._absXorSetSign(n1, true)._absAddSetSign(_ONE, true); | 726 return p._absXorSetSign(n1, true)._absAddSetSign(_ONE, true); |
| 712 } | 727 } |
| 713 | 728 |
| 714 // Return ~this. | 729 // Return ~this. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 // Multiply and accumulate. | 772 // Multiply and accumulate. |
| 758 // Input: | 773 // Input: |
| 759 // x_digits[xi]: multiplier digit x. | 774 // x_digits[xi]: multiplier digit x. |
| 760 // m_digits[i..i+n-1]: multiplicand digits. | 775 // m_digits[i..i+n-1]: multiplicand digits. |
| 761 // a_digits[j..j+n-1]: accumulator digits. | 776 // a_digits[j..j+n-1]: accumulator digits. |
| 762 // Operation: | 777 // Operation: |
| 763 // a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1]. | 778 // a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1]. |
| 764 // return 1. | 779 // return 1. |
| 765 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices | 780 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices |
| 766 // and return 2. | 781 // and return 2. |
| 767 static int _mulAdd(Uint32List x_digits, int xi, | 782 static int _mulAdd(Uint32List x_digits, int xi, Uint32List m_digits, int i, |
| 768 Uint32List m_digits, int i, | 783 Uint32List a_digits, int j, int n) { |
| 769 Uint32List a_digits, int j, int n) { | |
| 770 // Verify that digit pairs are accessible for 64-bit processing. | 784 // Verify that digit pairs are accessible for 64-bit processing. |
| 771 assert(x_digits.length > (xi | 1)); | 785 assert(x_digits.length > (xi | 1)); |
| 772 assert(m_digits.length > ((i + n - 1) | 1)); | 786 assert(m_digits.length > ((i + n - 1) | 1)); |
| 773 assert(a_digits.length > ((j + n) | 1)); | 787 assert(a_digits.length > ((j + n) | 1)); |
| 774 int x = x_digits[xi]; | 788 int x = x_digits[xi]; |
| 775 if (x == 0) { | 789 if (x == 0) { |
| 776 // No-op if x is 0. | 790 // No-op if x is 0. |
| 777 return 1; | 791 return 1; |
| 778 } | 792 } |
| 779 int c = 0; | 793 int c = 0; |
| 780 int xl = x & _DIGIT2_MASK; | 794 int xl = x & _DIGIT2_MASK; |
| 781 int xh = x >> _DIGIT2_BITS; | 795 int xh = x >> _DIGIT2_BITS; |
| 782 while (--n >= 0) { | 796 while (--n >= 0) { |
| 783 int l = m_digits[i] & _DIGIT2_MASK; | 797 int l = m_digits[i] & _DIGIT2_MASK; |
| 784 int h = m_digits[i++] >> _DIGIT2_BITS; | 798 int h = m_digits[i++] >> _DIGIT2_BITS; |
| 785 int m = xh*l + h*xl; | 799 int m = xh * l + h * xl; |
| 786 l = xl*l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c; | 800 l = xl * l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c; |
| 787 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh*h; | 801 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh * h; |
| 788 a_digits[j++] = l & _DIGIT_MASK; | 802 a_digits[j++] = l & _DIGIT_MASK; |
| 789 } | 803 } |
| 790 while (c != 0) { | 804 while (c != 0) { |
| 791 int l = a_digits[j] + c; | 805 int l = a_digits[j] + c; |
| 792 c = l >> _DIGIT_BITS; | 806 c = l >> _DIGIT_BITS; |
| 793 a_digits[j++] = l & _DIGIT_MASK; | 807 a_digits[j++] = l & _DIGIT_MASK; |
| 794 } | 808 } |
| 795 return 1; | 809 return 1; |
| 796 } | 810 } |
| 797 | 811 |
| 798 // Square and accumulate. | 812 // Square and accumulate. |
| 799 // Input: | 813 // Input: |
| 800 // x_digits[i..used-1]: digits of operand being squared. | 814 // x_digits[i..used-1]: digits of operand being squared. |
| 801 // a_digits[2*i..i+used-1]: accumulator digits. | 815 // a_digits[2*i..i+used-1]: accumulator digits. |
| 802 // Operation: | 816 // Operation: |
| 803 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + | 817 // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] + |
| 804 // 2*x_digits[i]*x_digits[i+1..used-1]. | 818 // 2*x_digits[i]*x_digits[i+1..used-1]. |
| 805 // return 1. | 819 // return 1. |
| 806 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices | 820 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices |
| 807 // and return 2. | 821 // and return 2. |
| 808 static int _sqrAdd(Uint32List x_digits, int i, | 822 static int _sqrAdd( |
| 809 Uint32List a_digits, int used) { | 823 Uint32List x_digits, int i, Uint32List a_digits, int used) { |
| 810 // Verify that digit pairs are accessible for 64-bit processing. | 824 // Verify that digit pairs are accessible for 64-bit processing. |
| 811 assert(x_digits.length > ((used - 1) | 1)); | 825 assert(x_digits.length > ((used - 1) | 1)); |
| 812 assert(a_digits.length > ((i + used - 1) | 1)); | 826 assert(a_digits.length > ((i + used - 1) | 1)); |
| 813 int x = x_digits[i]; | 827 int x = x_digits[i]; |
| 814 if (x == 0) return 1; | 828 if (x == 0) return 1; |
| 815 int j = 2*i; | 829 int j = 2 * i; |
| 816 int c = 0; | 830 int c = 0; |
| 817 int xl = x & _DIGIT2_MASK; | 831 int xl = x & _DIGIT2_MASK; |
| 818 int xh = x >> _DIGIT2_BITS; | 832 int xh = x >> _DIGIT2_BITS; |
| 819 int m = 2*xh*xl; | 833 int m = 2 * xh * xl; |
| 820 int l = xl*xl + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j]; | 834 int l = xl * xl + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j]; |
| 821 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh*xh; | 835 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh * xh; |
| 822 a_digits[j] = l & _DIGIT_MASK; | 836 a_digits[j] = l & _DIGIT_MASK; |
| 823 x <<= 1; | 837 x <<= 1; |
| 824 xl = x & _DIGIT2_MASK; | 838 xl = x & _DIGIT2_MASK; |
| 825 xh = x >> _DIGIT2_BITS; | 839 xh = x >> _DIGIT2_BITS; |
| 826 int n = used - i - 1; | 840 int n = used - i - 1; |
| 827 int k = i + 1; | 841 int k = i + 1; |
| 828 j++; | 842 j++; |
| 829 while (--n >= 0) { | 843 while (--n >= 0) { |
| 830 int l = x_digits[k] & _DIGIT2_MASK; | 844 int l = x_digits[k] & _DIGIT2_MASK; |
| 831 int h = x_digits[k++] >> _DIGIT2_BITS; | 845 int h = x_digits[k++] >> _DIGIT2_BITS; |
| 832 int m = xh*l + h*xl; | 846 int m = xh * l + h * xl; |
| 833 l = xl*l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c; | 847 l = xl * l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c; |
| 834 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh*h; | 848 c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh * h; |
| 835 a_digits[j++] = l & _DIGIT_MASK; | 849 a_digits[j++] = l & _DIGIT_MASK; |
| 836 } | 850 } |
| 837 c += a_digits[i + used]; | 851 c += a_digits[i + used]; |
| 838 if (c >= _DIGIT_BASE) { | 852 if (c >= _DIGIT_BASE) { |
| 839 a_digits[i + used] = c - _DIGIT_BASE; | 853 a_digits[i + used] = c - _DIGIT_BASE; |
| 840 a_digits[i + used + 1] = 1; | 854 a_digits[i + used + 1] = 1; |
| 841 } else { | 855 } else { |
| 842 a_digits[i + used] = c; | 856 a_digits[i + used] = c; |
| 843 } | 857 } |
| 844 return 1; | 858 return 1; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 858 var r_digits = new Uint32List(r_used + (r_used & 1)); | 872 var r_digits = new Uint32List(r_used + (r_used & 1)); |
| 859 var i = 0; | 873 var i = 0; |
| 860 while (i < a_used) { | 874 while (i < a_used) { |
| 861 i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used); | 875 i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used); |
| 862 } | 876 } |
| 863 return new _Bigint(_neg != a._neg, r_used, r_digits); | 877 return new _Bigint(_neg != a._neg, r_used, r_digits); |
| 864 } | 878 } |
| 865 | 879 |
| 866 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*a_digits[0..a_used-1]. | 880 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*a_digits[0..a_used-1]. |
| 867 // Return r_used = x_used + a_used. | 881 // Return r_used = x_used + a_used. |
| 868 static int _mulDigits(Uint32List x_digits, int x_used, | 882 static int _mulDigits(Uint32List x_digits, int x_used, Uint32List a_digits, |
| 869 Uint32List a_digits, int a_used, | 883 int a_used, Uint32List r_digits) { |
| 870 Uint32List r_digits) { | |
| 871 var r_used = x_used + a_used; | 884 var r_used = x_used + a_used; |
| 872 var i = r_used + (r_used & 1); | 885 var i = r_used + (r_used & 1); |
| 873 assert(r_digits.length >= i); | 886 assert(r_digits.length >= i); |
| 874 while (--i >= 0) { | 887 while (--i >= 0) { |
| 875 r_digits[i] = 0; | 888 r_digits[i] = 0; |
| 876 } | 889 } |
| 877 i = 0; | 890 i = 0; |
| 878 while (i < a_used) { | 891 while (i < a_used) { |
| 879 i += _mulAdd(a_digits, i, x_digits, 0, r_digits, i, x_used); | 892 i += _mulAdd(a_digits, i, x_digits, 0, r_digits, i, x_used); |
| 880 } | 893 } |
| 881 return r_used; | 894 return r_used; |
| 882 } | 895 } |
| 883 | 896 |
| 884 // Return this^2. | 897 // Return this^2. |
| 885 _Bigint _sqr() { | 898 _Bigint _sqr() { |
| 886 var used = _used; | 899 var used = _used; |
| 887 if (used == 0) { | 900 if (used == 0) { |
| 888 return _ZERO; | 901 return _ZERO; |
| 889 } | 902 } |
| 890 var r_used = 2 * used; | 903 var r_used = 2 * used; |
| 891 var digits = _digits; | 904 var digits = _digits; |
| 892 var r_digits = new Uint32List(r_used); | 905 var r_digits = new Uint32List(r_used); |
| 893 // Since r_used is even, no need for a leading zero for 64-bit processing. | 906 // Since r_used is even, no need for a leading zero for 64-bit processing. |
| 894 var i = 0; | 907 var i = 0; |
| 895 while (i < used - 1) { | 908 while (i < used - 1) { |
| 896 i += _sqrAdd(digits, i, r_digits, used); | 909 i += _sqrAdd(digits, i, r_digits, used); |
| 897 } | 910 } |
| 898 // The last step is already done if digit pairs were processed above. | 911 // The last step is already done if digit pairs were processed above. |
| 899 if (i < used) { | 912 if (i < used) { |
| 900 _mulAdd(digits, i, digits, i, r_digits, 2*i, 1); | 913 _mulAdd(digits, i, digits, i, r_digits, 2 * i, 1); |
| 901 } | 914 } |
| 902 return new _Bigint(false, r_used, r_digits); | 915 return new _Bigint(false, r_used, r_digits); |
| 903 } | 916 } |
| 904 | 917 |
| 905 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*x_digits[0..x_used-1]. | 918 // r_digits[0..r_used-1] = x_digits[0..x_used-1]*x_digits[0..x_used-1]. |
| 906 // Return r_used = 2*x_used. | 919 // Return r_used = 2*x_used. |
| 907 static int _sqrDigits(Uint32List x_digits, int x_used, Uint32List r_digits) { | 920 static int _sqrDigits(Uint32List x_digits, int x_used, Uint32List r_digits) { |
| 908 var r_used = 2 * x_used; | 921 var r_used = 2 * x_used; |
| 909 assert(r_digits.length >= r_used); | 922 assert(r_digits.length >= r_used); |
| 910 // Since r_used is even, no need for a leading zero for 64-bit processing. | 923 // Since r_used is even, no need for a leading zero for 64-bit processing. |
| 911 var i = r_used; | 924 var i = r_used; |
| 912 while (--i >= 0) { | 925 while (--i >= 0) { |
| 913 r_digits[i] = 0; | 926 r_digits[i] = 0; |
| 914 } | 927 } |
| 915 i = 0; | 928 i = 0; |
| 916 while (i < x_used - 1) { | 929 while (i < x_used - 1) { |
| 917 i += _sqrAdd(x_digits, i, r_digits, x_used); | 930 i += _sqrAdd(x_digits, i, r_digits, x_used); |
| 918 } | 931 } |
| 919 // The last step is already done if digit pairs were processed above. | 932 // The last step is already done if digit pairs were processed above. |
| 920 if (i < x_used) { | 933 if (i < x_used) { |
| 921 _mulAdd(x_digits, i, x_digits, i, r_digits, 2*i, 1); | 934 _mulAdd(x_digits, i, x_digits, i, r_digits, 2 * i, 1); |
| 922 } | 935 } |
| 923 return r_used; | 936 return r_used; |
| 924 } | 937 } |
| 925 | 938 |
| 926 // Indices of the arguments of _estQuotientDigit. | 939 // Indices of the arguments of _estQuotientDigit. |
| 927 // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair | 940 // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair |
| 928 // of divisor y is provided in the args array, and a 64-bit estimated quotient | 941 // of divisor y is provided in the args array, and a 64-bit estimated quotient |
| 929 // is returned. However, on 32-bit platforms, the low 32-bit digit is ignored | 942 // is returned. However, on 32-bit platforms, the low 32-bit digit is ignored |
| 930 // and only one 32-bit digit is returned as the estimated quotient. | 943 // and only one 32-bit digit is returned as the estimated quotient. |
| 931 static const int _YT_LO = 0; // Low digit of top digit pair of y, for 64-bit. | 944 static const int _YT_LO = 0; // Low digit of top digit pair of y, for 64-bit. |
| 932 static const int _YT = 1; // Top digit of divisor y. | 945 static const int _YT = 1; // Top digit of divisor y. |
| 933 static const int _QD = 2; // Estimated quotient. | 946 static const int _QD = 2; // Estimated quotient. |
| 934 static const int _QD_HI = 3; // High digit of estimated quotient, for 64-bit. | 947 static const int _QD_HI = 3; // High digit of estimated quotient, for 64-bit. |
| 935 | 948 |
| 936 // Operation: | 949 // Operation: |
| 937 // Estimate args[_QD] = digits[i-1..i] ~/ args[_YT] | 950 // Estimate args[_QD] = digits[i-1..i] ~/ args[_YT] |
| 938 // return 1 | 951 // return 1 |
| 939 // Note: Intrinsics on 64-bit platforms process a digit pair (i always odd): | 952 // Note: Intrinsics on 64-bit platforms process a digit pair (i always odd): |
| 940 // Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT] | 953 // Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT] |
| 941 // return 2 | 954 // return 2 |
| 942 static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { | 955 static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) { |
| 943 // Verify that digit pairs are accessible for 64-bit processing. | 956 // Verify that digit pairs are accessible for 64-bit processing. |
| 944 assert(digits.length >= 4); | 957 assert(digits.length >= 4); |
| 945 if (digits[i] == args[_YT]) { | 958 if (digits[i] == args[_YT]) { |
| 946 args[_QD] = _DIGIT_MASK; | 959 args[_QD] = _DIGIT_MASK; |
| 947 } else { | 960 } else { |
| 948 // Chop off one bit, since a Mint cannot hold 2 DIGITs. | 961 // Chop off one bit, since a Mint cannot hold 2 DIGITs. |
| 949 var qd = ((digits[i] << (_DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) | 962 var qd = ((digits[i] << (_DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) ~/ |
| 950 ~/ (args[_YT] >> 1); | 963 (args[_YT] >> 1); |
| 951 if (qd > _DIGIT_MASK) { | 964 if (qd > _DIGIT_MASK) { |
| 952 args[_QD] = _DIGIT_MASK; | 965 args[_QD] = _DIGIT_MASK; |
| 953 } else { | 966 } else { |
| 954 args[_QD] = qd; | 967 args[_QD] = qd; |
| 955 } | 968 } |
| 956 } | 969 } |
| 957 return 1; | 970 return 1; |
| 958 } | 971 } |
| 959 | 972 |
| 960 // Return trunc(this / a), a != 0. | 973 // Return trunc(this / a), a != 0. |
| 961 _Bigint _div(_Bigint a) { | 974 _Bigint _div(_Bigint a) { |
| 962 assert(a._used > 0); | 975 assert(a._used > 0); |
| 963 if (_used < a._used) { | 976 if (_used < a._used) { |
| 964 return _ZERO; | 977 return _ZERO; |
| 965 } | 978 } |
| 966 _divRem(a); | 979 _divRem(a); |
| 967 // Return quotient, i.e. | 980 // Return quotient, i.e. |
| 968 // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign. | 981 // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign. |
| 969 var lastQuo_used = _lastQuoRem_used - _lastRem_used; | 982 var lastQuo_used = _lastQuoRem_used - _lastRem_used; |
| 970 var quo_digits = _cloneDigits(_lastQuoRem_digits, | 983 var quo_digits = _cloneDigits( |
| 971 _lastRem_used, | 984 _lastQuoRem_digits, _lastRem_used, _lastQuoRem_used, lastQuo_used); |
| 972 _lastQuoRem_used, | |
| 973 lastQuo_used); | |
| 974 var quo = new _Bigint(false, lastQuo_used, quo_digits); | 985 var quo = new _Bigint(false, lastQuo_used, quo_digits); |
| 975 if ((_neg != a._neg) && (quo._used > 0)) { | 986 if ((_neg != a._neg) && (quo._used > 0)) { |
| 976 quo = quo._negate(); | 987 quo = quo._negate(); |
| 977 } | 988 } |
| 978 return quo; | 989 return quo; |
| 979 } | 990 } |
| 980 | 991 |
| 981 // Return this - a * trunc(this / a), a != 0. | 992 // Return this - a * trunc(this / a), a != 0. |
| 982 _Bigint _rem(_Bigint a) { | 993 _Bigint _rem(_Bigint a) { |
| 983 assert(a._used > 0); | 994 assert(a._used > 0); |
| 984 if (_used < a._used) { | 995 if (_used < a._used) { |
| 985 return this; | 996 return this; |
| 986 } | 997 } |
| 987 _divRem(a); | 998 _divRem(a); |
| 988 // Return remainder, i.e. | 999 // Return remainder, i.e. |
| 989 // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign. | 1000 // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign. |
| 990 var rem_digits = _cloneDigits(_lastQuoRem_digits, | 1001 var rem_digits = |
| 991 0, | 1002 _cloneDigits(_lastQuoRem_digits, 0, _lastRem_used, _lastRem_used); |
| 992 _lastRem_used, | |
| 993 _lastRem_used); | |
| 994 var rem = new _Bigint(false, _lastRem_used, rem_digits); | 1003 var rem = new _Bigint(false, _lastRem_used, rem_digits); |
| 995 if (_lastRem_nsh > 0) { | 1004 if (_lastRem_nsh > 0) { |
| 996 rem = rem._rShift(_lastRem_nsh); // Denormalize remainder. | 1005 rem = rem._rShift(_lastRem_nsh); // Denormalize remainder. |
| 997 } | 1006 } |
| 998 if (_neg && (rem._used > 0)) { | 1007 if (_neg && (rem._used > 0)) { |
| 999 rem = rem._negate(); | 1008 rem = rem._negate(); |
| 1000 } | 1009 } |
| 1001 return rem; | 1010 return rem; |
| 1002 } | 1011 } |
| 1003 | 1012 |
| 1004 // Cache concatenated positive quotient and normalized positive remainder. | 1013 // Cache concatenated positive quotient and normalized positive remainder. |
| 1005 void _divRem(_Bigint a) { | 1014 void _divRem(_Bigint a) { |
| 1006 // Check if result is already cached (identical on Bigint is too expensive). | 1015 // Check if result is already cached (identical on Bigint is too expensive). |
| 1007 if ((this._used == _lastDividend_used) && | 1016 if ((this._used == _lastDividend_used) && |
| 1008 (a._used == _lastDivisor_used) && | 1017 (a._used == _lastDivisor_used) && |
| 1009 identical(this._digits, _lastDividend_digits) && | 1018 identical(this._digits, _lastDividend_digits) && |
| 1010 identical(a._digits, _lastDivisor_digits)) { | 1019 identical(a._digits, _lastDivisor_digits)) { |
| 1011 return; | 1020 return; |
| 1012 } | 1021 } |
| 1013 var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]); | 1022 var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]); |
| 1014 // For 64-bit processing, make sure y has an even number of digits. | 1023 // For 64-bit processing, make sure y has an even number of digits. |
| 1015 if (a._used.isOdd) { | 1024 if (a._used.isOdd) { |
| 1016 nsh += _DIGIT_BITS; | 1025 nsh += _DIGIT_BITS; |
| 1017 } | 1026 } |
| 1018 // Concatenated positive quotient and normalized positive remainder. | 1027 // Concatenated positive quotient and normalized positive remainder. |
| 1019 var r_digits; | 1028 var r_digits; |
| 1020 var r_used; | 1029 var r_used; |
| 1021 // Normalized positive divisor. | 1030 // Normalized positive divisor. |
| 1022 var y_digits; | 1031 var y_digits; |
| 1023 var y_used; | 1032 var y_used; |
| 1024 if (nsh > 0) { | 1033 if (nsh > 0) { |
| 1025 y_digits = new Uint32List(a._used + 5); // +5 for norm. and 64-bit. | 1034 y_digits = new Uint32List(a._used + 5); // +5 for norm. and 64-bit. |
| 1026 y_used = _lShiftDigits(a._digits, a._used, nsh, y_digits); | 1035 y_used = _lShiftDigits(a._digits, a._used, nsh, y_digits); |
| 1027 r_digits = new Uint32List(_used + 5); // +5 for normalization and 64-bit. | 1036 r_digits = new Uint32List(_used + 5); // +5 for normalization and 64-bit. |
| 1028 r_used = _lShiftDigits(_digits, _used, nsh, r_digits); | 1037 r_used = _lShiftDigits(_digits, _used, nsh, r_digits); |
| 1029 } else { | 1038 } else { |
| 1030 y_digits = a._digits; | 1039 y_digits = a._digits; |
| 1031 y_used = a._used; | 1040 y_used = a._used; |
| 1032 r_digits = _cloneDigits(_digits, 0, _used, _used + 2); | 1041 r_digits = _cloneDigits(_digits, 0, _used, _used + 2); |
| 1033 r_used = _used; | 1042 r_used = _used; |
| 1034 } | 1043 } |
| 1035 Uint32List yt_qd = new Uint32List(4); | 1044 Uint32List yt_qd = new Uint32List(4); |
| 1036 yt_qd[_YT_LO] = y_digits[y_used - 2]; | 1045 yt_qd[_YT_LO] = y_digits[y_used - 2]; |
| 1037 yt_qd[_YT] = y_digits[y_used - 1]; | 1046 yt_qd[_YT] = y_digits[y_used - 1]; |
| 1038 // For 64-bit processing, make sure y_used, i, and j are even. | 1047 // For 64-bit processing, make sure y_used, i, and j are even. |
| 1039 assert(y_used.isEven); | 1048 assert(y_used.isEven); |
| 1040 var i = r_used + (r_used & 1); | 1049 var i = r_used + (r_used & 1); |
| 1041 var j = i - y_used; | 1050 var j = i - y_used; |
| 1042 // t_digits is a temporary array of i digits. | 1051 // t_digits is a temporary array of i digits. |
| 1043 var t_digits = new Uint32List(i); | 1052 var t_digits = new Uint32List(i); |
| 1044 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); | 1053 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); |
| 1045 // Explicit first division step in case normalized dividend is larger or | 1054 // Explicit first division step in case normalized dividend is larger or |
| 1046 // equal to shifted normalized divisor. | 1055 // equal to shifted normalized divisor. |
| 1047 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { | 1056 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { |
| 1048 assert(i == r_used); | 1057 assert(i == r_used); |
| 1049 r_digits[r_used++] = 1; // Quotient = 1. | 1058 r_digits[r_used++] = 1; // Quotient = 1. |
| 1050 // Subtract divisor from remainder. | 1059 // Subtract divisor from remainder. |
| 1051 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1060 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1052 } else { | 1061 } else { |
| 1053 // Account for possible carry in _mulAdd step. | 1062 // Account for possible carry in _mulAdd step. |
| 1054 r_digits[r_used++] = 0; | 1063 r_digits[r_used++] = 0; |
| 1055 } | 1064 } |
| 1056 r_digits[r_used] = 0; // Leading zero for 64-bit processing. | 1065 r_digits[r_used] = 0; // Leading zero for 64-bit processing. |
| 1057 // Negate y so we can later use _mulAdd instead of non-existent _mulSub. | 1066 // Negate y so we can later use _mulAdd instead of non-existent _mulSub. |
| 1058 var ny_digits = new Uint32List(y_used + 2); | 1067 var ny_digits = new Uint32List(y_used + 2); |
| 1059 ny_digits[y_used] = 1; | 1068 ny_digits[y_used] = 1; |
| 1060 _absSub(ny_digits, y_used + 1, y_digits, y_used, ny_digits); | 1069 _absSub(ny_digits, y_used + 1, y_digits, y_used, ny_digits); |
| 1061 // ny_digits is read-only and has y_used digits (possibly including several | 1070 // ny_digits is read-only and has y_used digits (possibly including several |
| 1062 // leading zeros) plus a leading zero for 64-bit processing. | 1071 // leading zeros) plus a leading zero for 64-bit processing. |
| 1063 // r_digits is modified during iteration. | 1072 // r_digits is modified during iteration. |
| 1064 // r_digits[0..y_used-1] is the current remainder. | 1073 // r_digits[0..y_used-1] is the current remainder. |
| 1065 // r_digits[y_used..r_used-1] is the current quotient. | 1074 // r_digits[y_used..r_used-1] is the current quotient. |
| 1066 --i; | 1075 --i; |
| 1067 while (j > 0) { | 1076 while (j > 0) { |
| 1068 var d0 = _estQuotientDigit(yt_qd, r_digits, i); | 1077 var d0 = _estQuotientDigit(yt_qd, r_digits, i); |
| 1069 j -= d0; | 1078 j -= d0; |
| 1070 var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used); | 1079 var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used); |
| 1071 // _estQuotientDigit and _mulAdd must agree on the number of digits to | 1080 // _estQuotientDigit and _mulAdd must agree on the number of digits to |
| 1072 // process. | 1081 // process. |
| 1073 assert(d0 == d1); | 1082 assert(d0 == d1); |
| 1074 if (d0 == 1) { | 1083 if (d0 == 1) { |
| 1075 if (r_digits[i] < yt_qd[_QD]) { | 1084 if (r_digits[i] < yt_qd[_QD]) { |
| 1076 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); | 1085 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); |
| 1077 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1086 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1078 while (r_digits[i] < --yt_qd[_QD]) { | 1087 while (r_digits[i] < --yt_qd[_QD]) { |
| 1079 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1088 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1080 } | 1089 } |
| 1081 } | 1090 } |
| 1082 } else { | 1091 } else { |
| 1083 assert(d0 == 2); | 1092 assert(d0 == 2); |
| 1084 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1093 assert(r_digits[i] <= yt_qd[_QD_HI]); |
| 1085 if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i-1] < yt_qd[_QD])) { | 1094 if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) { |
| 1086 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); | 1095 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); |
| 1087 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1096 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1088 if (yt_qd[_QD] == 0) { | 1097 if (yt_qd[_QD] == 0) { |
| 1089 --yt_qd[_QD_HI]; | 1098 --yt_qd[_QD_HI]; |
| 1090 } | 1099 } |
| 1091 --yt_qd[_QD]; | 1100 --yt_qd[_QD]; |
| 1092 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1101 assert(r_digits[i] <= yt_qd[_QD_HI]); |
| 1093 while ((r_digits[i] < yt_qd[_QD_HI]) || | 1102 while ( |
| 1094 (r_digits[i-1] < yt_qd[_QD])) { | 1103 (r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) { |
| 1095 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1104 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1096 if (yt_qd[_QD] == 0) { | 1105 if (yt_qd[_QD] == 0) { |
| 1097 --yt_qd[_QD_HI]; | 1106 --yt_qd[_QD_HI]; |
| 1098 } | 1107 } |
| 1099 --yt_qd[_QD]; | 1108 --yt_qd[_QD]; |
| 1100 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1109 assert(r_digits[i] <= yt_qd[_QD_HI]); |
| 1101 } | 1110 } |
| 1102 } | 1111 } |
| 1103 } | 1112 } |
| 1104 i -= d0; | 1113 i -= d0; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1120 // y_digits[0..y_used-1]: normalized positive divisor. | 1129 // y_digits[0..y_used-1]: normalized positive divisor. |
| 1121 // ny_digits[0..y_used-1]: negated y_digits. | 1130 // ny_digits[0..y_used-1]: negated y_digits. |
| 1122 // nsh: normalization shift amount. | 1131 // nsh: normalization shift amount. |
| 1123 // yt_qd: top y digit(s) and place holder for estimated quotient digit(s). | 1132 // yt_qd: top y digit(s) and place holder for estimated quotient digit(s). |
| 1124 // t_digits: temp array of 2*y_used digits. | 1133 // t_digits: temp array of 2*y_used digits. |
| 1125 // r_digits: result digits array large enough to temporarily hold | 1134 // r_digits: result digits array large enough to temporarily hold |
| 1126 // concatenated quotient and normalized remainder. | 1135 // concatenated quotient and normalized remainder. |
| 1127 // Output: | 1136 // Output: |
| 1128 // r_digits[0..r_used-1]: positive remainder. | 1137 // r_digits[0..r_used-1]: positive remainder. |
| 1129 // Returns r_used. | 1138 // Returns r_used. |
| 1130 static int _remDigits(Uint32List x_digits, int x_used, | 1139 static int _remDigits( |
| 1131 Uint32List y_digits, int y_used, Uint32List ny_digits, | 1140 Uint32List x_digits, |
| 1132 int nsh, | 1141 int x_used, |
| 1133 Uint32List yt_qd, | 1142 Uint32List y_digits, |
| 1134 Uint32List t_digits, | 1143 int y_used, |
| 1135 Uint32List r_digits) { | 1144 Uint32List ny_digits, |
| 1145 int nsh, |
| 1146 Uint32List yt_qd, |
| 1147 Uint32List t_digits, |
| 1148 Uint32List r_digits) { |
| 1136 // Initialize r_digits to normalized positive dividend. | 1149 // Initialize r_digits to normalized positive dividend. |
| 1137 var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits); | 1150 var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits); |
| 1138 // For 64-bit processing, make sure y_used, i, and j are even. | 1151 // For 64-bit processing, make sure y_used, i, and j are even. |
| 1139 assert(y_used.isEven); | 1152 assert(y_used.isEven); |
| 1140 var i = r_used + (r_used & 1); | 1153 var i = r_used + (r_used & 1); |
| 1141 var j = i - y_used; | 1154 var j = i - y_used; |
| 1142 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); | 1155 var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits); |
| 1143 // Explicit first division step in case normalized dividend is larger or | 1156 // Explicit first division step in case normalized dividend is larger or |
| 1144 // equal to shifted normalized divisor. | 1157 // equal to shifted normalized divisor. |
| 1145 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { | 1158 if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) { |
| 1146 assert(i == r_used); | 1159 assert(i == r_used); |
| 1147 r_digits[r_used++] = 1; // Quotient = 1. | 1160 r_digits[r_used++] = 1; // Quotient = 1. |
| 1148 // Subtract divisor from remainder. | 1161 // Subtract divisor from remainder. |
| 1149 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1162 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1150 } else { | 1163 } else { |
| 1151 // Account for possible carry in _mulAdd step. | 1164 // Account for possible carry in _mulAdd step. |
| 1152 r_digits[r_used++] = 0; | 1165 r_digits[r_used++] = 0; |
| 1153 } | 1166 } |
| 1154 r_digits[r_used] = 0; // Leading zero for 64-bit processing. | 1167 r_digits[r_used] = 0; // Leading zero for 64-bit processing. |
| 1155 // Negated y_digits passed in ny_digits allow the use of _mulAdd instead of | 1168 // Negated y_digits passed in ny_digits allow the use of _mulAdd instead of |
| 1156 // unimplemented _mulSub. | 1169 // unimplemented _mulSub. |
| 1157 // ny_digits is read-only and has y_used digits (possibly including several | 1170 // ny_digits is read-only and has y_used digits (possibly including several |
| 1158 // leading zeros) plus a leading zero for 64-bit processing. | 1171 // leading zeros) plus a leading zero for 64-bit processing. |
| 1159 // r_digits is modified during iteration. | 1172 // r_digits is modified during iteration. |
| 1160 // r_digits[0..y_used-1] is the current remainder. | 1173 // r_digits[0..y_used-1] is the current remainder. |
| 1161 // r_digits[y_used..r_used-1] is the current quotient. | 1174 // r_digits[y_used..r_used-1] is the current quotient. |
| 1162 --i; | 1175 --i; |
| 1163 while (j > 0) { | 1176 while (j > 0) { |
| 1164 var d0 = _estQuotientDigit(yt_qd, r_digits, i); | 1177 var d0 = _estQuotientDigit(yt_qd, r_digits, i); |
| 1165 j -= d0; | 1178 j -= d0; |
| 1166 var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used); | 1179 var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used); |
| 1167 // _estQuotientDigit and _mulAdd must agree on the number of digits to | 1180 // _estQuotientDigit and _mulAdd must agree on the number of digits to |
| 1168 // process. | 1181 // process. |
| 1169 assert(d0 == d1); | 1182 assert(d0 == d1); |
| 1170 if (d0 == 1) { | 1183 if (d0 == 1) { |
| 1171 if (r_digits[i] < yt_qd[_QD]) { | 1184 if (r_digits[i] < yt_qd[_QD]) { |
| 1172 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); | 1185 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); |
| 1173 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1186 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1174 while (r_digits[i] < --yt_qd[_QD]) { | 1187 while (r_digits[i] < --yt_qd[_QD]) { |
| 1175 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1188 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1176 } | 1189 } |
| 1177 } | 1190 } |
| 1178 } else { | 1191 } else { |
| 1179 assert(d0 == 2); | 1192 assert(d0 == 2); |
| 1180 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1193 assert(r_digits[i] <= yt_qd[_QD_HI]); |
| 1181 if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i-1] < yt_qd[_QD])) { | 1194 if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) { |
| 1182 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); | 1195 var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits); |
| 1183 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1196 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1184 if (yt_qd[_QD] == 0) { | 1197 if (yt_qd[_QD] == 0) { |
| 1185 --yt_qd[_QD_HI]; | 1198 --yt_qd[_QD_HI]; |
| 1186 } | 1199 } |
| 1187 --yt_qd[_QD]; | 1200 --yt_qd[_QD]; |
| 1188 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1201 assert(r_digits[i] <= yt_qd[_QD_HI]); |
| 1189 while ((r_digits[i] < yt_qd[_QD_HI]) || | 1202 while ( |
| 1190 (r_digits[i-1] < yt_qd[_QD])) { | 1203 (r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) { |
| 1191 _absSub(r_digits, r_used, t_digits, t_used, r_digits); | 1204 _absSub(r_digits, r_used, t_digits, t_used, r_digits); |
| 1192 if (yt_qd[_QD] == 0) { | 1205 if (yt_qd[_QD] == 0) { |
| 1193 --yt_qd[_QD_HI]; | 1206 --yt_qd[_QD_HI]; |
| 1194 } | 1207 } |
| 1195 --yt_qd[_QD]; | 1208 --yt_qd[_QD]; |
| 1196 assert(r_digits[i] <= yt_qd[_QD_HI]); | 1209 assert(r_digits[i] <= yt_qd[_QD_HI]); |
| 1197 } | 1210 } |
| 1198 } | 1211 } |
| 1199 } | 1212 } |
| 1200 i -= d0; | 1213 i -= d0; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1211 int get hashCode => this; | 1224 int get hashCode => this; |
| 1212 int get _identityHashCode => this; | 1225 int get _identityHashCode => this; |
| 1213 | 1226 |
| 1214 int operator ~() { | 1227 int operator ~() { |
| 1215 return _not()._toValidInt(); | 1228 return _not()._toValidInt(); |
| 1216 } | 1229 } |
| 1217 | 1230 |
| 1218 int get bitLength { | 1231 int get bitLength { |
| 1219 if (_used == 0) return 0; | 1232 if (_used == 0) return 0; |
| 1220 if (_neg) return (~this).bitLength; | 1233 if (_neg) return (~this).bitLength; |
| 1221 return _DIGIT_BITS*(_used - 1) + _nbits(_digits[_used - 1]); | 1234 return _DIGIT_BITS * (_used - 1) + _nbits(_digits[_used - 1]); |
| 1222 } | 1235 } |
| 1223 | 1236 |
| 1224 // This method must support smi._toBigint()._shrFromInt(int). | 1237 // This method must support smi._toBigint()._shrFromInt(int). |
| 1225 int _shrFromInt(int other) { | 1238 int _shrFromInt(int other) { |
| 1226 if (_used == 0) return other; // Shift amount is zero. | 1239 if (_used == 0) return other; // Shift amount is zero. |
| 1227 if (_neg) throw new RangeError.range(this, 0, null); | 1240 if (_neg) throw new RangeError.range(this, 0, null); |
| 1228 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 1241 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
| 1229 var shift; | 1242 var shift; |
| 1230 if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) { | 1243 if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) { |
| 1231 if (other < 0) { | 1244 if (other < 0) { |
| 1232 return -1; | 1245 return -1; |
| 1233 } else { | 1246 } else { |
| 1234 return 0; | 1247 return 0; |
| 1235 } | 1248 } |
| 1236 } else { | 1249 } else { |
| 1237 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; | 1250 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; |
| 1238 } | 1251 } |
| 1239 return other._toBigint()._rShift(shift)._toValidInt(); | 1252 return other._toBigint()._rShift(shift)._toValidInt(); |
| 1240 } | 1253 } |
| 1241 | 1254 |
| 1242 // This method must support smi._toBigint()._shlFromInt(int). | 1255 // This method must support smi._toBigint()._shlFromInt(int). |
| 1243 // An out of memory exception is thrown if the result cannot be allocated. | 1256 // An out of memory exception is thrown if the result cannot be allocated. |
| 1244 int _shlFromInt(int other) { | 1257 int _shlFromInt(int other) { |
| 1245 if (_used == 0) return other; // Shift amount is zero. | 1258 if (_used == 0) return other; // Shift amount is zero. |
| 1246 if (_neg) throw new RangeError.range(this, 0, null); | 1259 if (_neg) throw new RangeError.range(this, 0, null); |
| 1247 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. | 1260 assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised. |
| 1248 var shift; | 1261 var shift; |
| 1249 if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) { | 1262 if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) { |
| 1250 if (other == 0) return 0; // Shifted value is zero. | 1263 if (other == 0) return 0; // Shifted value is zero. |
| 1251 throw new OutOfMemoryError(); | 1264 throw new OutOfMemoryError(); |
| 1252 } else { | 1265 } else { |
| 1253 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; | 1266 shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0]; |
| 1254 } | 1267 } |
| 1255 return other._toBigint()._lShift(shift)._toValidInt(); | 1268 return other._toBigint()._lShift(shift)._toValidInt(); |
| 1256 } | 1269 } |
| 1257 | 1270 |
| 1258 // Overriden operators and methods. | 1271 // Overriden operators and methods. |
| 1259 | 1272 |
| 1260 // The following operators override operators of _IntegerImplementation for | 1273 // The following operators override operators of _IntegerImplementation for |
| 1261 // efficiency, but are not necessary for correctness. They shortcut native | 1274 // efficiency, but are not necessary for correctness. They shortcut native |
| 1262 // calls that would return null because the receiver is _Bigint. | 1275 // calls that would return null because the receiver is _Bigint. |
| 1263 num operator +(num other) { | 1276 num operator +(num other) { |
| 1264 return other._toBigintOrDouble()._addFromInteger(this); | 1277 return other._toBigintOrDouble()._addFromInteger(this); |
| 1265 } | 1278 } |
| 1279 |
| 1266 num operator -(num other) { | 1280 num operator -(num other) { |
| 1267 return other._toBigintOrDouble()._subFromInteger(this); | 1281 return other._toBigintOrDouble()._subFromInteger(this); |
| 1268 } | 1282 } |
| 1283 |
| 1269 num operator *(num other) { | 1284 num operator *(num other) { |
| 1270 return other._toBigintOrDouble()._mulFromInteger(this); | 1285 return other._toBigintOrDouble()._mulFromInteger(this); |
| 1271 } | 1286 } |
| 1287 |
| 1272 num operator ~/(num other) { | 1288 num operator ~/(num other) { |
| 1273 return other._toBigintOrDouble()._truncDivFromInteger(this); | 1289 return other._toBigintOrDouble()._truncDivFromInteger(this); |
| 1274 } | 1290 } |
| 1291 |
| 1275 num operator %(num other) { | 1292 num operator %(num other) { |
| 1276 return other._toBigintOrDouble()._moduloFromInteger(this); | 1293 return other._toBigintOrDouble()._moduloFromInteger(this); |
| 1277 } | 1294 } |
| 1295 |
| 1278 int operator &(int other) { | 1296 int operator &(int other) { |
| 1279 return other._toBigintOrDouble()._bitAndFromInteger(this); | 1297 return other._toBigintOrDouble()._bitAndFromInteger(this); |
| 1280 } | 1298 } |
| 1299 |
| 1281 int operator |(int other) { | 1300 int operator |(int other) { |
| 1282 return other._toBigintOrDouble()._bitOrFromInteger(this); | 1301 return other._toBigintOrDouble()._bitOrFromInteger(this); |
| 1283 } | 1302 } |
| 1303 |
| 1284 int operator ^(int other) { | 1304 int operator ^(int other) { |
| 1285 return other._toBigintOrDouble()._bitXorFromInteger(this); | 1305 return other._toBigintOrDouble()._bitXorFromInteger(this); |
| 1286 } | 1306 } |
| 1307 |
| 1287 int operator >>(int other) { | 1308 int operator >>(int other) { |
| 1288 return other._toBigintOrDouble()._shrFromInt(this); | 1309 return other._toBigintOrDouble()._shrFromInt(this); |
| 1289 } | 1310 } |
| 1311 |
| 1290 int operator <<(int other) { | 1312 int operator <<(int other) { |
| 1291 return other._toBigintOrDouble()._shlFromInt(this); | 1313 return other._toBigintOrDouble()._shlFromInt(this); |
| 1292 } | 1314 } |
| 1293 // End of operator shortcuts. | 1315 // End of operator shortcuts. |
| 1294 | 1316 |
| 1295 int operator -() { | 1317 int operator -() { |
| 1296 return _negate()._toValidInt(); | 1318 return _negate()._toValidInt(); |
| 1297 } | 1319 } |
| 1298 | 1320 |
| 1299 int get sign { | 1321 int get sign { |
| 1300 return (_used == 0) ? 0 : _neg ? -1 : 1; | 1322 return (_used == 0) ? 0 : _neg ? -1 : 1; |
| 1301 } | 1323 } |
| 1302 | 1324 |
| 1303 bool get isEven => _used == 0 || (_digits[0] & 1) == 0; | 1325 bool get isEven => _used == 0 || (_digits[0] & 1) == 0; |
| 1304 bool get isNegative => _neg; | 1326 bool get isNegative => _neg; |
| 1305 | 1327 |
| 1306 String _toPow2String(int radix) { | 1328 String _toPow2String(int radix) { |
| 1307 if (_used == 0) return "0"; | 1329 if (_used == 0) return "0"; |
| 1308 assert(radix & (radix - 1) == 0); | 1330 assert(radix & (radix - 1) == 0); |
| 1309 final bitsPerChar = radix.bitLength - 1; | 1331 final bitsPerChar = radix.bitLength - 1; |
| 1310 final firstcx = _neg ? 1 : 0; // Index of first char in str after the sign. | 1332 final firstcx = _neg ? 1 : 0; // Index of first char in str after the sign. |
| 1311 final lastdx = _used - 1; // Index of last digit in bigint. | 1333 final lastdx = _used - 1; // Index of last digit in bigint. |
| 1312 final bitLength = lastdx*_DIGIT_BITS + _nbits(_digits[lastdx]); | 1334 final bitLength = lastdx * _DIGIT_BITS + _nbits(_digits[lastdx]); |
| 1313 // Index of char in str. Initialize with str length. | 1335 // Index of char in str. Initialize with str length. |
| 1314 var cx = firstcx + (bitLength + bitsPerChar - 1) ~/ bitsPerChar; | 1336 var cx = firstcx + (bitLength + bitsPerChar - 1) ~/ bitsPerChar; |
| 1315 _OneByteString str = _OneByteString._allocate(cx); | 1337 _OneByteString str = _OneByteString._allocate(cx); |
| 1316 str._setAt(0, 0x2d); // '-'. Is overwritten if not negative. | 1338 str._setAt(0, 0x2d); // '-'. Is overwritten if not negative. |
| 1317 final mask = radix - 1; | 1339 final mask = radix - 1; |
| 1318 var dx = 0; // Digit index in bigint. | 1340 var dx = 0; // Digit index in bigint. |
| 1319 var bx = 0; // Bit index in bigint digit. | 1341 var bx = 0; // Bit index in bigint digit. |
| 1320 do { | 1342 do { |
| 1321 var ch; | 1343 var ch; |
| 1322 if (bx > (_DIGIT_BITS - bitsPerChar)) { | 1344 if (bx > (_DIGIT_BITS - bitsPerChar)) { |
| 1323 ch = _digits[dx++] >> bx; | 1345 ch = _digits[dx++] >> bx; |
| 1324 bx += bitsPerChar - _DIGIT_BITS; | 1346 bx += bitsPerChar - _DIGIT_BITS; |
| 1325 if (dx <= lastdx) { | 1347 if (dx <= lastdx) { |
| 1326 ch |= (_digits[dx] & ((1 << bx) - 1)) << (bitsPerChar - bx); | 1348 ch |= (_digits[dx] & ((1 << bx) - 1)) << (bitsPerChar - bx); |
| 1327 } | 1349 } |
| 1328 } else { | 1350 } else { |
| 1329 ch = (_digits[dx] >> bx) & mask; | 1351 ch = (_digits[dx] >> bx) & mask; |
| 1330 bx += bitsPerChar; | 1352 bx += bitsPerChar; |
| 1331 if (bx >= _DIGIT_BITS) { | 1353 if (bx >= _DIGIT_BITS) { |
| 1332 bx -= _DIGIT_BITS; | 1354 bx -= _DIGIT_BITS; |
| 1333 dx++; | 1355 dx++; |
| 1334 } | 1356 } |
| 1335 } | 1357 } |
| 1336 str._setAt(--cx, _IntegerImplementation._digits.codeUnitAt(ch)); | 1358 str._setAt(--cx, _IntegerImplementation._digits.codeUnitAt(ch)); |
| 1337 } while (cx > firstcx); | 1359 } while (cx > firstcx); |
| 1338 return str; | 1360 return str; |
| 1339 } | 1361 } |
| 1340 | 1362 |
| 1341 int _bitAndFromSmi(int other) => _bitAndFromInteger(other); | 1363 int _bitAndFromSmi(int other) => _bitAndFromInteger(other); |
| 1342 | 1364 |
| 1343 int _bitAndFromInteger(int other) { | 1365 int _bitAndFromInteger(int other) { |
| 1344 return other._toBigint()._and(this)._toValidInt(); | 1366 return other._toBigint()._and(this)._toValidInt(); |
| 1345 } | 1367 } |
| 1368 |
| 1346 int _bitOrFromInteger(int other) { | 1369 int _bitOrFromInteger(int other) { |
| 1347 return other._toBigint()._or(this)._toValidInt(); | 1370 return other._toBigint()._or(this)._toValidInt(); |
| 1348 } | 1371 } |
| 1372 |
| 1349 int _bitXorFromInteger(int other) { | 1373 int _bitXorFromInteger(int other) { |
| 1350 return other._toBigint()._xor(this)._toValidInt(); | 1374 return other._toBigint()._xor(this)._toValidInt(); |
| 1351 } | 1375 } |
| 1376 |
| 1352 int _addFromInteger(int other) { | 1377 int _addFromInteger(int other) { |
| 1353 return other._toBigint()._add(this)._toValidInt(); | 1378 return other._toBigint()._add(this)._toValidInt(); |
| 1354 } | 1379 } |
| 1380 |
| 1355 int _subFromInteger(int other) { | 1381 int _subFromInteger(int other) { |
| 1356 return other._toBigint()._sub(this)._toValidInt(); | 1382 return other._toBigint()._sub(this)._toValidInt(); |
| 1357 } | 1383 } |
| 1384 |
| 1358 int _mulFromInteger(int other) { | 1385 int _mulFromInteger(int other) { |
| 1359 return other._toBigint()._mul(this)._toValidInt(); | 1386 return other._toBigint()._mul(this)._toValidInt(); |
| 1360 } | 1387 } |
| 1388 |
| 1361 int _truncDivFromInteger(int other) { | 1389 int _truncDivFromInteger(int other) { |
| 1362 if (_used == 0) { | 1390 if (_used == 0) { |
| 1363 throw const IntegerDivisionByZeroException(); | 1391 throw const IntegerDivisionByZeroException(); |
| 1364 } | 1392 } |
| 1365 return other._toBigint()._div(this)._toValidInt(); | 1393 return other._toBigint()._div(this)._toValidInt(); |
| 1366 } | 1394 } |
| 1395 |
| 1367 int _moduloFromInteger(int other) { | 1396 int _moduloFromInteger(int other) { |
| 1368 if (_used == 0) { | 1397 if (_used == 0) { |
| 1369 throw const IntegerDivisionByZeroException(); | 1398 throw const IntegerDivisionByZeroException(); |
| 1370 } | 1399 } |
| 1371 _Bigint result = other._toBigint()._rem(this); | 1400 _Bigint result = other._toBigint()._rem(this); |
| 1372 if (result._neg) { | 1401 if (result._neg) { |
| 1373 if (_neg) { | 1402 if (_neg) { |
| 1374 result = result._sub(this); | 1403 result = result._sub(this); |
| 1375 } else { | 1404 } else { |
| 1376 result = result._add(this); | 1405 result = result._add(this); |
| 1377 } | 1406 } |
| 1378 } | 1407 } |
| 1379 return result._toValidInt(); | 1408 return result._toValidInt(); |
| 1380 } | 1409 } |
| 1410 |
| 1381 int _remainderFromInteger(int other) { | 1411 int _remainderFromInteger(int other) { |
| 1382 if (_used == 0) { | 1412 if (_used == 0) { |
| 1383 throw const IntegerDivisionByZeroException(); | 1413 throw const IntegerDivisionByZeroException(); |
| 1384 } | 1414 } |
| 1385 return other._toBigint()._rem(this)._toValidInt(); | 1415 return other._toBigint()._rem(this)._toValidInt(); |
| 1386 } | 1416 } |
| 1417 |
| 1387 bool _greaterThanFromInteger(int other) { | 1418 bool _greaterThanFromInteger(int other) { |
| 1388 return other._toBigint()._compare(this) > 0; | 1419 return other._toBigint()._compare(this) > 0; |
| 1389 } | 1420 } |
| 1421 |
| 1390 bool _equalToInteger(int other) { | 1422 bool _equalToInteger(int other) { |
| 1391 return other._toBigint()._compare(this) == 0; | 1423 return other._toBigint()._compare(this) == 0; |
| 1392 } | 1424 } |
| 1393 | 1425 |
| 1394 // Returns pow(this, e) % m, with e >= 0, m > 0. | 1426 // Returns pow(this, e) % m, with e >= 0, m > 0. |
| 1395 int modPow(int e, int m) { | 1427 int modPow(int e, int m) { |
| 1396 if (e is! int) { | 1428 if (e is! int) { |
| 1397 throw new ArgumentError.value(e, "exponent", "not an integer"); | 1429 throw new ArgumentError.value(e, "exponent", "not an integer"); |
| 1398 } | 1430 } |
| 1399 if (m is! int) { | 1431 if (m is! int) { |
| 1400 throw new ArgumentError.value(m, "modulus", "not an integer"); | 1432 throw new ArgumentError.value(m, "modulus", "not an integer"); |
| 1401 } | 1433 } |
| 1402 if (e < 0) throw new RangeError.range(e, 0, null, "exponent"); | 1434 if (e < 0) throw new RangeError.range(e, 0, null, "exponent"); |
| 1403 if (m <= 0) throw new RangeError.range(m, 1, null, "modulus"); | 1435 if (m <= 0) throw new RangeError.range(m, 1, null, "modulus"); |
| 1404 if (e == 0) return 1; | 1436 if (e == 0) return 1; |
| 1405 m = m._toBigint(); | 1437 m = m._toBigint(); |
| 1406 final m_used = m._used; | 1438 final m_used = m._used; |
| 1407 final m_used2p4 = 2 * m_used + 4; | 1439 final m_used2p4 = 2 * m_used + 4; |
| 1408 final e_bitlen = e.bitLength; | 1440 final e_bitlen = e.bitLength; |
| 1409 if (e_bitlen <= 0) return 1; | 1441 if (e_bitlen <= 0) return 1; |
| 1410 final bool cannotUseMontgomery = m.isEven || _abs() >= m; | 1442 final bool cannotUseMontgomery = m.isEven || _abs() >= m; |
| 1411 if (cannotUseMontgomery || e_bitlen < 64) { | 1443 if (cannotUseMontgomery || e_bitlen < 64) { |
| 1412 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) ? | 1444 _Reduction z = (cannotUseMontgomery || e_bitlen < 8) |
| 1413 new _Classic(m) : new _Montgomery(m); | 1445 ? new _Classic(m) |
| 1446 : new _Montgomery(m); |
| 1414 // TODO(regis): Should we use Barrett reduction for an even modulus and a | 1447 // TODO(regis): Should we use Barrett reduction for an even modulus and a |
| 1415 // large exponent? | 1448 // large exponent? |
| 1416 var r_digits = new Uint32List(m_used2p4); | 1449 var r_digits = new Uint32List(m_used2p4); |
| 1417 var r2_digits = new Uint32List(m_used2p4); | 1450 var r2_digits = new Uint32List(m_used2p4); |
| 1418 var g_digits = new Uint32List(m_used + (m_used & 1)); | 1451 var g_digits = new Uint32List(m_used + (m_used & 1)); |
| 1419 var g_used = z._convert(this, g_digits); | 1452 var g_used = z._convert(this, g_digits); |
| 1420 // Initialize r with g. | 1453 // Initialize r with g. |
| 1421 var j = g_used + (g_used & 1); // Copy leading zero if any. | 1454 var j = g_used + (g_used & 1); // Copy leading zero if any. |
| 1422 while (--j >= 0) { | 1455 while (--j >= 0) { |
| 1423 r_digits[j] = g_digits[j]; | 1456 r_digits[j] = g_digits[j]; |
| 1424 } | 1457 } |
| 1425 var r_used = g_used; | 1458 var r_used = g_used; |
| 1426 var r2_used; | 1459 var r2_used; |
| 1427 var i = e_bitlen - 1; | 1460 var i = e_bitlen - 1; |
| 1428 while (--i >= 0) { | 1461 while (--i >= 0) { |
| 1429 r2_used = z._sqr(r_digits, r_used, r2_digits); | 1462 r2_used = z._sqr(r_digits, r_used, r2_digits); |
| 1430 if ((e & (1 << i)) != 0) { | 1463 if ((e & (1 << i)) != 0) { |
| 1431 r_used = z._mul(r2_digits, r2_used, g_digits, g_used, r_digits); | 1464 r_used = z._mul(r2_digits, r2_used, g_digits, g_used, r_digits); |
| 1432 } else { | 1465 } else { |
| 1433 var t_digits = r_digits; | 1466 var t_digits = r_digits; |
| 1434 var t_used = r_used; | 1467 var t_used = r_used; |
| 1435 r_digits = r2_digits; | 1468 r_digits = r2_digits; |
| 1436 r_used = r2_used; | 1469 r_used = r2_used; |
| 1437 r2_digits = t_digits; | 1470 r2_digits = t_digits; |
| 1438 r2_used = t_used; | 1471 r2_used = t_used; |
| 1439 } | 1472 } |
| 1440 } | 1473 } |
| 1441 return z._revert(r_digits, r_used)._toValidInt(); | 1474 return z._revert(r_digits, r_used)._toValidInt(); |
| 1442 } | 1475 } |
| 1443 e = e._toBigint(); | 1476 e = e._toBigint(); |
| 1444 var k; | 1477 var k; |
| 1445 if (e_bitlen < 18) k = 1; | 1478 if (e_bitlen < 18) |
| 1446 else if (e_bitlen < 48) k = 3; | 1479 k = 1; |
| 1447 else if (e_bitlen < 144) k = 4; | 1480 else if (e_bitlen < 48) |
| 1448 else if (e_bitlen < 768) k = 5; | 1481 k = 3; |
| 1449 else k = 6; | 1482 else if (e_bitlen < 144) |
| 1483 k = 4; |
| 1484 else if (e_bitlen < 768) |
| 1485 k = 5; |
| 1486 else |
| 1487 k = 6; |
| 1450 _Reduction z = new _Montgomery(m); | 1488 _Reduction z = new _Montgomery(m); |
| 1451 var n = 3; | 1489 var n = 3; |
| 1452 final k1 = k - 1; | 1490 final k1 = k - 1; |
| 1453 final km = (1 << k) - 1; | 1491 final km = (1 << k) - 1; |
| 1454 List g_digits = new List(km + 1); | 1492 List g_digits = new List(km + 1); |
| 1455 List g_used = new List(km + 1); | 1493 List g_used = new List(km + 1); |
| 1456 g_digits[1] = new Uint32List(m_used + (m_used & 1)); | 1494 g_digits[1] = new Uint32List(m_used + (m_used & 1)); |
| 1457 g_used[1] = z._convert(this, g_digits[1]); | 1495 g_used[1] = z._convert(this, g_digits[1]); |
| 1458 if (k > 1) { | 1496 if (k > 1) { |
| 1459 var g2_digits = new Uint32List(m_used2p4); | 1497 var g2_digits = new Uint32List(m_used2p4); |
| 1460 var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits); | 1498 var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits); |
| 1461 while (n <= km) { | 1499 while (n <= km) { |
| 1462 g_digits[n] = new Uint32List(m_used2p4); | 1500 g_digits[n] = new Uint32List(m_used2p4); |
| 1463 g_used[n] = z._mul(g2_digits, g2_used, | 1501 g_used[n] = z._mul( |
| 1464 g_digits[n - 2], g_used[n - 2], | 1502 g2_digits, g2_used, g_digits[n - 2], g_used[n - 2], g_digits[n]); |
| 1465 g_digits[n]); | |
| 1466 n += 2; | 1503 n += 2; |
| 1467 } | 1504 } |
| 1468 } | 1505 } |
| 1469 var w; | 1506 var w; |
| 1470 var is1 = true; | 1507 var is1 = true; |
| 1471 var r_digits = _ONE._digits; | 1508 var r_digits = _ONE._digits; |
| 1472 var r_used = _ONE._used; | 1509 var r_used = _ONE._used; |
| 1473 var r2_digits = new Uint32List(m_used2p4); | 1510 var r2_digits = new Uint32List(m_used2p4); |
| 1474 var r2_used; | 1511 var r2_used; |
| 1475 var e_digits = e._digits; | 1512 var e_digits = e._digits; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1486 } | 1523 } |
| 1487 n = k; | 1524 n = k; |
| 1488 while ((w & 1) == 0) { | 1525 while ((w & 1) == 0) { |
| 1489 w >>= 1; | 1526 w >>= 1; |
| 1490 --n; | 1527 --n; |
| 1491 } | 1528 } |
| 1492 if ((i -= n) < 0) { | 1529 if ((i -= n) < 0) { |
| 1493 i += _DIGIT_BITS; | 1530 i += _DIGIT_BITS; |
| 1494 --j; | 1531 --j; |
| 1495 } | 1532 } |
| 1496 if (is1) { // r == 1, don't bother squaring or multiplying it. | 1533 if (is1) { |
| 1534 // r == 1, don't bother squaring or multiplying it. |
| 1497 r_digits = new Uint32List(m_used2p4); | 1535 r_digits = new Uint32List(m_used2p4); |
| 1498 r_used = g_used[w]; | 1536 r_used = g_used[w]; |
| 1499 var gw_digits = g_digits[w]; | 1537 var gw_digits = g_digits[w]; |
| 1500 var ri = r_used + (r_used & 1); // Copy leading zero if any. | 1538 var ri = r_used + (r_used & 1); // Copy leading zero if any. |
| 1501 while (--ri >= 0) { | 1539 while (--ri >= 0) { |
| 1502 r_digits[ri] = gw_digits[ri]; | 1540 r_digits[ri] = gw_digits[ri]; |
| 1503 } | 1541 } |
| 1504 is1 = false; | 1542 is1 = false; |
| 1505 } | 1543 } else { |
| 1506 else { | |
| 1507 while (n > 1) { | 1544 while (n > 1) { |
| 1508 r2_used = z._sqr(r_digits, r_used, r2_digits); | 1545 r2_used = z._sqr(r_digits, r_used, r2_digits); |
| 1509 r_used = z._sqr(r2_digits, r2_used, r_digits); | 1546 r_used = z._sqr(r2_digits, r2_used, r_digits); |
| 1510 n -= 2; | 1547 n -= 2; |
| 1511 } | 1548 } |
| 1512 if (n > 0) { | 1549 if (n > 0) { |
| 1513 r2_used = z._sqr(r_digits, r_used, r2_digits); | 1550 r2_used = z._sqr(r_digits, r_used, r2_digits); |
| 1514 } else { | 1551 } else { |
| 1515 var t_digits = r_digits; | 1552 var t_digits = r_digits; |
| 1516 var t_used = r_used; | 1553 var t_used = r_used; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1581 if ((y_digits[0] & 1) == 1) { | 1618 if ((y_digits[0] & 1) == 1) { |
| 1582 var t_digits = x_digits; | 1619 var t_digits = x_digits; |
| 1583 var t_used = x_used; | 1620 var t_used = x_used; |
| 1584 x_digits = y_digits; | 1621 x_digits = y_digits; |
| 1585 x_used = y_used; | 1622 x_used = y_used; |
| 1586 y_digits = t_digits; | 1623 y_digits = t_digits; |
| 1587 y_used = t_used; | 1624 y_used = t_used; |
| 1588 } | 1625 } |
| 1589 } | 1626 } |
| 1590 var u_digits = _cloneDigits(x_digits, 0, x_used, m_len); | 1627 var u_digits = _cloneDigits(x_digits, 0, x_used, m_len); |
| 1591 var v_digits = _cloneDigits(y_digits, 0, y_used, m_len + 2); // +2 for lsh. | 1628 var v_digits = _cloneDigits(y_digits, 0, y_used, m_len + 2); // +2 for lsh. |
| 1592 final bool ac = (x_digits[0] & 1) == 0; | 1629 final bool ac = (x_digits[0] & 1) == 0; |
| 1593 | 1630 |
| 1594 // Variables a, b, c, and d require one more digit. | 1631 // Variables a, b, c, and d require one more digit. |
| 1595 final abcd_used = m_used + 1; | 1632 final abcd_used = m_used + 1; |
| 1596 final abcd_len = abcd_used + (abcd_used & 1) + 2; // +2 to satisfy _absAdd. | 1633 final abcd_len = abcd_used + (abcd_used & 1) + 2; // +2 to satisfy _absAdd. |
| 1597 var a_digits, b_digits, c_digits, d_digits; | 1634 var a_digits, b_digits, c_digits, d_digits; |
| 1598 bool a_neg, b_neg, c_neg, d_neg; | 1635 bool a_neg, b_neg, c_neg, d_neg; |
| 1599 if (ac) { | 1636 if (ac) { |
| 1600 a_digits = new Uint32List(abcd_len); | 1637 a_digits = new Uint32List(abcd_len); |
| 1601 a_neg = false; | 1638 a_neg = false; |
| 1602 a_digits[0] = 1; | 1639 a_digits[0] = 1; |
| 1603 c_digits = new Uint32List(abcd_len); | 1640 c_digits = new Uint32List(abcd_len); |
| 1604 c_neg = false; | 1641 c_neg = false; |
| 1605 } | 1642 } |
| 1606 b_digits = new Uint32List(abcd_len); | 1643 b_digits = new Uint32List(abcd_len); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1633 } else { | 1670 } else { |
| 1634 _absSub(x_digits, m_used, b_digits, m_used, b_digits); | 1671 _absSub(x_digits, m_used, b_digits, m_used, b_digits); |
| 1635 b_neg = true; | 1672 b_neg = true; |
| 1636 } | 1673 } |
| 1637 } | 1674 } |
| 1638 _rsh(a_digits, abcd_used, 1, a_digits); | 1675 _rsh(a_digits, abcd_used, 1, a_digits); |
| 1639 } else if ((b_digits[0] & 1) == 1) { | 1676 } else if ((b_digits[0] & 1) == 1) { |
| 1640 if (b_neg) { | 1677 if (b_neg) { |
| 1641 _absAdd(b_digits, abcd_used, x_digits, m_used, b_digits); | 1678 _absAdd(b_digits, abcd_used, x_digits, m_used, b_digits); |
| 1642 } else if ((b_digits[m_used] != 0) || | 1679 } else if ((b_digits[m_used] != 0) || |
| 1643 (_compareDigits(b_digits, m_used, x_digits, m_used) > 0)) { | 1680 (_compareDigits(b_digits, m_used, x_digits, m_used) > 0)) { |
| 1644 _absSub(b_digits, abcd_used, x_digits, m_used, b_digits); | 1681 _absSub(b_digits, abcd_used, x_digits, m_used, b_digits); |
| 1645 } else { | 1682 } else { |
| 1646 _absSub(x_digits, m_used, b_digits, m_used, b_digits); | 1683 _absSub(x_digits, m_used, b_digits, m_used, b_digits); |
| 1647 b_neg = true; | 1684 b_neg = true; |
| 1648 } | 1685 } |
| 1649 } | 1686 } |
| 1650 _rsh(b_digits, abcd_used, 1, b_digits); | 1687 _rsh(b_digits, abcd_used, 1, b_digits); |
| 1651 } | 1688 } |
| 1652 while ((v_digits[0] & 1) == 0) { | 1689 while ((v_digits[0] & 1) == 0) { |
| 1653 _rsh(v_digits, m_used, 1, v_digits); | 1690 _rsh(v_digits, m_used, 1, v_digits); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1672 } else { | 1709 } else { |
| 1673 _absSub(x_digits, m_used, d_digits, m_used, d_digits); | 1710 _absSub(x_digits, m_used, d_digits, m_used, d_digits); |
| 1674 d_neg = true; | 1711 d_neg = true; |
| 1675 } | 1712 } |
| 1676 } | 1713 } |
| 1677 _rsh(c_digits, abcd_used, 1, c_digits); | 1714 _rsh(c_digits, abcd_used, 1, c_digits); |
| 1678 } else if ((d_digits[0] & 1) == 1) { | 1715 } else if ((d_digits[0] & 1) == 1) { |
| 1679 if (d_neg) { | 1716 if (d_neg) { |
| 1680 _absAdd(d_digits, abcd_used, x_digits, m_used, d_digits); | 1717 _absAdd(d_digits, abcd_used, x_digits, m_used, d_digits); |
| 1681 } else if ((d_digits[m_used] != 0) || | 1718 } else if ((d_digits[m_used] != 0) || |
| 1682 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1719 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
| 1683 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1720 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
| 1684 } else { | 1721 } else { |
| 1685 _absSub(x_digits, m_used, d_digits, m_used, d_digits); | 1722 _absSub(x_digits, m_used, d_digits, m_used, d_digits); |
| 1686 d_neg = true; | 1723 d_neg = true; |
| 1687 } | 1724 } |
| 1688 } | 1725 } |
| 1689 _rsh(d_digits, abcd_used, 1, d_digits); | 1726 _rsh(d_digits, abcd_used, 1, d_digits); |
| 1690 } | 1727 } |
| 1691 if (_compareDigits(u_digits, m_used, v_digits, m_used) >= 0) { | 1728 if (_compareDigits(u_digits, m_used, v_digits, m_used) >= 0) { |
| 1692 _absSub(u_digits, m_used, v_digits, m_used, u_digits); | 1729 _absSub(u_digits, m_used, v_digits, m_used, u_digits); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1772 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1809 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
| 1773 } else { | 1810 } else { |
| 1774 _absSub(x_digits, m_used, d_digits, m_used, d_digits); | 1811 _absSub(x_digits, m_used, d_digits, m_used, d_digits); |
| 1775 d_neg = false; | 1812 d_neg = false; |
| 1776 } | 1813 } |
| 1777 } else { | 1814 } else { |
| 1778 _absSub(x_digits, m_used, d_digits, m_used, d_digits); | 1815 _absSub(x_digits, m_used, d_digits, m_used, d_digits); |
| 1779 d_neg = false; | 1816 d_neg = false; |
| 1780 } | 1817 } |
| 1781 } else if ((d_digits[m_used] != 0) || | 1818 } else if ((d_digits[m_used] != 0) || |
| 1782 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1819 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
| 1783 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1820 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
| 1784 if ((d_digits[m_used] != 0) || | 1821 if ((d_digits[m_used] != 0) || |
| 1785 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { | 1822 (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) { |
| 1786 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); | 1823 _absSub(d_digits, abcd_used, x_digits, m_used, d_digits); |
| 1787 } | 1824 } |
| 1788 } | 1825 } |
| 1789 return new _Bigint(false, m_used, d_digits)._toValidInt(); | 1826 return new _Bigint(false, m_used, d_digits)._toValidInt(); |
| 1790 } | 1827 } |
| 1791 | 1828 |
| 1792 // Returns 1/this % m, with m > 0. | 1829 // Returns 1/this % m, with m > 0. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1814 return this.abs(); | 1851 return this.abs(); |
| 1815 } | 1852 } |
| 1816 return _binaryGcd(this, other._toBigint(), false); | 1853 return _binaryGcd(this, other._toBigint(), false); |
| 1817 } | 1854 } |
| 1818 } | 1855 } |
| 1819 | 1856 |
| 1820 // Interface for modular reduction. | 1857 // Interface for modular reduction. |
| 1821 class _Reduction { | 1858 class _Reduction { |
| 1822 // Return the number of digits used by r_digits. | 1859 // Return the number of digits used by r_digits. |
| 1823 int _convert(_Bigint x, Uint32List r_digits); | 1860 int _convert(_Bigint x, Uint32List r_digits); |
| 1824 int _mul(Uint32List x_digits, int x_used, | 1861 int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used, |
| 1825 Uint32List y_digits, int y_used, Uint32List r_digits); | 1862 Uint32List r_digits); |
| 1826 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits); | 1863 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits); |
| 1827 | 1864 |
| 1828 // Return x reverted to _Bigint. | 1865 // Return x reverted to _Bigint. |
| 1829 _Bigint _revert(Uint32List x_digits, int x_used); | 1866 _Bigint _revert(Uint32List x_digits, int x_used); |
| 1830 } | 1867 } |
| 1831 | 1868 |
| 1832 // Montgomery reduction on _Bigint. | 1869 // Montgomery reduction on _Bigint. |
| 1833 class _Montgomery implements _Reduction { | 1870 class _Montgomery implements _Reduction { |
| 1834 _Bigint _m; // Modulus. | 1871 _Bigint _m; // Modulus. |
| 1835 int _mused2p2; | 1872 int _mused2p2; |
| 1836 Uint32List _args; | 1873 Uint32List _args; |
| 1837 int _digits_per_step; // Number of digits processed in one step. 1 or 2. | 1874 int _digits_per_step; // Number of digits processed in one step. 1 or 2. |
| 1838 static const int _X = 0; // Index of x. | 1875 static const int _X = 0; // Index of x. |
| 1839 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only). | 1876 static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only). |
| 1840 static const int _RHO = 2; // Index of rho. | 1877 static const int _RHO = 2; // Index of rho. |
| 1841 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only). | 1878 static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only). |
| 1842 static const int _MU = 4; // Index of mu. | 1879 static const int _MU = 4; // Index of mu. |
| 1843 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only). | 1880 static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only). |
| 1844 | 1881 |
| 1845 _Montgomery(m) { | 1882 _Montgomery(m) { |
| 1846 _m = m._toBigint(); | 1883 _m = m._toBigint(); |
| 1847 _mused2p2 = 2*_m._used + 2; | 1884 _mused2p2 = 2 * _m._used + 2; |
| 1848 _args = new Uint32List(6); | 1885 _args = new Uint32List(6); |
| 1849 // Determine if we can process digit pairs by calling an intrinsic. | 1886 // Determine if we can process digit pairs by calling an intrinsic. |
| 1850 _digits_per_step = _mulMod(_args, _args, 0); | 1887 _digits_per_step = _mulMod(_args, _args, 0); |
| 1851 _args[_X] = _m._digits[0]; | 1888 _args[_X] = _m._digits[0]; |
| 1852 if (_digits_per_step == 1) { | 1889 if (_digits_per_step == 1) { |
| 1853 _invDigit(_args); | 1890 _invDigit(_args); |
| 1854 } else { | 1891 } else { |
| 1855 assert(_digits_per_step == 2); | 1892 assert(_digits_per_step == 2); |
| 1856 _args[_X_HI] = _m._digits[1]; | 1893 _args[_X_HI] = _m._digits[1]; |
| 1857 _invDigitPair(_args); | 1894 _invDigitPair(_args); |
| 1858 } | 1895 } |
| 1859 } | 1896 } |
| 1860 | 1897 |
| 1861 // Calculates -1/x % _DIGIT_BASE, x is 32-bit digit. | 1898 // Calculates -1/x % _DIGIT_BASE, x is 32-bit digit. |
| 1862 // xy == 1 (mod m) | 1899 // xy == 1 (mod m) |
| 1863 // xy = 1+km | 1900 // xy = 1+km |
| 1864 // xy(2-xy) = (1+km)(1-km) | 1901 // xy(2-xy) = (1+km)(1-km) |
| 1865 // x(y(2-xy)) = 1-k^2 m^2 | 1902 // x(y(2-xy)) = 1-k^2 m^2 |
| 1866 // x(y(2-xy)) == 1 (mod m^2) | 1903 // x(y(2-xy)) == 1 (mod m^2) |
| 1867 // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 | 1904 // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 |
| 1868 // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded. | 1905 // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded. |
| 1869 // | 1906 // |
| 1870 // Operation: | 1907 // Operation: |
| 1871 // args[_RHO] = 1/args[_X] mod _DIGIT_BASE. | 1908 // args[_RHO] = 1/args[_X] mod _DIGIT_BASE. |
| 1872 static void _invDigit(Uint32List args) { | 1909 static void _invDigit(Uint32List args) { |
| 1873 var x = args[_X]; | 1910 var x = args[_X]; |
| 1874 var y = x & 3; // y == 1/x mod 2^2 | 1911 var y = x & 3; // y == 1/x mod 2^2 |
| 1875 y = (y*(2 - (x & 0xf)*y)) & 0xf; // y == 1/x mod 2^4 | 1912 y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4 |
| 1876 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 | 1913 y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8 |
| 1877 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 | 1914 y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 |
| 1878 // Last step - calculate inverse mod _DIGIT_BASE directly; | 1915 // Last step - calculate inverse mod _DIGIT_BASE directly; |
| 1879 // Assumes 16 < _DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. | 1916 // Assumes 16 < _DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. |
| 1880 y = (y*(2 - x*y % _Bigint._DIGIT_BASE)) % _Bigint._DIGIT_BASE; | 1917 y = (y * (2 - x * y % _Bigint._DIGIT_BASE)) % _Bigint._DIGIT_BASE; |
| 1881 // y == 1/x mod _DIGIT_BASE | 1918 // y == 1/x mod _DIGIT_BASE |
| 1882 y = -y; // We really want the negative inverse. | 1919 y = -y; // We really want the negative inverse. |
| 1883 args[_RHO] = y & _Bigint._DIGIT_MASK; | 1920 args[_RHO] = y & _Bigint._DIGIT_MASK; |
| 1884 } | 1921 } |
| 1885 | 1922 |
| 1886 // Calculates -1/x % _DIGIT_BASE^2, x is a pair of 32-bit digits. | 1923 // Calculates -1/x % _DIGIT_BASE^2, x is a pair of 32-bit digits. |
| 1887 // Operation: | 1924 // Operation: |
| 1888 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod _DIGIT_BASE^2. | 1925 // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod _DIGIT_BASE^2. |
| 1889 static void _invDigitPair(Uint32List args) { | 1926 static void _invDigitPair(Uint32List args) { |
| 1890 var xl = args[_X]; // Lower 32-bit digit of x. | 1927 var xl = args[_X]; // Lower 32-bit digit of x. |
| 1891 var y = xl & 3; // y == 1/x mod 2^2 | 1928 var y = xl & 3; // y == 1/x mod 2^2 |
| 1892 y = (y*(2 - (xl & 0xf)*y)) & 0xf; // y == 1/x mod 2^4 | 1929 y = (y * (2 - (xl & 0xf) * y)) & 0xf; // y == 1/x mod 2^4 |
| 1893 y = (y*(2 - (xl & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 | 1930 y = (y * (2 - (xl & 0xff) * y)) & 0xff; // y == 1/x mod 2^8 |
| 1894 y = (y*(2 - (((xl & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 | 1931 y = (y * (2 - (((xl & 0xffff) * y) & 0xffff))) & |
| 1895 y = (y*(2 - ((xl*y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32 | 1932 0xffff; // y == 1/x mod 2^16 |
| 1933 y = (y * (2 - ((xl * y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32 |
| 1896 var x = (args[_X_HI] << _Bigint._DIGIT_BITS) | xl; | 1934 var x = (args[_X_HI] << _Bigint._DIGIT_BITS) | xl; |
| 1897 y = (y*(2 - ((x*y) & 0xffffffffffffffff))) & 0xffffffffffffffff; | 1935 y = (y * (2 - ((x * y) & 0xffffffffffffffff))) & 0xffffffffffffffff; |
| 1898 // y == 1/x mod _DIGIT_BASE^2 | 1936 // y == 1/x mod _DIGIT_BASE^2 |
| 1899 y = -y; // We really want the negative inverse. | 1937 y = -y; // We really want the negative inverse. |
| 1900 args[_RHO] = y & _Bigint._DIGIT_MASK; | 1938 args[_RHO] = y & _Bigint._DIGIT_MASK; |
| 1901 args[_RHO_HI] = (y >> _Bigint._DIGIT_BITS) & _Bigint._DIGIT_MASK; | 1939 args[_RHO_HI] = (y >> _Bigint._DIGIT_BITS) & _Bigint._DIGIT_MASK; |
| 1902 } | 1940 } |
| 1903 | 1941 |
| 1904 // Operation: | 1942 // Operation: |
| 1905 // args[_MU] = args[_RHO]*digits[i] mod _DIGIT_BASE. | 1943 // args[_MU] = args[_RHO]*digits[i] mod _DIGIT_BASE. |
| 1906 // return 1. | 1944 // return 1. |
| 1907 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices: | 1945 // Note: Intrinsics on 64-bit platforms process digit pairs at even indices: |
| 1908 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod _DIGIT_BASE^2. | 1946 // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod _DIGIT_BASE^2. |
| 1909 // return 2. | 1947 // return 2. |
| 1910 static int _mulMod(Uint32List args, Uint32List digits, int i) { | 1948 static int _mulMod(Uint32List args, Uint32List digits, int i) { |
| 1911 // Verify that digit pairs are accessible for 64-bit processing. | 1949 // Verify that digit pairs are accessible for 64-bit processing. |
| 1912 assert(digits.length > (i | 1)); | 1950 assert(digits.length > (i | 1)); |
| 1913 const int MU_MASK = (1 << (_Bigint._DIGIT_BITS - _Bigint._DIGIT2_BITS)) - 1; | 1951 const int MU_MASK = (1 << (_Bigint._DIGIT_BITS - _Bigint._DIGIT2_BITS)) - 1; |
| 1914 var rhol = args[_RHO] & _Bigint._DIGIT2_MASK; | 1952 var rhol = args[_RHO] & _Bigint._DIGIT2_MASK; |
| 1915 var rhoh = args[_RHO] >> _Bigint._DIGIT2_BITS; | 1953 var rhoh = args[_RHO] >> _Bigint._DIGIT2_BITS; |
| 1916 var dh = digits[i] >> _Bigint._DIGIT2_BITS; | 1954 var dh = digits[i] >> _Bigint._DIGIT2_BITS; |
| 1917 var dl = digits[i] & _Bigint._DIGIT2_MASK; | 1955 var dl = digits[i] & _Bigint._DIGIT2_MASK; |
| 1918 args[_MU] = | 1956 args[_MU] = (dl * rhol + |
| 1919 (dl*rhol + (((dl*rhoh + dh*rhol) & MU_MASK) << _Bigint._DIGIT2_BITS)) | 1957 (((dl * rhoh + dh * rhol) & MU_MASK) << _Bigint._DIGIT2_BITS)) & |
| 1920 & _Bigint._DIGIT_MASK; | 1958 _Bigint._DIGIT_MASK; |
| 1921 return 1; | 1959 return 1; |
| 1922 } | 1960 } |
| 1923 | 1961 |
| 1924 // r = x*R mod _m. | 1962 // r = x*R mod _m. |
| 1925 // Return r_used. | 1963 // Return r_used. |
| 1926 int _convert(_Bigint x, Uint32List r_digits) { | 1964 int _convert(_Bigint x, Uint32List r_digits) { |
| 1927 // Montgomery reduction only works if abs(x) < _m. | 1965 // Montgomery reduction only works if abs(x) < _m. |
| 1928 assert(x._abs() < _m); | 1966 assert(x._abs() < _m); |
| 1929 var r = x._abs()._dlShift(_m._used)._rem(_m); | 1967 var r = x._abs()._dlShift(_m._used)._rem(_m); |
| 1930 if (x._neg && !r._neg && r._used > 0) { | 1968 if (x._neg && !r._neg && r._used > 0) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1945 while (--i >= 0) { | 1983 while (--i >= 0) { |
| 1946 r_digits[i] = x_digits[i]; | 1984 r_digits[i] = x_digits[i]; |
| 1947 } | 1985 } |
| 1948 var r_used = _reduce(r_digits, x_used); | 1986 var r_used = _reduce(r_digits, x_used); |
| 1949 return new _Bigint(false, r_used, r_digits); | 1987 return new _Bigint(false, r_used, r_digits); |
| 1950 } | 1988 } |
| 1951 | 1989 |
| 1952 // x = x/R mod _m. | 1990 // x = x/R mod _m. |
| 1953 // Return x_used. | 1991 // Return x_used. |
| 1954 int _reduce(Uint32List x_digits, int x_used) { | 1992 int _reduce(Uint32List x_digits, int x_used) { |
| 1955 while (x_used < _mused2p2) { // Pad x so _mulAdd has enough room later. | 1993 while (x_used < _mused2p2) { |
| 1994 // Pad x so _mulAdd has enough room later. |
| 1956 x_digits[x_used++] = 0; | 1995 x_digits[x_used++] = 0; |
| 1957 } | 1996 } |
| 1958 var m_used = _m._used; | 1997 var m_used = _m._used; |
| 1959 var m_digits = _m._digits; | 1998 var m_digits = _m._digits; |
| 1960 var i = 0; | 1999 var i = 0; |
| 1961 while (i < m_used) { | 2000 while (i < m_used) { |
| 1962 var d = _mulMod(_args, x_digits, i); | 2001 var d = _mulMod(_args, x_digits, i); |
| 1963 assert(d == _digits_per_step); | 2002 assert(d == _digits_per_step); |
| 1964 d = _Bigint._mulAdd(_args, _MU, m_digits, 0, x_digits, i, m_used); | 2003 d = _Bigint._mulAdd(_args, _MU, m_digits, 0, x_digits, i, m_used); |
| 1965 assert(d == _digits_per_step); | 2004 assert(d == _digits_per_step); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1979 --x_used; | 2018 --x_used; |
| 1980 } | 2019 } |
| 1981 return x_used; | 2020 return x_used; |
| 1982 } | 2021 } |
| 1983 | 2022 |
| 1984 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) { | 2023 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) { |
| 1985 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits); | 2024 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits); |
| 1986 return _reduce(r_digits, r_used); | 2025 return _reduce(r_digits, r_used); |
| 1987 } | 2026 } |
| 1988 | 2027 |
| 1989 int _mul(Uint32List x_digits, int x_used, | 2028 int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used, |
| 1990 Uint32List y_digits, int y_used, | 2029 Uint32List r_digits) { |
| 1991 Uint32List r_digits) { | 2030 var r_used = |
| 1992 var r_used = _Bigint._mulDigits(x_digits, x_used, | 2031 _Bigint._mulDigits(x_digits, x_used, y_digits, y_used, r_digits); |
| 1993 y_digits, y_used, | |
| 1994 r_digits); | |
| 1995 return _reduce(r_digits, r_used); | 2032 return _reduce(r_digits, r_used); |
| 1996 } | 2033 } |
| 1997 } | 2034 } |
| 1998 | 2035 |
| 1999 // Modular reduction using "classic" algorithm. | 2036 // Modular reduction using "classic" algorithm. |
| 2000 class _Classic implements _Reduction { | 2037 class _Classic implements _Reduction { |
| 2001 _Bigint _m; // Modulus. | 2038 _Bigint _m; // Modulus. |
| 2002 _Bigint _norm_m; // Normalized _m. | 2039 _Bigint _norm_m; // Normalized _m. |
| 2003 Uint32List _neg_norm_m_digits; // Negated _norm_m digits. | 2040 Uint32List _neg_norm_m_digits; // Negated _norm_m digits. |
| 2004 int _m_nsh; // Normalization shift amount. | 2041 int _m_nsh; // Normalization shift amount. |
| 2005 Uint32List _mt_qd; // Top _norm_m digit(s) and place holder for | 2042 Uint32List _mt_qd; // Top _norm_m digit(s) and place holder for |
| 2006 // estimated quotient digit(s). | 2043 // estimated quotient digit(s). |
| 2007 Uint32List _t_digits; // Temporary digits used during reduction. | 2044 Uint32List _t_digits; // Temporary digits used during reduction. |
| 2008 | 2045 |
| 2009 _Classic(int m) { | 2046 _Classic(int m) { |
| 2010 _m = m._toBigint(); | 2047 _m = m._toBigint(); |
| 2011 // Preprocess arguments to _remDigits. | 2048 // Preprocess arguments to _remDigits. |
| 2012 var nsh = _Bigint._DIGIT_BITS - _Bigint._nbits(_m._digits[_m._used - 1]); | 2049 var nsh = _Bigint._DIGIT_BITS - _Bigint._nbits(_m._digits[_m._used - 1]); |
| 2013 // For 64-bit processing, make sure _norm_m_digits has an even number of | 2050 // For 64-bit processing, make sure _norm_m_digits has an even number of |
| 2014 // digits. | 2051 // digits. |
| 2015 if (_m._used.isOdd) { | 2052 if (_m._used.isOdd) { |
| 2016 nsh += _Bigint._DIGIT_BITS; | 2053 nsh += _Bigint._DIGIT_BITS; |
| 2017 } | 2054 } |
| 2018 _m_nsh = nsh; | 2055 _m_nsh = nsh; |
| 2019 _norm_m = _m._lShift(nsh); | 2056 _norm_m = _m._lShift(nsh); |
| 2020 var nm_used = _norm_m._used; | 2057 var nm_used = _norm_m._used; |
| 2021 assert(nm_used.isEven); | 2058 assert(nm_used.isEven); |
| 2022 _mt_qd = new Uint32List(4); | 2059 _mt_qd = new Uint32List(4); |
| 2023 _mt_qd[_Bigint._YT_LO] = _norm_m._digits[nm_used - 2]; | 2060 _mt_qd[_Bigint._YT_LO] = _norm_m._digits[nm_used - 2]; |
| 2024 _mt_qd[_Bigint._YT] = _norm_m._digits[nm_used - 1]; | 2061 _mt_qd[_Bigint._YT] = _norm_m._digits[nm_used - 1]; |
| 2025 // Negate _norm_m so we can use _mulAdd instead of unimplemented _mulSub. | 2062 // Negate _norm_m so we can use _mulAdd instead of unimplemented _mulSub. |
| 2026 var neg_norm_m = _Bigint._ONE._dlShift(nm_used)._sub(_norm_m); | 2063 var neg_norm_m = _Bigint._ONE._dlShift(nm_used)._sub(_norm_m); |
| 2027 if (neg_norm_m._used < nm_used) { | 2064 if (neg_norm_m._used < nm_used) { |
| 2028 _neg_norm_m_digits = | 2065 _neg_norm_m_digits = |
| 2029 _Bigint._cloneDigits(neg_norm_m._digits, 0, nm_used, nm_used); | 2066 _Bigint._cloneDigits(neg_norm_m._digits, 0, nm_used, nm_used); |
| 2030 } else { | 2067 } else { |
| 2031 _neg_norm_m_digits = neg_norm_m._digits; | 2068 _neg_norm_m_digits = neg_norm_m._digits; |
| 2032 } | 2069 } |
| 2033 // _neg_norm_m_digits is read-only and has nm_used digits (possibly | 2070 // _neg_norm_m_digits is read-only and has nm_used digits (possibly |
| 2034 // including several leading zeros) plus a leading zero for 64-bit | 2071 // including several leading zeros) plus a leading zero for 64-bit |
| 2035 // processing. | 2072 // processing. |
| 2036 _t_digits = new Uint32List(2*nm_used); | 2073 _t_digits = new Uint32List(2 * nm_used); |
| 2037 } | 2074 } |
| 2038 | 2075 |
| 2039 int _convert(_Bigint x, Uint32List r_digits) { | 2076 int _convert(_Bigint x, Uint32List r_digits) { |
| 2040 var digits; | 2077 var digits; |
| 2041 var used; | 2078 var used; |
| 2042 if (x._neg || x._compare(_m) >= 0) { | 2079 if (x._neg || x._compare(_m) >= 0) { |
| 2043 var r = x._rem(_m); | 2080 var r = x._rem(_m); |
| 2044 if (x._neg && !r._neg && r._used > 0) { | 2081 if (x._neg && !r._neg && r._used > 0) { |
| 2045 r = _m._sub(r); | 2082 r = _m._sub(r); |
| 2046 } | 2083 } |
| 2047 assert(!r._neg); | 2084 assert(!r._neg); |
| 2048 used = r._used; | 2085 used = r._used; |
| 2049 digits = r._digits; | 2086 digits = r._digits; |
| 2050 } else { | 2087 } else { |
| 2051 used = x._used; | 2088 used = x._used; |
| 2052 digits = x._digits; | 2089 digits = x._digits; |
| 2053 } | 2090 } |
| 2054 var i = used + (used & 1); // Copy leading zero if any. | 2091 var i = used + (used & 1); // Copy leading zero if any. |
| 2055 while (--i >= 0) { | 2092 while (--i >= 0) { |
| 2056 r_digits[i] = digits[i]; | 2093 r_digits[i] = digits[i]; |
| 2057 } | 2094 } |
| 2058 return used; | 2095 return used; |
| 2059 } | 2096 } |
| 2060 | 2097 |
| 2061 _Bigint _revert(Uint32List x_digits, int x_used) { | 2098 _Bigint _revert(Uint32List x_digits, int x_used) { |
| 2062 return new _Bigint(false, x_used, x_digits); | 2099 return new _Bigint(false, x_used, x_digits); |
| 2063 } | 2100 } |
| 2064 | 2101 |
| 2065 int _reduce(Uint32List x_digits, int x_used) { | 2102 int _reduce(Uint32List x_digits, int x_used) { |
| 2066 if (x_used < _m._used) { | 2103 if (x_used < _m._used) { |
| 2067 return x_used; | 2104 return x_used; |
| 2068 } | 2105 } |
| 2069 // The function _remDigits(...) is optimized for reduction and equivalent to | 2106 // The function _remDigits(...) is optimized for reduction and equivalent to |
| 2070 // calling _convert(_revert(x_digits, x_used)._rem(_m), x_digits); | 2107 // calling _convert(_revert(x_digits, x_used)._rem(_m), x_digits); |
| 2071 return _Bigint._remDigits(x_digits, x_used, | 2108 return _Bigint._remDigits(x_digits, x_used, _norm_m._digits, _norm_m._used, |
| 2072 _norm_m._digits, _norm_m._used, | 2109 _neg_norm_m_digits, _m_nsh, _mt_qd, _t_digits, x_digits); |
| 2073 _neg_norm_m_digits, | |
| 2074 _m_nsh, | |
| 2075 _mt_qd, | |
| 2076 _t_digits, | |
| 2077 x_digits); | |
| 2078 } | 2110 } |
| 2079 | 2111 |
| 2080 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) { | 2112 int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) { |
| 2081 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits); | 2113 var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits); |
| 2082 return _reduce(r_digits, r_used); | 2114 return _reduce(r_digits, r_used); |
| 2083 } | 2115 } |
| 2084 | 2116 |
| 2085 int _mul(Uint32List x_digits, int x_used, | 2117 int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used, |
| 2086 Uint32List y_digits, int y_used, | 2118 Uint32List r_digits) { |
| 2087 Uint32List r_digits) { | 2119 var r_used = |
| 2088 var r_used = _Bigint._mulDigits(x_digits, x_used, | 2120 _Bigint._mulDigits(x_digits, x_used, y_digits, y_used, r_digits); |
| 2089 y_digits, y_used, | |
| 2090 r_digits); | |
| 2091 return _reduce(r_digits, r_used); | 2121 return _reduce(r_digits, r_used); |
| 2092 } | 2122 } |
| 2093 } | 2123 } |
| OLD | NEW |