Modular inverse: Difference between revisions

m
(Modular inverse in BASIC256)
m (→‎{{header|Wren}}: Minor tidy)
 
(33 intermediate revisions by 11 users not shown)
Line 216:
 
<pre>1969</pre>
 
=={{header|ATS}}==
 
===Using allocated memory===
 
In addition to solving the task, I demonstrate some aspects of call-by-reference in ATS. In particular, ATS can distinguish ''at compile time'' between uninitialized and initialized variables.
 
The code is written as templates that will expand to code for any of the (non-dependent) signed integer types. In the main program, I use <code>llint</code> (typically exactly the same as <code>long long int</code> in C).
 
The return value of <code>inverse</code> is a linear optional value. It is allocated in the heap, used once, and freed.
 
<syntaxhighlight lang="ats">
(*
 
Using the algorithm described at
https://en.wikipedia.org/w/index.php?title=Extended_Euclidean_algorithm&oldid=1135569411#Modular_integers
 
*)
 
#include "share/atspre_staload.hats"
 
fn {tk : tkind}
division_with_nonnegative_remainder
(n : g0int tk, d : g0int tk,
(* q and r are called by reference, and start out
uninitialized. *)
q : &g0int tk? >> g0int tk,
r : &g0int tk? >> g0int tk)
: void =
let
(* The C optimizer most likely will reduce these these two
divisions to just one. They are simply synonyms for C '/' and
'%', and perform division that rounds the quotient towards
zero. *)
val q0 = g0int_div (n, d)
val r0 = g0int_mod (n, d)
in
(* The following calculation results in 'floor division', if the
divisor is positive, or 'ceiling division', if the divisor is
negative. This choice of method results in the remainder never
being negative. *)
if isgtez n || iseqz r0 then
(q := q0; r := r0)
else if isltz d then
(q := succ q0; r := r0 - d)
else
(q := pred q0; r := r0 + d)
end
 
fn {tk : tkind}
inverse (a : g0int tk, n : g0int tk) : Option_vt (g0int tk) =
let
typedef integer = g0int tk
 
fun
loop (t : integer, newt : integer,
r : integer, newr : integer) : Option_vt integer =
if iseqz newr then
begin
if r > g0i2i 1 then
None_vt ()
else if t < g0i2i 0 then
Some_vt (t + n)
else
Some_vt t
end
else
let
(* These become C variables. *)
var quotient : g0int tk?
var remainder : g0int tk?
 
(* Show the type AT COMPILE TIME. *)
prval _ = $showtype quotient
prval _ = $showtype remainder
 
val () =
division_with_nonnegative_remainder
(r, newr, quotient, remainder)
 
(* THE TYPES WILL HAVE CHANGED, because the storage is
initialized by the call to
division_with_nonnegative_remainder. *)
prval _ = $showtype quotient
prval _ = $showtype remainder
 
val t = newt
and newt = t - (quotient * newt)
and r = newr
and newr = remainder
in
loop (t, newt, r, newr)
end
in
loop (g0i2i 0, g0i2i 1, n, a)
end
 
implement
main0 () =
case+ inverse (42LL, 2017LL) of
| ~ None_vt () => println! "There is no inverse."
| ~ Some_vt value => println! value
</syntaxhighlight>
 
{{out}}
 
