source: CGBLisp/src/modular.lisp@ 8

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

Moving sources into trunk

File size: 2.1 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(proclaim '(optimize (speed 0) (debug 3)))
20
21(defun modular-inverse (x p)
22 "Find the inverse of X modulo prime P, using Euclid algorithm."
23 (multiple-value-bind (gcd u v)
24 (xgcd x p)
25 (declare (ignore gcd v))
26 (mod u p)))
27
28(defun modular-division (x y p)
29 "Divide X by Y modulo prime P."
30 (mod (* x (modular-inverse y p)) p))
31
32(defvar *inverse-by-lookup-limit* 100000
33 "If prime modulus is < this number then the division algorithm
34will use a lookup table of inverses created at the time when field-modulo-prime is called.")
35
36(defun make-inverse-table (modulus &aux (table (list 0)))
37 "Make a vector of length MODULUS containing all inverses modulo MODULUS,
38which should be a prime number. The inverse of 0 is 0."
39 (do ((x 1 (1+ x))) ((>= x modulus) (apply #'vector (nreverse table)))
40 (push (modular-inverse x modulus) table)))
41
42(defun make-modular-division (modulus)
43 "Return a function of two arguments which will perform division
44modulo MODULUS. Currently, if MODULUS is < *INVERSE-BY-LOOKUP-LIMIT*
45then the returned function does table lookup, otherwise it uses
46the Euclid algorithm to find the inverse."
47 (cond
48 ((>= modulus *inverse-by-lookup-limit*)
49 #'(lambda (x y) (modular-division x y modulus)))
50 (t
51 (let ((table (make-inverse-table modulus)))
52 #'(lambda (x y)
53 (mod (* x (svref table y)) modulus))))))
Note: See TracBrowser for help on using the repository browser.