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 irinte
)
15 (load-macsyma-macros rzmac
)
17 (declare-top (special checkcoefsignlist var zerosigntest productcase
))
19 (defun hasvar (exp) (not (freevar exp
)))
21 (defun zerp (a) (equal a
0))
23 (defun integerpfr (a) (if (not (maxima-integerp a
)) (integerp1 a
)))
25 (defun nonzerp (a) (not (equal a
0)))
27 (defun freevnz (a) (and (freevar a
) (not (equal a
0))))
30 (let ((checkcoefsignlist nil
)
31 (*globalcareflag
* nil
)
33 (declare (special checkcoefsignlist
*globalcareflag
* $radexpand
))
36 (defun intir-ref (fun x
)
38 (when (setq a
(intir1 fun x
)) (return a
))
39 (when (setq a
(intir2 fun x
)) (return a
))
40 (return (intir3 fun x
))))
43 (prog (assoclist e0 r0 e1 e2 r1 r2 d p
)
44 (setq assoclist
(factpow (specrepcheck fun
) x
))
45 (setq e1
(cdras 'e1 assoclist
)
46 e2
(cdras 'e2 assoclist
))
47 (cond ((null assoclist
)(return nil
)))
48 (setq d
(cdras 'd assoclist
)
49 p
(cdras 'p assoclist
)
50 e0
(cdras 'e0 assoclist
)
51 r0
(cdras 'r0 assoclist
)
52 r1
(cdras 'r1 assoclist
)
53 r2
(cdras 'r2 assoclist
))
55 (setq e0
(rdis (ration1 e0
)))))
57 (setq e1
(rdis (ration1 e1
)))))
59 (setq e2
(rdis (ration1 e2
)))))
60 (return (intir1-ref d p r0 e0 r1 e1 r2 e2 x
))))
62 (defun intir2 (funct x
)
63 (let ((res (intir funct x
)))
66 (intirfactoroot funct x
))))
69 (prog ((assoclist (elliptquad exp x
)) e f g r0
)
71 (setq e
(cdras 'e assoclist
) f
(cdras 'f assoclist
)
72 g
(cdras 'g assoclist
) r0
(cdras 'r0 assoclist
))
73 (assume `(($notequal
) ,e
0))
74 (return (intir3-r0test assoclist x e f g r0
))))
77 (defun intir3-r0test (assoclist x e f g r0
)
78 (if (root+anything r0 x
)
80 (intir3-ref assoclist x e f g r0
)))
82 ;; Handle integrals of the form d*p(x)*r1(x)^e1*r2(x)^e2*r0(x)^e0,
83 ;; where p(x) is a polynomial, e1 and e2 are both half an odd integer,
84 ;; and e3 is an integer.
85 (defun intir1-ref (d p r0 e0 r1 e1 r2 e2 x
)
86 (let ((nume1 (cadr e1
)) ;; nume1 = 2*e1
87 (nume2 (cadr e2
))) ;; nume2 = 2*e2
88 ;; I think what this does is try to rationalize r1(x)^e1 or
89 ;; r2(x)^e2 so we end up with a new integrand of the form
90 ;; d*p'(x)*r0'(x)^e0*ra(x)^ea, where p'(x) is a new polynomial
91 ;; obtained from rationaling one term and r0'(x) is a more
93 (cond ((and (plusp nume1
) (plusp nume2
))
94 (pp-intir1 d p r0 e0 r1 e1 r2 e2 x
))
95 ((and (minusp nume1
) (minusp nume2
))
96 (mm-intir1 d p r0 e0 r1 e1 r2 e2 x
))
98 (pm-intir1 d p r0 e0 r1 e1 r2 e2 x
))
100 (pm-intir1 d p r0 e0 r2 e2 r1 e1 x
)))))
102 (defun pp-intir1 (d p r0 e0 r1 e1 r2 e2 x
)
103 (if (> (cadr e1
) (cadr e2
))
104 (pp-intir1-exec d p r0 e0 r1 e1 r2 e2 x
)
105 (pp-intir1-exec d p r0 e0 r2 e2 r1 e1 x
)))
107 ;; Handle integrals of the form d*p(x)*r0(x)^e0*r1(x)^e1*r2(x)^e2
108 ;; where p(x) is a polynomial, e1 < 0, and e2 < 0 and are both half an
109 ;; odd integer, and e3 is an integer.
110 (defun mm-intir1 (d p r0 e0 r1 e1 r2 e2 x
)
111 (if (> (cadr e1
) (cadr e2
))
112 (mm-intir1-exec d p r0 e0 r1 e1 r2 e2 x
)
113 (mm-intir1-exec d p r0 e0 r2 e2 r1 e1 x
)))
115 ;; Handle integrals of the form d*p(x)*r0(x)^e0*r1(x)^e1*r2(x)^e2
116 ;; where p(x) is a polynomial, e1 > 0, and e2 < 0 and are both half an
117 ;; odd integer, and e3 is an integer.
119 (defun pm-intir1 (d p r0 e0 rofpos epos rofneg eneg x
)
120 (let ((numepos (cadr epos
)) ;; numepos = 2*epos = 2*e1
121 (numul-1eneg (mul -
1 (cadr eneg
)))) ;; numul-1eneg = -2*eneg = -2*e2
122 (cond ((> numepos numul-1eneg
)
123 (mm-intir1 d
(mul p
(power rofpos
(sub epos eneg
)))
124 r0 e0 rofpos eneg rofneg eneg x
))
125 ((or (equal e0
0) (plusp e0
))
126 (pp-intir1 d
(mul p
(power rofneg
(sub eneg epos
)))
127 r0 e0 rofpos epos rofneg epos x
))
129 (mm-intir1 d
(mul p
(power rofpos
(sub epos eneg
)))
130 r0 e0 rofpos eneg rofneg eneg x
)))))
132 (defun pp-intir1-exec (d p r0 e0 rofmax emax rofmin emin x
)
133 (intir (mul d p
(if (equal e0
0) 1 (power r0 e0
))
134 (power rofmax
(add emax
(mul -
1 emin
)))
135 (power ($expand
(mul rofmax rofmin
)) emin
)) x
))
137 ;; Handle integrals of the form d*p(x)*r0(x)^e0*r1(x)^e1*r2(x)^e2
138 ;; where p(x) is a polynomial, e1 < 0, and e2 < 0 and are both half an
139 ;; odd integer, and e3 is an integer. And e2 > e1.
140 (defun mm-intir1-exec (d p r0 e0 rofmin emin rofmax emax x
)
144 (power rofmax
(add emax
(mul -
1 emin
)))
145 (power ($expand
(mul rofmax rofmin
)) emin
)) x
))
147 ;; Integrating the form (e*x^2+f*x+g)^m*r0(x)^e0.
149 (defun intir3-ref (assoclist x e f g r0
)
150 (let ((signdisc (signdiscr e f g
))
151 (d (cdras 'd assoclist
))
152 (p (cdras 'p assoclist
))
153 (e0 (cdras 'e0 assoclist
)))
154 (cond ((eq signdisc
'$positive
)
155 (pns-intir3 x e f g d p r0 e0
))
156 ((eq signdisc
'$negative
)
157 (ns-intir3 x e f g d p r0 e0
))
159 (zs-intir3 x e f d p r0 e0
)))))
161 (defun root+anything
(exp var
)
163 ((coeffpt) (c nonzerp
) ((mexpt) (u hasvar
) (v integerpfr
)))
164 ((coeffpp) (c true
)))))
166 ;; Handle d*p(x)/(e*x^2+f*x+g)*r0(x)^e0. We know that e*x^2+f*x+g has
167 ;; no repeated roots. Let D be the discriminant of this quadratic,
168 ;; sqrt(f^2-4*e*g). (If we're here, we already know that f^2-4*e*g >
169 ;; 0). Thus, we can factor this quadratic as
170 ;; (2*e*x+f-D)*(2*e*x+f+D)/(4*e). Thus, the original integrand
173 ;; 4*e*d/(2*e*x+f-D)/(2*e*x+f+D)*p(x)*r0(x)^e0.
175 ;; We can separate this as a partial fraction to get
177 ;; (2*d*e/D/(2*e*x+f-D) - 2*d*e/D/(2*e*x+f+D))*p(x)*r0(x)^e0.
179 ;; So we have separated this into two "simpler" integrals.
180 (defun pns-intir3 (x e f g d p r0 e0
)
181 (let* ((discr (power (sub (mul f f
) (mul 4 e g
)) 1//2)) ;; Compute discriminant of
182 (p*r0^e0
(mul p
(power r0 e0
))) ;; quadratic: sqrt(f^2-4*e*g)
183 (2*e
*x
+f
(add (mul 2 e x
) f
))
184 (2*e
*d
*invdisc
(mul 2 e d
(inv discr
))))
186 (sub (intir2 (mul (inv (sub 2*e
*x
+f discr
)) p
*r0^e0
) x
)
187 (intir2 (mul (inv (add 2*e
*x
+f discr
)) p
*r0^e0
) x
)))))
189 ;; Handle d*p(x)/(e*x^2+f*x+g)*r0(x)^e0. We know that e*x^2+f*x+g has
192 (defun zs-intir3 (x e f d p r0 e0
)
193 ;; Since e*x^2+f*x+g has repeated roots, it can be written as e*(x+r)^2.
194 ;; We easily see that r = f/(2*e), so rewrite the integrand as
196 ;; d*p(x)/e/(x+r)^2*r0(x)^e0.
197 (intir2 (mul d p
(inv e
)
198 (power (add x
(div f
(add e e
))) -
2)
202 ;; Handle d*p(x)/(e*x^2+f*x+g)*r0(x)^e0. We know that e*x^2+f*x+g has
205 ;; G&R 2.252 shows how we can handle these integrals, but I'm too lazy
206 ;; to implement them right now, so return NIL to indicate we don't
207 ;; know what to do. But whatever it is we do, it's definitely not
208 ;; calling intir or intir2 like zs-intir3 or pns-intir3 do because
209 ;; they eventually call inti which only handles linear forms (e = 0.)
210 ;; We'll need to write custom versions.
211 (defun ns-intir3 (xx ee fff gg dd pp r0 e0
)
212 (declare (ignore xx ee fff gg dd pp r0 e0
))
216 (cdr (assoc a b
:test
#'equal
)))
218 (defun intir (funct x
)
219 (inti funct x
(jmaug (specrepcheck funct
) x
)))
221 ;; Integrate d*p(x)*(f*x+e)^m*(a*x^2+b*x+c)^n. p(x) is a polynomial,
222 ;; m is an integer, n is a number(?). a, b, c, e, and f are
223 ;; expressions independent of x (var).
224 (defun inti (funct x assoclist
)
225 (prog (met n expr f e
#+nil denom
)
226 (setq n
(cdras 'n assoclist
))
227 (when (or (null assoclist
) (maxima-integerp n
))
229 (setq f
(cdras 'f assoclist
)
230 e
(cdras 'e assoclist
))
231 ;; If e is 0 (or not given, we don't have to do the
232 ;; transformation. Just integrate it and return.
233 (when (or (equal e
0) (null e
))
234 (return (intira funct x
)))
236 ;; (unless (numberp f) (go jump))
237 ;; (when (plusp f) (go jump))
238 ;; I (rtoy) think this is the case where f is a negative number.
239 ;; I think this is trying to convert f*x+e to -f*x-e to make the
240 ;; coefficient of x positive. And if I'm right, the code below
241 ;; isn't doing it correctly, except when m = 1 or m = -1.
242 ;; (setq denom (add (mul f x) e)
245 ;; funct (mul -1 (div (meval (mul denom funct))
246 ;; (add (mul f x) e))))
250 ;; Apply the linear substitution y = f*x+e. That is x = (y-e)/f.
251 ;; Then use INTIRA to integrate this. The integrand becomes
252 ;; something like p(y)*y^m and other terms.
253 (setq expr
(intira (distrexpandroot
256 (add (setq met
(make-symbol (symbol-name '#:yannis
)))
260 (setq expr
(and expr
(mul (inv f
) expr
)))
261 (return ($expand
($substitute
(add (mul f x
) e
) met expr
)))))
263 (defun distrexpandroot (expr)
266 (mul (expandroot (car expr
))
267 (distrexpandroot (cdr expr
)))))
269 (defun expandroot (expr)
272 (if (and (eq (caar expr
) 'mexpt
)
273 (integerpfr (caddr expr
)))
277 (defun intirfactoroot (expr x
)
278 (let ((factors (timestest expr
)))
280 (let* ((e (distrfactor factors x
))
282 (when alist
(inti e x alist
)))))
284 (let ((*globalcareflag
* t
))
285 (declare (special *globalcareflag
*))
290 ;; Apply FACTOROOT to each element in the list, FACTORS. Accumulate the results
291 ;; by multiplication, associating to the right.
292 (defun distrfactor (factors x
)
295 (mul (factoroot (first factors
) x
)
296 (distrfactor (rest factors
) x
))))
300 ;; If EXPR is of the form A^B and is not free of VAR, use CAREFULFACTOR to try
301 ;; to factor it. Otherwise just return EXPR.
302 (defun factoroot (expr var
)
303 (if (and (mexptp expr
)
305 (integerpfr (caddr expr
)))
306 (carefulfactor expr var
)
311 ;; Try to factor an expression of the form A^B. If *GLOBALCAREFLAG* is NIL, this
312 ;; is exactly the same as $FACTOR. Otherwise, use $FACTOR on (A/x)^B and then
313 ;; restore the missing x^B afterwards using RESTOREX.
314 (defun carefulfactor (expr x
)
315 (declare (special *globalcareflag
*))
316 (if (null *globalcareflag
*)
318 (restorex ($factor
(power (div (cadr expr
) x
) (caddr expr
)))
323 ;; Multiply EXPR by VAR^EXPT, trying to insert the factor of VAR inside terms in
324 ;; a product if possible.
325 (defun restorex (expr var expt
)
328 (equal expt
(caddr expr
)))
329 (power (restorex (cadr expr
) var
1) (caddr expr
)))
332 (distrestorex (cdr expr
) var expt
))
335 (mul (power var expt
) expr
))))
339 ;; Takes a list of factors. Returns an expression that equals the product of
340 ;; these factors, but after multiplying one of them by VAR to try to multiply
341 ;; the entire product by VAR^EXPT. If it's not possible to multiply factors to
342 ;; do so, add a factor of VAR^EXPT to the end.
343 (defun distrestorex (factors var expt
)
346 (let ((start (first factors
)))
347 (if (and (mexptp start
)
348 (equal expt
(caddr start
)))
351 (cons (power ($expand
(mul var
(cadr start
)))
355 (mul start
(distrestorex (rest factors
) var expt
))))))
357 (defun timestest (expr)
362 ;; Integrate a function of the form d*p(y)*y^m*(a*y^2+b*x+c)^n.
363 ;; n is half of an integer.
364 (defun intira (funct x
)
365 (prog (a b c
*ec-1
* d m n
(assoclist (jmaug (specrepcheck funct
) x
))
366 pluspowfo1 pluspowfo2 minuspowfo
367 polfact signn poszpowlist negpowlist
)
368 (declare (special *ec-1
*))
369 (setq n
(cdras 'n assoclist
))
371 ;; (format t "n = ~A~%" n)
372 (when (or (null assoclist
)
376 (setq n
(rdis (ration1 n
))))
377 (setq d
(cdras 'd assoclist
))
378 (when (equal d
0) (return 0))
379 (setq c
(cdras 'a assoclist
))
380 (when (equal c
0) (return nil
))
381 (setq m
(cdras 'm assoclist
)
382 polfact
(cdras 'p assoclist
)
383 ;; We know that n is of the form s/2, so just make n = s,
384 ;; and remember that the actual exponent needs to be
387 signn
(checksigntm n
)
389 b
(cdras 'b assoclist
)
390 a
(cdras 'c assoclist
)
391 ;; pluspowfo1 = 1/2*(n-1), That is, the original exponent - 1/2.
392 pluspowfo1
(mul 1//2 (+ n -
1))
393 ;; minupowfo = 1/2*(n+1), that is, the original exponent + 1/2.
394 minuspowfo
(mul 1//2 (+ n
1))
395 ;; pluspowfo2 = -1/2*(n+1), that is, the negative of 1/2
396 ;; plus the original exponent.
397 pluspowfo2
(* -
1 minuspowfo
))
398 (destructuring-bind (pos &optional neg
)
399 (powercoeflist polfact m x
)
400 (setf poszpowlist pos
)
401 (setf negpowlist neg
))
404 (format t
"n = ~A~%" n
)
405 (format t
"pluspowfo1 = ~A~%" pluspowfo1
)
406 (format t
"minuspowfo = ~A~%" minuspowfo
)
407 (format t
"pluspowfo2 = ~A~%" pluspowfo2
))
409 ;; I (rtoy) think powercoeflist computes p(x)/x^m as a Laurent
410 ;; series. POSZPOWLIST is a list of coefficients of the positive
411 ;; powers and NEGPOWLIST is a list of the negative coefficients.
412 (when (and (null negpowlist
)
413 (not (null poszpowlist
)))
414 ;; Only polynomial parts.
415 (when (eq signn
'$positive
)
416 (return (augmult (mul d
417 (nummnumn poszpowlist
419 minuspowfo c b a x
)))))
420 (return (augmult (mul d
421 (nummdenn poszpowlist
422 pluspowfo2 c b a x
)))))
423 (when (and (null poszpowlist
)
424 (not (null negpowlist
)))
425 ;; No polynomial parts
426 (when (eq signn
'$positive
)
427 (return (augmult (mul d
428 (denmnumn negpowlist minuspowfo c b a x
)))))
429 (return (augmult (mul d
430 (denmdenn negpowlist pluspowfo2 c b a x
)))))
431 (when (and (not (null negpowlist
))
432 (not (null poszpowlist
)))
433 ;; Positive and negative powers.
434 (when (eq signn
'$positive
)
435 (return (add (augmult (mul d
436 (nummnumn poszpowlist
438 minuspowfo c b a x
)))
441 minuspowfo c b a x
))))))
442 (return (add (augmult (mul d
443 (nummdenn poszpowlist
444 pluspowfo2 c b a x
)))
447 pluspowfo2 c b a x
))))))))
449 ;; Match d*p(x)*(f*x+e)^m*(a*x^2+b*x+c)^n. p(x) is a polynomial, m is
450 ;; an integer, n is half of an integer. a, b, c, e, and f are
451 ;; expressions independent of x (var).
452 (defun jmaug (exp var
)
454 ((coefftt) (d freevar
))
455 ((coefftt) (p polyp
))
456 ((mexpt) ((mplus) ((coeffpt) (f freevar
) (x varp
))
457 ((coeffpp)(e freevar
)))
460 ((coeffpt) (a freevar
) ((mexpt) (x varp
) 2))
461 ((coeffpt) (b freevar
) (x varp
))
462 ((coeffpp) (c freevar
)))
465 ;; Match d*p(x)*r1(x)^e1*r2(x)^e2*r0(x)^e0, where p(x) is a
466 ;; polynomial, e1 and e2 are both half an odd integer, and e3 is an
468 (defun factpow (exp var
)
469 (m2 exp
'((mtimes) ((coefftt) (d freevar
))
470 ((coefftt) (p polyp
))
476 (e0 maxima-integerp
)))))
478 ;; Match EXP to the form
479 ;; d*p/(e*x^2+f*x+g)*r0(x)^e0. p is a polynomial in x.
480 (defun elliptquad (exp var
)
482 ((coefftt) (d freevar
))
483 ((coefftt) (p polyp
))
484 ((mexpt) ((mplus) ((coeffpt) (e freevnz
) ((mexpt) (x varp
) 2))
485 ((coeffpt) (f freevar
) (x varp
))
486 ((coeffpp) (g freevar
)))
491 ;; From the set of coefficients, generate the polynomial c*x^2+b*x+a.
492 (defun polfoo (c b a x
)
497 ;; I think this is computing the list of coefficients of fun(x)/x^m,
498 ;; where fun(x) is a polynomial and m is a non-negative integer. The
499 ;; result is a list of two lists. The first list contains the
500 ;; polynomial part of fun(x)/x^m. The second is the principal part
501 ;; containing negative powers.
503 ;; Each of the lists is itself a list of power and coefficient itself.
505 ;; Thus (x+3)^2/x^2 = 1 + 6/x + 9/x^2 returns
507 ;; '(((0 1)) ((1 6) (2 9)))
508 (defun powercoeflist (fun m var
)
509 (prog ((expanfun (unquote ($expand
(mul (prevconstexpan fun var
) (power var m
)))))
510 maxpowfun powfun coef poszpowlist negpowlist
)
511 (when (and (equal fun
1) (plusp m
))
512 (return (cons nil
(list (list (cons m
(list 1)))))))
513 (when (and (equal fun
1) (minusp m
))
514 (return (cons nil
(list (list (cons (- m
) (list 1)))))))
515 (when (equal expanfun
1)
516 (return (cons (list (cons 0 (list 1))) (list nil
))))
517 (setq maxpowfun
($hipow expanfun var
)
518 powfun
($lopow expanfun var
))
519 loop
(setq coef
($coeff expanfun
(power var powfun
)))
520 (when (numberp coef
) (go testjump
))
522 testjump
(when (and (not (zerop powfun
)) (zerop coef
))
524 nojump
(when (plusp powfun
)
525 (setq poszpowlist
(append poszpowlist
526 (list (cons powfun
(list coef
))))))
530 (list (cons 0 (list (consterm (cdr expanfun
) var
)))))))
531 (when (minusp powfun
)
532 (setq negpowlist
(append negpowlist
(list (cons (- powfun
) (list coef
))))))
533 (when (= powfun maxpowfun
)
534 (return (list poszpowlist
(reverse negpowlist
))))
538 (defun consterm (fun var
)
540 ((freeof var
(car fun
))
541 (add (car fun
) (consterm (cdr fun
) var
)))
542 (t (consterm (cdr fun
) var
))))
544 (defun prevconstexpan (fun var
)
545 (cond ((atom fun
) fun
)
546 ((eq (caar fun
) 'mplus
)
547 (cond ((and (freeof var fun
)
548 (not (inside fun
'mexpt
)))
549 (list '(mquote) fun
))
550 ((and (freeof var fun
) (inside fun
'mexpt
))
552 (distrinplusprev (cdr fun
) var
)))
554 (distrinplusprev (cdr fun
) var
))
556 ((eq (caar fun
) 'mtimes
)
557 (distrintimesprev (cdr fun
) var
))
558 ((and (not (inside (cdr fun
) var
))
559 (eq (caar fun
) 'mexpt
))
560 (power (prevconstexpan (cadr fun
) var
) (caddr fun
)))
563 (defun distrinplusprev (fun var
)
565 (t (add (prevconstexpan (car fun
) var
)
566 (distrinplusprev (cdr fun
) var
)))))
568 (defun distrintimesprev (fun var
)
570 (t (mul (prevconstexpan (car fun
) var
)
571 (distrintimesprev (cdr fun
) var
)))))
573 (defun inside (fun arg
)
574 (cond ((atom fun
)(equal fun arg
))
575 ((inside (car fun
) arg
) t
)
576 (t (inside (cdr fun
) arg
))))
579 (cond ((not (inside fun
'mquote
)) fun
)
580 (t (unquote (meval fun
)))))
582 (defun checksigntm (expr)
583 (prog (aslist quest zerosigntest productcase
)
584 (setq aslist checkcoefsignlist
)
585 (cond ((atom expr
) (go loop
)))
586 (cond ((eq (caar expr
) 'mtimes
)(setq productcase t
)))
587 loop
(cond ((null aslist
)
588 (setq checkcoefsignlist
589 (append checkcoefsignlist
592 (setq quest
(checkflagandact expr
)))))))
594 (cond ((equal (caar aslist
) expr
) (return (cadar aslist
))))
595 (setq aslist
(cdr aslist
))
598 (defun checkflagandact (expr)
600 (setq productcase nil
)
601 (findsignoftheirproduct (findsignofactors (cdr expr
))))
602 (t (asksign ($realpart expr
)))))
604 (defun findsignofactors (listofactors)
605 (cond ((null listofactors
) nil
)
606 ((eq zerosigntest
'$zero
) '$zero
)
607 (t (append (list (setq zerosigntest
(checksigntm (car listofactors
))))
608 (findsignofactors (cdr listofactors
))))))
610 (defun findsignoftheirproduct (llist)
612 (cond ((eq llist
'$zero
) (return '$zero
)))
613 (setq sign
'$positive
)
614 loop
(cond ((null llist
) (return sign
)))
615 (cond ((eq (car llist
) '$positive
)
616 (setq llist
(cdr llist
))
618 (cond ((eq (car llist
) '$negative
)
619 (setq sign
(changesign sign
) llist
(cdr llist
))
623 (defun changesign (sign)
624 (if (eq sign
'$positive
)
628 ;; Integrate 1/sqrt(c*x^2+b*x+a).
630 ;; G&R 2.261 gives the following, where R = c*x^2+b*x+a and D =
634 ;; 1/sqrt(c)*log(2*sqrt(c*R)+2*c*x+b)
637 ;; 1/sqrt(c)*asinh((2*c*x+b)/sqrt(D))
640 ;; -1/sqrt(-c)*asin((2*c*x+b)/sqrt(-D))
643 ;; 1/sqrt(c)*log(2*c*x+b)
645 (defun den1 (c b a x
)
646 (let* ((expr (add (mul 2 c x
) b
)) ;; expr = 2*c*x+b
647 (signc (checksigntm (power c -
1)))
648 (signb (checksigntm (power b
2)))
649 (signdiscrim (signdis2 c b a signc signb
)))
650 (when (and (eq signc
'$positive
)
651 (eq signdiscrim
'$negative
))
653 (return-from den1
(augmult (mul* (power c -
1//2)
656 (power (add (mul 4 c a
)
659 (when (and (eq signc
'$positive
)
660 (eq signdiscrim
'$zero
))
662 (return-from den1
(augmult (mul* (power -
1 expr
)
665 (when (eq signc
'$positive
)
667 (return-from den1
(augmult (mul* (power c -
1//2)
671 (power (polfoo c b a x
) 1//2))
673 (when (and (eq signc
'$negative
)
674 (eq signdiscrim
'$positive
))
676 (return-from den1
(augmult (mul* -
1
677 (power (mul -
1 c
) -
1//2)
680 (power (add (mul b b
)
683 (when (eq signc
'$negative
)
684 ;; c < 0. We try again, but flip the sign of the
685 ;; polynomial, and multiply by -%i.
686 (return-from den1
(augmult (mul (power -
1 -
1//2)
692 ;; Compute sign of discriminant of the quadratic c*x^2+b*x+a. That
693 ;; is, the sign of b^2-4*c*a.
694 (defun signdiscr (c b a
)
695 (checksigntm (simplifya (add (power b
2) (mul -
4 c a
)) nil
)))
698 (checksigntm (inv a
)))
700 (defun signdis1 (c b a
)
701 (cond ((equal (mul b a
) 0)
702 (if (and (equal b
0) (equal a
0))
706 ;; Why are we checking the sign of (b^2-4*a*c)^2?
707 (checksigntm (power (add (mul b b
) (mul -
4 c a
)) 2)))))
709 ;; Check sign of discriminant of c*x^2+b*x+a, but also taking into
710 ;; account the sign of c and b.
711 (defun signdis2 (c b a signc signb
)
712 (cond ((equal signb
'$zero
)
713 (cond ((equal a
0) '$zero
)
714 (t (let ((askinv (askinver a
)))
715 (if (or (and (eq signc
'$positive
)
716 (eq askinv
'$negative
))
717 (and (eq signc
'$negative
)
718 (eq askinv
'$positive
)))
723 (signdiscr c b a
)))))
725 (defun signdis3 (c b a signa
)
726 (declare (special *ec-1
*))
728 (if (equal (checksigntm *ec-1
*) signa
)
731 (t (signdiscr c b a
))))
733 ;; Integrate things like x^m*R^(p-1/2), p > 0, m > 0.
735 ;; I think pluspowfo1 = p - 1.
736 (defun nummnumn (poszpowlist pluspowfo1 p c b a x
)
737 (declare (special *ec-1
*))
738 (let ((expr (power (polfoo c b a x
) (add p
1//2))) ;; expr = R^(p+1/2)
739 (expo *ec-1
*) ;; expo = 1/c
740 (ex (power c -
2))) ;; ex = 1/c^2
742 (controlpow (caar poszpowlist
))
743 (coef (cadar poszpowlist
))
744 count res1 res2 m partres
)
745 #+nil
(format t
"p = ~A~%pluspowfo1 = ~A~%" p pluspowfo1
)
746 (when (zerop controlpow
)
747 ;; Integrate R^(p-1/2)
748 (setq result
(augmult (mul coef
(numn pluspowfo1 c b a x
)))
753 ;; Handle x*R^(p-1/2)
757 ;; integrate(x*R^(2*p-1),x) =
758 ;; R^(p+1/2)/(2*p+1)/c
759 ;; - b/2/c*integrate(sqrt(R^(2*p-1)),x)
760 (setq res1
(add (augmult (mul expr expo
761 (power (+ p p
1) -
1)))
762 (augmult (mul -
1 b
1//2 expo
763 (numn pluspowfo1 c b a x
)))))
764 (when (equal controlpow
1)
765 (setq result
(add result
(augmult (mul coef res1
)))
770 ;; Handle x^2*R^(p-1/2)
774 ;; integrate(x^2*R^(2*p-1),x) =
775 ;; x*R^(p+1/2)/(2*p+2)/c
776 ;; - (2*p+3)*b/2/(2*p+2)/c*integrate(x*sqrt(R^(2*p-1)),x)
777 ;; - a/(2*p+2)/c*integrate(sqrt(R^(2*p-1)),x)
778 (setq res2
(add (augmult (mul* x expr expo
780 (augmult (mul* b
(+ p p
3)
787 (augmult (mul (inv (1+ p
))
790 (add (mul (power b
2)
793 (numn pluspowfo1 c b a x
)))))
794 (when (equal controlpow
2)
795 (setq result
(add result
(augmult (mul coef res2
)))
803 ;; The general case: x^m*R^(p-1/2)
805 (let ((pro (inv (+ m p p
))))
810 ;; integrate(x^m*R^(2*p-1),x) =
811 ;; x^(m-1)*R^(p+1/2)/(m+2*p)/c
812 ;; - (2*m+2*p-1)*b/2/(m+2*p)/c*integrate(x^(m-1)*sqrt(R^(2*p-1)),x)
813 ;; - (m-1)*a/(m+2*p)/c*integrate(x^(m-2)*sqrt(R^(2*p-1)),x)
814 (add (augmult (mul (power x
(1- m
))
816 (augmult (mul -
1 b
(+ p p m m -
1)
818 (augmult (mul -
1 a
(1- m
)
821 (when (> m controlpow
)
822 (setq result
(add result
(augmult (mul coef partres
))))
831 (setq poszpowlist
(cdr poszpowlist
))
832 (when (null poszpowlist
) (return result
))
833 (setq coef
(cadar poszpowlist
))
834 (setq controlpow
(caar poszpowlist
))
835 (when (equal count
4) (go jump4
))
836 (when (equal count
1) (go jump1
))
837 (when (equal count
2) (go jump2
))
840 ;; Integrate R^(p+1/2)
841 (defun numn (p c b a x
)
842 (declare (special *ec-1
*))
843 (let ((exp1 *ec-1
*) ;; exp1 = 1/c
844 (exp2 (add b
(mul 2 c x
))) ;; exp2 = b+2*c*x
845 (exp4 (add (mul 4 a c
) (mul -
1 b b
))) ;; exp4 = 4*a*c-b^2
846 (exp5 (div 1 (1+ p
)))) ;; exp5 = 1/(p+1)
848 ;; integrate(sqrt(R),x)
852 ;; integrate(sqrt(R),x) =
853 ;; (2*c*x+b)*sqrt(R)/4/c + del/8/c*integrate(1/sqrt(R),x)
856 (add (augmult (mul '((rat simp
) 1 4)
858 (power (polfoo c b a x
) 1//2)))
859 (augmult (mul '((rat simp
) 1 8)
867 ;; integrate(sqrt(R^(2*p+1)),x) =
868 ;; (2*c*x+b)/4/(p+1)/c*R^(p+1/2)
869 ;; + (2*p+1)*del/8/(p+1)/c*integrate(sqrt(R^(2*p-1)),x)
870 (add (augmult (mul '((rat simp
) 1 4)
872 (power (polfoo c b a x
) (add p
1//2))))
873 (augmult (mul '((rat simp
) 1 8)
876 (numn (1- p
) c b a x
)))))))
879 ($multthru
(simplifya x nil
)))
881 ;; Integrate things like 1/x^m/R^(p+1/2), p > 0.
882 (defun denmdenn (negpowlist p c b a x
)
883 (let ((exp1 (power (polfoo c b a x
) (add 1//2 (- p
))))) ;; exp1 = 1/R^(p-1/2)
884 (prog (result controlpow coef count res1 res2 m partres
885 (signa (checksigntm (simplifya a nil
)))
887 (when (eq signa
'$zero
)
888 (return (noconstquad negpowlist p c b x
)))
890 controlpow
(caar negpowlist
)
892 (setq coef
(cadar negpowlist
))
893 (when (zerop controlpow
)
894 ;; I'm not sure we ever get here because m = 0 is
895 ;; usually handled elsewhere.
896 (setq result
(augmult (mul coef
(denn p c b a x
)))
901 ;; Handle 1/x/R^(p+1/2)
902 (setq res1
(den1denn p c b a x
))
903 (when (equal controlpow
1)
904 (setq result
(add result
(augmult (mul coef res1
)))
909 ;; Handle 1/x^2/R^(p+1/2)
913 ;; integrate(1/x^2/R^(p+1/2),x) =
914 ;; -1/a/x/sqrt(R^(2*p-1))
915 ;; -(2*p+1)*b/2/a*integrate(1/x/sqrt(R^(2*p+1)),x)
916 ;; -2*p*c/a*integrate(1/sqrt(R^(2*p+1)),x)
917 (setq res2
(add (augmult (mul -
1 ea-1
(power x -
1) exp1
))
918 (augmult (mul -
1 b
(+ 1 p p
) 1//2
919 ea-1
(den1denn p c b a x
)))
920 (augmult (mul -
2 p c ea-1
(denn p c b a x
)))))
921 (when (equal controlpow
2)
922 (setq result
(add result
(augmult (mul coef res2
)))
931 ;; General case 1/x^m/R^(p+1/2)
935 ;; integrate(1/x^2/R^(p+1/2),x) =
936 ;; -1/(m-1)/a/x^(m-1)/sqrt(R^(2*p-1))
937 ;; -(2*p+2*m-3)*b/2/(m-1)/a*integrate(1/x^(m-1)/sqrt(R^(2*p+1)),x)
938 ;; -(2*n+m-2)*c/(m-1)/a*integrate(1/x^(m-2)/sqrt(R^(2*p+1)),x)
940 (let ((exp2 (div -
1 (1- m
))))
942 (add (augmult (mul exp2 ea-1
945 (augmult (mul b
(+ p p m m -
3) 1//2
947 (augmult (mul c ea-1 exp2
948 (+ p p m -
2) res1
)))))
950 (when (> m controlpow
)
951 (setq result
(add result
(augmult (mul coef partres
))))
955 (setq res1 res2 res2 partres
)
959 (setq negpowlist
(cdr negpowlist
))
960 (when (null negpowlist
) (return result
))
961 (setq coef
(cadar negpowlist
)
962 controlpow
(caar negpowlist
))
963 (when (equal count
4) (go jump4
))
964 (when (equal count
1) (go jump1
))
965 (when (equal count
2) (go jump2
))
968 ;; Integral of 1/(c*x^2+b*x+a)^(n), n > 0. p = n + 1/2.
970 ;; See G&R 2.263 formula 3.
972 ;; Let R = c*x^2+b*x+a.
973 (defun denn (p c b a x
)
974 (let ((signdisc (signdis1 c b a
))
975 (exp1 (add b
(mul 2 c x
))) ;; exp1 = b + 2*c*x;
976 (exp2 (add (mul 4 a c
) (mul b b -
1))) ;; exp2 = (4*a*c-b^2)
977 (exp3 (inv (+ p p -
1))) ;; exp3 = 1/(2*p-1)
979 (declare (special *ec-1
*))
980 #+nil
(format t
"signdisc = ~A~%p = ~A~%" signdisc p
)
981 (cond ((and (eq signdisc
'$zero
) (zerop p
))
982 ;; 1/sqrt(R), and R has duplicate roots. That is, we have
983 ;; 1/sqrt(c*(x+b/(2c))^2) = 1/sqrt(c)/sqrt((x+b/2/c)^2).
985 ;; We return 1/sqrt(c)*log(x+b/2/c). Shouldn't we return
986 ;; 1/c*log(|x+b/2/c|)?
987 (augmult (mul* (power *ec-1
* 1//2)
988 `((%log
) ,(add x
(mul b
1//2 *ec-1
*))))))
989 ((and (eq signdisc
'$zero
) (plusp p
))
990 ;; 1/sqrt(R^(2*p+1)), with duplicate roots.
992 ;; That is, 1/sqrt((c*(x+b/2/c)^(2)^(2*p+1))), or
993 ;; 1/c^(p+1/2)/(x+b/2/c)^(2*p+1). So the result is
994 ;; -1/2/p*c^(-p-1/2)/(x+b/2/c)^(2*p)
995 (augmult (mul (div -
1 (+ p p
))
996 (power c
(mul -
1//2 (+ p p
1)))
997 (power (add x
(mul b
1//2 *ec-1
*)) (* -
2 p
)))))
1004 ;; G&R 2.264 eq. 5 says
1006 ;; 2*(2*c*x+b)/del/sqrt(R).
1007 (augmult (mul 2 exp1
(inv exp2
)
1008 (power (polfoo c b a x
) -
1//2))))
1010 ;; The general case. G&R 2.263 eq. 3.
1012 ;; integrate(1/sqrt(R^(2*p+1)),x) =
1013 ;; 2*(2*c*x+b)/(2*p-1)/c/sqrt(R^(2*p-1))
1014 ;; + 8*(p-1)*c/(2*p-1)/del*integrate(1/sqrt(R^(2*p-1)),x)
1016 ;; where del = 4*a*c-b^2.
1017 (add (augmult (mul 2 exp1
1019 (power (polfoo c b a x
)
1021 (augmult (mul 8 c
(1- p
)
1023 (denn (1- p
) c b a x
))))))))
1025 ;; Integral of 1/x/(c*x^2+b*x+a)^(p+1/2), p > 0.
1026 (defun den1denn (p c b a x
)
1027 (let ((signa (checksigntm (power a
2))) ;; signa = sign of a^2
1028 (ea-1 (inv a
))) ;; ea-1 = 1/a
1029 (cond ((eq signa
'$zero
)
1030 ;; This is wrong because noconstquad expects a
1031 ;; powercoeflist for th first arg. But I don't think
1032 ;; there's any way to get here from anywhere. I'm pretty
1033 ;; sure den1denn is never called with a equal to 0.
1034 (noconstquad 1 p c b x
))
1036 ;; 1/x/sqrt(c*x^2+b*x+a)
1039 ;; The general case. See G&R 2.268:
1043 ;; integrate(1/x/sqrt(R^(2*p+1)),x) =
1045 ;; 1/(2*p-1)/a/sqrt(R^(2*p-1))
1046 ;; - b/2/a*integrate(1/sqrt(R^(2*p+1)),x)
1047 ;; + 1/a*integrate(1/x/sqrt(R^(2*p-1)),x)
1048 (add (augmult (mul (inv (+ p p -
1))
1050 (power (polfoo c b a x
)
1052 (augmult (mul ea-1
(den1denn (1- p
) c b a x
)))
1053 (augmult (mul -
1 1//2 ea-1 b
(denn p c b a x
))))))))
1055 ;; Integral of 1/x/sqrt(c*x^2+b*x+a).
1057 ;; G&R 2.266 gives the following results, where del is the
1058 ;; discriminant 4*a*c-b^2. (I think this is the opposite of what we
1059 ;; compute below for the discriminant.)
1061 (defun den1den1 (c b a x
)
1062 (let ((exp2 (add (mul b x
) a a
)) ; exp2 = b*x+2*a
1063 (exp3 (inv (simplify (list '(mabs) x
))))) ; exp3 = 1/abs(x)
1065 (condition (add (mul b x
) a a
))
1066 (signa (checksigntm (simplifya a nil
)))
1068 (when (eq signa
'$zero
)
1069 (return (noconstquad '((1 1)) 0 c b x
)))
1070 (setq signdiscrim
(signdis3 c b a signa
)
1071 exp1
(power a
(inv -
2)))
1072 #+nil
(format t
"signa = ~A~%signdiscrim = ~A~%" signa signdiscrim
)
1074 (when (and (eq signa
'$positive
)
1075 (eq signdiscrim
'$negative
))
1076 ;; G&R case a > 0, del > 0
1078 ;; -1/sqrt(a)*asinh((2*a+b*x)/x/sqrt(del)
1079 (return (mul* -
1 exp1
1081 ,(augmult (mul exp2 exp3
1082 (power (add (mul 4 a c
)
1085 (when (and (eq signdiscrim
'$zero
)
1086 (eq signa
'$positive
))
1087 ;; G&R case del = 0, a > 0
1089 ;; 1/sqrt(a)*log(x/(2*a+b*x))
1090 (return (mul* (power -
1 condition
)
1092 `((%log
) ,(augmult (mul exp3 exp2
))))))
1093 (when (eq signa
'$positive
)
1096 ;; -1/sqrt(a)*log((2*a+b*x+2*sqrt(a*R))/x)
1099 (return (mul* -
1 exp1
1101 ,(add b
(mul 2 a exp3
)
1104 (power (polfoo c b a x
) 1//2)))))))
1105 (when (and (eq signa
'$negative
)
1106 (eq signdiscrim
'$positive
))
1107 ;; G&R case a < 0, del < 0
1109 ;; 1/sqrt(-a)*asin((2*a+b*x)/x/sqrt(b^2-4*a*c))
1110 (return (mul* (power (mul -
1 a
) -
1//2)
1112 ,(augmult (mul exp2 exp3
1113 (power (add (mul b b
) (mul -
4 a c
)) -
1//2)))))))
1114 ;; I think this is the case of a < 0. We flip the sign of
1115 ;; coefficients of the quadratic to make a positive, and
1116 ;; multiply the result by 1/%i.
1118 ;; Why can't we use the case a < 0 in G&R 2.266:
1120 ;; 1/sqrt(-a)*atan((2*a+b*x)/2/sqrt(-a)/sqrt(R)
1122 ;; FIXME: Why the multiplication by -1?
1123 (return (mul #+nil -
1
1125 (den1den1 (mul -
1 c
) (mul -
1 b
) (mul -
1 a
) x
))))))
1127 ;; Integral of d/x^m/(c*x^2+b*x)^(p+1/2), p > 0. The values of m and
1128 ;; d are in NEGPOWLIST.
1129 (defun noconstquad (negpowlist p c b x
)
1130 (let ((exp1 (inv (+ p p
1))) ;; exp1 = 1/(2*p+1)
1131 (exp2 (inv x
)) ;; exp2 = 1/x
1132 (exp3 (- p
))) ;; exp3 = -p
1133 (prog (result controlpow coef count res1 signb m partres eb-1
)
1134 (setq signb
(checksigntm (power b
2)))
1135 (when (eq signb
'$zero
)
1136 (return (trivial1 negpowlist p c x
)))
1138 controlpow
(caar negpowlist
)
1139 coef
(cadar negpowlist
)
1141 (when (zerop controlpow
)
1142 ;; Not sure if we ever actually get here. The case of
1143 ;; m=0 is usually handled at a higher level.
1144 (setq result
(augmult (mul coef
(denn p c b
0 x
)))
1148 ;; Handle 1/x/R^(p+1/2)
1150 ;; G&R 2.268, a = 0, m = 1
1152 ;; integrate(1/x^m/sqrt(R^(2*p+1)),x) =
1153 ;; -2/(2*p+1)/b/x/sqrt(R^(2*p-1))
1154 ;; -4*p*c/(2*p+1)/b*integrate(1/sqrt(R^(2*p+1)),x)
1155 (setq res1
(add (augmult (mul -
2 exp1 eb-1 exp2
1156 (power (polfoo c b
0 x
)
1158 (augmult (mul -
4 p c exp1 eb-1
(denn p c b
0 x
)))))
1159 (when (equal controlpow
1)
1160 (setq result
(add result
(augmult (mul coef res1
)))
1163 jump2
(setq count
3 m
2)
1165 ;; Handle general case 1/x^m/R^(p+1/2)
1169 ;; integrate(1/x^m/sqrt(R^(2*p+1)),x) =
1170 ;; -2/(2*p+2*m-1)/b/x^m/sqrt(R^(2*p+1))
1171 ;; -(4*p+2*m-2)*c/(2*p+2*m-1)/b*integrate(1/x^(m-1)/sqrt(R^(2*p+1)),x)
1173 (add (augmult (mul -
2 (inv (+ p p m m -
1))
1175 (power x
(mul -
1 m
))
1176 (power (polfoo c b
0 x
)
1178 (augmult (mul -
2 c
(+ p p m -
1)
1180 (inv (+ p p m m -
1))
1183 (when (> m controlpow
)
1184 (setq result
(add result
(augmult (mul coef partres
))))
1190 (setq negpowlist
(cdr negpowlist
))
1191 (when (null negpowlist
) (return result
))
1192 (setq coef
(cadar negpowlist
)
1193 controlpow
(caar negpowlist
))
1194 (when (= count
3) (go jump3
))
1195 (when (= count
1) (go jump1
))
1198 ;; The trivial case of d/x^m/(c*x^2+b*x+a)^(p+1/2), p > 0, and a=b=0.
1199 (defun trivial1 (negpowlist p c x
)
1200 (cond ((null negpowlist
) 0)
1202 ;; d/x^m/c^(p+1/2)/x^(2*p+1) = d/c^(p+1/2)/x^(m+2*p+1)
1203 ;; The integral is obviously
1205 ;; -d/c^(p+1/2)/x^(m+2*p)/(m+2*p)
1206 (add (augmult (mul (power x
1208 (mul -
1 (caar negpowlist
))))
1210 (power c
(add (- p
) -
1//2))
1212 (mul -
1 (caar negpowlist
))))))
1213 (trivial1 (cdr negpowlist
) p c x
)))))
1215 ;; Integrate pl(x)/(c*x^2+b*x+a)^(p+1/2) where pl(x) is a polynomial
1216 ;; and p > 0. The polynomial is given in POSZPOWLIST.
1217 (defun nummdenn (poszpowlist p c b a x
)
1218 (declare (special *ec-1
*))
1219 (let ((exp1 (inv (+ p p -
1))) ;; exp1 = 1/(2*p-1)
1220 (exp2 (power (polfoo c b a x
) (add 1//2 (- p
)))) ;; exp2 = (a*x^2+b*x+c)^(p-1/2)
1221 (exp3 (add (mul 4 a c
) (mul -
1 b b
))) ;; exp3 = (4*a*c-b^2) (negative of the discriminant)
1222 (exp4 (add x
(mul b
1//2 *ec-1
*))) ;; exp4 = x+b/2/c
1223 (exp5 (power c -
2)) ;; exp5 = 1/c^2
1224 (exp6 (+ 2 (* -
2 p
))) ;; exp6 = -2*p+2
1225 (exp7 (1+ (* -
2 p
)))) ;; exp7 = -2*p+1
1226 (prog (result controlpow coef count res1 res2 m partres signdiscrim
)
1229 ;; We are trying to integrate pl(x)/S
1230 ;; = (p0 + p1*x + p2*x^3 + ...)/S
1232 ;; So the general term is pm*x^m/S. This integral is given by
1235 ;; integrate(x^m/sqrt(R^(2*p+1)),x) =
1237 ;; x^(m-1)/(m-2*n)/sqrt(R^(2*p-1))
1238 ;; - (2*m-2*n-1)*b/2/(m-2*n)/c*integrate(x^(m-1)/sqrt(R^(2*p+1)),x)
1239 ;; - (m-1)*a/(m-2*n)/c*integrate(x^(m-2)/sqrt(R^(2*p+1)),x)
1241 ;; Thus the integration of x^m/S involves x^(m-1)/S and x^(m-2)/S.
1243 ;; I think what this loop does is integrate x^(m-1)/S and
1244 ;; x^(m-2)/S, and remember them so that we can integrate x^m/S
1245 ;; without having to do all the integrals again. Thus we
1246 ;; start with the constant term and work our way up to the
1249 ;; I think this would be much simpler if we used memoization
1250 ;; and start with the highest power. Then all the
1251 ;; intermediate forms will have been computed, and we can just
1252 ;; simply integrate all the lower terms by looking them up.
1254 controlpow
(caar poszpowlist
))
1255 (setq coef
(cadar poszpowlist
)
1256 signdiscrim
(signdis1 c b a
))
1257 ;; We're looking at coef*x^controlpow/R^(p+1/2) right now.
1258 (when (zerop controlpow
)
1259 ;; Actually it's coef/R^(p+1/2), so handle that now, go
1260 ;; to the next coefficient.
1261 (setq result
(augmult (mul coef
(denn p c b a x
)))
1267 ;; This handles the case coef*x/R^(p+1/2)
1269 ;; res1 = -1/c/(2*p-1)*R^(p-1/2)
1270 ;; -b/2/c*integrate(R^(p+1/2),x)
1273 (add (augmult (mul -
1 *ec-1
* exp1 exp2
))
1274 (augmult (mul b -
1//2 *ec-1
* (denn p c b a x
)))))
1275 (when (= controlpow
1)
1276 ;; Integrate coef*x/R^(p+1/2).
1278 ;; x/R^(p+1/2) is in res1.
1279 (setq result
(add result
(augmult (mul coef res1
)))
1283 ;; This handles the case coef*x^2/R^(p+1/2)
1284 (when (and (plusp p
) (not (eq signdiscrim
'$zero
)))
1285 ;; p > 0, no repeated roots
1287 (add (augmult (mul *ec-1
* exp1
(inv exp3
) exp2
1291 (augmult (mul *ec-1
* (inv exp3
) exp1
1297 (when (and (zerop p
) (not (eq signdiscrim
'$zero
)))
1298 ;; x^2/sqrt(R), no repeated roots.
1302 ;; integrate(x^2/sqrt(R),x) =
1303 ;; (x/2/c-3*b/4/c^2)*sqrt(R)
1304 ;; + (3*b^2/8/c^2-a/2/c)*integrate(1/sqrt(R),x)
1306 ;; = (2*c*x-3*b)/4/c^2*sqrt(R)
1307 ;; + (3*b^2-4*a*c)/8/c^2*integrate(1/sqrt(R),x)
1309 (add (augmult (mul '((rat simp
) 1 4)
1313 (power (polfoo c b a x
)
1315 (augmult (mul '((rat simp
) 1 8)
1320 (when (and (zerop p
) (eq signdiscrim
'$zero
))
1321 ;; x^2/sqrt(R), repeated roots
1323 ;; With repeated roots, R is really of the form
1324 ;; c*x^2+b*x+b^2/4/c = c*(x+b/2/c)^2. So we have
1326 ;; x^2/sqrt(c)/(x+b/2/c)
1328 ;; And the integral of this is
1330 ;; b^2*log(x+b/2/c)/4/c^(5/2) + x^2/2/sqrt(c) - b*x/2/c^(3/2).
1333 ;; (add (augmult (mul* b b (list '(rat) 1 4)
1335 ;; (list '(%log) exp4)))
1336 ;; (augmult (mul *ec-1* 1//2 (power exp4 2)))
1337 ;; (augmult (mul -1 b x exp5)))
1338 (add (augmult (mul* b b
'((rat) 1 4)
1339 (power c
(div -
5 2))
1341 (augmult (mul (power c -
1//2) 1//2 (power x
2)))
1342 (augmult (mul -
1//2 b x
(power c
(div -
3 2)))))))
1344 (when (and (= p
1) (eq signdiscrim
'$zero
))
1345 ;; x^2/sqrt(R^3), repeated roots
1347 ;; As above, we have c*(x+b/2/c)^2, so
1349 ;; x^2/sqrt(R^3) = x^2/sqrt(c^3)/(x+b/2/c)^3
1351 ;; And the integral is
1353 ;; log(x+b/2/c)/c^(3/2) + z*(3*z+4*x)/2/c^(3/2)/(z+x)^2
1357 ;; (add (augmult (mul* *ec-1* (list '(%log) exp4)))
1358 ;; (augmult (mul b exp5 (power exp4 -1)))
1359 ;; (augmult (mul (list '(rat) -1 8)
1361 ;; b b (power exp4 -2))))
1362 (add (augmult (mul* (power c
(div -
3 2)) `((%log
) ,exp4
)))
1363 (augmult (mul b x
(power c
(div -
5 2)) (power exp4 -
2)))
1364 (augmult (mul (div 3 8)
1365 (power c
(div -
7 2))
1366 b b
(power exp4 -
2))))))
1368 (when (and (eq signdiscrim
'$zero
) (> p
1))
1369 ;; x^2/R^(p+1/2), repeated roots, p > 1
1371 ;; As above, we have R=c*(x+b/2/c)^2, so the integral is
1373 ;; x^2/(x+b/2/c)^(2*p+1)/c^(p+1/2).
1375 ;; Let d = b/2/c. Then write x^2 =
1376 ;; (x+d)^2-2*d*(x+d)+d^2. The integrand becomes
1378 ;; 1/(x+d)^(2*p-1) - 2*d/(x+d)^(2*p) + d^2/(x+d)^(2*p+1)
1380 ;; whose integral is
1382 ;; 1/(2*p-2)/(x+d)^(2*p-2) - 2*d/(2*p-1)/(x+d)^(2*p-1)
1383 ;; + d^2/(2*p)/(x+d)^(2*p)
1385 ;; And don't forget the factor c^(-p-1/2). Finally,
1387 ;; 1/c^(p+1/2)/(2*p-2)/(x+d)^(2*p-2)
1388 ;; - b/c^(p+3/2)/(2*p-1)/(x+d)^(2*p-1)
1389 ;; + b^2/8/c^(p+5/2)/p/(x+d)^(2*p)
1391 ;; (add (augmult (mul *ec-1*
1392 ;; (power exp4 exp6)
1394 ;; (augmult (mul -1 b exp5 (inv exp7)
1395 ;; (power exp4 exp7)))
1396 ;; (augmult (mul b b (list '(rat) -1 8)
1401 (add (augmult (mul (inv (power c
(add p
1//2)))
1405 (inv (power c
(add p
(div 3 2))))
1408 (augmult (mul b b
'((rat simp
) -
1 8)
1409 (inv (power c
(add p
(div 5 2))))
1413 (when (= controlpow
2)
1416 ;; We computed this result above, so just multiply by
1417 ;; the coefficient and add it to the result.
1418 (setq result
(add result
(augmult (mul coef res2
)))
1425 ;; coef*x^m/R^(p+1/2). m >= 3
1427 (let ((denom (+ p p
(- m
))))
1432 ;; integrate(x^m/sqrt(R^(2*p+1)),x) =
1433 ;; x^(m-1)/c/(m-2*p)/sqrt(R^(2*p-1))
1434 ;; - b*(2*m-2*p-1)/2/(m-2*p)*integrate(x^(m-1)/sqrt(R^(2*p+1)),x)
1435 ;; + (m-1)*a/(m-2*p)/c*integrate(x^(m-2)/sqrt(R^(2*p+1)),x)
1437 ;; The two integrals here were computed above in res2
1438 ;; and res1, respectively.
1439 (add (augmult (mul* (power x
(1- m
))
1440 *ec-1
* (div -
1 denom
)
1441 (power (polfoo c b a x
)
1443 (augmult (mul b
(+ p p
1 (* -
2 m
))
1445 *ec-1
* (inv denom
) res2
))
1446 (augmult (mul a
(1- m
) *ec-1
* (inv denom
) res1
)))))
1448 ;; Move on to next higher power
1450 (when (> m controlpow
)
1451 (setq result
(add result
(augmult (mul coef partres
))))
1458 (let ((expr (nummdenn (list (list (1- m
) 1)) p c b a x
)))
1460 (mul -
1 (distrint (cdr ($expand expr
)) x
)))))
1464 ;; Done with first term of polynomial. Exit if we're done.
1465 (setq poszpowlist
(cdr poszpowlist
))
1466 (when (null poszpowlist
) (return result
))
1467 (setq coef
(cadar poszpowlist
) controlpow
(caar poszpowlist
))
1468 (when (= count
4) (go jump4
))
1469 (when (= count
1) (go jump1
))
1470 (when (= count
2) (go jump2
))
1473 ;; Integrate functions of the form coef*R^(pow-1/2)/x^m. NEGPOWLIST
1474 ;; contains the list of coef's and m's.
1475 (defun denmnumn (negpowlist pow c b a x
)
1476 (let ((exp1 (inv x
)) ;; exp1 = 1/x
1477 (exp2 (+ pow pow -
1))) ;; exp2 = 2*pow-1
1478 (prog (result controlpow coef count res1 res2 m partres signa ea-1
1479 (p (+ pow pow -
1))) ;; p = 2*pow-1.
1480 ;; NOTE: p is not the same here as in other routines!
1481 ;; Why is there this special case for negpowlist?
1482 ;; CASE1 calls this in this way.
1483 (when (eq (car negpowlist
) 't
)
1484 (setq negpowlist
(cdr negpowlist
))
1486 (setq signa
(checksigntm (power a
2)))
1487 (when (eq signa
'$zero
)
1488 (return (nonconstquadenum negpowlist p c b x
)))
1492 controlpow
(caar negpowlist
)
1493 coef
(cadar negpowlist
))
1494 (when (zerop controlpow
)
1495 ;; integrate(sqrt(R)).
1496 ;; I don't think we can normally get here.
1497 (setq result
(augmult (mul coef
1498 (numn (add (mul p
1//2) 1//2)
1503 ;; Handle integrate(sqrt(R^(2*pow-1))/x),x
1504 (setq res1
(den1numn pow c b a x
))
1505 (when (equal controlpow
1)
1506 (setq result
(add result
(augmult (mul coef res1
)))
1510 ;; Handle integrate(sqrt(R^(2*pow-1))/x^2,x)
1512 ;; integrate(sqrt(R^(2*pow-1))/x^2,x)
1514 ;; We can use integration by parts to get
1516 ;; integrate(sqrt(R^(2*pow-1))/x^2,x) =
1518 ;; + (2*pow-1)*b/2*integrate(sqrt(R^(2*pow-3))/x,x)
1519 ;; + (2*pow-1)*c*integrate(sqrt(R^(2*pow-3)),x)
1521 (add (augmult (mul -
1 exp1
1522 (power (polfoo c b a x
)
1524 (augmult (mul b
(div exp2
2)
1525 (den1numn (1- pow
) c b a x
)))
1526 (augmult (mul c exp2
(numn (- pow
2) c b a x
))))))
1528 ;; integrate(sqrt(R)/x^2,x)
1532 ;; integrate(sqrt(R)/x^2,x) =
1534 ;; + b/2*integrate(1/x/sqrt(R),x)
1535 ;; + c*integrate(1/sqrt(R),x)
1537 (setq res2
(add (augmult (mul -
1 (power (polfoo c b a x
) 1//2)
1539 (augmult (mul b
1//2 (den1den1 c b a x
)))
1540 (augmult (mul c
(den1 c b a x
))))))
1541 (when (equal controlpow
2)
1542 (setq result
(add result
(augmult (mul coef res2
)))
1549 ;; The general case sqrt(R^(2*p-1))/x^m
1553 ;; integrate(sqrt(R^(2*p-1))/x^m,x) =
1554 ;; -sqrt(R^(2*p+1))/(m-1)/a/x^(m-1)
1555 ;; + (2*p-2*m+3)*b/2/(m-1)/a*integrate(sqrt(R^(2*p-3))/x^(m-1),x)
1556 ;; + (2*p-m+2)*c/(m-1)/a*integrate(sqrt(R^(2*n-3))/x^(m-2),x)
1558 ;; NOTE: The p here is 2*pow-1. And we're
1559 ;; integrating R^(pow-1/2).
1562 (add (augmult (mul (div -
1 (1- m
))
1564 (power x
(1+ (- m
)))
1565 (power (polfoo c b a x
)
1566 (add (div p
2) 1))))
1567 (augmult (mul (inv (+ m m -
2))
1571 (augmult (mul c ea-1
1573 (inv (1- m
)) res1
))))
1575 (when (> m controlpow
)
1576 (setq result
(add result
(augmult (mul coef partres
))))
1583 (setq negpowlist
(cdr negpowlist
))
1584 (when (null negpowlist
) (return result
))
1585 (setq coef
(cadar negpowlist
)
1586 controlpow
(caar negpowlist
))
1595 ;; Like denmnumn, but a = 0.
1596 (defun nonconstquadenum (negpowlist p c b x
)
1597 (prog (result coef m
)
1599 (return (case1 negpowlist c b x
))))
1602 (setq m
(caar negpowlist
)
1603 coef
(cadar negpowlist
))
1604 (setq result
(add result
(augmult (mul coef
(casegen m p c b x
))))
1605 negpowlist
(cdr negpowlist
))
1606 (cond ((null negpowlist
) (return result
)))
1609 ;; Integrate (c*x^2+b*x)^(p-1/2)/x^m
1610 (defun casegen (m p c b x
)
1611 (let ((exp1 (power (polfoo c b
0 x
) (div p
2))) ;; exp1 = R^(p/2)
1612 (exp3 (power x
(1+ (- m
))))) ;; exp3 = 1/x^(m-1)
1614 ;; sqrt(c*x^2+b*x)/x^m
1615 (case1 (list (list m
1)) c b x
))
1617 ;; (c*x^2+b*x)^(p-1/2)
1620 ;; (c*x^2+b*x)^(p-1/2)/x^(p+1)
1621 (add (augmult (mul -
1 exp1
(inv (1- m
)) exp3
))
1622 (augmult (mul b
1//2 (casegen (1- m
) (- p
2) c b x
)))
1623 (augmult (mul c
(casegen (- m
2) (- p
2) c b x
)))))
1625 ;; (c*x^2+b*x)^(p-1/2)/x
1627 (add (augmult (mul (inv p
) exp1
))
1628 (augmult (mul b
1//2 (case0 (- p
2) c b x
)))))
1630 ;; (c*x^2+b*x)^(p-1/2)/x^m
1631 (add (augmult (mul -
1 exp1
(inv (- m
(1+ p
))) exp3
))
1632 (augmult (mul -
1 p b
1//2 (inv (- m
(1+ p
)))
1633 (casegen (1- m
) (- p
2) c b x
))))))))
1635 ;; Integrate things like sqrt(c*x^2+b*x))/x^m.
1636 (defun case1 (negpowlist c b x
)
1637 (declare (special *ec-1
*))
1638 (let ((exp1 (power c -
1//2)) ;; exp1 = 1/sqrt(c)
1639 (eb-1 (inv b
))) ;; eb-1 = 1/b
1640 (prog ((result 0) (controlpow (caar negpowlist
)) (coef (cadar negpowlist
))
1641 m1 count res1 res2 m signc signb partres res
)
1642 (setq m1
(- controlpow
2))
1643 (when (zerop controlpow
)
1644 (setq result
(augmult (mul coef
(case0 1 c b x
)))
1649 (when (= controlpow
1)
1652 (augmult (mul coef
(den1numn 1 c b
0 x
))))
1657 (when (= controlpow
2)
1661 (denmnumn '(t (2 1)) 1 c b
0 x
))))
1665 (setq signb
(checksigntm (power b
2)))
1666 (when (eq signb
'$zero
)
1671 signc
(checksigntm *ec-1
*))
1672 (when (eq signc
'$positive
)
1674 (augmult (mul* 2 exp1
1676 ,(add (power (mul c x
) 1//2)
1677 (power (add b
(mul c x
)) 1//2))))))
1680 (augmult (mul* 2 exp1
1683 (inv (add b
(mul -
1 c x
))))
1687 (setq res
(add (augmult (mul -
2 (power (polfoo c b
0 x
) 1//2)
1688 eb-1
(inv (+ m m -
1))
1690 (augmult (mul (div -
2 (+ m m -
1))
1691 c
(1- m
) eb-1 res
))))
1699 partres
(add (augmult (mul -
1
1700 (power (polfoo c b
0 x
) 1//2)
1703 (augmult (mul b
1//2 (r1m m
) res1
))
1704 (augmult (mul c
(r1m m
) res2
))))
1710 (setq partres
(mul* exp1
`((%log
) ,x
)))
1712 (setq partres
(mul -
1 exp1
(power x
(- m
)) (r1m m
)))
1714 (setq result
(add result
(augmult (mul coef partres
))))
1716 (setq negpowlist
(cdr negpowlist
))
1717 (when (null negpowlist
) (return result
))
1718 (setq coef
(cadar negpowlist
)
1719 controlpow
(caar negpowlist
))
1720 (when (= count
5) (go jump5
))
1721 (when (= count
1) (go jump1
))
1722 (when (= count
2) (go jump2
))
1723 (when (= count
3) (go jump3
))
1724 (setq m1
(- controlpow
2))
1732 ;; Integrate (c*x^2+b*x)^(p-1/2)
1733 (defun case0 (power c b x
)
1734 (let ((exp1 '((rat simp
) 1 4))
1735 (exp2 (add b
(mul 2 c x
)))
1736 (exp3 (power c
'((rat simp
) -
3 2)))
1737 (exp4 (add (mul 2 c x
) (mul -
1 b
))))
1742 (declare (special *ec-1
*))
1743 (prog (signc p result
)
1744 (setq signc
(checksigntm *ec-1
*)
1748 ;; This could be handled by numn. Why don't we?
1749 (when (eq signc
'$positive
)
1751 (add (augmult (mul exp1
*ec-1
* exp2
1752 (power (polfoo c b
0 x
) 1//2)))
1753 (augmult (mul* b b
'((rat) -
1 8)
1759 (power (polfoo c b
0 x
) 1//2)))))))))
1760 (when (eq signc
'$negative
)
1762 (add (augmult (mul exp1
*ec-1
* exp4
1763 (power (polfoo (mul -
1 c
) b
0 x
) 1//2)))
1764 (augmult (mul* b b
'((rat) 1 8)
1766 `((%asin
) ,(mul (inv b
) exp4
)))))))
1768 (when (equal power p
) (return result
))
1771 ;; integrate(sqrt(R^(2*n+1)),x) =
1772 ;; (2*c*x+b)/4/(n+1)/c*sqrt(R^(2*n+1))
1773 ;; + (2*n+1)*del/8/(n+1)/c*integrate(sqrt(R^(2*n-1)),x)
1775 (setq result
(add (augmult (mul 1//2 *ec-1
* (inv (1+ p
)) exp2
1776 (power (polfoo c b
0 x
)
1778 (augmult (mul p b b
'((rat simp
) -
1 4)
1779 *ec-1
* (inv (1+ p
)) result
))))
1782 ;; Integrate R^(p-1/2)/x, p >= 1.
1783 (defun den1numn (p c b a x
)
1785 ;; integrate(sqrt(R)/x,x)
1789 ;; integrate(sqrt(R)/x,x) =
1791 ;; + a*integrate(1/x/sqrt(R),x)
1792 ;; + b/2*integrate(1/sqrt(R),x)
1793 (add (power (polfoo c b a x
) 1//2)
1794 (augmult (mul a
(den1den1 c b a x
)))
1795 (augmult (mul b
1//2 (den1 c b a x
)))))
1801 ;; integrate(sqrt(R^(2*p-1)/x,x) =
1802 ;; R^(p-1/2)/(2*p-1)
1803 ;; + b/2*integrate(sqrt(R^(2*p-3)),x)
1804 ;; + a*integrate(sqrt(2^(2*p-3))/x,x)
1805 (add (augmult (mul (power (polfoo c b a x
)
1808 (augmult (mul a
(den1numn (+ p -
1) c b a x
)))
1809 (augmult (mul b
1//2 (numn (+ p -
2) c b a x
)))))))
1811 ;; L is a list of expressions that INTIRA should be applied to.
1812 ;; Sum up the results of applying INTIRA to each.
1813 (defun distrint (l x
)
1814 (addn (mapcar #'(lambda (e)
1815 (let ((ie (intira e x
)))
1818 `((%integrate simp
) ,e
,x
))))