 |
Changeset 4146
- Timestamp:
- 12/02/08 07:40:10
(1 hour ago)
- Author:
- Don Clugston
- Message:
BigInt? now uses BigDigit? internally, a stepping stone to using ulongs internally on 64-bit platforms.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
- Property svn:eol-style set to native
| r3900 |
r4146 |
|
| 17 | 17 | |
|---|
| 18 | 18 | public: |
|---|
| | 19 | alias uint BigDigit; // A Bignum is an array of BigDigits. |
|---|
| | 20 | |
|---|
| 19 | 21 | // Limits for when to switch between multiplication algorithms. |
|---|
| 20 | 22 | enum : int { KARATSUBALIMIT = 10 }; // Minimum value for which Karatsuba is worthwhile. |
|---|
- Property svn:eol-style set to native
| r4032 |
r4146 |
|
| 55 | 55 | */ |
|---|
| 56 | 56 | |
|---|
| 57 | | private: |
|---|
| 58 | 57 | version(GNU) { |
|---|
| 59 | 58 | // GDC is a filthy liar. It can't actually do inline asm. |
|---|
| 60 | 59 | } else version(D_InlineAsm_X86) { |
|---|
| | 60 | |
|---|
| | 61 | private: |
|---|
| | 62 | |
|---|
| 61 | 63 | /* Duplicate string s, with n times, substituting index for '@'. |
|---|
| 62 | 64 | * |
|---|
| … | … | |
| 88 | 90 | |
|---|
| 89 | 91 | public: |
|---|
| | 92 | |
|---|
| | 93 | alias uint BigDigit; // A Bignum is an array of BigDigits. Usually the machine word size. |
|---|
| 90 | 94 | |
|---|
| 91 | 95 | // Limits for when to switch between multiplication algorithms. |
|---|
| r4140 |
r4146 |
|
| 40 | 40 | const int FASTDIVLIMIT; // crossover to recursive division |
|---|
| 41 | 41 | |
|---|
| 42 | | const uint [] ZERO = [0]; |
|---|
| 43 | | const uint [] ONE = [1]; |
|---|
| 44 | | const uint [] TWO = [2]; |
|---|
| 45 | | const uint [] TEN = [10]; |
|---|
| | 42 | const BigDigit [] ZERO = [0]; |
|---|
| | 43 | const BigDigit [] ONE = [1]; |
|---|
| | 44 | const BigDigit [] TWO = [2]; |
|---|
| | 45 | const BigDigit [] TEN = [10]; |
|---|
| 46 | 46 | public: |
|---|
| 47 | 47 | |
|---|
| … | … | |
| 50 | 50 | private: |
|---|
| 51 | 51 | invariant() { assert(data.length==1 || data[$-1]!=0); } |
|---|
| 52 | | uint [] data = ZERO; |
|---|
| 53 | | public: |
|---|
| 54 | | static BigUint opCall(uint []x) { |
|---|
| | 52 | BigDigit [] data = ZERO; |
|---|
| | 53 | static BigUint opCall(BigDigit []x) { |
|---|
| 55 | 54 | BigUint a; |
|---|
| 56 | 55 | a.data=x; |
|---|
| 57 | 56 | return a; |
|---|
| 58 | 57 | } |
|---|
| | 58 | public: |
|---|
| 59 | 59 | void opAssign(uint u) { |
|---|
| 60 | 60 | if (u == 0) data = ZERO; |
|---|
| … | … | |
| 63 | 63 | else if (u == 10) data = TEN; |
|---|
| 64 | 64 | else { |
|---|
| 65 | | data = new uint[1]; |
|---|
| | 65 | data = new BigDigit[1]; |
|---|
| 66 | 66 | data[0] = u; |
|---|
| 67 | 67 | } |
|---|
| … | … | |
| 78 | 78 | |
|---|
| 79 | 79 | //return 1 if x>y, -1 if x<y, 0 if equal |
|---|
| 80 | | static int compare(BigUint x, uint y) |
|---|
| 81 | | { |
|---|
| 82 | | if (x.data.length!=1) return 1; |
|---|
| 83 | | if (x.data[0]==y) return 0; |
|---|
| 84 | | return x.data[0] > y ? 1: -1; |
|---|
| | 80 | static int compare(BigUint x, ulong y) |
|---|
| | 81 | { |
|---|
| | 82 | if (x.data.length>2) return 1; |
|---|
| | 83 | uint ylo = cast(uint)(y & 0xFFFF_FFFF); |
|---|
| | 84 | uint yhi = y>>32; |
|---|
| | 85 | if (x.data.length==2 && x.data[1]!=yhi) return x.data[1]>yhi ? 1: -1; |
|---|
| | 86 | if (x.data[0]==ylo) return 0; |
|---|
| | 87 | return x.data[0] > ylo ? 1: -1; |
|---|
| 85 | 88 | } |
|---|
| 86 | 89 | |
|---|
| … | … | |
| 92 | 95 | |
|---|
| 93 | 96 | int numBytes() { |
|---|
| 94 | | return data.length * uint.sizeof; |
|---|
| | 97 | return data.length * BigDigit.sizeof; |
|---|
| 95 | 98 | } |
|---|
| 96 | 99 | |
|---|
| … | … | |
| 125 | 128 | } |
|---|
| 126 | 129 | int len = (s.length - firstNonZero + 15)>>4; |
|---|
| 127 | | data = new uint[len+1]; |
|---|
| | 130 | data = new BigDigit[len+1]; |
|---|
| 128 | 131 | uint part = 0; |
|---|
| 129 | 132 | uint sofar = 0; |
|---|
| … | … | |
| 167 | 170 | } |
|---|
| 168 | 171 | uint predictlength = (18*2 + 2* (s.length-firstNonZero))/19; |
|---|
| 169 | | data = new uint[predictlength]; |
|---|
| | 172 | data = new BigDigit[predictlength]; |
|---|
| 170 | 173 | uint hi = biguintFromDecimal(data, s[firstNonZero..$]); |
|---|
| 171 | 174 | data.length = hi; |
|---|
| … | … | |
| 187 | 190 | return BigUint(x.data[words..$]); |
|---|
| 188 | 191 | } else { |
|---|
| 189 | | uint [] result = new uint[x.data.length - words]; |
|---|
| | 192 | uint [] result = new BigDigit[x.data.length - words]; |
|---|
| 190 | 193 | multibyteShr(result, x.data[words..$], bits); |
|---|
| 191 | 194 | if (result.length>1 && result[$-1]==0) return BigUint(result[0..$-1]); |
|---|
| … | … | |
| 202 | 205 | assert ((y>>5) < cast(ulong)(uint.max)); |
|---|
| 203 | 206 | uint words = cast(uint)(y >> 5); |
|---|
| 204 | | uint [] result = new uint[x.data.length + words+1]; |
|---|
| | 207 | BigDigit [] result = new BigDigit[x.data.length + words+1]; |
|---|
| 205 | 208 | result[0..words] = 0; |
|---|
| 206 | 209 | if (bits==0) { |
|---|
| … | … | |
| 236 | 239 | return r; |
|---|
| 237 | 240 | } |
|---|
| 238 | | r.data = new uint[ d > uint.max ? 2: 1]; |
|---|
| | 241 | r.data = new BigDigit[ d > uint.max ? 2: 1]; |
|---|
| 239 | 242 | r.data[0] = cast(uint)(d & 0xFFFF_FFFF); |
|---|
| 240 | 243 | if (d > uint.max) r.data[1] = cast(uint)(d>>32); |
|---|
| … | … | |
| 269 | 272 | uint hi = cast(uint)(y >>> 32); |
|---|
| 270 | 273 | uint lo = cast(uint)(y & 0xFFFF_FFFF); |
|---|
| 271 | | uint [] result = new uint[x.data.length+1+(hi!=0)]; |
|---|
| | 274 | uint [] result = new BigDigit[x.data.length+1+(hi!=0)]; |
|---|
| 272 | 275 | result[x.data.length] = multibyteMul(result[0..x.data.length], x.data, lo, 0); |
|---|
| 273 | 276 | if (hi!=0) { |
|---|
| … | … | |
| 287 | 290 | uint len = x.data.length + y.data.length; |
|---|
| 288 | 291 | BigUint r; |
|---|
| 289 | | r.data = new uint[len]; |
|---|
| | 292 | r.data = new BigDigit[len]; |
|---|
| 290 | 293 | if (y.data.length > x.data.length) { |
|---|
| 291 | 294 | mulInternal(r.data, y.data, x.data); |
|---|
| … | … | |
| 303 | 306 | // return x/y |
|---|
| 304 | 307 | static BigUint divInt(BigUint x, uint y) { |
|---|
| 305 | | uint [] result = new uint[x.data.length]; |
|---|
| | 308 | uint [] result = new BigDigit[x.data.length]; |
|---|
| 306 | 309 | if ((y&(-y))==y) { |
|---|
| 307 | 310 | assert(y!=0); |
|---|
| … | … | |
| 328 | 331 | } else { |
|---|
| 329 | 332 | // horribly inefficient - malloc, copy, & store are unnecessary. |
|---|
| 330 | | uint [] wasteful = new uint[x.data.length]; |
|---|
| | 333 | uint [] wasteful = new BigDigit[x.data.length]; |
|---|
| 331 | 334 | wasteful[] = x.data[]; |
|---|
| 332 | 335 | uint rem = multibyteDivAssign(wasteful, y, 0); |
|---|
| … | … | |
| 341 | 344 | if (y.data.length > x.data.length) return BigUint(ZERO); |
|---|
| 342 | 345 | if (y.data.length == 1) return divInt(x, y.data[0]); |
|---|
| 343 | | uint [] result = new uint[x.data.length - y.data.length + 1]; |
|---|
| | 346 | BigDigit [] result = new BigDigit[x.data.length - y.data.length + 1]; |
|---|
| 344 | 347 | divModInternal(result, null, x.data, y.data); |
|---|
| 345 | 348 | if (result.length>1 && result[$-1]==0) result=result[0..$-1]; |
|---|
| … | … | |
| 352 | 355 | if (y.data.length > x.data.length) return x; |
|---|
| 353 | 356 | if (y.data.length == 1) return divInt(x, y.data[0]); |
|---|
| 354 | | uint [] result = new uint[x.data.length - y.data.length + 1]; |
|---|
| 355 | | uint [] rem = new uint[y.data.length]; |
|---|
| | 357 | BigDigit [] result = new BigDigit[x.data.length - y.data.length + 1]; |
|---|
| | 358 | BigDigit [] rem = new BigDigit[y.data.length]; |
|---|
| 356 | 359 | divModInternal(result, rem, x.data, y.data); |
|---|
| 357 | 360 | while (rem.length>1 && rem[$-1]==0) rem = rem[0..$-1]; |
|---|
| … | … | |
| 367 | 370 | * Sets result = x - y. If the result is negative, negative will be true. |
|---|
| 368 | 371 | */ |
|---|
| 369 | | uint [] sub(uint[] x, uint[] y, bool *negative) |
|---|
| | 372 | BigDigit [] sub(BigDigit[] x, BigDigit[] y, bool *negative) |
|---|
| 370 | 373 | { |
|---|
| 371 | 374 | if (x.length == y.length) { |
|---|
| 372 | 375 | // There's a possibility of cancellation, if x and y are almost equal. |
|---|
| 373 | 376 | int last = highestDifferentDigit(x, y); |
|---|
| 374 | | uint [] result = new uint[last+1]; |
|---|
| | 377 | BigDigit [] result = new BigDigit[last+1]; |
|---|
| 375 | 378 | if (x[last] < y[last]) { // we know result is negative |
|---|
| 376 | 379 | multibyteAddSub!('-')(result[0..last+1], y[0..last+1], x[0..last+1], 0); |
|---|
| … | … | |
| 384 | 387 | } |
|---|
| 385 | 388 | // Lengths are different |
|---|
| 386 | | uint [] large, small; |
|---|
| | 389 | BigDigit [] large, small; |
|---|
| 387 | 390 | if (x.length < y.length) { |
|---|
| 388 | 391 | *negative = true; |
|---|
| … | … | |
| 394 | 397 | // result.length will be equal to larger length, or could decrease by 1. |
|---|
| 395 | 398 | |
|---|
| 396 | | uint [] result = new uint[large.length]; |
|---|
| 397 | | uint carry = multibyteAddSub!('-')(result[0..small.length], large[0..small.length], small, 0); |
|---|
| | 399 | BigDigit [] result = new BigDigit[large.length]; |
|---|
| | 400 | BigDigit carry = multibyteAddSub!('-')(result[0..small.length], large[0..small.length], small, 0); |
|---|
| 398 | 401 | result[small.length..$] = large[small.length..$]; |
|---|
| 399 | 402 | if (carry) { |
|---|
| … | … | |
| 405 | 408 | |
|---|
| 406 | 409 | // return a + b |
|---|
| 407 | | uint [] add(uint[] a, uint [] b) { |
|---|
| 408 | | uint [] x, y; |
|---|
| | 410 | BigDigit [] add(BigDigit[] a, BigDigit [] b) { |
|---|
| | 411 | BigDigit [] x, y; |
|---|
| 409 | 412 | if (a.length<b.length) { x = b; y = a; } else { x = a; y = b; } |
|---|
| 410 | 413 | // now we know x.length > y.length |
|---|
| 411 | 414 | // create result. add 1 in case it overflows |
|---|
| 412 | | uint [] result = new uint[x.length + 1]; |
|---|
| 413 | | |
|---|
| 414 | | uint carry = multibyteAddSub!('+')(result[0..y.length], x[0..y.length], y, 0); |
|---|
| | 415 | BigDigit [] result = new BigDigit[x.length + 1]; |
|---|
| | 416 | |
|---|
| | 417 | BigDigit carry = multibyteAddSub!('+')(result[0..y.length], x[0..y.length], y, 0); |
|---|
| 415 | 418 | if (x.length != y.length){ |
|---|
| 416 | 419 | result[y.length..$-1]= x[y.length..$]; |
|---|
| … | … | |
| 425 | 428 | /** return x + y |
|---|
| 426 | 429 | */ |
|---|
| 427 | | uint [] addInt(uint[] x, ulong y) |
|---|
| | 430 | BigDigit [] addInt(BigDigit[] x, ulong y) |
|---|
| 428 | 431 | { |
|---|
| 429 | 432 | uint hi = cast(uint)(y >>> 32); |
|---|
| … | … | |
| 431 | 434 | uint len = x.length; |
|---|
| 432 | 435 | if (x.length < 2 && hi!=0) ++len; |
|---|
| 433 | | uint [] result = new uint[len+1]; |
|---|
| | 436 | BigDigit [] result = new BigDigit[len+1]; |
|---|
| 434 | 437 | result[0..x.length] = x[]; |
|---|
| 435 | 438 | if (x.length < 2 && hi!=0) { result[1]=hi; hi=0; } |
|---|
| … | … | |
| 445 | 448 | * x must be greater than y. |
|---|
| 446 | 449 | */ |
|---|
| 447 | | uint [] subInt(uint[] x, ulong y) |
|---|
| | 450 | BigDigit [] subInt(BigDigit[] x, ulong y) |
|---|
| 448 | 451 | { |
|---|
| 449 | 452 | uint hi = cast(uint)(y >>> 32); |
|---|
| 450 | 453 | uint lo = cast(uint)(y& 0xFFFF_FFFF); |
|---|
| 451 | | uint [] result = new uint[x.length]; |
|---|
| | 454 | BigDigit [] result = new BigDigit[x.length]; |
|---|
| 452 | 455 | result[] = x[]; |
|---|
| 453 | 456 | multibyteIncrementAssign!('-')(result[], lo); |
|---|
| … | … | |
| 464 | 467 | * |
|---|
| 465 | 468 | */ |
|---|
| 466 | | void mulInternal(uint[] result, uint[] x, uint[] y) |
|---|
| | 469 | void mulInternal(BigDigit[] result, BigDigit[] x, BigDigit[] y) |
|---|
| 467 | 470 | { |
|---|
| 468 | 471 | assert( result.length == x.length + y.length ); |
|---|
| … | … | |
| 491 | 494 | // result[done .. done+ylength] already has a value. |
|---|
| 492 | 495 | chunksize = (done + (CACHELIMIT/y.length) < x.length) ? (CACHELIMIT/y.length) : x.length - done; |
|---|
| 493 | | uint [KARATSUBALIMIT] partial; |
|---|
| | 496 | BigDigit [KARATSUBALIMIT] partial; |
|---|
| 494 | 497 | partial[0..y.length] = result[done..done+y.length]; |
|---|
| 495 | 498 | mulSimple(result[done..done+chunksize+y.length], x[done..done+chunksize], y); |
|---|
| … | … | |
| 536 | 539 | } |
|---|
| 537 | 540 | // We make the buffer a bit bigger so we have space for the partial sums. |
|---|
| 538 | | uint [] scratchbuff = new uint[karatsubaRequiredBuffSize(maxchunk) + y.length]; |
|---|
| 539 | | uint [] partial = scratchbuff[$ - y.length .. $]; |
|---|
| | 541 | BigDigit [] scratchbuff = new BigDigit[karatsubaRequiredBuffSize(maxchunk) + y.length]; |
|---|
| | 542 | BigDigit [] partial = scratchbuff[$ - y.length .. $]; |
|---|
| 540 | 543 | uint done; // how much of X have we done so far? |
|---|
| 541 | 544 | double residual = 0; |
|---|
| … | … | |
| 564 | 567 | } else { |
|---|
| 565 | 568 | // Balanced. Use Karatsuba directly. |
|---|
| 566 | | uint [] scratchbuff = new uint[karatsubaRequiredBuffSize(x.length)]; |
|---|
| | 569 | BigDigit [] scratchbuff = new BigDigit[karatsubaRequiredBuffSize(x.length)]; |
|---|
| 567 | 570 | mulKaratsuba(result, x, y, scratchbuff); |
|---|
| 568 | 571 | delete scratchbuff; |
|---|
| … | … | |
| 573 | 576 | import tango.core.BitManip : bsr; |
|---|
| 574 | 577 | |
|---|
| 575 | | void divModInternal(uint [] quotient, uint[] remainder, uint [] u, uint [] v) |
|---|
| | 578 | void divModInternal(BigDigit [] quotient, BigDigit[] remainder, BigDigit [] u, BigDigit [] v) |
|---|
| 576 | 579 | { |
|---|
| 577 | 580 | assert(quotient.length == u.length - v.length + 1); |
|---|
| … | … | |
| 584 | 587 | // same amount. |
|---|
| 585 | 588 | |
|---|
| 586 | | uint [] vn = new uint[v.length]; |
|---|
| 587 | | uint [] un = new uint[u.length + 1]; |
|---|
| | 589 | BigDigit [] vn = new BigDigit[v.length]; |
|---|
| | 590 | BigDigit [] un = new BigDigit[u.length + 1]; |
|---|
| 588 | 591 | // How much to left shift v, so that its MSB is set. |
|---|
| 589 | 592 | uint s = 31 - bsr(v[$-1]); |
|---|
| … | … | |
| 631 | 634 | // buff.length must be data.length*8 if separator is zero, |
|---|
| 632 | 635 | // or data.length*9 if separator is non-zero. It will be completely filled. |
|---|
| 633 | | char [] biguintToHex(char [] buff, uint [] data, char separator=0) |
|---|
| | 636 | char [] biguintToHex(char [] buff, BigDigit [] data, char separator=0) |
|---|
| 634 | 637 | { |
|---|
| 635 | 638 | int x=0; |
|---|
| … | … | |
| 657 | 660 | * the lowest index of buff which was used. |
|---|
| 658 | 661 | */ |
|---|
| 659 | | int biguintToDecimal(char [] buff, uint [] data){ |
|---|
| | 662 | int biguintToDecimal(char [] buff, BigDigit [] data){ |
|---|
| 660 | 663 | int sofar = buff.length; |
|---|
| 661 | 664 | // Might be better to divide by (10^38/2^32) since that gives 38 digits for |
|---|
| … | … | |
| 690 | 693 | * the highest index of data which was used. |
|---|
| 691 | 694 | */ |
|---|
| 692 | | int biguintFromDecimal(uint [] data, char [] s) { |
|---|
| | 695 | int biguintFromDecimal(BigDigit [] data, char [] s) { |
|---|
| 693 | 696 | // Convert to base 1e19 = 10_000_000_000_000_000_000. |
|---|
| 694 | 697 | // (this is the largest power of 10 that will fit into a long). |
|---|
| … | … | |
| 775 | 778 | |
|---|
| 776 | 779 | // Classic 'schoolbook' multiplication. |
|---|
| 777 | | void mulSimple(uint[] result, uint [] left, uint[] right) |
|---|
| | 780 | void mulSimple(BigDigit[] result, BigDigit [] left, BigDigit[] right) |
|---|
| 778 | 781 | in { |
|---|
| 779 | 782 | assert(result.length == left.length + right.length); |
|---|
| … | … | |
| 788 | 791 | // add two uints of possibly different lengths. Result must be as long |
|---|
| 789 | 792 | // as the larger length. |
|---|
| 790 | | uint addSimple(uint [] result, uint [] left, uint [] right) |
|---|
| | 793 | // Returns carry (0 or 1). |
|---|
| | 794 | uint addSimple(BigDigit [] result, BigDigit [] left, BigDigit [] right) |
|---|
| 791 | 795 | in { |
|---|
| 792 | 796 | assert(result.length == left.length); |
|---|
| … | … | |
| 804 | 808 | } |
|---|
| 805 | 809 | |
|---|
| 806 | | uint subSimple(uint [] result, uint [] left, uint [] right) |
|---|
| | 810 | // result = left - right |
|---|
| | 811 | // returns carry (0 or 1) |
|---|
| | 812 | uint subSimple(BigDigit [] result, BigDigit [] left, BigDigit [] right) |
|---|
| 807 | 813 | in { |
|---|
| 808 | 814 | assert(result.length == left.length); |
|---|
| … | … | |
| 821 | 827 | |
|---|
| 822 | 828 | |
|---|
| 823 | | /* Returns carry if result was less than right. |
|---|
| | 829 | /* result = result - right |
|---|
| | 830 | * Returns carry = 1 if result was less than right. |
|---|
| 824 | 831 | */ |
|---|
| 825 | | uint simpleSubAssign(uint [] result, uint [] right) |
|---|
| | 832 | uint simpleSubAssign(BigDigit [] result, BigDigit [] right) |
|---|
| 826 | 833 | { |
|---|
| 827 | 834 | assert(result.length >= right.length); |
|---|
| … | … | |
| 832 | 839 | |
|---|
| 833 | 840 | |
|---|
| 834 | | void simpleAddAssign(uint [] result, uint [] right) |
|---|
| | 841 | void simpleAddAssign(BigDigit [] result, BigDigit [] right) |
|---|
| 835 | 842 | { |
|---|
| 836 | 843 | assert(result.length >= right.length); |
|---|
| … | … | |
| 861 | 868 | * scratchbuff An array long enough to store all the temporaries. Will be destroyed. |
|---|
| 862 | 869 | */ |
|---|
| 863 | | void mulKaratsuba(uint [] result, uint [] x, uint[] y, uint [] scratchbuff) |
|---|
| | 870 | void mulKaratsuba(BigDigit [] result, BigDigit [] x, BigDigit[] y, BigDigit [] scratchbuff) |
|---|
| 864 | 871 | { |
|---|
| 865 | 872 | assert(x.length >= y.length); |
|---|
| … | … | |
| 945 | 952 | * u[0..v.length] holds the remainder. |
|---|
| 946 | 953 | */ |
|---|
| 947 | | void schoolbookDivMod(uint [] quotient, uint [] u, in uint [] v) |
|---|
| | 954 | void schoolbookDivMod(BigDigit [] quotient, BigDigit [] u, in BigDigit [] v) |
|---|
| 948 | 955 | { |
|---|
| 949 | 956 | assert(quotient.length == u.length - v.length); |
|---|
| … | … | |
| 951 | 958 | assert(u.length >= v.length); |
|---|
| 952 | 959 | assert((v[$-1]&0x8000_0000)!=0); |
|---|
| 953 | | |
|---|
| | 960 | uint vhi = v[$-1]; |
|---|
| | 961 | |
|---|
| 954 | 962 | for (int j = u.length - v.length-1; j >= 0; j--) { |
|---|
| 955 | 963 | // Compute estimate qhat of quotient[j]. |
|---|
| 956 | | ulong bigqhat, rhat; |
|---|
| 957 | | bigqhat = ( (cast(ulong)(u[j+v.length]) << 32) + u[j+v.length-1]) |
|---|
| 958 | | / v[$-1]; |
|---|
| 959 | | rhat = ((cast(ulong)(u[j+v.length]) << 32) + u[j+v.length-1]) |
|---|
| 960 | | - bigqhat * v[$-1]; |
|---|
| | 964 | ulong uu = (cast(ulong)(u[j+v.length]) << 32) | u[j+v.length-1]; |
|---|
| | 965 | ulong bigqhat = uu / vhi; |
|---|
| | 966 | ulong rhat = uu - bigqhat * vhi; |
|---|
| 961 | 967 | again: |
|---|
| 962 | 968 | if ((bigqhat & 0xFFFF_FFFF_0000_0000L) |
|---|
| 963 | 969 | || bigqhat*v[$-2] > ((rhat<<32) + u[j+v.length-2])) { |
|---|
| 964 | 970 | --bigqhat; |
|---|
| 965 | | rhat += v[$-1]; |
|---|
| | 971 | rhat += vhi; |
|---|
| 966 | 972 | if (rhat < 0x1_0000_0000L) goto again; |
|---|
| 967 | 973 | } |
|---|
| … | … | |
| 1003 | 1009 | // Returns the highest value of i for which left[i]!=right[i], |
|---|
| 1004 | 1010 | // or 0 if left[]==right[] |
|---|
| 1005 | | int highestDifferentDigit(uint [] left, uint [] right) |
|---|
| | 1011 | int highestDifferentDigit(BigDigit [] left, BigDigit [] right) |
|---|
| 1006 | 1012 | { |
|---|
| 1007 | 1013 | assert(left.length == right.length); |
|---|
| … | … | |
| 1024 | 1030 | scratch is temporary storage space, must be at least as long as quotient. |
|---|
| 1025 | 1031 | */ |
|---|
| 1026 | | void recursiveDivMod(uint[] quotient, uint[] u, in uint[] v, |
|---|
| 1027 | | uint[] scratch) |
|---|
| | 1032 | void recursiveDivMod(BigDigit[] quotient, BigDigit[] u, in BigDigit[] v, |
|---|
| | 1033 | BigDigit[] scratch) |
|---|
| 1028 | 1034 | in { |
|---|
| 1029 | 1035 | assert(quotient.length == u.length - v.length); |
|---|
| … | … | |
| 1052 | 1058 | // If would make rem negative, decrease quot until rem is >=0. |
|---|
| 1053 | 1059 | // Needs (quot.length * k) scratch space to store the result of the multiply. |
|---|
| 1054 | | void adjustRemainder(uint[] quot, uint[] rem, in uint[] v, int k, |
|---|
| 1055 | | uint[] scratch) { |
|---|
| | 1060 | void adjustRemainder(BigDigit[] quot, BigDigit[] rem, in BigDigit[] v, int k, |
|---|
| | 1061 | BigDigit[] scratch) |
|---|
| | 1062 | { |
|---|
| 1056 | 1063 | assert(rem.length == v.length); |
|---|
| 1057 | 1064 | mulInternal(scratch, quot, v[0 .. k]); |
|---|
| … | … | |
| 1063 | 1070 | } |
|---|
| 1064 | 1071 | |
|---|
| 1065 | | void fastDivMod(uint [] quotient, uint [] u, in uint [] v) |
|---|
| | 1072 | void fastDivMod(BigDigit [] quotient, BigDigit [] u, in BigDigit [] v) |
|---|
| 1066 | 1073 | { |
|---|
| 1067 | 1074 | assert(quotient.length == u.length - v.length); |
|---|
| … | … | |
| 1069 | 1076 | assert(u.length >= v.length); |
|---|
| 1070 | 1077 | assert((v[$-1] & 0x8000_0000)!=0); |
|---|
| 1071 | | uint [] scratch = new uint[v.length]; |
|---|
| | 1078 | BigDigit [] scratch = new BigDigit[v.length]; |
|---|
| 1072 | 1079 | |
|---|
| 1073 | 1080 | // Perform block schoolbook division, with 'v.length' blocks. |
|---|
Download in other formats:
|
 |