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/pol.lisp@ 2001

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

* empty log message *

File size: 6.9 KB
Line 
1;;; -*- Mode: Lisp -*-
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23;;
24;; Polynomials implemented in CLOS
25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26;;
27;; A polynomial is an collection of terms. A
28;; term has a monomial and a coefficient.
29;;
30;; A polynomial can be represented by an s-expp
31;; (EXPR . VARS) where EXPR is an arithmetical formula
32;; recursively built of the arithmetical operations,
33;; and VARS are the variables of the polynomial.
34;; If a subtree of this s-exp is not an arithmetical
35;; operator +, -, *, expt, and is not a member
36;; of VARS then it represents a scalar expression
37;; which the Lisp reader must know how to convert
38;; into an object for which can be multiplied by a variable,
39;; subject to commutativity and associativity rules.
40;;
41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
42
43(defpackage "POL"
44 (:use :cl :ring :ring-and-order :monom :order :term :termlist :infix)
45 (:export "POLY"
46 "POLY-TERMLIST"
47 "POLY-SUGAR"
48 "POLY-RESET-SUGAR"
49 "POLY-LT"
50 "MAKE-POLY-FROM-TERMLIST"
51 "MAKE-POLY-ZERO"
52 "MAKE-POLY-VARIABLE"
53 "POLY-UNIT"
54 "POLY-LM"
55 "POLY-SECOND-LM"
56 "POLY-SECOND-LT"
57 "POLY-LC"
58 "POLY-SECOND-LC"
59 "POLY-ZEROP"
60 "POLY-LENGTH"
61 "SCALAR-TIMES-POLY"
62 "SCALAR-TIMES-POLY-1"
63 "MONOM-TIMES-POLY"
64 "TERM-TIMES-POLY"
65 "POLY-ADD"
66 "POLY-SUB"
67 "POLY-UMINUS"
68 "POLY-MUL"
69 "POLY-EXPT"
70 "POLY-APPEND"
71 "POLY-NREVERSE"
72 "POLY-REVERSE"
73 "POLY-CONTRACT"
74 "POLY-EXTEND"
75 "POLY-ADD-VARIABLES"
76 "POLY-LIST-ADD-VARIABLES"
77 "POLY-STANDARD-EXTENSION"
78 "SATURATION-EXTENSION"
79 "POLYSATURATION-EXTENSION"
80 "SATURATION-EXTENSION-1"
81 "COERCE-COEFF"
82 "POLY-EVAL"
83 "POLY-EVAL-SCALAR"
84 "SPOLY"
85 "POLY-PRIMITIVE-PART"
86 "POLY-CONTENT"
87 "READ-INFIX-FORM"
88 "READ-POLY"
89 "STRING->POLY"
90 "POLY->ALIST"
91 "STRING->ALIST"
92 "POLY-EQUAL-NO-SUGAR-P"
93 "POLY-SET-EQUAL-NO-SUGAR-P"
94 "POLY-LIST-EQUAL-NO-SUGAR-P"
95 ))
96
97(in-package :pol)
98
99(proclaim '(optimize (speed 0) (space 0) (safety 3) (debug 3)))
100
101(defclass poly ()
102 ((termlist :initarg :termlist :accessor termlist))
103 (:default-initargs :termlist nil))
104
105(defun make-poly-from-termlist (termlist)
106 (make-instance 'poly :termlist termlist :sugar sugar))
107
108(defun make-poly-zero (&aux (termlist nil) (sugar -1))
109 (make-instance 'poly :termlist termlist))
110
111(defun make-poly-variable (ring nvars pos &optional (power 1)
112 &aux
113 (termlist (list
114 (make-term-variable ring nvars pos power))))
115 (make-instance 'poly :termlist termlist))
116
117(defun poly-unit (ring dimension
118 &aux
119 (termlist (termlist-unit ring dimension)))
120 (make-instance 'poly :termlist termlist))
121
122
123(defmethod print-object ((self poly) stream)
124 (princ (slot-value self 'termlist)))
125
126(defmethod poly-termlist ((self poly))
127 (slot-value self 'termlist))
128
129(defmethod (setf poly-termlist) (new-value (poly poly))
130 (setf (slot-value poly 'termlist) new-value))
131
132(defmethod poly-add ((p poly) (q poly)))
133
134(defmethod poly-sub ((p poly) (q poly)))
135
136(defmethod poly-uminus ((self poly)))
137
138(defmethod poly-mul ((p poly) (poly q)))
139
140(defmethod poly-expt ((self poly) n))
141
142(defmethod initialize-instance :after ((self poly) expr vars)
143 "Evaluate Lisp form EXPR to a polynomial or a list of polynomials in
144variables VARS. Return the resulting polynomial or list of
145polynomials. Standard arithmetical operators in form EXPR are
146replaced with their analogues in the ring of polynomials, and the
147resulting expression is evaluated, resulting in a polynomial or a list
148of polynomials in internal form. A similar operation in another computer
149algebra system could be called 'expand' or so."
150 (cond
151 ((null expr) (error "Empty expression"))
152 ((eql expr 0) (make-poly-zero))
153 ((member expr vars :test #'equalp)
154 (let ((pos (position expr vars :test #'equalp)))
155 (make-poly-variable ring (length vars) pos)))
156 ((atom expr)
157 (scalar->poly ring expr vars))
158 ((eq (car expr) list-marker)
159 (cons list-marker (p-eval-list (cdr expr))))
160 (t
161 (case (car expr)
162 (+ (reduce #'p-add (p-eval-list (cdr expr))))
163 (- (case (length expr)
164 (1 (make-poly-zero))
165 (2 (poly-uminus ring (p-eval (cadr expr))))
166 (3 (poly-sub ring-and-order (p-eval (cadr expr)) (p-eval (caddr expr))))
167 (otherwise (poly-sub ring-and-order (p-eval (cadr expr))
168 (reduce #'p-add (p-eval-list (cddr expr)))))))
169 (*
170 (if (endp (cddr expr)) ;unary
171 (p-eval (cdr expr))
172 (reduce #'(lambda (p q) (poly-mul ring-and-order p q)) (p-eval-list (cdr expr)))))
173 (/
174 ;; A polynomial can be divided by a scalar
175 (cond
176 ((endp (cddr expr))
177 ;; A special case (/ ?), the inverse
178 (scalar->poly ring (apply (ring-div ring) (cdr expr)) vars))
179 (t
180 (let ((num (p-eval (cadr expr)))
181 (denom-inverse (apply (ring-div ring)
182 (cons (funcall (ring-unit ring))
183 (mapcar #'p-eval-scalar (cddr expr))))))
184 (scalar-times-poly ring denom-inverse num)))))
185 (expt
186 (cond
187 ((member (cadr expr) vars :test #'equalp)
188 ;;Special handling of (expt var pow)
189 (let ((pos (position (cadr expr) vars :test #'equalp)))
190 (make-poly-variable ring (length vars) pos (caddr expr))))
191 ((not (and (integerp (caddr expr)) (plusp (caddr expr))))
192 ;; Negative power means division in coefficient ring
193 ;; Non-integer power means non-polynomial coefficient
194 (scalar->poly ring expr vars))
195 (t (poly-expt ring-and-order (p-eval (cadr expr)) (caddr expr)))))
196 (otherwise
197 (scalar->poly ring expr vars)))))))
198
199(defun poly-eval-scalar (expr
200 &optional
201 (ring +ring-of-integers+)
202 &aux
203 (order #'lex>))
204 "Evaluate a scalar expression EXPR in ring RING."
205 (declare (type ring ring))
206 (poly-lc (poly-eval expr nil ring order)))
207
208
209
210
Note: See TracBrowser for help on using the repository browser.