First compile the program:
<pre>$ patscc -DATS_MEMALLOC_LIBC -g -O2 modular-inverse.dats
**SHOWTYPE[UP]**(/home/trashman/src/chemoelectric/rosettacode-contributions/modular-inverse.dats: 1786(line=62, offs=31) -- 1794(line=62, offs=39)): S2Etop(knd=0; S2Eapp(S2Ecst(g0int_t0ype); S2Evar(tk(8481)))): S2RTbas(S2RTBASimp(1; t@ype))
**SHOWTYPE[UP]**(/home/trashman/src/chemoelectric/rosettacode-contributions/modular-inverse.dats: 1825(line=63, offs=31) -- 1834(line=63, offs=40)): S2Etop(knd=0; S2Eapp(S2Ecst(g0int_t0ype); S2Evar(tk(8481)))): S2RTbas(S2RTBASimp(1; t@ype))
**SHOWTYPE[UP]**(/home/trashman/src/chemoelectric/rosettacode-contributions/modular-inverse.dats: 2137(line=72, offs=31) -- 2145(line=72, offs=39)): S2Eapp(S2Ecst(g0int_t0ype); S2Evar(tk(8481))): S2RTbas(S2RTBASimp(1; t@ype))
**SHOWTYPE[UP]**(/home/trashman/src/chemoelectric/rosettacode-contributions/modular-inverse.dats: 2176(line=73, offs=31) -- 2185(line=73, offs=40)): S2Eapp(S2Ecst(g0int_t0ype); S2Evar(tk(8481))): S2RTbas(S2RTBASimp(1; t@ype))
</pre>
 
You may notice there is a subtle change in the type of <code>quotient</code> and <code>remainder</code>, once they have been initialized. ATS is making it safe ''not'' to initialize variables (with phony values) when you declare them.
 
Now run the program:
<pre>$ ./a.out
1969</pre>
 
===Safely avoiding the need for an allocator===
 
Here I demonstrate an optional value that requires no runtime overhead at all, but which is safe. If there is no inverse, then the compiler knows that <code>inverse_value</code> is still uninitialized, and will not let you use its value. (Try it and see.)
 
<syntaxhighlight lang="ats">
(*
Using the algorithm described at
https://en.wikipedia.org/w/index.php?title=Extended_Euclidean_algorithm&oldid=1135569411#Modular_integers
*)
 
#include "share/atspre_staload.hats"
 
fn {tk : tkind}
division_with_nonnegative_remainder
(n : g0int tk, d : g0int tk,
(* q and r are called by reference, and start out
uninitialized. *)
q : &g0int tk? >> g0int tk,
r : &g0int tk? >> g0int tk)
: void =
let
(* The C optimizer most likely will reduce these these two
divisions to just one. They are simply synonyms for C '/' and
'%', and perform division that rounds the quotient towards
zero. *)
val q0 = g0int_div (n, d)
val r0 = g0int_mod (n, d)
in
(* The following calculation results in 'floor division', if the
divisor is positive, or 'ceiling division', if the divisor is
negative. This choice of method results in the remainder never
being negative. *)
if isgtez n || iseqz r0 then
(q := q0; r := r0)
else if isltz d then
(q := succ q0; r := r0 - d)
else
(q := pred q0; r := r0 + d)
end
 
fn {tk : tkind}
inverse (a : g0int tk, n : g0int tk,
inverse_exists : &bool? >> bool exists,
inverse_value : &g0int tk? >> opt (g0int tk, exists))
: #[exists: bool] void =
let
typedef integer = g0int tk
 
fun
loop (t : integer, newt : integer,
r : integer, newr : integer,
inverse_exists : &bool? >> bool exists,
inverse_value : &g0int tk? >> opt (g0int tk, exists))
: #[exists: bool] void =
if iseqz newr then
begin
if r > g0i2i 1 then
let
val () = inverse_exists := false
prval () = opt_none inverse_value
in
end
else if t < g0i2i 0 then
let
val () = inverse_exists := true
val () = inverse_value := t + n
prval () = opt_some inverse_value
in
end
else
let
val () = inverse_exists := true
val () = inverse_value := t
prval () = opt_some inverse_value
in
end
end
else
let
(* These become C variables. *)
var quotient : g0int tk?
var remainder : g0int tk?
 
val () =
division_with_nonnegative_remainder
(r, newr, quotient, remainder)
 
val t = newt
and newt = t - (quotient * newt)
and r = newr
and newr = remainder
in
loop (t, newt, r, newr, inverse_exists, inverse_value)
end
in
loop (g0i2i 0, g0i2i 1, n, a, inverse_exists, inverse_value)
end
 
