close Warning: Can't synchronize with repository "(default)" (The repository directory has changed, you should resynchronize the repository with: trac-admin $ENV repository resync '(default)'). Look in the Trac log for more information.

source: branches/f4grobner/polynomial.lisp@ 87

Last change on this file since 87 was 77, checked in by Marek Rychlik, 10 years ago

* empty log message *

File size: 9.4 KB
RevLine 
[77]1;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*-
2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3;;;
4;;; Copyright (C) 1999, 2002, 2009, 2015 Marek Rychlik <rychlik@u.arizona.edu>
5;;;
6;;; This program is free software; you can redistribute it and/or modify
7;;; it under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 2 of the License, or
9;;; (at your option) any later version.
10;;;
11;;; This program is distributed in the hope that it will be useful,
12;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with this program; if not, write to the Free Software
18;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19;;;
20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
21
22
[52]23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24;;
25;; Polynomials
26;;
27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28
29(defstruct (poly
30 ;;
31 ;; BOA constructor, by default constructs zero polynomial
32 (:constructor make-poly-from-termlist (termlist &optional (sugar (termlist-sugar termlist))))
33 (:constructor make-poly-zero (&aux (termlist nil) (sugar -1)))
34 ;; Constructor of polynomials representing a variable
35 (:constructor make-variable (ring nvars pos &optional (power 1)
[53]36 &aux
37 (termlist (list
38 (make-term-variable ring nvars pos power)))
39 (sugar power)))
40 (:constructor poly-unit (ring dimension
41 &aux
42 (termlist (termlist-unit ring dimension))
43 (sugar 0))))
[52]44 (termlist nil :type list)
45 (sugar -1 :type fixnum))
46
47;; Leading term
48(defmacro poly-lt (p) `(car (poly-termlist ,p)))
49
50;; Second term
51(defmacro poly-second-lt (p) `(cadar (poly-termlist ,p)))
52
53;; Leading monomial
54(defun poly-lm (p) (term-monom (poly-lt p)))
55
56;; Second monomial
57(defun poly-second-lm (p) (term-monom (poly-second-lt p)))
58
59;; Leading coefficient
60(defun poly-lc (p) (term-coeff (poly-lt p)))
61
62;; Second coefficient
63(defun poly-second-lc (p) (term-coeff (poly-second-lt p)))
64
65;; Testing for a zero polynomial
66(defun poly-zerop (p) (null (poly-termlist p)))
67
68;; The number of terms
69(defun poly-length (p) (length (poly-termlist p)))
70
71(defun scalar-times-poly (ring c p)
72 (make-poly-from-termlist (scalar-times-termlist ring c (poly-termlist p)) (poly-sugar p)))
73
74;; The scalar product omitting the head term
75(defun scalar-times-poly-1 (ring c p)
76 (make-poly-from-termlist (scalar-times-termlist ring c (cdr (poly-termlist p))) (poly-sugar p)))
[53]77
[52]78(defun monom-times-poly (m p)
79 (make-poly-from-termlist (monom-times-termlist m (poly-termlist p)) (+ (poly-sugar p) (monom-sugar m))))
80
81(defun term-times-poly (ring term p)
82 (make-poly-from-termlist (term-times-termlist ring term (poly-termlist p)) (+ (poly-sugar p) (term-sugar term))))
83
84(defun poly-add (ring p q)
85 (make-poly-from-termlist (termlist-add ring (poly-termlist p) (poly-termlist q)) (max (poly-sugar p) (poly-sugar q))))
86
87(defun poly-sub (ring p q)
88 (make-poly-from-termlist (termlist-sub ring (poly-termlist p) (poly-termlist q)) (max (poly-sugar p) (poly-sugar q))))
89
90(defun poly-uminus (ring p)
91 (make-poly-from-termlist (termlist-uminus ring (poly-termlist p)) (poly-sugar p)))
92
93(defun poly-mul (ring p q)
94 (make-poly-from-termlist (termlist-mul ring (poly-termlist p) (poly-termlist q)) (+ (poly-sugar p) (poly-sugar q))))
95
96(defun poly-expt (ring p n)
97 (make-poly-from-termlist (termlist-expt ring (poly-termlist p) n) (* n (poly-sugar p))))
98
99(defun poly-append (&rest plist)
100 (make-poly-from-termlist (apply #'append (mapcar #'poly-termlist plist))
[53]101 (apply #'max (mapcar #'poly-sugar plist))))
[52]102
103(defun poly-nreverse (p)
104 (setf (poly-termlist p) (nreverse (poly-termlist p)))
105 p)
106
107(defun poly-contract (p &optional (k 1))
108 (make-poly-from-termlist (termlist-contract (poly-termlist p) k)
[53]109 (poly-sugar p)))
[52]110
111(defun poly-extend (p &optional (m (make-monom 1 :initial-element 0)))
112 (make-poly-from-termlist
113 (termlist-extend (poly-termlist p) m)
114 (+ (poly-sugar p) (monom-sugar m))))
115
116(defun poly-add-variables (p k)
117 (setf (poly-termlist p) (termlist-add-variables (poly-termlist p) k))
118 p)
119
120(defun poly-list-add-variables (plist k)
121 (mapcar #'(lambda (p) (poly-add-variables p k)) plist))
122
123(defun poly-standard-extension (plist &aux (k (length plist)))
124 "Calculate [U1*P1,U2*P2,...,UK*PK], where PLIST=[P1,P2,...,PK]."
125 (declare (list plist) (fixnum k))
126 (labels ((incf-power (g i)
127 (dolist (x (poly-termlist g))
128 (incf (monom-elt (term-monom x) i)))
129 (incf (poly-sugar g))))
130 (setf plist (poly-list-add-variables plist k))
131 (dotimes (i k plist)
132 (incf-power (nth i plist) i))))
133
134(defun saturation-extension (ring f plist &aux (k (length plist)) (d (monom-dimension (poly-lm (car plist)))))
135 "Calculate [F, U1*P1-1,U2*P2-1,...,UK*PK-1], where PLIST=[P1,P2,...,PK]."
136 (setf f (poly-list-add-variables f k)
137 plist (mapcar #'(lambda (x)
138 (setf (poly-termlist x) (nconc (poly-termlist x)
139 (list (make-term (make-monom d :initial-element 0)
140 (funcall (ring-uminus ring) (funcall (ring-unit ring)))))))
141 x)
142 (poly-standard-extension plist)))
143 (append f plist))
144
145
146(defun polysaturation-extension (ring f plist &aux (k (length plist))
[53]147 (d (+ k (length (poly-lm (car plist))))))
[52]148 "Calculate [F, U1*P1+U2*P2+...+UK*PK-1], where PLIST=[P1,P2,...,PK]."
149 (setf f (poly-list-add-variables f k)
150 plist (apply #'poly-append (poly-standard-extension plist))
151 (cdr (last (poly-termlist plist))) (list (make-term (make-monom d :initial-element 0)
152 (funcall (ring-uminus ring) (funcall (ring-unit ring))))))
153 (append f (list plist)))
154
155(defun saturation-extension-1 (ring f p) (polysaturation-extension ring f (list p)))
[53]156
157
158
159;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
160;;
161;; Evaluation of polynomial (prefix) expressions
162;;
163;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
164
165(defun coerce-coeff (ring expr vars)
166 "Coerce an element of the coefficient ring to a constant polynomial."
167 ;; Modular arithmetic handler by rat
168 (make-poly-from-termlist (list (make-term (make-monom (length vars) :initial-element 0)
169 (funcall (ring-parse ring) expr)))
170 0))
171
172(defun poly-eval (ring expr vars &optional (list-marker '[))
173 (labels ((p-eval (arg) (poly-eval ring arg vars))
174 (p-eval-list (args) (mapcar #'p-eval args))
175 (p-add (x y) (poly-add ring x y)))
176 (cond
177 ((eql expr 0) (make-poly-zero))
178 ((member expr vars :test #'equalp)
179 (let ((pos (position expr vars :test #'equalp)))
180 (make-variable ring (length vars) pos)))
181 ((atom expr)
182 (coerce-coeff ring expr vars))
183 ((eq (car expr) list-marker)
184 (cons list-marker (p-eval-list (cdr expr))))
185 (t
186 (case (car expr)
187 (+ (reduce #'p-add (p-eval-list (cdr expr))))
188 (- (case (length expr)
189 (1 (make-poly-zero))
190 (2 (poly-uminus ring (p-eval (cadr expr))))
191 (3 (poly-sub ring (p-eval (cadr expr)) (p-eval (caddr expr))))
192 (otherwise (poly-sub ring (p-eval (cadr expr))
193 (reduce #'p-add (p-eval-list (cddr expr)))))))
194 (*
195 (if (endp (cddr expr)) ;unary
196 (p-eval (cdr expr))
197 (reduce #'(lambda (p q) (poly-mul ring p q)) (p-eval-list (cdr expr)))))
198 (expt
199 (cond
200 ((member (cadr expr) vars :test #'equalp)
201 ;;Special handling of (expt var pow)
202 (let ((pos (position (cadr expr) vars :test #'equalp)))
203 (make-variable ring (length vars) pos (caddr expr))))
204 ((not (and (integerp (caddr expr)) (plusp (caddr expr))))
205 ;; Negative power means division in coefficient ring
206 ;; Non-integer power means non-polynomial coefficient
207 (coerce-coeff ring expr vars))
208 (t (poly-expt ring (p-eval (cadr expr)) (caddr expr)))))
209 (otherwise
210 (coerce-coeff ring expr vars)))))))
[55]211
212(defun spoly (ring f g)
213 "It yields the S-polynomial of polynomials F and G."
214 (declare (type poly f g))
215 (let* ((lcm (monom-lcm (poly-lm f) (poly-lm g)))
216 (mf (monom-div lcm (poly-lm f)))
217 (mg (monom-div lcm (poly-lm g))))
218 (declare (type monom mf mg))
219 (multiple-value-bind (c cf cg)
220 (funcall (ring-ezgcd ring) (poly-lc f) (poly-lc g))
221 (declare (ignore c))
222 (poly-sub
223 ring
224 (scalar-times-poly ring cg (monom-times-poly mf f))
[53]225 (scalar-times-poly ring cf (monom-times-poly mg g))))))
226
[55]227
228(defun poly-primitive-part (ring p)
229 "Divide polynomial P with integer coefficients by gcd of its
230coefficients and return the result."
231 (declare (type poly p))
232 (if (poly-zerop p)
233 (values p 1)
234 (let ((c (poly-content ring p)))
235 (values (make-poly-from-termlist (mapcar
236 #'(lambda (x)
237 (make-term (term-monom x)
238 (funcall (ring-div ring) (term-coeff x) c)))
239 (poly-termlist p))
240 (poly-sugar p))
241 c))))
242
243(defun poly-content (ring p)
244 "Greatest common divisor of the coefficients of the polynomial P. Use the RING structure
245to compute the greatest common divisor."
246 (declare (type poly p))
[57]247 (reduce (ring-gcd ring) (mapcar #'term-coeff (rest (poly-termlist p))) :initial-value (poly-lc p)))
248
Note: See TracBrowser for help on using the repository browser.