In documentation for lreduce and rreduce, supply second argument as an explicit list
[maxima.git] / share / algebra / charsets / charsets_powers.lisp
blobee4e0ab02590d5091aecf2401a21c9accd371b37
1 ;; Maxima code for extracting powers, finding leading and trailing
2 ;; coefficients, and finding the degree of polynomials.
4 ;; Author Barton Willis, University of Nebraska at Kearney (aka UNK)
5 ;; December 2001, December 2002
7 ;; License: GPL
8 ;; The user of this code assumes all risk for its use. It has no warranty.
9 ;; If you don't know the meaning of "no warranty," don't use this code. :)
11 (in-package :maxima)
12 ($put '$powers 1 '$version)
14 ;; Acknowledgement: Dan Stanger helped find and correct bugs. He
15 ;; also wrote user documentation and a test routine.
17 ;; posintp(x) returns true iff x is a positive integer or if x has been declared
18 ;; to be an integer and has been assumed to be greater than zero. Thus
20 ;; (C1) declare(m, integer)$
21 ;; (C2) assume(m > 0)$
22 ;; (C3) posintp(m);
23 ;; (D3) TRUE
24 ;; posintp isn't used by any functions in powers; it could be expunged.
26 (defun $posintp (x)
27 (and (or ($integerp x) ($featurep x '$integer)) (mgrp x 0)))
29 ;; Set ratfac to nil, return rat(e,x), and reset ratfac to
30 ;; its previous value.
32 (defun myrat (e &rest x)
33 (let ((save-ratfac $ratfac))
34 (setq $ratfac nil)
35 (unwind-protect
36 (apply '$rat `(,e ,@x))
37 (setq $ratfac save-ratfac))))
39 ;; If x list a Maxima list of symbols, return true iff the expression p
40 ;; doesn't depend on any member of x. If x is a symbol, return true
41 ;; iff p doesn't depend on x. This function is similar to $freeof, but
42 ;; it maybe somewhat more efficient when p is a CRE expression. Finally,
43 ;; if x (any member of x when x is a Maxima list) isn't a symbol signal
44 ;; an error.
46 (defun $ratfreeof (x p)
47 (setq x (require-list-of-symbols x "$ratfreeof" 2))
48 (let ((p-vars (cdr ($showratvars p))))
49 (cond ((every #'(lambda (z) (or ($symbolp z) ($subvarp z))) p-vars)
50 (every #'(lambda (z) (null (member z p-vars :test #'like))) x))
51 (t
52 (setq p ($totaldisrep p))
53 (every #'(lambda(z) ($freeof ($totaldisrep z) p)) x)))))
55 ;; variablep(e) evaluates to true if and only if e is a non-constant symbol
56 ;; or a subscripted symbol. Because symbolp(pi) evaluates to true, we need to
57 ;; check whether cd mae is constant.
59 (defun $variablep (e)
60 (and (or ($symbolp e) ($subvarp e)) (not ($constantp e))))
62 ;; ordinal_string(i) returns the ordinal name of the integer i. When
63 ;; i > 10, i < 1, or i isn't an integer, give up and return i-th.
65 (defun $ordinal_string (i)
66 (case i
67 (1 "first")
68 (2 "second")
69 (3 "third")
70 (4 "fourth")
71 (5 "fifth")
72 (6 "sixth")
73 (7 "seventh")
74 (8 "eighth")
75 (9 "ninth")
76 (10 "tenth")
77 (otherwise
78 (format nil "~A-th" (mfuncall '$string i)))))
80 ;; If variablep(v) evaluates to false, signal an error saying that
81 ;; the i-th argument of the function f requires a symbol; otherwise,
82 ;; return true.
84 (defun require-symbol (v f i)
85 (if (not ($variablep v))
86 (merror "The ~A argument of ~:M must be a symbol, instead found ~:M"
87 ($ordinal_string i) f v) t))
89 ;; If v is a Maxima list and each element of v is a symbol, return the
90 ;; cdr of v. When v isn't a list, but is a symbol, return the Lisp list
91 ;; (list v). Otherwise signal an error saying that the i-th argument of the
92 ;; function f requires a symbol or a list of symbols.
94 (defun require-list-of-symbols (v f i)
95 (let ((x))
96 (if ($listp v) (setq x (cdr v)) (setq x (list v)))
97 (if (every #'$variablep x) x
98 (merror "The ~A argument of ~:M must be a symbol or a list of symbols, instead found ~:M" ($ordinal_string i) f v))))
100 (defun require-poly (p v f i)
101 (setq p (myrat p v))
102 (if ($charsets_polynomialp p v) p
103 (merror "The ~A argument of ~:M requires a polynomial, instead found ~:M" ($ordinal_string i) f p)))
105 (defun require-nonlist (e f i)
106 (if ($listp e)
107 (merror "The ~A argument of ~:M requires a nonlist, instead found ~:M"
108 ($ordinal_string i) f e)))
110 ;; Return a Maxima list of the non-constant rat variables in e.
112 (defun non-constant-ratvars (e)
113 (let ((v (cdr ($showratvars e)))
114 (acc))
115 (dolist (vi v `((mlist simp) ,@acc))
116 (if (not ($constantp vi)) (push vi acc)))))
118 ;; If e is a list, map $powers over the list. If e is a sum of powers
119 ;; of powers of x, return a list of the exponents.
121 (defun $powers (e x)
122 (require-symbol x "$powers" 2)
123 (cond (($listp e)
124 (cons '(mlist simp) (mapcar #'(lambda (p) ($powers p x)) (cdr e))))
126 (setq e (require-poly (myrat e x) x "$powers" 1))
127 (cond (($ratfreeof x e)
128 `((mlist simp) 0))
130 (cons '(mlist simp) (odds (cadr e) 0)))))))
132 ;; Return the highest power of the polynomial e in the variable x.
134 (defun $hipower (e x)
135 (require-symbol x "$hipower" 2)
136 (setq e (require-poly (myrat e x) x "$hipower" 1))
137 (if (or ($constantp e) ($ratfreeof x e)) 0 (cadadr e)))
139 ;; Return the lowest power of the polynomial e in the variable x.
141 (defun $lowpower (e x)
142 (require-symbol x "$lowpower" 2)
143 (setq e (require-poly (myrat e x) x "$lowpower" 1))
144 (if (or ($constantp e) ($ratfreeof x e)) 0 (nth 1 (reverse (cadr e)))))
146 ;; Flatten a Maxima list.
148 (defun flatten-list (e)
149 (cond (($listp e)
150 (let ((acc))
151 (dolist (ei (cdr e) (cons '(mlist simp) (nreverse acc)))
152 (setq acc (if ($listp ei) (nconc (cdr (flatten-list ei)) acc)
153 (cons ei acc))))))
154 (t e)))
156 ;; If e is a sum of powers of x, return a list of the coefficients
157 ;; of powers of x. When e isn't a sum of powers, return false. This
158 ;; function is based on a Macsyma function written by A.D. Kennedy and
159 ;; referenced in "Mathematics and System Reference Manual," 16th edition,
160 ;; 1996.
162 (defun $allcoeffs (e x)
163 (flatten-list (allcoeffs e x)))
165 (defun allcoeffs (e x)
166 (cond (($listp e)
167 (cons '(mlist simp) (mapcar #'(lambda (s) (allcoeffs s x)) (cdr e))))
168 (($listp x)
169 (cond ((= 0 ($length x)) e)
170 (t (allcoeffs (allcoeffs e ($first x)) ($rest x)))))
172 (require-symbol x "$allcoeffs" 2)
173 (setq e (myrat e x))
174 (let ((p ($powers e x)))
175 (cons '(mlist simp)
176 (mapcar #'(lambda (n) ($ratcoef e x n)) (cdr p)))))))
178 ;; Return the coefficient of the term of the polynomial e that
179 ;; contains the highest power of x. When x = [x1,x2,...,xn], return
180 ;; lcoeff(lcoeff( ... (lcoeff(e,x1),x2),...,xn)...)
182 (defun $lcoeff (e &optional v)
183 (require-nonlist e "$lcoeff" 1)
184 (if (null v) (setq v (non-constant-ratvars e)))
185 (lcoeff (require-poly (myrat e) v "$lcoeff" 1)
186 (require-list-of-symbols v "$lcoeff" 2)))
188 (defun lcoeff (e x)
189 (if (null x) e (lcoeff ($ratcoef e (car x) ($hipower e (car x))) (cdr x))))
191 ;; Return the coefficient of the term of the polynomial e that
192 ;; contains the least power of x. When x = [x1,x2,...,xn], return
193 ;; lcoeff(lcoeff( ... (lcoeff(e,x1),x2),...,xn)...)
195 (defun $tcoeff (e &optional v)
196 (require-nonlist e "$tcoeff" 1)
197 (if (null v) (setq v (non-constant-ratvars e)))
198 (tcoeff (require-poly (myrat e) v "$tcoeff" 1)
199 (require-list-of-symbols v "$tcoeff" 2)))
201 (defun tcoeff (e x)
202 (if (null x) e (tcoeff ($ratcoef e (car x) ($lowpower e (car x))) (cdr x))))
204 ;; Return the degree of the symbol x in the polynomial p. When
205 ;; x is a list, degree(p, [x1,x2,...,xn]) returns
206 ;; degree(p,x1) + degree(lcoeff(p, x1),[x2,...xn]).
207 ;; Finally, degree(p,[]) returns 0.
209 (defun $degree (p x)
210 (degree (require-poly (myrat p) x "$degree" 1)
211 (require-list-of-symbols x "$degree" 2)))
213 (defun degree (p x)
214 (if (null x) 0
215 (add ($hipower p (car x)) (degree (lcoeff p `(,(car x))) (cdr x)))))
217 ;; Return the total degree of the polynomial. Four cases:
218 ;; (a) total_degree(p) returns the total degree of the polynomial
219 ;; in the variables listofvars(p).
220 ;; (b) total_degree(p,x), where x isn't a list returns the
221 ;; total_degree of p in the variable x.
222 ;; (c) total_degree(p,[x1,x2,...,xn]), where x = [x1,x2,...,xn]
223 ;; returns the total_degree of p in the variables x1 thru xn.
224 ;; (d) total_degree(p,x1,x2,...xn), where the x's are symbols
225 ;; returns the total_degree of p in the variables x1 thru xn.
227 (defun $total_degree (p &optional v)
228 (if (null v) (setq v (non-constant-ratvars p)))
229 (setq v (require-list-of-symbols v "$total_degree" 2))
230 (total-degree (cadr (apply 'myrat `(,p ,@v)))))
232 (defun total-degree (e)
233 (cond ((consp (nth 2 e))
234 (+ (nth 1 e) (total-degree (nth 2 e))))
236 (nth 1 e))))
238 (defun $lcm (p q)
239 (nth 1 ($divide (mul p q) ($gcd p q))))
241 ;; Compute the s-polynomial of f and g. For a definition of the
242 ;; s-polynomial, see Davenport, Siret, and Tournier, "Computer Algebra,"
243 ;; 1988, page 100.
245 (defun $spoly (f g v)
246 (setq v (cons '(mlist simp) (require-list-of-symbols v "$spoly" 3)))
247 (setq f (myrat f))
248 (setq g (myrat g))
249 (let ((fp ($lterm f v))
250 (gp ($lterm g v)))
251 (mul ($lcm fp gp) (add (div f fp) (mul -1 (div g gp))))))
253 (defun $lterm (p &optional v)
254 (if (null v) (setq v (non-constant-ratvars p)))
255 (lterm (require-poly (myrat p) v "$lterm" 1)
256 (require-list-of-symbols v "$lterm" 2)))
258 (defun lterm (p v)
259 (cond ((null v) p)
261 (let* ((vo (car v))
262 (n ($hipower p vo)))
263 (lterm (mult ($ratcoef p vo n) (power vo n)) (cdr v))))))
265 (defun $get_exponents (p x)
266 (setq x (require-list-of-symbols x "$get_exponents" 2))
267 (let ((acc))
268 (setq p (myrat p))
269 (require-poly p (cons '(mlist simp) x) "$get_exponents" 1)
270 (dolist (xi x (cons '(mlist simp) (nreverse acc)))
271 (push ($hipower p xi) acc)
272 (setq p ($lcoeff p xi)))))
274 ;; Return true iff and only if e is a polynomial in the variables var.
276 (defun $charsets_polynomialp (e &optional vars cp ep)
277 (declare (ignore cp ep))
278 (if (null vars) (setq vars (non-constant-ratvars e)))
279 (setq vars (require-list-of-symbols vars "$charsets_polynomialp" 2))
280 (setq vars `((mlist simp) ,@vars))
281 (and (every #'(lambda (x) (or ($variablep x) ($ratfreeof vars x)
282 ($constantp x)))
283 (cdr ($showratvars e)))
284 (not ($taylorp e)) ($ratfreeof vars ($ratdenom e))))