source: CGBLisp/src/modular.lisp@ 1

Last change on this file since 1 was 1, checked in by Marek Rychlik, 15 years ago

First import of a version circa 1997.

File size: 2.2 KB
Line 
1;;; -*- Mode: Lisp; Syntax: Common-Lisp; Package: Grobner; Base: 10 -*-
2#|
3 $Id: modular.lisp,v 1.4 2009/01/22 04:03:50 marek Exp $
4 *--------------------------------------------------------------------------*
5 | Copyright (C) 1994, Marek Rychlik (e-mail: rychlik@math.arizona.edu) |
6 | Department of Mathematics, University of Arizona, Tucson, AZ 85721 |
7 | |
8 | Everyone is permitted to copy, distribute and modify the code in this |
9 | directory, as long as this copyright note is preserved verbatim. |
10 *--------------------------------------------------------------------------*
11|#
12
13(defpackage "MODULAR"
14 (:export modular-division make-modular-division)
15 (:use "XGCD" "COMMON-LISP"))
16
17(in-package "MODULAR")
18
19#+debug(proclaim '(optimize (speed 0) (debug 3)))
20#-debug(proclaim '(optimize (speed 3) (debug 0)))
21
22(defun modular-inverse (x p)
23 "Find the inverse of X modulo prime P, using Euclid algorithm."
24 (multiple-value-bind (gcd u v)
25 (xgcd x p)
26 (declare (ignore gcd v))
27 (mod u p)))
28
29(defun modular-division (x y p)
30 "Divide X by Y modulo prime P."
31 (mod (* x (modular-inverse y p)) p))
32
33(defvar *inverse-by-lookup-limit* 100000
34 "If prime modulus is < this number then the division algorithm
35will use a lookup table of inverses created at the time when field-modulo-prime is called.")
36
37(defun make-inverse-table (modulus &aux (table (list 0)))
38 "Make a vector of length MODULUS containing all inverses modulo MODULUS,
39which should be a prime number. The inverse of 0 is 0."
40 (do ((x 1 (1+ x))) ((>= x modulus) (apply #'vector (nreverse table)))
41 (push (modular-inverse x modulus) table)))
42
43(defun make-modular-division (modulus)
44 "Return a function of two arguments which will perform division
45modulo MODULUS. Currently, if MODULUS is < *INVERSE-BY-LOOKUP-LIMIT*
46then the returned function does table lookup, otherwise it uses
47the Euclid algorithm to find the inverse."
48 (cond
49 ((>= modulus *inverse-by-lookup-limit*)
50 #'(lambda (x y) (modular-division x y modulus)))
51 (t
52 (let ((table (make-inverse-table modulus)))
53 #'(lambda (x y)
54 (mod (* x (svref table y)) modulus))))))
Note: See TracBrowser for help on using the repository browser.