Bug fix: simplode on a singleton list could return a non-string
[maxima.git] / src / sin.lisp
blobbbff4cda2086061278ed2c8a1fb516217a43b9d3
1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancments. ;;;;;
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 sin)
15 ;;; Reference: J. Moses, Symbolic Integration, MIT-LCS-TR-047, 12-1-1967.
16 ;;; http://www.lcs.mit.edu/publications/pubs/pdf/MIT-LCS-TR-047.pdf.
17 ;;;;
18 ;;;; Unfortunately, some important pages in the scan are all black.
19 ;;;;
20 ;;;; A version with the missing pages is available (2008-12-14) from
21 ;;;; http://www.softwarepreservation.org/projects/LISP/MIT
23 (declare-top (special $radexpand $%e_to_numlog ans arcpart coef
24 aa powerlist *a* *b* k stack e w y expres arg var
25 *powerl* *c* *d* exp varlist genvar $liflag $opsubst))
27 (defvar *debug-integrate* nil
28 "Enable debugging for the integrator routines.")
30 ;; When T do not call the risch integrator. This flag can be set by the risch
31 ;; integrator to avoid endless loops when calling the integrator from risch.
32 (defvar *in-risch-p* nil)
34 (defmacro op (frob)
35 `(get ,frob 'operators))
37 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
39 ;;; Predicate functions
41 (declaim (inline varp))
42 (defun varp (x)
43 (alike1 x var))
45 (defun integerp1 (x)
46 "Returns 2*x if 2*x is an integer, else nil"
47 (integerp2 (mul2* 2 x)))
49 (defun integerp2 (x)
50 "Returns x if x is an integer, else false"
51 (let (u)
52 (cond ((not (numberp x)) nil)
53 ((not (floatp x)) x)
54 ((prog2 (setq u (maxima-rationalize x))
55 (equal (cdr u) 1)) (car u)))))
57 ;; This predicate is used with m2 pattern matcher.
58 ;; A rational expression in var.
59 (defun rat8 (ex)
60 (cond ((or (varp ex) (freevar ex))
62 ((member (caar ex) '(mplus mtimes) :test #'eq)
63 (do ((u (cdr ex) (cdr u)))
64 ((null u) t)
65 (if (not (rat8 (car u)))
66 (return nil))))
67 ((not (eq (caar ex) 'mexpt))
68 nil)
69 ((integerp (caddr ex))
70 (rat8 (cadr ex)))))
72 (defun rat8prime (c)
73 (and (rat8 c)
74 (or (not (mnump c))
75 (not (zerop1 c)))))
77 (defun elem (a)
78 (cond ((freevar a) t)
79 ((atom a) nil)
80 ((m2 a expres) t)
81 (t (every #'elem (cdr a)))))
83 (defun freevar (a)
84 (cond ((atom a) (not (eq a var)))
85 ((varp a) nil)
86 ((and (not (atom (car a)))
87 (member 'array (cdar a) :test #'eq))
88 (cond ((freevar (cdr a)) t)
89 (t (merror "~&FREEVAR: variable of integration appeared in subscript."))))
90 (t (and (freevar (car a)) (freevar (cdr a))))))
92 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
94 ;; possibly a bug: For var = x and *d* =3, we have expand(?subst10(x^9 * (x+x^6))) --> x^5+x^4, but
95 ;; ?subst10(expand(x^9 * (x+x^6))) --> x^5+x^3. (Barton Willis)
97 (defun subst10 (ex)
98 (cond ((atom ex) ex)
99 ((and (eq (caar ex) 'mexpt) (eq (cadr ex) var))
100 (list '(mexpt) var (integerp2 (quotient (caddr ex) *d*))))
101 (t (cons (remove 'simp (car ex))
102 (mapcar #'(lambda (c) (subst10 c)) (cdr ex))))))
104 (defun rationalizer (x)
105 (let ((ex (simplify ($factor x))))
106 (if (not (alike1 ex x)) ex)))
108 ;; Like FIND-IF, but calls FUNC on elements of SEQ in turn until one returns
109 ;; non-NIL. At that point, return the result (rather than the input, which is
110 ;; what you'd get from FIND-IF)
112 (defun map-find (func seq)
113 (map nil (lambda (x)
114 (let ((result (funcall func x)))
115 (when result (return-from map-find result))))
116 seq))
118 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
120 ;;; Stage II of the Integrator
122 ;;; Check if the problem can be transformed or solved by special methods.
123 ;;; 11 Methods are implemented by Moses, some more have been added.
125 (defun intform (expres &aux w)
126 (cond ((freevar expres) nil)
127 ((atom expres) nil)
129 ;; Map the function intform over the arguments of a sum or a product
130 ((member (caar expres) '(mplus mtimes) :test #'eq)
131 (map-find #'intform (cdr expres)))
133 ((or (eq (caar expres) '%log)
134 (arcp (caar expres)))
135 (cond
136 ;; Method 9: Rational function times a log or arctric function
137 ((setq arg (m2 exp
138 `((mtimes) ((,(caar expres)) (b rat8))
139 ((coefftt) (c rat8prime)))))
140 ;; Integrand is of the form R(x)*F(S(x)) where F is a log, or
141 ;; arctric function and R(x) and S(x) are rational functions.
142 (ratlog exp var (cons (cons 'a expres) arg)))
144 (prog (y z)
145 (cond
146 ((setq y (intform (cadr expres))) (return y))
148 ;; Method 10: Rational function times log(b*x+a)
149 ((and (eq (caar expres) '%log)
150 (setq z (m2-b*x+a (cadr expres)))
151 (setq y (m2 exp
152 '((mtimes)
153 ((coefftt) (c rat8))
154 ((coefftt) (d elem))))))
155 (return
156 (let ((a (cdr (assoc 'a z :test #'eq)))
157 (b (cdr (assoc 'b z :test #'eq)))
158 (c (cdr (assoc 'c y :test #'eq)))
159 (d (cdr (assoc 'd y :test #'eq)))
160 (newvar (gensym "intform")))
161 ;; keep var from appearing in questions to user
162 (putprop newvar t 'internal)
163 ;; Substitute y = log(b*x+a) and integrate again
164 (substint
165 expres
166 newvar
167 (integrator
168 (muln
169 (list (maxima-substitute
170 `((mquotient) ((mplus) ((mexpt) $%e ,newvar)
171 ((mtimes) -1 ,a))
175 `((mquotient) ((mexpt) $%e ,newvar) ,b)
176 (maxima-substitute newvar expres d))
177 nil)
178 newvar)))))
179 (t (return nil)))))))
181 ;; We have a special function with an integral on the property list.
182 ;; After the integral property was defined for the trig functions,
183 ;; in rev 1.52, need to exclude trig functions here.
184 ((and (not (atom (car expres)))
185 (not (optrig (caar expres)))
186 (not (eq (caar expres) 'mexpt))
187 (get (caar expres) 'integral))
188 (when *debug-integrate*
189 (format t "~&INTFORM: found 'INTEGRAL on property list~%"))
190 (cond
191 ((setq arg
192 (m2 exp `((mtimes) ((,(caar expres)) (b rat8)) ((coefftt) (c rat8prime)))))
193 ;; A rational function times the special function.
194 ;; Integrate with the method integration-by-parts.
195 (partial-integration (cons (cons 'a expres) arg) var))
196 ;; The method of integration-by-parts can not be applied.
197 ;; Maxima tries to get a clue for the argument of the function which
198 ;; allows a substitution for the argument.
199 ((intform (cadr expres)))
200 (t nil)))
202 ;; Method 6: Elementary function of trigonometric functions
203 ((optrig (caar expres))
204 (cond ((not (setq w (m2-b*x+a (cadr expres))))
205 (intform (cadr expres)))
207 (prog2
208 (setq *powerl* t)
209 (monstertrig exp var (cadr expres))))))
211 ((and (eq (caar expres) '%derivative)
212 (eq (caar exp) (caar expres))
213 (checkderiv exp)))
215 ;; Stop intform if we have not a power function.
216 ((not (eq (caar expres) 'mexpt)) nil)
218 ;; Method 2: Substitution for an integral power
219 ((integerp (caddr expres)) (intform (cadr expres)))
221 ;; Method 1: Elementary function of exponentials
222 ((freevar (cadr expres))
223 (cond ((setq w (m2-b*x+a (caddr expres)))
224 (superexpt exp var (cadr expres) w))
225 ((intform (caddr expres)))
226 ((and (eq '$%e (cadr expres))
227 (isinop (caddr expres) '%log))
228 ;; Found something like exp(r*log(x))
229 (let* (($%e_to_numlog t)
230 ($radexpand nil) ; do not simplify sqrt(x^2) -> abs(x)
231 (nexp (resimplify exp)))
232 (cond ((alike1 exp nexp) nil)
233 (t (integrator (setq exp nexp) var)))))
234 (t nil)))
236 ;; The base is not a rational function. Try to get a clue for the base.
237 ((not (rat8 (cadr expres)))
238 (intform (cadr expres)))
240 ;; Method 3: Substitution for a rational root
241 ((and (setq w (m2-ratrootform (cadr expres))) ; e*(a*x+b) / (c*x+d)
242 (denomfind (caddr expres))) ; expon is ratnum
243 (or (progn
244 (setq *powerl* t)
245 (ratroot exp var (cadr expres) w))
246 (inte exp var)))
248 ;; Method 4: Binomial - Chebyschev
249 ((not (integerp1 (caddr expres))) ; 2*exponent not integer
250 (cond ((m2-chebyform exp)
251 (chebyf exp var))
252 (t (intform (cadr expres)))))
254 ;; Method 5: Arctrigonometric substitution
255 ((setq w (m2-c*x^2+b*x+a (cadr expres))) ; sqrt(c*x^2+b*x+a)
256 #+nil
257 (format t "expres = sqrt(c*x^2+b*x+a)~%")
258 ;; I think this is method 5, arctrigonometric substitutions.
259 ;; (Moses, pg 80.) The integrand is of the form
260 ;; R(x,sqrt(c*x^2+b*x+a)). This method first eliminates the b
261 ;; term of the quadratic, and then uses an arctrig substitution.
262 (inte exp var))
264 ;; Method 4: Binomial - Chebyschev
265 ((m2-chebyform exp )
266 (chebyf exp var))
268 ;; Expand expres.
269 ;; Substitute the expanded factor into the integrand and try again.
270 ((not (m2 (setq w ($expand (cadr expres)))
271 (cadr expres)))
272 (prog2
273 (setq exp (maxima-substitute w (cadr expres) exp))
274 (intform (simplify (list '(mexpt) w (caddr expres))))))
276 ;; Factor expres.
277 ;; Substitute the factored factor into the integrand and try again.
278 ((setq w (rationalizer (cadr expres)))
279 ;; The forms below used to have $radexpand set to $all. But I
280 ;; don't think we really want to do that here because that makes
281 ;; sqrt(x^2) become x, which might be totally wrong. This is one
282 ;; reason why we returned -4/3 for the
283 ;; integrate(sqrt(x+1/x-2),x,0,1). We were replacing
284 ;; sqrt((x-1)^2) with x - 1, which is totally wrong since 0 <= x
285 ;; <= 1.
286 (setq exp (let (($radexpand $radexpand))
287 (maxima-substitute w (cadr expres) exp)))
288 (intform (let (($radexpand '$all))
289 (simplify (list '(mexpt) w (caddr expres))))))))
291 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
293 (defun separc (ex)
294 (cond ((arcfuncp ex) (setq arcpart ex coef 1))
295 ((and (consp ex) (eq (caar ex) 'mtimes))
296 (arclist (cdr ex))
297 (setq coef (cond ((null (cdr coef)) (car coef))
298 (t (setq coef (cons (car ex) coef))))))))
300 (defun arclist (list)
301 (cond ((null list) nil)
302 ((and (arcfuncp (car list)) (null arcpart))
303 (setq arcpart (car list)) (arclist (cdr list)))
304 (t (setq coef (cons (car list) coef))
305 (arclist (cdr list)))))
307 (defun arcfuncp (ex)
308 (and (not (atom ex))
309 (or (arcp (caar ex))
310 (eq (caar ex) '%log) ; Experimentally treat logs also.
311 (and (eq (caar ex) 'mexpt)
312 (integerp2 (caddr ex))
313 (> (integerp2 (caddr ex)) 0)
314 (arcfuncp (cadr ex))))))
316 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
318 ;;; Five pattern for the Integrator and other routines.
320 ;; This is matching the pattern e*(a*x+b)/(c*x+d), where
321 ;; a, b, c, d, and e are free of x, and x is the variable of integration.
322 (defun m2-ratrootform (expr)
323 (m2 expr
324 `((mtimes)
325 ((coefftt) (e freevar))
326 ((mplus)
327 ((coeffpt) (a freevar) (var varp))
328 ((coeffpt) (b freevar)))
329 ((mexpt)
330 ((mplus)
331 ((coeffpt) (c freevar) (var varp))
332 ((coeffpt) (d freevar)))
333 -1))))
335 ;; This is for matching the pattern a*x^r1*(c1+c2*x^q)^r2.
336 (defun m2-chebyform (expr)
337 (m2 expr
338 `((mtimes)
339 ((mexpt) (var varp) (r1 numberp))
340 ((mexpt)
341 ((mplus)
342 ((mtimes)
343 ((coefftt) (c2 freevar))
344 ((mexpt) (var varp) (q free1)))
345 ((coeffpp) (c1 freevar)))
346 (r2 numberp))
347 ((coefftt) (a freevar)))))
349 ;; Pattern to match b*x + a
350 (defun m2-b*x+a (expr)
351 (m2 expr
352 `((mplus)
353 ((coeffpt) (b freevar) (x varp))
354 ((coeffpt) (a freevar)))))
356 ;; This is the pattern c*x^2 + b * x + a.
357 (defun m2-c*x^2+b*x+a (expr)
358 (m2 expr
359 `((mplus)
360 ((coeffpt) (c freevar) ((mexpt) (x varp) 2))
361 ((coeffpt) (b freevar) (x varp))
362 ((coeffpt) (a freevar)))))
364 ;; This is the pattern (a*x+b)*(c*x+d)
365 (defun m2-a*x+b/c*x+d (expr)
366 (m2 expr
367 `((mtimes)
368 ((mplus)
369 ((coeffpt) (a freevar) (var varp))
370 ((coeffpt) (b freevar)))
371 ((mplus)
372 ((coeffpt) (c freevar) (var varp))
373 ((coeffpt) (d freevar))))))
375 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
377 ;;; This is the main integration routine. It is called from sinint.
379 (defun integrator (exp var)
380 (prog (y arg *powerl* const *b* w arcpart coef integrand result)
381 (declare (special *integrator-level*))
382 ;; Increment recursion counter
383 (incf *integrator-level*)
385 ;; Trivial case. exp is not a function of var.
386 (if (freevar exp) (return (mul2* exp var)))
388 ;; Remove constant factors
389 (setq w (partition exp var 1))
390 (setq const (car w))
391 (setq exp (cdr w))
392 #+nil
393 (progn
394 (format t "w = ~A~%" w)
395 (format t "const = ~A~%" const)
396 (format t "exp = ~A~%" exp))
398 (cond ;; First stage, Method I: Integrate a sum.
399 ((mplusp exp)
400 (return (mul2* const (integrate1 (cdr exp)))))
402 ;; Convert atan2(a,b) to atan(a/b) and try again.
403 ((setq w (isinop exp '$atan2))
404 (setq exp
405 (maxima-substitute (take '(%atan) (div (cadr w) (caddr w)))
407 exp))
408 (return (mul* const
409 (integrator exp var))))
411 ;; First stage, Method II: Integrate sums.
412 ((and (not (atom exp))
413 (eq (caar exp) '%sum))
414 (return (mul2* const (intsum exp var))))
416 ;; First stage, Method III: Try derivative-divides method.
417 ;; This is the workhorse that solves many integrals.
418 ((setq y (diffdiv exp var))
419 (return (mul2* const y))))
421 ;; At this point, we have EXP as a product of terms. Make Y a
422 ;; list of the terms of the product.
423 (setq y (cond ((mtimesp exp)
424 (cdr exp))
426 (list exp))))
428 ;; Second stage:
429 ;; We're looking at each term of the product and check if we can
430 ;; apply one of the special methods.
431 loop
432 #+nil
433 (progn
434 (format t "car y =~%")
435 (maxima-display (car y)))
436 (cond ((rat8 (car y))
437 #+nil
438 (format t "In loop, go skip~%")
439 (go skip))
440 ((and (setq w (intform (car y)))
441 ;; Do not return a noun form as result at this point, because
442 ;; we would like to check for further special integrals.
443 ;; We store the result for later use.
444 (setq result w)
445 (not (isinop w '%integrate)))
446 #+nil
447 (format t "In loop, case intform~%")
448 (return (mul2* const w)))
450 #+nil
451 (format t "In loop, go special~%")
452 ;; Store a possible partial result
453 (setq result w)
454 (go special)))
455 skip
456 (setq y (cdr y))
457 (cond ((null y)
458 ;; Method 8: Rational functions
459 (return (mul2* const (cond ((setq y (powerlist exp var)) y)
460 (t (ratint exp var)))))))
461 (go loop)
463 special
464 ;; Third stage: Try more general methods
466 ;; SEPARC SETQS ARCPART AND COEF SUCH THAT
467 ;; COEF*ARCEXP=EXP WHERE ARCEXP IS OF THE FORM
468 ;; ARCFUNC^N AND COEF IS ITS ALGEBRAIC COEFFICIENT
469 (separc exp)
471 #+nil
472 (progn
473 (format t "arcpart = ~A~%" arcpart)
474 (format t "coef =~%")
475 (maxima-display coef))
476 (cond ((and (not (null arcpart))
477 (do ((stacklist stack (cdr stacklist)))
478 ((null stacklist) t)
479 (cond ((alike1 (car stacklist) coef)
480 (return nil))))
481 (not (isinop (setq w (let ((stack (cons coef stack)))
482 (integrator coef var)))
483 '%integrate))
484 (setq integrand (mul2 w (sdiff arcpart var)))
485 (do ((stacklist stack (cdr stacklist)))
486 ((null stacklist) t)
487 (cond ((alike1 (car stacklist) integrand)
488 (return nil))))
489 (not (isinop
490 (setq y (let ((stack (cons integrand stack))
491 (integ integrand))
492 (integrator integ var)))
493 '%integrate)))
494 (return (add* (list '(mtimes) const w arcpart)
495 (list '(mtimes) -1 const y))))
497 (return
498 (mul* const
499 (cond ((setq y (scep exp var))
500 (cond ((cddr y)
501 #+nil
502 (progn
503 (format t "cddr y =~%")
504 (maxima-display (cddr y)))
505 (integrator ($trigreduce exp) var))
506 (t (sce-int (car y) (cadr y) var))))
507 ;; I don't understand why we do this. This
508 ;; causes the stack overflow in Bug
509 ;; 1487703, because we keep expanding exp
510 ;; into a form that matches the original
511 ;; and therefore we loop forever. To
512 ;; break this we keep track how how many
513 ;; times we've tried this and give up
514 ;; after 4 (arbitrarily selected) times.
515 ((and (< *integrator-level* 4)
516 (not (alike1 exp (setq y ($expand exp)))))
517 #+nil
518 (progn
519 (format t "exp = ~A~%" exp)
520 (maxima-display exp)
521 (format t "y = ~A~%" y)
522 (maxima-display y)
523 (break))
524 (integrator y var))
525 ((and (not *powerl*)
526 (setq y (powerlist exp var)))
528 ((and (not *in-risch-p*) ; Not called from rischint
529 (setq y (rischint exp var))
530 ;; rischint has not found an integral but
531 ;; returns a noun form. Do not return that
532 ;; noun form as result at this point, but
533 ;; store it for later use.
534 (setq result y)
535 (not (isinop y '%integrate)))
537 ((setq y (integrate-exp-special exp var))
538 ;; Maxima found an integral for a power function
541 ;; Integrate-exp-special has not found an integral
542 ;; We look for a previous result obtained by
543 ;; intform or rischint.
544 (if result
545 result
546 (list '(%integrate) exp var))))))))))
548 (defun optrig (x)
549 (member x '(%sin %cos %sec %tan %csc %cot) :test #'eq))
551 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
553 ;;; Stage I
554 ;;; Implementation of Method 1: Integrate a sum
556 ;;after finding a non-integrable summand usually better to pass rest to risch
557 (defun integrate1 (exp)
558 (do ((terms exp (cdr terms)) (ans))
559 ((null terms) (addn ans nil))
560 (let ($liflag) ; don't gen li's for
561 (push (integrator (car terms) var) ans)) ; parts of integrand
562 (when (and (not *in-risch-p*) ; Not called from rischint
563 (not (free (car ans) '%integrate))
564 (cdr terms))
565 (return (addn (cons (rischint (cons '(mplus) terms) var) (cdr ans))
566 nil)))))
568 (defun scep (expr var &aux trigl exp) ; Product of SIN, COS, EXP
569 (and (mtimesp expr) ; of linear args.
570 (loop for fac in (cdr expr) do
571 (cond ((atom fac) (return nil))
572 ((trig1 (car fac))
573 (if (linearp (cadr fac) var) (push fac trigl)
574 (return nil)))
575 ((and (mexptp fac)
576 (eq (cadr fac) '$%e)
577 (linearp (caddr fac) var))
578 ;; should be only one exponential factor
579 (setq exp fac))
580 (t (return nil)))
581 finally (return (cons exp trigl)))))
583 ;; Integrates exponential * sin or cos, all with linear args.
585 (defun sce-int (exp s-c var) ; EXP is non-trivial
586 (let* ((e-coef (car (islinear (caddr exp) var)))
587 (sc-coef (car (islinear (cadr s-c) var)))
588 (sc-arg (cadr s-c))
589 (abs-val (add (power e-coef 2) (power sc-coef 2))))
590 (if (zerop1 abs-val)
591 ;; The numerator is zero. Exponentialize the integrand and try again.
592 (integrator ($exponentialize (mul exp s-c)) var)
593 (mul (div exp abs-val)
594 (add (mul e-coef s-c)
595 (if (eq (caar s-c) '%sin)
596 (mul* (neg sc-coef) `((%cos) ,sc-arg))
597 (mul* sc-coef `((%sin) ,sc-arg))))))))
599 (defun checkderiv (expr)
600 (checkderiv1 (cadr expr) (cddr expr) () ))
602 ;; CHECKDERIV1 gets called on the expression being differentiated,
603 ;; an alternating list of variables being differentiated with
604 ;; respect to and powers thereof, and a reversed list of the latter
605 ;; that have already been examined. It returns either the antiderivative
606 ;; or (), saying this derivative isn't wrt the variable of integration.
608 (defun checkderiv1 (expr wrt old-wrt)
609 (cond ((varp (car wrt))
610 (if (equal (cadr wrt) 1) ;Power = 1?
611 (if (null (cddr wrt)) ;single or partial
612 (if (null old-wrt)
613 expr ;single
614 `((%derivative), expr ;partial in old-wrt
615 ,.(nreverse old-wrt)))
616 `((%derivative) ,expr ;Partial, return rest
617 ,.(nreverse old-wrt)
618 ,@(cddr wrt)))
619 `((%derivative) ,expr ;Higher order, reduce order
620 ,.(nreverse old-wrt)
621 ,(car wrt) ,(add* (cadr wrt) -1)
622 ,@ (cddr wrt))))
623 ((null (cddr wrt)) () ) ;Say it doesn't apply here
624 (t (checkderiv1 expr (cddr wrt) ;Else we check later terms
625 (list* (cadr wrt) (car wrt) old-wrt)))))
627 (defun integrallookups (exp)
628 (let (form dummy-args real-args)
629 (cond
630 ((eq (caar exp) 'mqapply)
631 ;; Transform to functional form and try again.
632 ;; For example:
633 ;; ((MQAPPLY SIMP) (($PSI SIMP ARRAY) 1) $X)
634 ;; => (($PSI) 1 $X)
635 (integrallookups `((,(caaadr exp)) ,@(cdadr exp) ,@(cddr exp))))
637 ;; Lookup algorithm for integral of a special function.
638 ;; The integral form is put on the property list, and can be a
639 ;; lisp function of the args. If the form is nil, or evaluates
640 ;; to nil, then return noun form unevaluated.
641 ((and (not (atom (car exp)))
642 (setq form (get (caar exp) 'integral))
643 (setq dummy-args (car form))
644 (setq real-args (cdr exp))
645 ;; search through the args of exp and find the arg containing var
646 ;; look up the integral wrt this arg from form
647 (setq form
648 (do ((x real-args (cdr x))
649 (y (cdr form) (cdr y)))
650 ((or (null x) (null y)) nil)
651 (if (not (freevar (car x))) (return (car y)))))
652 ;; If form is a function then evaluate it with actual args
653 (or (not (functionp form))
654 (setq form (apply form real-args))))
655 (when *debug-integrate*
656 (format t "~&INTEGRALLOOKUPS: Found integral ~A.~%" (caar exp)))
657 (substitutel real-args dummy-args form))
659 ((eq (caar exp) 'mplus)
660 (muln (list '((rat simp) 1 2) exp exp) nil))
662 (t nil))))
664 ;; Define the antiderivatives of some elementary special functions.
665 ;; This may not be the best place for this definition, but it is close
666 ;; to the original code.
667 ;; Antiderivatives that depend on the logabs flag are defined further below.
668 (defprop %log ((x) ((mplus) ((mtimes) x ((%log) x)) ((mtimes) -1 x))) integral)
669 (defprop %sin ((x) ((mtimes) -1 ((%cos) x))) integral)
670 (defprop %cos ((x) ((%sin) x)) integral)
671 (defprop %sinh ((x) ((%cosh) x)) integral)
672 (defprop %cosh ((x) ((%sinh) x)) integral)
673 ;; No need to take logabs into account for tanh(x), because cosh(x) is positive.
674 (defprop %tanh ((x) ((%log) ((%cosh) x))) integral)
675 (defprop %sech ((x) ((%atan) ((%sinh) x))) integral)
676 (defprop %asin ((x) ((mplus) ((mexpt) ((mplus) 1 ((mtimes) -1 ((mexpt) x 2))) ((rat) 1 2)) ((mtimes) x ((%asin) x)))) integral)
677 (defprop %acos ((x) ((mplus) ((mtimes) -1 ((mexpt) ((mplus) 1 ((mtimes) -1 ((mexpt) x 2))) ((rat) 1 2))) ((mtimes) x ((%acos) x)))) integral)
678 (defprop %atan ((x) ((mplus) ((mtimes) x ((%atan) x)) ((mtimes) ((rat) -1 2) ((%log) ((mplus) 1 ((mexpt) x 2)))))) integral)
679 (defprop %acsc ((x) ((mplus) ((mtimes) ((rat) -1 2) ((%log) ((mplus) 1 ((mtimes) -1 ((mexpt) ((mplus) 1 ((mtimes) -1 ((mexpt) x -2))) ((rat) 1 2)))))) ((mtimes) ((rat) 1 2) ((%log) ((mplus) 1 ((mexpt) ((mplus) 1 ((mtimes) -1 ((mexpt) x -2))) ((rat) 1 2))))) ((mtimes) x ((%acsc) x)))) integral)
680 (defprop %asec ((x) ((mplus) ((mtimes) ((rat) 1 2) ((%log) ((mplus) 1 ((mtimes) -1 ((mexpt) ((mplus) 1 ((mtimes) -1 ((mexpt) x -2))) ((rat) 1 2)))))) ((mtimes) ((rat) -1 2) ((%log) ((mplus) 1 ((mexpt) ((mplus) 1 ((mtimes) -1 ((mexpt) x -2))) ((rat) 1 2))))) ((mtimes) x ((%asec) x)))) integral)
681 (defprop %acot ((x) ((mplus) ((mtimes) x ((%acot) x)) ((mtimes) ((rat) 1 2) ((%log) ((mplus) 1 ((mexpt) x 2)))))) integral)
682 (defprop %asinh ((x) ((mplus) ((mtimes) -1 ((mexpt) ((mplus) 1 ((mexpt) x 2)) ((rat) 1 2))) ((mtimes) x ((%asinh) x)))) integral)
683 (defprop %acosh ((x) ((mplus) ((mtimes) -1 ((mexpt) ((mplus) -1 ((mexpt) x 2)) ((rat) 1 2))) ((mtimes) x ((%acosh) x)))) integral)
684 (defprop %atanh ((x) ((mplus) ((mtimes) x ((%atanh) x)) ((mtimes) ((rat) 1 2) ((%log) ((mplus) 1 ((mtimes) -1 ((mexpt) x 2))))))) integral)
685 (defprop %acsch ((x) ((mplus) ((mtimes) ((rat) -1 2) ((%log) ((mplus) -1 ((mexpt) ((mplus) 1 ((mexpt) x -2)) ((rat) 1 2))))) ((mtimes) ((rat) 1 2) ((%log) ((mplus) 1 ((mexpt) ((mplus) 1 ((mexpt) x -2)) ((rat) 1 2))))) ((mtimes) x ((%acsch) x)))) integral)
686 (defprop %asech ((x) ((mplus) ((mtimes) -1 ((%atan) ((mexpt) ((mplus) -1 ((mexpt) x -2)) ((rat) 1 2)))) ((mtimes) x ((%asech) x)))) integral)
687 (defprop %acoth ((x) ((mplus) ((mtimes) x ((%acoth) x)) ((mtimes) ((rat) 1 2) ((%log) ((mplus) 1 ((mtimes) -1 ((mexpt) x 2))))))) integral)
689 ;; Define a little helper function to be used in antiderivatives.
690 ;; Depending on the logabs flag, it either returns log(x) or log(abs(x)).
691 (defun log-or-logabs (x)
692 (take '(%log) (if $logabs (take '(mabs) x) x)))
694 ;; Define the antiderivative of tan(x), taking logabs into account.
695 (defun integrate-tan (x)
696 (log-or-logabs (take '(%sec) x)))
697 (putprop '%tan `((x) ,#'integrate-tan) 'integral)
699 ;; ... the same for csc(x) ...
700 (defun integrate-csc (x)
701 (mul -1 (log-or-logabs (add (take '(%csc) x) (take '(%cot) x)))))
702 (putprop '%csc `((x) ,#'integrate-csc) 'integral)
704 ;; ... the same for sec(x) ...
705 (defun integrate-sec (x)
706 (log-or-logabs (add (take '(%sec) x) (take '(%tan) x))))
707 (putprop '%sec `((x) ,#'integrate-sec) 'integral)
709 ;; ... the same for cot(x) ...
710 (defun integrate-cot (x)
711 (log-or-logabs (take '(%sin) x)))
712 (putprop '%cot `((x) ,#'integrate-cot) 'integral)
714 ;; ... the same for coth(x) ...
715 (defun integrate-coth (x)
716 (log-or-logabs (take '(%sinh) x)))
717 (putprop '%coth `((x) ,#'integrate-coth) 'integral)
719 ;; ... the same for csch(x) ...
720 (defun integrate-csch (x)
721 (log-or-logabs (take '(%tanh) (mul '((rat simp) 1 2) x))))
722 (putprop '%csch `((x) ,#'integrate-csch) 'integral)
724 ;; integrate(x^n,x) = if n # -1 then x^(n+1)/(n+1) else log-or-logabs(x).
725 (defun integrate-mexpt-1 (x n)
726 (let ((n-is-minus-one ($askequal n -1)))
727 (cond ((eq '$yes n-is-minus-one)
728 (log-or-logabs x))
730 (setq n (add n 1))
731 (div (take '(mexpt) x n) n)))))
733 ;; integrate(a^x,x) = a^x/log(a).
734 (defun integrate-mexpt-2 (a x)
735 (div (take '(mexpt) a x) (take '(%log) a)))
737 (putprop 'mexpt `((x n) ,#'integrate-mexpt-1 ,#'integrate-mexpt-2) 'integral)
739 (defun rat10 (ex)
740 (cond ((freevar ex) t)
741 ((varp ex) nil)
742 ((eq (caar ex) 'mexpt)
743 (if (varp (cadr ex))
744 (if (integerp2 (caddr ex))
745 (setq powerlist (cons (caddr ex) powerlist)))
746 (and (rat10 (cadr ex)) (rat10 (caddr ex)))))
747 ((member (caar ex) '(mplus mtimes) :test #'eq)
748 (do ((u (cdr ex) (cdr u))) ((null u) t)
749 (if (not (rat10 (car u))) (return nil))))))
751 (defun integrate5 (ex var)
752 (if (rat8 ex)
753 (ratint ex var)
754 (integrator ex var)))
756 (defun denomfind (x)
757 (cond ((ratnump x) (caddr x))
758 ((not (numberp x)) nil)
759 ((not (floatp x)) 1)
760 (t (cdr (maxima-rationalize x)))))
762 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
764 ;;; Stage II
765 ;;; Implementation of Method 1: Elementary function of exponentials
767 ;;; The following examples are integrated with this method:
769 ;;; integrate(exp(x)/(2+3*exp(2*x)),x)
770 ;;; integrate(exp(x+1)/(1+exp(x)),x)
771 ;;; integrate(10^x*exp(x),x)
773 (let ((bas nil) ; The common base.
774 (pow nil) ; The common power of the form b*x+a. The values are
775 ; stored in a list which is returned from m2.
776 (exptflag nil)) ; When T, the substitution is not possible.
778 (defun superexpt (exp var bas1 pow1)
779 (prog (y)
780 (setq bas bas1
781 pow pow1
782 exptflag nil)
783 ;; Transform the integrand. At this point resimplify, because it is not
784 ;; guaranteed, that a correct simplified expression is returned.
785 (setq y (resimplify (elemxpt exp)))
786 (when exptflag (return nil))
787 ;; Integrate the transformed integrand and substitute back.
788 (return
789 ($multthru
790 (substint (list '(mexpt) bas
791 (list '(mplus) (cdras 'a pow)
792 (list '(mtimes) (cdras 'b pow) var)))
794 (integrator (div y
795 (mul var
796 (cdras 'b pow)
797 (take '(%log) bas))) var))))))
799 ;; Transform expressions like g^(b*x+a) to the common base bas and
800 ;; do the substitution y = bas^(b*x+a) in the expr.
801 (defun elemxpt (expr &aux w)
802 (cond ((freevar expr) expr)
803 ;; var is the base of a subexpression. The transformation fails.
804 ((atom expr) (setq exptflag t))
805 ((not (eq (caar expr) 'mexpt))
806 (cons (car expr)
807 (mapcar #'(lambda (c) (elemxpt c)) (cdr expr))))
808 ((not (freevar (cadr expr)))
809 (list '(mexpt)
810 (elemxpt (cadr expr))
811 (elemxpt (caddr expr))))
812 ;; Transform the expression to the common base.
813 ((not (eq (cadr expr) bas))
814 (elemxpt (list '(mexpt)
816 (mul (power (take '(%log) bas) -1)
817 (take '(%log) (cadr expr))
818 (caddr expr)))))
819 ;; The exponent must be linear in the variable of integration.
820 ((not (setq w (m2-b*x+a (caddr expr))))
821 (list (car expr) bas (elemxpt (caddr expr))))
822 ;; Do the substitution y = g^(b*x+a).
824 (setq w (cons (cons 'bb (cdras 'b pow)) w))
825 (setq w (cons (cons 'aa (cdras 'a pow)) w))
826 (setq w (cons (cons 'bas bas) w))
827 (subliss w '((mtimes)
828 ((mexpt) bas a)
829 ((mexpt)
831 ((mquotient)
832 ((mtimes) -1 aa b) bb))
833 ((mexpt)
835 ((mquotient) b bb)))))))
836 ) ; End of let
838 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
840 ;;; Stage II
841 ;;; Implementation of Method 3:
842 ;;; Substitution for a rational root of a linear fraction of x
844 ;;; This method is applicable when the integrand is of the form:
846 ;;; /
847 ;;; [ a x + b n1/m1 a x + b n1/m2
848 ;;; I R(x, (-------) , (-------) , ...) dx
849 ;;; ] c x + d c x + d
850 ;;; /
852 ;;; Substitute
854 ;;; (1) t = ((a*x+b)/(c*x+d))^(1/k), or
856 ;;; (2) x = (b-d*t^k)/(c*t^k-a)
858 ;;; where k is the least common multiplier of m1, m2, ... and
860 ;;; (3) dx = k*(a*d-b*c)*t^(k-1)/(a-c*t^k)^2 * dt
862 ;;; First, the algorithm calls the routine RAT3 to collect the roots of the
863 ;;; form ((a*x+b)/(c*x+d))^(n/m) in the list *ROOTLIST*.
864 ;;; search for the least common multiplier of m1, m2, ... then the
865 ;;; substitutions (2) and (3) are done and the new problem is integrated.
866 ;;; As always, W is an alist which associates to the coefficients
867 ;;; a, b... (and to VAR) their values.
869 (defvar *ratroot* nil) ; Expression of the form (a*x+b)/(c*x+d)
870 (defvar *rootlist* nil) ; List of powers of the expression *ratroot*.
872 (defun ratroot (exp var *ratroot* w)
873 (prog (*rootlist* k y w1)
874 ;; Check if the integrand has a chebyform, if so return the result.
875 (when (setq y (chebyf exp var)) (return y))
876 ;; Check if the integrand has a suitably form and collect the roots
877 ;; in the global special variable *ROOTLIST*.
878 (unless (rat3 exp t) (return nil))
879 ;; Get the least common multiplier of m1, m2, ...
880 (setq k (apply #'lcm *rootlist*))
881 (setq w1 (cons (cons 'k k) w))
882 ;; Substitute for the roots.
883 (setq y
884 (subst41 exp
885 (subliss w1
886 '((mquotient)
887 ((mplus) ((mtimes) b e)
888 ((mtimes) -1 d ((mexpt) var k)))
889 ((mplus) ((mtimes) c ((mexpt) var k))
890 ((mtimes) -1 e a))))
891 var))
892 ;; Integrate the new problem.
893 (setq y
894 (integrator
895 (mul y
896 (subliss w1
897 '((mquotient)
898 ((mtimes) e
899 ((mplus)
900 ((mtimes) a d k
901 ((mexpt) var ((mplus) -1 k)))
902 ((mtimes) -1
903 ((mtimes) b c k
904 ((mexpt) var ((mplus) -1 k))))))
905 ((mexpt) ((mplus)
906 ((mtimes) c ((mexpt) var k))
907 ((mtimes) -1 a e))
908 2))))
909 var))
910 ;; Substitute back and return the result.
911 (return (substint (power *ratroot* (power k -1)) var y))))
913 (defun rat3 (ex ind)
914 (cond ((freevar ex) t)
915 ((atom ex) ind)
916 ((member (caar ex) '(mtimes mplus) :test #'eq)
917 (do ((u (cdr ex) (cdr u)))
918 ((null u) t)
919 (if (not (rat3 (car u) ind))
920 (return nil))))
921 ((not (eq (caar ex) 'mexpt))
922 (rat3 (car (margs ex)) t))
923 ((freevar (cadr ex))
924 (rat3 (caddr ex) t))
925 ((integerp (caddr ex))
926 (rat3 (cadr ex) ind))
927 ((and (m2 (cadr ex) *ratroot*)
928 (denomfind (caddr ex)))
929 (setq *rootlist* (cons (denomfind (caddr ex)) *rootlist*)))
930 (t (rat3 (cadr ex) nil))))
932 (let ((rootform nil) ; Expression of the form x = (b*e-d*t^k)/(c*t^k-e*a).
933 (rootvar nil)) ; The variable we substitute for the root.
935 (defun subst4 (ex)
936 (cond ((freevar ex) ex)
937 ((atom ex) rootform)
938 ((not (eq (caar ex) 'mexpt))
939 (mapcar #'(lambda (u) (subst4 u)) ex))
940 ((m2 (cadr ex) *ratroot*)
941 (list (car ex) rootvar (integerp2 (timesk k (caddr ex)))))
942 (t (list (car ex) (subst4 (cadr ex)) (subst4 (caddr ex))))))
944 (defun subst41 (exp a b)
945 (setq rootform a
946 rootvar b)
947 ;; At this point resimplify, because it is not guaranteed, that a correct
948 ;; simplified expression is returned.
949 (resimplify (subst4 exp)))
950 ) ; End of let
952 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
954 ;;; Stage II
955 ;;; Implementation of Method 4: Binomial Chebyschev
957 ;; exp = a*t^r1*(c1+c2*t^q)^r2, where var = t.
959 ;; G&S 2.202 has says this integral can be expressed by elementary
960 ;; functions ii:
962 ;; 1. q is an integer
963 ;; 2. (r1+1)/q is an integer
964 ;; 3. (r1+1)/q+r2 is an integer.
966 ;; I (rtoy) think that for this code to work, r1, r2, and q must be numbers.
967 (defun chebyf (exp var)
968 (prog (r1 r2 d1 d2 n1 n2 w q)
969 ;; Return NIL if the expression doesn't match.
970 (when (not (setq w (m2-chebyform exp)))
971 (return nil))
972 #+nil
973 (format t "w = ~A~%" w)
974 (when (zerop1 (cdr (assoc 'c1 w :test #'eq)))
975 ;; rtoy: Is it really possible to be in this routine with c1 =
976 ;; 0?
977 (return
978 (mul*
979 ;; This factor is locally constant as long as t and
980 ;; c2*t^q avoid log's branch cut.
981 (subliss w '((mtimes) a ((mexpt) var ((mtimes) -1 q r2))
982 ((mexpt) ((mtimes) c2 ((mexpt) var q)) r2)))
983 (integrator
984 (subliss w '((mexpt) var ((mplus) r1 ((mtimes) q r2)))) var))))
985 (setq q (cdr (assoc 'q w :test #'eq)))
986 ;; Reset parameters. a = a/q, r1 = (1 - q + r1)/q
987 (setq w
988 (list* (cons 'a (div* (cdr (assoc 'a w :test #'eq)) q))
989 (cons
991 (div* (addn (list 1 (neg (simplify q)) (cdr (assoc 'r1 w :test #'eq))) nil) q))
993 #+nil
994 (format t "new w = ~A~%" w)
995 (setq r1 (cdr (assoc 'r1 w :test #'eq))
996 r2 (cdr (assoc 'r2 w :test #'eq)))
997 #+nil
998 (progn
999 (format t "new r1 = ~A~%" r1)
1000 (format t "r2 = ~A~%" r2))
1001 ;; Write r1 = d1/n1, r2 = d2/n2, if possible. Update w with
1002 ;; these values, if so. If we can't, give up. I (rtoy) think
1003 ;; this only happens if r1 or r2 can't be expressed as rational
1004 ;; numbers. Hence, r1 and r2 have to be numbers, not variables.
1005 (cond
1006 ((not (and (setq d1 (denomfind r1))
1007 (setq d2 (denomfind r2))
1008 (setq n1 (integerp2 (timesk r1 d1)))
1009 (setq n2 (integerp2 (timesk r2 d2)))
1010 (setq w (list* (cons 'd1 d1) (cons 'd2 d2)
1011 (cons 'n1 n1) (cons 'n2 n2)
1012 w))))
1013 #+nil
1014 (progn
1015 (format t "cheby can't find one of d1,d2,n1,n2:~%")
1016 (format t " d1 = ~A~%" d1)
1017 (format t " d2 = ~A~%" d2)
1018 (format t " n1 = ~A~%" n1)
1019 (format t " n2 = ~A~%" n2))
1020 (return nil))
1021 ((and (integerp2 r1) (> r1 0))
1022 #+nil (format t "integer r1 > 0~%")
1023 ;; (r1+q-1)/q is positive integer.
1025 ;; I (rtoy) think we are using the substitution z=(c1+c2*t^q).
1026 ;; Maxima thinks the resulting integral should then be
1028 ;; a/q*c2^(-r1/q-1/q)*integrate(z^r2*(z-c1)^(r1/q+1/q-1),z)
1030 (return
1031 (substint
1032 (subliss w '((mplus) c1 ((mtimes) c2 ((mexpt) var q))))
1034 (integrator
1035 (expands (list (subliss w
1036 ;; a*t^r2*c2^(-r1-1)
1037 '((mtimes)
1039 ((mexpt) var r2)
1040 ((mexpt)
1042 ((mtimes)
1044 ((mplus) r1 1))))))
1045 (cdr
1046 ;; (t-c1)^r1
1047 (expandexpt (subliss w
1048 '((mplus)
1050 ((mtimes) -1 c1)))
1051 r1)))
1052 var))))
1053 ((integerp2 r2)
1054 #+nil (format t "integer r2~%")
1055 ;; I (rtoy) think this is using the substitution z = t^(q/d1).
1057 ;; The integral (as maxima will tell us) becomes
1059 ;; a*d1/q*integrate(z^(n1/q+d1/q-1)*(c1+c2*z^d1)^r2,z)
1061 ;; But be careful because the variable A in the code is
1062 ;; actually a/q.
1063 (return
1064 (substint (subliss w '((mexpt) var ((mquotient) q d1)))
1066 (ratint (simplify (subliss w
1067 '((mtimes)
1068 d1 a
1069 ((mexpt)
1071 ((mplus)
1072 n1 d1 -1))
1073 ((mexpt)
1074 ((mplus)
1075 ((mtimes)
1077 ((mexpt)
1078 var d1))
1080 r2))))
1081 var))))
1082 ((and (integerp2 r1) (< r1 0))
1083 #+nil (format t "integer r1 < 0~%")
1084 ;; I (rtoy) think this is using the substitution
1086 ;; z = (c1+c2*t^q)^(1/d2)
1088 ;; With this substitution, maxima says the resulting integral
1089 ;; is
1091 ;; a/q*c2^(-r1/q-1/q)*d2*
1092 ;; integrate(z^(n2+d2-1)*(z^d2-c1)^(r1/q+1/q-1),z)
1093 (return
1094 (substint (subliss w
1095 ;; (c1+c2*t^q)^(1/d2)
1096 '((mexpt)
1097 ((mplus)
1099 ((mtimes) c2 ((mexpt) var q)))
1100 ((mquotient) 1 d2)))
1102 (ratint (simplify (subliss w
1103 ;; This is essentially
1104 ;; the integrand above,
1105 ;; except A and R1 here
1106 ;; are not the same as
1107 ;; derived above.
1108 '((mtimes)
1109 a d2
1110 ((mexpt)
1112 ((mtimes)
1114 ((mplus)
1115 r1 1)))
1116 ((mexpt)
1118 ((mplus)
1119 n2 d2 -1))
1120 ((mexpt)
1121 ((mplus)
1122 ((mexpt)
1123 var d2)
1124 ((mtimes) -1 c1))
1125 r1))))
1126 var))))
1127 ((integerp2 (add* r1 r2))
1128 #+nil (format t "integer r1+r2~%")
1129 ;; If we're here, (r1-q+1)/q+r2 is an integer.
1131 ;; I (rtoy) think this is using the substitution
1133 ;; z = ((c1+c2*t^q)/t^q)^(1/d1)
1135 ;; With this substitution, maxima says the resulting integral
1136 ;; is
1138 ;; a*d2/q*c1^(r2+r1/q+1/q)*
1139 ;; integrate(z^(d2*r2+d2-1)*(z^d2-c2)^(-r2-r1/q-1/q-1),z)
1140 (return
1141 (substint (let (($radexpand '$all))
1142 ;; Setting $radexpand to $all here gets rid of
1143 ;; ABS in the subtitution. I think that's ok in
1144 ;; this case. See Bug 1654183.
1145 (subliss w
1146 '((mexpt)
1147 ((mquotient)
1148 ((mplus)
1150 ((mtimes) c2 ((mexpt) var q)))
1151 ((mexpt) var q))
1152 ((mquotient) 1 d1))))
1154 (ratint (simplify (subliss w
1155 '((mtimes)
1156 -1 a d1
1157 ((mexpt)
1159 ((mplus)
1160 r1 r2 1))
1161 ((mexpt)
1163 ((mplus)
1164 n2 d1 -1))
1165 ((mexpt)
1166 ((mplus)
1167 ((mexpt)
1168 var d1)
1169 ((mtimes)
1170 -1 c2))
1171 ((mtimes)
1173 ((mplus)
1174 r1 r2
1175 2))))))
1176 var))))
1177 (t (return (list '(%integrate) exp var))))))
1179 (defun greaterratp (x1 x2)
1180 (cond ((and (numberp x1) (numberp x2))
1181 (> x1 x2))
1182 ((ratnump x1)
1183 (greaterratp (quotient (float (cadr x1))
1184 (caddr x1))
1185 x2))
1186 ((ratnump x2)
1187 (greaterratp x1
1188 (quotient (float (cadr x2))
1189 (caddr x2))))))
1191 (defun trig1 (x)
1192 (member (car x) '(%sin %cos) :test #'eq))
1194 (defun supertrig (exp)
1195 (declare (special *notsame* *trigarg*))
1196 (cond ((freevar exp) t)
1197 ((atom exp) nil)
1198 ((member (caar exp) '(mplus mtimes) :test #'eq)
1199 (and (supertrig (cadr exp))
1200 (or (null (cddr exp))
1201 (supertrig (cons (car exp)
1202 (cddr exp))))))
1203 ((eq (caar exp) 'mexpt)
1204 (and (supertrig (cadr exp))
1205 (supertrig (caddr exp))))
1206 ((eq (caar exp) '%log)
1207 (supertrig (cadr exp)))
1208 ((member (caar exp)
1209 '(%sin %cos %tan %sec %cot %csc) :test #'eq)
1210 (cond ((m2 (cadr exp) *trigarg*) t)
1211 ((m2-b*x+a (cadr exp))
1212 (and (setq *notsame* t) nil))
1213 (t (supertrig (cadr exp)))))
1214 (t (supertrig (cadr exp)))))
1216 (defun subst2s (ex pat)
1217 (cond ((null ex) nil)
1218 ((m2 ex pat) var)
1219 ((atom ex) ex)
1220 (t (cons (subst2s (car ex) pat)
1221 (subst2s (cdr ex) pat)))))
1223 ;; Match (c*x+b), where c and b are free of x
1224 (defun simple-trig-arg (exp)
1225 (m2 exp '((mplus) ((mtimes)
1226 ((coefftt) (c freevar))
1227 ((coefftt) (v varp)))
1228 ((coeffpp) (b freevar)))))
1230 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1232 ;;; Stage II
1233 ;;; Implementation of Method 6: Elementary function of trigonometric functions
1235 (defun monstertrig (exp var *trigarg*)
1236 (declare (special *trigarg*))
1237 (when (and (not (atom *trigarg*))
1238 ;; Do not exute the following code when called from rischint.
1239 (not *in-risch-p*))
1240 (let ((arg (simple-trig-arg *trigarg*)))
1241 (cond (arg
1242 ;; We have trig(c*x+b). Use the substitution y=c*x+b to
1243 ;; try to compute the integral. Why? Because x*sin(n*x)
1244 ;; takes longer and longer as n gets larger and larger.
1245 ;; This is caused by the Risch integrator. This is a
1246 ;; work-around for this issue.
1247 (let* ((c (cdras 'c arg))
1248 (b (cdras 'b arg))
1249 (new-var (gensym "NEW-VAR-"))
1250 (new-exp (maxima-substitute (div (sub new-var b) c)
1251 var exp)))
1252 (if (every-trigarg-alike new-exp new-var)
1253 ;; avoid endless recursion when more than one
1254 ;; trigarg exists or c is a float
1255 (return-from monstertrig
1256 (maxima-substitute
1257 *trigarg*
1258 new-var
1259 (div (integrator new-exp new-var) c))))))
1261 (return-from monstertrig (rischint exp var))))))
1262 (prog (*notsame* w a b y d)
1263 (declare (special *notsame*))
1264 (cond
1265 ((supertrig exp) (go a))
1266 ((null *notsame*) (return nil))
1267 ;; Check for an expression like a*trig1(m*x)*trig2(n*x),
1268 ;; where trig1 and trig2 are sin or cos.
1269 ((not (setq y (m2 exp
1270 '((mtimes)
1271 ((coefftt) (a freevar))
1272 (((b trig1))
1273 ((mtimes)
1274 (x varp)
1275 ((coefftt) (m freevar))))
1276 (((d trig1))
1277 ((mtimes)
1278 (x varp)
1279 ((coefftt) (n freevar))))))))
1280 (go b))
1281 ; This check has been done with the pattern match.
1282 ; ((not (and (member (car (setq b (cdr (assoc 'b y :test #'eq)))) '(%sin %cos) :test #'eq)
1283 ; (member (car (setq d (cdr (assoc 'd y :test #'eq)))) '(%sin %cos) :test #'eq)))
1284 ; (return nil))
1285 ((progn
1286 ;; The tests after this depend on values of b and d being
1287 ;; set. Set them here unconditionally, before doing the
1288 ;; tests.
1289 (setq b (cdras 'b y))
1290 (setq d (cdras 'd y))
1291 (and (eq (car b) '%sin)
1292 (eq (car d) '%sin)))
1293 ;; We have a*sin(m*x)*sin(n*x).
1294 ;; The integral is: a*(sin((m-n)*x)/(2*(m-n))-sin((m+n)*x)/(2*(m+n))
1295 (return (subliss y
1296 '((mtimes) a
1297 ((mplus)
1298 ((mquotient)
1299 ((%sin) ((mtimes) ((mplus) m ((mtimes) -1 n)) x))
1300 ((mtimes) 2 ((mplus) m ((mtimes) -1 n))))
1301 ((mtimes) -1
1302 ((mquotient)
1303 ((%sin) ((mtimes) ((mplus) m n) x))
1304 ((mtimes) 2 ((mplus) m n)))))))))
1305 ((and (eq (car b) '%cos) (eq (car d) '%cos))
1306 ;; We have a*cos(m*x)*cos(n*x).
1307 ;; The integral is: a*(sin((m-n)*x)/(2*(m-n))+sin((m+n)*x)/(2*(m+n))
1308 (return (subliss y
1309 '((mtimes) a
1310 ((mplus)
1311 ((mquotient)
1312 ((%sin) ((mtimes) ((mplus) m ((mtimes) -1 n)) x))
1313 ((mtimes) 2
1314 ((mplus) m ((mtimes) -1 n))))
1315 ((mquotient)
1316 ((%sin) ((mtimes) ((mplus) m n) x))
1317 ((mtimes) 2 ((mplus) m n))))))))
1318 ((or (and (eq (car b) '%cos)
1319 ;; The following (destructively!) swaps the values of
1320 ;; m and n if first trig term is sin. I (rtoy) don't
1321 ;; understand why this is needed. The formula
1322 ;; doesn't depend on that.
1323 (setq w (cdras 'm y ))
1324 (rplacd (assoc 'm y) (cdras 'n y))
1325 (rplacd (assoc 'n y) w))
1327 ;; We have a*cos(n*x)*sin(m*x).
1328 ;; The integral is: -a*(cos((m-n)*x)/(2*(m-n))+cos((m+n)*x)/(2*(m+n))
1329 (return (subliss y
1330 '((mtimes) -1 a
1331 ((mplus)
1332 ((mquotient)
1333 ((%cos) ((mtimes) ((mplus) m ((mtimes) -1 n)) x))
1334 ((mtimes) 2 ((mplus) m ((mtimes) -1 n))))
1335 ((mquotient)
1336 ((%cos) ((mtimes) ((mplus) m n) x))
1337 ((mtimes) 2 ((mplus) m n)))))))))
1338 b ;; At this point we have trig functions with different arguments,
1339 ;; but not a product of sin and cos.
1340 (cond ((not (setq y (prog2
1341 (setq *trigarg* var)
1342 (m2 exp
1343 '((mtimes)
1344 ((coefftt) (a freevar))
1345 (((b trig1))
1346 ((mtimes)
1347 (x varp)
1348 ((coefftt) (n integerp2))))
1349 ((coefftt) (c supertrig)))))))
1350 (return nil)))
1351 ;; We have a product of trig functions: trig1(n*x)*trig2(y).
1352 ;; trig1 is sin or cos, where n is a numerical integer. trig2 is not a sin
1353 ;; or cos. The cos or sin function is expanded.
1354 (return
1355 (integrator
1356 ($expand
1357 (list '(mtimes)
1358 (cdras 'a y) ; constant factor
1359 (cdras 'c y) ; trig functions
1360 (cond ((eq (car (cdras 'b y)) '%cos) ; expand cos(n*x)
1361 (maxima-substitute var
1363 (supercosnx (cdras 'n y))))
1364 (t ; expand sin(x*x)
1365 (maxima-substitute var
1367 (supersinx (cdras 'n y)))))))
1368 var))
1369 a ;; A product of trig functions and all trig functions have the same
1370 ;; argument *trigarg*. Maxima substitutes *trigarg* with the variable var
1371 ;; of integration and calls trigint to integrate the new problem.
1372 (setq w (subst2s exp *trigarg*))
1373 (setq b (cdras 'b (m2-b*x+a *trigarg*)))
1374 (setq a (substint *trigarg* var (trigint (div* w b) var)))
1375 (return (if (isinop a '%integrate)
1376 (list '(%integrate) exp var)
1377 a))))
1379 (defun trig2 (x)
1380 (member (car x) '(%sin %cos %tan %cot %sec %csc) :test #'eq))
1382 (defun supersinx (n)
1383 (let ((i (if (< n 0) -1 1)))
1384 ($expand (list '(mtimes) i (sinnx (timesk i n))))))
1386 (defun supercosnx (n)
1387 ($expand (cosnx (timesk (if (< n 0) -1 1) n))))
1389 (defun sinnx (n)
1390 (if (equal n 1)
1391 '((%sin) x)
1392 (list '(mplus)
1393 (list '(mtimes) '((%sin) x) (cosnx (1- n)))
1394 (list '(mtimes) '((%cos) x) (sinnx (1- n))))))
1396 (defun cosnx (n)
1397 (if (equal n 1)
1398 '((%cos) x)
1399 (list '(mplus)
1400 (list '(mtimes) '((%cos) x) (cosnx (1- n)))
1401 (list '(mtimes) -1 '((%sin) x) (sinnx (1- n))))))
1403 (defun poseven (x)
1404 (and (even x) (> x -1)))
1406 (defun trigfree (x)
1407 (if (atom x)
1408 (not (member x '(sin* cos* sec* tan*) :test #'eq))
1409 (and (trigfree (car x)) (trigfree (cdr x)))))
1411 (defun rat1 (exp)
1412 (prog (*b1* *notsame*)
1413 (declare (special *yy* *b1* *notsame*))
1414 (when (and (numberp exp) (zerop exp))
1415 (return nil))
1416 (setq *b1* (subst *b* 'b '((mexpt) b (n even))))
1417 (return (prog2
1418 (setq *yy* (rats exp))
1419 (cond ((not *notsame*) *yy*))))))
1421 (defun rats (exp)
1422 (prog (y)
1423 (declare (special *notsame* *b1*))
1424 (return
1425 (cond ((eq exp *a*) 'x)
1426 ((atom exp)
1427 (cond ((member exp '(sin* cos* sec* tan*) :test #'eq)
1428 (setq *notsame* t))
1429 (t exp)))
1430 ((setq y (m2 exp *b1*))
1431 (f3 y))
1432 (t (cons (car exp) (mapcar #'(lambda (g) (rats g)) (cdr exp))))))))
1434 (defun f3 (y)
1435 (maxima-substitute *c*
1437 (maxima-substitute (quotient (cdr (assoc 'n y :test #'eq)) 2)
1439 '((mexpt)
1440 ((mplus)
1442 ((mtimes)
1444 ((mexpt) x 2)))
1445 n))))
1447 (defun odd1 (n)
1448 (declare (special *yz*))
1449 (cond ((not (numberp n)) nil)
1450 ((not (equal (rem n 2) 0))
1451 (setq *yz*
1452 (maxima-substitute *c*
1454 (list '(mexpt)
1455 '((mplus) 1 ((mtimes) c ((mexpt) x 2)))
1456 (quotient (1- n) 2)))))
1457 (t nil)))
1459 (defun subvar (x)
1460 (maxima-substitute var 'x x))
1462 (defun subvardlg (x)
1463 (mapcar #'(lambda (m)
1464 (cons (maxima-substitute var 'x (car m)) (cdr m)))
1467 ;; This appears to be the implementation of Method 6, pp.82 in Moses' thesis.
1469 (defun trigint (exp var)
1470 (prog (y repl y1 y2 *yy* z m n *c* *yz* *a* *b* )
1471 (declare (special *yy* *yz*))
1472 ;; Transform trig(x) into trig* (for simplicity?) Convert cot to
1473 ;; tan and csc to sin.
1474 (setq y2
1475 (subliss (subvardlg '((((%sin) x) . sin*)
1476 (((%cos) x) . cos*)
1477 (((%tan) x) . tan*)
1478 (((%cot) x) . ((mexpt) tan* -1))
1479 (((%sec) x) . sec*)
1480 (((%csc) x) . ((mexpt) sin* -1))))
1481 exp))
1483 (when *debug-integrate*
1484 (format t "~& in TRIGINT:~%")
1485 (format t "~& : y2 = ~A~%" y2))
1487 ;; Now transform tan to sin/cos and sec to 1/cos.
1488 (setq y1 (setq y (subliss '((tan* . ((mtimes) sin*
1489 ((mexpt) cos* -1)))
1490 (sec* . ((mexpt) cos* -1)))
1491 y2)))
1493 (when *debug-integrate* (format t "~& : y = ~A~%" y))
1495 (when (null (setq z
1496 (m2 y
1497 '((mtimes)
1498 ((coefftt) (b trigfree))
1499 ((mexpt) sin* (m poseven))
1500 ((mexpt) cos* (n poseven))))))
1501 ;; Go if y is not of the form sin^m*cos^n for positive even m and n.
1502 (go l1))
1504 ;; Case III:
1505 ;; Handle the case of sin^m*cos^n, m, n both non-negative and even.
1507 (setq m (cdras 'm z))
1508 (setq n (cdras 'n z))
1509 (setq *a* (integerp2 (* 0.5 (if (< m n) 1 -1) (+ n (* -1 m)))))
1510 (setq z (cons (cons 'a *a*) z))
1511 (setq z (cons (cons 'x var) z))
1513 (when *debug-integrate*
1514 (format t "~& CASE III:~%")
1515 (format t "~& : m, n = ~A ~A~%" m n)
1516 (format t "~& : a = ~A~%" *a*)
1517 (format t "~& : z = ~A~%" z))
1519 ;; integrate(sin(y)^m*cos(y)^n,y) is transformed to the following form:
1521 ;; m < n: integrate((sin(2*y)/2)^n*(1/2+1/2*cos(2*y)^((n-m)/2),y)
1522 ;; m >= n: integrate((sin(2*y)/2)^n*(1/2-1/2*cos(2*y)^((m-n)/2),y)
1523 (return
1524 (mul (cdras 'b z)
1525 (div 1 2)
1526 (substint
1527 (mul 2 var)
1529 (integrator
1530 (cond ((< m n)
1531 (subliss z
1532 '((mtimes)
1533 ((mexpt)
1534 ((mtimes) ((rat simp) 1 2) ((%sin) x))
1536 ((mexpt)
1537 ((mplus)
1538 ((rat simp) 1 2)
1539 ((mtimes)
1540 ((rat simp) 1 2) ((%cos) x))) a))))
1542 (subliss z
1543 '((mtimes)
1544 ((mexpt)
1545 ((mtimes) ((rat simp) 1 2) ((%sin) x))
1547 ((mexpt)
1548 ((mplus)
1549 ((rat simp) 1 2)
1550 ((mtimes)
1551 ((rat simp) -1 2)
1552 ((%cos) x))) a)))))
1553 var))))
1555 ;; Case IV:
1556 ;; I think this is case IV, working on the expression in terms of
1557 ;; sin and cos.
1559 ;; Elem(x) means constants, x, trig functions of x, log and
1560 ;; inverse trig functions of x, and which are closed under
1561 ;; addition, multiplication, exponentiation, and substitution.
1563 ;; Elem(f(x)) is the same as Elem(x), but f(x) replaces x in the
1564 ;; definition.
1566 (when *debug-integrate* (format t "~& Case IV:~%"))
1568 (setq *c* -1)
1569 (setq *a* 'sin*)
1570 (setq *b* 'cos*)
1571 (when (and (m2 y '((coeffpt) (c rat1) ((mexpt) cos* (n odd1))))
1572 (setq repl (list '(%sin) var)))
1573 ;; The case cos^(2*n+1)*Elem(cos^2,sin). Use the substitution z = sin.
1574 (go getout))
1575 (setq *a* *b*)
1576 (setq *b* 'sin*)
1577 (when (and (m2 y '((coeffpt) (c rat1) ((mexpt) sin* (n odd1))))
1578 (setq repl (list '(%cos) var)))
1579 ;; The case sin^(2*n+1)*Elem(sin^2,cos). Use the substitution z = cos.
1580 (go get3))
1582 ;; Case V:
1583 ;; Transform sin and cos to tan and sec to see if the integral is
1584 ;; of the form Elem(tan, sec^2). If so, use the substitution z = tan.
1586 (when *debug-integrate* (format t "~& Case V:~%"))
1588 (setq y (subliss '((sin* (mtimes) tan* ((mexpt) sec* -1))
1589 (cos* (mexpt) sec* -1))
1590 y2))
1591 (setq *c* 1)
1592 (setq *a* 'tan*)
1593 (setq *b* 'sec*)
1594 (when (and (rat1 y) (setq repl (list '(%tan) var)))
1595 (go get1))
1596 (setq *a* *b*)
1597 (setq *b* 'tan*)
1598 (when (and (m2 y '((coeffpt) (c rat1) ((mexpt) tan* (n odd1))))
1599 (setq repl (list '(%sec) var)))
1600 (go getout))
1601 (when (not (alike1 (setq repl ($expand exp)) exp))
1602 (return (integrator repl var)))
1603 (setq y (subliss '((sin* (mtimes) 2 x
1604 ((mexpt) ((mplus) 1 ((mexpt) x 2)) -1))
1605 (cos* (mtimes)
1606 ((mplus) 1 ((mtimes) -1 ((mexpt) x 2)))
1607 ((mexpt) ((mplus) 1 ((mexpt) x 2)) -1)))
1608 y1))
1609 (setq y (list '(mtimes)
1611 '((mtimes) 2 ((mexpt) ((mplus) 1 ((mexpt) x 2)) -1))))
1612 (setq repl (subvar '((mquotient) ((%sin) x) ((mplus) 1 ((%cos) x)))))
1613 (go get2)
1614 get3
1615 (setq y (list '(mtimes) -1 *yy* *yz*))
1616 (go get2)
1617 get1
1618 (setq y (list '(mtimes) '((mexpt) ((mplus) 1 ((mexpt) x 2)) -1) *yy*))
1619 (go get2)
1620 getout
1621 (setq y (list '(mtimes) *yy* *yz*))
1622 get2
1623 (when *debug-integrate*
1624 (format t "~& Call the INTEGRATOR with:~%")
1625 (format t "~& : y = ~A~%" y)
1626 (format t "~& : repl = ~A~%" repl))
1627 ;; See Bug 2880797. We want atan(tan(x)) to simplify to x, so
1628 ;; set $triginverses to '$all.
1629 (return
1630 ;; Do not integrate for the global variable VAR, but substitute it.
1631 ;; This way possible assumptions on VAR are no longer present. The
1632 ;; algorithm of DEFINT depends on this behavior. See Bug 3085498.
1633 (let (($triginverses '$all) (newvar (gensym)))
1634 (substint repl
1635 newvar
1636 (integrator (maxima-substitute newvar 'x y) newvar))))))
1638 (defmvar $integration_constant_counter 0)
1639 (defmvar $integration_constant '$%c)
1641 ;; This is the top level of the integrator
1642 (defmfun sinint (exp var)
1643 ;; *integrator-level* is a recursion counter for INTEGRATOR. See
1644 ;; INTEGRATOR for more details. Initialize it here.
1645 (let ((*integrator-level* 0))
1646 (declare (special *integrator-level*))
1648 ;; Sanity checks for variables
1649 (when (mnump var)
1650 (merror (intl:gettext "integrate: variable must not be a number; found: ~:M") var))
1651 (when ($ratp var) (setf var (ratdisrep var)))
1652 (when ($ratp exp) (setf exp (ratdisrep exp)))
1654 (cond
1655 ;; Distribute over lists and matrices
1656 ((mxorlistp exp)
1657 (cons (car exp)
1658 (mapcar #'(lambda (y) (sinint y var)) (cdr exp))))
1660 ;; The symbolic integration code doesn't really deal very well with
1661 ;; subscripted variables, so if we have one then replace occurrences of var
1662 ;; with an atomic gensym and recurse.
1663 ((and (not (atom var))
1664 (member 'array (cdar var)))
1665 (let ((dummy-var (gensym)))
1666 (maxima-substitute var dummy-var
1667 (sinint (maxima-substitute dummy-var var exp) dummy-var))))
1669 ;; If exp is an equality, integrate both sides and add an integration
1670 ;; constant
1671 ((mequalp exp)
1672 (list (car exp) (sinint (cadr exp) var)
1673 (add (sinint (caddr exp) var)
1674 ($concat $integration_constant (incf $integration_constant_counter)))))
1676 ;; If var is an atom which occurs as an operator in exp, then return a noun form.
1677 ((and (atom var)
1678 (isinop exp var))
1679 (list '(%integrate) exp var))
1681 ((zerop1 exp) ;; special case because 0 will not pass sum-of-intsp test
1684 ((let ((ans (simplify
1685 (let ($opsubst varlist genvar stack)
1686 (integrator exp var)))))
1687 (if (sum-of-intsp ans)
1688 (list '(%integrate) exp var)
1689 ans))))))
1691 ;; SUM-OF-INTSP
1693 ;; This is a heuristic that SININT uses to work out whether the result from
1694 ;; INTEGRATOR is worth returning or whether just to return a noun form. If this
1695 ;; function returns T, then SININT will return a noun form.
1697 ;; The logic, as I understand it (Rupert 01/2014):
1699 ;; (1) If I integrate f(x) wrt x and get an atom other than x or 0, either
1700 ;; something's gone horribly wrong, or this is part of a larger
1701 ;; expression. In the latter case, we can return T here because hopefully
1702 ;; something else interesting will make the top-level return NIL.
1704 ;; (2) If I get a sum, return a noun form if every one of the summands is no
1705 ;; better than what I started with. (Presumably this is where the name
1706 ;; came from)
1708 ;; (3) If this is a noun form, it doesn't convey much information on its own,
1709 ;; so return T.
1711 ;; (4) If this is a product, something interesting has probably happened. But
1712 ;; I still want a noun form if the result is like 2*'integrate(f(x),x), so
1713 ;; I'm only interested in terms in the product that are not free of
1714 ;; VAR. If one of those terms is worthy of report, that's great: return
1715 ;; NIL. Otherwise, return T if we saw at least two things (eg splitting an
1716 ;; integral into a product of two integrals)
1718 ;; (5) If the result is free of VAR, we're in a similar position to (1).
1720 ;; (6) Otherwise something interesting (and hopefully useful) has
1721 ;; happened. Return NIL to tell SININT to report it.
1722 (defun sum-of-intsp (ans)
1723 (cond ((atom ans)
1724 ;; Result of integration should never be a constant other than zero.
1725 ;; If the result of integration is zero, it is either because:
1726 ;; 1) a subroutine inside integration failed and returned nil,
1727 ;; and (mul 0 nil) yielded 0, meaning that the result is wrong, or
1728 ;; 2) the original integrand was actually zero - this is handled
1729 ;; with a separate special case in sinint
1730 (not (eq ans var)))
1731 ((mplusp ans) (every #'sum-of-intsp (cdr ans)))
1732 ((eq (caar ans) '%integrate) t)
1733 ((mtimesp ans)
1734 (let ((int-factors 0))
1735 (not (or (dolist (factor (cdr ans))
1736 (unless (freeof var factor)
1737 (if (sum-of-intsp factor)
1738 (incf int-factors)
1739 (return t))))
1740 (<= 2 int-factors)))))
1741 ((freeof var ans) t)
1742 (t nil)))
1744 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1746 ;;; Stage I
1747 ;;; Implementation of Method 2: Integrate a summation
1749 (defun intsum (form var)
1750 (prog (exp idx ll ul pair val)
1751 (setq exp (cadr form)
1752 idx (caddr form)
1753 ll (cadddr form)
1754 ul (car (cddddr form)))
1755 (if (or (not (atom var))
1756 (not (free idx var))
1757 (not (free ll var))
1758 (not (free ul var)))
1759 (return (list '(%integrate) form var)))
1760 (setq pair (partition exp var 1))
1761 (when (and (mexptp (cdr pair))
1762 (eq (caddr pair) var))
1763 (setq val (maxima-substitute ll idx (cadddr pair)))
1764 (cond ((equal val -1)
1765 (return (add (integrator (maxima-substitute ll idx exp) var)
1766 (intsum1 exp idx (add 1 ll) ul var))))
1767 ((mlsp val -1)
1768 (return (list '(%integrate) form var)))))
1769 (return (intsum1 exp idx ll ul var))))
1771 (defun intsum1 (exp idx ll ul var)
1772 (assume (list '(mgeqp) idx ll))
1773 (if (not (eq ul '$inf))
1774 (assume (list '(mgeqp) ul idx)))
1775 (simplifya (list '(%sum) (integrator exp var) idx ll ul) t))
1777 (defun finds (x)
1778 (if (atom x)
1779 (member x '(%log %integrate %atan) :test #'eq)
1780 (or (finds (car x)) (finds (cdr x)))))
1782 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1784 ;;; Stage II
1785 ;;; Implementation of Method 9:
1786 ;;; Rational function times a log or arctric function
1788 ;;; ratlog is called for an expression containing a log or arctrig function
1789 ;;; The integrand is like log(x)*f'(x). To obtain the result the technique of
1790 ;;; partial integration is applied: log(x)*f(x)-integrate(1/x*f(x),x)
1792 (defun ratlog (exp var form)
1793 (prog (b c d y z w)
1794 (setq y form)
1795 (setq b (cdr (assoc 'b y :test #'eq)))
1796 (setq c (cdr (assoc 'c y :test #'eq)))
1797 (setq y (integrator c var))
1798 (when (finds y) (return nil))
1799 (setq d (sdiff (cdr (assoc 'a form :test #'eq)) var))
1801 (setq z (integrator (mul2* y d) var))
1802 (setq d (cdr (assoc 'a form :test #'eq)))
1803 (return (simplify (list '(mplus)
1804 (list '(mtimes) y d)
1805 (list '(mtimes) -1 z))))))
1807 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1809 ;;; partial-integration is an extension of the algorithm of ratlog to support
1810 ;;; the technique of partial integration for more cases. The integrand
1811 ;;; is like g(x)*f'(x) and the result is g(x)*f(x)-integrate(g'(x)*f(x),x).
1813 ;;; Adding integrals properties for elementary functions led to infinite recursion
1814 ;;; with integrate(z*expintegral_shi(z),z). This was resolved by limiting the
1815 ;;; recursion depth. *integrator-level* needs to be at least 3 to solve
1816 ;;; o integrate(expintegral_ei(1/sqrt(x)),x)
1817 ;;; o integrate(sqrt(z)*expintegral_li(z),z)
1818 ;;; while a value of 4 causes testsuite regressions with
1819 ;;; o integrate(z*expintegral_shi(z),z)
1820 (defun partial-integration (form var)
1821 (declare (special *integrator-level*))
1822 (let ((g (cdr (assoc 'a form))) ; part g(x)
1823 (df (cdr (assoc 'c form))) ; part f'(x)
1824 (f nil))
1825 (setq f (integrator df var)) ; integrate f'(x) wrt var
1826 (cond
1827 ((or (isinop f '%integrate) ; no result or
1828 (isinop f (caar g)) ; g in result
1829 (> *integrator-level* 3))
1830 nil) ; we return nil
1832 ;; Build the result: g(x)*f(x)-integrate(g'(x)*f(x))
1833 (add (mul f g)
1834 (mul -1 (integrator (mul f (sdiff g var)) var)))))))
1836 ;; returns t if argument of every trig operation in y matches arg
1837 (defun every-trigarg-alike (y arg)
1838 (cond ((atom y) t)
1839 ((optrig (caar y)) (alike1 arg (cadr y)))
1840 (t (every (lambda (exp)
1841 (every-trigarg-alike exp arg))
1842 (cdr y)))))
1844 ;; return argument of first trig operation encountered in y
1845 (defun find-first-trigarg (y)
1846 (cond ((atom y) nil)
1847 ((optrig (caar y)) (cadr y))
1848 (t (some (lambda (exp)
1849 (find-first-trigarg exp))
1850 (cdr y)))))
1852 ;; return constant factor that makes elements of alist match elements of blist
1853 ;; or nil if no match found
1854 ;; (we could replace this using rat package to divide alist and blist)
1855 (defun matchsum (alist blist)
1856 (prog (r s *c* *d*)
1857 (setq s (m2 (car alist) ;; find coeff for first term of alist
1858 '((mtimes)
1859 ((coefftt) (a freevar))
1860 ((coefftt) (c true)))))
1861 (setq *c* (cdr (assoc 'c s :test #'eq)))
1862 (cond ((not (setq r ;; find coeff for first term of blist
1863 (m2 (car blist)
1864 (cons '(mtimes)
1865 (cons '((coefftt) (b free1))
1866 (cond ((mtimesp *c*)
1867 (cdr *c*))
1868 (t (list *c*))))))))
1869 (return nil)))
1870 (setq *d* (simplify (list '(mtimes)
1871 (subliss s 'a)
1872 (list '(mexpt)
1873 (subliss r 'b)
1874 -1))))
1875 (cond ((m2 (cons '(mplus) alist) ;; check that all terms match
1876 (timesloop *d* blist))
1877 (return *d*))
1878 (t (return nil)))))
1880 (defun timesloop (a b)
1881 (cons '(mplus) (mapcar #'(lambda (c) (mul2* a c)) b)))
1883 (defun expands (aa b)
1884 (addn (mapcar #'(lambda (c) (timesloop c aa)) b) nil))
1886 (defun powerlist (exp var)
1887 (prog (y *c* *d* powerlist *b*)
1888 (setq y (m2 exp
1889 '((mtimes)
1890 ((mexpt) (var varp) (c integerp2))
1891 ((coefftt) (a freevar))
1892 ((coefftt) (b true)))))
1893 (setq *b* (cdr (assoc 'b y :test #'eq)))
1894 (setq *c* (cdr (assoc 'c y :test #'eq)))
1895 (unless (rat10 *b*) (return nil))
1896 (setq *d* (apply #'gcd (cons (1+ *c*) powerlist)))
1897 (when (or (eql 1 *d*) (zerop *d*)) (return nil))
1898 (return
1899 (substint
1900 (list '(mexpt) var *d*)
1902 (integrate5 (simplify (list '(mtimes)
1903 (power* *d* -1)
1904 (cdr (assoc 'a y :test #'eq))
1905 (list '(mexpt) var (1- (quotient (1+ *c*) *d*)))
1906 (subst10 *b*)))
1907 var)))))
1909 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1911 ;;; Stage I
1912 ;;; Implementation of Method 3: Derivative-divides algorithm
1914 ;; This is the derivative-divides algorithm of Moses.
1916 ;; /
1917 ;; [
1918 ;; Look for form I c * op(u(x)) * u'(x) dx
1919 ;; ]
1920 ;; /
1922 ;; where: c is a constant
1923 ;; u(x) is an elementary expression in x
1924 ;; u'(x) is its derivative
1925 ;; op is an elementary operator:
1926 ;; - the indentity, or
1927 ;; - any function that can be integrated by INTEGRALLOOKUPS
1929 ;; The method of solution, once the problem has been determined to
1930 ;; posses the form above, is to look up OP in a table and substitute
1931 ;; u(x) for each occurrence of x in the expression given in the table.
1932 ;; In other words, the method performs an implicit substitution y = u(x),
1933 ;; and obtains the integral of op(y)dy by a table look up.
1935 (defun diffdiv (exp var)
1936 (prog (y *a* x v *d* z w r)
1937 (cond ((and (mexptp exp)
1938 (mplusp (cadr exp))
1939 (integerp (caddr exp))
1940 (< (caddr exp) 6)
1941 (> (caddr exp) 0))
1942 (return (integrator (expandexpt (cadr exp) (caddr exp)) var))))
1944 ;; If not a product, transform to a product with one term
1945 (setq exp (cond ((mtimesp exp) exp) (t (list '(mtimes) exp))))
1947 ;; Loop over the terms in exp
1948 (setq z (cdr exp))
1949 a (setq y (car z))
1951 ;; This m2 pattern matches const*(exp/y)
1952 (setq r (list '(mplus)
1953 (cons '(coeffpt)
1954 (cons '(c free1)
1955 (remove y (cdr exp) :count 1)))))
1956 (cond
1957 ;; Case u(var) is the identity function. y is a term in exp.
1958 ;; Match if diff(y,var) == c*(exp/y).
1959 ;; This even works when y is a function with multiple args.
1960 ((setq w (m2 (sdiff y var) r))
1961 (return (muln (list y y (power* (mul2* 2 (cdr (assoc 'c w :test #'eq))) -1)) nil))))
1963 ;; w is the arg in y.
1964 (let ((arg-freevar))
1965 (setq w
1966 (cond
1967 ((or (atom y) (member (caar y) '(mplus mtimes) :test #'eq)) y)
1968 ;; Take the argument of a function with one value.
1969 ((= (length (cdr y)) 1) (cadr y))
1970 ;; A function has multiple args, and exactly one arg depends on var
1971 ((= (count-if #'null (setq arg-freevar (mapcar #'freevar (cdr y)))) 1)
1972 (do ((args (cdr y) (cdr args))
1973 (argf arg-freevar (cdr argf)))
1974 ((if (not (car argf)) (return (car args))))))
1975 (t 0))))
1977 (cond
1978 ((setq w (cond ((and (setq x (sdiff w var))
1979 (mplusp x)
1980 (setq *d* (remove y (cdr exp) :count 1))
1981 (setq v (car *d*))
1982 (mplusp v)
1983 (not (cdr *d*)))
1984 (cond ((setq *d* (matchsum (cdr x) (cdr v)))
1985 (list (cons 'c *d*)))
1986 (t nil)))
1987 (t (m2 x r))))
1988 (return (cond ((null (setq x (integrallookups y))) nil)
1989 ((eq w t) x)
1990 (t (mul2* x (power* (cdr (assoc 'c w :test #'eq)) -1)))))))
1991 (setq z (cdr z))
1992 (when (null z) (return nil))
1993 (go a)))
1995 (defun subliss (alist expr)
1996 "Alist is an alist consisting of a variable (symbol) and its value. expr is
1997 an expression. For each entry in alist, substitute the corresponding
1998 value into expr."
1999 (let ((x expr))
2000 (dolist (a alist x)
2001 (setq x (maxima-substitute (cdr a) (car a) x)))))
2003 (defun substint (x y expres)
2004 (if (and (not (atom expres)) (eq (caar expres) '%integrate))
2005 (list (car expres) exp var)
2006 (substint1 (maxima-substitute x y expres))))
2008 (defun substint1 (exp)
2009 (cond ((atom exp) exp)
2010 ((and (eq (caar exp) '%integrate)
2011 (null (cdddr exp))
2012 (not (symbolp (caddr exp)))
2013 (not (free (caddr exp) var)))
2014 (simplify (list '(%integrate)
2015 (mul2 (cadr exp) (sdiff (caddr exp) var))
2016 var)))
2017 (t (recur-apply #'substint1 exp))))
2019 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2021 ;:; Extension of the integrator for more integrals with power functions
2023 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2025 ;;; Recognize (a^(c*(z^r)^p+d)^v
2027 (defun m2-exp-type-1a (expr)
2028 (m2 expr
2029 '((mexpt)
2030 ((mexpt)
2031 (a freevar0)
2032 ((mplus)
2033 ;; The order of the pattern is critical. If we change it,
2034 ;; we do not get the expected match.
2035 ((coeffpp) (d freevar))
2036 ((coefft) (c freevar0)
2037 ((mexpt)
2038 ((mexpt) (z varp) (r freevar0))
2039 (p freevar)))))
2040 (v freevar))))
2042 ;;; Recognize z^v*a^(b*z^r+d)
2044 (defun m2-exp-type-2 (expr)
2045 (m2 expr
2046 '((mtimes)
2047 ((mexpt) (z varp) (v freevar0))
2048 ((mexpt)
2049 (a freevar0)
2050 ((mplus)
2051 ((coeffpp) (d freevar))
2052 ((coefft) (b freevar0) ((mexpt) (z varp) (r freevar0))))))))
2054 ;;; Recognize z^v*%e^(a*z^r+b)^u
2056 (defun m2-exp-type-2-1 (expr)
2057 (m2 expr
2058 '((mtimes)
2059 ((mexpt) (z varp) (v freevar0))
2060 ((mexpt)
2061 ((mexpt)
2063 ((mplus)
2064 ((coeffpp) (b freevar))
2065 ((coefft) (a freevar0) ((mexpt) (z varp) (r freevar0)))))
2066 (u freevar)))))
2068 ;;; Recognize (a*z+b)^p*%e^(c*z+d)
2070 (defun m2-exp-type-3 (expr)
2071 (m2 expr
2072 '((mtimes)
2073 ((mexpt)
2074 ((mplus)
2075 ((coefft) (a freevar0) (z varp))
2076 ((coeffpp) (b freevar)))
2077 (p freevar0))
2078 ((mexpt)
2080 ((mplus)
2081 ((coefft) (c freevar0) (z varp))
2082 ((coeffpp) (d freevar)))))))
2084 ;;; Recognize d^(a*z^2+b/z^2+c)
2086 (defun m2-exp-type-4 (expr)
2087 (m2 expr
2088 '((mexpt)
2089 (d freevar0)
2090 ((mplus)
2091 ((coefft) (a freevar0) ((mexpt) (z varp) 2))
2092 ((coefft) (b freevar0) ((mexpt) (z varp) -2))
2093 ((coeffpp) (c freevar))))))
2095 ;;; Recognize z^(2*n)*d^(a*z^2+b/z^2+c)
2097 (defun m2-exp-type-4-1 (expr)
2098 (m2 expr
2099 '((mtimes)
2100 ((mexpt) (z varp) (n freevar0))
2101 ((mexpt)
2102 (d freevar0)
2103 ((mplus)
2104 ((coefft) (a freevar0) ((mexpt) (z varp) 2))
2105 ((coefft) (b freevar0) ((mexpt) (z varp) -2))
2106 ((coeffpp) (c freevar)))))))
2108 ;;; Recognize z^n*d^(a*z^2+b*z+c)
2110 (defun m2-exp-type-5 (expr)
2111 (m2 expr
2112 '((mtimes)
2113 ((mexpt) (z varp) (n freevar))
2114 ((mexpt)
2115 (d freevar0)
2116 ((mplus)
2117 ((coeffpt) (a freevar) ((mexpt) (z varp) 2))
2118 ((coeffpt) (b freevar) (z varp))
2119 ((coeffpp) (c freevar)))))))
2121 ;;; Recognize z^n*(%e^(a*z^2+b*z+c))^u
2123 (defun m2-exp-type-5-1 (expr)
2124 (m2 expr
2125 '((mtimes)
2126 ((mexpt) (z varp) (n freevar0))
2127 ((mexpt)
2128 ((mexpt)
2130 ((mplus)
2131 ((coeffpp) (c freevar))
2132 ((coefft) (a freevar0) ((mexpt) (z varp) 2))
2133 ((coefft) (b freevar0) (z varp))))
2134 (u freevar)))))
2136 ;;; Recognize z^n*d^(a*sqrt(z)+b*z+c)
2138 (defun m2-exp-type-6 (expr)
2139 (m2 expr
2140 '((mtimes)
2141 ((mexpt) (z varp) (n freevar0))
2142 ((mexpt)
2143 (d freevar0)
2144 ((mplus)
2145 ((coefft) (a freevar0) ((mexpt) (z varp) ((rat) 1 2)))
2146 ((coefft) (b freevar0) (z varp))
2147 ((coeffpp) (c freevar)))))))
2149 ;;; Recognize z^n*(%e^(a*sqrt(z)+b*z+c))^u
2151 (defun m2-exp-type-6-1 (expr)
2152 (m2 expr
2153 '((mtimes)
2154 ((mexpt) (z varp) (n freevar0))
2155 ((mexpt)
2156 ((mexpt)
2158 ((mplus)
2159 ((coeffpp) (c freevar))
2160 ((coefft) (a freevar0) ((mexpt) (z varp) ((rat) 1 2)))
2161 ((coefft) (b freevar0) (z varp))))
2162 (u freevar)))))
2164 ;;; Recognize z^n*a^(b*z^r+e)*h^(c*z^r+g)
2166 (defun m2-exp-type-7 (expr)
2167 (m2 expr
2168 '((mtimes)
2169 ((mexpt) (z varp) (n freevar))
2170 ((mexpt)
2171 (a freevar0)
2172 ((mplus)
2173 ((coefft)
2174 (b freevar0)
2175 ((mexpt) (z varp) (r freevar0)))
2176 ((coeffpp) (e freevar))))
2177 ((mexpt)
2178 (h freevar0)
2179 ((mplus)
2180 ((coefft)
2181 (c freevar0)
2182 ((mexpt) (z varp) (r1 freevar0)))
2183 ((coeffpp) (g freevar)))))))
2185 ;;; Recognize z^v*(%e^(b*z^r+e))^q*(%e^(c*z^r+g))^u
2187 (defun m2-exp-type-7-1 (expr)
2188 (m2 expr
2189 '((mtimes)
2190 ((mexpt) (z varp) (v freevar))
2191 ((mexpt)
2192 ((mexpt)
2194 ((mplus)
2195 ((coeffpp) (e freevar))
2196 ((coefft) (b freevar0) ((mexpt) (z varp) (r freevar0)))))
2197 (q freevar))
2198 ((mexpt)
2199 ((mexpt)
2201 ((mplus)
2202 ((coeffpp) (g freevar))
2203 ((coefft) (c freevar0) ((mexpt) (z varp) (r1 freevar0)))))
2204 (u freevar)))))
2206 ;;; Recognize a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z)+f*z+g)
2208 (defun m2-exp-type-8 (expr)
2209 (m2 expr
2210 '((mtimes)
2211 ((mexpt)
2212 (a freevar0)
2213 ((mplus)
2214 ((coeffpt) (b freevar) ((mexpt) (z varp) ((rat) 1 2)))
2215 ((coeffpt) (d freevar) (z varp))
2216 ((coeffpp) (e freevar))))
2217 ((mexpt)
2218 (h freevar0)
2219 ((mplus)
2220 ((coeffpt) (c freevar) ((mexpt) (z varp) ((rat) 1 2)))
2221 ((coeffpt) (f freevar) (z varp))
2222 ((coeffpp) (g freevar)))))))
2224 ;;; Recognize (%e^(b*sqrt(z)+d*z+e))^u*(%e^(c*sqrt(z)+f*z+g))^v
2226 (defun m2-exp-type-8-1 (expr)
2227 (m2 expr
2228 '((mtimes)
2229 ((mexpt)
2230 ((mexpt)
2232 ((mplus)
2233 ((coeffpp) (e freevar))
2234 ((coeffpt) (b freevar) ((mexpt) (z varp) ((rat) 1 2)))
2235 ((coeffpt) (d freevar) (z varp))))
2236 (u freevar))
2237 ((mexpt)
2238 ((mexpt)
2240 ((mplus)
2241 ((coeffpp) (g freevar))
2242 ((coeffpt) (c freevar) ((mexpt) (z varp) ((rat) 1 2)))
2243 ((coeffpt) (f freevar) (z varp))))
2244 (v freevar)))))
2246 ;;; Recognize (%e^(b*z^r+e))^u*(%e^(c*z^r+g))^v
2248 (defun m2-exp-type-8-2 (expr)
2249 (m2 expr
2250 '((mtimes)
2251 ((mexpt)
2252 ((mexpt)
2254 ((mplus)
2255 ((coeffpp) (e freevar))
2256 ((coefft) (b freevar) ((mexpt) (z varp) (r freevar0)))))
2257 (u freevar))
2258 ((mexpt)
2259 ((mexpt)
2261 ((mplus)
2262 ((coeffpp) (g freevar))
2263 ((coefft) (c freevar) ((mexpt) (z varp) (r1 freevar0)))))
2264 (v freevar)))))
2266 ;;; Recognize z^n*a^(b*z^2+d*z+e)*h^(c*z^2+f*z+g)
2268 (defun m2-exp-type-9 (expr)
2269 (m2 expr
2270 '((mtimes)
2271 ((mexpt) (z varp) (n freevar))
2272 ((mexpt)
2273 (a freevar0)
2274 ((mplus)
2275 ((coeffpt) (b freevar) ((mexpt) (z varp) 2))
2276 ((coeffpt) (d freevar) (z varp))
2277 ((coeffpp) (e freevar))))
2278 ((mexpt)
2279 (h freevar0)
2280 ((mplus)
2281 ((coeffpt) (c freevar) ((mexpt) (z varp) 2))
2282 ((coeffpt) (f freevar) (z varp))
2283 ((coeffpp) (g freevar)))))))
2285 ;;; Recognize z^n*(%e^(b*z^2+d*z+e))^q*(%e^(c*z^2+f*z+g))^u
2287 (defun m2-exp-type-9-1 (expr)
2288 (m2 expr
2289 '((mtimes)
2290 ((mexpt) (z varp) (n freevar))
2291 ((mexpt)
2292 ((mexpt)
2294 ((mplus)
2295 ((coeffpp) (e freevar))
2296 ((coeffpt) (b freevar) ((mexpt) (z varp) 2))
2297 ((coeffpt) (d freevar) (z varp))))
2298 (q freevar))
2299 ((mexpt)
2300 ((mexpt)
2302 ((mplus)
2303 ((coeffpp) (g freevar))
2304 ((coeffpt) (c freevar) ((mexpt) (z varp) 2))
2305 ((coeffpt) (f freevar) (z varp))))
2306 (u freevar)))))
2308 ;;; Recognize z^n*a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z+)f*z+g)
2310 (defun m2-exp-type-10 (expr)
2311 (m2 expr
2312 '((mtimes)
2313 ((mexpt) (z varp) (n freevar))
2314 ((mexpt)
2315 (a freevar0)
2316 ((mplus)
2317 ((coeffpt) (b freevar) ((mexpt) (z varp) ((rat) 1 2)))
2318 ((coeffpt) (d freevar) (z varp))
2319 ((coeffpp) (e freevar))))
2320 ((mexpt)
2321 (h freevar0)
2322 ((mplus)
2323 ((coeffpt) (c freevar) ((mexpt) (z varp) ((rat) 1 2)))
2324 ((coeffpt) (f freevar) (z varp))
2325 ((coeffpp) (g freevar)))))))
2327 ;;; Recognize z^n*(%e^(b*sqrt(z)+d*z+e))^q*(%e^(c*sqrt(z)+f*z+g))^u
2329 (defun m2-exp-type-10-1 (expr)
2330 (m2 expr
2331 '((mtimes)
2332 ((mexpt) (z varp) (n freevar))
2333 ((mexpt)
2334 ((mexpt)
2336 ((mplus)
2337 ((coeffpp) (e freevar))
2338 ((coeffpt) (b freevar) ((mexpt) (z varp) ((rat) 1 2)))
2339 ((coeffpt) (d freevar) (z varp))))
2340 (q freevar))
2341 ((mexpt)
2342 ((mexpt)
2344 ((mplus)
2345 ((coeffpp) (g freevar))
2346 ((coeffpt) (c freevar) ((mexpt) (z varp) ((rat) 1 2)))
2347 ((coeffpt) (f freevar) (z varp))))
2348 (u freevar)))))
2350 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2352 (defun integrate-exp-special (expr var &aux w const)
2354 ;; First factor the expression.
2355 (setq expr ($factor expr))
2357 ;; Remove constant factors.
2358 (setq w (partition expr var 1))
2359 (setq const (car w))
2360 (setq expr (cdr w))
2362 (schatchen-cond w
2363 ((m2-exp-type-1a (facsum-exponent expr))
2364 (a c d r p v)
2365 (when *debug-integrate*
2366 (format t "~&Type 1a: (a^(c*(z^r)^p+d)^v : w = ~A~%" w))
2368 (mul -1
2369 const
2370 ;; 1/(p*r*(a^(c*v*(var^r)^p)))
2371 (inv (mul p r (power a (mul c v (power (power var r) p)))))
2373 ;; (a^(d+c*(var^r)^p))^v
2374 (power (power a (add d (mul c (power (power var r) p)))) v)
2375 ;; gamma_incomplete(1/(p*r), -c*v*(var^r)^p*log(a))
2376 (take '(%gamma_incomplete)
2377 (inv (mul p r))
2378 (mul -1 c v (power (power var r) p) (take '(%log) a)))
2379 ;; (-c*v*(var^r)^p*log(a))^(-1/(p*r))
2380 (power (mul -1 c v (power (power var r) p) (take '(%log) a))
2381 (div -1 (mul p r)))))
2383 ((m2-exp-type-2 (facsum-exponent expr))
2384 (a b d v r)
2386 (when *debug-integrate*
2387 (format t "~&Type 2: z^v*a^(b*z^r+d) : w = ~A~%" w))
2389 (mul
2390 const
2391 (div -1 r)
2392 (power a d)
2393 (power var (add v 1))
2394 ($gamma_incomplete
2395 (div (add v 1) r)
2396 (mul -1 b (power var r) ($log a)))
2397 (power
2398 (mul -1 b (power var r) ($log a))
2399 (mul -1 (div (add v 1) r)))))
2401 ((m2-exp-type-2-1 (facsum-exponent expr))
2402 (a b v r u)
2403 (when *debug-integrate*
2404 (format t "~&Type 2-1: z^v*(%e^(a*z^r+b))^u : w = ~A~%" w))
2406 (mul const
2408 (inv r)
2409 (power '$%e (mul -1 a u (power var r)))
2410 (power (power '$%e (add (mul a (power var r)) b)) u)
2411 (power var (add v 1))
2412 (power (mul -1 a u (power var r)) (div (mul -1 (add v 1)) r))
2413 (take '(%gamma_incomplete)
2414 (div (add v 1) r)
2415 (mul -1 a u (power var r)))))
2417 ((m2-exp-type-3 (facsum-exponent expr))
2418 (a b c d p)
2419 (when *debug-integrate*
2420 (format t "~&Type 3: (a*z+b)^p*%e^(c*z+d) : w = ~A~%" w))
2421 (mul
2422 const
2423 (div -1 a)
2424 (power '$%e (sub d (div (mul b c) a)))
2425 (power (add b (mul a var)) (add p 1))
2426 ($expintegral_e (mul -1 p) (mul (div -1 a) c (add b (mul a var))))))
2428 ((m2-exp-type-4 expr)
2429 (a b c d)
2430 (let (($trigsign nil)) ; Do not simplify erfc(-x) !
2431 (when *debug-integrate*
2432 (format t "~&Type 4: d^(a*z^2+b/z^2+c) : w = ~A~%" w))
2434 (mul
2435 const
2436 (div 1 (mul 4 (power (mul -1 a ($log d)) (div 1 2))))
2437 (mul
2438 (power d c)
2439 (power '$%pi (div 1 2))
2440 (power '$%e
2441 (mul -2
2442 (power (mul -1 a ($log d)) (div 1 2))
2443 (power (mul -1 b ($log d)) (div 1 2))))
2444 (add
2445 ($erfc
2446 (add
2447 (div (power (mul -1 b ($log d)) (div 1 2)) var)
2448 (mul -1 var (power (mul -1 a ($log d)) (div 1 2)))))
2449 (mul -1
2450 (power '$%e
2451 (mul 4
2452 (power (mul -1 a ($log d)) (div 1 2))
2453 (power (mul -1 b ($log d)) (div 1 2))))
2454 ($erfc
2455 (add
2456 (mul var (power (mul -1 a ($log d)) (div 1 2)))
2457 (div (power (mul -1 b ($log d)) (div 1 2)) var)))))))))
2459 ((and (m2-exp-type-4-1 expr)
2460 (poseven (cdras 'n w)) ; only for n a positive, even integer
2461 (symbolp (cdras 'a w))) ; a has to be a symbol
2462 (a b c d n)
2463 (let (($trigsign nil)) ; Do not simplify erfc(-x) !
2465 (when *debug-integrate*
2466 (format t "~&Type 4-1: z^(2*n)*d^(a*z^2+b/z^2+c) : w = ~A~%" w))
2468 (setq n (div n 2))
2470 (mul const
2471 (div 1 4)
2472 (power d c)
2473 (power '$%pi (div 1 2))
2474 (simplify (list '(%derivative)
2475 (div
2476 (sub
2477 (mul
2478 (power ($log d) (mul -1 n))
2479 (add
2480 (mul
2481 (power
2482 '$%e
2483 (mul -2
2484 (power (mul -1 a ($log d)) (div 1 2))
2485 (power (mul -1 b ($log d)) (div 1 2))))
2486 ($erfc
2487 (sub
2488 (div
2489 (power (mul -1 b ($log d)) (div 1 2))
2490 var)
2491 (mul var (power (mul -1 ($log d)) (div 1 2))))))))
2492 (mul
2493 (power
2494 '$%e
2495 (mul 2
2496 (power (mul -1 a ($log d)) (div 1 2))
2497 (power (mul -1 b ($log d)) (div 1 2))))
2498 ($erfc
2499 (add
2500 (power (mul -1 a ($log d)) (div 1 2))
2501 (div (power (mul -1 b ($log d)) (div 1 2)) var)))))
2502 (power (mul -1 a ($log d)) (div 1 2)))
2503 a n)))))
2505 ((and (m2-exp-type-5 (facsum-exponent expr))
2506 (maxima-integerp (cdras 'n w))
2507 (eq ($sign (cdras 'n w)) '$pos))
2508 (a b c d n)
2510 (when *debug-integrate*
2511 (format t "~&Type 5: z^n*d^(a*z^2+b*z+c) : w = ~A~%" w))
2513 (mul
2514 const
2515 (div -1 (mul 2 (power (mul a ($log d)) (div 1 2))))
2516 (mul
2517 (power d (sub c (div (mul b b) (mul 4 a))))
2518 (let ((index (gensumindex))
2519 ($simpsum t))
2520 (mfuncall '$sum
2521 (mul
2522 (power 2 (sub index n))
2523 ($binomial n index)
2524 ($gamma_incomplete
2525 (div (add index 1) 2)
2526 (mul
2527 (div -1 (mul 4 a))
2528 (power (add b (mul 2 a var)) 2)
2529 ($log d)))
2530 (power (mul a ($log d)) (mul -1 (add n (div 1 2))))
2531 (power (mul -1 b ($log d)) (sub n index))
2532 (power (mul (add b (mul 2 a var)) ($log d)) (add index 1))
2533 (power
2534 (mul (div -1 a) (power (add b (mul 2 a var)) 2) ($log d))
2535 (mul (div -1 2) (add index 1))))
2536 index 0 n)))))
2538 ((and (m2-exp-type-5-1 (facsum-exponent expr))
2539 (maxima-integerp (cdras 'n w))
2540 (eq ($sign (cdras 'n w)) '$pos))
2541 (a b c u n)
2542 (when *debug-integrate*
2543 (format t "~&Type 5-1: z^n*(%e^(a*z^2+b*z+c))^u : w = ~A~%" w))
2545 (mul const
2546 (div -1 2)
2547 (power '$%e
2548 (add (mul -1 (div (mul b b u) (mul 4 a)))
2549 (mul -1 u (add (mul a var var) (mul b var)))))
2550 (power a (mul -1 (add n 1)))
2551 (power (power '$%e
2552 (add (mul a var var) (mul b var) c))
2554 (let ((index (gensumindex))
2555 ($simpsum t))
2556 (dosum
2557 (mul (power 2 (sub index n))
2558 (power (mul -1 b) (sub n index))
2559 (power (add b (mul 2 a var)) (add index 1))
2560 (power (div (mul -1 u (power (add b (mul 2 a var)) 2)) a)
2561 (mul (div -1 2) (add index 1)))
2562 (take '(%binomial) n index)
2563 (take '(%gamma_incomplete)
2564 (div (add index 1) 2)
2565 (div (mul -1 u (power (add b (mul 2 a var)) 2))
2566 (mul 4 a))))
2567 index 0 n t))))
2569 ((and (m2-exp-type-6 (facsum-exponent expr))
2570 (maxima-integerp (cdras 'n w))
2571 (eq ($sign (cdras 'n w)) '$pos))
2572 (a b c d n)
2573 (when *debug-integrate*
2574 (format t "~&Type 6: z^n*d^(a*sqrt(z)+b*z+c) : w = ~A~%" w))
2576 (mul
2577 const
2578 (power 2 (mul -1 (add n 1)))
2579 (power d (sub c (div (mul a a) (mul 4 b))))
2580 (power (mul b ($log d)) (mul -2 (add n 1)))
2581 (let ((index1 (gensumindex))
2582 (index2 (gensumindex))
2583 ($simpsum t))
2584 (mfuncall '$sum
2585 (mfuncall '$sum
2586 (mul
2587 (power -1 (sub index1 index2))
2588 (power 4 index1)
2589 ($binomial index1 index2)
2590 ($binomial n index1)
2591 ($log d)
2592 (power (mul a ($log d)) (sub (mul 2 n) (add index1 index2)))
2593 (power
2594 (mul (add a (mul 2 b (power var (div 1 2)))) ($log d))
2595 (add index1 index2))
2596 (power
2597 (mul
2598 (div -1 b)
2599 (power (add a (mul 2 b (power var (div 1 2)))) 2)
2600 ($log d))
2601 (mul (div -1 2) (add index1 index2 1)))
2602 (add
2603 (mul 2 b
2604 (power
2605 (mul
2606 (div -1 b)
2607 (power (add a (mul 2 b (power var (div 1 2)))) 2)
2608 ($log d))
2609 (div 1 2))
2610 ($gamma_incomplete
2611 (div (add index1 index2 2) 2)
2612 (mul
2613 (div -1 (mul 4 b))
2614 (power (add a (mul 2 b (power var (div 1 2)))) 2)
2615 ($log d))))
2616 (mul a
2617 (add a (mul 2 b (power var (div 1 2))))
2618 ($log d)
2619 ($gamma_incomplete
2620 (div (add index1 index2 1) 2)
2621 (mul
2622 (div -1 (mul 4 b))
2623 (power (add a (mul 2 b (power var (div 1 2)))) 2)
2624 ($log d))))))
2625 index2 0 index1)
2626 index1 0 n))))
2628 ((and (m2-exp-type-6-1 (facsum-exponent expr))
2629 (maxima-integerp (cdras 'n w))
2630 (eq ($sign (cdras 'n w)) '$pos))
2631 (a b c u n)
2632 (when *debug-integrate*
2633 (format t "~&Type 6-1: z^n*(%e^(a*sqrt(z)+b*z+c))^u : w = ~A~%" w))
2635 (mul const
2636 (power 2 (mul -1 (add (mul 2 n) 1)))
2637 (power '$%e
2638 (add (div (mul -1 u a a) (mul 4 b))
2639 (mul u (add (mul a (power var (div 1 2)))
2640 (mul b var)
2641 c))))
2642 (power b (mul -2 (add n 1)))
2643 (power (power '$%e
2644 (add (mul a (power var (div 1 2)))
2645 (mul b var)))
2647 (let ((index1 (gensumindex))
2648 (index2 (gensumindex))
2649 ($simpsum t))
2650 (dosum
2651 (dosum
2652 (mul (power -1 (sub index1 index2))
2653 (power 4 index1)
2654 (power a (add (neg index2) (neg index1) (mul 2 n)))
2655 (power (add a (mul 2 b (power var (div 1 2))))
2656 (add index1 index2))
2657 (power (div (mul -1 u
2658 (power (add a
2659 (mul 2
2661 (power var (div 1 2))))
2664 (mul (div -1 2) (add index1 index2 1)))
2665 (take '(%binomial) index1 index2)
2666 (take '(%binomial) n index1)
2667 (add (mul a
2668 (add a (mul 2 b (power var (div 1 2))))
2669 (take '(%gamma_incomplete)
2670 (div (add index1 index2 1) 2)
2671 (div (mul -1 u
2672 (power (add a
2673 (mul 2 b
2674 (power var
2675 (div 1 2))))
2677 (mul 4 b))))
2678 (mul (inv u)
2679 (power (div (mul -1 u
2680 (power (add a
2681 (mul 2 b
2682 (power var
2683 (div 1 2))))
2686 (div 1 2))
2687 (mul 2 b)
2688 (take '(%gamma_incomplete)
2689 (div (add index1 index2 2) 2)
2690 (div (mul -1 u
2691 (power (add a
2692 (mul 2 b
2693 (power var (div 1 2))))
2695 (mul 4 b))))))
2696 index2 0 index1 t)
2697 index1 0 n t))))
2699 ((and (m2-exp-type-7 (facsum-exponent expr))
2700 (eq ($sign (sub (cdras 'r w) (cdras 'r1 w))) '$zero))
2701 (a b c e g h r n)
2702 (when *debug-integrate*
2703 (format t "~&Type 7: z^n*a^(b*z^r+e)*h^(c*z^r+g) : w = ~A~%" w))
2705 (setq n (add n 1))
2707 (mul
2708 const
2709 (power var n)
2710 (div -1 r)
2711 (power a e)
2712 (power h g)
2713 (power
2714 (mul -1
2715 (power var r)
2716 (add (mul b ($log a)) (mul c ($log h))))
2717 (div (mul -1 n) r))
2718 ($gamma_incomplete
2719 (div n r)
2720 (mul -1 (power var r) (add (mul b ($log a)) (mul c ($log h)))))))
2722 ((and (m2-exp-type-7-1 (facsum-exponent expr))
2723 (eq ($sign (sub (cdras 'r w) (cdras 'r1 w))) '$zero))
2724 (b c e g r v q u)
2725 (when *debug-integrate*
2726 (format t "~&Type 7-1: z^v*(%e^(b*z^r+e))^q*(%e^(c*z^r+g))^u : w = ~A~%" w))
2728 (mul const
2729 (div -1 r)
2730 (power '$%e (mul -1 (power var r) (add (mul b q) (mul c u))))
2731 (power (power '$%e (add e (mul b (power var r)))) q)
2732 (power (power '$%e (add g (mul c (power var r)))) u)
2733 (power var (add v 1))
2734 (power (mul -1 (power var r) (add (mul b q) (mul c u)))
2735 (div (mul -1 (add v 1)) r))
2736 (take '(%gamma_incomplete)
2737 (div (add v 1) r)
2738 (mul -1 (power var r) (add (mul b q) (mul c u))))))
2740 ((m2-exp-type-8 (facsum-exponent expr))
2741 (a b c d e f g h)
2742 (when *debug-integrate*
2743 (format t "~&Type 8: a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z)+f*z+g)")
2744 (format t "~& : w = ~A~%" w))
2746 (mul
2747 const
2748 (div 1 2)
2749 (power a e)
2750 (power h g)
2751 (add
2752 (mul 2
2753 (power a (add (mul b (power var (div 1 2))) (mul d var)))
2754 (power h (add (mul c (power var (div 1 2))) (mul f var)))
2755 (div 1 (add (mul d ($log a)) (mul f ($log h)))))
2756 (mul -1
2757 (power '$%pi (div 1 2))
2758 (power '$%e
2759 (mul -1
2760 (div
2761 (power (add (mul b ($log a)) (mul c ($log h))) 2)
2762 (mul 4 (add (mul d ($log a)) (mul f ($log h)))))))
2763 ($erfi
2764 (div
2765 (add
2766 (mul b ($log a))
2767 (mul c ($log h))
2768 (mul 2
2769 (power var (div 1 2))
2770 (add (mul d ($log a)) (mul f ($log h)))))
2771 (mul 2
2772 (power (add (mul d ($log a)) (mul f ($log h))) (div 1 2)))))
2773 (add (mul b ($log a)) (mul c ($log h)))
2774 (power (add (mul d ($log a)) (mul f ($log h))) (div -3 2))))))
2776 ((m2-exp-type-8-1 (facsum-exponent expr))
2777 (b c d e f g u v)
2778 (when *debug-integrate*
2779 (format t "~&Type 8-1: (%e^(b*sqrt(z)+d*z+e))^u*(%e^(c*sqrt(z)+f*z+g))^v")
2780 (format t "~& : w = ~A~%" w))
2782 (mul const
2783 (div 1 2)
2784 (power (add (mul d u) (mul f v)) (div -3 2))
2785 (mul (power '$%e
2786 (mul -1
2787 (power (add (mul b u)
2788 (mul 2 d u (power var (div 1 2)))
2789 (mul v (add c (mul 2 f (power var (div 1 2))))))
2791 (inv (mul 4 (add (mul d u) (mul f v))))))
2792 (power (power '$%e
2793 (add (mul b (power var (div 1 2)))
2795 (mul d var)))
2797 (power (power '$%e
2798 (add (mul c (power var (div 1 2)))
2800 (mul f var)))
2802 (add (mul 2
2803 (power '$%e
2804 (mul (power (add (mul b u)
2805 (mul 2 d u (power var (div 1 2)))
2806 (mul v (add c (mul 2 f (power var (div 1 2))))))
2808 (inv (mul 4 (add (mul d u) (mul f v))))))
2809 (power (add (mul d u) (mul f v)) (div 1 2)))
2810 (mul -1
2811 (power '$%pi (div 1 2))
2812 (add (mul b u) (mul c v))
2813 (take '(%erfi)
2814 (div (add (mul b u)
2815 (mul 2 d u (power var (div 1 2)))
2816 (mul c v)
2817 (mul 2 f v (power var (div 1 2))))
2818 (mul 2
2819 (power (add (mul d u) (mul f v))
2820 (div 1 2))))))))))
2822 ((and (m2-exp-type-8-2 (facsum-exponent expr))
2823 (eq ($sign (sub (cdras 'r w) (cdras 'r1 w))) '$zero))
2824 (b c e g r u v)
2825 (when *debug-integrate*
2826 (format t "~&Type 8-2: (%e^(b*z^r+e))^u*(%e^(c*z^r+g))^v")
2827 (format t "~& : w = ~A~%" w))
2829 (mul const
2831 (inv r)
2832 (power '$%e
2833 (mul -1
2834 (power var r)
2835 (add (mul b u) (mul c v))))
2836 (power (power '$%e
2837 (add (power var r) e))
2839 (power (power '$%e
2840 (add (power var r) g))
2843 (power (mul -1
2844 (power var r)
2845 (add (mul b u) (mul c v)))
2846 (div -1 r))
2847 (take '(%gamma_incomplete)
2848 (div 1 r)
2849 (mul -1 (power var r) (add (mul b u) (mul c v))))))
2851 ((and (m2-exp-type-9 (facsum-exponent expr))
2852 (maxima-integerp (cdras 'n w))
2853 (eq ($sign (cdras 'n w)) '$pos)
2854 (or (not (eq ($sign (cdras 'b w)) '$zero))
2855 (not (eq ($sign (cdras 'c w)) '$zero))))
2856 (a b c d e f g h n)
2857 (when *debug-integrate*
2858 (format t "~&Type 9: z^n*a^(b*z^2+d*z+e)*h^(c*z^2+f*z+g)")
2859 (format t "~& : w = ~A~%" w))
2861 (mul
2862 const
2863 (div -1 2)
2864 (power a e)
2865 (power h g)
2866 (power '$%e
2867 (div
2868 (power (add (mul d ($log a)) (mul f ($log h))) 2)
2869 (mul -4 (add (mul b ($log a)) (mul c ($log h))))))
2870 (power (add (mul b ($log a)) (mul c ($log h))) (mul -1 (add n 1)))
2871 (let ((index (gensumindex))
2872 ($simpsum t))
2873 (mfuncall '$sum
2874 (mul
2875 (power 2 (sub index n))
2876 ($binomial n index)
2877 (power
2878 (add (mul -1 d ($log a)) (mul -1 f ($log h)))
2879 (sub n index))
2880 (power
2881 (add
2882 (mul (add d (mul 2 b var)) ($log a))
2883 (mul (add f (mul 2 c var)) ($log h)))
2884 (add index 1))
2885 (power
2886 (mul -1
2887 (div
2888 (power
2889 (add
2890 (mul (add d (mul 2 b var)) ($log a))
2891 (mul (add f (mul 2 c var)) ($log h)))
2893 (add (mul b ($log a)) (mul c ($log h)))))
2894 (div (add index 1) -2))
2895 ($gamma_incomplete
2896 (div (add index 1) 2)
2897 (mul -1
2898 (div
2899 (power
2900 (add
2901 (mul (add d (mul 2 b var)) ($log a))
2902 (mul (add f (mul 2 c var)) ($log h)))
2904 (mul 4 (add (mul b ($log a)) (mul c ($log h))))))))
2905 index 0 n))))
2907 ((and (m2-exp-type-9-1 (facsum-exponent expr))
2908 (maxima-integerp (cdras 'n w))
2909 (eq ($sign (cdras 'n w)) '$pos)
2910 (or (not (eq ($sign (cdras 'b w)) '$zero))
2911 (not (eq ($sign (cdras 'c w)) '$zero))))
2912 (b c d e f g q u n)
2913 (when *debug-integrate*
2914 (format t "~&Type 9-1: z^n*(%e^(b*z^2+d*z+e))^q*(%e^(c*z^2+f*z+g))^u")
2915 (format t "~& : w = ~A~%" w))
2917 (mul const
2918 (div -1 2)
2919 (power (add (mul b q) (mul c u)) (div -1 2))
2920 (power '$%e
2921 (add (div (power (add (mul d q) (mul f u)) 2)
2922 (mul -4 (add (mul b q) (mul c u))))
2923 (mul -1 var
2924 (add (mul d q)
2925 (mul b q var)
2926 (mul f u)
2927 (mul c u var)))))
2928 (power (power '$%e
2929 (add e
2930 (mul var (add d (mul b var)))))
2932 (power (power '$%e
2933 (add g
2934 (mul var (add f (mul c var)))))
2936 (let ((index (gensumindex))
2937 ($simpsum t))
2938 (dosum
2939 (mul (power 2 (sub index n))
2940 (power (add (mul b q) (mul c u)) (neg (add n (div 1 2))))
2941 (power (add (neg (mul d q)) (neg (mul f u)))
2942 (sub n index))
2943 (power (add (mul d q)
2944 (mul f u)
2945 (mul 2 var (add (mul b q) (mul c u))))
2946 (add index 1))
2947 (power (div (power (add (mul d q)
2948 (mul f u)
2949 (mul 2
2950 (add (mul b q)
2951 (mul c u))
2952 var))
2954 (neg (add (mul b q) (mul c u))))
2955 (mul (div -1 2) (add index 1)))
2956 (take '(%binomial) n index)
2957 (take '(%gamma_incomplete)
2958 (div (add index 1) 2)
2959 (div (power (add (mul d q)
2960 (mul f u)
2961 (mul 2
2962 (add (mul b q)
2963 (mul c u))
2964 var))
2966 (mul -4 (add (mul b q) (mul c u))))))
2967 index 0 n t))))
2969 ((and (m2-exp-type-10 (facsum-exponent expr))
2970 (maxima-integerp (cdras 'n w))
2971 (eq ($sign (cdras 'n w)) '$pos)
2972 (or (not (eq ($sign (cdras 'b w)) '$zero))
2973 (not (eq ($sign (cdras 'c w)) '$zero))))
2974 (a b c d e f g h n)
2975 (when *debug-integrate*
2976 (format t "~&Type 10: z^n*a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z)+f*z+g)")
2977 (format t "~& : w = ~A~%" w))
2979 (mul const
2980 (power 2 (add (mul -2 n) -1))
2981 (power a e)
2982 (power h g)
2983 (power '$%e
2984 (div (power (add (mul b ($log a)) (mul c ($log h))) 2)
2985 (mul -4 (add (mul d ($log a)) (mul f ($log h))))))
2986 (power (add (mul d ($log a)) (mul f ($log h))) (mul -2 (add n 1)))
2987 (let ((index1 (gensumindex))
2988 (index2 (gensumindex))
2989 ($simpsum t))
2990 (dosum
2991 (dosum
2992 (mul (power -1 (sub index1 index2))
2993 (power 4 index1)
2994 ($binomial index1 index2)
2995 ($binomial n index1)
2996 (power (add (mul b ($log a)) (mul c ($log h)))
2997 (sub (mul 2 n) (add index1 index2)))
2998 (power (add (mul b ($log a))
2999 (mul c ($log h))
3000 (mul 2
3001 (power var (div 1 2))
3002 (add (mul d ($log a)) (mul f ($log h)))))
3003 (add index1 index2))
3004 (power (mul -1
3005 (div (power (add (mul b ($log a))
3006 (mul c ($log h))
3007 (mul 2
3008 (power var (div 1 2))
3009 (add (mul d ($log a))
3010 (mul f ($log h)))))
3012 (add (mul d ($log a)) (mul f ($log h)))))
3013 (mul (div -1 2) (add index1 index2 1)))
3014 (add (mul ($gamma_incomplete (mul (div 1 2)
3015 (add index1 index2 1))
3016 (mul (div -1 4)
3017 (div (power (add (mul b ($log a))
3018 (mul c ($log h))
3019 (mul 2
3020 (power var (div 1 2))
3021 (add (mul d ($log a)) (mul f ($log h)))))
3023 (add (mul d ($log a)) (mul f ($log h))))))
3024 (add (mul b ($log a)) (mul c ($log h)))
3025 (add (mul b ($log a))
3026 (mul c ($log h))
3027 (mul 2
3028 (power var (div 1 2))
3029 (add (mul d ($log a)) (mul f ($log h))))))
3030 (mul 2
3031 ($gamma_incomplete (mul (div 1 2)
3032 (add index1 index2 2))
3033 (mul (div -1 4)
3034 (div (power (add (mul b ($log a))
3035 (mul c ($log h))
3036 (mul 2
3037 (power var (div 1 2))
3038 (add (mul d ($log a))
3039 (mul f ($log h)))))
3041 (add (mul d ($log a))
3042 (mul f ($log h))))))
3043 (add (mul d ($log a)) (mul f ($log h)))
3044 (power (mul -1
3045 (div (power (add (mul b ($log a))
3046 (mul c ($log h))
3047 (mul 2
3048 (power var (div 1 2))
3049 (add (mul d ($log a))
3050 (mul f ($log h)))))
3052 (add (mul d ($log a))
3053 (mul f ($log h)))))
3054 (div 1 2)))))
3055 index2 0 index1 t)
3056 index1 0 n t))))
3058 ((and (m2-exp-type-10-1 (facsum-exponent expr))
3059 (maxima-integerp (cdras 'n w))
3060 (eq ($sign (cdras 'n w)) '$pos)
3061 (or (not (eq ($sign (cdras 'b w)) '$zero))
3062 (not (eq ($sign (cdras 'c w)) '$zero))))
3063 (b c d e f g q u n)
3064 (let ((bq+cu (add (mul b q) (mul c u)))
3065 (dq+fu (add (mul d q) (mul f u))))
3066 (when *debug-integrate*
3067 (format t "~&Type 10-1: z^n*(%e^(b*sqrt(z)+d*z+e))^q*(%e^(c*sqrt(z)+f*z+g))^u")
3068 (format t "~& : w = ~A~%" w))
3070 (mul const
3071 (power 2 (mul -1 (add (mul 2 n) 1)))
3072 (power '$%e
3073 (add (div (mul -1 (power bq+cu 2)) (mul 4 dq+fu))
3074 (mul -1 d var q)
3075 (mul -1 b (power var (div 1 2)) q)
3076 (mul -1 f var u)
3077 (mul -1 c (power var (div 1 2)) u)))
3078 (power (power '$%e
3079 (add (mul b (power var (div 1 2)))
3080 (mul d var)
3083 (power (power '$%e
3084 (add (mul c (power var (div 1 2)))
3085 (mul f var)
3088 (power dq+fu (mul -2 (add n 1)))
3089 (let ((index1 (gensumindex))
3090 (index2 (gensumindex))
3091 ($simpsum t))
3092 (dosum
3093 (dosum
3094 (mul (power -1 (sub index1 index2))
3095 (power 4 index1)
3096 (power bq+cu
3097 (add (neg index1) (neg index2) (mul 2 n)))
3098 (power (add bq+cu
3099 (mul 2 (power var (div 1 2)) dq+fu))
3100 (add index1 index2))
3101 (power (div (power (add bq+cu
3102 (mul 2
3103 (power var (div 1 2))
3104 dq+fu))
3106 (mul -1 dq+fu))
3107 (mul (div -1 2)
3108 (add index1 index2 1)))
3109 (take '(%binomial) index1 index2)
3110 (take '(%binomial) n index1)
3111 (add (mul bq+cu
3112 (add bq+cu
3113 (mul 2
3114 (power var (div 1 2))
3115 dq+fu))
3116 (take '(%gamma_incomplete)
3117 (mul (div 1 2)
3118 (add index1 index2 1))
3119 (div (power (add (mul b q)
3120 (mul c u)
3121 (mul 2
3122 (power var (div 1 2))
3123 dq+fu))
3125 (mul -4
3126 dq+fu))))
3127 (mul 2
3128 (power (div (power (add bq+cu
3129 (mul 2
3130 (power var (div 1 2))
3131 dq+fu))
3133 (mul 1 dq+fu))
3134 (div 1 2))
3135 dq+fu
3136 (take '(%gamma_incomplete)
3137 (mul (div 1 2)
3138 (add index1 index2 2))
3139 (div (power (add bq+cu
3140 (mul 2
3141 (power var (div 1 2))
3142 dq+fu))
3144 (mul -4
3145 dq+fu))))))
3146 index2 0 index1 t)
3147 index1 0 n t)))))))
3149 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3151 ;;; Do a facsum for the exponent of power functions.
3152 ;;; This is necessary to integrate all general forms. The pattern matcher is
3153 ;;; not powerful enough to do the job.
3155 (defun facsum-exponent (expr)
3156 ;; Make sure that expr has the form ((mtimes) factor1 factor2 ...)
3157 (when (not (mtimesp expr)) (setq expr (list '(mtimes) expr)))
3158 (do ((result nil)
3159 (l (cdr expr) (cdr l)))
3160 ((null l) (cons (list 'mtimes) result))
3161 (cond
3162 ((mexptp (car l))
3163 ;; Found an power function. Factor the exponent with facsum.
3164 (let* ((fac (mfuncall '$facsum (caddr (car l)) var))
3165 (num ($num fac))
3166 (den ($denom fac)))
3167 (setq result
3168 (cons (cons (list 'mexpt)
3169 (cons (cadr (car l))
3170 (if (equal 1 den)
3171 (list num)
3172 (list ($multthru (inv den) num)))))
3173 result))))
3175 ;; Nothing to do.
3176 (setq result (cons (car l) result))))))
3178 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;