| /* |
| * Copyright 2009 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with this |
| * work for additional information regarding copyright ownership. The ASF |
| * licenses this file to You under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| * |
| * INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE. |
| */ |
| package java.math; |
| |
| /** |
| * Static library that provides all operations related with division and modular |
| * arithmetic to {@link BigInteger}. Some methods are provided in both mutable |
| * and immutable way. There are several variants provided listed below: |
| * |
| * <ul type="circle"> <li><b>Division</b> <ul type="circle"> <li> |
| * {@link BigInteger} division and remainder by {@link BigInteger}.</li> <li> |
| * {@link BigInteger} division and remainder by {@code int}.</li> <li><i>gcd</i> |
| * between {@link BigInteger} numbers.</li> </ul> </li> <li><b>Modular |
| * arithmetic </b> <ul type="circle"> <li>Modular exponentiation between |
| * {@link BigInteger} numbers.</li> <li>Modular inverse of a {@link BigInteger} |
| * numbers.</li> </ul> </li> </ul> |
| */ |
| class Division { |
| |
| /** |
| * 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 |
| */ |
| 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 = Integer.numberOfLeadingZeros(b[bLength - 1]); |
| if (divisorShift != 0) { |
| BitLevel.shiftLeft(normB, b, 0, divisorShift); |
| BitLevel.shiftLeft(normA, a, 0, divisorShift); |
| } else { |
| System.arraycopy(a, 0, normA, 0, aLength); |
| System.arraycopy(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; |
| boolean 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 (Integer.numberOfLeadingZeros((int) (longR >>> 32)) < 32) { |
| rOverflowed = true; |
| } else { |
| rem = (int) longR; |
| } |
| } 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 >>>= 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; |
| } |
| System.arraycopy(normA, 0, normB, 0, bLength); |
| return normA; |
| } |
| |
| /** |
| * Computes the quotient and the remainder after a division by an {@code int} |
| * number. |
| * |
| * @return an array of the form {@code [quotient, remainder]}. |
| */ |
| static BigInteger[] divideAndRemainderByInteger(BigInteger val, int divisor, |
| int divisorSign) { |
| // res[0] is a quotient and res[1] is a remainder: |
| int[] valDigits = val.digits; |
| int valLen = val.numberLength; |
| int valSign = val.sign; |
| if (valLen == 1) { |
| long a = (valDigits[0] & 0xffffffffL); |
| long b = (divisor & 0xffffffffL); |
| long quo = a / b; |
| long rem = a % b; |
| if (valSign != divisorSign) { |
| quo = -quo; |
| } |
| if (valSign < 0) { |
| rem = -rem; |
| } |
| return new BigInteger[] {BigInteger.valueOf(quo), BigInteger.valueOf(rem)}; |
| } |
| int quotientLength = valLen; |
| int quotientSign = ((valSign == divisorSign) ? 1 : -1); |
| int quotientDigits[] = new int[quotientLength]; |
| int remainderDigits[]; |
| remainderDigits = new int[] {Division.divideArrayByInt(quotientDigits, |
| valDigits, valLen, divisor)}; |
| BigInteger result0 = new BigInteger(quotientSign, quotientLength, |
| quotientDigits); |
| BigInteger result1 = new BigInteger(valSign, 1, remainderDigits); |
| result0.cutOffLeadingZeroes(); |
| result1.cutOffLeadingZeroes(); |
| return new BigInteger[] {result0, result1}; |
| } |
| |
| /** |
| * Divides an array by an integer value. Implements the Knuth's division |
| * algorithm. See D. Knuth, The Art of Computer Programming, vol. 2. |
| * |
| * @param dest the quotient |
| * @param src the dividend |
| * @param srcLength the length of the dividend |
| * @param divisor the divisor |
| * @return remainder |
| */ |
| static int divideArrayByInt(int dest[], int src[], final int srcLength, |
| final int divisor) { |
| |
| long rem = 0; |
| long bLong = divisor & 0xffffffffL; |
| |
| for (int i = srcLength - 1; i >= 0; i--) { |
| long temp = (rem << 32) | (src[i] & 0xffffffffL); |
| long quot; |
| if (temp >= 0) { |
| quot = (temp / bLong); |
| rem = (temp % bLong); |
| } else { |
| /* |
| * make the dividend positive shifting it right by 1 bit then get the |
| * quotient an remainder and correct them properly |
| */ |
| long aPos = temp >>> 1; |
| long bPos = divisor >>> 1; |
| quot = aPos / bPos; |
| rem = aPos % bPos; |
| // double the remainder and add 1 if a is odd |
| rem = (rem << 1) + (temp & 1); |
| if ((divisor & 1) != 0) { |
| // the divisor is odd |
| if (quot <= rem) { |
| rem -= quot; |
| } else { |
| if (quot - rem <= bLong) { |
| rem += bLong - quot; |
| quot -= 1; |
| } else { |
| rem += (bLong << 1) - quot; |
| quot -= 2; |
| } |
| } |
| } |
| } |
| dest[i] = (int) (quot & 0xffffffffL); |
| } |
| return (int) rem; |
| } |
| |
| /** |
| * Divides an unsigned long a by an unsigned int b. It is supposed that the |
| * most significant bit of b is set to 1, i.e. b < 0 |
| * |
| * @param a the dividend |
| * @param b the divisor |
| * @return the long value containing the unsigned integer remainder in the |
| * left half and the unsigned integer quotient in the right half |
| */ |
| static long divideLongByInt(long a, int b) { |
| long quot; |
| long rem; |
| long bLong = b & 0xffffffffL; |
| |
| if (a >= 0) { |
| quot = (a / bLong); |
| rem = (a % bLong); |
| } else { |
| /* |
| * Make the dividend positive shifting it right by 1 bit then get the |
| * quotient an remainder and correct them properly |
| */ |
| long aPos = a >>> 1; |
| long bPos = b >>> 1; |
| quot = aPos / bPos; |
| rem = aPos % bPos; |
| // double the remainder and add 1 if a is odd |
| rem = (rem << 1) + (a & 1); |
| if ((b & 1) != 0) { // the divisor is odd |
| if (quot <= rem) { |
| rem -= quot; |
| } else { |
| if (quot - rem <= bLong) { |
| rem += bLong - quot; |
| quot -= 1; |
| } else { |
| rem += (bLong << 1) - quot; |
| quot -= 2; |
| } |
| } |
| } |
| } |
| return (rem << 32) | (quot & 0xffffffffL); |
| } |
| |
| /** |
| * Performs modular exponentiation using the Montgomery Reduction. It requires |
| * that all parameters be positive and the modulus be even. Based <i>The |
| * square and multiply algorithm and the Montgomery Reduction C. K. Koc - |
| * Montgomery Reduction with Even Modulus</i>. The square and multiply |
| * algorithm and the Montgomery Reduction. |
| * |
| * @ar.org.fitc.ref "C. K. Koc - Montgomery Reduction with Even Modulus" |
| * @see BigInteger#modPow(BigInteger, BigInteger) |
| */ |
| 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)); |
| } |
| |
| /** |
| * Performs the final reduction of the Montgomery algorithm. |
| * |
| * @see #monPro(BigInteger, BigInteger, BigInteger, long) |
| * @see #monSquare(BigInteger, BigInteger, long) |
| */ |
| static BigInteger finalSubtraction(int res[], BigInteger modulus) { |
| |
| // skipping leading zeros |
| int modulusLen = modulus.numberLength; |
| boolean doSub = res[modulusLen] != 0; |
| if (!doSub) { |
| int modulusDigits[] = modulus.digits; |
| doSub = true; |
| for (int i = modulusLen - 1; i >= 0; i--) { |
| if (res[i] != modulusDigits[i]) { |
| doSub = (res[i] != 0) |
| && ((res[i] & 0xFFFFFFFFL) > (modulusDigits[i] & 0xFFFFFFFFL)); |
| break; |
| } |
| } |
| } |
| |
| BigInteger result = new BigInteger(1, modulusLen + 1, res); |
| |
| // if (res >= modulusDigits) compute (res - modulusDigits) |
| if (doSub) { |
| Elementary.inplaceSubtract(result, modulus); |
| } |
| |
| result.cutOffLeadingZeroes(); |
| return result; |
| } |
| |
| /** |
| * @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)} |
| */ |
| 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); |
| } |
| |
| /** |
| * Performs the same as {@link #gcdBinary(BigInteger, BigInteger)}, but with |
| * numbers of 63 bits, represented in positives values of {@code long} type. |
| * |
| * @param op1 a positive number |
| * @param op2 a positive number |
| * @see #gcdBinary(BigInteger, BigInteger) |
| * @return <code>GCD(op1, op2)</code> |
| */ |
| static long gcdBinary(long op1, long op2) { |
| // PRE: (op1 > 0) and (op2 > 0) |
| int lsb1 = Long.numberOfTrailingZeros(op1); |
| int lsb2 = Long.numberOfTrailingZeros(op2); |
| int pow2Count = Math.min(lsb1, lsb2); |
| |
| if (lsb1 != 0) { |
| op1 >>>= lsb1; |
| } |
| if (lsb2 != 0) { |
| op2 >>>= lsb2; |
| } |
| do { |
| if (op1 >= op2) { |
| op1 -= op2; |
| op1 >>>= Long.numberOfTrailingZeros(op1); |
| } else { |
| op2 -= op1; |
| op2 >>>= Long.numberOfTrailingZeros(op2); |
| } |
| } while (op1 != 0); |
| return (op2 << pow2Count); |
| } |
| |
| /** |
| * Performs {@code x = x mod (2<sup>n</sup>)}. |
| * |
| * @param x a positive number, it will store the result. |
| * @param n a positive exponent of {@code 2}. |
| */ |
| 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; |
| x.digits[fd] &= (leadingZeros < 32) ? (-1 >>> leadingZeros) : 0; |
| x.cutOffLeadingZeroes(); |
| } |
| |
| /** |
| * |
| * Based on "New Algorithm for Classical Modular Inverse" Róbert Lórencz. LNCS |
| * 2523 (2002) |
| * |
| * @return a^(-1) mod m |
| */ |
| static BigInteger modInverseLorencz(BigInteger a, BigInteger modulo) { |
| // PRE: a is coprime with modulo, a < 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]; |
| System.arraycopy(modulo.digits, 0, uDigits, 0, modulo.numberLength); |
| System.arraycopy(a.digits, 0, vDigits, 0, 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) { |
| // math.19: BigInteger not invertible |
| 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; |
| } |
| |
| /** |
| * Calculates a.modInverse(p) Based on: Savas, E; Koc, C "The Montgomery |
| * Modular Inverse - Revised". |
| */ |
| static BigInteger modInverseMontgomery(BigInteger a, BigInteger p) { |
| if (a.sign == 0) { |
| // ZERO hasn't inverse |
| // math.19: BigInteger not invertible |
| throw new ArithmeticException("BigInteger not invertible."); |
| } |
| |
| if (!p.testBit(0)) { |
| // montgomery inverse require even modulo |
| return modInverseLorencz(a, p); |
| } |
| |
| int m = p.numberLength * 32; |
| // PRE: a \in [1, p - 1] |
| BigInteger u, v, r, s; |
| u = p.copy(); // make copy to use inplace method |
| v = a.copy(); |
| int max = Math.max(v.numberLength, u.numberLength); |
| r = new BigInteger(1, 1, new int[max + 1]); |
| s = new BigInteger(1, 1, new int[max + 1]); |
| s.digits[0] = 1; |
| // s == 1 && v == 0 |
| |
| int k = 0; |
| |
| int lsbu = u.getLowestSetBit(); |
| int lsbv = v.getLowestSetBit(); |
| int toShift; |
| |
| if (lsbu > lsbv) { |
| BitLevel.inplaceShiftRight(u, lsbu); |
| BitLevel.inplaceShiftRight(v, lsbv); |
| BitLevel.inplaceShiftLeft(r, lsbv); |
| k += lsbu - lsbv; |
| } else { |
| BitLevel.inplaceShiftRight(u, lsbu); |
| BitLevel.inplaceShiftRight(v, lsbv); |
| BitLevel.inplaceShiftLeft(s, lsbu); |
| k += lsbv - lsbu; |
| } |
| |
| r.sign = 1; |
| while (v.signum() > 0) { |
| // INV v >= 0, u >= 0, v odd, u odd (except last iteration when v is even |
| // (0)) |
| |
| while (u.compareTo(v) > BigInteger.EQUALS) { |
| Elementary.inplaceSubtract(u, v); |
| toShift = u.getLowestSetBit(); |
| BitLevel.inplaceShiftRight(u, toShift); |
| Elementary.inplaceAdd(r, s); |
| BitLevel.inplaceShiftLeft(s, toShift); |
| k += toShift; |
| } |
| |
| while (u.compareTo(v) <= BigInteger.EQUALS) { |
| Elementary.inplaceSubtract(v, u); |
| if (v.signum() == 0) { |
| break; |
| } |
| toShift = v.getLowestSetBit(); |
| BitLevel.inplaceShiftRight(v, toShift); |
| Elementary.inplaceAdd(s, r); |
| BitLevel.inplaceShiftLeft(r, toShift); |
| k += toShift; |
| } |
| } |
| if (!u.isOne()) { |
| // in u is stored the gcd |
| // math.19: BigInteger not invertible. |
| throw new ArithmeticException("BigInteger not invertible."); |
| } |
| if (r.compareTo(p) >= BigInteger.EQUALS) { |
| Elementary.inplaceSubtract(r, p); |
| } |
| |
| r = p.subtract(r); |
| |
| // Have pair: ((BigInteger)r, (Integer)k) where r == a^(-1) * 2^k mod |
| // (module) |
| int n1 = calcN(p); |
| if (k > m) { |
| r = monPro(r, BigInteger.ONE, p, n1); |
| k = k - m; |
| } |
| |
| r = monPro(r, BigInteger.getPowerOfTwo(m - k), p, n1); |
| return r; |
| } |
| |
| /** |
| * @param x an odd positive number. |
| * @param n the exponent by which 2 is raised. |
| * @return {@code x<sup>-1</sup> (mod 2<sup>n</sup>)}. |
| */ |
| static BigInteger modPow2Inverse(BigInteger x, int n) { |
| // PRE: (x > 0), (x is odd), and (n > 0) |
| BigInteger y = new BigInteger(1, new int[1 << n]); |
| y.numberLength = 1; |
| y.digits[0] = 1; |
| y.sign = 1; |
| |
| for (int i = 1; i < n; i++) { |
| if (BitLevel.testBit(x.multiply(y), i)) { |
| // Adding 2^i to y (setting the i-th bit) |
| y.digits[i >> 5] |= (1 << (i & 31)); |
| } |
| } |
| return y; |
| } |
| |
| /** |
| * Implements the Montgomery Product of two integers represented by {@code |
| * int} arrays. The arrays are supposed in <i>little endian</i> notation. |
| * |
| * @param a The first factor of the product. |
| * @param b The second factor of the product. |
| * @param modulus The modulus of the operations. Z<sub>modulus</sub>. |
| * @param n2 The digit modulus'[0]. |
| * @ar.org.fitc.ref "C. K. Koc - Analyzing and Comparing Montgomery |
| * Multiplication Algorithms" |
| * @see #modPowOdd(BigInteger, BigInteger, BigInteger) |
| */ |
| static BigInteger monPro(BigInteger a, BigInteger b, BigInteger modulus, |
| int n2) { |
| int modulusLen = modulus.numberLength; |
| int res[] = new int[(modulusLen << 1) + 1]; |
| Multiplication.multArraysPAP(a.digits, |
| Math.min(modulusLen, a.numberLength), b.digits, Math.min(modulusLen, |
| b.numberLength), res); |
| monReduction(res, modulus, n2); |
| return finalSubtraction(res, modulus); |
| } |
| |
| /** |
| * Multiplies an array by int and subtracts it from a subarray of another |
| * array. |
| * |
| * @param a the array to subtract from |
| * @param start the start element of the subarray of a |
| * @param b the array to be multiplied and subtracted |
| * @param bLen the length of b |
| * @param c the multiplier of b |
| * @return the carry element of subtraction |
| */ |
| static int multiplyAndSubtract(int a[], int start, int b[], int bLen, int c) { |
| long carry0 = 0; |
| long carry1 = 0; |
| |
| for (int i = 0; i < bLen; i++) { |
| carry0 = Multiplication.unsignedMultAddAdd(b[i], c, (int) carry0, 0); |
| carry1 = (a[start + i] & 0xffffffffL) - (carry0 & 0xffffffffL) + carry1; |
| a[start + i] = (int) carry1; |
| carry1 >>= 32; // -1 or 0 |
| carry0 >>>= 32; |
| } |
| |
| carry1 = (a[start + bLen] & 0xffffffffL) - carry0 + carry1; |
| a[start + bLen] = (int) carry1; |
| return (int) (carry1 >> 32); // -1 or 0 |
| } |
| |
| /** |
| * Performs modular exponentiation using the Montgomery Reduction. It requires |
| * that all parameters be positive and the modulus be odd. > |
| * |
| * @see BigInteger#modPow(BigInteger, BigInteger) |
| * @see #monPro(BigInteger, BigInteger, BigInteger, int) |
| * @see #slidingWindow(BigInteger, BigInteger, BigInteger, BigInteger, int) |
| * @see #squareAndMultiply(BigInteger, BigInteger, BigInteger, BigInteger, |
| * int) |
| */ |
| 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); |
| } |
| |
| /** |
| * It requires that all parameters be positive. |
| * |
| * @return {@code base<sup>exponent</sup> mod (2<sup>j</sup>)}. |
| * @see BigInteger#modPow(BigInteger, BigInteger) |
| */ |
| 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; |
| } |
| |
| /** |
| * Divides a <code>BigInteger</code> by a signed <code>int</code> and returns |
| * the remainder. |
| * |
| * @param dividend the BigInteger to be divided. Must be non-negative. |
| * @param divisor a signed int |
| * @return divide % divisor |
| */ |
| static int remainder(BigInteger dividend, int divisor) { |
| return remainderArrayByInt(dividend.digits, dividend.numberLength, divisor); |
| } |
| |
| /** |
| * Divides an array by an integer value. Implements the Knuth's division |
| * algorithm. See D. Knuth, The Art of Computer Programming, vol. 2. |
| * |
| * @param src the dividend |
| * @param srcLength the length of the dividend |
| * @param divisor the divisor |
| * @return remainder |
| */ |
| static int remainderArrayByInt(int src[], final int srcLength, |
| final int divisor) { |
| |
| long result = 0; |
| |
| for (int i = srcLength - 1; i >= 0; i--) { |
| long temp = (result << 32) + (src[i] & 0xffffffffL); |
| long res = divideLongByInt(temp, divisor); |
| result = (int) (res >> 32); |
| } |
| return (int) result; |
| } |
| |
| /* |
| * Implements the Montgomery modular exponentiation based in <i>The sliding |
| * windows algorithm and the MongomeryReduction</i>. |
| * |
| * @ar.org.fitc.ref |
| * "A. Menezes,P. van Oorschot, S. Vanstone - Handbook of Applied Cryptography" |
| * ; |
| * |
| * @see #oddModPow(BigInteger, BigInteger, BigInteger) |
| */ |
| 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; |
| } |
| |
| 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; |
| } |
| |
| /** |
| * Calculate the first digit of the inverse. |
| */ |
| private static int calcN(BigInteger a) { |
| long m0 = a.digits[0] & 0xFFFFFFFFL; |
| long n2 = 1L; // this is a'[0] |
| long powerOfTwo = 2L; |
| do { |
| if (((m0 * n2) & powerOfTwo) != 0) { |
| n2 |= powerOfTwo; |
| } |
| powerOfTwo <<= 1; |
| } while (powerOfTwo < 0x100000000L); |
| n2 = -n2; |
| return (int) (n2 & 0xFFFFFFFFL); |
| } |
| |
| /** |
| * Calculate how many iteration of Lorencz's algorithm would perform the same |
| * operation. |
| * |
| * @param bi |
| * @param n |
| * @return |
| */ |
| 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()); |
| } |
| } |
| |
| /** |
| * Returns {@code bi == abs(2^exp)}. |
| */ |
| private static boolean isPowerOfTwo(BigInteger bi, int exp) { |
| boolean result = false; |
| result = (exp >> 5 == bi.numberLength - 1) |
| && (bi.digits[bi.numberLength - 1] == 1 << (exp & 31)); |
| if (result) { |
| for (int i = 0; result && i < bi.numberLength - 1; i++) { |
| result = bi.digits[i] == 0; |
| } |
| } |
| return result; |
| } |
| |
| private static void monReduction(int[] res, BigInteger modulus, int n2) { |
| |
| /* res + m*modulus_digits */ |
| int[] modulusDigits = modulus.digits; |
| int modulusLen = modulus.numberLength; |
| long outerCarry = 0; |
| |
| for (int i = 0; i < modulusLen; i++) { |
| long innnerCarry = 0; |
| int m = (int) Multiplication.unsignedMultAddAdd(res[i], n2, 0, 0); |
| for (int j = 0; j < modulusLen; j++) { |
| innnerCarry = Multiplication.unsignedMultAddAdd(m, modulusDigits[j], |
| res[i + j], (int) innnerCarry); |
| res[i + j] = (int) innnerCarry; |
| innnerCarry >>>= 32; |
| } |
| |
| outerCarry += (res[i + modulusLen] & 0xFFFFFFFFL) + innnerCarry; |
| res[i + modulusLen] = (int) outerCarry; |
| outerCarry >>>= 32; |
| } |
| |
| res[modulusLen << 1] = (int) outerCarry; |
| |
| /* res / r */ |
| for (int j = 0; j < modulusLen + 1; j++) { |
| res[j] = res[j + modulusLen]; |
| } |
| } |
| } |