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 1982 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 (macsyma-module sinint
)
15 (load-macsyma-macros ratmac
)
17 (defun rootfac (q sinint-var
)
18 (prog (nthdq nthdq1 simproots ans n-loops
)
19 (setq nthdq
(pgcd q
(pderivative q sinint-var
)))
20 (setq simproots
(pquotient q nthdq
))
21 (setq ans
(list (pquotient simproots
(pgcd nthdq simproots
))))
25 ((= n-loops $factor_max_degree
)
27 ((or (pcoefp nthdq
) (pointergp sinint-var
(car nthdq
)))
28 (return (reverse ans
))))
29 (setq nthdq1
(pgcd (pderivative nthdq sinint-var
) nthdq
))
30 (push (pquotient (pgcd nthdq simproots
)
31 (pgcd nthdq1 simproots
))
37 (defun aprog (q sinint-var
)
38 (setq q
(oldcontent q
))
39 (let ((sinint-rootfactor
40 (rootfac (cadr q
) sinint-var
)))
41 (setq sinint-rootfactor
42 (cons (ptimes (car q
) (car sinint-rootfactor
))
43 (cdr sinint-rootfactor
)))
44 (let (sinint-pardenom)
45 (do ((pd (list (car sinint-rootfactor
)))
46 (rf (cdr sinint-rootfactor
) (cdr rf
))
49 (setq sinint-pardenom
(reverse pd
)))
50 (push (pexpt (car rf
) n
)
52 (values sinint-rootfactor sinint-pardenom
))))
54 (defun cprog (top bottom sinint-var sinint-pardenom
)
55 (prog (frpart pardenomc ppdenom thebpg sinint-parnumer sinint-wholepart
)
56 (setq frpart
(pdivide top bottom
))
57 (setq sinint-wholepart
(car frpart
))
58 (setq frpart
(cadr frpart
))
59 (if (= (length sinint-pardenom
) 1)
60 (return (values (list frpart
) sinint-wholepart
)))
61 (setq pardenomc
(cdr sinint-pardenom
))
62 (setq ppdenom
(list (car sinint-pardenom
)))
64 (if (= (length pardenomc
) 1)
66 (setq ppdenom
(cons (ptimes (car ppdenom
) (car pardenomc
))
68 (setq pardenomc
(cdr pardenomc
))
71 (setq pardenomc
(reverse sinint-pardenom
))
73 (setq thebpg
(bprog (car pardenomc
)
77 (cons (cdr (ratdivide (ratti frpart
(cdr thebpg
) t
)
81 (cdr (ratdivide (ratti frpart
(car thebpg
) t
)
83 (setq pardenomc
(cdr pardenomc
))
84 (setq ppdenom
(cdr ppdenom
))
86 (return (values (cons frpart sinint-parnumer
)
90 (defun polyint (p sinint-var
)
92 ((polyint1 (p sinint-var
)
93 (cond ((or (null p
) (equal p
0))
96 (list sinint-var
1 p
))
97 ((not (numberp (car p
)))
98 (if (pointergp sinint-var
(car p
))
100 (polyint1 (cdr p
) sinint-var
)))
102 (ratplus (polyint2 p sinint-var
)
103 (polyint1 (cddr p
) sinint-var
)))))
105 (polyint2 (p sinint-var
)
106 (cons (list sinint-var
110 (ratqu (polyint1 (ratnumerator p
) sinint-var
)
111 (ratdenominator p
))))
114 (defun dprog (ratarg sinint-ratform sinint-var
)
115 (prog (klth kx arootf deriv thebpg thetop thebot prod1 prod2 ans
116 sinint-logptdx sinint-parnumer sinint-pardenom sinint-rootfactor sinint-wholepart
)
117 (setq ans
(cons 0 1))
118 (if (or (pcoefp (cdr ratarg
)) (pointergp sinint-var
(cadr ratarg
)))
119 (return (values (disrep (polyint ratarg sinint-var
) sinint-ratform
)
121 (multiple-value-setq (sinint-rootfactor sinint-pardenom
)
122 (aprog (ratdenominator ratarg
) sinint-var
))
123 (multiple-value-setq (sinint-parnumer sinint-wholepart
)
124 (cprog (ratnumerator ratarg
)
125 (ratdenominator ratarg
)
128 (setq sinint-rootfactor
(reverse sinint-rootfactor
))
129 (setq sinint-parnumer
(reverse sinint-parnumer
))
130 (setq klth
(length sinint-rootfactor
))
132 (if (= klth
1) (go simp
))
133 (setq arootf
(car sinint-rootfactor
))
134 (if (zerop (pdegree arootf sinint-var
))
136 (setq deriv
(pderivative arootf sinint-var
))
137 (setq thebpg
(bprog arootf deriv sinint-var
))
139 (setq thetop
(car sinint-parnumer
))
141 (setq prod1
(ratti thetop
(car thebpg
) t
))
142 (setq prod2
(ratti thetop
(cdr thebpg
) t
))
143 (setq thebot
(pexpt arootf kx
))
145 (ratplus ans
(ratqu (ratminus prod2
)
146 (ratti kx thebot t
))))
149 (ratqu (ratreduce (pderivative (car prod2
) sinint-var
)
152 (setq thetop
(cdr (ratdivide thetop thebot
)))
154 (setq sinint-logptdx
(cons (ratqu thetop arootf
)
160 (setq sinint-rootfactor
(cdr sinint-rootfactor
))
161 (setq sinint-parnumer
(cdr sinint-parnumer
))
165 (push (ratqu (car sinint-parnumer
) (car sinint-rootfactor
))
168 (return (values (disrep (polyint sinint-wholepart sinint-var
) sinint-ratform
)
171 (cadr (pdivide (ratnumerator ans
) (ratdenominator ans
))))
172 (return (values (list '(mplus)
173 (disrep (polyint sinint-wholepart sinint-var
) sinint-ratform
)
174 (disrep (ratqu thetop
(ratdenominator ans
)) sinint-ratform
))
178 (list '(%log
) (if $logabs
179 (simplify (list '(mabs) x
))
182 (defun npask (npask-exp)
183 (cond ((freeof '$%i npask-exp
)
184 (learn `((mnotequal) ,npask-exp
0)
189 (defmvar $integrate_use_rootsof nil
190 "Use the rootsof form for integrals when denominator does not factor"
191 :setting-list
(nil t
))
193 (defun integrate-use-rootsof (f q variable sinint-ratform
)
194 (let ((dummy (make-param))
195 (qprime (disrep (pderivative q
(p-var q
)) sinint-ratform
))
196 (ff (disrep f sinint-ratform
))
197 (qq (disrep q sinint-ratform
)))
198 ;; This basically does a partial fraction expansion and integrates
199 ;; the result. Let r be one (simple) root of the denominator
200 ;; polynomial q. Then the partial fraction expansion is
202 ;; f(x)/q(x) = A/(x-r) + similar terms.
206 ;; f(x) = A*q(x)/(x-r) + others
208 ;; Take the limit as x -> r.
210 ;; f(r) = A*limit(q(x)/(x-r),x,r) + others
211 ;; = A*at(diff(q(x),r), [x=r])
213 ;; Hence, A = f(r)/at(diff(q(x),x),[x=r])
215 ;; Then it follows that the integral is
219 ;; Note that we don't express the polynomial in terms of the
220 ;; variable of integration, but in our dummy variable instead.
221 ;; Using the variable of integration results in a wrong answer
222 ;; when a substitution was done previously, since when the
223 ;; substitution is finally undone, that modifies the polynomial.
225 ,(div* (subst dummy variable ff
)
226 (subst dummy variable qprime
))
227 ((%log
) ,(sub* variable dummy
)))
229 (($rootsof
) ,(subst dummy variable qq
) ,dummy
))))
231 (defun eprog (p sinint-ratform sinint-var sinint-switch1
)
232 (prog (p1e p2e a1e a2e a3e discrim repart sign ncc dcc allcc xx deg
233 sinint-parnumer sinint-pardenom sinint-wholepart
)
234 (if (or (equal p
0) (equal (car p
) 0))
236 (setq p1e
(ratnumerator p
)
237 p2e
(ratdenominator p
))
238 (cond ((or sinint-switch1
239 (and (not (atom p2e
))
240 (eq (car (setq xx
(cadr (oldcontent p2e
))))
242 (member (setq deg
(pdegree xx sinint-var
)) '(5 6) :test
#'equal
)
243 (zerocoefl xx deg sinint-var
)
245 (not (pminusp (car (last xx
)))))))
247 (setq a1e
(intfactor p2e
))
248 (if (> (length a1e
) 1)
251 (setq ncc
(oldcontent p1e
))
252 (setq p1e
(cadr ncc
))
253 (setq dcc
(oldcontent p2e
))
254 (setq p2e
(cadr dcc
))
255 (setq allcc
(ratqu (car ncc
) (car dcc
)))
256 (setq deg
(pdegree p2e sinint-var
))
257 (setq a1e
(pderivative p2e sinint-var
))
258 (setq a2e
(ratqu (polcoef p1e
(pdegree p1e sinint-var
) sinint-var
)
259 (polcoef a1e
(pdegree a1e sinint-var
) sinint-var
)))
260 (cond ((equal (ratti a2e a1e t
) (cons p1e
1))
261 (return (list '(mtimes)
262 (disrep (ratti allcc a2e t
) sinint-ratform
)
263 (logmabs (disrep p2e sinint-ratform
))))))
264 (cond ((equal deg
1) (go e10
))
265 ((equal deg
2) (go e20
))
266 ((and (equal deg
3) (equal (polcoef p2e
2 sinint-var
) 0)
267 (equal (polcoef p2e
1 sinint-var
) 0))
268 (return (e3prog p1e p2e allcc sinint-ratform sinint-var sinint-switch1
)))
269 ((and (member deg
'(4 5 6) :test
#'equal
)
270 (zerocoefl p2e deg sinint-var
))
271 (return (enprog p1e p2e allcc deg sinint-ratform sinint-var
))))
272 (cond ((and $integrate_use_rootsof
273 (equal (car (psqfr p2e
)) p2e
))
274 (return (list '(mtimes)
275 (disrep allcc sinint-ratform
)
276 (integrate-use-rootsof p1e p2e
279 (return (list '(mtimes)
280 (disrep allcc sinint-ratform
)
283 (disrep p1e sinint-ratform
)
284 (disrep p2e sinint-ratform
))
285 (car (last varlist
)))))
287 (return (list '(mtimes)
289 (ratqu (polcoef p1e
(pdegree p1e sinint-var
) sinint-var
)
290 (polcoef p2e
1 sinint-var
))
293 (logmabs (disrep p2e sinint-ratform
))))
296 (ratdifference (cons (pexpt (polcoef p2e
1 sinint-var
) 2)
299 (ratti (polcoef p2e
2 sinint-var
)
300 (polcoef p2e
0 sinint-var
)
303 (setq a2e
(ratti (polcoef p2e
(pdegree p2e sinint-var
) sinint-var
) 2 t
))
304 (setq xx
(simplify (disrep discrim sinint-ratform
)))
305 (when (equal ($imagpart xx
) 0)
306 (setq sign
(npask xx
))
307 (cond ((eq sign
'$negative
) (go e30
))
308 ((eq sign
'$zero
) (go zip
))))
309 (setq a1e
(ratsqrt discrim sinint-ratform
))
314 (disrep a2e sinint-ratform
)
315 (disrep (list sinint-var
1 1) sinint-ratform
))
316 (disrep (polcoef p2e
1 sinint-var
) sinint-ratform
)
317 (list '(mminus) a1e
))
320 (disrep a2e sinint-ratform
)
321 (disrep (list sinint-var
1 1) sinint-ratform
))
322 (disrep (polcoef p2e
1 sinint-var
) sinint-ratform
)
324 (cond ((zerop (pdegree p1e sinint-var
))
325 (return (list '(mtimes)
326 (disrep allcc sinint-ratform
)
328 (disrep (polcoef p1e
0 sinint-var
) sinint-ratform
)
336 (ratqu (polcoef p1e
(pdegree p1e sinint-var
) sinint-var
) a2e
)
339 (logmabs (disrep p2e sinint-ratform
)))
345 (ratqu (eprogratd a2e p1e p2e sinint-var
) a2e
)
351 (setq a1e
(ratsqrt (ratminus discrim
) sinint-ratform
))
354 (ratqu (cond ((zerop (pdegree p1e sinint-var
))
355 (ratti a2e
(polcoef p1e
0 sinint-var
) t
))
357 (eprogratd a2e p1e p2e sinint-var
)))
358 (polcoef p2e
(pdegree p2e sinint-var
) sinint-var
)))
359 (setq a3e
(cond ((equal 0 (car repart
))
362 `((mtimes) ((mquotient)
363 ,(disrep (ratti allcc repart t
) sinint-ratform
)
367 ,(disrep (pderivative p2e sinint-var
) sinint-ratform
)
369 (if (zerop (pdegree p1e sinint-var
))
371 (return (list '(mplus)
374 (ratqu (polcoef p1e
(pdegree p1e sinint-var
) sinint-var
) a2e
)
377 (logmabs (disrep p2e sinint-ratform
)))
386 (pexpt (ptimes 2 (polcoef p2e
2 sinint-var
)) 2)
388 (ptimes 4 (ptimes (polcoef p2e
2 sinint-var
)
389 (polcoef p2e
1 sinint-var
)))
390 (pcoefadd 0 (pexpt (polcoef p2e
1 sinint-var
) 2) ()))))
391 (ptimes 4 (polcoef p2e
2 sinint-var
))))
392 (return (fprog (ratti allcc
(ratqu p1e p2e
) t
)
396 (setq sinint-parnumer nil
399 (multiple-value-setq (sinint-parnumer sinint-wholepart
)
400 (cprog p1e p2e sinint-var sinint-pardenom
))
402 (mapcar #'(lambda (j k
)
403 (eprog (ratqu j k
) sinint-ratform sinint-var sinint-switch1
))
404 sinint-parnumer sinint-pardenom
))
405 (setq sinint-switch1 nil
)
406 (return (cons '(mplus) a2e
))))
408 (defun e3prog (num denom cont sinint-ratform sinint-var sinint-switch1
)
409 (prog (a b c d e r ratr var
* x
)
410 (setq a
(polcoef num
2 sinint-var
)
411 b
(polcoef num
1 sinint-var
)
412 c
(polcoef num
0 sinint-var
)
413 d
(polcoef denom
3 sinint-var
)
414 e
(polcoef denom
0 sinint-var
))
415 (setq r
(cond ((eq (npask (simplify (disrep (ratqu e d
) sinint-ratform
)))
417 (simpnrt (disrep (ratqu (ratti -
1 e t
) d
) sinint-ratform
) 3))
419 (neg (simpnrt (disrep (ratqu e d
) sinint-ratform
) 3)))))
420 (setq var
* (list sinint-var
1 1))
422 (orderpointer varlist
)
424 (setq sinint-ratform
(car x
) ratr
(cdr x
))
429 (disrep (ratqu (r* cont
(r+ (r* a ratr ratr
) (r* b ratr
) c
))
432 (logmabs (disrep (ratpl (ratti -
1 ratr t
) var
*) sinint-ratform
)))
433 (eprog (r* cont
(ratqu (r+ (r* (r+ (r* 2 a ratr ratr
)
437 (r+ (ratqu (r* -
1 a e
) d
)
441 (r+ (ratti var
* var
* t
)
443 (ratti ratr ratr t
)))))
449 (defun eprogratd (a2e p1e p2e sinint-var
)
450 (ratdifference (ratti a2e
451 (polcoef p1e
(1- (pdegree p1e sinint-var
)) sinint-var
)
453 (ratti (polcoef p2e
(1- (pdegree p2e sinint-var
)) sinint-var
)
454 (polcoef p1e
(pdegree p1e sinint-var
) sinint-var
)
457 (defun enprog (num denom cont deg sinint-ratform sinint-var
)
458 ;; Denominator is (A*VAR^4+B) =
459 ;; if B<0 then (SQRT(A)*VAR^2 - SQRT(-B)) (SQRT(A)*VAR^2 + SQRT(-B))
461 ;; (SQRT(A)*VAR^2 - SQRT(2)*A^(1/4)*B^(1/4)*VAR + SQRT(B)) *
462 ;; (SQRT(A)*VAR^2 + SQRT(2)*A^(1/4)*B^(1/4)*VAR + SQRT(B))
464 ;; (1/4) * (A^(1/5)*VAR + B^(1/5)) *
465 ;; (2*A^(2/5)*VAR^2 + (-SQRT(5)-1)*A^(1/5)*B^(1/5)*VAR + 2*B^(2/5)) *
466 ;; (2*A^(2/5)*VAR^2 + (+SQRT(5)-1)*A^(1/5)*B^(1/5)*VAR + 2*B^(2/5))
468 ;; if B<0 then (SQRT(A)*VAR^3 - SQRT(-B)) (SQRT(A)*VAR^3 + SQRT(-B))
470 ;; (A^(1/3)*VAR^2 + B^(1/3)) *
471 ;; (A^(1/3)*VAR^2 - SQRT(3)*A^(1/6)*B^(1/6)*VAR + B^(1/3)) *
472 ;; (A^(1/3)*VAR^2 + SQRT(3)*A^(1/6)*B^(1/6)*VAR + B^(1/3))
473 (prog (($expop
0) ($expon
0) a b term disvar $algebraic
)
475 (setq $expop
0 $expon
0)
476 (setq a
(simplify (disrep (polcoef denom deg sinint-var
) sinint-ratform
))
477 b
(simplify (disrep (polcoef denom
0 sinint-var
) sinint-ratform
))
478 disvar
(simplify (get sinint-var
'disrep
))
479 num
(simplify (disrep num sinint-ratform
))
480 cont
(simplify (disrep cont sinint-ratform
)))
482 (if (eq '$neg
($asksign b
))
484 (mul2 (add2 (mul2 (power a
'((rat simp
) 1 2)) (power disvar
2))
485 (power (mul -
1 b
) '((rat simp
) 1 2)))
486 (add2 (mul2 (power a
'((rat simp
) 1 2)) (power disvar
2))
487 (mul -
1 (power (mul -
1 b
) '((rat simp
) 1 2))))))
489 (setq denom
(add2 (mul2 (power a
'((rat simp
) 1 2)) (power disvar
2))
490 (power b
'((rat simp
) 1 2)))
491 term
(muln (list (power 2 '((rat simp
) 1 2))
492 (power a
'((rat simp
) 1 4))
493 (power b
'((rat simp
) 1 4))
496 (setq denom
(mul2 (add2 denom term
) (sub denom term
))))))
498 (setq term
(mul3 (power a
'((rat simp
) 1 5))
499 (power b
'((rat simp
) 1 5))
501 (setq denom
(add2 (mul3 2 (power a
'((rat simp
) 2 5))
503 (sub (mul2 2 (power b
'((rat simp
) 2 5))) term
)))
504 (setq term
(mul2 (power 5 '((rat simp
) 1 2)) term
))
505 (setq denom
(muln (list '((rat simp
) 1 4)
506 (add2 (mul2 (power a
'((rat simp
) 1 5)) disvar
)
507 (power b
'((rat simp
) 1 5)))
508 (add2 denom term
) (sub denom term
))
511 (if (eq '$neg
($asksign b
))
513 (mul2 (add2 (mul2 (power a
'((rat simp
) 1 2)) (power disvar
3))
514 (power (mul -
1 b
) '((rat simp
) 1 2)))
515 (add2 (mul2 (power a
'((rat simp
) 1 2)) (power disvar
3))
516 (mul -
1 (power (mul -
1 b
) '((rat simp
) 1 2))))))
518 (setq denom
(add2 (mul2 (power a
'((rat simp
) 1 3)) (power disvar
2))
519 (power b
'((rat simp
) 1 3)))
520 term
(muln (list (power 3 '((rat simp
) 1 2))
521 (power a
'((rat simp
) 1 6))
522 (power b
'((rat simp
) 1 6))
525 (setq denom
(mul3 denom
(add2 denom term
) (sub denom term
))))
527 ;;Needs $ALGEBRAIC NIL so next call to RATF will preserve factorization.
528 (return (mul2 cont
(ratint (div num denom
) disvar
)))))
530 (defun zerocoefl (e n sinint-var
)
533 (if (not (equal (polcoef e i sinint-var
) 0))
536 (defun ratsqrt (a sinint-ratform
)
538 (simpnrt (disrep a sinint-ratform
) 2)))
540 (defun fprog (rat* sinint-ratform sinint-var
)
541 (multiple-value-bind (dprog-ret sinint-logptdx
)
542 (dprog rat
* sinint-ratform sinint-var
)
543 (addn (cons dprog-ret
544 (mapcar #'(lambda (p)
545 (eprog p sinint-ratform sinint-var nil
))
549 (defun ratint (sinint-exp sinint-var
)
550 (prog (genvar *checkfactors
* varlist ratarg $keepfloat
)
551 (setq varlist
(list sinint-var
))
552 (setq ratarg
(ratf sinint-exp
))
553 (let ((sinint-ratform (car ratarg
))
554 (sinint-var (caadr (ratf sinint-var
))))
555 (return (fprog (cdr ratarg
) sinint-ratform sinint-var
)))))
558 (labels ((everysecond (a)
559 (if a
(cons (if (numberp (car a
))
560 (pexpt (car a
) (cadr a
))
562 (everysecond (cddr a
))))))
564 (prog ($factorflag a b
)
565 (setq a
(oldcontent l
)
566 b
(everysecond (pfactor (cadr a
))))
567 (return (if (equal (car a
) 1)
569 (cons (car a
) b
))))))