This commit is contained in:
Ingy döt Net 2013-04-10 21:29:02 -07:00
parent 764da6cbbb
commit db842d013d
19005 changed files with 197040 additions and 7 deletions

View file

@ -0,0 +1,12 @@
From [http://en.wikipedia.org/wiki/Modular_multiplicative_inverse Wikipedia]:
:In [[wp:modular arithmetic|modular arithmetic]], the '''modular multiplicative inverse''' of an [[integer]] ''a'' [[wp:modular arithmetic|modulo]] ''m'' is an integer ''x'' such that
::<math>a^{-1} \equiv x \pmod{m}.</math>
Or in other words, such that:
:<math>\exists k \in\mathbf{Z},\qquad a\, x = 1 + k\,m</math>
It can be shown that such an inverse exists if and only if a and m are [[wp:coprime|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.

View file

@ -0,0 +1,42 @@
with Ada.Text_IO;
procedure Mod_Inv is
procedure X_GCD(A, B: in Natural; D, X, Y: out Integer) is
-- the Extended Euclidean Algorithm
-- finds (D, X, Y) with D = GCD(A, B) = A*X + B*Y
R: Natural := A mod B;
begin
if R=0 then
D := B;
X := 0;
Y := 1;
else
X_GCD(B, R, D, Y, X);
Y := Y - (A/B)*X;
end if;
end X_GCD;
function Inverse(A, M: Integer) return Integer is
-- computes the multiplicative inverse of A mod M, using X_GCD
Result, GCD, Dummy: Integer;
begin
X_GCD(A, M, GCD, Result, Dummy);
if GCD /= 1 then -- inverse does not exist!
raise Constraint_Error with
"GCD (" & Integer'Image(A) & "," & Integer'Image(M) & " ) =" &
Integer'Image(GCD) & " /= 1";
else -- make sure Result is in {0, ..., M-1}
if Result < 0 then
return Result+M;
else
return Result;
end if;
end if;
end Inverse;
begin
Ada.Text_IO.Put_Line(Natural'Image(Inverse(42, 2017)));
-- Ada.Text_IO.Put_Line(Natural'Image(Inverse(154, 3311)));
-- The above would raise CONSTRAINT_ERROR : GCD ( 154, 3311 ) = 77 /= 1
end Mod_Inv;

View file

@ -0,0 +1,20 @@
#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;
}

View file

@ -0,0 +1,23 @@
T modInverse(T)(T a, T b) pure nothrow {
if (b == 1)
return 1;
T b0 = b,
x0 = 0,
x1 = 1;
while (a > 1) {
immutable q = a / b;
auto t = b;
b = a % b;
a = t;
t = x0;
x0 = x1 - q * x0;
x1 = t;
}
return (x1 < 0) ? (x1 + b0) : x1;
}
void main() {
import std.stdio;
writeln(modInverse(42, 2017));
}

View file

@ -0,0 +1,13 @@
package main
import (
"fmt"
"math/big"
)
func main() {
a := big.NewInt(42)
m := big.NewInt(2017)
k := new(big.Int).ModInverse(a, m)
fmt.Println(k)
}

View file

@ -0,0 +1,16 @@
-- 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

View file

@ -0,0 +1,16 @@
procedure main(args)
a := integer(args[1]) | 42
b := integer(args[2]) | 2017
write(mul_inv(a,b))
end
procedure mul_inv(a,b)
if b == 1 then return 1
(b0 := b, x0 := 0, x1 := 1)
while a > 1 do {
q := a/b
(t := b, b := a%b, a := t)
(t := x0, x0 := x1-q*x0, x1 := t)
}
return if (x1 > 0) then x1 else x1+b0
end

View file

@ -0,0 +1 @@
modInv =: dyad def 'x y&|@^ <: 5 p: y'"0

View file

@ -0,0 +1,2 @@
42 modInv 2017
1969

View file

@ -0,0 +1 @@
System.out.println(BigInteger.valueOf(42).modInverse(BigInteger.valueOf(2017)));

View file

@ -0,0 +1,2 @@
modInv[a_, m_] :=
Block[{x,k}, x /. FindInstance[a x == 1 + k m, {x, k}, Integers]]

View file

@ -0,0 +1,2 @@
use Math::ModInt qw(mod);
print mod(42, 2017)->inverse

View file

@ -0,0 +1,18 @@
>>> 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
>>>

View file

@ -0,0 +1,13 @@
/*REXX program calcuates the modular inverse of an integer X modulo Y.*/
parse arg x y . /*get two integers from the C.L. */
say 'modular inverse of ' x " by " y ' ' modInv(x,y)
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────MODINV subroutine───────────────────*/
modInv: parse arg a,b 1 ob; ox=0; $=1
if b \= 1 then do while a>1
parse value a/b a//b b ox with q b a t
ox=$-q*ox; $=trunc(t)
end /*while a>1*/
if $<0 then $=$+ob
return $

View file

@ -0,0 +1,17 @@
proc gcdExt {a b} {
if {$b == 0} {
return [list 1 0 $a]
}
set q [expr {$a / $b}]
set r [expr {$a % $b}]
lassign [gcdExt $b $r] s t g
return [list $t [expr {$s - $q*$t}] $g]
}
proc modInv {a m} {
lassign [gcdExt $a $m] i -> g
if {$g != 1} {
return -code error "no inverse exists of $a %! $m"
}
while {$i < 0} {incr i $m}
return $i
}

View file

@ -0,0 +1,4 @@
puts "42 %! 2017 = [modInv 42 2017]"
catch {
puts "2 %! 4 = [modInv 2 4]"
} msg; puts $msg