source: CGBLisp/src/svpoly.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: 8.8 KB
Line 
1#|
2 $Id: svpoly.lisp,v 1.4 2009/01/23 10:37:28 marek Exp $
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(defpackage "SVPOLY"
12 (:export))
13
14(in-package "SVPOLY")
15
16#+debug(proclaim '(optimize (speed 0) (debug 3)))
17#-debug(proclaim '(optimize (speed 3) (debug 0)))
18
19(defstruct (svpoly (:constructor make-svpoly-raw))
20 (nvars "Number of variables." (:type fixnum))
21 (coefficient-type "Type of the coefficient.")
22 (order "Monomial order.")
23 (terms "The array of terms."))
24
25(defun make-svpoly (alist order
26 &aux (nterms (length alist))
27 (nvars (length (caar alist)))
28 (coefficient-type (type-of (cdar alist))))
29 "Construct svpolynomial from ALIST."
30 (let ((svp (make-svpoly-raw
31 :nvars nvars
32 :coefficient-type (type-of (cdar alist))
33 :order order
34 :terms (make-array nterms :element-type 'cons))))
35 (dotimes (i nterms)
36 (let ((term (nth i alist)))
37 (setf (svref (svpoly-terms svp) i)
38 (cons (make-array nvars :initial-contents (car term))
39 (cdr term)))))
40 (svpoly-sort svp)))
41
42(defun svpoly-sort (svp)
43 "Destructively sorts an sv-polynomial SVP."
44 (setf (svpoly-terms svp) (sort (svpoly-terms svp) (svpoly-order svp) :key #'car)) svp)
45
46(defun make-order (nvars order)
47 "Returns an order function with two parameters P and Q such that if called
48on a pair of monomials with exactly NVARS variables, this function
49will return T if P is greater than Q and NIL otherwise. The keyword
50ORDER indicates one of several standard orders (:LEX, etc)."
51 (declare (fixnum nvars))
52 (ecase order
53 (:lex #'(lambda (p q)
54 (dotimes (i nvars (values NIL T))
55 (declare (fixnum i))
56 (cond
57 ((> (svref p i) (svref q i))
58 (return (values t nil)))
59 ((< (svref p i) (svref q i))
60 (return (values nil nil)))))))))
61
62(defun svpoly-add (p q)
63 "Adds polynomials P and Q, where P and Q are assumed to be ordered
64by the same monomial order. Destructive to P and Q."
65 (setf (svpoly-terms p) (add-terms (svpoly-terms p) (svpoly-terms q)
66 (svpoly-order p)))
67 p)
68
69(defun add-terms (p q pred &aux (lp (length p)) (lq (length q)))
70 (do ((r (make-array (+ lp lq) :element-type 'cons))
71 (i 0) (j 0) (k 0) done)
72 (done (coerce (adjust-array r k) 'simple-vector))
73 (cond
74 ((= i lp)
75 (do nil
76 ((>= j lq) (setf done t))
77 (setf (aref r k) (svref q j))
78 (incf j) (incf k)))
79 ((= j lq)
80 (do nil
81 ((>= i lp) (setf done t))
82 (setf (aref r k) (svref p i))
83 (incf i) (incf k)))
84 (t
85 (multiple-value-bind
86 (mgreater mequal)
87 (funcall pred (car (svref p i)) (car (svref q j)))
88 (cond
89 (mequal
90 (let ((s (+ (cdr (svref p i)) (cdr (svref q j)))))
91 (unless (zerop s) ;check for cancellation
92 (setf (aref r k) (cons (car (svref p i)) s))
93 (incf k))
94 (incf i)
95 (incf j)))
96 (mgreater
97 (setf (aref r k) (svref p i))
98 (incf i)
99 (incf k))
100 (t
101 (setf (aref r k) (svref q j))
102 (incf j)
103 (incf k))))))))
104
105#|
106
107(defun scalar-times-poly (c p)
108 "Return product of a scalar C by a polynomial P with coefficient ring RING."
109 (unless (funcall (ring-zerop ring) c)
110 (mapcar
111 #'(lambda (term) (cons (car term) (funcall (ring-* ring) c (cdr term))))
112 p)))
113
114(defun term-times-poly (term f &optional (ring *coefficient-ring*))
115 "Return product of a term TERM by a polynomial F with coefficient ring RING."
116 (mapcar #'(lambda (x) (term* term x ring)) f))
117
118(defun monom-times-poly (m f)
119 "Return product of a monomial M by a polynomial F with coefficient ring RING."
120 (mapcar #'(lambda (x) (monom-times-term m x)) f))
121
122(defun minus-poly (f &optional (ring *coefficient-ring*))
123 "Changes the sign of a polynomial F with coefficients in coefficient ring
124RING, and returns the result."
125 (mapcar #'(lambda (x) (cons (car x) (funcall (ring-- ring) (cdr x)))) f))
126
127
128(defun poly+ (p q &optional (pred #'lex>) (ring *coefficient-ring*))
129 "Returns the sum of two polynomials P and Q with coefficients in
130ring RING, with terms ordered according to monomial order PRED."
131 (do (r done)
132 (done r)
133 (cond
134 ((endp p) (setf r (append (nreverse r) q) done t))
135 ((endp q) (setf r (append (nreverse r) p) done t))
136 (t
137 (multiple-value-bind
138 (mgreater mequal)
139 (funcall pred (caar p) (caar q))
140 (cond
141 (mequal
142 (let ((s (funcall (ring-+ ring) (cdar p) (cdar q))))
143 (unless (funcall (ring-zerop ring) s) ;check for cancellation
144 (setf r (cons (cons (caar p) s) r)))
145 (setf p (cdr p) q (cdr q))))
146 (mgreater
147 (setf r (cons (car p) r)
148 p (cdr p)))
149 (t (setf r (cons (car q) r)
150 q (cdr q)))))))))
151
152(defun poly- (p q &optional (pred #'lex>) (ring *coefficient-ring*))
153 "Returns the difference of two polynomials P and Q with coefficients
154in ring RING, with terms ordered according to monomial order PRED."
155 (do (r done)
156 (done r)
157 (cond
158 ((endp p) (setf r (append (nreverse r) (minus-poly q ring)) done t))
159 ((endp q) (setf r (append (nreverse r) p) done t))
160 (t
161 (multiple-value-bind
162 (mgreater mequal)
163 (funcall pred (caar p) (caar q))
164 (cond
165 (mequal
166 (let ((s (funcall (ring-- ring) (cdar p) (cdar q))))
167 (unless (zerop s) ;check for cancellation
168 (setf r (cons (cons (caar p) s) r)))
169 (setf p (cdr p) q (cdr q))))
170 (mgreater
171 (setf r (cons (car p) r)
172 p (cdr p)))
173 (t (setf r (cons (cons (caar q) (funcall (ring-- ring) (cdar q))) r)
174 q (cdr q)))))))))
175
176;; Multiplication of polynomials
177;; Non-destructive version
178(defun poly* (p q &optional (pred #'lex>) (ring *coefficient-ring*))
179 "Returns the product of two polynomials P and Q with coefficients in
180ring RING, with terms ordered according to monomial order PRED."
181 (cond ((or (endp p) (endp q)) nil) ;p or q is 0 (represented by NIL)
182 ;; If p=p0+p1 and q=q0+q1 then pq=p0q0+p0q1+p1q
183 (t (cons (cons (monom* (caar p) (caar q))
184 (funcall (ring-* ring) (cdar p) (cdar q)))
185 (poly+ (term-times-poly (car p) (cdr q) ring)
186 (poly* (cdr p) q pred ring)
187 pred ring)))))
188
189(defun poly-op (f m g pred ring)
190 "Returns F-M*G, where F and G are polynomials with coefficients in
191ring RING, ordered according to monomial order PRED and M is a
192monomial."
193 (poly- f (term-times-poly m g ring) pred ring))
194
195(defun poly-expt (poly n &optional (pred #'lex>) (ring *coefficient-ring*))
196 "Exponentiate a polynomial POLY to power N. The terms of the
197polynomial are assumed to be ordered by monomial order PRED and with
198coefficients in ring RING. Use the Chinese algorithm; assume N>=0 and
199POLY is non-zero (not NIL)."
200 (labels ((poly-one ()
201 (list
202 (cons (make-list (length (caar poly)) :initial-element 0) (ring-unit ring)))))
203 (cond
204 ((minusp n) (error "Negative exponent."))
205 ((endp poly) (if (zerop n) (poly-one) nil))
206 (t
207 (do ((k 1 (ash k 1))
208 (q poly (poly* q q pred ring)) ;keep squaring
209 (p (poly-one) (if (not (zerop (logand k n))) (poly* p q pred ring) p)))
210 ((> k n) p))))))
211
212(defun poly-mexpt (plist monom &optional (pred #'lex>) (ring *coefficient-ring*))
213 "Raise a polynomial vector represented ad a list of polynomials
214PLIST to power MULTIINDEX. Every polynomial has its terms ordered by
215predicate PRED and coefficients in the ring RING."
216 (reduce
217 #'(lambda (u v) (poly* u v pred ring))
218 (mapcan #'(lambda (y i)
219 (cond ((endp y) (if (zerop i) nil (list nil)))
220 (t (list (poly-expt y i pred ring)))))
221 plist monom)))
222
223(defun poly-constant-p (p)
224 "Returns T if P is a constant polynomial."
225 (and (= (length p) 1)
226 (every #'zerop (caar p))))
227
228
229(defun poly-extend (p &optional (m (list 0)))
230 "Given a polynomial P in k[x[r+1],...,xn], it returns the same
231polynomial as an element of k[x1,...,xn], optionally multiplying it by
232a monomial x1^m1*x2^m2*...*xr^mr, where m=(m1,m2,...,mr) is a
233multiindex."
234 (mapcar #'(lambda (term) (cons (append m (car term)) (cdr term))) p))
235
236(defun poly-extend-end (p &optional (m (list 0)))
237 "Similar to POLY-EXTEND, but it adds new variables at the end."
238 (mapcar #'(lambda (term) (cons (append (car term) m) (cdr term))) p))
239
240(defun poly-zerop (p)
241 "Returns T if P is a zero polynomial."
242 (null p))
243
244(defun lt (p)
245 "Returns the leading term of a polynomial P."
246 #+debugging(assert (consp p))
247 (first p))
248
249(defun lm (p)
250 "Returns the leading monomial of a polynomial P."
251 #+debugging(assert (consp (lt p)))
252 (car (lt p)))
253
254(defun lc (p)
255 "Returns the leading coefficient of a polynomial P."
256 #+debugging(assert (consp (lt p)))
257 (cdr (lt p)))
258
259|#
Note: See TracBrowser for help on using the repository browser.