| [150] | 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 | 
 | 
|---|
| [411] | 22 | (defpackage "TERMLIST"
 | 
|---|
| [445] | 23 |   (:use :cl :ring :monomial :order :term)
 | 
|---|
| [411] | 24 |   (:export "TERMLIST-SUGAR"
 | 
|---|
 | 25 |            "TERMLIST-CONTRACT"
 | 
|---|
 | 26 |            "TERMLIST-EXTEND"
 | 
|---|
 | 27 |            "TERMLIST-ADD-VARIABLES"
 | 
|---|
 | 28 |            "TERMLIST-LT"
 | 
|---|
 | 29 |            "TERMLIST-LM"
 | 
|---|
 | 30 |            "TERMLIST-LC"
 | 
|---|
 | 31 |            "SCALAR-MUL"
 | 
|---|
 | 32 |            "SCALAR-TIMES-TERMLIST"
 | 
|---|
 | 33 |            "TERM-MUL-LST"
 | 
|---|
 | 34 |            "TERMLIST-TIMES-TERM"
 | 
|---|
 | 35 |            "TERM-TIMES-TERMLIST"
 | 
|---|
 | 36 |            "MONOM-TIMES-TERM"
 | 
|---|
 | 37 |            "MONOM-TIMES-TERMLIST"
 | 
|---|
 | 38 |            "TERMLIST-UMINUS"
 | 
|---|
 | 39 |            "TERMLIST-ADD"
 | 
|---|
 | 40 |            "TERMLIST-SUB"
 | 
|---|
 | 41 |            "TERMLIST-MUL"
 | 
|---|
 | 42 |            "TERMLIST-UNIT"
 | 
|---|
 | 43 |            "TERMLIST-EXPT"))
 | 
|---|
| [150] | 44 | 
 | 
|---|
| [436] | 45 | (in-package :termlist)
 | 
|---|
 | 46 | 
 | 
|---|
| [401] | 47 | (defun termlist-sugar (p &aux (sugar -1))
 | 
|---|
 | 48 |   (declare (fixnum sugar))
 | 
|---|
 | 49 |   (dolist (term p sugar)
 | 
|---|
 | 50 |     (setf sugar (max sugar (term-sugar term)))))
 | 
|---|
 | 51 | 
 | 
|---|
 | 52 | (defun termlist-contract (p &optional (k 1))
 | 
|---|
 | 53 |   "Eliminate first K variables from a polynomial P."
 | 
|---|
 | 54 |   (mapcar #'(lambda (term) (make-term (monom-contract k (term-monom term))
 | 
|---|
 | 55 |                                       (term-coeff term)))
 | 
|---|
 | 56 |           p))
 | 
|---|
 | 57 | 
 | 
|---|
 | 58 | (defun termlist-extend (p &optional (m (make-monom 1 :initial-element 0)))
 | 
|---|
 | 59 |   "Extend every monomial in a polynomial P by inserting at the
 | 
|---|
 | 60 | beginning of every monomial the list of powers M."
 | 
|---|
 | 61 |   (mapcar #'(lambda (term) (make-term (monom-append m (term-monom term))
 | 
|---|
 | 62 |                                       (term-coeff term)))
 | 
|---|
 | 63 |           p))
 | 
|---|
 | 64 | 
 | 
|---|
 | 65 | (defun termlist-add-variables (p n)
 | 
|---|
 | 66 |   "Add N variables to a polynomial P by inserting zero powers
 | 
|---|
 | 67 | at the beginning of each monomial."
 | 
|---|
 | 68 |   (declare (fixnum n))
 | 
|---|
 | 69 |   (mapcar #'(lambda (term)
 | 
|---|
 | 70 |               (make-term (monom-append (make-monom n :initial-element 0)
 | 
|---|
 | 71 |                                        (term-monom term))
 | 
|---|
 | 72 |                          (term-coeff term)))
 | 
|---|
 | 73 |           p))
 | 
|---|
 | 74 | 
 | 
|---|
 | 75 | 
 | 
|---|
| [150] | 76 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
|---|
 | 77 | ;;
 | 
|---|
 | 78 | ;; Low-level polynomial arithmetic done on 
 | 
|---|
 | 79 | ;; lists of terms
 | 
|---|
 | 80 | ;;
 | 
|---|
 | 81 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
|---|
 | 82 | 
 | 
