source: CGBLisp/src/RCS/poly.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: 9.0 KB
Line 
1head 1.6;
2access;
3symbols;
4locks; strict;
5comment @;;; @;
6
7
81.6
9date 2009.01.22.04.05.52; author marek; state Exp;
10branches;
11next 1.5;
12
131.5
14date 2009.01.19.09.28.37; author marek; state Exp;
15branches;
16next 1.4;
17
181.4
19date 2009.01.19.07.56.24; author marek; state Exp;
20branches;
21next 1.3;
22
231.3
24date 2009.01.19.07.51.39; author marek; state Exp;
25branches;
26next 1.2;
27
281.2
29date 2009.01.19.07.37.58; author marek; state Exp;
30branches;
31next 1.1;
32
331.1
34date 2009.01.19.06.48.25; author marek; state Exp;
35branches;
36next ;
37
38
39desc
40@@
41
42
431.6
44log
45@*** empty log message ***
46@
47text
48@#|
49 $Id$
50 *--------------------------------------------------------------------------*
51 | Copyright (C) 1994, Marek Rychlik (e-mail: rychlik@@math.arizona.edu) |
52 | Department of Mathematics, University of Arizona, Tucson, AZ 85721 |
53 | |
54 | Everyone is permitted to copy, distribute and modify the code in this |
55 | directory, as long as this copyright note is preserved verbatim. |
56 *--------------------------------------------------------------------------*
57|#
58(defpackage "POLY"
59 (:export monom-times-poly scalar-times-poly term-times-poly
60 minus-poly poly+ poly- poly* poly-expt
61 sort-poly poly-op poly-constant-p poly-extend
62 poly-mexpt poly-extend-end
63 lt lm lc poly-zerop)
64 (:use "ORDER" "MONOM" "TERM" "COEFFICIENT-RING" "COMMON-LISP"))
65(in-package "POLY")
66
67#+debug(proclaim '(optimize (speed 0) (debug 3)))
68#-debug(proclaim '(optimize (speed 3) (debug 0)))
69
70;;----------------------------------------------------------------
71;; BASIC OPERATIONS ON POLYNOMIALS of many variables
72;; Hybrid operations involving polynomials and monomials or terms
73;;----------------------------------------------------------------
74;; The representations are as follows:
75;;
76;; monom: (n1 n2 ... nk) where ni are non-negative integers
77;; term: (monom . coefficient)
78;; polynomial: (term1 term2 ... termk)
79;;
80;; The terms in a polynomial are assumed to be sorted in descending order by
81;; some admissible well-ordering, typically defaulting to the lexicographic
82;; order from the "order" package. Thus, the polynomials are represented
83;; non-recursively as alists.
84;;----------------------------------------------------------------
85;; EXAMPLES: Suppose that variables are x and y. Then
86;; Monom x*y^2 ---> (1 2)
87;; Term 3*x*y^2 ---> ((1 2) . 3)
88;; Polynomial x^2+x*y ---> (((2 0) . 1) ((1 1) . 1))
89;;----------------------------------------------------------------
90
91
92(defun scalar-times-poly (c p &optional (ring *coefficient-ring*))
93 "Return product of a scalar C by a polynomial P with coefficient ring RING."
94 (unless (funcall (ring-zerop ring) c)
95 (mapcar
96 #'(lambda (term) (cons (car term) (funcall (ring-* ring) c (cdr term))))
97 p)))
98
99(defun term-times-poly (term f &optional (ring *coefficient-ring*))
100 "Return product of a term TERM by a polynomial F with coefficient ring RING."
101 (mapcar #'(lambda (x) (term* term x ring)) f))
102
103(defun monom-times-poly (m f)
104 "Return product of a monomial M by a polynomial F with coefficient ring RING."
105 (mapcar #'(lambda (x) (monom-times-term m x)) f))
106
107(defun minus-poly (f &optional (ring *coefficient-ring*))
108 "Changes the sign of a polynomial F with coefficients in coefficient ring
109RING, and returns the result."
110 (mapcar #'(lambda (x) (cons (car x) (funcall (ring-- ring) (cdr x)))) f))
111
112(defun sort-poly (poly
113 &optional
114 (pred #'lex>)
115 (start 0)
116 (end (unless (null poly) ;zero
117 (length (caar poly)))))
118 "Destructively Sorts a polynomial POLY by predicate PRED; the predicate is assumed
119to take arguments START and END in addition to the pair of
120monomials, as the functions in the ORDER package do."
121 (sort poly #'(lambda (p q) (funcall pred p q :start start :end end))
122 :key #'first))
123
124(defun poly+ (p q &optional (pred #'lex>) (ring *coefficient-ring*))
125 "Returns the sum of two polynomials P and Q with coefficients in
126ring RING, with terms ordered according to monomial order PRED."
127 (do (r)
128 (nil)
129 (cond
130 ((endp p) (return (nreconc r q)))
131 ((endp q) (return (nreconc r p)))
132 (t
133 (multiple-value-bind
134 (mgreater mequal)
135 (funcall pred (caar p) (caar q))
136 (cond
137 (mequal
138 (let ((s (funcall (ring-+ ring) (cdar p) (cdar q))))
139 (unless (funcall (ring-zerop ring) s) ;check for cancellation
140 (setf r (cons (cons (caar p) s) r)))
141 (setf p (cdr p) q (cdr q))))
142 (mgreater
143 (setf r (cons (car p) r)
144 p (cdr p)))
145 (t (setf r (cons (car q) r)
146 q (cdr q)))))))))
147
148(defun poly- (p q &optional (pred #'lex>) (ring *coefficient-ring*))
149 "Returns the difference of two polynomials P and Q with coefficients
150in ring RING, with terms ordered according to monomial order PRED."
151 (do (r done)
152 (done r)
153 (cond
154 ((endp p) (return (revappend r (minus-poly q ring))))
155 ((endp q) (return (revappend r p)))
156 (t
157 (multiple-value-bind
158 (mgreater mequal)
159 (funcall pred (caar p) (caar q))
160 (cond
161 (mequal
162 (let ((s (funcall (ring-- ring) (cdar p) (cdar q))))
163 (unless (zerop s) ;check for cancellation
164 (setf r (cons (cons (caar p) s) r)))
165 (setf p (cdr p) q (cdr q))))
166 (mgreater
167 (setf r (cons (car p) r)
168 p (cdr p)))
169 (t (setf r (cons (cons (caar q) (funcall (ring-- ring) (cdar q))) r)
170 q (cdr q)))))))))
171
172;; Multiplication of polynomials
173;; Non-destructive version
174(defun poly* (p q &optional (pred #'lex>) (ring *coefficient-ring*))
175 "Returns the product of two polynomials P and Q with coefficients in
176ring RING, with terms ordered according to monomial order PRED."
177 (cond ((or (endp p) (endp q)) nil) ;p or q is 0 (represented by NIL)
178 ;; If p=p0+p1 and q=q0+q1 then pq=p0q0+p0q1+p1q
179 (t (cons (cons (monom* (caar p) (caar q))
180 (funcall (ring-* ring) (cdar p) (cdar q)))
181 (poly+ (term-times-poly (car p) (cdr q) ring)
182 (poly* (cdr p) q pred ring)
183 pred ring)))))
184
185(defun poly-op (f m g pred ring)
186 "Returns F-M*G, where F and G are polynomials with coefficients in
187ring RING, ordered according to monomial order PRED and M is a
188monomial."
189 (poly- f (term-times-poly m g ring) pred ring))
190
191(defun poly-expt (poly n &optional (pred #'lex>) (ring *coefficient-ring*))
192 "Exponentiate a polynomial POLY to power N. The terms of the
193polynomial are assumed to be ordered by monomial order PRED and with
194coefficients in ring RING. Use the Chinese algorithm; assume N>=0 and
195POLY is non-zero (not NIL)."
196 (labels ((poly-one ()
197 (list
198 (cons (make-list (length (caar poly)) :initial-element 0) (ring-unit ring)))))
199 (cond
200 ((minusp n) (error "Negative exponent."))
201 ((endp poly) (if (zerop n) (poly-one) nil))
202 (t
203 (do ((k 1 (ash k 1))
204 (q poly (poly* q q pred ring)) ;keep squaring
205 (p (poly-one) (if (not (zerop (logand k n))) (poly* p q pred ring) p)))
206 ((> k n) p))))))
207
208(defun poly-mexpt (plist monom &optional (pred #'lex>) (ring *coefficient-ring*))
209 "Raise a polynomial vector represented ad a list of polynomials
210PLIST to power MULTIINDEX. Every polynomial has its terms ordered by
211predicate PRED and coefficients in the ring RING."
212 (reduce
213 #'(lambda (u v) (poly* u v pred ring))
214 (mapcan #'(lambda (y i)
215 (cond ((endp y) (if (zerop i) nil (list nil)))
216 (t (list (poly-expt y i pred ring)))))
217 plist monom)))
218
219(defun poly-constant-p (p)
220 "Returns T if P is a constant polynomial."
221 (and (= (length p) 1)
222 (every #'zerop (caar p))))
223
224
225(defun poly-extend (p &optional (m (list 0)))
226 "Given a polynomial P in k[x[r+1],...,xn], it returns the same
227polynomial as an element of k[x1,...,xn], optionally multiplying it by
228a monomial x1^m1*x2^m2*...*xr^mr, where m=(m1,m2,...,mr) is a
229multiindex."
230 (mapcar #'(lambda (term) (cons (append m (car term)) (cdr term))) p))
231
232(defun poly-extend-end (p &optional (m (list 0)))
233 "Similar to POLY-EXTEND, but it adds new variables at the end."
234 (mapcar #'(lambda (term) (cons (append (car term) m) (cdr term))) p))
235
236(defun poly-zerop (p)
237 "Returns T if P is a zero polynomial."
238 (null p))
239
240(defun lt (p)
241 "Returns the leading term of a polynomial P."
242 #+debugging(assert (consp p))
243 (first p))
244
245(defun lm (p)
246 "Returns the leading monomial of a polynomial P."
247 #+debugging(assert (consp (lt p)))
248 (car (lt p)))
249
250(defun lc (p)
251 "Returns the leading coefficient of a polynomial P."
252 #+debugging(assert (consp (lt p)))
253 (cdr (lt p)))
254
255@
256
257
2581.5
259log
260@*** empty log message ***
261@
262text
263@d20 2
264a21 2
265;;(proclaim '(optimize (speed 0) (debug 3)))
266(proclaim '(optimize (speed 3) (debug 0)))
267@
268
269
2701.4
271log
272@*** empty log message ***
273@
274text
275@d20 2
276a21 1
277(proclaim '(optimize (speed 0) (debug 3)))
278@
279
280
2811.3
282log
283@*** empty log message ***
284@
285text
286@d80 1
287a80 1
288 ()
289@
290
291
2921.2
293log
294@*** empty log message ***
295@
296text
297@a187 3
298(eval-when (compile)
299 (proclaim '(inline lt lm lc poly-zerop scalar-times-poly)))
300
301@
302
303
3041.1
305log
306@Initial revision
307@
308text
309@d2 1
310a2 1
311 $Id: poly.lisp,v 1.33 1998/01/18 09:05:28 marek Exp $
312d20 1
313a20 4
314(eval-when (compile)
315 (proclaim '(optimize (speed 3) (safety 0)))
316 (proclaim '(inline monom-times-poly scalar-times-poly
317 term-times-poly minus-poly sort-poly poly-op)))
318@
Note: See TracBrowser for help on using the repository browser.