64)
jaroslav@1258: return euclidModInverse(k);
jaroslav@1258:
jaroslav@1258: int t = inverseMod32(value[offset+intLen-1]);
jaroslav@1258:
jaroslav@1258: if (k < 33) {
jaroslav@1258: t = (k == 32 ? t : t & ((1 << k) - 1));
jaroslav@1258: return new MutableBigInteger(t);
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: long pLong = (value[offset+intLen-1] & LONG_MASK);
jaroslav@1258: if (intLen > 1)
jaroslav@1258: pLong |= ((long)value[offset+intLen-2] << 32);
jaroslav@1258: long tLong = t & LONG_MASK;
jaroslav@1258: tLong = tLong * (2 - pLong * tLong); // 1 more Newton iter step
jaroslav@1258: tLong = (k == 64 ? tLong : tLong & ((1L << k) - 1));
jaroslav@1258:
jaroslav@1258: MutableBigInteger result = new MutableBigInteger(new int[2]);
jaroslav@1258: result.value[0] = (int)(tLong >>> 32);
jaroslav@1258: result.value[1] = (int)tLong;
jaroslav@1258: result.intLen = 2;
jaroslav@1258: result.normalize();
jaroslav@1258: return result;
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: /*
jaroslav@1258: * Returns the multiplicative inverse of val mod 2^32. Assumes val is odd.
jaroslav@1258: */
jaroslav@1258: static int inverseMod32(int val) {
jaroslav@1258: // Newton's iteration!
jaroslav@1258: int t = val;
jaroslav@1258: t *= 2 - val*t;
jaroslav@1258: t *= 2 - val*t;
jaroslav@1258: t *= 2 - val*t;
jaroslav@1258: t *= 2 - val*t;
jaroslav@1258: return t;
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: /*
jaroslav@1258: * Calculate the multiplicative inverse of 2^k mod mod, where mod is odd.
jaroslav@1258: */
jaroslav@1258: static MutableBigInteger modInverseBP2(MutableBigInteger mod, int k) {
jaroslav@1258: // Copy the mod to protect original
jaroslav@1258: return fixup(new MutableBigInteger(1), new MutableBigInteger(mod), k);
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: /**
jaroslav@1258: * Calculate the multiplicative inverse of this mod mod, where mod is odd.
jaroslav@1258: * This and mod are not changed by the calculation.
jaroslav@1258: *
jaroslav@1258: * This method implements an algorithm due to Richard Schroeppel, that uses
jaroslav@1258: * the same intermediate representation as Montgomery Reduction
jaroslav@1258: * ("Montgomery Form"). The algorithm is described in an unpublished
jaroslav@1258: * manuscript entitled "Fast Modular Reciprocals."
jaroslav@1258: */
jaroslav@1258: private MutableBigInteger modInverse(MutableBigInteger mod) {
jaroslav@1258: MutableBigInteger p = new MutableBigInteger(mod);
jaroslav@1258: MutableBigInteger f = new MutableBigInteger(this);
jaroslav@1258: MutableBigInteger g = new MutableBigInteger(p);
jaroslav@1258: SignedMutableBigInteger c = new SignedMutableBigInteger(1);
jaroslav@1258: SignedMutableBigInteger d = new SignedMutableBigInteger();
jaroslav@1258: MutableBigInteger temp = null;
jaroslav@1258: SignedMutableBigInteger sTemp = null;
jaroslav@1258:
jaroslav@1258: int k = 0;
jaroslav@1258: // Right shift f k times until odd, left shift d k times
jaroslav@1258: if (f.isEven()) {
jaroslav@1258: int trailingZeros = f.getLowestSetBit();
jaroslav@1258: f.rightShift(trailingZeros);
jaroslav@1258: d.leftShift(trailingZeros);
jaroslav@1258: k = trailingZeros;
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: // The Almost Inverse Algorithm
jaroslav@1258: while(!f.isOne()) {
jaroslav@1258: // If gcd(f, g) != 1, number is not invertible modulo mod
jaroslav@1258: if (f.isZero())
jaroslav@1258: throw new ArithmeticException("BigInteger not invertible.");
jaroslav@1258:
jaroslav@1258: // If f < g exchange f, g and c, d
jaroslav@1258: if (f.compare(g) < 0) {
jaroslav@1258: temp = f; f = g; g = temp;
jaroslav@1258: sTemp = d; d = c; c = sTemp;
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: // If f == g (mod 4)
jaroslav@1258: if (((f.value[f.offset + f.intLen - 1] ^
jaroslav@1258: g.value[g.offset + g.intLen - 1]) & 3) == 0) {
jaroslav@1258: f.subtract(g);
jaroslav@1258: c.signedSubtract(d);
jaroslav@1258: } else { // If f != g (mod 4)
jaroslav@1258: f.add(g);
jaroslav@1258: c.signedAdd(d);
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: // Right shift f k times until odd, left shift d k times
jaroslav@1258: int trailingZeros = f.getLowestSetBit();
jaroslav@1258: f.rightShift(trailingZeros);
jaroslav@1258: d.leftShift(trailingZeros);
jaroslav@1258: k += trailingZeros;
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: while (c.sign < 0)
jaroslav@1258: c.signedAdd(p);
jaroslav@1258:
jaroslav@1258: return fixup(c, p, k);
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: /*
jaroslav@1258: * The Fixup Algorithm
jaroslav@1258: * Calculates X such that X = C * 2^(-k) (mod P)
jaroslav@1258: * Assumes C> 5; i= 0)
jaroslav@1258: c.subtract(p);
jaroslav@1258:
jaroslav@1258: return c;
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: /**
jaroslav@1258: * Uses the extended Euclidean algorithm to compute the modInverse of base
jaroslav@1258: * mod a modulus that is a power of 2. The modulus is 2^k.
jaroslav@1258: */
jaroslav@1258: MutableBigInteger euclidModInverse(int k) {
jaroslav@1258: MutableBigInteger b = new MutableBigInteger(1);
jaroslav@1258: b.leftShift(k);
jaroslav@1258: MutableBigInteger mod = new MutableBigInteger(b);
jaroslav@1258:
jaroslav@1258: MutableBigInteger a = new MutableBigInteger(this);
jaroslav@1258: MutableBigInteger q = new MutableBigInteger();
jaroslav@1258: MutableBigInteger r = b.divide(a, q);
jaroslav@1258:
jaroslav@1258: MutableBigInteger swapper = b;
jaroslav@1258: // swap b & r
jaroslav@1258: b = r;
jaroslav@1258: r = swapper;
jaroslav@1258:
jaroslav@1258: MutableBigInteger t1 = new MutableBigInteger(q);
jaroslav@1258: MutableBigInteger t0 = new MutableBigInteger(1);
jaroslav@1258: MutableBigInteger temp = new MutableBigInteger();
jaroslav@1258:
jaroslav@1258: while (!b.isOne()) {
jaroslav@1258: r = a.divide(b, q);
jaroslav@1258:
jaroslav@1258: if (r.intLen == 0)
jaroslav@1258: throw new ArithmeticException("BigInteger not invertible.");
jaroslav@1258:
jaroslav@1258: swapper = r;
jaroslav@1258: a = swapper;
jaroslav@1258:
jaroslav@1258: if (q.intLen == 1)
jaroslav@1258: t1.mul(q.value[q.offset], temp);
jaroslav@1258: else
jaroslav@1258: q.multiply(t1, temp);
jaroslav@1258: swapper = q;
jaroslav@1258: q = temp;
jaroslav@1258: temp = swapper;
jaroslav@1258: t0.add(q);
jaroslav@1258:
jaroslav@1258: if (a.isOne())
jaroslav@1258: return t0;
jaroslav@1258:
jaroslav@1258: r = b.divide(a, q);
jaroslav@1258:
jaroslav@1258: if (r.intLen == 0)
jaroslav@1258: throw new ArithmeticException("BigInteger not invertible.");
jaroslav@1258:
jaroslav@1258: swapper = b;
jaroslav@1258: b = r;
jaroslav@1258:
jaroslav@1258: if (q.intLen == 1)
jaroslav@1258: t0.mul(q.value[q.offset], temp);
jaroslav@1258: else
jaroslav@1258: q.multiply(t0, temp);
jaroslav@1258: swapper = q; q = temp; temp = swapper;
jaroslav@1258:
jaroslav@1258: t1.add(q);
jaroslav@1258: }
jaroslav@1258: mod.subtract(t1);
jaroslav@1258: return mod;
jaroslav@1258: }
jaroslav@1258:
jaroslav@1258: }