public static BigInteger powerOf10(long exp) { // PRE: exp >= 0 int intExp = (int)exp; // "SMALL POWERS" if (exp < bigTenPows.Length) { // The largest power that fit in 'long' type return(bigTenPows[intExp]); } else if (exp <= 50) { // To calculate: 10^exp return(BigInteger.TEN.pow(intExp)); } else if (exp <= 1000) { // To calculate: 5^exp * 2^exp return(bigFivePows[1].pow(intExp).shiftLeft(intExp)); } if (exp <= Int32.MaxValue) { // To calculate: 5^exp * 2^exp return(bigFivePows[1].pow(intExp).shiftLeft(intExp)); } /* * "HUGE POWERS" * * This branch probably won't be executed since the power of ten is too * big. */ // To calculate: 5^exp BigInteger powerOfFive = bigFivePows[1].pow(Int32.MaxValue); BigInteger res = powerOfFive; long longExp = exp - Int32.MaxValue; intExp = (int)(exp % Int32.MaxValue); while (longExp > Int32.MaxValue) { res = res.multiply(powerOfFive); longExp -= Int32.MaxValue; } res = res.multiply(bigFivePows[1].pow(intExp)); // To calculate: 5^exp << exp res = res.shiftLeft(Int32.MaxValue); longExp = exp - Int32.MaxValue; while (longExp > Int32.MaxValue) { res = res.shiftLeft(Int32.MaxValue); longExp -= Int32.MaxValue; } res = res.shiftLeft(intExp); return(res); }
internal static BigInteger oddModPow(BigInteger _base, BigInteger exponent, BigInteger modulus) { // PRE: (base > 0), (exponent > 0), (modulus > 0) and (odd modulus) int k = (modulus.numberLength << 5); // r = 2^k // n-residue of base [base * r (mod modulus)] BigInteger a2 = _base.shiftLeft(k).mod(modulus); // n-residue of base [1 * r (mod modulus)] BigInteger x2 = BigInteger.getPowerOfTwo(k).mod(modulus); BigInteger res; // Compute (modulus[0]^(-1)) (mod 2^32) for odd modulus int n2 = calcN(modulus); if (modulus.numberLength == 1) { res = squareAndMultiply(x2, a2, exponent, modulus, n2); } else { res = slidingWindow(x2, a2, exponent, modulus, n2); } return(monPro(res, BigInteger.ONE, modulus, n2)); }
public static BigInteger karatsuba(BigInteger op1, BigInteger op2) { BigInteger temp; if (op2.numberLength > op1.numberLength) { temp = op1; op1 = op2; op2 = temp; } if (op2.numberLength < whenUseKaratsuba) { return(multiplyPAP(op1, op2)); } /* Karatsuba: u = u1*B + u0 * v = v1*B + v0 * u*v = (u1*v1)*B^2 + ((u1-u0)*(v0-v1) + u1*v1 + u0*v0)*B + u0*v0 */ // ndiv2 = (op1.numberLength / 2) * 32 int ndiv2 = (int)(op1.numberLength & 0xFFFFFFFE) << 4; BigInteger upperOp1 = op1.shiftRight(ndiv2); BigInteger upperOp2 = op2.shiftRight(ndiv2); BigInteger lowerOp1 = op1.subtract(upperOp1.shiftLeft(ndiv2)); BigInteger lowerOp2 = op2.subtract(upperOp2.shiftLeft(ndiv2)); BigInteger upper = karatsuba(upperOp1, upperOp2); BigInteger lower = karatsuba(lowerOp1, lowerOp2); BigInteger middle = karatsuba(upperOp1.subtract(lowerOp1), lowerOp2.subtract(upperOp2)); middle = middle.add(upper).add(lower); middle = middle.shiftLeft(ndiv2); upper = upper.shiftLeft(ndiv2 << 1); return(upper.add(middle).add(lower)); }
internal static BigInteger oddModPow(BigInteger _base, BigInteger exponent, BigInteger modulus) { // PRE: (base > 0), (exponent > 0), (modulus > 0) and (odd modulus) int k = (modulus.numberLength << 5); // r = 2^k // n-residue of base [base * r (mod modulus)] BigInteger a2 = _base.shiftLeft(k).mod(modulus); // n-residue of base [1 * r (mod modulus)] BigInteger x2 = BigInteger.getPowerOfTwo(k).mod(modulus); BigInteger res; // Compute (modulus[0]^(-1)) (mod 2^32) for odd modulus int n2 = calcN(modulus); if( modulus.numberLength == 1 ){ res = squareAndMultiply(x2,a2, exponent, modulus,n2); } else { res = slidingWindow(x2, a2, exponent, modulus, n2); } return monPro(res, BigInteger.ONE, modulus, n2); }
internal static BigInteger gcdBinary(BigInteger op1, BigInteger op2) { // PRE: (op1 > 0) and (op2 > 0) /* * Divide both number the maximal possible times by 2 without rounding * gcd(2*a, 2*b) = 2 * gcd(a,b) */ int lsb1 = op1.getLowestSetBit(); int lsb2 = op2.getLowestSetBit(); int pow2Count = Math.Min(lsb1, lsb2); BitLevel.inplaceShiftRight(op1, lsb1); BitLevel.inplaceShiftRight(op2, lsb2); BigInteger swap; // I want op2 > op1 if (op1.compareTo(op2) == BigInteger.GREATER) { swap = op1; op1 = op2; op2 = swap; } do { // INV: op2 >= op1 && both are odd unless op1 = 0 // Optimization for small operands // (op2.bitLength() < 64) implies by INV (op1.bitLength() < 64) if (( op2.numberLength == 1 ) || ( ( op2.numberLength == 2 ) && ( op2.digits[1] > 0 ) )) { op2 = BigInteger.valueOf(Division.gcdBinary(op1.longValue(), op2.longValue())); break; } // Implements one step of the Euclidean algorithm // To reduce one operand if it's much smaller than the other one if (op2.numberLength > op1.numberLength * 1.2) { op2 = op2.remainder(op1); if (op2.signum() != 0) { BitLevel.inplaceShiftRight(op2, op2.getLowestSetBit()); } } else { // Use Knuth's algorithm of successive subtract and shifting do { Elementary.inplaceSubtract(op2, op1); // both are odd BitLevel.inplaceShiftRight(op2, op2.getLowestSetBit()); // op2 is even } while (op2.compareTo(op1) >= BigInteger.EQUALS); } // now op1 >= op2 swap = op2; op2 = op1; op1 = swap; } while (op1.sign != 0); return op2.shiftLeft(pow2Count); }
internal static BigInteger gcdBinary(BigInteger op1, BigInteger op2) { // PRE: (op1 > 0) and (op2 > 0) /* * Divide both number the maximal possible times by 2 without rounding * gcd(2*a, 2*b) = 2 * gcd(a,b) */ int lsb1 = op1.getLowestSetBit(); int lsb2 = op2.getLowestSetBit(); int pow2Count = Math.Min(lsb1, lsb2); BitLevel.inplaceShiftRight(op1, lsb1); BitLevel.inplaceShiftRight(op2, lsb2); BigInteger swap; // I want op2 > op1 if (op1.compareTo(op2) == BigInteger.GREATER) { swap = op1; op1 = op2; op2 = swap; } do // INV: op2 >= op1 && both are odd unless op1 = 0 // Optimization for small operands // (op2.bitLength() < 64) implies by INV (op1.bitLength() < 64) { if ((op2.numberLength == 1) || ((op2.numberLength == 2) && (op2.digits[1] > 0))) { op2 = BigInteger.valueOf(Division.gcdBinary(op1.longValue(), op2.longValue())); break; } // Implements one step of the Euclidean algorithm // To reduce one operand if it's much smaller than the other one if (op2.numberLength > op1.numberLength * 1.2) { op2 = op2.remainder(op1); if (op2.signum() != 0) { BitLevel.inplaceShiftRight(op2, op2.getLowestSetBit()); } } else { // Use Knuth's algorithm of successive subtract and shifting do { Elementary.inplaceSubtract(op2, op1); // both are odd BitLevel.inplaceShiftRight(op2, op2.getLowestSetBit()); // op2 is even } while (op2.compareTo(op1) >= BigInteger.EQUALS); } // now op1 >= op2 swap = op2; op2 = op1; op1 = swap; } while (op1.sign != 0); return(op2.shiftLeft(pow2Count)); }