 |
Changeset 3877
- Timestamp:
- 08/14/08 02:58:10
(3 months ago)
- Author:
- Don Clugston
- Message:
Added biguintMulInt. Improved comments.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r3831 |
r3877 |
|
| 84 | 84 | // Limits for when to switch between multiplication algorithms. |
|---|
| 85 | 85 | enum : int { KARATSUBALIMIT = 18 }; // Minimum value for which Karatsuba is worthwhile. |
|---|
| 86 | | |
|---|
| 87 | 86 | |
|---|
| 88 | 87 | /** Multi-byte addition or subtraction |
|---|
| … | … | |
| 828 | 827 | dec EAX; |
|---|
| 829 | 828 | ror EAX, CL ; //ecx bits at msb |
|---|
| 830 | | push EAX; |
|---|
| 831 | | |
|---|
| | 829 | push EAX; // MASK |
|---|
| 832 | 830 | |
|---|
| 833 | 831 | // Then divide 2^(32+cx) by divisor (edx already ok) |
|---|
| r3876 |
r3877 |
|
| 162 | 162 | * Sets result = x - y. If the result is negative, negative will be true. |
|---|
| 163 | 163 | */ |
|---|
| 164 | | uint [] biguintSubtract(uint[] x, uint[] y, bool *negative) |
|---|
| | 164 | uint [] biguintSub(uint[] x, uint[] y, bool *negative) |
|---|
| 165 | 165 | { |
|---|
| 166 | 166 | if (x.length == y.length) { |
|---|
| … | … | |
| 252 | 252 | } |
|---|
| 253 | 253 | |
|---|
| | 254 | /** return x*y. |
|---|
| | 255 | * y must not be zero. |
|---|
| | 256 | */ |
|---|
| | 257 | uint [] biguintMulInt(uint [] x, ulong y) |
|---|
| | 258 | { |
|---|
| | 259 | uint hi = cast(uint)(y >>> 32); |
|---|
| | 260 | uint lo = cast(uint)(y & 0xFFFF_FFFF); |
|---|
| | 261 | uint [] result = new uint[x.length+1+(hi!=0)]; |
|---|
| | 262 | result[x.length] = multibyteMul(result[0..x.length], x, lo, 0); |
|---|
| | 263 | if (hi!=0) { |
|---|
| | 264 | result[x.length+1] = multibyteMulAdd(result[1..x.length+1], x, hi, 0); |
|---|
| | 265 | } |
|---|
| | 266 | return result; |
|---|
| | 267 | } |
|---|
| | 268 | |
|---|
| 254 | 269 | /** General unsigned multiply routine for bigints. |
|---|
| 255 | 270 | * Sets result = x*y. |
|---|
| … | … | |
| 270 | 285 | return; |
|---|
| 271 | 286 | } |
|---|
| 272 | | if (x.length * y.length < CACHELIMIT) return mulSimple(result, x, y); |
|---|
| | 287 | if (x.length + y.length < CACHELIMIT) return mulSimple(result, x, y); |
|---|
| 273 | 288 | |
|---|
| 274 | 289 | // If x is so big that it won't fit into the cache, we divide it into chunks |
|---|
| … | … | |
| 472 | 487 | * x must be longer or equal to y. |
|---|
| 473 | 488 | * Valid only for balanced multiplies, where x is not shorter than y. |
|---|
| 474 | | * It is efficient only if sqrt(2)*y.length > x.length >= y.length |
|---|
| | 489 | * It is efficient only if sqrt(2)*y.length > x.length >= y.length. |
|---|
| | 490 | * Karatsuba multiplication is O(n^1.59), whereas schoolbook is O(n^2) |
|---|
| 475 | 491 | * Params: |
|---|
| 476 | 492 | * scratchbuff An array long enough to store all the temporaries. Will be destroyed. |
|---|
| … | … | |
| 491 | 507 | // requiring 3 multiplies of length N, instead of 4. |
|---|
| 492 | 508 | |
|---|
| 493 | | // TODO: Knuth's variant is superior: |
|---|
| 494 | | // (Nx1 + x0)*(Ny1 + y0) = (N*N) x1y1 + x0y0 - N * mid |
|---|
| 495 | | // where mid = (x0-x1)*(y0-y1) - x1y1 - x0y0 |
|---|
| 496 | | // since then the lengths cannot exceed length N. |
|---|
| 497 | 509 | |
|---|
| 498 | 510 | // half length, round up. |
|---|
| … | … | |
| 510 | 522 | uint [] resultHigh = result[x0.length + y0.length .. $]; |
|---|
| 511 | 523 | |
|---|
| | 524 | |
|---|
| 512 | 525 | // Add the high and low parts of x and y. |
|---|
| 513 | 526 | // This will generate carries of either 0 or 1. |
|---|
| | 527 | // TODO: Knuth's variant would save the extra two additions: |
|---|
| | 528 | // (Nx1 + x0)*(Ny1 + y0) = (N*N) x1y1 + x0y0 - N * mid |
|---|
| | 529 | // where mid = (x0-x1)*(y0-y1) - x1y1 - x0y0 |
|---|
| | 530 | // since then the lengths cannot exceed length N. |
|---|
| 514 | 531 | uint carry_x = addSimple(xsum, x0, x1); |
|---|
| 515 | 532 | uint carry_y = addSimple(ysum, y0, y1); |
|---|
| … | … | |
| 519 | 536 | if (carry_x) simpleAddAssign(mid[half..$], ysum); |
|---|
| 520 | 537 | if (carry_y) simpleAddAssign(mid[half..$], xsum); |
|---|
| 521 | | |
|---|
| | 538 | |
|---|
| 522 | 539 | // Low half of result gets x0 * y0. High half gets x1 * y1 |
|---|
| 523 | 540 | |
|---|
| … | … | |
| 533 | 550 | } else { |
|---|
| 534 | 551 | // divide x1 in two, then use schoolbook multiply on the two pieces. |
|---|
| 535 | | // Note that this will be smaller than y1, except when x1 = 2*y1 + 1. |
|---|
| 536 | 552 | uint quarter = (x1.length >> 1) + (x1.length & 1); |
|---|
| 537 | 553 | bool ysmaller = (quarter >= y1.length); |
|---|
| … | … | |
| 582 | 598 | return 0; |
|---|
| 583 | 599 | } |
|---|
| 584 | | |
|---|
Download in other formats:
|
 |
 |
|
 |
Copyright © 2006-2008 Tango. All Rights Reserved. | Page Width:
Static or
Dynamic