source: CGBLisp/trunk/src/poly.lisp@ 54

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

* empty log message *

File size: 7.8 KB
Line 
1#|
2 $Id: poly.lisp,v 1.6 2009/01/22 04:05:52 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 "POLY"
12 (:export monom-times-poly scalar-times-poly term-times-poly
13 minus-poly poly+ poly- poly* poly-expt
14 sort-poly poly-op poly-constant-p poly-extend
15 poly-mexpt poly-extend-end
16 lt lm lc poly-zerop)
17 (:use "ORDER" "MONOM" "TERM" "COEFFICIENT-RING" "COMMON-LISP"))
18(in-package "POLY")
19
20(proclaim '(optimize (speed 3) (space 0) (safety 0) (debug 0)))
21
22;;----------------------------------------------------------------
23;; BASIC OPERATIONS ON POLYNOMIALS of many variables
24;; Hybrid operations involving polynomials and monomials or terms
25;;----------------------------------------------------------------
26;; The representations are as follows:
27;;
28;; monom: (n1 n2 ... nk) where ni are non-negative integers
29;; term: (monom . coefficient)
30;; polynomial: (term1 term2 ... termk)
31;;
32;; The terms in a polynomial are assumed to be sorted in descending order by
33;; some admissible well-ordering, typically defaulting to the lexicographic
34;; order from the "order" package. Thus, the polynomials are represented
35;; non-recursively as alists.
36;;----------------------------------------------------------------
37;; EXAMPLES: Suppose that variables are x and y. Then
38;; Monom x*y^2 ---> (1 2)
39;; Term 3*x*y^2 ---> ((1 2) . 3)
40;; Polynomial x^2+x*y ---> (((2 0) . 1) ((1 1) . 1))
41;;----------------------------------------------------------------
42
43
44(defun scalar-times-poly (c p &optional (ring *coefficient-ring*))
45 "Return product of a scalar C by a polynomial P with coefficient ring RING."
46 (unless (funcall (ring-zerop ring) c)
47 (mapcar
48 #'(lambda (term) (cons (car term) (funcall (ring-* ring) c (cdr term))))
49 p)))
50
51(defun term-times-poly (term f &optional (ring *coefficient-ring*))
52 "Return product of a term TERM by a polynomial F with coefficient ring RING."
53 (mapcar #'(lambda (x) (term* term x ring)) f))
54
55(defun monom-times-poly (m f)
56 "Return product of a monomial M by a polynomial F with coefficient ring RING."
57 (mapcar #'(lambda (x) (monom-times-term m x)) f))
58
59(defun minus-poly (f &optional (ring *coefficient-ring*))
60 "Changes the sign of a polynomial F with coefficients in coefficient ring
61RING, and returns the result."
62 (mapcar #'(lambda (x) (cons (car x) (funcall (ring-- ring) (cdr x)))) f))
63
64(defun sort-poly (poly
65 &optional
66 (pred #'lex>)
67 (start 0)
68 (end (unless (null poly) ;zero
69 (length (caar poly)))))
70 "Destructively Sorts a polynomial POLY by predicate PRED; the predicate is assumed
71to take arguments START and END in addition to the pair of
72monomials, as the functions in the ORDER package do."
73 (sort poly #'(lambda (p q) (funcall pred p q :start start :end end))
74 :key #'first))
75
76(defun poly+ (p q &optional (pred #'lex>) (ring *coefficient-ring*))
77 "Returns the sum of two polynomials P and Q with coefficients in
78ring RING, with terms ordered according to monomial order PRED."
79 (do (r)
80 (nil)
81 (cond
82 ((endp p) (return (nreconc r q)))
83 ((endp q) (return (nreconc r p)))
84 (t
85 (multiple-value-bind
86 (mgreater mequal)
87 (funcall pred (caar p) (caar q))
88 (cond
89 (mequal
90 (let ((s (funcall (ring-+ ring) (cdar p) (cdar q))))
91 (unless (funcall (ring-zerop ring) s) ;check for cancellation
92 (setf r (cons (cons (caar p) s) r)))
93 (setf p (cdr p) q (cdr q))))
94 (mgreater
95 (setf r (cons (car p) r)
96 p (cdr p)))
97 (t (setf r (cons (car q) r)
98 q (cdr q)))))))))
99
100(defun poly- (p q &optional (pred #'lex>) (ring *coefficient-ring*))
101 "Returns the difference of two polynomials P and Q with coefficients
102in ring RING, with terms ordered according to monomial order PRED."
103 (do (r done)
104 (done r)
105 (cond
106 ((endp p) (return (revappend r (minus-poly q ring))))
107 ((endp q) (return (revappend r p)))
108 (t
109 (multiple-value-bind
110 (mgreater mequal)
111 (funcall pred (caar p) (caar q))
112 (cond
113 (mequal
114 (let ((s (funcall (ring-- ring) (cdar p) (cdar q))))
115 (unless (zerop s) ;check for cancellation
116 (setf r (cons (cons (caar p) s) r)))
117 (setf p (cdr p) q (cdr q))))
118 (mgreater
119 (setf r (cons (car p) r)
120 p (cdr p)))
121 (t (setf r (cons (cons (caar q) (funcall (ring-- ring) (cdar q))) r)
122 q (cdr q)))))))))
123
124;; Multiplication of polynomials
125;; Non-destructive version
126(defun poly* (p q &optional (pred #'lex>) (ring *coefficient-ring*))
127 "Returns the product of two polynomials P and Q with coefficients in
128ring RING, with terms ordered according to monomial order PRED."
129 (cond ((or (endp p) (endp q)) nil) ;p or q is 0 (represented by NIL)
130 ;; If p=p0+p1 and q=q0+q1 then pq=p0q0+p0q1+p1q
131 (t (cons (cons (monom* (caar p) (caar q))
132 (funcall (ring-* ring) (cdar p) (cdar q)))
133 (poly+ (term-times-poly (car p) (cdr q) ring)
134 (poly* (cdr p) q pred ring)
135 pred ring)))))
136
137(defun poly-op (f m g pred ring)
138 "Returns F-M*G, where F and G are polynomials with coefficients in
139ring RING, ordered according to monomial order PRED and M is a
140monomial."
141 (poly- f (term-times-poly m g ring) pred ring))
142
143(defun poly-expt (poly n &optional (pred #'lex>) (ring *coefficient-ring*))
144 "Exponentiate a polynomial POLY to power N. The terms of the
145polynomial are assumed to be ordered by monomial order PRED and with
146coefficients in ring RING. Use the Chinese algorithm; assume N>=0 and
147POLY is non-zero (not NIL)."
148 (labels ((poly-one ()
149 (list
150 (cons (make-list (length (caar poly)) :initial-element 0) (ring-unit ring)))))
151 (cond
152 ((minusp n) (error "Negative exponent."))
153 ((endp poly) (if (zerop n) (poly-one) nil))
154 (t
155 (do ((k 1 (ash k 1))
156 (q poly (poly* q q pred ring)) ;keep squaring
157 (p (poly-one) (if (not (zerop (logand k n))) (poly* p q pred ring) p)))
158 ((> k n) p))))))
159
160(defun poly-mexpt (plist monom &optional (pred #'lex>) (ring *coefficient-ring*))
161 "Raise a polynomial vector represented ad a list of polynomials
162PLIST to power MULTIINDEX. Every polynomial has its terms ordered by
163predicate PRED and coefficients in the ring RING."
164 (reduce
165 #'(lambda (u v) (poly* u v pred ring))
166 (mapcan #'(lambda (y i)
167 (cond ((endp y) (if (zerop i) nil (list nil)))
168 (t (list (poly-expt y i pred ring)))))
169 plist monom)))
170
171(defun poly-constant-p (p)
172 "Returns T if P is a constant polynomial."
173 (and (= (length p) 1)
174 (every #'zerop (caar p))))
175
176
177(defun poly-extend (p &optional (m (list 0)))
178 "Given a polynomial P in k[x[r+1],...,xn], it returns the same
179polynomial as an element of k[x1,...,xn], optionally multiplying it by
180a monomial x1^m1*x2^m2*...*xr^mr, where m=(m1,m2,...,mr) is a
181multiindex."
182 (mapcar #'(lambda (term) (cons (append m (car term)) (cdr term))) p))
183
184(defun poly-extend-end (p &optional (m (list 0)))
185 "Similar to POLY-EXTEND, but it adds new variables at the end."
186 (mapcar #'(lambda (term) (cons (append (car term) m) (cdr term))) p))
187
188(defun poly-zerop (p)
189 "Returns T if P is a zero polynomial."
190 (null p))
191
192(defun lt (p)
193 "Returns the leading term of a polynomial P."
194 #+debugging(assert (consp p))
195 (first p))
196
197(defun lm (p)
198 "Returns the leading monomial of a polynomial P."
199 #+debugging(assert (consp (lt p)))
200 (car (lt p)))
201
202(defun lc (p)
203 "Returns the leading coefficient of a polynomial P."
204 #+debugging(assert (consp (lt p)))
205 (cdr (lt p)))
206
Note: See TracBrowser for help on using the repository browser.