public BigInteger modPow(BigInteger exponent, BigInteger m) { if (m.sign <= 0) { throw new ArithmeticException("BigInteger: modulus not positive"); } BigInteger _base = this; if (m.isOne() | (exponent.sign > 0 & _base.sign == 0)) { return(BigInteger.ZERO); } if (_base.sign == 0 && exponent.sign == 0) { return(BigInteger.ONE); } if (exponent.sign < 0) { _base = modInverse(m); exponent = exponent.negate(); } // From now on: (m > 0) and (exponent >= 0) BigInteger res = (m.testBit(0)) ? Division.oddModPow(_base.abs(), exponent, m) : Division.evenModPow(_base.abs(), exponent, m); if ((_base.sign < 0) && exponent.testBit(0)) { // -b^e mod m == ((-1 mod m) * (b^e mod m)) mod m res = m.subtract(BigInteger.ONE).multiply(res).mod(m); } // else exponent is even, so base^exp is positive return(res); }
internal static BigInteger subtract(BigInteger op1, BigInteger op2) { int resSign; int[] resDigits; int op1Sign = op1.sign; int op2Sign = op2.sign; if (op2Sign == 0) { return(op1); } if (op1Sign == 0) { return(op2.negate()); } int op1Len = op1.numberLength; int op2Len = op2.numberLength; if (op1Len + op2Len == 2) { long a = (op1.digits[0] & 0xFFFFFFFFL); long b = (op2.digits[0] & 0xFFFFFFFFL); if (op1Sign < 0) { a = -a; } if (op2Sign < 0) { b = -b; } return(BigInteger.valueOf(a - b)); } int cmp = ((op1Len != op2Len) ? ((op1Len > op2Len) ? 1 : -1) : Elementary.compareArrays(op1.digits, op2.digits, op1Len)); if (cmp == BigInteger.LESS) { resSign = -op2Sign; resDigits = (op1Sign == op2Sign) ? subtract(op2.digits, op2Len, op1.digits, op1Len) : add(op2.digits, op2Len, op1.digits, op1Len); } else { resSign = op1Sign; if (op1Sign == op2Sign) { if (cmp == BigInteger.EQUALS) { return(BigInteger.ZERO); } resDigits = subtract(op1.digits, op1Len, op2.digits, op2Len); } else { resDigits = add(op1.digits, op1Len, op2.digits, op2Len); } } BigInteger res = new BigInteger(resSign, resDigits.Length, resDigits); res.cutOffLeadingZeroes(); return(res); }
public BigInteger modPow(BigInteger exponent, BigInteger m) { if (m.sign <= 0) { throw new ArithmeticException("BigInteger: modulus not positive"); } BigInteger _base = this; if (m.isOne() | (exponent.sign > 0 & _base.sign == 0)) { return BigInteger.ZERO; } if (_base.sign == 0 && exponent.sign == 0) { return BigInteger.ONE; } if (exponent.sign < 0) { _base = modInverse(m); exponent = exponent.negate(); } // From now on: (m > 0) and (exponent >= 0) BigInteger res = (m.testBit(0)) ? Division.oddModPow(_base.abs(), exponent, m) : Division.evenModPow(_base.abs(), exponent, m); if ((_base.sign < 0) && exponent.testBit(0)) { // -b^e mod m == ((-1 mod m) * (b^e mod m)) mod m res = m.subtract(BigInteger.ONE).multiply(res).mod(m); } // else exponent is even, so base^exp is positive 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 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 BigInteger subtract(BigInteger op1, BigInteger op2) { int resSign; int[] resDigits; int op1Sign = op1.sign; int op2Sign = op2.sign; if (op2Sign == 0) { return op1; } if (op1Sign == 0) { return op2.negate (); } int op1Len = op1.numberLength; int op2Len = op2.numberLength; if (op1Len + op2Len == 2) { long a = ( op1.digits[0] & 0xFFFFFFFFL ); long b = ( op2.digits[0] & 0xFFFFFFFFL ); if (op1Sign < 0) { a = -a; } if (op2Sign < 0) { b = -b; } return BigInteger.valueOf (a - b); } int cmp = ( ( op1Len != op2Len ) ? ( ( op1Len > op2Len ) ? 1 : -1 ) : Elementary.compareArrays (op1.digits, op2.digits, op1Len) ); if (cmp == BigInteger.LESS) { resSign = -op2Sign; resDigits = ( op1Sign == op2Sign ) ? subtract (op2.digits, op2Len, op1.digits, op1Len) : add (op2.digits, op2Len, op1.digits, op1Len); } else { resSign = op1Sign; if (op1Sign == op2Sign) { if (cmp == BigInteger.EQUALS) { return BigInteger.ZERO; } resDigits = subtract (op1.digits, op1Len, op2.digits, op2Len); } else { resDigits = add (op1.digits, op1Len, op2.digits, op2Len); } } BigInteger res = new BigInteger (resSign, resDigits.Length, resDigits); res.cutOffLeadingZeroes(); return res; }