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
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. :)
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)$
24 ;; posintp isn't used by any functions in powers; it could be expunged.
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
))
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
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
))
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.
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)
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,
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
)
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
)
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
)
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
)))
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.
122 (require-symbol x
"$powers" 2)
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
)
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)
151 (dolist (ei (cdr e
) (cons '(mlist simp
) (nreverse acc
)))
152 (setq acc
(if ($listp ei
) (nconc (cdr (flatten-list ei
)) acc
)
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,
162 (defun $allcoeffs
(e x
)
163 (flatten-list (allcoeffs e x
)))
165 (defun allcoeffs (e x
)
167 (cons '(mlist simp
) (mapcar #'(lambda (s) (allcoeffs s x
)) (cdr e
))))
169 (cond ((= 0 ($length x
)) e
)
170 (t (allcoeffs (allcoeffs e
($first x
)) ($rest x
)))))
172 (require-symbol x
"$allcoeffs" 2)
174 (let ((p ($powers e x
)))
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)))
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)))
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.
210 (degree (require-poly (myrat p
) x
"$degree" 1)
211 (require-list-of-symbols x
"$degree" 2)))
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
))))
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,"
245 (defun $spoly
(f g v
)
246 (setq v
(cons '(mlist simp
) (require-list-of-symbols v
"$spoly" 3)))
249 (let ((fp ($lterm f 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)))
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))
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
)
283 (cdr ($showratvars e
)))
284 (not ($taylorp e
)) ($ratfreeof vars
($ratdenom e
))))