/** * @param m a positive modulus * Return the greatest common divisor of op1 and op2, * * @param op1 * must be greater than zero * @param op2 * must be greater than zero * @see BigInteger#gcd(BigInteger) * @return {@code GCD(op1, op2)} */ public 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.LowestSetBit; int lsb2 = op2.LowestSetBit; int pow2Count = System.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.ToInt64(), op2.ToInt64())); 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.Sign != 0) { BitLevel.InplaceShiftRight(op2, op2.LowestSetBit); } } else { // Use Knuth's algorithm of successive subtract and shifting do { Elementary.inplaceSubtract(op2, op1); // both are odd BitLevel.InplaceShiftRight(op2, op2.LowestSetBit); // 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)); }
/** * Divides the array 'a' by the array 'b' and gets the quotient and the * remainder. Implements the Knuth's division algorithm. See D. Knuth, The * Art of Computer Programming, vol. 2. Steps D1-D8 correspond the steps in * the algorithm description. * * @param quot the quotient * @param quotLength the quotient's length * @param a the dividend * @param aLength the dividend's length * @param b the divisor * @param bLength the divisor's length * @return the remainder */ public static int[] Divide(int[] quot, int quotLength, int[] a, int aLength, int[] b, int bLength) { int[] normA = new int[aLength + 1]; // the normalized dividend // an extra byte is needed for correct shift int[] normB = new int[bLength + 1]; // the normalized divisor; int normBLength = bLength; /* * Step D1: normalize a and b and put the results to a1 and b1 the * normalized divisor's first digit must be >= 2^31 */ int divisorShift = Utils.NumberOfLeadingZeros(b[bLength - 1]); if (divisorShift != 0) { BitLevel.ShiftLeft(normB, b, 0, divisorShift); BitLevel.ShiftLeft(normA, a, 0, divisorShift); } else { Array.Copy(a, 0, normA, 0, aLength); Array.Copy(b, 0, normB, 0, bLength); } int firstDivisorDigit = normB[normBLength - 1]; // Step D2: set the quotient index int i = quotLength - 1; int j = aLength; while (i >= 0) { // Step D3: calculate a guess digit guessDigit int guessDigit = 0; if (normA[j] == firstDivisorDigit) { // set guessDigit to the largest unsigned int value guessDigit = -1; } else { long product = (((normA[j] & 0xffffffffL) << 32) + (normA[j - 1] & 0xffffffffL)); long res = Division.DivideLongByInt(product, firstDivisorDigit); guessDigit = (int)res; // the quotient of divideLongByInt int rem = (int)(res >> 32); // the remainder of // divideLongByInt // decrease guessDigit by 1 while leftHand > rightHand if (guessDigit != 0) { long leftHand = 0; long rightHand = 0; bool rOverflowed = false; guessDigit++; // to have the proper value in the loop // below do { guessDigit--; if (rOverflowed) { break; } // leftHand always fits in an unsigned long leftHand = (guessDigit & 0xffffffffL) * (normB[normBLength - 2] & 0xffffffffL); /* * rightHand can overflow; in this case the loop * condition will be true in the next step of the loop */ rightHand = ((long)rem << 32) + (normA[j - 2] & 0xffffffffL); long longR = (rem & 0xffffffffL) + (firstDivisorDigit & 0xffffffffL); /* * checks that longR does not fit in an unsigned int; * this ensures that rightHand will overflow unsigned * long in the next step */ if (Utils.NumberOfLeadingZeros((int)Utils.URShift(longR, 32)) < 32) { rOverflowed = true; } else { rem = (int)longR; } } while ((leftHand ^ Int64.MinValue) > (rightHand ^ Int64.MinValue)); //} while ((leftHand ^ Int64.MaxValue) > (rightHand ^ Int64.MaxValue)); // while (((leftHand ^ 0x8000000000000000L) > (rightHand ^ 0x8000000000000000L))) ; } } // Step D4: multiply normB by guessDigit and subtract the production // from normA. if (guessDigit != 0) { int borrow = Division.MultiplyAndSubtract(normA, j - normBLength, normB, normBLength, guessDigit); // Step D5: check the borrow if (borrow != 0) { // Step D6: compensating addition guessDigit--; long carry = 0; for (int k = 0; k < normBLength; k++) { carry += (normA[j - normBLength + k] & 0xffffffffL) + (normB[k] & 0xffffffffL); normA[j - normBLength + k] = (int)carry; carry = Utils.URShift(carry, 32); } } } if (quot != null) { quot[i] = guessDigit; } // Step D7 j--; i--; } /* * Step D8: we got the remainder in normA. Denormalize it id needed */ if (divisorShift != 0) { // reuse normB BitLevel.ShiftRight(normB, normBLength, normA, 0, divisorShift); return(normB); } Array.Copy(normA, 0, normB, 0, bLength); return(normA); }
/** * It uses the sieve of Eratosthenes to discard several composite numbers in * some appropriate range (at the moment {@code [this, this + 1024]}). After * this process it applies the Miller-Rabin test to the numbers that were * not discarded in the sieve. * * @see BigInteger#nextProbablePrime() * @see #millerRabin(BigInteger, int) */ public static BigInteger NextProbablePrime(BigInteger n) { // PRE: n >= 0 int i, j; int certainty; int gapSize = 1024; // for searching of the next probable prime number int[] modules = new int[primes.Length]; bool[] isDivisible = new bool[gapSize]; BigInteger startPoint; BigInteger probPrime; // If n < "last prime of table" searches next prime in the table if ((n.numberLength == 1) && (n.Digits[0] >= 0) && (n.Digits[0] < primes[primes.Length - 1])) { for (i = 0; n.Digits[0] >= primes[i]; i++) { ; } return(BIprimes[i]); } /* * Creates a "N" enough big to hold the next probable prime Note that: N < * "next prime" < 2*N */ startPoint = new BigInteger(1, n.numberLength, new int[n.numberLength + 1]); Array.Copy(n.Digits, 0, startPoint.Digits, 0, n.numberLength); // To fix N to the "next odd number" if (n.TestBit(0)) { Elementary.inplaceAdd(startPoint, 2); } else { startPoint.Digits[0] |= 1; } // To set the improved certainly of Miller-Rabin j = startPoint.BitLength; for (certainty = 2; j < BITS[certainty]; certainty++) { ; } // To calculate modules: N mod p1, N mod p2, ... for first primes. for (i = 0; i < primes.Length; i++) { modules[i] = Division.Remainder(startPoint, primes[i]) - gapSize; } while (true) { // At this point, all numbers in the gap are initialized as // probably primes // Arrays.fill(isDivisible, false); for (int k = 0; k < isDivisible.Length; k++) { isDivisible[k] = false; } // To discard multiples of first primes for (i = 0; i < primes.Length; i++) { modules[i] = (modules[i] + gapSize) % primes[i]; j = (modules[i] == 0) ? 0 : (primes[i] - modules[i]); for (; j < gapSize; j += primes[i]) { isDivisible[j] = true; } } // To execute Miller-Rabin for non-divisible numbers by all first // primes for (j = 0; j < gapSize; j++) { if (!isDivisible[j]) { probPrime = startPoint.Copy(); Elementary.inplaceAdd(probPrime, j); if (MillerRabin(probPrime, certainty)) { return(probPrime); } } } Elementary.inplaceAdd(startPoint, gapSize); } }