implement
main0 () =
let
var inverse_exists : bool?
var inverse_value : llint?
in
inverse (42LL, 2017LL, inverse_exists, inverse_value);
if inverse_exists then
let
prval () = opt_unsome inverse_value
in
println! inverse_value
end
else
let
prval () = opt_unnone inverse_value
in
println! "There is no inverse."
end
end
</syntaxhighlight>
 
{{out}}
There is no need to tell patscc what allocator to use, because none is used.
<pre>$ patscc -g -O2 modular-inverse-noheap.dats && ./a.out
1969</pre>
 
=={{header|AutoHotkey}}==
Line 337 ⟶ 581:
{{out}}
<pre>1969</pre>
 
==={{header|Chipmunk Basic}}===
{{works with|Chipmunk Basic|3.6.4}}
{{works with|QBasic}}
{{trans|BASIC256}}
<syntaxhighlight lang="qbasic">10 CLS
20 CALL modularinverse(42, 2017)
30 CALL modularinverse(40, 1)
40 END
50 SUB modularinverse(e,t)
60 d = 0
70 IF e < t THEN
80 b = e
90 c = 1
100 WHILE b > 1
110 s = INT(((t-b)/e)+1)
120 b = b+s*e
130 c = c+s
140 b = b-t
150 WEND
160 d = c
170 ENDIF
180 m = d
190 PRINT m
200 END SUB</syntaxhighlight>
 
==={{header|Minimal BASIC}}===
{{trans|Pascal}}
{{works with|Applesoft BASIC}}
{{works with|Commodore BASIC|3.5}}
{{works with|Nascom ROM BASIC|4.7}}
Line 363 ⟶ 633:
610 RETURN
</syntaxhighlight>
 
