📄 biginteger.java
字号:
return nBitLength; } // // bitLen(val) is the number of bits in val. // static int bitLen(int w) { // Binary search - decision tree (5 tests, rarely 6) return (w < 1 << 15 ? (w < 1 << 7 ? (w < 1 << 3 ? (w < 1 << 1 ? (w < 1 << 0 ? (w < 0 ? 32 : 0) : 1) : (w < 1 << 2 ? 2 : 3)) : (w < 1 << 5 ? (w < 1 << 4 ? 4 : 5) : (w < 1 << 6 ? 6 : 7))) : (w < 1 << 11 ? (w < 1 << 9 ? (w < 1 << 8 ? 8 : 9) : (w < 1 << 10 ? 10 : 11)) : (w < 1 << 13 ? (w < 1 << 12 ? 12 : 13) : (w < 1 << 14 ? 14 : 15)))) : (w < 1 << 23 ? (w < 1 << 19 ? (w < 1 << 17 ? (w < 1 << 16 ? 16 : 17) : (w < 1 << 18 ? 18 : 19)) : (w < 1 << 21 ? (w < 1 << 20 ? 20 : 21) : (w < 1 << 22 ? 22 : 23))) : (w < 1 << 27 ? (w < 1 << 25 ? (w < 1 << 24 ? 24 : 25) : (w < 1 << 26 ? 26 : 27)) : (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31))))); } public int compareTo(Object o) { return compareTo((BigInteger)o); } /** * unsigned comparison on two arrays - note the arrays may * start with leading zeros. */ private int compareTo(int xIndx, int[] x, int yIndx, int[] y) { while (xIndx != x.length && x[xIndx] == 0) { xIndx++; } while (yIndx != y.length && y[yIndx] == 0) { yIndx++; } if ((x.length - xIndx) < (y.length - yIndx)) { return -1; } if ((x.length - xIndx) > (y.length - yIndx)) { return 1; } // lengths of magnitudes the same, test the magnitude values while (xIndx < x.length) { long v1 = (long)(x[xIndx++]) & IMASK; long v2 = (long)(y[yIndx++]) & IMASK; if (v1 < v2) { return -1; } if (v1 > v2) { return 1; } } return 0; } public int compareTo(BigInteger val) { if (sign < val.sign) return -1; if (sign > val.sign) return 1; if (sign == 0) return 0; return sign * compareTo(0, magnitude, 0, val.magnitude); } /** * return z = x / y - done in place (z value preserved, x contains the * remainder) */ private int[] divide(int[] x, int[] y) { int xyCmp = compareTo(0, x, 0, y); int[] count; if (xyCmp > 0) { int[] c; int shift = bitLength(0, x) - bitLength(0, y); if (shift > 1) { c = shiftLeft(y, shift - 1); count = shiftLeft(ONE.magnitude, shift - 1); if (shift % 32 == 0) { // Special case where the shift is the size of an int. int countSpecial[] = new int[shift / 32 + 1]; System.arraycopy(count, 0, countSpecial, 1, countSpecial.length - 1); countSpecial[0] = 0; count = countSpecial; } } else { c = new int[x.length]; count = new int[1]; System.arraycopy(y, 0, c, c.length - y.length, y.length); count[0] = 1; } int[] iCount = new int[count.length]; subtract(0, x, 0, c); System.arraycopy(count, 0, iCount, 0, count.length); int xStart = 0; int cStart = 0; int iCountStart = 0; for (; ; ) { int cmp = compareTo(xStart, x, cStart, c); while (cmp >= 0) { subtract(xStart, x, cStart, c); add(count, iCount); cmp = compareTo(xStart, x, cStart, c); } xyCmp = compareTo(xStart, x, 0, y); if (xyCmp > 0) { if (x[xStart] == 0) { xStart++; } shift = bitLength(cStart, c) - bitLength(xStart, x); if (shift == 0) { c = shiftRightOne(cStart, c); iCount = shiftRightOne(iCountStart, iCount); } else { c = shiftRight(cStart, c, shift); iCount = shiftRight(iCountStart, iCount, shift); } if (c[cStart] == 0) { cStart++; } if (iCount[iCountStart] == 0) { iCountStart++; } } else if (xyCmp == 0) { add(count, ONE.magnitude); for (int i = xStart; i != x.length; i++) { x[i] = 0; } break; } else { break; } } } else if (xyCmp == 0) { count = new int[1]; count[0] = 1; } else { count = new int[1]; count[0] = 0; } return count; } public BigInteger divide(BigInteger val) throws ArithmeticException { if (val.sign == 0) { throw new ArithmeticException("Divide by zero"); } if (sign == 0) { return BigInteger.ZERO; } if (val.compareTo(BigInteger.ONE) == 0) { return this; } int[] mag = new int[this.magnitude.length]; System.arraycopy(this.magnitude, 0, mag, 0, mag.length); return new BigInteger(this.sign * val.sign, divide(mag, val.magnitude)); } public BigInteger[] divideAndRemainder(BigInteger val) throws ArithmeticException { if (val.sign == 0) { throw new ArithmeticException("Divide by zero"); } BigInteger biggies[] = new BigInteger[2]; if (sign == 0) { biggies[0] = biggies[1] = BigInteger.ZERO; return biggies; } if (val.compareTo(BigInteger.ONE) == 0) { biggies[0] = this; biggies[1] = BigInteger.ZERO; return biggies; } int[] remainder = new int[this.magnitude.length]; System.arraycopy(this.magnitude, 0, remainder, 0, remainder.length); int[] quotient = divide(remainder, val.magnitude); biggies[0] = new BigInteger(this.sign * val.sign, quotient); biggies[1] = new BigInteger(this.sign, remainder); return biggies; } public boolean equals(Object val) { if (val == this) return true; if (!(val instanceof BigInteger)) return false; BigInteger biggie = (BigInteger)val; if (biggie.sign != sign || biggie.magnitude.length != magnitude.length) return false; for (int i = 0; i < magnitude.length; i++) { if (biggie.magnitude[i] != magnitude[i]) return false; } return true; } public BigInteger gcd(BigInteger val) { if (val.sign == 0) return this.abs(); else if (sign == 0) return val.abs(); BigInteger r; BigInteger u = this; BigInteger v = val; while (v.sign != 0) { r = u.mod(v); u = v; v = r; } return u; } public int hashCode() { int hc = magnitude.length; if (magnitude.length > 0) { hc ^= magnitude[0]; if (magnitude.length > 1) { hc ^= magnitude[magnitude.length - 1]; } } return sign < 0 ? ~hc : hc; } public int intValue() { if (magnitude.length == 0) { return 0; } if (sign < 0) { return -magnitude[magnitude.length - 1]; } else { return magnitude[magnitude.length - 1]; } } /** * return whether or not a BigInteger is probably prime with a * probability of 1 - (1/2)**certainty. * <p> * From Knuth Vol 2, pg 395. */ public boolean isProbablePrime(int certainty) { if (certainty <= 0) return true; if (sign == 0) return false; BigInteger n = this.abs(); if (!n.testBit(0)) return n.equals(TWO); if (n.equals(ONE)) return false; int test = n.remainder(smallPrimesProduct); for (int index = 0; index < smallPrimes.length; ++index) { int smallPrime = smallPrimes[index]; if (test % smallPrime == 0) return n.bitLength() <= 5 && n.intValue() == smallPrime; } // // let n = 1 + 2^kq // BigInteger nMinusOne = n.subtract(ONE); BigInteger q = nMinusOne; int k = q.getLowestSetBit(); q = q.shiftRight(k); Random rnd = new Random(); do { BigInteger x; do { x = new BigInteger(n.bitLength(), rnd); } // NB: Spec says 0 < x < n, but 1 is trivial while (x.compareTo(ONE) <= 0 || x.compareTo(n) >= 0); BigInteger y = x.modPow(q, n); if (!y.equals(ONE)) { // check already = x.ModPow(q << 0, n) int r = 0; while (!y.equals(nMinusOne)) { if (++r == k) return false; // check becomes a.ModPow(q << r, n) y = y.modPow(TWO, n); } } certainty -= 2; // composites pass for only 1/4 possible 'x' } while (certainty > 0); return true; } public long longValue() { long val = 0; if (magnitude.length == 0) { return 0; } if (magnitude.length > 1) { val = ((long)magnitude[magnitude.length - 2] << 32) | (magnitude[magnitude.length - 1] & IMASK); } else { val = (magnitude[magnitude.length - 1] & IMASK); } if (sign < 0) { return -val; } else { return val; } } public BigInteger max(BigInteger val) { return (compareTo(val) > 0) ? this : val; } public BigInteger min(BigInteger val) { return (compareTo(val) < 0) ? this : val; } public BigInteger mod(BigInteger m) throws ArithmeticException { if (m.sign <= 0) { throw new ArithmeticException("BigInteger: modulus is not positive"); } BigInteger biggie = this.remainder(m); return (biggie.sign >= 0 ? biggie : biggie.add(m)); } public BigInteger modInverse(BigInteger m) throws ArithmeticException { if (m.sign != 1) { throw new ArithmeticException("Modulus must be positive"); } BigInteger x = new BigInteger(); BigInteger y = new BigInteger(); BigInteger gcd = BigInteger.extEuclid(this, m, x, y); if (!gcd.equals(BigInteger.ONE)) { throw new ArithmeticException("Numbers not relatively prime."); } if (x.compareTo(BigInteger.ZERO) < 0) { x = x.add(m); } return x; } /** * Calculate the numbers u1, u2, and u3 such that: * * u1 * a + u2 * b = u3 * * where u3 is the greatest common divider of a and b. * a and b using the extended Euclid algorithm (refer p. 323 * of The Art of Computer Programming vol 2, 2nd ed). * This also seems to have the side effect of calculating * some form of multiplicative inverse. * * @param a First number to calculate gcd for * @param b Second number to calculate gcd for * @param u1Out the return object for the u1 value * @param u2Out the return object for the u2 value * @return The greatest common divisor of a and b */ private static BigInteger extEuclid(BigInteger a, BigInteger b, BigInteger u1Out, BigInteger u2Out) { BigInteger res; BigInteger u1 = BigInteger.ONE; BigInteger u3 = a; BigInteger v1 = BigInteger.ZERO; BigInteger v3 = b; while (v3.compareTo(BigInteger.ZERO) > 0) { BigInteger q, tn; q = u3.divide(v3); tn = u1.subtract(v1.multiply(q)); u1 = v1; v1 = tn; tn = u3.subtract(v3.multiply(q)); u3 = v3; v3 = tn; } u1Out.sign = u1.sign; u1Out.magnitude = u1.magnitude; res = u3.subtract(u1.multiply(a)).divide(b); u2Out.sign = res.sign; u2Out.magnitude = res.magnitude; return u3; } /** * zero out the array x */ private void zero(int[] x) { for (int i = 0; i != x.length; i++) { x[i] = 0; } } public BigInteger modPow(BigInteger exponent, BigInteger m) throws ArithmeticException { if (m.sign < 1) { throw new ArithmeticException("Modulus must be positive"); } if (m.equals(ONE)) { return ZERO; } // Zero exponent check if (exponent.sign == 0) { return ONE; } if (sign == 0) return ZERO; int[] zVal = null; int[] yAccum = null; int[] yVal; // Montgomery exponentiation is only possible if the modulus is odd, // but AFAIK, this is always the case for crypto algo's boolean useMonty = ((m.magnitude[m.magnitude.length - 1] & 1) == 1); long mQ = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -