internal static BigInteger pow2ModPow(BigInteger _base, BigInteger exponent, int j) { // PRE: (base > 0), (exponent > 0) and (j > 0) BigInteger res = BigInteger.ONE; BigInteger e = exponent.copy(); BigInteger baseMod2toN = _base.copy(); BigInteger res2; /* * If 'base' is odd then it's coprime with 2^j and phi(2^j) = 2^(j-1); * so we can reduce reduce the exponent (mod 2^(j-1)). */ if (_base.testBit(0)) { inplaceModPow2(e, j - 1); } inplaceModPow2(baseMod2toN, j); for (int i = e.bitLength() - 1; i >= 0; i--) { res2 = res.copy(); inplaceModPow2(res2, j); res = res.multiply(res2); if (BitLevel.testBit(e, i)) { res = res.multiply(baseMod2toN); inplaceModPow2(res, j); } } inplaceModPow2(res, j); return(res); }
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); }
internal static BigInteger slidingWindow(BigInteger x2, BigInteger a2, BigInteger exponent, BigInteger modulus, int n2) { // fill odd low pows of a2 BigInteger[] pows = new BigInteger[8]; BigInteger res = x2; int lowexp; BigInteger x3; int acc3; pows[0] = a2; x3 = monPro(a2, a2, modulus, n2); for (int i = 1; i <= 7; i++) { pows[i] = monPro(pows[i - 1], x3, modulus, n2); } for (int i = exponent.bitLength() - 1; i >= 0; i--) { if (BitLevel.testBit(exponent, i)) { lowexp = 1; acc3 = i; for (int j = Math.Max(i - 3, 0); j <= i - 1; j++) { if (BitLevel.testBit(exponent, j)) { if (j < acc3) { acc3 = j; lowexp = (lowexp << (i - j)) ^ 1; } else { lowexp = lowexp ^ (1 << (j - acc3)); } } } for (int j = acc3; j <= i; j++) { res = monPro(res, res, modulus, n2); } res = monPro(pows[(lowexp - 1) >> 1], res, modulus, n2); i = acc3; } else { res = monPro(res, res, modulus, n2); } } return(res); }
internal static BigInteger squareAndMultiply(BigInteger x2, BigInteger a2, BigInteger exponent, BigInteger modulus, int n2) { BigInteger res = x2; for (int i = exponent.bitLength() - 1; i >= 0; i--) { res = monPro(res, res, modulus, n2); if (BitLevel.testBit(exponent, i)) { res = monPro(res, a2, modulus, n2); } } return(res); }
internal static void inplaceModPow2(BigInteger x, int n) { // PRE: (x > 0) and (n >= 0) int fd = n >> 5; int leadingZeros; if ((x.numberLength < fd) || (x.bitLength() <= n)) { return; } leadingZeros = 32 - (n & 31); x.numberLength = fd + 1; unchecked { x.digits[fd] &= (leadingZeros < 32) ? ((int)(((uint)-1) >> leadingZeros)) : 0; } x.cutOffLeadingZeroes(); }
internal static bool isProbablePrime(BigInteger n, int certainty) { // PRE: n >= 0; if ((certainty <= 0) || ((n.numberLength == 1) && (n.digits[0] == 2))) { return(true); } // To discard all even numbers if (!n.testBit(0)) { return(false); } // To check if 'n' exists in the table (it fit in 10 bits) if ((n.numberLength == 1) && ((n.digits[0] & 0XFFFFFC00) == 0)) { return(Array.BinarySearch(primes, n.digits[0]) >= 0); } // To check if 'n' is divisible by some prime of the table for (int i = 1; i < primes.Length; i++) { if (Division.remainderArrayByInt(n.digits, n.numberLength, primes[i]) == 0) { return(false); } } // To set the number of iterations necessary for Miller-Rabin test int ix; int bitLength = n.bitLength(); for (ix = 2; bitLength < BITS[ix]; ix++) { ; } certainty = Math.Min(ix, 1 + ((certainty - 1) >> 1)); return(millerRabin(n, certainty)); }
internal static bool isProbablePrime(BigInteger n, int certainty) { // PRE: n >= 0; if ((certainty <= 0) || ((n.numberLength == 1) && (n.digits[0] == 2))) { return true; } // To discard all even numbers if (!n.testBit(0)) { return false; } // To check if 'n' exists in the table (it fit in 10 bits) if ((n.numberLength == 1) && ((n.digits[0] & 0XFFFFFC00) == 0)) { return (Array.BinarySearch(primes, n.digits[0]) >= 0); } // To check if 'n' is divisible by some prime of the table for (int i = 1; i < primes.Length; i++) { if (Division.remainderArrayByInt(n.digits, n.numberLength, primes[i]) == 0) { return false; } } // To set the number of iterations necessary for Miller-Rabin test int ix; int bitLength = n.bitLength(); for (ix = 2; bitLength < BITS[ix]; ix++) { ; } certainty = Math.Min(ix, 1 + ((certainty - 1) >> 1)); return millerRabin(n, certainty); }
internal 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, startPoint.digits, 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 Array.Clear(isDivisible, 0, isDivisible.Length); // 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); } }
internal 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, startPoint.digits, 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 Array.Clear(isDivisible, 0, isDivisible.Length); // 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); } }
internal static BigInteger squareAndMultiply(BigInteger x2, BigInteger a2, BigInteger exponent,BigInteger modulus, int n2 ) { BigInteger res = x2; for (int i = exponent.bitLength() - 1; i >= 0; i--) { res = monPro(res,res,modulus, n2); if (BitLevel.testBit(exponent, i)) { res = monPro(res, a2, modulus, n2); } } return res; }
internal static BigInteger slidingWindow(BigInteger x2, BigInteger a2, BigInteger exponent,BigInteger modulus, int n2) { // fill odd low pows of a2 BigInteger[] pows = new BigInteger[8]; BigInteger res = x2; int lowexp; BigInteger x3; int acc3; pows[0] = a2; x3 = monPro(a2,a2,modulus,n2); for (int i = 1; i <= 7; i++){ pows[i] = monPro(pows[i-1],x3,modulus,n2) ; } for (int i = exponent.bitLength()-1; i>=0;i--){ if( BitLevel.testBit(exponent,i) ) { lowexp = 1; acc3 = i; for(int j = Math.Max(i-3,0);j <= i-1 ;j++) { if (BitLevel.testBit(exponent,j)) { if (j<acc3) { acc3 = j; lowexp = (lowexp << (i-j))^1; } else { lowexp = lowexp^(1<<(j-acc3)); } } } for(int j = acc3; j <= i; j++) { res = monPro(res,res,modulus,n2); } res = monPro(pows[(lowexp-1)>>1], res, modulus,n2); i = acc3 ; }else{ res = monPro(res, res, modulus, n2) ; } } return res; }
internal static BigInteger modInverseLorencz(BigInteger a, BigInteger modulo) { int max = Math.Max(a.numberLength, modulo.numberLength); int[] uDigits = new int[max + 1]; // enough place to make all the inplace operation int[] vDigits = new int[max + 1]; Array.Copy(modulo.digits, uDigits, modulo.numberLength); Array.Copy(a.digits, vDigits, a.numberLength); BigInteger u = new BigInteger(modulo.sign, modulo.numberLength, uDigits); BigInteger v = new BigInteger(a.sign, a.numberLength, vDigits); BigInteger r = new BigInteger(0, 1, new int[max + 1]); // BigInteger.ZERO; BigInteger s = new BigInteger(1, 1, new int[max + 1]); s.digits[0] = 1; // r == 0 && s == 1, but with enough place int coefU = 0, coefV = 0; int n = modulo.bitLength(); int k; while (!isPowerOfTwo(u, coefU) && !isPowerOfTwo(v, coefV)) { // modification of original algorithm: I calculate how many times the algorithm will enter in the same branch of if k = howManyIterations(u, n); if (k != 0) { BitLevel.inplaceShiftLeft(u, k); if (coefU >= coefV) { BitLevel.inplaceShiftLeft(r, k); } else { BitLevel.inplaceShiftRight(s, Math.Min(coefV - coefU, k)); if (k - ( coefV - coefU ) > 0) { BitLevel.inplaceShiftLeft(r, k - coefV + coefU); } } coefU += k; } k = howManyIterations(v, n); if (k != 0) { BitLevel.inplaceShiftLeft(v, k); if (coefV >= coefU) { BitLevel.inplaceShiftLeft(s, k); } else { BitLevel.inplaceShiftRight(r, Math.Min(coefU - coefV, k)); if (k - ( coefU - coefV ) > 0) { BitLevel.inplaceShiftLeft(s, k - coefU + coefV); } } coefV += k; } if (u.signum() == v.signum()) { if (coefU <= coefV) { Elementary.completeInPlaceSubtract(u, v); Elementary.completeInPlaceSubtract(r, s); } else { Elementary.completeInPlaceSubtract(v, u); Elementary.completeInPlaceSubtract(s, r); } } else { if (coefU <= coefV) { Elementary.completeInPlaceAdd(u, v); Elementary.completeInPlaceAdd(r, s); } else { Elementary.completeInPlaceAdd(v, u); Elementary.completeInPlaceAdd(s, r); } } if (v.signum() == 0 || u.signum() == 0){ throw new ArithmeticException("BigInteger not invertible"); } } if (isPowerOfTwo(v, coefV)) { r = s; if (v.signum() != u.signum()) u = u.negate(); } if (u.testBit(n)) { if (r.signum() < 0) { r = r.negate(); } else { r = modulo.subtract(r); } } if (r.signum() < 0) { r = r.add(modulo); } return r; }
internal static void inplaceModPow2(BigInteger x, int n) { // PRE: (x > 0) and (n >= 0) int fd = n >> 5; int leadingZeros; if ((x.numberLength < fd) || (x.bitLength() <= n)) { return; } leadingZeros = 32 - (n & 31); x.numberLength = fd + 1; unchecked { x.digits[fd] &= (leadingZeros < 32) ? ((int)(((uint)-1) >> leadingZeros)) : 0; } x.cutOffLeadingZeroes(); }
internal static BigInteger modInverseLorencz(BigInteger a, BigInteger modulo) { int max = Math.Max(a.numberLength, modulo.numberLength); int[] uDigits = new int[max + 1]; // enough place to make all the inplace operation int[] vDigits = new int[max + 1]; Array.Copy(modulo.digits, uDigits, modulo.numberLength); Array.Copy(a.digits, vDigits, a.numberLength); BigInteger u = new BigInteger(modulo.sign, modulo.numberLength, uDigits); BigInteger v = new BigInteger(a.sign, a.numberLength, vDigits); BigInteger r = new BigInteger(0, 1, new int[max + 1]); // BigInteger.ZERO; BigInteger s = new BigInteger(1, 1, new int[max + 1]); s.digits[0] = 1; // r == 0 && s == 1, but with enough place int coefU = 0, coefV = 0; int n = modulo.bitLength(); int k; while (!isPowerOfTwo(u, coefU) && !isPowerOfTwo(v, coefV)) { // modification of original algorithm: I calculate how many times the algorithm will enter in the same branch of if k = howManyIterations(u, n); if (k != 0) { BitLevel.inplaceShiftLeft(u, k); if (coefU >= coefV) { BitLevel.inplaceShiftLeft(r, k); } else { BitLevel.inplaceShiftRight(s, Math.Min(coefV - coefU, k)); if (k - (coefV - coefU) > 0) { BitLevel.inplaceShiftLeft(r, k - coefV + coefU); } } coefU += k; } k = howManyIterations(v, n); if (k != 0) { BitLevel.inplaceShiftLeft(v, k); if (coefV >= coefU) { BitLevel.inplaceShiftLeft(s, k); } else { BitLevel.inplaceShiftRight(r, Math.Min(coefU - coefV, k)); if (k - (coefU - coefV) > 0) { BitLevel.inplaceShiftLeft(s, k - coefU + coefV); } } coefV += k; } if (u.signum() == v.signum()) { if (coefU <= coefV) { Elementary.completeInPlaceSubtract(u, v); Elementary.completeInPlaceSubtract(r, s); } else { Elementary.completeInPlaceSubtract(v, u); Elementary.completeInPlaceSubtract(s, r); } } else { if (coefU <= coefV) { Elementary.completeInPlaceAdd(u, v); Elementary.completeInPlaceAdd(r, s); } else { Elementary.completeInPlaceAdd(v, u); Elementary.completeInPlaceAdd(s, r); } } if (v.signum() == 0 || u.signum() == 0) { throw new ArithmeticException("BigInteger not invertible"); } } if (isPowerOfTwo(v, coefV)) { r = s; if (v.signum() != u.signum()) { u = u.negate(); } } if (u.testBit(n)) { if (r.signum() < 0) { r = r.negate(); } else { r = modulo.subtract(r); } } if (r.signum() < 0) { r = r.add(modulo); } return(r); }
private void setUnscaledValue(BigInteger unscaledValue) { this.intVal = unscaledValue; this._bitLength = unscaledValue.bitLength(); if(this._bitLength < 64) { this.smallValue = unscaledValue.longValue(); } }
private static BigDecimal divideBigIntegers(BigInteger scaledDividend, BigInteger scaledDivisor, int scale, RoundingMode roundingMode) { BigInteger[] quotAndRem = scaledDividend.divideAndRemainder(scaledDivisor); // quotient and remainder // If after division there is a remainder... BigInteger quotient = quotAndRem[0]; BigInteger remainder = quotAndRem[1]; if (remainder.signum() == 0) { return new BigDecimal(quotient, scale); } int sign = scaledDividend.signum() * scaledDivisor.signum(); int compRem; // 'compare to remainder' if(scaledDivisor.bitLength() < 63) { // 63 in order to avoid out of long after <<1 long rem = remainder.longValue(); long divisor = scaledDivisor.longValue(); compRem = longCompareTo(Math.Abs(rem) << 1,Math.Abs(divisor)); // To look if there is a carry compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, sign * (5 + compRem), roundingMode); } else { // Checking if: remainder * 2 >= scaledDivisor compRem = remainder.abs().shiftLeftOneBit().compareTo(scaledDivisor.abs()); compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, sign * (5 + compRem), roundingMode); } if (compRem != 0) { if(quotient.bitLength() < 63) { return valueOf(quotient.longValue() + compRem,scale); } quotient = quotient.add(BigInteger.valueOf(compRem)); return new BigDecimal(quotient, scale); } // Constructing the result with the appropriate unscaled value return new BigDecimal(quotient, scale); }