source: CGBLisp/trunk/src/modular.lisp@ 98

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

Removed useless RCS version info. Added missing Emacs mode lines.

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