⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 biginteger.java

📁 java源代码 请看看啊 提点宝贵的意见
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
     * after a suitable number of squarings have passed (e.g. a pattern     * of "100" in the buffer requires that we multiply by n^1 immediately;     * a pattern of "110" calls for multiplying by n^3 after one more     * squaring), clear the buffer, and continue.     *     * When we start, there is one more optimization: the result buffer     * is implcitly one, so squaring it or multiplying by it can be     * optimized away.  Further, if we start with a pattern like "100"     * in the lookahead window, rather than placing n into the buffer     * and then starting to square it, we have already computed n^2     * to compute the odd-powers table, so we can place that into     * the buffer and save a squaring.     *     * This means that if you have a k-bit window, to compute n^z,     * where z is the high k bits of the exponent, 1/2 of the time     * it requires no squarings.  1/4 of the time, it requires 1     * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings.     * And the remaining 1/2^(k-1) of the time, the top k bits are a     * 1 followed by k-1 0 bits, so it again only requires k-2     * squarings, not k-1.  The average of these is 1.  Add that     * to the one squaring we have to do to compute the table,     * and you'll see that a k-bit window saves k-2 squarings     * as well as reducing the multiplies.  (It actually doesn't     * hurt in the case k = 1, either.)     */        // Special case for exponent of one        if (y.equals(ONE))            return this;        // Special case for base of zero        if (signum==0)            return ZERO;        int[] base = (int[])mag.clone();        int[] exp = y.mag;        int[] mod = z.mag;        int modLen = mod.length;        // Select an appropriate window size        int wbits = 0;        int ebits = bitLength(exp, exp.length);        while (ebits > bnExpModThreshTable[wbits])            wbits++;        // Calculate appropriate table size        int tblmask = 1 << wbits;                // Allocate table for precomputed odd powers of base in Montgomery form        int[][] table = new int[tblmask][];        for (int i=0; i<tblmask; i++)            table[i] = new int[modLen];        // Compute the modular inverse        int inv = -MutableBigInteger.inverseMod32(mod[modLen-1]);        // Convert base to Montgomery form        int[] a = leftShift(base, base.length, modLen << 5);        MutableBigInteger q = new MutableBigInteger(),                          r = new MutableBigInteger(),                          a2 = new MutableBigInteger(a),                          b2 = new MutableBigInteger(mod);        a2.divide(b2, q, r);        table[0] = r.toIntArray();        // Pad table[0] with leading zeros so its length is at least modLen        if (table[0].length < modLen) {           int offset = modLen - table[0].length;           int[] t2 = new int[modLen];           for (int i=0; i<table[0].length; i++)               t2[i+offset] = table[0][i];           table[0] = t2;        }        // Set b to the square of the base        int[] b = squareToLen(table[0], modLen, null);        b = montReduce(b, mod, modLen, inv);        // Set t to high half of b        int[] t = new int[modLen];        for(int i=0; i<modLen; i++)            t[i] = b[i];        // Fill in the table with odd powers of the base                for (int i=1; i<tblmask; i++) {            int[] prod = multiplyToLen(t, modLen, table[i-1], modLen, null);            table[i] = montReduce(prod, mod, modLen, inv);        }        // Pre load the window that slides over the exponent        int bitpos = 1 << ((ebits-1) & (32-1));                int buf = 0;        int elen = exp.length;        int eIndex = 0;	for (int i = 0; i <= wbits; i++) {            buf = (buf << 1) | (((exp[eIndex] & bitpos) != 0)?1:0);            bitpos >>>= 1;            if (bitpos == 0) {                eIndex++;                bitpos = 1 << (32-1);                elen--;            }	}        int multpos = ebits;        // The first iteration, which is hoisted out of the main loop        ebits--;        boolean isone = true;	multpos = ebits - wbits;	while ((buf & 1) == 0) {            buf >>>= 1;            multpos++;	}	int[] mult = table[buf >>> 1];	buf = 0;        if (multpos == ebits)	    isone = false;        // The main loop        while(true) {            ebits--;            // Advance the window            buf <<= 1;            if (elen != 0) {                buf |= ((exp[eIndex] & bitpos) != 0) ? 1 : 0;                bitpos >>>= 1;                if (bitpos == 0) {                    eIndex++;                    bitpos = 1 << (32-1);                    elen--;                }            }            // Examine the window for pending multiplies            if ((buf & tblmask) != 0) {                multpos = ebits - wbits;                while ((buf & 1) == 0) {                    buf >>>= 1;                    multpos++;                }                mult = table[buf >>> 1];                buf = 0;            }            // Perform multiply            if (ebits == multpos) {                if (isone) {                    b = (int[])mult.clone();                    isone = false;                } else {                    t = b;                    a = multiplyToLen(t, modLen, mult, modLen, a);                    a = montReduce(a, mod, modLen, inv);                    t = a; a = b; b = t;                }            }            // Check if done            if (ebits == 0)                break;            // Square the input            if (!isone) {                t = b;                a = squareToLen(t, modLen, a);                a = montReduce(a, mod, modLen, inv);                t = a; a = b; b = t;            }	}        // Convert result out of Montgomery form and return        int[] t2 = new int[2*modLen];        for(int i=0; i<modLen; i++)            t2[i+modLen] = b[i];        b = montReduce(t2, mod, modLen, inv);        t2 = new int[modLen];        for(int i=0; i<modLen; i++)            t2[i] = b[i];                   return new BigInteger(1, t2);    }    /**     * Montgomery reduce n, modulo mod.  This reduces modulo mod and divides     * by 2^(32*mlen). Adapted from Colin Plumb's C library.     */    private static int[] montReduce(int[] n, int[] mod, int mlen, int inv) {        int c=0;        int len = mlen;        int offset=0;        do {            int nEnd = n[n.length-1-offset];            int carry = mulAdd(n, mod, offset, mlen, inv * nEnd);            c += addOne(n, offset, mlen, carry);            offset++;        } while(--len > 0);                while(c>0)            c += subN(n, mod, mlen);        while (intArrayCmpToLen(n, mod, mlen) >= 0)            subN(n, mod, mlen);        return n;    }    /*     * Returns -1, 0 or +1 as big-endian unsigned int array arg1 is less than,     * equal to, or greater than arg2 up to length len.     */    private static int intArrayCmpToLen(int[] arg1, int[] arg2, int len) {	for (int i=0; i<len; i++) {	    long b1 = arg1[i] & LONG_MASK;	    long b2 = arg2[i] & LONG_MASK;	    if (b1 < b2)		return -1;	    if (b1 > b2)		return 1;	}	return 0;    }    /**     * Subtracts two numbers of same length, returning borrow.     */    private static int subN(int[] a, int[] b, int len) {        long sum = 0;        while(--len >= 0) {            sum = (a[len] & LONG_MASK) -                  (b[len] & LONG_MASK) + (sum >> 32);            a[len] = (int)sum;        }        return (int)(sum >> 32);    }    /**     * Multiply an array by one word k and add to result, return the carry     */    static int mulAdd(int[] out, int[] in, int offset, int len, int k) {        long kLong = k & LONG_MASK;        long carry = 0;        offset = out.length-offset - 1;        for (int j=len-1; j >= 0; j--) {            long product = (in[j] & LONG_MASK) * kLong +                           (out[offset] & LONG_MASK) + carry;            out[offset--] = (int)product;            carry = product >>> 32;        }        return (int)carry;    }    /**     * Add one word to the number a mlen words into a. Return the resulting     * carry.     */    static int addOne(int[] a, int offset, int mlen, int carry) {        offset = a.length-1-mlen-offset;        long t = (a[offset] & LONG_MASK) + (carry & LONG_MASK);                a[offset] = (int)t;        if ((t >>> 32) == 0)            return 0;        while (--mlen >= 0) {            if (--offset < 0) { // Carry out of number                return 1;            } else {                a[offset]++;                if (a[offset] != 0)                    return 0;            }        }        return 1;    }    /**     * Returns a BigInteger whose value is (this ** exponent) mod (2**p)     */    private BigInteger modPow2(BigInteger exponent, int p) {	/*	 * Perform exponentiation using repeated squaring trick, chopping off	 * high order bits as indicated by modulus.	 */	BigInteger result = valueOf(1);	BigInteger baseToPow2 = this.mod2(p);        int expOffset = 0;        int limit = exponent.bitLength();        if (this.testBit(0))           limit = (p-1) < limit ? (p-1) : limit;	while (expOffset < limit) {	    if (exponent.testBit(expOffset))		result = result.multiply(baseToPow2).mod2(p);            expOffset++;	    if (expOffset < limit)                baseToPow2 = baseToPow2.square().mod2(p);	}	return result;    }    /**     * Returns a BigInteger whose value is this mod(2**p).     * Assumes that this BigInteger &gt;= 0 and p &gt; 0.     */    private BigInteger mod2(int p) {	if (bitLength() <= p)	    return this;	// Copy remaining ints of mag	int numInts = (p+31)/32;	int[] mag = new int[numInts];	for (int i=0; i<numInts; i++)	    mag[i] = this.mag[i + (this.mag.length - numInts)];	// Mask out any excess bits	int excessBits = (numInts << 5) - p;	mag[0] &= (1L << (32-excessBits)) - 1;	return (mag[0]==0 ? new BigInteger(1, mag) : new BigInteger(mag, 1));    }    /**     * Returns a BigInteger whose value is <tt>(this<sup>-1</sup> mod m)</tt>.     *     * @param  m the modulus.     * @return <tt>this<sup>-1</sup> mod m</tt>.     * @throws ArithmeticException <tt> m &lt;= 0</tt>, or this BigInteger     *	       has no multiplicative inverse mod m (that is, this BigInteger     *	       is not <i>relatively prime</i> to m).     */    public BigInteger modInverse(BigInteger m) {	if (m.signum != 1)	    throw new ArithmeticException("BigInteger: modulus not positive");        if (m.equals(ONE))            return ZERO;	// Calculate (this mod m)        BigInteger modVal = this;        if (signum < 0 || (intArrayCmp(mag, m.mag) >= 0))            modVal = this.mod(m);        if (modVal.equals(ONE))            return ONE;        MutableBigInteger a = new MutableBigInteger(modVal);        MutableBigInteger b = new MutableBigInteger(m);          MutableBigInteger result = a.mutableModInverse(b);          return new BigInteger(result, 1);    }    // Shift Operations    /**     * Returns a BigInteger whose value is <tt>(this &lt;&lt; n)</tt>.     * The shift distance, <tt>n</tt>, may be negative, in which case     * this method performs a right shift.     * (Computes <tt>floor(this * 2<sup>n</sup>)</tt>.)     *     * @param  n shift distance, in bits.     * @return <tt>this &lt;&lt; n</tt>     * @see #shiftRight   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -