1017 |
return xy; |
return xy; |
1018 |
} |
} |
1019 |
|
|
1020 |
private static final BigInteger[] euclidInv(BigInteger a, BigInteger b, |
private static final void euclidInv(BigInteger a, BigInteger b, |
1021 |
BigInteger prevDiv) |
BigInteger prevDiv, BigInteger[] xy) |
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 |
return new BigInteger[] { neg(prevDiv), ONE }; |
xy[0] = neg(prevDiv); |
1031 |
|
xy[1] = ONE; |
1032 |
|
return; |
1033 |
} |
} |
1034 |
|
|
|
BigInteger[] result; |
|
1035 |
// Recursion happens in the following conditional! |
// Recursion happens in the following conditional! |
1036 |
|
|
1037 |
// 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. |
1038 |
if (a.words == null) |
if (a.words == null) |
1039 |
{ |
{ |
1040 |
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); |
1041 |
result = new BigInteger[] { // non-shared BI |
xy[0] = new BigInteger(xyInt[0]); |
1042 |
new BigInteger(xyInt[0]), |
xy[1] = new BigInteger(xyInt[1]); |
|
new BigInteger(xyInt[1]) |
|
|
}; |
|
1043 |
} |
} |
1044 |
else |
else |
1045 |
{ |
{ |
1049 |
// quot and rem may not be in canonical form. ensure |
// quot and rem may not be in canonical form. ensure |
1050 |
rem.canonicalize(); |
rem.canonicalize(); |
1051 |
quot.canonicalize(); |
quot.canonicalize(); |
1052 |
result = euclidInv(b, rem, quot); |
euclidInv(b, rem, quot, xy); |
1053 |
} |
} |
1054 |
|
|
1055 |
BigInteger t = result[0]; |
BigInteger t = xy[0]; |
1056 |
result[0] = add(result[1], times(t, prevDiv), -1); |
xy[0] = add(xy[1], times(t, prevDiv), -1); |
1057 |
result[1] = t; |
xy[1] = t; |
|
return result; |
|
1058 |
} |
} |
1059 |
|
|
1060 |
public BigInteger modInverse(BigInteger y) |
public BigInteger modInverse(BigInteger y) |
1122 |
// quot and rem may not be in canonical form. ensure |
// quot and rem may not be in canonical form. ensure |
1123 |
rem.canonicalize(); |
rem.canonicalize(); |
1124 |
quot.canonicalize(); |
quot.canonicalize(); |
1125 |
BigInteger xy0 = new BigInteger(); |
BigInteger[] xy = new BigInteger[2]; |
1126 |
BigInteger xy1 = new BigInteger(); |
euclidInv(y, rem, quot, xy); |
|
BigInteger[] xy = euclidInv(y, rem, quot); |
|
1127 |
result = swapped ? xy[0] : xy[1]; |
result = swapped ? xy[0] : xy[1]; |
1128 |
|
|
1129 |
// Result can't be negative, so make it positive by adding the |
// Result can't be negative, so make it positive by adding the |