Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Changeset 3877

Show
Ignore:
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
  • trunk/tango/math/internal/BignumX86.d

    r3831 r3877  
    8484// Limits for when to switch between multiplication algorithms. 
    8585enum : int { KARATSUBALIMIT = 18 }; // Minimum value for which Karatsuba is worthwhile. 
    86  
    8786     
    8887/** Multi-byte addition or subtraction 
     
    828827        dec     EAX; 
    829828        ror     EAX, CL ; //ecx bits at msb 
    830         push    EAX; 
    831          
     829        push    EAX; // MASK         
    832830         
    833831        // Then divide 2^(32+cx) by divisor (edx already ok) 
  • trunk/tango/math/internal/BiguintCore.d

    r3876 r3877  
    162162 *  Sets result = x - y. If the result is negative, negative will be true. 
    163163 */ 
    164 uint [] biguintSubtract(uint[] x, uint[] y, bool *negative) 
     164uint [] biguintSub(uint[] x, uint[] y, bool *negative) 
    165165{ 
    166166    if (x.length == y.length) { 
     
    252252} 
    253253 
     254/** return x*y. 
     255 *  y must not be zero. 
     256 */ 
     257uint [] 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 
    254269/** General unsigned multiply routine for bigints. 
    255270 *  Sets result = x*y. 
     
    270285            return; 
    271286        } 
    272         if (x.length * y.length < CACHELIMIT) return mulSimple(result, x, y); 
     287        if (x.length + y.length < CACHELIMIT) return mulSimple(result, x, y); 
    273288         
    274289        // If x is so big that it won't fit into the cache, we divide it into chunks             
     
    472487* x must be longer or equal to y. 
    473488* 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) 
    475491* Params: 
    476492* scratchbuff      An array long enough to store all the temporaries. Will be destroyed. 
     
    491507    // requiring 3 multiplies of length N, instead of 4. 
    492508     
    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. 
    497509 
    498510    // half length, round up. 
     
    510522    uint [] resultHigh = result[x0.length + y0.length .. $]; 
    511523         
     524     
    512525    // Add the high and low parts of x and y. 
    513526    // 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. 
    514531    uint carry_x = addSimple(xsum, x0, x1); 
    515532    uint carry_y = addSimple(ysum, y0, y1); 
     
    519536    if (carry_x)  simpleAddAssign(mid[half..$], ysum); 
    520537    if (carry_y)  simpleAddAssign(mid[half..$], xsum); 
    521      
     538         
    522539    // Low half of result gets x0 * y0. High half gets x1 * y1 
    523540    
     
    533550        } else { 
    534551            // 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. 
    536552            uint quarter = (x1.length >> 1) + (x1.length & 1); 
    537553            bool ysmaller = (quarter >= y1.length); 
     
    582598    return 0; 
    583599} 
    584