1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancements. ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; (c) Copyright 1980 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 (macsyma-module polyrz
)
15 ;;(declare-top (special equations))
17 (load-macsyma-macros ratmac
)
19 ;; PACKAGE FOR FINDING REAL ZEROS OF UNIVARIATE POLYNOMIALS
20 ;; WITH INTEGER COEFFICIENTS USING STURM SEQUENCES.
22 (defmfun $realroots
(exp &optional
(eps $rootsepsilon
) &aux exp1
)
23 (setq exp1
(meqhk exp
))
25 (setq exp1
($ratdisrep exp1
)))
26 (when (or (not (mnump eps
)) (mnegp eps
) (equal eps
0))
27 (merror (intl:gettext
"realroots: second argument must be a positive number; found: ~M") eps
))
28 (let (($keepfloat nil
))
29 (sturmseq exp exp1 eps
)))
31 (defun unipoly (exp exp1
)
32 (setq exp1
(cadr (ratf exp1
)))
33 (cond ((and (not (atom exp1
))
34 (loop for v in
(cdr exp1
)
38 ;;(EVERY #'ATOM (CDR EXP)))
40 (t (merror (intl:gettext
"UNIPOLY: argument must be a univariate polynomial with rational coefficients; found: ~M") exp
))))
43 (cond ((floatp pt
) (maxima-rationalize pt
))
44 ((numberp pt
) (cons pt
1))
45 (($bfloatp pt
) (bigfloat2rat pt
))
46 ((atom pt
) (merror (intl:gettext
"MAKRAT: argument must be a number; found: ~M") pt
))
47 ((equal (caar pt
) 'rat
) (cons (cadr pt
) (caddr pt
)))
48 (t (merror (intl:gettext
"MAKRAT: argument must be a number; found: ~M") pt
))))
50 ;;(declare-top (special equations))
52 (defun sturmseq (exp exp1 eps
)
53 (let (varlist $factorflag $ratprint $ratfac
)
56 (multout (findroots (psqfr (pabs (unipoly exp exp1
)))
59 (multiple-value-bind (soln equations
)
60 (solve2 (findroots (psqfr (pabs (unipoly exp exp1
)))
63 (cons '(mlist) equations
))))))
65 ;;(declare-top (unspecial equations))
67 (defun sturm1 (poly eps
&aux b llist
)
68 (setq b
(cons (root-bound (cdr poly
)) 1))
69 (setq llist
(isolat poly
(cons (- (car b
)) (cdr b
)) b
))
70 (mapcar #'(lambda (int) (refine poly
(car int
) (cdr int
) eps
)) llist
))
73 (prog (n lcf loglcf coef logb
)
75 (setq lcf
(abs (cadr p
)))
76 (setq loglcf
(- (integer-length lcf
) 2))
78 loop
(cond ((null (setq p
(cddr p
))) (return (expt 2 logb
)))
79 ((< (setq coef
(abs (cadr p
))) lcf
) (go loop
)))
80 (setq logb
(max logb
(1+ (ceil (- (integer-length coef
) loglcf
1) (- n
(car p
))))))
84 (+ (quotient a b
) ;CEILING FOR POS A,B
87 (defun sturmapc (fn llist multiplicity
)
88 (cond ((null llist
) nil
)
89 (t (cons (funcall fn
(car llist
))
91 (sturmapc fn
(cdr llist
) multiplicity
)))) ))
93 (defun findroots (l eps
)
95 ((numberp (car l
)) (findroots (cddr l
) eps
))
96 (t (append (sturmapc 'sturmout
(sturm1 (car l
) eps
)(cadr l
))
97 (findroots (cddr l
) eps
) )) ))
100 (list '(mequal simp
) (car varlist
)
101 (midout (rhalf (rplus* (car int
) (cadr int
)))) ))
104 (cond ((equal (cdr pt
) 1) (car pt
))
105 ($float
(fpcofrat1 (car pt
) (cdr pt
)))
106 (t (list '(rat simp
) (car pt
) (cdr pt
))) ))
108 (defun uprimitive (p)
109 (pquotient p
(ucontent p
))) ;PRIMITIVE UNIVAR. POLY
113 (setq p1
(uprimitive p
))
114 (setq p2
(uprimitive (pderivative p1
(car p1
))))
115 (setq seq
(list p2 p1
))
116 a
(setq r
(prem p1
(pabs p2
)))
117 (cond ((pzerop r
) (return (reverse seq
))))
119 (setq p2
(pminus (uprimitive r
)))
128 ;; IVAR COUNTS SIGN CHANGES IN A STURM SEQUENCE
134 a
(cond ((null seq
)(return v
)))
135 (setq s
(reval (car seq
) pt
))
137 (cond ((minusp (* s ls
))(setq v
(1+ v
)))
138 ((not (zerop ls
))(go a
)))
142 (defun ivar2 (seq pt
)
143 (cond ((not (atom pt
)) (ivar seq pt
))
144 (t (setq seq
(mapcar (function leadterm
) seq
))
145 (ivar seq
(cons pt
1)) )))
147 ;; OUTPUT SIGN(P(R)) , R RATIONAL (A.B)
150 (cond ((pcoefp p
) (signum p
))
151 ((zerop (car r
)) (signum (ptterm (cdr p
) 0)))
152 (t (prog (a b bi v m c
)
159 a
(cond ((equal m
(car p
)) (setq c
(cadr p
))
162 (cond ((zerop m
) (return (signum (+ v
(* bi c
))))))
163 (setq v
(* a
(+ v
(* bi c
))))
169 (cond ((eq pt
'$inf
) 1)
171 (t (makrat (let (($numer t
))
174 (defmfun $nroots
(exp &optional
(l '$minf
) (r '$inf
))
175 (let (varlist $keepfloat $ratfac
)
176 (nroots (unipoly exp
(meqhk exp
)) (makpoint l
) (makpoint r
))))
178 (defun nroots (p l r
)
179 (rootaddup (psqfr p
) l r
))
181 (defun rootaddup (llist l r
)
182 (cond ((null llist
) 0)
183 ((numberp (car llist
)) (rootaddup (cddr llist
) l r
))
184 (t (+ (rootaddup (cddr llist
) l r
)
185 (* (cadr llist
) (nroot1 (car llist
) l r
)))) ))
187 (defun nroot1 (p l r
)
188 (let ((seq (sturm p
)))
189 (- (ivar2 seq l
) (ivar2 seq r
))))
191 ;; RETURNS ROOT IN INTERVAL OF FORM (A,B])
193 (defun isolat (p l r
)
194 (prog (seq lv rv mid midv tlist islist rts
)
196 (setq lv
(ivar seq l
))
197 (setq rv
(ivar seq r
))
198 (setq tlist
(setq islist nil
))
199 (cond ((equal lv rv
) (return nil
)))
200 a
(cond ((> (setq rts
(- lv rv
)) 1)(go b
))
201 ((equal rts
1)(setq islist
(cons (cons l r
) islist
))))
202 (cond ((null tlist
) (return islist
)))
203 (setq lv
(car tlist
))
204 (setq rv
(cadr tlist
))
205 (setq l
(caddr tlist
))
206 (setq r
(cadddr tlist
))
207 (setq tlist
(cddddr tlist
))
209 b
(setq mid
(rhalf (rplus* l r
)))
210 (setq midv
(ivar seq mid
))
211 (cond ((not (equal lv midv
))
212 (setq tlist
(append (list lv midv l mid
) tlist
))))
217 (defun refine (p l r eps
)
219 (cond ((zerop (setq sr
(reval p r
)))
220 (return (list r r
))) )
221 a
(cond ((rlessp (rdifference* r l
) eps
)
222 (return (list l r
))) )
223 (setq mid
(rhalf (rplus* l r
)))
224 (setq smid
(reval p mid
))
225 (cond ((zerop smid
)(return (list mid mid
)))
226 ((equal smid sr
)(setq r mid
))
230 (defun rhalf (r) (rreduce (car r
) (* 2 (cdr r
))))
233 (let ((g (abs (gcd a b
))))
234 (cons (truncate a g
) (truncate b g
))) )
237 (cons (+ (* (car a
) (cdr b
)) (* (car b
) (cdr a
)))
238 (* (cdr a
) (cdr b
))))
240 (defun rdifference* (a b
)
241 (rplus* a
(cons (- (car b
)) (cdr b
))) )
244 (< (* (car a
) (cdr b
))
245 (* (car b
) (cdr a
)) ))
248 ;;; This next function is to do what SOLVE2 should do in programmode
249 (defun multout (rootlist)
251 (setq rootlist
(do ((rtlst)
254 ((null lunch
) (cons (reverse rtlst
)
256 (setq rtlst
(cons (car lunch
) rtlst
))
257 (setq multlst
(cons (cadr lunch
) multlst
))
258 (setq lunch
(cddr lunch
))))
259 (setq $multiplicities
(cons '(mlist) (cdr rootlist
)))
262 ;;(declare-top (unspecial equations))