source: CGBLisp/src/RCS/modular.lisp,v@ 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.9 KB
Line 
1head 1.4;
2access;
3symbols;
4locks; strict;
5comment @;;; @;
6
7
81.4
9date 2009.01.22.04.03.50; author marek; state Exp;
10branches;
11next 1.3;
12
131.3
14date 2009.01.19.09.26.32; author marek; state Exp;
15branches;
16next 1.2;
17
181.2
19date 2009.01.19.07.39.06; author marek; state Exp;
20branches;
21next 1.1;
22
231.1
24date 2009.01.19.06.44.13; author marek; state Exp;
25branches;
26next ;
27
28
29desc
30@@
31
32
331.4
34log
35@*** empty log message ***
36@
37text
38@;;; -*- Mode: Lisp; Syntax: Common-Lisp; Package: Grobner; Base: 10 -*-
39#|
40 $Id$
41 *--------------------------------------------------------------------------*
42 | Copyright (C) 1994, Marek Rychlik (e-mail: rychlik@@math.arizona.edu) |
43 | Department of Mathematics, University of Arizona, Tucson, AZ 85721 |
44 | |
45 | Everyone is permitted to copy, distribute and modify the code in this |
46 | directory, as long as this copyright note is preserved verbatim. |
47 *--------------------------------------------------------------------------*
48|#
49
50(defpackage "MODULAR"
51 (:export modular-division make-modular-division)
52 (:use "XGCD" "COMMON-LISP"))
53
54(in-package "MODULAR")
55
56#+debug(proclaim '(optimize (speed 0) (debug 3)))
57#-debug(proclaim '(optimize (speed 3) (debug 0)))
58
59(defun modular-inverse (x p)
60 "Find the inverse of X modulo prime P, using Euclid algorithm."
61 (multiple-value-bind (gcd u v)
62 (xgcd x p)
63 (declare (ignore gcd v))
64 (mod u p)))
65
66(defun modular-division (x y p)
67 "Divide X by Y modulo prime P."
68 (mod (* x (modular-inverse y p)) p))
69
70(defvar *inverse-by-lookup-limit* 100000
71 "If prime modulus is < this number then the division algorithm
72will use a lookup table of inverses created at the time when field-modulo-prime is called.")
73
74(defun make-inverse-table (modulus &aux (table (list 0)))
75 "Make a vector of length MODULUS containing all inverses modulo MODULUS,
76which should be a prime number. The inverse of 0 is 0."
77 (do ((x 1 (1+ x))) ((>= x modulus) (apply #'vector (nreverse table)))
78 (push (modular-inverse x modulus) table)))
79
80(defun make-modular-division (modulus)
81 "Return a function of two arguments which will perform division
82modulo MODULUS. Currently, if MODULUS is < *INVERSE-BY-LOOKUP-LIMIT*
83then the returned function does table lookup, otherwise it uses
84the Euclid algorithm to find the inverse."
85 (cond
86 ((>= modulus *inverse-by-lookup-limit*)
87 #'(lambda (x y) (modular-division x y modulus)))
88 (t
89 (let ((table (make-inverse-table modulus)))
90 #'(lambda (x y)
91 (mod (* x (svref table y)) modulus))))))@
92
93
941.3
95log
96@*** empty log message ***
97@
98text
99@d19 2
100a20 2
101;;(proclaim '(optimize (speed 0) (debug 3)))
102(proclaim '(optimize (speed 3) (debug 0)))
103@
104
105
1061.2
107log
108@*** empty log message ***
109@
110text
111@d19 2
112a20 1
113(proclaim '(optimize (speed 0) (debug 3)))
114@
115
116
1171.1
118log
119@Initial revision
120@
121text
122@d3 1
123a3 1
124 $Id: modular.lisp,v 1.6 1997/12/13 15:55:32 marek Exp $
125d19 2
126@
Note: See TracBrowser for help on using the repository browser.