1017 |
return xy; |
return xy; |
1018 |
} |
} |
1019 |
|
|
1020 |
private static final void euclidInv(BigInteger a, BigInteger b, |
private static final BigInteger[] euclidInv(BigInteger a, BigInteger b, |
1021 |
BigInteger prevDiv, BigInteger xy0, |
BigInteger prevDiv) |
|
BigInteger xy1, BigInteger xy2) |
|
1022 |
{ |
{ |
1023 |
if (b.isZero()) |
if (b.isZero()) |
1024 |
throw new ArithmeticException("not invertible"); |
throw new ArithmeticException("not invertible"); |
1027 |
{ |
{ |
1028 |
// Success: values are indeed invertible! |
// Success: values are indeed invertible! |
1029 |
// Bottom of the recursion reached; start unwinding. |
// Bottom of the recursion reached; start unwinding. |
1030 |
// WARNING: xy1 is, and xy0 may be, a shared BI! |
return new BigInteger[] { neg(prevDiv), ONE }; |
|
xy0 = neg(prevDiv); |
|
|
xy1 = ONE; |
|
|
return; |
|
1031 |
} |
} |
1032 |
|
|
1033 |
|
BigInteger[] result; |
1034 |
// Recursion happens in the following conditional! |
// Recursion happens in the following conditional! |
1035 |
|
|
1036 |
// If a just contains an int, then use integer math for the rest. |
// If a just contains an int, then use integer math for the rest. |
1037 |
if (a.words == null) |
if (a.words == null) |
1038 |
{ |
{ |
1039 |
int[] xyInt = euclidInv(b.ival, a.ival % b.ival, a.ival / b.ival); |
int[] xyInt = euclidInv(b.ival, a.ival % b.ival, a.ival / b.ival); |
1040 |
xy0 = new BigInteger(xyInt[0]); // non-shared BI |
result = new BigInteger[] { // non-shared BI |
1041 |
xy1 = new BigInteger(xyInt[1]); // non-shared BI |
new BigInteger(xyInt[0]), |
1042 |
|
new BigInteger(xyInt[1]) |
1043 |
|
}; |
1044 |
} |
} |
1045 |
else |
else |
1046 |
{ |
{ |
1050 |
// quot and rem may not be in canonical form. ensure |
// quot and rem may not be in canonical form. ensure |
1051 |
rem.canonicalize(); |
rem.canonicalize(); |
1052 |
quot.canonicalize(); |
quot.canonicalize(); |
1053 |
euclidInv(b, rem, quot, xy0, xy1, xy2); |
result = euclidInv(b, rem, quot); |
1054 |
} |
} |
1055 |
|
|
1056 |
// xy2 is just temp storage for intermediate results in the following |
BigInteger t = result[0]; |
1057 |
// calculation. This saves us a bit of space over having a BigInteger |
result[0] = add(result[1], times(t, prevDiv), -1); |
1058 |
// allocated at every level of this recursive method. |
result[1] = t; |
1059 |
xy2 = xy0; |
return result; |
|
xy0 = add(xy1, times(xy2, prevDiv), -1); |
|
|
xy1 = xy2; |
|
1060 |
} |
} |
1061 |
|
|
1062 |
public BigInteger modInverse(BigInteger y) |
public BigInteger modInverse(BigInteger y) |
1126 |
quot.canonicalize(); |
quot.canonicalize(); |
1127 |
BigInteger xy0 = new BigInteger(); |
BigInteger xy0 = new BigInteger(); |
1128 |
BigInteger xy1 = new BigInteger(); |
BigInteger xy1 = new BigInteger(); |
1129 |
euclidInv(y, rem, quot, xy0, xy1, result); |
BigInteger[] xy = euclidInv(y, rem, quot); |
1130 |
result = swapped ? xy0 : xy1; |
result = swapped ? xy[0] : xy[1]; |
1131 |
|
|
1132 |
// Result can't be negative, so make it positive by adding the |
// Result can't be negative, so make it positive by adding the |
1133 |
// original modulus, y (which is now x if they were swapped). |
// original modulus, y (which is now x if they were swapped). |