Well, you can try starting from Extended Euclid Algorithm, e.g. (let it be implemented as extension methods)
public static (BigInteger LeftFactor,
BigInteger RightFactor,
BigInteger Gcd) Egcd(this BigInteger left, BigInteger right) {
BigInteger leftFactor = 0;
BigInteger rightFactor = 1;
BigInteger u = 1;
BigInteger v = 0;
BigInteger gcd = 0;
while (left != 0) {
BigInteger q = right / left;
BigInteger r = right % left;
BigInteger m = leftFactor - u * q;
BigInteger n = rightFactor - v * q;
right = left;
left = r;
leftFactor = u;
rightFactor = v;
u = m;
v = n;
gcd = right;
}
return (LeftFactor: leftFactor,
RightFactor: rightFactor,
Gcd: gcd);
}
Then you can continue with mod inversion and mod division:
public static BigInteger ModInversion(this BigInteger value, BigInteger modulo) {
var egcd = Egcd(value, modulo);
if (egcd.Gcd != 1)
throw new ArgumentException("Invalid modulo", nameof(modulo));
BigInteger result = egcd.LeftFactor;
if (result < 0)
result += modulo;
return result % modulo;
}
public static BigInteger ModDivision(
this BigInteger left, BigInteger right, BigInteger modulo) =>
(left * ModInversion(right, modulo)) % modulo;
Finally, your test:
BigInteger b = new BigInteger(12345678912345678912);
//DONE: Please, note that ^ stands for XOR, so 2 ^ 64 == 66
BigInteger mod = BigInteger.Pow(2, 64);
var modedInteger = b * 3712931 % mod;
BigInteger result = modedInteger.ModDivision(3712931, mod);
Console.Write(result);
Outcome:
12345678912345678912