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