Modular inverse
From Wikipedia:
- In modular arithmetic, the modular multiplicative inverse of an integer a modulo m is an integer x such that
Or in other words, such that:
It can be shown that such an inverse exists if and only if a and m are coprime, but we will ignore this for this task.
Either by implementing the algorithm, by using a dedicated library or by using a builtin function in your language, compute the modular inverse of 42 modulo 2017.
C
<lang c>#include <stdio.h>
int mul_inv(int a, int b) { int b0 = b, t, q; int x0 = 0, x1 = 1; if (b == 1) return 1; while (a > 1) { q = a / b; t = b, b = a % b, a = t; t = x0, x0 = x1 - q * x0, x1 = t; } if (x1 < 0) x1 += b0; return x1; }
int main(void) { printf("%d\n", mul_inv(42, 2017)); return 0; }</lang>
Haskell
<lang haskell>-- Extended Euclidean algorithm. Given non-negative a and b, return x, y and g -- such that ax + by = g, where g = gcd(a,b). Note that x or y may be negative. gcdExt a 0 = (1, 0, a) gcdExt a b = let (q, r) = a `quotRem` b
(s, t, g) = gcdExt b r in (t, s - q * t, g)
-- Given a and m, return Just x such that ax = 1 mod m. If there is no such x -- return Nothing. modInv a m = let (i, _, g) = gcdExt a m
in if g == 1 then Just (mkPos i) else Nothing where mkPos x = if x < 0 then x + m else x
main = do
print $ 2 `modInv` 4 print $ 42 `modInv` 2017</lang>
Output
Nothing Just 1969
J
Solution:<lang j> modInv =: dyad def 'x y&|@^ <: 5 p: y'"0</lang> Example:<lang j> 42 modInv 2017 1969</lang> Notes: Calculates the modular inverse as a^( totient(m) - 1 ) mod m. Note that J has a fast implementation of modular exponentiation (which avoids the exponentiation altogether), invoked with the form m&|@^ (hence, we use explicitly-named arguments for this entry, as opposed to the "variable free" tacit style).
Java
The BigInteger
library has a method for this:
<lang java>System.out.println(BigInteger.valueOf(42).modInverse(BigInteger.valueOf(2017)));</lang>
- Output:
1969
Perl
The modular inverse is not a perl builtin but there is a CPAN module who does the job.
<lang perl>use Math::ModInt qw(mod); print mod(42, 2017)->inverse</lang>
- Output:
mod(1969, 2017)
Perl 6
<lang perl6>sub inverse(Int $n, Int :$modulo) returns Int {
my Int ($c, $d, $uc, $vc, $ud, $vd) = ($n % $modulo, $modulo, 1, 0, 0, 1); my Int $q; while $c != 0 { ($q, $c, $d) = ($d div $c, $d % $c, $c); ($uc, $vc, $ud, $vd) = ($ud - $q*$uc, $vd - $q*$vc, $uc, $vc); } return $ud < 0 ?? $ud + $modulo !! $ud;
}
say inverse 42, :modulo(2017)</lang>
Python
Implementation of this pseudocode with this. <lang python>>>> def extended_gcd(aa, bb):
lastremainder, remainder = abs(aa), abs(bb) x, lastx, y, lasty = 0, 1, 1, 0 while remainder: lastremainder, (quotient, remainder) = remainder, divmod(lastremainder, remainder) x, lastx = lastx - quotient*x, x y, lasty = lasty - quotient*y, y return lastremainder, lastx * (-1 if aa < 0 else 1), lasty * (-1 if bb < 0 else 1)
>>> def modinv(a, m): g, x, y = extended_gcd(a, m) if g != 1: raise ValueError return x % m
>>> modinv(42, 2017) 1969 >>> </lang>
Run BASIC
<lang runbasic>print multInv(42, 2017) end
function multInv(a,b) b0 = b multInv = 1 if b = 1 then goto [endFun] while a > 1 q = a / b t = b b = a mod b a = t t = x0 x0 = multInv - q * x0 multInv = int(t) wend if multInv < 0 then multInv = multInv + b0 [endFun] end function</lang>1969