==={{header|QBasic}}===
The [[#Chipmunk_Basic|Chipmunk Basic]] solution works without any changes.
<syntaxhighlight lang="qbasic"></syntaxhighlight>
 
==={{header|True BASIC}}===
<syntaxhighlight lang="qbasic">SUB modularinverse(e,t)
LET d = 0
IF e < t then
LET b = e
LET c = 1
DO WHILE b > 1
LET s = int(((t-b)/e)+1)
LET b = b+s*e
LET c = c+s
LET b = b-t
LOOP
LET d = c
END IF
LET m = d
PRINT m
END SUB
 
CALL modularinverse(42,2017)
CALL modularinverse(40,1)
END</syntaxhighlight>
 
=={{header|Batch File}}==
Line 856 ⟶ 1,152:
 
return</syntaxhighlight>
{{out| Output}}<pre>1969</pre>
 
=={{header|Crystal}}==
Line 975 ⟶ 1,272:
-486, 217 -> 121
40, 2018 -> no inverse</pre>
 
=={{header|EasyLang}}==
{{trans|AWK}}
<syntaxhighlight lang="easylang">
func mod_inv a b .
b0 = b
x1 = 1
if b = 1
return 1
.
while a > 1
q = a div b
t = b
b = a mod b
a = t
t = x0
x0 = x1 - q * x0
x1 = t
.
if x1 < 0
x1 += b0
.
return x1
.
print mod_inv 42 2017
</syntaxhighlight>
 
=={{header|EchoLisp}}==
Line 1,126 ⟶ 1,449:
42 2017 invmod . 1969
42 2017 modinv . 1969
</pre>
 
=={{header|Fortran}}==
<syntaxhighlight lang="fortran">
program modular_inverse_task
 
implicit none
 
write (*,*) inverse (42, 2017)
 
contains
 
! Returns -1 if there is no inverse. I assume n > 0. The algorithm
! is described at
! https://en.wikipedia.org/w/index.php?title=Extended_Euclidean_algorithm&oldid=1135569411#Modular_integers
function inverse (a, n) result (inverse_value)
integer, intent(in) :: a, n
integer :: inverse_value
 
integer :: t, newt
integer :: r, newr
integer :: quotient, remainder, tmp
 
if (n <= 0) error stop
t = 0; newt = 1
r = n; newr = a
do while (newr /= 0)
remainder = modulo (r, newr) ! Floor division.
quotient = (r - remainder) / newr
tmp = newt; newt = t - (quotient * newt); t = tmp
r = newr; newr = remainder
end do
if (r > 1) then
inverse_value = -1
else if (t < 0) then
inverse_value = t + n
else
inverse_value = t
end if
end function inverse
 
end program modular_inverse_task
</syntaxhighlight>
 
{{out}}
<pre>$ gfortran -Wall -Wextra modular_inverse_task.f90 && ./a.out
1969
</pre>
 
Line 1,423 ⟶ 1,793:
{{out}}
<pre>1969</pre>
Alternatively, working from first principles.
<syntaxhighlight lang="java">
public final class ModularInverse {
 
public static void main(String[] aArgs) {
System.out.println(inverseModulus(42, 2017));
}
private static Egcd extendedGCD(int aOne, int aTwo) {
if ( aOne == 0 ) {
return new Egcd(aTwo, 0, 1);
}
Egcd value = extendedGCD(aTwo % aOne, aOne);
return new Egcd(value.aG, value.aY - ( aTwo / aOne ) * value.aX, value.aX);
}
private static int inverseModulus(int aNumber, int aModulus) {
Egcd value = extendedGCD(aNumber, aModulus);
return ( value.aG == 1 ) ? ( value.aX + aModulus ) % aModulus : 0;
}
private static record Egcd(int aG, int aX, int aY) {}
 
}
</syntaxhighlight>
{{ out }}
<pre>
1969
</pre>
 
=={{header|JavaScript}}==
Line 1,492 ⟶ 1,891:
The following code works on any integer type.
To maximize performance, we ensure (via a promotion rule) that the operands are the same type (and use built-ins <code>zero(T)</code> and <code>one(T)</code> for initialization of temporary variables to ensure that they remain of the same type throughout execution).
<syntaxhighlight lang="julia">function modinv{T<:Integer}(a::T, b::T) where T <: Integer
b0 = b
x0, x1 = zero(T), one(T)
Line 1,567 ⟶ 1,966:
 
</syntaxhighlight>
 
=={{header|m4}}==
{{trans|Mercury}}
 
Note that <code>$0</code> is the name of the macro being evaluated. Therefore, in the following, <code>_$0</code> is the name of another macro, the same as the name of the first macro, except for an underscore prepended. This is a common idiom.
 
The core of the program is <code>__inverse</code> recursively calling itself.
 
m4 is a macro-preprocessor, and so some of the following is there simply to keep things from being echoed to the output. :)
 
<syntaxhighlight lang="m4">
divert(-1)
 
# I assume non-negative arguments. The algorithm is described at
# https://en.wikipedia.org/w/index.php?title=Extended_Euclidean_algorithm&oldid=1135569411#Modular_integers
 
define(`inverse',`_$0(eval(`$1'), eval(`$2'))')
define(`_inverse',`_$0($2, 0, 1, $2, $1)')
define(`__inverse',
`dnl n = $1, t = $2, newt = $3, r = $4, newr = $5
ifelse(eval($5 != 0), 1, `$0($1, $3,
eval($2 - (($4 / $5) * $3)),
$5,eval($4 % $5))',
eval($4 > 1), 1, `no inverse',
eval($2 < 0), 1, eval($2 + $1),
$2)')
 
divert`'dnl
inverse(42, 2017)
</syntaxhighlight>
 
{{out}}
<pre>$ m4 modular-inverse-task.m4
1969</pre>
 
=={{header|MAD}}==
Line 1,625 ⟶ 2,058:
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
TheUse the built-in function <code>FindInstanceModularInverse</code> works well for this:
<syntaxhighlight lang="mathematica">modInv[a_, m_] :=
Block[{x,k}, x /. FindInstance[a x == 1 + k m, {x, k}, Integers]]</syntaxhighlight>
 
<syntaxhighlight lang="mathematica">ModularInverse[a, m]</syntaxhighlight>
Another way by using the built-in function <code>PowerMod</code> :
For example:
<syntaxhighlight lang="mathematica">PowerMod[a,-1,m]</syntaxhighlight>
<pre>ModularInverse[42, 2017]
For example :
<pre>modInv[42, 2017]
{1969}
PowerMod[42, -1, 2017]
1969</pre>
 
=={{header|Maxima}}==
Using built-in function inv_mod
<syntaxhighlight lang="maxima">
inv_mod(42,2017);
</syntaxhighlight>
{{out}}
<pre>
1969
</pre>
 
=={{header|Mercury}}==
{{works with|Mercury|22.01.1}}
 
<syntaxhighlight lang="mercury">
%%% -*- mode: mercury; prolog-indent-width: 2; -*-
%%%
%%% Compile with:
%%% mmc --make --use-subdirs modular_inverse_task
%%%
 
:- module modular_inverse_task.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
 
:- implementation.
:- import_module exception.
:- import_module int.
 
%% inverse(A, N, Inverse). I assume N > 0, and throw an exception if
%% it is not. The predicate fails if there is no inverse (and thus is
%% "semidet"). The algorithm is described at
%% https://en.wikipedia.org/w/index.php?title=Extended_Euclidean_algorithm&oldid=1135569411#Modular_integers
:- pred inverse(int::in, int::in, int::out) is semidet.
inverse(A, N, Inverse) :-
if (N =< 0) then throw(domain_error("inverse"))
else inverse_(N, 0, 1, N, A, Inverse).
 
:- pred inverse_(int::in, int::in, int::in, int::in, int::in,
int::out) is semidet.
inverse_(N, T, NewT, R, NewR, Inverse) :-
if (NewR \= 0)
then (Quotient = div(R, NewR), % Floor division.
inverse_(N,
NewT, T - (Quotient * NewT),
NewR, R - (Quotient * NewR),
Inverse)) % Tail recursion.
else (R =< 1, % R =< 1 FAILS if R > 1.
(if (T < 0) then Inverse = T + N else Inverse = T)).
 
main(!IO) :-
if inverse(42, 2017, Inverse)
then (print(Inverse, !IO), nl(!IO))
else (print("There is no inverse.", !IO), nl(!IO)).
 
:- end_module modular_inverse_task.
</syntaxhighlight>
 
{{out}}
<pre>$ mmc --make --use-subdirs modular_inverse_task && ./modular_inverse_task
Making Mercury/int3s/modular_inverse_task.int3
Making Mercury/ints/modular_inverse_task.int
Making Mercury/cs/modular_inverse_task.c
Making Mercury/os/modular_inverse_task.o
Making modular_inverse_task
1969
</pre>
 
=={{header|МК-61/52}}==
Line 1,754 ⟶ 2,250:
{{out}}
<pre>1969</pre>
 
=={{header|Oberon-2}}==
{{works with|Oxford Oberon-2 Compiler|3.3.0}}
 
<syntaxhighlight lang="oberon">
(*-*- mode: indented-text; tab-width: 2; -*-*)
 
MODULE modularInverseInOberon2;
 
IMPORT Out;
 
(* Division with a non-negative remainder. This will work no matter
how your compiler handles DIV (and mine seems not to do what the
Oberon-2 specification says). *)
PROCEDURE euclidDiv (x, y : INTEGER) : INTEGER;
VAR q : INTEGER;
BEGIN
IF 0 <= y THEN (* Do floor division. *)
IF 0 <= x THEN
q := x DIV y
ELSE
q := -((-x) DIV y);
IF (-x) MOD y # 0 THEN q := q - 1 END
END;
ELSE (* Do ceiling division. *)
IF 0 <= x THEN
q := -(x DIV (-y))
ELSE
q := ((-x) DIV (-y));
IF (-x) MOD (-y) # 0 THEN q := q + 1 END
END
END;
RETURN q
END euclidDiv;
 
(* I have added this unit test because, earlier, I posted a buggy
version of euclidDiv. *)
PROCEDURE testEuclidDiv;
VAR x, y, q, r : INTEGER;
BEGIN
FOR x := -100 TO 100 DO
FOR y := -100 TO 100 DO
IF y # 0 THEN
q := euclidDiv (x, y);
r := x - (q * y);
IF (r < 0) OR (ABS (y) <= r) THEN
(* A remainder was outside the expected range. *)
Out.String ("euclidDiv fails its test")
END
END
END
END
END testEuclidDiv;
 
PROCEDURE inverse (a, n : INTEGER) : INTEGER;
VAR t, newt : INTEGER;
VAR r, newr : INTEGER;
VAR quotient : INTEGER;
VAR tmp : INTEGER;
BEGIN
t := 0; newt := 1;
r := n; newr := a;
WHILE newr # 0 DO
quotient := euclidDiv (r, newr);
tmp := newt; newt := t - (quotient * newt); t := tmp;
tmp := newr; newr := r - (quotient * newr); r := tmp
END;
IF r > 1 THEN
t := -1
ELSIF t < 0 THEN
t := t + n
END;
RETURN t
END inverse;
 
BEGIN
testEuclidDiv;
Out.Int (inverse (42, 2017), 0);
Out.Ln
END modularInverseInOberon2.
</syntaxhighlight>
 
{{out}}
<pre>$ obc modularInverseInOberon2.Mod && ./a.out
1969
</pre>
 
=={{header|ObjectIcon}}==
{{trans|Oberon-2}}
{{trans|Mercury}}
 
<syntaxhighlight lang="objecticon">
# -*- ObjectIcon -*-
 
import exception
import io
 
procedure main ()
test_euclid_div ()
io.write (inverse (42, 2017))
end
 
procedure inverse (a, n) # FAILS if there is no inverse.
local t, newt, r, newr, quotient, tmp
 
if n <= 0 then throw ("non-positive modulus")
t := 0; newt := 1
r := n; newr := a
while newr ~= 0 do
{
quotient := euclid_div (r, newr)
tmp := newt; newt := t - (quotient * newt); t := tmp
tmp := newr; newr := r - (quotient * newr); r := tmp
}
r <= 1 | fail
return (if t < 0 then t + n else t)
end
 
procedure euclid_div (x, y)
# This kind of integer division always gives a remainder between 0
# and abs(y)-1, inclusive. Thus the remainder is always a LEAST
# RESIDUE modulo abs(y). (If y is a positive modulus, then only the
# floor division branch is used.)
return \
if 0 <= y then # Do floor division.
(if 0 <= x then x / y
else if (-x) % y = 0 then -((-x) / y)
else -((-x) / y) - 1)
else # Do ceiling division.
(if 0 <= x then -(x / (-y))
else if (-x) % (-y) = 0 then ((-x) / (-y))
else ((-x) / (-y)) + 1)
end
 
procedure test_euclid_div ()
local x, y, q, r
 
every x := -100 to 100 do
every y := -100 to 100 & y ~= 0 do
{
q := euclid_div (x, y)
r := x - (q * y)
if r < 0 | abs (y) <= r then
# A remainder was outside the expected range.
throw ("Test of euclid_div failed.")
}
end
</syntaxhighlight>
 
{{out}}
<pre>$ oiscript modular-inverse-task-OI.icn
1969</pre>
 
=={{header|OCaml}}==
Line 1,825 ⟶ 2,473:
1969
</pre>
 
=={{header|Owl Lisp}}==
{{works with|Owl Lisp|0.2.1}}
 
<syntaxhighlight lang="scheme">
(import (owl math)
(owl math extra))
 
(define (euclid-quotient x y)
(if (<= 0 y)
(cond ((<= 0 x) (quotient x y))
((zero? (remainder (negate x) y))
(negate (quotient (negate x) y)))
(else (- (negate (quotient (negate x) y)) 1)))
(cond ((<= 0 x) (negate (quotient x (negate y))))
((zero? (remainder (negate x) (negate y)))
(quotient (negate x) (negate y)))
(else (+ (quotient (negate x) (negate y)) 1)))))
 
;; A unit test of euclid-quotient.
(let repeat ((x -100)
(y -100))
(cond ((= x 101) #t)
((= y 0) (repeat x (+ y 1)))
((= y 101) (repeat (+ x 1) -100))
(else (let* ((q (euclid-quotient x y))
(r (- x (* q y))))
(cond ((< r 0) (display "negative remainder\n"))
((<= (abs y) r) (display "remainder too large\n"))
(else (repeat x (+ y 1))))))))
 
(define (inverse a n)
(let repeat ((t 0) (newt 1)
(r n) (newr a))
(cond ((not (zero? newr))
(let ((quotient (euclid-quotient r newr)))
(repeat newt (- t (* quotient newt))
newr (- r (* quotient newr)))))
((< 1 r) #f) ; The inverse does not exist.
((negative? t) (+ t n))
(else t))))
 
(display (inverse 42 2017))
(newline)
</syntaxhighlight>
 
{{out}}
<pre>$ ol modular-inverse-task-Owl.scm
1969</pre>
 
=={{header|PARI/GP}}==
Line 2,104 ⟶ 2,801:
 
=={{header|Python}}==
 
===Builtin function===
Since python3.8, builtin function "pow" can be used directly to compute modular inverses by specifying an exponent of -1:
<syntaxhighlight lang="python">>>> pow(42, -1, 2017)
1969
</syntaxhighlight>
 
===Iteration and error-handling===
Line 2,249 ⟶ 2,952:
 
<pre>1969</pre>
 
===Using Extended Euclidean Algorithm===
 
Handles negative args. Returns -1 for non-coprime args.
 
<syntaxhighlight lang="quackery"> [ dup 0 = iff
[ 2drop 1 0 ]
done
dup unrot /mod
dip swap recurse
tuck 2swap *
dip swap - ] is egcd ( n n --> n n )
 
[ dup 0 < if negate
over 0 < if
[ swap negate
over tuck mod
- swap ]
dup rot 2dup egcd
2swap 2over rot *
unrot * + 1 != iff
[ drop 2drop -1 ]
done
nip swap mod ] is modinv ( n n --> n )
 
say " 42 2017 modinv --> " 42 2017 modinv echo cr ( --> 1969 )
say " 40 1 modinv --> " 40 1 modinv echo cr ( --> 0 )
say " 52 -217 modinv --> " 52 -217 modinv echo cr ( --> 96 )
say "-486 217 modinv --> " -486 217 modinv echo cr ( --> 121 )
say " 40 2018 modinv --> " 40 2018 modinv echo cr ( --> -1 )</syntaxhighlight>
 
{{out}}
 
<pre> 42 2017 modinv --> 1969
40 1 modinv --> 0
52 -217 modinv --> 96
-486 217 modinv --> 121
40 2018 modinv --> -1
</pre>
 
=={{header|Racket}}==
Line 2,914 ⟶ 3,656:
121
a is not invertible</pre>
 
=={{header|V (Vlang)}}==
<syntaxhighlight lang="Zig">
fn main() {
println("42 %! 2017 = ${mult_inv(42, 2017)}")
}
 
fn mult_inv(aa int, bb int) int {
mut a, mut b := aa, bb
mut x0, mut t := 0, 0
mut b0 := b
mut x1 := 1
if b == 1 {return 1}
for 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
}
</syntaxhighlight>
 
{{out}}
<pre>
42 %! 2017 = 1969
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-big}}
<syntaxhighlight lang="ecmascriptwren">import "./big" for BigInt
 
var a = BigInt.new(42)
9,476

edits