1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancments. ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; (c) Copyright 1982 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 (macsyma-module result
)
15 (declare-top (special varlist genvar $ratfac $keepfloat modulus
*alpha xv
))
17 (load-macsyma-macros ratmac
)
19 (defmfun $poly_discriminant
(poly var
)
20 (let* ((varlist (list var
))
24 (rvar (car (last genvar
)))
25 (n (pdegree (setq poly
(car rform
)) rvar
)))
28 ((or (= n
0) (not (atom (cdr rform
))))
29 (merror (intl:gettext
"poly_discriminant: first argument must be a polynomial in ~:M; found: ~M") var poly
))
32 (pquotient (resultant poly
(pderivative poly rvar
))
35 (defmfun $resultant
(a b mainvar
)
36 (let ((varlist (list mainvar
)) (genvar nil
)
37 ($ratfac t
) ($keepfloat nil
)
39 (when ($ratp a
) (setf a
($ratdisrep a
) formflag t
))
40 (when ($ratp b
) (setf b
($ratdisrep b
) formflag t
))
43 (setq a
(lmake2 (cadr (ratrep* a
)) nil
))
44 (setq b
(lmake2 (cadr (ratrep* b
)) nil
))
45 (setq mainvar
(caadr (ratrep* mainvar
)))
49 (setq res
(result1 (car a-term
) (car b-term
) mainvar
))
52 (if (zerop (third res
))
54 (ptimeschk (first res
)
55 (pexpt (makprod (second res
) nil
)
57 (* (cdr a-term
) (cdr b-term
)))))))
59 (if formflag
(pdis* ans
) (pdis ans
))))
61 (defun result1 (p1 p2 var
)
62 (cond ((or (pcoefp p1
) (pointergp var
(car p1
)))
63 (list 1 p1
(pdegree p2 var
)))
64 ((or (pcoefp p2
) (pointergp var
(car p2
)))
65 (list 1 p2
(pdegree p1 var
)))
67 (cond ((null (cdddr p2
)) (list 0 0 1))
68 (t (list (pexpt (caddr p1
) (cadr p2
))
72 (list (pexpt (caddr p2
) (cadr p1
))
75 ((> (setq var
(gcd (pgcdexpon p1
) (pgcdexpon p2
))) 1)
76 (list 1 (resultant (pexpon*// p1 var nil
)
77 (pexpon*// p2 var nil
)) var
))
78 (t (list 1 (resultant p1 p2
) 1))))
80 (defmvar $resultant
'$subres
"Designates which resultant algorithm")
82 (defvar *resultlist
'($subres $mod $red
))
84 (defun resultant (p1 p2
) ;assumes same main var
85 (if (> (p-le p2
) (p-le p1
))
86 (presign (* (p-le p1
) (p-le p2
)) (resultant p2 p1
))
88 ($subres
(subresult p1 p2
))
89 #+broken
($mod
(modresult p1 p2
))
90 ($red
(redresult p1 p2
))
91 (t (merror (intl:gettext
"resultant: no such algorithm: ~M") $resultant
)))))
94 (if (oddp n
) (pminus p
) p
))
96 ;; Computes resultant using subresultant PRS. See Brown, "The Subresultant PRS
97 ;; Algorithm" (TOMS Sept. 1978). This is Algorithm 1, as found on page 241.
99 ;; This routine will not work if the coefficients contain hidden copies of the
100 ;; main polynomial variable. For example, if P is x*sqrt(x^2-1) + 2 then, when
101 ;; encoded as a polynomial in x, it appears as x*c + 2 for some (opaque)
102 ;; c. While doing the PRS calculation, the SUBRESULT code will square c, causing
103 ;; extra x's to appear and making the degree of polynomials derived from P
104 ;; behave erratically. The code might error or, worse, return a wrong result.
106 ;; Write G[1] = P, G[2] = Q and write g[i] for the leading coefficient of
107 ;; G[i]. On the k'th iteration of the loop, we are computing G[k+2], which is
108 ;; given by the formula
110 ;; G[k+2] = (-1)^(delta[k]+1) prem(G[k], G[k+1]) / (g[k] h[k]^delta[k])
112 ;; except we set the denominator to 1 when k=1. Here, h[2] = g[2]^delta[1] and,
113 ;; for i >= 3, satisfies the recurrence:
115 ;; h[i] = g[i]^delta[i-1] h[i-1]^(1 - delta[i-1])
117 ;; Here, delta[i] = deg(G[i]) - deg(G[i+1]), which is non-negative.
119 ;; Dictionary between program variables and values computed by the algorithm:
121 ;; - g is set to g[i-2]
122 ;; - h is set to g[i-2]^d / "h^1-d"
124 ;; Since d and h^1-d haven't yet been set on this iteration, they get their
125 ;; previous values, which turn out to give:
127 ;; - h is set to g[i-2]^delta[i-3] h[i-3]^[1-delta[i-3]] which, substituting
132 ;; - degq is set to deg(G[i-1])
133 ;; - d is set to delta[i-2]
134 ;; - h^1-d is (confusingly!) set to h[i-2]^(delta[i-2] - 1).
136 (defun subresult (p q
)
137 (loop for g
= 1 then
(p-lc p
)
138 for h
= 1 then
(pquotient (pexpt g d
) h^
1-d
)
139 for degq
= (pdegree q
(p-var p
))
140 for d
= (- (p-le p
) degq
)
141 for h^
1-d
= (if (equal h
1) 1 (pexpt h
(1- d
)))
142 if
(zerop degq
) return
(if (pzerop q
) q
(pquotient (pexpt q d
) h^
1-d
))
144 q
(presign (1+ d
) (pquotient (prem p q
)
145 (ptimes g
(ptimes h h^
1-d
)))))))
147 ;; PACKAGE FOR CALCULATING MULTIVARIATE POLYNOMIAL RESULTANTS
148 ;; USING MODIFIED REDUCED P.R.S.
150 (defun redresult (u v
)
155 a
(if (pzerop (setq r
(prem u v
))) (return (pzero)))
156 (setq c
(ptimeschk c
(pexpt (p-lc v
)
157 (* (- (p-le u
) (p-le v
))
158 (- (p-le v
) (pdegree r
(p-var u
))
160 (setq sigma
(+ sigma
(* (p-le u
) (p-le v
))))
161 (if (zerop (pdegree r
(p-var u
)))
164 (pquotient (pexpt (pquotientchk r a
) (p-le v
)) c
))))
167 a
(pexpt (p-lc v
) (+ (p-le u
) 1 (- (p-le v
)))))
171 ;; PACKAGE FOR CALCULATING MULTIVARIATE POLYNOMIAL RESULTANTS
172 ;; USING MODULAR AND EVALUATION HOMOMORPHISMS.
173 ;; modresultant fails on the following example
174 ;;RESULTANT(((-4)*Z)^4+(Y+8*Z)^4+(X-5*Z)^4-1,
175 ;; ((-4)*Z)^4-(X-5*Z)^3*((-4)*Z)^3+(Y+8*Z)^3*((-4)*Z)^2
176 ;; +(-2)*(Y+8*Z)^4+((-4)*Z)^4+1,Z)
180 (defun modresult (a b
)
181 (modresult1 a b
(sort (union* (listovars a
) (listovars b
))
182 (function pointergp
))))
184 (defun modresult1 (x y varl
)
185 (cond ((null modulus
) (pres x y
(car varl
) (cdr varl
)))
186 (t (cpres x y
(car varl
) (cdr varl
))) ))
188 (defun pres (a b xr1 varl
)
189 (prog (m n f a
* b
* c
* p q c modulus
)
192 (setq f
(coefbound m n
(maxnorm (cdr a
)) (maxnorm (cdr b
)) ))
197 step2
(setq p
(newprime p
))
198 step3
(set-modulus p
)
201 (cond ((or (reject a
* m xr1
) (reject b
* n xr1
)) (go step2
)))
202 (setq c
* (cpres a
* b
* xr1 varl
))
204 (setq c
(lagrange3 c c
* p q
))
206 (cond ((> q f
) (return c
))
209 (defun reject (a m xv
)
210 (not (eqn (pdegree a xv
) m
)))
212 (defun coefbound (m n d e
)
213 (* 2 (expt (1+ m
) (ash n -
1))
214 (expt (1+ n
) (ash m -
1))
215 (cond ((oddp n
) (1+ ($isqrt
(1+ m
))))
217 (cond ((oddp m
) (1+ ($isqrt
(1+ n
))))
219 ;; (FACTORIAL (PLUS M N)) USED TO REPLACE PREV. 4 LINES. KNU II P. 375
223 (defun main2 (a var exp tot
)
224 (cond ((null a
) (cons exp tot
))
225 (t (main2 (cddr a
) var
226 (max (setq var
(pdegree (cadr a
) var
)) exp
)
227 (max (+ (car a
) var
) tot
))) ))
229 (defun cpres (a b xr1 varl
) ;XR1 IS MAIN VAR WHICH
230 (cond ((null varl
) (cpres1 (cdr a
) (cdr b
))) ;RESULTANT ELIMINATES
231 (t (prog ( m2
( m1
(cadr a
))
232 ( n1
(cadr b
)) n2
(k 0) c d a
* b
* c
* bp xv
) ;XV IS INTERPOLATED VAR
233 (declare (fixnum m1 n1 k
))
237 (setq varl
(cdr varl
))
238 (setq m2
(main2 (cdr a
) xv
0 0)) ;<XV DEG . TOTAL DEG>
239 (setq n2
(main2 (cdr b
) xv
0 0))
240 (cond ((zerop (+ (car m2
) (car n2
)))
241 (cond ((null varl
) (return (cpres1 (cdr a
) (cdr b
))))
243 (setq k
(1+ (min (+ (* m1
(car n2
)) (* n1
(car m2
)))
244 (+ (* m1
(cdr n2
)) (* n1
(cdr m2
))
248 (setq m2
(car m2
) n2
(car n2
))
251 (cond ((equal (setq bp
(1+ bp
)) modulus
)
252 (merror "CPRES: resultant primes too small."))
253 ((zerop m2
) (setq a
* a
))
254 (t (setq a
* (pcsubst a bp xv
))
255 (cond ((reject a
* m1 xr1
)(go step3
)) )) )
256 (cond ((zerop n2
) (setq b
* b
))
257 (t (setq b
* (pcsubst b bp xv
))
258 (cond ((reject b
* n1 xr1
) (go step3
))) ))
259 (setq c
* (cpres a
* b
* xr1 varl
))
260 (setq c
(lagrange33 c c
* d bp
))
261 (setq d
(ptimeschk d
(list xv
1 1 0 (cminus bp
))))
262 (cond ((> (cadr d
) k
) (return c
))
266 ;; *** NOTE THAT MATRIX PRODUCED IS ALWAYS SYMETRIC
267 ;; *** ABOUT THE MINOR DIAGONAL.
269 (defmfun $bezout
(p q var
)
270 (let ((varlist (list var
)) genvar
)
273 (setq p
(cadr (ratrep* p
))
274 q
(cadr (ratrep* q
)))
275 (setq p
(cond ((> (cadr q
) (cadr p
)) (bezout q p
))
278 (mapcar #'(lambda (l) (cons '(mlist) (mapcar 'pdis l
)))
281 (defun vmake (poly n
*l
)
282 (do ((i (1- n
) (1- i
))) ((minusp i
))
283 (cond ((or (null poly
) (< (car poly
) i
))
284 (setq *l
(cons 0 *l
)))
285 (t (setq *l
(cons (cadr poly
) *l
))
286 (setq poly
(cddr poly
)))))
290 (let* ((n (1+ (p-le p
)))
292 (a (vmake (p-terms p
) n nil
))
293 (b (vmake (p-terms q
) n nil
))
294 (ar (reverse (nthcdr n2 a
)))
295 (br (reverse (nthcdr n2 b
)))
296 (l (make-list n
:initial-element
0)))
297 (rplacd (nthcdr (1- (p-le p
)) a
) nil
)
298 (rplacd (nthcdr (1- (p-le p
)) b
) nil
)
302 (setq l
(mapcar #'(lambda (a b l
)
303 (ppluschk l
(pdifference
304 (ptimes br a
) (ptimes ar b
))))
307 (and (pzerop (car b
))
308 (do ((b (vmake (cdr q
) (cadr p
) nil
) (rot* b
))
310 ((not (pzerop (car b
))) (cons b m
))))) ))
313 (setq b
(copy-list b
))
320 (defun ppluschk (p q
)