internal static BigInteger evenModPow(BigInteger _base, BigInteger exponent, BigInteger modulus) { // PRE: (base > 0), (exponent > 0), (modulus > 0) and (modulus even) // STEP 1: Obtain the factorization 'modulus'= q * 2^j. int j = modulus.getLowestSetBit(); BigInteger q = modulus.shiftRight(j); // STEP 2: Compute x1 := base^exponent (mod q). BigInteger x1 = oddModPow(_base, exponent, q); // STEP 3: Compute x2 := base^exponent (mod 2^j). BigInteger x2 = pow2ModPow(_base, exponent, j); // STEP 4: Compute q^(-1) (mod 2^j) and y := (x2-x1) * q^(-1) (mod 2^j) BigInteger qInv = modPow2Inverse(q, j); BigInteger y = (x2.subtract(x1)).multiply(qInv); inplaceModPow2(y, j); if (y.sign < 0) { y = y.add(BigInteger.getPowerOfTwo(j)); } // STEP 5: Compute and return: x1 + q * y return(x1.add(q.multiply(y))); }
private static bool millerRabin(BigInteger n, int t) { // PRE: n >= 0, t >= 0 BigInteger x; // x := UNIFORM{2...n-1} BigInteger y; // y := x^(q * 2^j) mod n BigInteger n_minus_1 = n.subtract(BigInteger.ONE); // n-1 int bitLength = n_minus_1.bitLength(); // ~ log2(n-1) // (q,k) such that: n-1 = q * 2^k and q is odd int k = n_minus_1.getLowestSetBit(); BigInteger q = n_minus_1.shiftRight(k); Random rnd = new Random(); for (int i = 0; i < t; i++) { // To generate a witness 'x', first it use the primes of table if (i < primes.Length) { x = BIprimes[i]; } else /* * It generates random witness only if it's necesssary. Note * that all methods would call Miller-Rabin with t <= 50 so * this part is only to do more robust the algorithm */ { do { x = new BigInteger(bitLength, rnd); } while ((x.compareTo(n) >= BigInteger.EQUALS) || (x.sign == 0) || x.isOne()); } y = x.modPow(q, n); if (y.isOne() || y.Equals(n_minus_1)) { continue; } for (int j = 1; j < k; j++) { if (y.Equals(n_minus_1)) { continue; } y = y.multiply(y).mod(n); if (y.isOne()) { return(false); } } if (!y.Equals(n_minus_1)) { return(false); } } return(true); }
private static int howManyIterations(BigInteger bi, int n) { int i = n - 1; if (bi.sign > 0) { while (!bi.testBit(i)) { i--; } return(n - 1 - i); } else { while (bi.testBit(i)) { i--; } return(n - 1 - Math.Max(i, bi.getLowestSetBit())); } }
private static int howManyIterations(BigInteger bi, int n) { int i = n - 1; if (bi.sign > 0) { while (!bi.testBit(i)) i--; return n - 1 - i; } else { while (bi.testBit(i)) i--; return n - 1 - Math.Max(i, bi.getLowestSetBit()); } }
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 evenModPow(BigInteger _base, BigInteger exponent, BigInteger modulus) { // PRE: (base > 0), (exponent > 0), (modulus > 0) and (modulus even) // STEP 1: Obtain the factorization 'modulus'= q * 2^j. int j = modulus.getLowestSetBit(); BigInteger q = modulus.shiftRight(j); // STEP 2: Compute x1 := base^exponent (mod q). BigInteger x1 = oddModPow(_base, exponent, q); // STEP 3: Compute x2 := base^exponent (mod 2^j). BigInteger x2 = pow2ModPow(_base, exponent, j); // STEP 4: Compute q^(-1) (mod 2^j) and y := (x2-x1) * q^(-1) (mod 2^j) BigInteger qInv = modPow2Inverse(q, j); BigInteger y = (x2.subtract(x1)).multiply(qInv); inplaceModPow2(y, j); if (y.sign < 0) { y = y.add(BigInteger.getPowerOfTwo(j)); } // STEP 5: Compute and return: x1 + q * y return x1.add(q.multiply(y)); }
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)); }