| Index: third_party/bigint/BigIntegerAlgorithms.cc
|
| diff --git a/third_party/bigint/BigIntegerAlgorithms.cc b/third_party/bigint/BigIntegerAlgorithms.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7edebda76a8e17de58dcb3476bc02e3d6be5a249
|
| --- /dev/null
|
| +++ b/third_party/bigint/BigIntegerAlgorithms.cc
|
| @@ -0,0 +1,70 @@
|
| +#include "BigIntegerAlgorithms.hh"
|
| +
|
| +BigUnsigned gcd(BigUnsigned a, BigUnsigned b) {
|
| + BigUnsigned trash;
|
| + // Neat in-place alternating technique.
|
| + for (;;) {
|
| + if (b.isZero())
|
| + return a;
|
| + a.divideWithRemainder(b, trash);
|
| + if (a.isZero())
|
| + return b;
|
| + b.divideWithRemainder(a, trash);
|
| + }
|
| +}
|
| +
|
| +void extendedEuclidean(BigInteger m, BigInteger n,
|
| + BigInteger &g, BigInteger &r, BigInteger &s) {
|
| + if (&g == &r || &g == &s || &r == &s)
|
| + throw "BigInteger extendedEuclidean: Outputs are aliased";
|
| + BigInteger r1(1), s1(0), r2(0), s2(1), q;
|
| + /* Invariants:
|
| + * r1*m(orig) + s1*n(orig) == m(current)
|
| + * r2*m(orig) + s2*n(orig) == n(current) */
|
| + for (;;) {
|
| + if (n.isZero()) {
|
| + r = r1; s = s1; g = m;
|
| + return;
|
| + }
|
| + // Subtract q times the second invariant from the first invariant.
|
| + m.divideWithRemainder(n, q);
|
| + r1 -= q*r2; s1 -= q*s2;
|
| +
|
| + if (m.isZero()) {
|
| + r = r2; s = s2; g = n;
|
| + return;
|
| + }
|
| + // Subtract q times the first invariant from the second invariant.
|
| + n.divideWithRemainder(m, q);
|
| + r2 -= q*r1; s2 -= q*s1;
|
| + }
|
| +}
|
| +
|
| +BigUnsigned modinv(const BigInteger &x, const BigUnsigned &n) {
|
| + BigInteger g, r, s;
|
| + extendedEuclidean(x, n, g, r, s);
|
| + if (g == 1)
|
| + // r*x + s*n == 1, so r*x === 1 (mod n), so r is the answer.
|
| + return (r % n).getMagnitude(); // (r % n) will be nonnegative
|
| + else
|
| + throw "BigInteger modinv: x and n have a common factor";
|
| +}
|
| +
|
| +BigUnsigned modexp(const BigInteger &base, const BigUnsigned &exponent,
|
| + const BigUnsigned &modulus) {
|
| + BigUnsigned ans = 1, base2 = (base % modulus).getMagnitude();
|
| + BigUnsigned::Index i = exponent.bitLength();
|
| + // For each bit of the exponent, most to least significant...
|
| + while (i > 0) {
|
| + i--;
|
| + // Square.
|
| + ans *= ans;
|
| + ans %= modulus;
|
| + // And multiply if the bit is a 1.
|
| + if (exponent.getBit(i)) {
|
| + ans *= base2;
|
| + ans %= modulus;
|
| + }
|
| + }
|
| + return ans;
|
| +}
|
|
|