I\'ve written the code for multiplicative inverse of modulo m. It works for most of the initial cases but not for some. The code is below:
(define (inverse x m)
I think this is the Haskell code on that page translated directly into Scheme:
(define (inverse p q)
(cond ((= p 0) #f)
((= p 1) 1)
(else
(let ((recurse (inverse (mod q p) p)))
(and recurse
(let ((n (- p recurse)))
(div (+ (* n q) 1) p)))))))
It looks like you're trying to convert it from recursive to tail-recursive, which is why things don't match up so well.
These two functions below can help you as well.
Here’s how we find the multiplicative inverse d. We want e*d = 1(mod n), which means that ed + nk = 1 for some integer k. So we’ll write a procedure that solves the general equation ax + by = 1, where a and b are given, x and y are variables, and all of these values are integers. We’ll use this procedure to solve ed + nk = 1 for d and k. Then we can throw away k and simply return d. >
(define (ax+by=1 a b)
(if (= b 0)
(cons 1 0)
(let* ((q (quotient a b))
(r (remainder a b))
(e (ax+by=1 b r))
(s (car e))
(t (cdr e)))
(cons t (- s (* q t))))))
This function is a general solution to an equation in form of ax+by=1 where a and b is given.The inverse-mod function simply uses this solution and returns the inverse.
(define inverse-mod (lambda (a m)
(if (not (= 1 (gcd a m)))
(display "**Error** No inverse exists.")
(if (> 0(car (ax+by=1 a m)))
(+ (car (ax+by=1 a m)) m)
(car (ax+by=1 a m))))))
Some test cases are :
(inverse-mod 5 11) ; -> 9 5*9 = 45 = 1 (mod 11)
(inverse-mod 9 11) ; -> 5
(inverse-mod 7 11) ; -> 8 7*8 = 56 = 1 (mod 11)
(inverse-mod 5 12) ; -> 5 5*5 = 25 = 1 (mod 12)
(inverse-mod 8 12) ; -> error no inverse exists
The algorithm you quoted is Algorithm 9.4.4 from the book Prime Numbers by Richard Crandall and Carl Pomerance. In the text of the book they state that the algorithm works for both prime and composite moduli, but in the errata to their book they correctly state that the algorithm works always for prime moduli and mostly, but not always, for composite moduli. Hence the failure that you found.
Like you, I used Algorithm 9.4.4 and was mystified at some of my results until I discovered the problem.
Here's the modular inverse function that I use now, which works with both prime and composite moduli, as long as its two arguments are coprime to one another. It is essentially the extended Euclidean algorithm that @OscarLopez uses, but with some redundant calculations stripped out. If you like, you can change the function to return #f
instead of throwing an error.
(define (inverse x m)
(let loop ((x x) (b m) (a 0) (u 1))
(if (zero? x)
(if (= b 1) (modulo a m)
(error 'inverse "must be coprime"))
(let* ((q (quotient b x)))
(loop (modulo b x) x u (- a (* u q)))))))
Does it have to be precisely that algorithm? if not, try this one, taken from wikibooks:
(define (egcd a b)
(if (zero? a)
(values b 0 1)
(let-values (((g y x) (egcd (modulo b a) a)))
(values g (- x (* (quotient b a) y)) y))))
(define (modinv a m)
(let-values (((g x y) (egcd a m)))
(if (not (= g 1))
#f
(modulo x m))))
It works as expected:
(modinv 5 11) ; 9
(modinv 9 11) ; 5
(modinv 7 11) ; 8
(modinv 8 12) ; #f
(modinv 5 12) ; 5