Fix some issues with make dist-gzip
[maxima.git] / src / irinte.lisp
blob27eba22a6a6890d62b18a3deff24e9ff1b8dfc4a
1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancements. ;;;;;
4 ;;; ;;;;;
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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11 (in-package :maxima)
13 (macsyma-module irinte)
15 (load-macsyma-macros rzmac)
17 (defun zerp (a) (equal a 0))
19 (defun integerpfr (a) (if (not (maxima-integerp a)) (integerp1 a)))
21 (defun nonzerp (a) (not (equal a 0)))
23 (defun hasvar2 (exp var2)
24 (not (freevar2 exp var2)))
26 (defun freevnz2 (a var2)
27 (and (freevar2 a var2)
28 (not (equal a 0))))
31 (defun inte (funct x)
32 (let ((*checkcoefsignlist* nil)
33 (*globalcareflag* nil)
34 ($radexpand t))
35 ;; It would be nice to remove *GLOBALCAREFLAG*, which is only used
36 ;; here, INTIRFACTOROOT, and CAREFULFACTOR. But to do that, we'd
37 ;; have to pass the value of *GLOBALCAREFACTOR* through many
38 ;; functions because CAREFULFACTOR is near or at the bottom of the
39 ;; call tree.
40 (declare (special *globalcareflag*))
41 (intir-ref funct x)))
43 (defun intir-ref (fun x)
44 (prog (a)
45 (when (setq a (intir1 fun x)) (return a))
46 (when (setq a (intir2 fun x)) (return a))
47 (return (intir3 fun x))))
49 (defun intir1 (fun x)
50 (prog (assoclist e0 r0 e1 e2 r1 r2 d p)
51 (setq assoclist (factpow (specrepcheck fun) x))
52 (setq e1 (cdras 'e1 assoclist)
53 e2 (cdras 'e2 assoclist))
54 (cond ((null assoclist)(return nil)))
55 (setq d (cdras 'd assoclist)
56 p (cdras 'p assoclist)
57 e0 (cdras 'e0 assoclist)
58 r0 (cdras 'r0 assoclist)
59 r1 (cdras 'r1 assoclist)
60 r2 (cdras 'r2 assoclist))
61 (cond ((floatp e0)
62 (setq e0 (rdis (ration1 e0)))))
63 (cond ((floatp e1)
64 (setq e1 (rdis (ration1 e1)))))
65 (cond ((floatp e2)
66 (setq e2 (rdis (ration1 e2)))))
67 (return (intir1-ref d p r0 e0 r1 e1 r2 e2 x))))
69 (defun intir2 (funct x)
70 (let ((res (intir funct x)))
71 (if res
72 res
73 (intirfactoroot funct x))))
75 (defun intir3 (exp x)
76 (prog ((assoclist (elliptquad exp x)) e f g r0)
77 (cond (assoclist
78 (setq e (cdras 'e assoclist) f (cdras 'f assoclist)
79 g (cdras 'g assoclist) r0 (cdras 'r0 assoclist))
80 (assume `(($notequal) ,e 0))
81 (return (intir3-r0test assoclist x e f g r0))))
82 (return nil)))
84 (defun intir3-r0test (assoclist x e f g r0)
85 (if (root+anything r0 x)
86 nil
87 (intir3-ref assoclist x e f g r0)))
89 ;; Handle integrals of the form d*p(x)*r1(x)^e1*r2(x)^e2*r0(x)^e0,
90 ;; where p(x) is a polynomial, e1 and e2 are both half an odd integer,
91 ;; and e3 is an integer.
92 (defun intir1-ref (d p r0 e0 r1 e1 r2 e2 x)
93 (let ((nume1 (cadr e1)) ;; nume1 = 2*e1
94 (nume2 (cadr e2))) ;; nume2 = 2*e2
95 ;; I think what this does is try to rationalize r1(x)^e1 or
96 ;; r2(x)^e2 so we end up with a new integrand of the form
97 ;; d*p'(x)*r0'(x)^e0*ra(x)^ea, where p'(x) is a new polynomial
98 ;; obtained from rationaling one term and r0'(x) is a more
99 ;; complicated term.
100 (cond ((and (plusp nume1) (plusp nume2))
101 (pp-intir1 d p r0 e0 r1 e1 r2 e2 x))
102 ((and (minusp nume1) (minusp nume2))
103 (mm-intir1 d p r0 e0 r1 e1 r2 e2 x))
104 ((plusp nume1)
105 (pm-intir1 d p r0 e0 r1 e1 r2 e2 x))
107 (pm-intir1 d p r0 e0 r2 e2 r1 e1 x)))))
109 (defun pp-intir1 (d p r0 e0 r1 e1 r2 e2 x)
110 (if (> (cadr e1) (cadr e2))
111 (pp-intir1-exec d p r0 e0 r1 e1 r2 e2 x)
112 (pp-intir1-exec d p r0 e0 r2 e2 r1 e1 x)))
114 ;; Handle integrals of the form d*p(x)*r0(x)^e0*r1(x)^e1*r2(x)^e2
115 ;; where p(x) is a polynomial, e1 < 0, and e2 < 0 and are both half an
116 ;; odd integer, and e3 is an integer.
117 (defun mm-intir1 (d p r0 e0 r1 e1 r2 e2 x)
118 (if (> (cadr e1) (cadr e2))
119 (mm-intir1-exec d p r0 e0 r1 e1 r2 e2 x)
120 (mm-intir1-exec d p r0 e0 r2 e2 r1 e1 x)))
122 ;; Handle integrals of the form d*p(x)*r0(x)^e0*r1(x)^e1*r2(x)^e2
123 ;; where p(x) is a polynomial, e1 > 0, and e2 < 0 and are both half an
124 ;; odd integer, and e3 is an integer.
126 (defun pm-intir1 (d p r0 e0 rofpos epos rofneg eneg x)
127 (let ((numepos (cadr epos)) ;; numepos = 2*epos = 2*e1
128 (numul-1eneg (mul -1 (cadr eneg)))) ;; numul-1eneg = -2*eneg = -2*e2
129 (cond ((> numepos numul-1eneg)
130 (mm-intir1 d (mul p (power rofpos (sub epos eneg)))
131 r0 e0 rofpos eneg rofneg eneg x))
132 ((or (equal e0 0) (plusp e0))
133 (pp-intir1 d (mul p (power rofneg (sub eneg epos)))
134 r0 e0 rofpos epos rofneg epos x))
136 (mm-intir1 d (mul p (power rofpos (sub epos eneg)))
137 r0 e0 rofpos eneg rofneg eneg x)))))
139 (defun pp-intir1-exec (d p r0 e0 rofmax emax rofmin emin x)
140 (intir (mul d p (if (equal e0 0) 1 (power r0 e0))
141 (power rofmax (add emax (mul -1 emin)))
142 (power ($expand (mul rofmax rofmin)) emin)) x))
144 ;; Handle integrals of the form d*p(x)*r0(x)^e0*r1(x)^e1*r2(x)^e2
145 ;; where p(x) is a polynomial, e1 < 0, and e2 < 0 and are both half an
146 ;; odd integer, and e3 is an integer. And e2 > e1.
147 (defun mm-intir1-exec (d p r0 e0 rofmin emin rofmax emax x)
148 (intir (mul d p
149 (if (equal e0 0) 1
150 (power r0 e0))
151 (power rofmax (add emax (mul -1 emin)))
152 (power ($expand (mul rofmax rofmin)) emin)) x))
154 ;; Integrating the form (e*x^2+f*x+g)^m*r0(x)^e0.
156 (defun intir3-ref (assoclist x e f g r0)
157 (let ((signdisc (signdiscr e f g))
158 (d (cdras 'd assoclist))
159 (p (cdras 'p assoclist))
160 (e0 (cdras 'e0 assoclist)))
161 (cond ((eq signdisc '$positive)
162 (pns-intir3 x e f g d p r0 e0))
163 ((eq signdisc '$negative)
164 (ns-intir3 x e f g d p r0 e0))
166 (zs-intir3 x e f d p r0 e0)))))
168 (defun root+anything (exp var2)
169 (m2 exp `((mplus)
170 ((coeffpt) (c nonzerp) ((mexpt) (u hasvar2 ,var2) (v integerpfr)))
171 ((coeffpp) (c true)))))
173 ;; Handle d*p(x)/(e*x^2+f*x+g)*r0(x)^e0. We know that e*x^2+f*x+g has
174 ;; no repeated roots. Let D be the discriminant of this quadratic,
175 ;; sqrt(f^2-4*e*g). (If we're here, we already know that f^2-4*e*g >
176 ;; 0). Thus, we can factor this quadratic as
177 ;; (2*e*x+f-D)*(2*e*x+f+D)/(4*e). Thus, the original integrand
178 ;; becomes
180 ;; 4*e*d/(2*e*x+f-D)/(2*e*x+f+D)*p(x)*r0(x)^e0.
182 ;; We can separate this as a partial fraction to get
184 ;; (2*d*e/D/(2*e*x+f-D) - 2*d*e/D/(2*e*x+f+D))*p(x)*r0(x)^e0.
186 ;; So we have separated this into two "simpler" integrals.
187 (defun pns-intir3 (x e f g d p r0 e0)
188 (let* ((discr (power (sub (mul f f) (mul 4 e g)) 1//2)) ;; Compute discriminant of
189 (p*r0^e0 (mul p (power r0 e0))) ;; quadratic: sqrt(f^2-4*e*g)
190 (2*e*x+f (add (mul 2 e x) f))
191 (2*e*d*invdisc (mul 2 e d (inv discr))))
192 (mul 2*e*d*invdisc
193 (sub (intir2 (mul (inv (sub 2*e*x+f discr)) p*r0^e0) x)
194 (intir2 (mul (inv (add 2*e*x+f discr)) p*r0^e0) x)))))
196 ;; Handle d*p(x)/(e*x^2+f*x+g)*r0(x)^e0. We know that e*x^2+f*x+g has
197 ;; repeated roots.
199 (defun zs-intir3 (x e f d p r0 e0)
200 ;; Since e*x^2+f*x+g has repeated roots, it can be written as e*(x+r)^2.
201 ;; We easily see that r = f/(2*e), so rewrite the integrand as
203 ;; d*p(x)/e/(x+r)^2*r0(x)^e0.
204 (intir2 (mul d p (inv e)
205 (power (add x (div f (add e e))) -2)
206 (power r0 e0))
209 ;; Handle d*p(x)/(e*x^2+f*x+g)*r0(x)^e0. We know that e*x^2+f*x+g has
210 ;; no real roots.
212 ;; G&R 2.252 shows how we can handle these integrals, but I'm too lazy
213 ;; to implement them right now, so return NIL to indicate we don't
214 ;; know what to do. But whatever it is we do, it's definitely not
215 ;; calling intir or intir2 like zs-intir3 or pns-intir3 do because
216 ;; they eventually call inti which only handles linear forms (e = 0.)
217 ;; We'll need to write custom versions.
218 (defun ns-intir3 (xx ee fff gg dd pp r0 e0)
219 (declare (ignore xx ee fff gg dd pp r0 e0))
220 nil)
222 (defun cdras (a b)
223 (cdr (assoc a b :test #'equal)))
225 (defun intir (funct x)
226 (inti funct x (jmaug (specrepcheck funct) x)))
228 ;; Integrate d*p(x)*(f*x+e)^m*(a*x^2+b*x+c)^n. p(x) is a polynomial,
229 ;; m is an integer, n is a number(?). a, b, c, e, and f are
230 ;; expressions independent of x (var).
231 (defun inti (funct x assoclist)
232 (prog (met n expr f e #+nil denom)
233 (setq n (cdras 'n assoclist))
234 (when (or (null assoclist) (maxima-integerp n))
235 (return nil))
236 (setq f (cdras 'f assoclist)
237 e (cdras 'e assoclist))
238 ;; If e is 0 (or not given, we don't have to do the
239 ;; transformation. Just integrate it and return.
240 (when (or (equal e 0) (null e))
241 (return (intira funct x)))
243 ;; (unless (numberp f) (go jump))
244 ;; (when (plusp f) (go jump))
245 ;; I (rtoy) think this is the case where f is a negative number.
246 ;; I think this is trying to convert f*x+e to -f*x-e to make the
247 ;; coefficient of x positive. And if I'm right, the code below
248 ;; isn't doing it correctly, except when m = 1 or m = -1.
249 ;; (setq denom (add (mul f x) e)
250 ;; f (mul -1 f)
251 ;; e (mul -1 e)
252 ;; funct (mul -1 (div (meval (mul denom funct))
253 ;; (add (mul f x) e))))
255 ;; jump
257 ;; Apply the linear substitution y = f*x+e. That is x = (y-e)/f.
258 ;; Then use INTIRA to integrate this. The integrand becomes
259 ;; something like p(y)*y^m and other terms.
260 (setq expr (intira (distrexpandroot
261 (cdr ($substitute
262 (mul (inv f)
263 (add (setq met (make-symbol (symbol-name '#:yannis)))
264 (mul -1 e)))
265 x funct)))
266 met))
267 (setq expr (and expr (mul (inv f) expr)))
268 (return ($expand ($substitute (add (mul f x) e) met expr)))))
270 (defun distrexpandroot (expr)
271 (if (null expr)
273 (mul (expandroot (car expr))
274 (distrexpandroot (cdr expr)))))
276 (defun expandroot (expr)
277 (if (atom expr)
278 expr
279 (if (and (eq (caar expr) 'mexpt)
280 (integerpfr (caddr expr)))
281 ($expand expr)
282 expr)))
284 (defun intirfactoroot (expr x)
285 (let ((factors (timestest expr)))
286 (flet ((try-inti ()
287 (let* ((e (distrfactor factors x))
288 (alist (jmaug e x)))
289 (when alist (inti e x alist)))))
290 (or (try-inti)
291 (let ((*globalcareflag* t))
292 (declare (special *globalcareflag*))
293 (try-inti))))))
295 ;; DISTRFACTOR
297 ;; Apply FACTOROOT to each element in the list, FACTORS. Accumulate the results
298 ;; by multiplication, associating to the right.
299 (defun distrfactor (factors x)
300 (if (null factors)
302 (mul (factoroot (first factors) x)
303 (distrfactor (rest factors) x))))
305 ;; FACTOROOT
307 ;; If EXPR is of the form A^B and is not free of VAR, use CAREFULFACTOR to try
308 ;; to factor it. Otherwise just return EXPR.
309 (defun factoroot (expr var2)
310 (if (and (mexptp expr)
311 (hasvar2 expr var2)
312 (integerpfr (caddr expr)))
313 (carefulfactor expr var2)
314 expr))
316 ;; CAREFULFACTOR
318 ;; Try to factor an expression of the form A^B. If *GLOBALCAREFLAG* is NIL, this
319 ;; is exactly the same as $FACTOR. Otherwise, use $FACTOR on (A/x)^B and then
320 ;; restore the missing x^B afterwards using RESTOREX.
321 (defun carefulfactor (expr x)
322 (declare (special *globalcareflag*))
323 (if (null *globalcareflag*)
324 ($factor expr)
325 (restorex ($factor (power (div (cadr expr) x) (caddr expr)))
326 x (caddr expr))))
328 ;; RESTOREX
330 ;; Multiply EXPR by VAR2^EXPT, trying to insert the factor of VAR2 inside terms in
331 ;; a product if possible.
332 (defun restorex (expr var2 expt)
333 (cond
334 ((and (mexptp expr)
335 (equal expt (caddr expr)))
336 (power (restorex (cadr expr) var2 1) (caddr expr)))
338 ((mtimesp expr)
339 (distrestorex (cdr expr) var2 expt))
342 (mul (power var2 expt) expr))))
344 ;; DISTRESTOREX
346 ;; Takes a list of factors. Returns an expression that equals the product of
347 ;; these factors, but after multiplying one of them by VAR to try to multiply
348 ;; the entire product by VAR^EXPT. If it's not possible to multiply factors to
349 ;; do so, add a factor of VAR^EXPT to the end.
350 (defun distrestorex (factors var2 expt)
351 (if (null factors)
352 (power var2 expt)
353 (let ((start (first factors)))
354 (if (and (mexptp start)
355 (equal expt (caddr start)))
357 (lmul
358 (cons (power ($expand (mul var2 (cadr start)))
359 (caddr start))
360 (rest factors)))
362 (mul start (distrestorex (rest factors) var2 expt))))))
364 (defun timestest (expr)
365 (if (mtimesp expr)
366 (cdr expr)
367 (list expr)))
369 ;; Integrate a function of the form d*p(y)*y^m*(a*y^2+b*x+c)^n.
370 ;; n is half of an integer.
371 (defun intira (funct x)
372 (prog (a b c ec-1 d m n (assoclist (jmaug (specrepcheck funct) x))
373 pluspowfo1 pluspowfo2 minuspowfo
374 polfact signn poszpowlist negpowlist)
375 (setq n (cdras 'n assoclist))
376 ;; r12 1//2)
377 ;; (format t "n = ~A~%" n)
378 (when (or (null assoclist)
379 (maxima-integerp n))
380 (return nil))
381 (when (floatp n)
382 (setq n (rdis (ration1 n))))
383 (setq d (cdras 'd assoclist))
384 (when (equal d 0) (return 0))
385 (setq c (cdras 'a assoclist))
386 (when (equal c 0) (return nil))
387 (setq m (cdras 'm assoclist)
388 polfact (cdras 'p assoclist)
389 ;; We know that n is of the form s/2, so just make n = s,
390 ;; and remember that the actual exponent needs to be
391 ;; divided by 2.
392 n (cadr n)
393 signn (checksigntm n)
394 ec-1 (power c -1)
395 b (cdras 'b assoclist)
396 a (cdras 'c assoclist)
397 ;; pluspowfo1 = 1/2*(n-1), That is, the original exponent - 1/2.
398 pluspowfo1 (mul 1//2 (+ n -1))
399 ;; minupowfo = 1/2*(n+1), that is, the original exponent + 1/2.
400 minuspowfo (mul 1//2 (+ n 1))
401 ;; pluspowfo2 = -1/2*(n+1), that is, the negative of 1/2
402 ;; plus the original exponent.
403 pluspowfo2 (* -1 minuspowfo))
404 (destructuring-bind (pos &optional neg)
405 (powercoeflist polfact m x)
406 (setf poszpowlist pos)
407 (setf negpowlist neg))
409 #+nil (progn
410 (format t "n = ~A~%" n)
411 (format t "pluspowfo1 = ~A~%" pluspowfo1)
412 (format t "minuspowfo = ~A~%" minuspowfo)
413 (format t "pluspowfo2 = ~A~%" pluspowfo2))
415 ;; I (rtoy) think powercoeflist computes p(x)/x^m as a Laurent
416 ;; series. POSZPOWLIST is a list of coefficients of the positive
417 ;; powers and NEGPOWLIST is a list of the negative coefficients.
418 (when (and (null negpowlist)
419 (not (null poszpowlist)))
420 ;; Only polynomial parts.
421 (when (eq signn '$positive)
422 (return (augmult (mul d
423 (nummnumn poszpowlist
424 pluspowfo1
425 minuspowfo c b a x ec-1)))))
426 (return (augmult (mul d
427 (nummdenn poszpowlist
428 pluspowfo2 c b a x ec-1)))))
429 (when (and (null poszpowlist)
430 (not (null negpowlist)))
431 ;; No polynomial parts
432 (when (eq signn '$positive)
433 (return (augmult (mul d
434 (denmnumn negpowlist minuspowfo c b a x ec-1)))))
435 (return (augmult (mul d
436 (denmdenn negpowlist pluspowfo2 c b a x ec-1)))))
437 (when (and (not (null negpowlist))
438 (not (null poszpowlist)))
439 ;; Positive and negative powers.
440 (when (eq signn '$positive)
441 (return (add (augmult (mul d
442 (nummnumn poszpowlist
443 pluspowfo1
444 minuspowfo c b a x ec-1)))
445 (augmult (mul d
446 (denmnumn negpowlist
447 minuspowfo c b a x ec-1))))))
448 (return (add (augmult (mul d
449 (nummdenn poszpowlist
450 pluspowfo2 c b a x ec-1)))
451 (augmult (mul d
452 (denmdenn negpowlist
453 pluspowfo2 c b a x ec-1))))))))
455 ;; Match d*p(x)*(f*x+e)^m*(a*x^2+b*x+c)^n. p(x) is a polynomial, m is
456 ;; an integer, n is half of an integer. a, b, c, e, and f are
457 ;; expressions independent of x (var).
458 (defun jmaug (exp var2)
459 (m2 exp `((mtimes)
460 ((coefftt) (d freevar2 ,var2))
461 ((coefftt) (p polyp-var ,var2))
462 ((mexpt) ((mplus) ((coeffpt) (f freevar2 ,var2) (x varp2 ,var2))
463 ((coeffpp)(e freevar2 ,var2)))
464 (m maxima-integerp))
465 ((mexpt) ((mplus)
466 ((coeffpt) (a freevar2 ,var2) ((mexpt) (x varp2 ,var2) 2))
467 ((coeffpt) (b freevar2 ,var2) (x varp2 ,var2))
468 ((coeffpp) (c freevar2 ,var2)))
469 (n integerp1)))))
471 ;; Match d*p(x)*r1(x)^e1*r2(x)^e2*r0(x)^e0, where p(x) is a
472 ;; polynomial, e1 and e2 are both half an odd integer, and e3 is an
473 ;; integer.
474 (defun factpow (exp var2)
475 (m2 exp `((mtimes) ((coefftt) (d freevar2 ,var2))
476 ((coefftt) (p polyp-var ,var2))
477 ((mexpt) (r1 hasvar2 ,var2)
478 (e1 integerpfr))
479 ((mexpt) (r2 hasvar2 ,var2)
480 (e2 integerpfr))
481 ((mexpt) (r0 hasvar2 ,var2)
482 (e0 maxima-integerp)))))
484 ;; Match EXP to the form
485 ;; d*p/(e*x^2+f*x+g)*r0(x)^e0. p is a polynomial in x.
486 (defun elliptquad (exp var2)
487 (m2 exp `((mtimes)
488 ((coefftt) (d freevar2 ,var2))
489 ((coefftt) (p polyp-var ,var2))
490 ((mexpt) ((mplus) ((coeffpt) (e freevnz2 ,var2) ((mexpt) (x varp2 ,var2) 2))
491 ((coeffpt) (f freevar2 ,var2) (x varp2 ,var2))
492 ((coeffpp) (g freevar2 ,var2)))
494 ((mexpt) (r0 hasvar2 ,var2)
495 (e0 integerpfr)))))
497 ;; From the set of coefficients, generate the polynomial c*x^2+b*x+a.
498 (defun polfoo (c b a x)
499 (add (mul c x x)
500 (mul b x)
503 ;; I think this is computing the list of coefficients of fun(x)/x^m,
504 ;; where fun(x) is a polynomial and m is a non-negative integer. The
505 ;; result is a list of two lists. The first list contains the
506 ;; polynomial part of fun(x)/x^m. The second is the principal part
507 ;; containing negative powers.
509 ;; Each of the lists is itself a list of power and coefficient itself.
511 ;; Thus (x+3)^2/x^2 = 1 + 6/x + 9/x^2 returns
513 ;; '(((0 1)) ((1 6) (2 9)))
514 (defun powercoeflist (fun m var2)
515 (prog ((expanfun (unquote ($expand (mul (prevconstexpan fun var2) (power var2 m)))))
516 maxpowfun powfun coef poszpowlist negpowlist)
517 (when (and (equal fun 1) (plusp m))
518 (return (cons nil (list (list (cons m (list 1)))))))
519 (when (and (equal fun 1) (minusp m))
520 (return (cons nil (list (list (cons (- m) (list 1)))))))
521 (when (equal expanfun 1)
522 (return (cons (list (cons 0 (list 1))) (list nil))))
523 (setq maxpowfun ($hipow expanfun var2)
524 powfun ($lopow expanfun var2))
525 loop (setq coef ($coeff expanfun (power var2 powfun)))
526 (when (numberp coef) (go testjump))
527 (go nojump)
528 testjump (when (and (not (zerop powfun)) (zerop coef))
529 (go jump))
530 nojump (when (plusp powfun)
531 (setq poszpowlist (append poszpowlist
532 (list (cons powfun (list coef))))))
533 (when (zerop powfun)
534 (setq poszpowlist
535 (append poszpowlist
536 (list (cons 0 (list (consterm (cdr expanfun) var2)))))))
537 (when (minusp powfun)
538 (setq negpowlist (append negpowlist (list (cons (- powfun) (list coef))))))
539 (when (= powfun maxpowfun)
540 (return (list poszpowlist (reverse negpowlist))))
541 jump (incf powfun)
542 (go loop)))
544 (defun consterm (fun var2)
545 (cond ((null fun) 0)
546 ((freeof var2 (car fun))
547 (add (car fun) (consterm (cdr fun) var2)))
548 (t (consterm (cdr fun) var2))))
550 (defun prevconstexpan (fun var2)
551 (cond ((atom fun) fun)
552 ((eq (caar fun) 'mplus)
553 (cond ((and (freeof var2 fun)
554 (not (inside fun 'mexpt)))
555 (list '(mquote) fun))
556 ((and (freeof var2 fun) (inside fun 'mexpt))
557 (list '(mquote)
558 (distrinplusprev (cdr fun) var2)))
559 ((inside fun 'mexpt)
560 (distrinplusprev (cdr fun) var2))
561 (t fun)))
562 ((eq (caar fun) 'mtimes)
563 (distrintimesprev (cdr fun) var2))
564 ((and (not (inside (cdr fun) var2))
565 (eq (caar fun) 'mexpt))
566 (power (prevconstexpan (cadr fun) var2) (caddr fun)))
567 (t fun)))
569 (defun distrinplusprev (fun var2)
570 (cond ((null fun) 0)
571 (t (add (prevconstexpan (car fun) var2)
572 (distrinplusprev (cdr fun) var2)))))
574 (defun distrintimesprev (fun var2)
575 (cond ((null fun) 1)
576 (t (mul (prevconstexpan (car fun) var2)
577 (distrintimesprev (cdr fun) var2)))))
579 (defun inside (fun arg)
580 (cond ((atom fun)(equal fun arg))
581 ((inside (car fun) arg) t)
582 (t (inside (cdr fun) arg))))
584 (defun unquote (fun)
585 (cond ((not (inside fun 'mquote)) fun)
586 (t (unquote (meval fun)))))
588 (let (zerosigntest productcase)
589 (defun checksigntm (expr)
590 (prog (aslist quest)
591 (setf zerosigntest nil
592 productcase nil)
593 (setq aslist *checkcoefsignlist*)
594 (cond ((atom expr) (go loop)))
595 (cond ((eq (caar expr) 'mtimes)(setq productcase t)))
596 loop (cond ((null aslist)
597 (setq *checkcoefsignlist*
598 (append *checkcoefsignlist*
599 (list (cons expr
600 (list
601 (setq quest (checkflagandact expr)))))))
602 (return quest)))
603 (cond ((equal (caar aslist) expr) (return (cadar aslist))))
604 (setq aslist (cdr aslist))
605 (go loop)))
607 (defun checkflagandact (expr)
608 (cond (productcase
609 (setq productcase nil)
610 (findsignoftheirproduct (findsignofactors (cdr expr))))
611 (t (asksign ($realpart expr)))))
613 (defun findsignofactors (listofactors)
614 (cond ((null listofactors) nil)
615 ((eq zerosigntest '$zero) '$zero)
616 (t (append (list (setq zerosigntest (checksigntm (car listofactors))))
617 (findsignofactors (cdr listofactors)))))))
619 (defun findsignoftheirproduct (llist)
620 (prog (sign)
621 (cond ((eq llist '$zero) (return '$zero)))
622 (setq sign '$positive)
623 loop (cond ((null llist) (return sign)))
624 (cond ((eq (car llist) '$positive)
625 (setq llist (cdr llist))
626 (go loop)))
627 (cond ((eq (car llist) '$negative)
628 (setq sign (changesign sign) llist (cdr llist))
629 (go loop)))
630 (return '$zero)))
632 (defun changesign (sign)
633 (if (eq sign '$positive)
634 '$negative
635 '$positive))
637 ;; Integrate 1/sqrt(c*x^2+b*x+a).
639 ;; G&R 2.261 gives the following, where R = c*x^2+b*x+a and D =
640 ;; 4*a*b-b^2:
642 ;; c > 0:
643 ;; 1/sqrt(c)*log(2*sqrt(c*R)+2*c*x+b)
645 ;; c > 0, D > 0:
646 ;; 1/sqrt(c)*asinh((2*c*x+b)/sqrt(D))
648 ;; c < 0, D < 0:
649 ;; -1/sqrt(-c)*asin((2*c*x+b)/sqrt(-D))
651 ;; c > 0, D = 0:
652 ;; 1/sqrt(c)*log(2*c*x+b)
654 (defun den1 (c b a x)
655 (let* ((expr (add (mul 2 c x) b)) ;; expr = 2*c*x+b
656 (signc (checksigntm (power c -1)))
657 (signb (checksigntm (power b 2)))
658 (signdiscrim (signdis2 c b a signc signb)))
659 (when (and (eq signc '$positive)
660 (eq signdiscrim '$negative))
661 ;; c > 0, D > 0
662 (return-from den1 (augmult (mul* (power c -1//2)
663 `((%asinh)
664 ,(mul expr
665 (power (add (mul 4 c a)
666 (mul -1 b b))
667 -1//2)))))))
668 (when (and (eq signc '$positive)
669 (eq signdiscrim '$zero))
670 ;; c > 0, D = 0
671 (return-from den1 (augmult (mul* (power -1 expr)
672 (power c -1//2)
673 `((%log) ,expr)))))
674 (when (eq signc '$positive)
675 ;; c > 0
676 (return-from den1 (augmult (mul* (power c -1//2)
677 `((%log)
678 ,(add (mul 2
679 (power c 1//2)
680 (power (polfoo c b a x) 1//2))
681 expr))))))
682 (when (and (eq signc '$negative)
683 (eq signdiscrim '$positive))
684 ;; c < 0, D > 0
685 (return-from den1 (augmult (mul* -1
686 (power (mul -1 c) -1//2)
687 `((%asin)
688 ,(mul expr
689 (power (add (mul b b)
690 (mul -4 c a))
691 -1//2)))))))
692 (when (eq signc '$negative)
693 ;; c < 0. We try again, but flip the sign of the
694 ;; polynomial, and multiply by -%i.
695 (return-from den1 (augmult (mul (power -1 -1//2)
696 (den1 (mul -1 c)
697 (mul -1 b)
698 (mul -1 a)
699 x)))))))
701 ;; Compute sign of discriminant of the quadratic c*x^2+b*x+a. That
702 ;; is, the sign of b^2-4*c*a.
703 (defun signdiscr (c b a)
704 (checksigntm (simplifya (add (power b 2) (mul -4 c a)) nil)))
706 (defun askinver (a)
707 (checksigntm (inv a)))
709 (defun signdis1 (c b a)
710 (cond ((equal (mul b a) 0)
711 (if (and (equal b 0) (equal a 0))
712 '$zero
713 '$nonzero))
715 ;; Why are we checking the sign of (b^2-4*a*c)^2?
716 (checksigntm (power (add (mul b b) (mul -4 c a)) 2)))))
718 ;; Check sign of discriminant of c*x^2+b*x+a, but also taking into
719 ;; account the sign of c and b.
720 (defun signdis2 (c b a signc signb)
721 (cond ((equal signb '$zero)
722 (cond ((equal a 0) '$zero)
723 (t (let ((askinv (askinver a)))
724 (if (or (and (eq signc '$positive)
725 (eq askinv '$negative))
726 (and (eq signc '$negative)
727 (eq askinv '$positive)))
728 '$positive
729 '$negative)))))
730 (t (if (equal a 0)
731 '$positive
732 (signdiscr c b a)))))
734 (defun signdis3 (c b a signa ec-1)
735 (cond ((equal b 0)
736 (if (equal (checksigntm ec-1) signa)
737 '$negative
738 '$positive))
739 (t (signdiscr c b a))))
741 ;; Integrate things like x^m*R^(p-1/2), p > 0, m > 0.
743 ;; I think pluspowfo1 = p - 1.
744 (defun nummnumn (poszpowlist pluspowfo1 p c b a x ec-1)
745 (let ((expr (power (polfoo c b a x) (add p 1//2))) ;; expr = R^(p+1/2)
746 (expo ec-1) ;; expo = 1/c
747 (ex (power c -2))) ;; ex = 1/c^2
748 (prog ((result 0)
749 (controlpow (caar poszpowlist))
750 (coef (cadar poszpowlist))
751 count res1 res2 m partres)
752 #+nil (format t "p = ~A~%pluspowfo1 = ~A~%" p pluspowfo1)
753 (when (zerop controlpow)
754 ;; Integrate R^(p-1/2)
755 (setq result (augmult (mul coef (numn pluspowfo1 c b a x ec-1)))
756 count 1)
757 (go loop))
759 jump1
760 ;; Handle x*R^(p-1/2)
762 ;; G&R 2.260, m = 1
764 ;; integrate(x*R^(2*p-1),x) =
765 ;; R^(p+1/2)/(2*p+1)/c
766 ;; - b/2/c*integrate(sqrt(R^(2*p-1)),x)
767 (setq res1 (add (augmult (mul expr expo
768 (power (+ p p 1) -1)))
769 (augmult (mul -1 b 1//2 expo
770 (numn pluspowfo1 c b a x ec-1)))))
771 (when (equal controlpow 1)
772 (setq result (add result (augmult (mul coef res1)))
773 count 2)
774 (go loop))
776 jump2
777 ;; Handle x^2*R^(p-1/2)
779 ;; G&R 2.260, m = 2
781 ;; integrate(x^2*R^(2*p-1),x) =
782 ;; x*R^(p+1/2)/(2*p+2)/c
783 ;; - (2*p+3)*b/2/(2*p+2)/c*integrate(x*sqrt(R^(2*p-1)),x)
784 ;; - a/(2*p+2)/c*integrate(sqrt(R^(2*p-1)),x)
785 (setq res2 (add (augmult (mul* x expr expo
786 (inv (+ p p 2))))
787 (augmult (mul* b (+ p p 3)
788 '((rat) -1 4)
790 (inv (+ p p p 1
791 (* p p)
792 (* p p)))
793 expr))
794 (augmult (mul (inv (1+ p))
796 '((rat simp) 1 8)
797 (add (mul (power b 2)
798 (+ p p 3))
799 (mul -4 a c))
800 (numn pluspowfo1 c b a x ec-1)))))
801 (when (equal controlpow 2)
802 (setq result (add result (augmult (mul coef res2)))
803 count 3)
804 (go loop))
806 jump3
807 (setq count 4
808 m 3)
809 jump
810 ;; The general case: x^m*R^(p-1/2)
811 (setq partres
812 (let ((pro (inv (+ m p p))))
813 ;; pro = 1/(m+2*p)
815 ;; G&R 2.260, m = 2
817 ;; integrate(x^m*R^(2*p-1),x) =
818 ;; x^(m-1)*R^(p+1/2)/(m+2*p)/c
819 ;; - (2*m+2*p-1)*b/2/(m+2*p)/c*integrate(x^(m-1)*sqrt(R^(2*p-1)),x)
820 ;; - (m-1)*a/(m+2*p)/c*integrate(x^(m-2)*sqrt(R^(2*p-1)),x)
821 (add (augmult (mul (power x (1- m))
822 expr expo pro))
823 (augmult (mul -1 b (+ p p m m -1)
824 1//2 expo pro res2))
825 (augmult (mul -1 a (1- m)
826 expo pro res1)))))
827 (incf m)
828 (when (> m controlpow)
829 (setq result (add result (augmult (mul coef partres))))
830 (go loop))
832 jump4
833 (setq res1 res2
834 res2 partres)
835 (go jump)
837 loop
838 (setq poszpowlist (cdr poszpowlist))
839 (when (null poszpowlist) (return result))
840 (setq coef (cadar poszpowlist))
841 (setq controlpow (caar poszpowlist))
842 (when (equal count 4) (go jump4))
843 (when (equal count 1) (go jump1))
844 (when (equal count 2) (go jump2))
845 (go jump3))))
847 ;; Integrate R^(p+1/2)
848 (defun numn (p c b a x ec-1)
849 (let ((exp1 ec-1) ;; exp1 = 1/c
850 (exp2 (add b (mul 2 c x))) ;; exp2 = b+2*c*x
851 (exp4 (add (mul 4 a c) (mul -1 b b))) ;; exp4 = 4*a*c-b^2
852 (exp5 (div 1 (1+ p)))) ;; exp5 = 1/(p+1)
853 (if (zerop p)
854 ;; integrate(sqrt(R),x)
856 ;; G&R 2.262 says
858 ;; integrate(sqrt(R),x) =
859 ;; (2*c*x+b)*sqrt(R)/4/c + del/8/c*integrate(1/sqrt(R),x)
861 ;; del = 4*a*c-b^2
862 (add (augmult (mul '((rat simp) 1 4)
863 exp1 exp2
864 (power (polfoo c b a x) 1//2)))
865 (augmult (mul '((rat simp) 1 8)
866 exp1 exp4
867 (den1 c b a x))))
869 ;; The general case
871 ;; G&R 2.260, eq. 2:
873 ;; integrate(sqrt(R^(2*p+1)),x) =
874 ;; (2*c*x+b)/4/(p+1)/c*R^(p+1/2)
875 ;; + (2*p+1)*del/8/(p+1)/c*integrate(sqrt(R^(2*p-1)),x)
876 (add (augmult (mul '((rat simp) 1 4)
877 exp1 exp5 exp2
878 (power (polfoo c b a x) (add p 1//2))))
879 (augmult (mul '((rat simp) 1 8)
880 exp1 exp5 (+ p p 1)
881 exp4
882 (numn (1- p) c b a x ec-1)))))))
884 (defun augmult (x)
885 ($multthru (simplifya x nil)))
887 ;; Integrate things like 1/x^m/R^(p+1/2), p > 0.
888 (defun denmdenn (negpowlist p c b a x ec-1)
889 (let ((exp1 (power (polfoo c b a x) (add 1//2 (- p))))) ;; exp1 = 1/R^(p-1/2)
890 (prog (result controlpow coef count res1 res2 m partres
891 (signa (checksigntm (simplifya a nil)))
892 ea-1)
893 (when (eq signa '$zero)
894 (return (noconstquad negpowlist p c b x)))
895 (setq result 0
896 controlpow (caar negpowlist)
897 ea-1 (power a -1))
898 (setq coef (cadar negpowlist))
899 (when (zerop controlpow)
900 ;; I'm not sure we ever get here because m = 0 is
901 ;; usually handled elsewhere.
902 (setq result (augmult (mul coef (denn p c b a x)))
903 count 1)
904 (go loop))
906 jump1
907 ;; Handle 1/x/R^(p+1/2)
908 (setq res1 (den1denn p c b a x ec-1))
909 (when (equal controlpow 1)
910 (setq result (add result (augmult (mul coef res1)))
911 count 2)
912 (go loop))
914 jump2
915 ;; Handle 1/x^2/R^(p+1/2)
917 ;; G&R 2.268, m = 2
919 ;; integrate(1/x^2/R^(p+1/2),x) =
920 ;; -1/a/x/sqrt(R^(2*p-1))
921 ;; -(2*p+1)*b/2/a*integrate(1/x/sqrt(R^(2*p+1)),x)
922 ;; -2*p*c/a*integrate(1/sqrt(R^(2*p+1)),x)
923 (setq res2 (add (augmult (mul -1 ea-1 (power x -1) exp1))
924 (augmult (mul -1 b (+ 1 p p) 1//2
925 ea-1 (den1denn p c b a x ec-1)))
926 (augmult (mul -2 p c ea-1 (denn p c b a x)))))
927 (when (equal controlpow 2)
928 (setq result (add result (augmult (mul coef res2)))
929 count 3)
930 (go loop))
932 jump3
933 (setq count 4
934 m 3)
936 jump
937 ;; General case 1/x^m/R^(p+1/2)
939 ;; G&R 2.268
941 ;; integrate(1/x^2/R^(p+1/2),x) =
942 ;; -1/(m-1)/a/x^(m-1)/sqrt(R^(2*p-1))
943 ;; -(2*p+2*m-3)*b/2/(m-1)/a*integrate(1/x^(m-1)/sqrt(R^(2*p+1)),x)
944 ;; -(2*n+m-2)*c/(m-1)/a*integrate(1/x^(m-2)/sqrt(R^(2*p+1)),x)
945 (setq partres
946 (let ((exp2 (div -1 (1- m))))
947 ;; exp2 = -1/(m-1)
948 (add (augmult (mul exp2 ea-1
949 (power x (1+ (- m)))
950 exp1))
951 (augmult (mul b (+ p p m m -3) 1//2
952 ea-1 exp2 res2))
953 (augmult (mul c ea-1 exp2
954 (+ p p m -2) res1)))))
955 (incf m)
956 (when (> m controlpow)
957 (setq result (add result (augmult (mul coef partres))))
958 (go loop))
960 jump4
961 (setq res1 res2 res2 partres)
962 (go jump)
964 loop
965 (setq negpowlist (cdr negpowlist))
966 (when (null negpowlist) (return result))
967 (setq coef (cadar negpowlist)
968 controlpow (caar negpowlist))
969 (when (equal count 4) (go jump4))
970 (when (equal count 1) (go jump1))
971 (when (equal count 2) (go jump2))
972 (go jump3))))
974 ;; Integral of 1/(c*x^2+b*x+a)^(n), n > 0. p = n + 1/2.
976 ;; See G&R 2.263 formula 3.
978 ;; Let R = c*x^2+b*x+a.
979 (defun denn (p c b a x)
980 (let ((signdisc (signdis1 c b a))
981 (exp1 (add b (mul 2 c x))) ;; exp1 = b + 2*c*x;
982 (exp2 (add (mul 4 a c) (mul b b -1))) ;; exp2 = (4*a*c-b^2)
983 (exp3 (inv (+ p p -1))) ;; exp3 = 1/(2*p-1)
984 (ec-1 (inv c)))
985 #+nil (format t "signdisc = ~A~%p = ~A~%" signdisc p)
986 (cond ((and (eq signdisc '$zero) (zerop p))
987 ;; 1/sqrt(R), and R has duplicate roots. That is, we have
988 ;; 1/sqrt(c*(x+b/(2c))^2) = 1/sqrt(c)/sqrt((x+b/2/c)^2).
990 ;; We return 1/sqrt(c)*log(x+b/2/c). Shouldn't we return
991 ;; 1/c*log(|x+b/2/c|)?
992 (augmult (mul* (power ec-1 1//2)
993 `((%log) ,(add x (mul b 1//2 ec-1))))))
994 ((and (eq signdisc '$zero) (plusp p))
995 ;; 1/sqrt(R^(2*p+1)), with duplicate roots.
997 ;; That is, 1/sqrt((c*(x+b/2/c)^(2)^(2*p+1))), or
998 ;; 1/c^(p+1/2)/(x+b/2/c)^(2*p+1). So the result is
999 ;; -1/2/p*c^(-p-1/2)/(x+b/2/c)^(2*p)
1000 (augmult (mul (div -1 (+ p p))
1001 (power c (mul -1//2 (+ p p 1)))
1002 (power (add x (mul b 1//2 ec-1)) (* -2 p)))))
1003 ((zerop p)
1004 ;; 1/sqrt(R)
1005 (den1 c b a x))
1006 ((equal p 1)
1007 ;; 1/sqrt(R^3).
1009 ;; G&R 2.264 eq. 5 says
1011 ;; 2*(2*c*x+b)/del/sqrt(R).
1012 (augmult (mul 2 exp1 (inv exp2)
1013 (power (polfoo c b a x) -1//2))))
1015 ;; The general case. G&R 2.263 eq. 3.
1017 ;; integrate(1/sqrt(R^(2*p+1)),x) =
1018 ;; 2*(2*c*x+b)/(2*p-1)/c/sqrt(R^(2*p-1))
1019 ;; + 8*(p-1)*c/(2*p-1)/del*integrate(1/sqrt(R^(2*p-1)),x)
1021 ;; where del = 4*a*c-b^2.
1022 (add (augmult (mul 2 exp1
1023 exp3 (inv exp2)
1024 (power (polfoo c b a x)
1025 (add 1//2 (- p)))))
1026 (augmult (mul 8 c (1- p)
1027 exp3 (inv exp2)
1028 (denn (1- p) c b a x))))))))
1030 ;; Integral of 1/x/(c*x^2+b*x+a)^(p+1/2), p > 0.
1031 (defun den1denn (p c b a x ec-1)
1032 (let ((signa (checksigntm (power a 2))) ;; signa = sign of a^2
1033 (ea-1 (inv a))) ;; ea-1 = 1/a
1034 (cond ((eq signa '$zero)
1035 ;; This is wrong because noconstquad expects a
1036 ;; powercoeflist for th first arg. But I don't think
1037 ;; there's any way to get here from anywhere. I'm pretty
1038 ;; sure den1denn is never called with a equal to 0.
1039 (noconstquad 1 p c b x))
1040 ((zerop p)
1041 ;; 1/x/sqrt(c*x^2+b*x+a)
1042 (den1den1 c b a x ec-1))
1044 ;; The general case. See G&R 2.268:
1046 ;; R=(c*x^2+b*x+a)
1048 ;; integrate(1/x/sqrt(R^(2*p+1)),x) =
1050 ;; 1/(2*p-1)/a/sqrt(R^(2*p-1))
1051 ;; - b/2/a*integrate(1/sqrt(R^(2*p+1)),x)
1052 ;; + 1/a*integrate(1/x/sqrt(R^(2*p-1)),x)
1053 (add (augmult (mul (inv (+ p p -1))
1054 ea-1
1055 (power (polfoo c b a x)
1056 (add 1//2 (- p)))))
1057 (augmult (mul ea-1 (den1denn (1- p) c b a x ec-1)))
1058 (augmult (mul -1 1//2 ea-1 b (denn p c b a x))))))))
1060 ;; Integral of 1/x/sqrt(c*x^2+b*x+a).
1062 ;; G&R 2.266 gives the following results, where del is the
1063 ;; discriminant 4*a*c-b^2. (I think this is the opposite of what we
1064 ;; compute below for the discriminant.)
1066 (defun den1den1 (c b a x ec-1)
1067 (let ((exp2 (add (mul b x) a a)) ; exp2 = b*x+2*a
1068 (exp3 (inv (simplify (list '(mabs) x))))) ; exp3 = 1/abs(x)
1069 (prog (signdiscrim
1070 (condition (add (mul b x) a a))
1071 (signa (checksigntm (simplifya a nil)))
1072 exp1)
1073 (when (eq signa '$zero)
1074 (return (noconstquad '((1 1)) 0 c b x)))
1075 (setq signdiscrim (signdis3 c b a signa ec-1)
1076 exp1 (power a (inv -2)))
1077 #+nil (format t "signa = ~A~%signdiscrim = ~A~%" signa signdiscrim)
1079 (when (and (eq signa '$positive)
1080 (eq signdiscrim '$negative))
1081 ;; G&R case a > 0, del > 0
1083 ;; -1/sqrt(a)*asinh((2*a+b*x)/x/sqrt(del)
1084 (return (mul* -1 exp1
1085 `((%asinh)
1086 ,(augmult (mul exp2 exp3
1087 (power (add (mul 4 a c)
1088 (mul -1 b b))
1089 -1//2)))))))
1090 (when (and (eq signdiscrim '$zero)
1091 (eq signa '$positive))
1092 ;; G&R case del = 0, a > 0
1094 ;; 1/sqrt(a)*log(x/(2*a+b*x))
1095 (return (mul* (power -1 condition)
1096 -1 exp1
1097 `((%log) ,(augmult (mul exp3 exp2))))))
1098 (when (eq signa '$positive)
1099 ;; G&R case a > 0
1101 ;; -1/sqrt(a)*log((2*a+b*x+2*sqrt(a*R))/x)
1103 ;; R = c*x^2+b*x+a.
1104 (return (mul* -1 exp1
1105 `((%log)
1106 ,(add b (mul 2 a exp3)
1107 (mul 2 exp3
1108 (power a 1//2)
1109 (power (polfoo c b a x) 1//2)))))))
1110 (when (and (eq signa '$negative)
1111 (eq signdiscrim '$positive))
1112 ;; G&R case a < 0, del < 0
1114 ;; 1/sqrt(-a)*asin((2*a+b*x)/x/sqrt(b^2-4*a*c))
1115 (return (mul* (power (mul -1 a) -1//2)
1116 `((%asin)
1117 ,(augmult (mul exp2 exp3
1118 (power (add (mul b b) (mul -4 a c)) -1//2)))))))
1119 ;; I think this is the case of a < 0. We flip the sign of
1120 ;; coefficients of the quadratic to make a positive, and
1121 ;; multiply the result by 1/%i.
1123 ;; Why can't we use the case a < 0 in G&R 2.266:
1125 ;; 1/sqrt(-a)*atan((2*a+b*x)/2/sqrt(-a)/sqrt(R)
1127 ;; FIXME: Why the multiplication by -1?
1128 (return (mul #+nil -1
1129 (power -1 1//2)
1130 (den1den1 (mul -1 c) (mul -1 b) (mul -1 a) x ec-1))))))
1132 ;; Integral of d/x^m/(c*x^2+b*x)^(p+1/2), p > 0. The values of m and
1133 ;; d are in NEGPOWLIST.
1134 (defun noconstquad (negpowlist p c b x)
1135 (let ((exp1 (inv (+ p p 1))) ;; exp1 = 1/(2*p+1)
1136 (exp2 (inv x)) ;; exp2 = 1/x
1137 (exp3 (- p))) ;; exp3 = -p
1138 (prog (result controlpow coef count res1 signb m partres eb-1)
1139 (setq signb (checksigntm (power b 2)))
1140 (when (eq signb '$zero)
1141 (return (trivial1 negpowlist p c x)))
1142 (setq result 0
1143 controlpow (caar negpowlist)
1144 coef (cadar negpowlist)
1145 eb-1 (inv b))
1146 (when (zerop controlpow)
1147 ;; Not sure if we ever actually get here. The case of
1148 ;; m=0 is usually handled at a higher level.
1149 (setq result (augmult (mul coef (denn p c b 0 x)))
1150 count 1)
1151 (go loop))
1152 jump1
1153 ;; Handle 1/x/R^(p+1/2)
1155 ;; G&R 2.268, a = 0, m = 1
1157 ;; integrate(1/x^m/sqrt(R^(2*p+1)),x) =
1158 ;; -2/(2*p+1)/b/x/sqrt(R^(2*p-1))
1159 ;; -4*p*c/(2*p+1)/b*integrate(1/sqrt(R^(2*p+1)),x)
1160 (setq res1 (add (augmult (mul -2 exp1 eb-1 exp2
1161 (power (polfoo c b 0 x)
1162 (add 1//2 exp3))))
1163 (augmult (mul -4 p c exp1 eb-1 (denn p c b 0 x)))))
1164 (when (equal controlpow 1)
1165 (setq result (add result (augmult (mul coef res1)))
1166 count 2)
1167 (go loop))
1168 jump2 (setq count 3 m 2)
1169 jump
1170 ;; Handle general case 1/x^m/R^(p+1/2)
1172 ;; G&R 2.268, a = 0
1174 ;; integrate(1/x^m/sqrt(R^(2*p+1)),x) =
1175 ;; -2/(2*p+2*m-1)/b/x^m/sqrt(R^(2*p+1))
1176 ;; -(4*p+2*m-2)*c/(2*p+2*m-1)/b*integrate(1/x^(m-1)/sqrt(R^(2*p+1)),x)
1177 (setq partres
1178 (add (augmult (mul -2 (inv (+ p p m m -1))
1179 eb-1
1180 (power x (mul -1 m))
1181 (power (polfoo c b 0 x)
1182 (add 1//2 exp3))))
1183 (augmult (mul -2 c (+ p p m -1)
1184 eb-1
1185 (inv (+ p p m m -1))
1186 res1))))
1187 (incf m)
1188 (when (> m controlpow)
1189 (setq result (add result (augmult (mul coef partres))))
1190 (go loop))
1191 jump3
1192 (setq res1 partres)
1193 (go jump)
1194 loop
1195 (setq negpowlist (cdr negpowlist))
1196 (when (null negpowlist) (return result))
1197 (setq coef (cadar negpowlist)
1198 controlpow (caar negpowlist))
1199 (when (= count 3) (go jump3))
1200 (when (= count 1) (go jump1))
1201 (go jump2))))
1203 ;; The trivial case of d/x^m/(c*x^2+b*x+a)^(p+1/2), p > 0, and a=b=0.
1204 (defun trivial1 (negpowlist p c x)
1205 (cond ((null negpowlist) 0)
1207 ;; d/x^m/c^(p+1/2)/x^(2*p+1) = d/c^(p+1/2)/x^(m+2*p+1)
1208 ;; The integral is obviously
1210 ;; -d/c^(p+1/2)/x^(m+2*p)/(m+2*p)
1211 (add (augmult (mul (power x
1212 (add (* -2 p)
1213 (mul -1 (caar negpowlist))))
1214 (cadar negpowlist)
1215 (power c (add (- p) -1//2))
1216 (inv (add (* -2 p)
1217 (mul -1 (caar negpowlist))))))
1218 (trivial1 (cdr negpowlist) p c x)))))
1220 ;; Integrate pl(x)/(c*x^2+b*x+a)^(p+1/2) where pl(x) is a polynomial
1221 ;; and p > 0. The polynomial is given in POSZPOWLIST.
1222 (defun nummdenn (poszpowlist p c b a x ec-1)
1223 (let ((exp1 (inv (+ p p -1))) ;; exp1 = 1/(2*p-1)
1224 (exp2 (power (polfoo c b a x) (add 1//2 (- p)))) ;; exp2 = (a*x^2+b*x+c)^(p-1/2)
1225 (exp3 (add (mul 4 a c) (mul -1 b b))) ;; exp3 = (4*a*c-b^2) (negative of the discriminant)
1226 (exp4 (add x (mul b 1//2 ec-1))) ;; exp4 = x+b/2/c
1227 (exp5 (power c -2)) ;; exp5 = 1/c^2
1228 (exp6 (+ 2 (* -2 p))) ;; exp6 = -2*p+2
1229 (exp7 (1+ (* -2 p)))) ;; exp7 = -2*p+1
1230 (prog (result controlpow coef count res1 res2 m partres signdiscrim)
1231 ;; Let S=R^(p+1/2).
1233 ;; We are trying to integrate pl(x)/S
1234 ;; = (p0 + p1*x + p2*x^3 + ...)/S
1236 ;; So the general term is pm*x^m/S. This integral is given by
1237 ;; G&R 2.263, eq.1:
1239 ;; integrate(x^m/sqrt(R^(2*p+1)),x) =
1241 ;; x^(m-1)/(m-2*n)/sqrt(R^(2*p-1))
1242 ;; - (2*m-2*n-1)*b/2/(m-2*n)/c*integrate(x^(m-1)/sqrt(R^(2*p+1)),x)
1243 ;; - (m-1)*a/(m-2*n)/c*integrate(x^(m-2)/sqrt(R^(2*p+1)),x)
1245 ;; Thus the integration of x^m/S involves x^(m-1)/S and x^(m-2)/S.
1247 ;; I think what this loop does is integrate x^(m-1)/S and
1248 ;; x^(m-2)/S, and remember them so that we can integrate x^m/S
1249 ;; without having to do all the integrals again. Thus we
1250 ;; start with the constant term and work our way up to the
1251 ;; highest term.
1253 ;; I think this would be much simpler if we used memoization
1254 ;; and start with the highest power. Then all the
1255 ;; intermediate forms will have been computed, and we can just
1256 ;; simply integrate all the lower terms by looking them up.
1257 (setq result 0
1258 controlpow (caar poszpowlist))
1259 (setq coef (cadar poszpowlist)
1260 signdiscrim (signdis1 c b a))
1261 ;; We're looking at coef*x^controlpow/R^(p+1/2) right now.
1262 (when (zerop controlpow)
1263 ;; Actually it's coef/R^(p+1/2), so handle that now, go
1264 ;; to the next coefficient.
1265 (setq result (augmult (mul coef (denn p c b a x)))
1266 count 1)
1267 (go loop))
1269 jump1
1271 ;; This handles the case coef*x/R^(p+1/2)
1273 ;; res1 = -1/c/(2*p-1)*R^(p-1/2)
1274 ;; -b/2/c*integrate(R^(p+1/2),x)
1276 (setq res1
1277 (add (augmult (mul -1 ec-1 exp1 exp2))
1278 (augmult (mul b -1//2 ec-1 (denn p c b a x)))))
1279 (when (= controlpow 1)
1280 ;; Integrate coef*x/R^(p+1/2).
1282 ;; x/R^(p+1/2) is in res1.
1283 (setq result (add result (augmult (mul coef res1)))
1284 count 2)
1285 (go loop))
1286 jump2
1287 ;; This handles the case coef*x^2/R^(p+1/2)
1288 (when (and (plusp p) (not (eq signdiscrim '$zero)))
1289 ;; p > 0, no repeated roots
1290 (setq res2
1291 (add (augmult (mul ec-1 exp1 (inv exp3) exp2
1292 (add (mul 2 a b)
1293 (mul 2 b b x)
1294 (mul -4 a c x))))
1295 (augmult (mul ec-1 (inv exp3) exp1
1296 (add (mul 4 a c)
1297 (mul 2 b b p)
1298 (mul -3 b b))
1299 (denn (+ p -1)
1300 c b a x))))))
1301 (when (and (zerop p) (not (eq signdiscrim '$zero)))
1302 ;; x^2/sqrt(R), no repeated roots.
1304 ;; G&R 2.264, eq. 3
1306 ;; integrate(x^2/sqrt(R),x) =
1307 ;; (x/2/c-3*b/4/c^2)*sqrt(R)
1308 ;; + (3*b^2/8/c^2-a/2/c)*integrate(1/sqrt(R),x)
1310 ;; = (2*c*x-3*b)/4/c^2*sqrt(R)
1311 ;; + (3*b^2-4*a*c)/8/c^2*integrate(1/sqrt(R),x)
1312 (setq res2
1313 (add (augmult (mul '((rat simp) 1 4)
1314 exp5
1315 (add (mul 2 c x)
1316 (mul -3 b))
1317 (power (polfoo c b a x)
1318 1//2)))
1319 (augmult (mul '((rat simp) 1 8)
1320 exp5
1321 (add (mul 3 b b)
1322 (mul -4 a c))
1323 (den1 c b a x))))))
1324 (when (and (zerop p) (eq signdiscrim '$zero))
1325 ;; x^2/sqrt(R), repeated roots
1327 ;; With repeated roots, R is really of the form
1328 ;; c*x^2+b*x+b^2/4/c = c*(x+b/2/c)^2. So we have
1330 ;; x^2/sqrt(c)/(x+b/2/c)
1332 ;; And the integral of this is
1334 ;; b^2*log(x+b/2/c)/4/c^(5/2) + x^2/2/sqrt(c) - b*x/2/c^(3/2).
1336 (setq res2
1337 ;; (add (augmult (mul* b b (list '(rat) 1 4)
1338 ;; (power c -3)
1339 ;; (list '(%log) exp4)))
1340 ;; (augmult (mul ec-1 1//2 (power exp4 2)))
1341 ;; (augmult (mul -1 b x exp5)))
1342 (add (augmult (mul* b b '((rat) 1 4)
1343 (power c (div -5 2))
1344 `((%log) ,exp4)))
1345 (augmult (mul (power c -1//2) 1//2 (power x 2)))
1346 (augmult (mul -1//2 b x (power c (div -3 2)))))))
1348 (when (and (= p 1) (eq signdiscrim '$zero))
1349 ;; x^2/sqrt(R^3), repeated roots
1351 ;; As above, we have c*(x+b/2/c)^2, so
1353 ;; x^2/sqrt(R^3) = x^2/sqrt(c^3)/(x+b/2/c)^3
1355 ;; And the integral is
1357 ;; log(x+b/2/c)/c^(3/2) + z*(3*z+4*x)/2/c^(3/2)/(z+x)^2
1359 ;; where z = b/2/c.
1360 (setq res2
1361 ;; (add (augmult (mul* ec-1 (list '(%log) exp4)))
1362 ;; (augmult (mul b exp5 (power exp4 -1)))
1363 ;; (augmult (mul (list '(rat) -1 8)
1364 ;; (power c -3)
1365 ;; b b (power exp4 -2))))
1366 (add (augmult (mul* (power c (div -3 2)) `((%log) ,exp4)))
1367 (augmult (mul b x (power c (div -5 2)) (power exp4 -2)))
1368 (augmult (mul (div 3 8)
1369 (power c (div -7 2))
1370 b b (power exp4 -2))))))
1372 (when (and (eq signdiscrim '$zero) (> p 1))
1373 ;; x^2/R^(p+1/2), repeated roots, p > 1
1375 ;; As above, we have R=c*(x+b/2/c)^2, so the integral is
1377 ;; x^2/(x+b/2/c)^(2*p+1)/c^(p+1/2).
1379 ;; Let d = b/2/c. Then write x^2 =
1380 ;; (x+d)^2-2*d*(x+d)+d^2. The integrand becomes
1382 ;; 1/(x+d)^(2*p-1) - 2*d/(x+d)^(2*p) + d^2/(x+d)^(2*p+1)
1384 ;; whose integral is
1386 ;; 1/(2*p-2)/(x+d)^(2*p-2) - 2*d/(2*p-1)/(x+d)^(2*p-1)
1387 ;; + d^2/(2*p)/(x+d)^(2*p)
1389 ;; And don't forget the factor c^(-p-1/2). Finally,
1391 ;; 1/c^(p+1/2)/(2*p-2)/(x+d)^(2*p-2)
1392 ;; - b/c^(p+3/2)/(2*p-1)/(x+d)^(2*p-1)
1393 ;; + b^2/8/c^(p+5/2)/p/(x+d)^(2*p)
1394 (setq res2
1395 ;; (add (augmult (mul ec-1
1396 ;; (power exp4 exp6)
1397 ;; (inv exp6)))
1398 ;; (augmult (mul -1 b exp5 (inv exp7)
1399 ;; (power exp4 exp7)))
1400 ;; (augmult (mul b b (list '(rat) -1 8)
1401 ;; (power c -3)
1402 ;; (inv p)
1403 ;; (power exp4
1404 ;; (* -2 p)))))
1405 (add (augmult (mul (inv (power c (add p 1//2)))
1406 (power exp4 exp6)
1407 (inv exp6)))
1408 (augmult (mul -1 b
1409 (inv (power c (add p (div 3 2))))
1410 (inv exp7)
1411 (power exp4 exp7)))
1412 (augmult (mul b b '((rat simp) -1 8)
1413 (inv (power c (add p (div 5 2))))
1414 (inv p)
1415 (power exp4
1416 (* -2 p)))))))
1417 (when (= controlpow 2)
1418 ;; x^2/R^(p+1/2)
1420 ;; We computed this result above, so just multiply by
1421 ;; the coefficient and add it to the result.
1422 (setq result (add result (augmult (mul coef res2)))
1423 count 3)
1424 (go loop))
1425 jump3
1426 (setq count 4
1427 m 3)
1428 jump
1429 ;; coef*x^m/R^(p+1/2). m >= 3
1430 (setq partres
1431 (let ((denom (+ p p (- m))))
1432 ;; denom = 2*p-m
1434 ;; G&R 2.263, eq 1:
1436 ;; integrate(x^m/sqrt(R^(2*p+1)),x) =
1437 ;; x^(m-1)/c/(m-2*p)/sqrt(R^(2*p-1))
1438 ;; - b*(2*m-2*p-1)/2/(m-2*p)*integrate(x^(m-1)/sqrt(R^(2*p+1)),x)
1439 ;; + (m-1)*a/(m-2*p)/c*integrate(x^(m-2)/sqrt(R^(2*p+1)),x)
1441 ;; The two integrals here were computed above in res2
1442 ;; and res1, respectively.
1443 (add (augmult (mul* (power x (1- m))
1444 ec-1 (div -1 denom)
1445 (power (polfoo c b a x)
1446 (add 1//2 (- p)))))
1447 (augmult (mul b (+ p p 1 (* -2 m))
1448 -1//2
1449 ec-1 (inv denom) res2))
1450 (augmult (mul a (1- m) ec-1 (inv denom) res1)))))
1452 ;; Move on to next higher power
1453 (incf m)
1454 (when (> m controlpow)
1455 (setq result (add result (augmult (mul coef partres))))
1456 (go loop))
1457 jump4
1458 (setq res1 res2
1459 res2 partres)
1460 (when (= m (+ p p))
1461 (setq partres
1462 (let ((expr (nummdenn (list (list (1- m) 1)) p c b a x ec-1)))
1463 (add (mul x expr)
1464 (mul -1 (distrint (cdr ($expand expr)) x)))))
1465 (go on))
1466 (go jump)
1467 loop
1468 ;; Done with first term of polynomial. Exit if we're done.
1469 (setq poszpowlist (cdr poszpowlist))
1470 (when (null poszpowlist) (return result))
1471 (setq coef (cadar poszpowlist) controlpow (caar poszpowlist))
1472 (when (= count 4) (go jump4))
1473 (when (= count 1) (go jump1))
1474 (when (= count 2) (go jump2))
1475 (go jump3))))
1477 ;; Integrate functions of the form coef*R^(pow-1/2)/x^m. NEGPOWLIST
1478 ;; contains the list of coef's and m's.
1479 (defun denmnumn (negpowlist pow c b a x ec-1)
1480 (let ((exp1 (inv x)) ;; exp1 = 1/x
1481 (exp2 (+ pow pow -1))) ;; exp2 = 2*pow-1
1482 (prog (result controlpow coef count res1 res2 m partres signa ea-1
1483 (p (+ pow pow -1))) ;; p = 2*pow-1.
1484 ;; NOTE: p is not the same here as in other routines!
1485 ;; Why is there this special case for negpowlist?
1486 ;; CASE1 calls this in this way.
1487 (when (eq (car negpowlist) 't)
1488 (setq negpowlist (cdr negpowlist))
1489 (go there))
1490 (setq signa (checksigntm (power a 2)))
1491 (when (eq signa '$zero)
1492 (return (nonconstquadenum negpowlist p c b x ec-1)))
1493 (setq ea-1 (inv a))
1494 there
1495 (setq result 0
1496 controlpow (caar negpowlist)
1497 coef (cadar negpowlist))
1498 (when (zerop controlpow)
1499 ;; integrate(sqrt(R)).
1500 ;; I don't think we can normally get here.
1501 (setq result (augmult (mul coef
1502 (numn (add (mul p 1//2) 1//2)
1503 c b a x ec-1)))
1504 count 1)
1505 (go loop))
1506 jump1
1507 ;; Handle integrate(sqrt(R^(2*pow-1))/x),x
1508 (setq res1 (den1numn pow c b a x ec-1))
1509 (when (equal controlpow 1)
1510 (setq result (add result (augmult (mul coef res1)))
1511 count 2)
1512 (go loop))
1513 jump2
1514 ;; Handle integrate(sqrt(R^(2*pow-1))/x^2,x)
1515 (unless (= p 1)
1516 ;; integrate(sqrt(R^(2*pow-1))/x^2,x)
1518 ;; We can use integration by parts to get
1520 ;; integrate(sqrt(R^(2*pow-1))/x^2,x) =
1521 ;; -R^(pow-1/2)/x
1522 ;; + (2*pow-1)*b/2*integrate(sqrt(R^(2*pow-3))/x,x)
1523 ;; + (2*pow-1)*c*integrate(sqrt(R^(2*pow-3)),x)
1524 (setq res2
1525 (add (augmult (mul -1 exp1
1526 (power (polfoo c b a x)
1527 (add pow -1//2))))
1528 (augmult (mul b (div exp2 2)
1529 (den1numn (1- pow) c b a x ec-1)))
1530 (augmult (mul c exp2 (numn (- pow 2) c b a x ec-1))))))
1531 (when (= p 1)
1532 ;; integrate(sqrt(R)/x^2,x)
1534 ;; G&R 2.267, eq. 2
1536 ;; integrate(sqrt(R)/x^2,x) =
1537 ;; -sqrt(R)/x
1538 ;; + b/2*integrate(1/x/sqrt(R),x)
1539 ;; + c*integrate(1/sqrt(R),x)
1541 (setq res2 (add (augmult (mul -1 (power (polfoo c b a x) 1//2)
1542 exp1))
1543 (augmult (mul b 1//2 (den1den1 c b a x ec-1)))
1544 (augmult (mul c (den1 c b a x))))))
1545 (when (equal controlpow 2)
1546 (setq result (add result (augmult (mul coef res2)))
1547 count 3)
1548 (go loop))
1549 jump3
1550 (setq count 4
1551 m 3)
1552 jump
1553 ;; The general case sqrt(R^(2*p-1))/x^m
1555 ;; G&R 2.265
1557 ;; integrate(sqrt(R^(2*p-1))/x^m,x) =
1558 ;; -sqrt(R^(2*p+1))/(m-1)/a/x^(m-1)
1559 ;; + (2*p-2*m+3)*b/2/(m-1)/a*integrate(sqrt(R^(2*p-3))/x^(m-1),x)
1560 ;; + (2*p-m+2)*c/(m-1)/a*integrate(sqrt(R^(2*n-3))/x^(m-2),x)
1562 ;; NOTE: The p here is 2*pow-1. And we're
1563 ;; integrating R^(pow-1/2).
1565 (setq partres
1566 (add (augmult (mul (div -1 (1- m))
1567 ea-1
1568 (power x (1+ (- m)))
1569 (power (polfoo c b a x)
1570 (add (div p 2) 1))))
1571 (augmult (mul (inv (+ m m -2))
1572 ea-1 b
1573 (+ p 4 (* -2 m))
1574 res2))
1575 (augmult (mul c ea-1
1576 (+ p 3 (- m))
1577 (inv (1- m)) res1))))
1578 (incf m)
1579 (when (> m controlpow)
1580 (setq result (add result (augmult (mul coef partres))))
1581 (go loop))
1582 jump4
1583 (setq res1 res2
1584 res2 partres)
1585 (go jump)
1586 loop
1587 (setq negpowlist (cdr negpowlist))
1588 (when (null negpowlist) (return result))
1589 (setq coef (cadar negpowlist)
1590 controlpow (caar negpowlist))
1591 (when (= count 4)
1592 (go jump4))
1593 (when (= count 1)
1594 (go jump1))
1595 (when (= count 2)
1596 (go jump2))
1597 (go jump3))))
1599 ;; Like denmnumn, but a = 0.
1600 (defun nonconstquadenum (negpowlist p c b x ec-1)
1601 (prog (result coef m)
1602 (cond ((equal p 1)
1603 (return (case1 negpowlist c b x ec-1))))
1604 (setq result 0)
1605 loop
1606 (setq m (caar negpowlist)
1607 coef (cadar negpowlist))
1608 (setq result (add result (augmult (mul coef (casegen m p c b x ec-1))))
1609 negpowlist (cdr negpowlist))
1610 (cond ((null negpowlist) (return result)))
1611 (go loop)))
1613 ;; Integrate (c*x^2+b*x)^(p-1/2)/x^m
1614 (defun casegen (m p c b x ec-1)
1615 (let ((exp1 (power (polfoo c b 0 x) (div p 2))) ;; exp1 = R^(p/2)
1616 (exp3 (power x (1+ (- m))))) ;; exp3 = 1/x^(m-1)
1617 (cond ((= p 1)
1618 ;; sqrt(c*x^2+b*x)/x^m
1619 (case1 (list (list m 1)) c b x ec-1))
1620 ((zerop m)
1621 ;; (c*x^2+b*x)^(p-1/2)
1622 (case0 p c b x ec-1))
1623 ((= m (1+ p))
1624 ;; (c*x^2+b*x)^(p-1/2)/x^(p+1)
1625 (add (augmult (mul -1 exp1 (inv (1- m)) exp3))
1626 (augmult (mul b 1//2 (casegen (1- m) (- p 2) c b x ec-1)))
1627 (augmult (mul c (casegen (- m 2) (- p 2) c b x ec-1)))))
1628 ((= m 1)
1629 ;; (c*x^2+b*x)^(p-1/2)/x
1631 (add (augmult (mul (inv p) exp1))
1632 (augmult (mul b 1//2 (case0 (- p 2) c b x ec-1)))))
1634 ;; (c*x^2+b*x)^(p-1/2)/x^m
1635 (add (augmult (mul -1 exp1 (inv (- m (1+ p))) exp3))
1636 (augmult (mul -1 p b 1//2 (inv (- m (1+ p)))
1637 (casegen (1- m) (- p 2) c b x ec-1))))))))
1639 ;; Integrate things like sqrt(c*x^2+b*x))/x^m.
1640 (defun case1 (negpowlist c b x ec-1)
1641 (let ((exp1 (power c -1//2)) ;; exp1 = 1/sqrt(c)
1642 (eb-1 (inv b))) ;; eb-1 = 1/b
1643 (prog ((result 0) (controlpow (caar negpowlist)) (coef (cadar negpowlist))
1644 m1 count res1 res2 m signc signb partres res)
1645 (setq m1 (- controlpow 2))
1646 (when (zerop controlpow)
1647 (setq result (augmult (mul coef (case0 1 c b x ec-1)))
1648 count 1)
1649 (go loop))
1650 jump1
1651 ;; sqrt(R)/x
1652 (when (= controlpow 1)
1653 (setq result
1654 (add result
1655 (augmult (mul coef (den1numn 1 c b 0 x ec-1))))
1656 count 2)
1657 (go loop))
1658 jump2
1659 ;; sqrt(R)/x^2
1660 (when (= controlpow 2)
1661 (setq result
1662 (add result
1663 (augmult (mul coef
1664 (denmnumn '(t (2 1)) 1 c b 0 x ec-1))))
1665 count 3)
1666 (go loop))
1667 jump3
1668 (setq signb (checksigntm (power b 2)))
1669 (when (eq signb '$zero)
1670 (setq count 5)
1671 (go jump5))
1672 (setq count 4
1674 signc (checksigntm ec-1))
1675 (when (eq signc '$positive)
1676 (setq res
1677 (augmult (mul* 2 exp1
1678 `((%log)
1679 ,(add (power (mul c x) 1//2)
1680 (power (add b (mul c x)) 1//2))))))
1681 (go jump4))
1682 (setq res
1683 (augmult (mul* 2 exp1
1684 `((%atan)
1685 ,(power (mul c x
1686 (inv (add b (mul -1 c x))))
1687 1//2)))))
1688 jump4
1689 (incf m)
1690 (setq res (add (augmult (mul -2 (power (polfoo c b 0 x) 1//2)
1691 eb-1 (inv (+ m m -1))
1692 (power x (- m))))
1693 (augmult (mul (div -2 (+ m m -1))
1694 c (1- m) eb-1 res))))
1695 (when (= m m1)
1696 (setq res2 res)
1697 (go jump4))
1698 (when (= (1- m) m1)
1699 (if (null res2)
1700 (return nil))
1701 (setq res1 res
1702 partres (add (augmult (mul -1
1703 (power (polfoo c b 0 x) 1//2)
1704 (r1m m)
1705 (power x (- m))))
1706 (augmult (mul b 1//2 (r1m m) res1))
1707 (augmult (mul c (r1m m) res2))))
1708 (go on))
1709 (go jump4)
1710 jump5
1711 (setq m controlpow)
1712 (when (zerop m)
1713 (setq partres (mul* exp1 `((%log) ,x)))
1714 (go on))
1715 (setq partres (mul -1 exp1 (power x (- m)) (r1m m)))
1717 (setq result (add result (augmult (mul coef partres))))
1718 loop
1719 (setq negpowlist (cdr negpowlist))
1720 (when (null negpowlist) (return result))
1721 (setq coef (cadar negpowlist)
1722 controlpow (caar negpowlist))
1723 (when (= count 5) (go jump5))
1724 (when (= count 1) (go jump1))
1725 (when (= count 2) (go jump2))
1726 (when (= count 3) (go jump3))
1727 (setq m1 (- controlpow 2))
1728 (when (= m1 m)
1729 (setq res2 res1))
1730 (go jump4))))
1732 (defun r1m (m)
1733 (div 1 m))
1735 ;; Integrate (c*x^2+b*x)^(p-1/2)
1736 (defun case0 (power c b x ec-1)
1737 (let ((exp1 '((rat simp) 1 4))
1738 (exp2 (add b (mul 2 c x)))
1739 (exp3 (power c '((rat simp) -3 2)))
1740 (exp4 (add (mul 2 c x) (mul -1 b))))
1741 ;; exp1 = 1/4
1742 ;; exp2 = b+2*c*x
1743 ;; exp3 = 1/c^(3/2)
1744 ;; exp4 = 2*c*x-b
1745 (prog (signc p result)
1746 (setq signc (checksigntm ec-1)
1747 p 1)
1748 ;; sqrt(c*x^2+b*x)
1750 ;; This could be handled by numn. Why don't we?
1751 (when (eq signc '$positive)
1752 (setq result
1753 (add (augmult (mul exp1 ec-1 exp2
1754 (power (polfoo c b 0 x) 1//2)))
1755 (augmult (mul* b b '((rat) -1 8)
1756 exp3
1757 `((%log)
1758 ,(add exp2
1759 (mul 2
1760 (power c 1//2)
1761 (power (polfoo c b 0 x) 1//2)))))))))
1762 (when (eq signc '$negative)
1763 (setq result
1764 (add (augmult (mul exp1 ec-1 exp4
1765 (power (polfoo (mul -1 c) b 0 x) 1//2)))
1766 (augmult (mul* b b '((rat) 1 8)
1767 exp3
1768 `((%asin) ,(mul (inv b) exp4)))))))
1769 loop
1770 (when (equal power p) (return result))
1771 (incf p 2)
1773 ;; integrate(sqrt(R^(2*n+1)),x) =
1774 ;; (2*c*x+b)/4/(n+1)/c*sqrt(R^(2*n+1))
1775 ;; + (2*n+1)*del/8/(n+1)/c*integrate(sqrt(R^(2*n-1)),x)
1777 (setq result (add (augmult (mul 1//2 ec-1 (inv (1+ p)) exp2
1778 (power (polfoo c b 0 x)
1779 (div p 2))))
1780 (augmult (mul p b b '((rat simp) -1 4)
1781 ec-1 (inv (1+ p)) result))))
1782 (go loop))))
1784 ;; Integrate R^(p-1/2)/x, p >= 1.
1785 (defun den1numn (p c b a x ec-1)
1786 (cond ((= p 1)
1787 ;; integrate(sqrt(R)/x,x)
1789 ;; G&R 2.267 eq. 1
1791 ;; integrate(sqrt(R)/x,x) =
1792 ;; sqrt(R)
1793 ;; + a*integrate(1/x/sqrt(R),x)
1794 ;; + b/2*integrate(1/sqrt(R),x)
1795 (add (power (polfoo c b a x) 1//2)
1796 (augmult (mul a (den1den1 c b a x ec-1)))
1797 (augmult (mul b 1//2 (den1 c b a x)))))
1799 ;; General case
1801 ;; G&R 2.265
1803 ;; integrate(sqrt(R^(2*p-1)/x,x) =
1804 ;; R^(p-1/2)/(2*p-1)
1805 ;; + b/2*integrate(sqrt(R^(2*p-3)),x)
1806 ;; + a*integrate(sqrt(2^(2*p-3))/x,x)
1807 (add (augmult (mul (power (polfoo c b a x)
1808 (add p -1//2))
1809 (inv (+ p p -1))))
1810 (augmult (mul a (den1numn (+ p -1) c b a x ec-1)))
1811 (augmult (mul b 1//2 (numn (+ p -2) c b a x ec-1)))))))
1813 ;; L is a list of expressions that INTIRA should be applied to.
1814 ;; Sum up the results of applying INTIRA to each.
1815 (defun distrint (l x)
1816 (addn (mapcar #'(lambda (e)
1817 (let ((ie (intira e x)))
1818 (if ie
1820 `((%integrate simp) ,e ,x))))