|---|
 | 83 | (defmacro termlist-lt (p) `(car ,p))
 | 
|---|
 | 84 | (defun termlist-lm (p) (term-monom (termlist-lt p)))
 | 
|---|
 | 85 | (defun termlist-lc (p) (term-coeff (termlist-lt p)))
 | 
|---|
 | 86 | 
 | 
|---|
 | 87 | (define-modify-macro scalar-mul (c) coeff-mul)
 | 
|---|
 | 88 | 
 | 
|---|
 | 89 | (defun scalar-times-termlist (ring c p)
 | 
|---|
 | 90 |   "Multiply scalar C by a polynomial P. This function works
 | 
|---|
 | 91 | even if there are divisors of 0."
 | 
|---|
 | 92 |   (mapcan
 | 
|---|
 | 93 |    #'(lambda (term)
 | 
|---|
 | 94 |        (let ((c1 (funcall (ring-mul ring) c (term-coeff term))))
 | 
|---|
 | 95 |          (unless (funcall (ring-zerop ring) c1)
 | 
|---|
 | 96 |            (list (make-term (term-monom term) c1)))))
 | 
|---|
 | 97 |    p))
 | 
|---|
 | 98 | 
 | 
|---|
 | 99 | 
 | 
|---|
| [379] | 100 | (defun term-mul-lst (ring term1 term2)
 | 
|---|
| [380] | 101 |   "A special version of term multiplication. Returns (LIST TERM) where
 | 
|---|
 | 102 | TERM is the product of the terms TERM1 TERM2, or NIL when the product
 | 
|---|
 | 103 | is 0. This definition takes care of divisors of 0 in the coefficient
 | 
|---|
 | 104 | ring."
 | 
|---|
| [150] | 105 |   (let ((c (funcall (ring-mul ring) (term-coeff term1) (term-coeff term2))))
 | 
|---|
 | 106 |     (unless (funcall (ring-zerop ring) c)
 | 
|---|
 | 107 |       (list (make-term (monom-mul (term-monom term1) (term-monom term2)) c)))))
 | 
|---|
 | 108 | 
 | 
|---|
 | 109 | (defun term-times-termlist (ring term f)
 | 
|---|
 | 110 |   (declare (type ring ring))
 | 
|---|
| [379] | 111 |   (mapcan #'(lambda (term-f) (term-mul-lst ring term term-f)) f))
 | 
|---|
| [150] | 112 | 
 | 
|---|
 | 113 | (defun termlist-times-term (ring f term)
 | 
|---|
| [379] | 114 |   (mapcan #'(lambda (term-f) (term-mul-lst ring term-f term)) f))
 | 
|---|
| [150] | 115 | 
 | 
|---|
 | 116 | (defun monom-times-term (m term)
 | 
|---|
 | 117 |   (make-term (monom-mul m (term-monom term)) (term-coeff term)))
 | 
|---|
 | 118 | 
 | 
|---|
 | 119 | (defun monom-times-termlist (m f)
 | 
|---|
 | 120 |   (cond
 | 
|---|
 | 121 |    ((null f) nil)
 | 
|---|
 | 122 |    (t
 | 
|---|
 | 123 |     (mapcar #'(lambda (x) (monom-times-term m x)) f))))
 | 
|---|
 | 124 | 
 | 
|---|
 | 125 | (defun termlist-uminus (ring f)
 | 
|---|
 | 126 |   (mapcar #'(lambda (x)
 | 
|---|
 | 127 |               (make-term (term-monom x) (funcall (ring-uminus ring) (term-coeff x))))
 | 
|---|
 | 128 |           f))
 | 
|---|
 | 129 | 
 | 
|---|
 | 130 | (defun termlist-add (ring p q)
 | 
|---|
 | 131 |   (declare (type list p q))
 | 
|---|
 | 132 |   (do (r)
 | 
|---|
 | 133 |       ((cond
 | 
|---|
 | 134 |         ((endp p)
 | 
|---|
 | 135 |          (setf r (revappend r q)) t)
 | 
|---|
 | 136 |         ((endp q)
 | 
|---|
 | 137 |          (setf r (revappend r p)) t)
 | 
|---|
 | 138 |         (t
 | 
|---|
 | 139 |          (multiple-value-bind
 | 
|---|
 | 140 |              (lm-greater lm-equal)
 | 
|---|
 | 141 |              (monomial-order (termlist-lm p) (termlist-lm q))
 | 
|---|
 | 142 |            (cond
 | 
|---|
 | 143 |             (lm-equal
 | 
|---|
 | 144 |              (let ((s (funcall (ring-add ring) (termlist-lc p) (termlist-lc q))))
 | 
|---|
 | 145 |                (unless (funcall (ring-zerop ring) s)    ;check for cancellation
 | 
|---|
 | 146 |                  (setf r (cons (make-term (termlist-lm p) s) r)))
 | 
|---|
 | 147 |                (setf p (cdr p) q (cdr q))))
 | 
|---|
 | 148 |             (lm-greater
 | 
|---|
 | 149 |              (setf r (cons (car p) r)
 | 
|---|
 | 150 |                    p (cdr p)))
 | 
|---|
 | 151 |             (t (setf r (cons (car q) r)
 | 
|---|
 | 152 |                      q (cdr q)))))
 | 
|---|
 | 153 |          nil))
 | 
|---|
 | 154 |        r)))
 | 
|---|
 | 155 | 
 | 
|---|
 | 156 | (defun termlist-sub (ring p q)
 | 
|---|
 | 157 |   (declare (type list p q))
 | 
|---|
 | 158 |   (do (r)
 | 
|---|
 | 159 |       ((cond
 | 
|---|
 | 160 |         ((endp p)
 | 
|---|
 | 161 |          (setf r (revappend r (termlist-uminus ring q)))
 | 
|---|
 | 162 |          t)
 | 
|---|
 | 163 |         ((endp q)
 | 
|---|
 | 164 |          (setf r (revappend r p))
 | 
|---|
 | 165 |          t)
 | 
|---|
 | 166 |         (t
 | 
|---|
 | 167 |          (multiple-value-bind
 | 
|---|
 | 168 |              (mgreater mequal)
 | 
|---|
 | 169 |              (monomial-order (termlist-lm p) (termlist-lm q))
 | 
|---|
 | 170 |            (cond
 | 
|---|
 | 171 |             (mequal
 | 
|---|
 | 172 |              (let ((s (funcall (ring-sub ring) (termlist-lc p) (termlist-lc q))))
 | 
|---|
 | 173 |                (unless (funcall (ring-zerop ring) s)    ;check for cancellation
 | 
|---|
 | 174 |                  (setf r (cons (make-term (termlist-lm p) s) r)))
 | 
|---|
 | 175 |                (setf p (cdr p) q (cdr q))))
 | 
|---|
 | 176 |             (mgreater
 | 
|---|
 | 177 |              (setf r (cons (car p) r)
 | 
|---|
 | 178 |                    p (cdr p)))
 | 
|---|
 | 179 |             (t (setf r (cons (make-term (termlist-lm q) (funcall (ring-uminus ring) (termlist-lc q))) r)
 | 
|---|
 | 180 |                      q (cdr q)))))
 | 
|---|
 | 181 |          nil))
 | 
|---|
 | 182 |        r)))
 | 
|---|
 | 183 | 
 | 
|---|
 | 184 | ;; Multiplication of polynomials
 | 
|---|
 | 185 | ;; Non-destructive version
 | 
|---|
 | 186 | (defun termlist-mul (ring p q)
 | 
|---|
 | 187 |   (cond ((or (endp p) (endp q)) nil)    ;p or q is 0 (represented by NIL)
 | 
|---|
 | 188 |         ;; If p=p0+p1 and q=q0+q1 then pq=p0q0+p0q1+p1q
 | 
|---|
 | 189 |         ((endp (cdr p))
 | 
|---|
 | 190 |          (term-times-termlist ring (car p) q))
 | 
|---|
 | 191 |         ((endp (cdr q))
 | 
|---|
 | 192 |          (termlist-times-term ring p (car q)))
 | 
|---|
 | 193 |         (t
 | 
|---|
| [379] | 194 |          (let ((head (term-mul-lst ring (termlist-lt p) (termlist-lt q)))
 | 
|---|
| [150] | 195 |                (tail (termlist-add ring (term-times-termlist ring (car p) (cdr q))
 | 
|---|
 | 196 |                                    (termlist-mul ring (cdr p) q))))
 | 
|---|
 | 197 |            (cond ((null head) tail)
 | 
|---|
 | 198 |                  ((null tail) head)
 | 
|---|
 | 199 |                  (t (nconc head tail)))))))
 | 
|---|
 | 200 |                     
 | 
|---|
 | 201 | (defun termlist-unit (ring dimension)
 | 
|---|
 | 202 |   (declare (fixnum dimension))
 | 
|---|
 | 203 |   (list (make-term (make-monom dimension :initial-element 0)
 | 
|---|
 | 204 |                    (funcall (ring-unit ring)))))
 | 
|---|
 | 205 | 
 | 
|---|
 | 206 | (defun termlist-expt (ring poly n &aux (dim (monom-dimension (termlist-lm poly))))
 | 
|---|
 | 207 |   (declare (type fixnum n dim))
 | 
|---|
 | 208 |   (cond
 | 
|---|
 | 209 |    ((minusp n) (error "termlist-expt: Negative exponent."))
 | 
|---|
 | 210 |    ((endp poly) (if (zerop n) (termlist-unit ring dim) nil))
 | 
|---|
 | 211 |    (t
 | 
|---|
 | 212 |     (do ((k 1 (ash k 1))
 | 
|---|
 | 213 |          (q poly (termlist-mul ring q q))       ;keep squaring
 | 
|---|
 | 214 |          (p (termlist-unit ring dim) (if (not (zerop (logand k n))) (termlist-mul ring p q) p)))
 | 
|---|
 | 215 |         ((> k n) p)
 | 
|---|
 | 216 |       (declare (fixnum k))))))
 | 
|---|