Merge branch 'rtoy-mathjax-for-lapack'
[maxima.git] / src / sin.lisp
blob098b19c203150f95118e87ef69e5c7df668d5fa0
1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancements. ;;;;;
4 ;;; ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; (c) Copyright 1982 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11 (in-package :maxima)
13 (macsyma-module 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 (defvar *debug-integrate* nil
24 "Enable debugging for the integrator routines.")
26 ;; When T do not call the risch integrator. This flag can be set by the risch
27 ;; integrator to avoid endless loops when calling the integrator from risch.
28 (defvar *in-risch-p* nil)
30 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32 ;;; Predicate functions
34 ;; Note: varp and freevarp are not used in this file anymore. But
35 ;; they are used in other files. Someday, varp and freevarp should be
36 ;; moved elsewhere.
37 (declaim (inline varp))
38 (defun varp (x)
39 (declare (special var))
40 (alike1 x var))
42 (defun freevar (a)
43 (declare (special var))
44 (cond ((atom a) (not (eq a var)))
45 ((varp a) nil)
46 ((and (not (atom (car a)))
47 (member 'array (cdar a) :test #'eq))
48 (cond ((freevar (cdr a)) t)
49 (t (merror "~&FREEVAR: variable of integration appeared in subscript."))))
50 (t (and (freevar (car a)) (freevar (cdr a))))))
52 ;; Same as varp, but the second arg specifiies the variable to be
53 ;; tested instead of using the special variable VAR.
54 (defun varp2 (x var2)
55 (alike1 x var2))
57 ;; Like freevar bug the second arg specifies the variable to be tested
58 ;; instead of using the special variable VAR.
59 (defun freevar2 (a var2)
60 (cond ((atom a) (not (eq a var2)))
61 ((varp2 a var2) nil)
62 ((and (not (atom (car a)))
63 (member 'array (cdar a) :test #'eq))
64 (cond ((freevar2 (cdr a) var2) t)
65 (t (merror "~&FREEVAR: variable of integration appeared in subscript."))))
66 (t (and (freevar2 (car a) var2) (freevar2 (cdr a) var2)))))
68 (defun integerp1 (x)
69 "Returns 2*x if 2*x is an integer, else nil"
70 (integerp2 (mul2* 2 x)))
72 (defun integerp2 (x)
73 "Returns x if x is an integer, else false"
74 (let (u)
75 (cond ((not (numberp x)) nil)
76 ((not (floatp x)) x)
77 ((prog2 (setq u (maxima-rationalize x))
78 (equal (cdr u) 1))
79 (car u)))))
81 ;; This predicate is used with m2 pattern matcher.
82 ;; A rational expression in var2.
83 (defun rat8 (ex var2)
84 (cond ((or (varp2 ex var2) (freevar2 ex var2))
86 ((member (caar ex) '(mplus mtimes) :test #'eq)
87 (do ((u (cdr ex) (cdr u)))
88 ((null u) t)
89 (if (not (rat8 (car u) var2))
90 (return nil))))
91 ((not (eq (caar ex) 'mexpt))
92 nil)
93 ((integerp (caddr ex))
94 (rat8 (cadr ex) var2))))
96 ;; Predicate for m2 pattern matcher
97 (defun rat8prime (c var2)
98 (and (rat8 c var2)
99 (or (not (mnump c))
100 (not (zerop1 c)))))
102 ;; Predicate for m2 patter matcher
103 (defun elem (a expres var2)
104 (cond ((freevar2 a var2) t)
105 ((atom a) nil)
106 ((m2 a expres) t)
107 (t (every #'(lambda (f)
108 (elem f expres var2))
109 (cdr a)))))
111 ;; Like freevar0 (in hypgeo.lisp), but we take a second arg to specify
112 ;; the variable instead of implicitly using VAR.
113 (defun freevar02 (m var2)
114 (cond ((equal m 0) nil)
115 (t (freevar2 m var2))))
117 ;; Like free1 in schatc, but takes an extra arg for the variable.
118 (defun free12 (a var2)
119 (and (null (pzerop a))
120 (free a var2)))
124 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
126 (defun rationalizer (x)
127 (let ((ex (simplify ($factor x))))
128 (if (not (alike1 ex x)) ex)))
130 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
132 ;;; Stage II of the Integrator
134 ;;; Check if the problem can be transformed or solved by special methods.
135 ;;; 11 Methods are implemented by Moses, some more have been added.
137 (let (powerl)
138 ;; POWERL is initialized in INTEGRATOR to NIL and can be modified in
139 ;; INTFORM in certain cases and is read by INTEGRATOR in some cases.
140 ;; Instead of a global special variable, use a closure.
142 ;; It would be really good to get rid of the special variable *EXP*
143 ;; used only in INTFORM and INTEGRATOR. I (rtoy) haven't been able
144 ;; to figure out exactly how to do that.
146 (defun intform (expres var2 &aux w arg)
147 (declare (special *exp*))
148 (cond ((freevar2 expres var2) nil)
149 ((atom expres) nil)
151 ;; Map the function intform over the arguments of a sum or a product
152 ((member (caar expres) '(mplus mtimes) :test #'eq)
153 (some #'(lambda (ex)
154 (intform ex var2))
155 (cdr expres)))
157 ((or (eq (caar expres) '%log)
158 (arcp (caar expres)))
159 (cond
160 ;; Method 9: Rational function times a log or arctric function
161 ((setq arg (m2 *exp*
162 `((mtimes) ((,(caar expres)) (b rat8 ,var2))
163 ((coefftt) (c rat8prime ,var2)))))
164 ;; Integrand is of the form R(x)*F(S(x)) where F is a log, or
165 ;; arctric function and R(x) and S(x) are rational functions.
166 (ratlog var2 (cons (cons 'a expres) arg)))
168 (prog (y z)
169 (cond
170 ((setq y (intform (cadr expres) var2)) (return y))
172 ;; Method 10: Rational function times log(b*x+a)
173 ((and (eq (caar expres) '%log)
174 (setq z (m2-b*x+a (cadr expres) var2))
175 (setq y (m2 *exp*
176 `((mtimes)
177 ((coefftt) (c rat8 ,var2))
178 ((coefftt) (d elem ,expres ,var2))))))
179 (return
180 (let ((a (cdr (assoc 'a z :test #'eq)))
181 (b (cdr (assoc 'b z :test #'eq)))
182 (c (cdr (assoc 'c y :test #'eq)))
183 (d (cdr (assoc 'd y :test #'eq)))
184 (newvar (gensym "intform")))
185 ;; keep var from appearing in questions to user
186 (putprop newvar t 'internal)
187 ;; Substitute y = log(b*x+a) and integrate again
188 (substint
189 expres
190 newvar
191 (integrator
192 (muln
193 (list (maxima-substitute
194 `((mquotient) ((mplus) ((mexpt) $%e ,newvar)
195 ((mtimes) -1 ,a))
197 var2
199 `((mquotient) ((mexpt) $%e ,newvar) ,b)
200 (maxima-substitute newvar expres d))
201 nil)
202 newvar)
203 var2
204 *exp*))))
205 (t (return nil)))))))
207 ;; We have a special function with an integral on the property list.
208 ;; After the integral property was defined for the trig functions,
209 ;; in rev 1.52, need to exclude trig functions here.
210 ((and (not (atom (car expres)))
211 (not (optrig (caar expres)))
212 (not (eq (caar expres) 'mexpt))
213 (get (caar expres) 'integral))
214 (when *debug-integrate*
215 (format t "~&INTFORM: found 'INTEGRAL on property list~%"))
216 (cond
217 ((setq arg
218 (m2 *exp* `((mtimes) ((,(caar expres)) (b rat8 ,var2)) ((coefftt) (c rat8prime ,var2)))))
219 ;; A rational function times the special function.
220 ;; Integrate with the method integration-by-parts.
221 (partial-integration (cons (cons 'a expres) arg) var2))
222 ;; The method of integration-by-parts can not be applied.
223 ;; Maxima tries to get a clue for the argument of the function which
224 ;; allows a substitution for the argument.
225 ((intform (cadr expres) var2))
226 (t nil)))
228 ;; Method 6: Elementary function of trigonometric functions
229 ((optrig (caar expres))
230 (cond ((not (setq w (m2-b*x+a (cadr expres) var2)))
231 (intform (cadr expres) var2))
233 (prog2
234 (setq powerl t)
235 (monstertrig *exp* var2 (cadr expres))))))
237 ((and (eq (caar expres) '%derivative)
238 (eq (caar *exp*) (caar expres))
239 (checkderiv *exp* var2)))
241 ;; Stop intform if we have not a power function.
242 ((not (eq (caar expres) 'mexpt)) nil)
244 ;; Method 2: Substitution for an integral power
245 ((integerp (caddr expres)) (intform (cadr expres) var2))
247 ;; Method 1: Elementary function of exponentials
248 ((freevar2 (cadr expres) var2)
249 (cond ((setq w (m2-b*x+a (caddr expres) var2))
250 (superexpt *exp* var2 (cadr expres) w))
251 ((intform (caddr expres) var2))
252 ((and (eq '$%e (cadr expres))
253 (isinop (caddr expres) '%log))
254 ;; Found something like exp(r*log(x))
255 (let* (($%e_to_numlog t)
256 ($radexpand nil) ; do not simplify sqrt(x^2) -> abs(x)
257 (nexp (resimplify *exp*)))
258 (cond ((alike1 *exp* nexp) nil)
259 (t (integrator (setq *exp* nexp) var2)))))
260 (t nil)))
262 ;; The base is not a rational function. Try to get a clue for the base.
263 ((not (rat8 (cadr expres) var2))
264 (intform (cadr expres) var2))
266 ;; Method 3: Substitution for a rational root
267 ((and (setq w (m2-ratrootform (cadr expres) var2)) ; e*(a*x+b) / (c*x+d)
268 (denomfind (caddr expres))) ; expon is ratnum
269 (or (progn
270 (setq powerl t)
271 (ratroot *exp* var2 (cadr expres) w))
272 (inte *exp* var2)))
274 ;; Method 4: Binomial - Chebyschev
275 ((not (integerp1 (caddr expres))) ; 2*exponent not integer
276 (cond ((m2-chebyform *exp* var2)
277 (chebyf *exp* var2))
278 (t (intform (cadr expres) var2))))
280 ;; Method 5: Arctrigonometric substitution
281 ((setq w (m2-c*x^2+b*x+a (cadr expres) var2)) ; sqrt(c*x^2+b*x+a)
282 #+nil
283 (format t "expres = sqrt(c*x^2+b*x+a)~%")
284 ;; I think this is method 5, arctrigonometric substitutions.
285 ;; (Moses, pg 80.) The integrand is of the form
286 ;; R(x,sqrt(c*x^2+b*x+a)). This method first eliminates the b
287 ;; term of the quadratic, and then uses an arctrig substitution.
288 (inte *exp* var2))
290 ;; Method 4: Binomial - Chebyschev
291 ((m2-chebyform *exp* var2)
292 (chebyf *exp* var2))
294 ;; Expand expres.
295 ;; Substitute the expanded factor into the integrand and try again.
296 ((not (m2 (setq w ($expand (cadr expres)))
297 (cadr expres)))
298 (prog2
299 (setq *exp* (maxima-substitute w (cadr expres) *exp*))
300 (intform (simplify (list '(mexpt) w (caddr expres)))
301 var2)))
303 ;; Factor expres.
304 ;; Substitute the factored factor into the integrand and try again.
305 ((setq w (rationalizer (cadr expres)))
306 ;; The forms below used to have $radexpand set to $all. But I
307 ;; don't think we really want to do that here because that makes
308 ;; sqrt(x^2) become x, which might be totally wrong. This is one
309 ;; reason why we returned -4/3 for the
310 ;; integrate(sqrt(x+1/x-2),x,0,1). We were replacing
311 ;; sqrt((x-1)^2) with x - 1, which is totally wrong since 0 <= x
312 ;; <= 1.
313 (setq *exp* (let (($radexpand $radexpand))
314 (maxima-substitute w (cadr expres) *exp*)))
315 (intform (let (($radexpand '$all))
316 (simplify (list '(mexpt) w (caddr expres))))
317 var2))))
318 ;;------------------------------------------------------------------------------
320 ;; This is the main integration routine. It is called from sinint.
322 (defun integrator (*exp* var2 &optional stack)
323 (declare (special *exp*))
324 (prog (y const w arcpart coef integrand result)
325 (declare (special *integrator-level*))
326 (setq powerl nil)
327 ;; Increment recursion counter
328 (incf *integrator-level*)
330 ;; Trivial case. exp is not a function of var2.
331 (if (freevar2 *exp* var2) (return (mul2* *exp* var2)))
333 ;; Remove constant factors
334 (setq w (partition *exp* var2 1))
335 (setq const (car w))
336 (setq *exp* (cdr w))
337 #+nil
338 (progn
339 (format t "w = ~A~%" w)
340 (format t "const = ~A~%" const)
341 (format t "exp = ~A~%" *exp*))
343 (cond ;; First stage, Method I: Integrate a sum.
344 ((mplusp *exp*)
345 (return (mul2* const (integrate1 (cdr *exp*) var2))))
347 ;; Convert atan2(a,b) to atan(a/b) and try again.
348 ((setq w (isinop *exp* '%atan2))
349 (setq *exp*
350 (maxima-substitute (take '(%atan) (div (cadr w) (caddr w)))
352 *exp*))
353 (return (mul* const
354 (integrator *exp* var2 stack))))
356 ;; First stage, Method II: Integrate sums.
357 ((and (not (atom *exp*))
358 (eq (caar *exp*) '%sum))
359 (return (mul2* const (intsum *exp* var2))))
361 ;; First stage, Method III: Try derivative-divides method.
362 ;; This is the workhorse that solves many integrals.
363 ((setq y (diffdiv *exp* var2))
364 (return (mul2* const y))))
366 ;; At this point, we have EXP as a product of terms. Make Y a
367 ;; list of the terms of the product.
368 (setq y (cond ((mtimesp *exp*)
369 (cdr *exp*))
371 (list *exp*))))
373 ;; Second stage:
374 ;; We're looking at each term of the product and check if we can
375 ;; apply one of the special methods.
376 loop
377 #+nil
378 (progn
379 (format t "car y =~%")
380 (maxima-display (car y)))
381 (cond ((rat8 (car y) var2)
382 #+nil
383 (format t "In loop, go skip~%")
384 (go skip))
385 ((and (setq w (intform (car y) var2))
386 ;; Do not return a noun form as result at this point, because
387 ;; we would like to check for further special integrals.
388 ;; We store the result for later use.
389 (setq result w)
390 (not (isinop w '%integrate)))
391 #+nil
392 (format t "In loop, case intform~%")
393 (return (mul2* const w)))
395 #+nil
396 (format t "In loop, go special~%")
397 ;; Store a possible partial result
398 (setq result w)
399 (go special)))
400 skip
401 (setq y (cdr y))
402 (cond ((null y)
403 ;; Method 8: Rational functions
404 (return (mul2* const (cond ((setq y (powerlist *exp* var2)) y)
405 (t (ratint *exp* var2)))))))
406 (go loop)
408 special
409 ;; Third stage: Try more general methods
411 ;; SEPARC SETQS ARCPART AND COEF SUCH THAT
412 ;; COEF*ARCEXP=EXP WHERE ARCEXP IS OF THE FORM
413 ;; ARCFUNC^N AND COEF IS ITS ALGEBRAIC COEFFICIENT
414 (multiple-value-setq
415 (arcpart coef)
416 (separc *exp*))
418 #+nil
419 (progn
420 (format t "arcpart = ~A~%" arcpart)
421 (format t "coef =~%")
422 (maxima-display coef))
423 (cond ((and (not (null arcpart))
424 (do ((stacklist stack (cdr stacklist)))
425 ((null stacklist) t)
426 (cond ((alike1 (car stacklist) coef)
427 (return nil))))
428 (not (isinop (setq w (let ((stack (cons coef stack)))
429 (integrator coef var2 stack)))
430 '%integrate))
431 (setq integrand (mul2 w (sdiff arcpart var2)))
432 (do ((stacklist stack (cdr stacklist)))
433 ((null stacklist) t)
434 (cond ((alike1 (car stacklist) integrand)
435 (return nil))))
436 (not (isinop
437 (setq y (let ((stack (cons integrand stack))
438 (integ integrand))
439 (integrator integ var2 stack)))
440 '%integrate)))
441 (return (add* (list '(mtimes) const w arcpart)
442 (list '(mtimes) -1 const y))))
444 (return
445 (mul* const
446 (cond ((setq y (scep *exp* var2))
447 (cond ((cddr y)
448 #+nil
449 (progn
450 (format t "cddr y =~%")
451 (maxima-display (cddr y)))
452 (integrator ($trigreduce *exp*) var2 stack))
453 (t (sce-int (car y) (cadr y) var2))))
454 ;; I don't understand why we do this. This
455 ;; causes the stack overflow in Bug
456 ;; 1487703, because we keep expanding *exp*
457 ;; into a form that matches the original
458 ;; and therefore we loop forever. To
459 ;; break this we keep track how how many
460 ;; times we've tried this and give up
461 ;; after 4 (arbitrarily selected) times.
462 ((and (< *integrator-level* 4)
463 (not (alike1 *exp* (setq y ($expand *exp*)))))
464 #+nil
465 (progn
466 (format t "*exp* = ~A~%" *exp*)
467 (maxima-display *exp*)
468 (format t "y = ~A~%" y)
469 (maxima-display y)
470 (break))
471 (integrator y var2 stack))
472 ((and (not powerl)
473 (setq y (powerlist *exp* var2)))
475 ((and (not *in-risch-p*) ; Not called from rischint
476 (setq y (rischint *exp* var2))
477 ;; rischint has not found an integral but
478 ;; returns a noun form. Do not return that
479 ;; noun form as result at this point, but
480 ;; store it for later use.
481 (setq result y)
482 (not (isinop y '%integrate)))
484 ((setq y (integrate-exp-special *exp* var2))
485 ;; Maxima found an integral for a power function
488 ;; Integrate-exp-special has not found an integral
489 ;; We look for a previous result obtained by
490 ;; intform or rischint.
491 (if result
492 result
493 (list '(%integrate) *exp* var2)))))))))))
495 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
497 (defun separc (ex)
498 (let (arcpart coef)
499 (labels
500 ((arcfuncp (ex)
501 (and (not (atom ex))
502 (or (arcp (caar ex))
503 (eq (caar ex) '%log) ; Experimentally treat logs also.
504 (and (eq (caar ex) 'mexpt)
505 (integerp2 (caddr ex))
506 (> (integerp2 (caddr ex)) 0)
507 (arcfuncp (cadr ex))))))
508 (arclist (list)
509 (cond ((null list)
510 nil)
511 ((and (arcfuncp (car list))
512 (null arcpart))
513 (setq arcpart (car list))
514 (arclist (cdr list)))
516 (setq coef (cons (car list) coef))
517 (arclist (cdr list))))))
518 (cond ((arcfuncp ex)
519 (setq arcpart ex
520 coef 1))
521 ((and (consp ex)
522 (eq (caar ex) 'mtimes))
523 (arclist (cdr ex))
524 (setq coef (cond ((null (cdr coef))
525 (car coef))
527 (setq coef (cons (car ex) coef)))))))
528 (values arcpart coef))))
530 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
532 ;;; Five pattern for the Integrator and other routines.
534 ;; This is matching the pattern e*(a*x+b)/(c*x+d), where
535 ;; a, b, c, d, and e are free of x, and x is the variable of integration.
536 (defun m2-ratrootform (expr var2)
537 (m2 expr
538 `((mtimes)
539 ((coefftt) (e freevar2 ,var2))
540 ((mplus)
541 ((coeffpt) (a freevar2 ,var2) (var varp2 ,var2))
542 ((coeffpt) (b freevar2 ,var2)))
543 ((mexpt)
544 ((mplus)
545 ((coeffpt) (c freevar2 ,var2) (var varp2 ,var2))
546 ((coeffpt) (d freevar2 ,var2)))
547 -1))))
549 ;; This is for matching the pattern a*x^r1*(c1+c2*x^q)^r2.
550 (defun m2-chebyform (expr var2)
551 (m2 expr
552 `((mtimes)
553 ((mexpt) (var varp2 ,var2) (r1 numberp))
554 ((mexpt)
555 ((mplus)
556 ((mtimes)
557 ((coefftt) (c2 freevar2 ,var2))
558 ((mexpt) (var varp2 ,var2) (q free12 ,var2)))
559 ((coeffpp) (c1 freevar2 ,var2)))
560 (r2 numberp))
561 ((coefftt) (a freevar2 ,var2)))))
563 ;; Pattern to match b*x + a
564 (defun m2-b*x+a (expr var2)
565 (m2 expr
566 `((mplus)
567 ((coeffpt) (b freevar2 ,var2) (x varp2 ,var2))
568 ((coeffpt) (a freevar2 ,var2)))))
570 ;; This is the pattern c*x^2 + b * x + a.
571 (defun m2-c*x^2+b*x+a (expr var2)
572 (m2 expr
573 `((mplus)
574 ((coeffpt) (c freevar2 ,var2) ((mexpt) (x varp2 ,var2) 2))
575 ((coeffpt) (b freevar2 ,var2) (x varp2 ,var2))
576 ((coeffpt) (a freevar2 ,var2)))))
578 ;; This is the pattern (a*x+b)*(c*x+d)
579 ;; NOTE: This doesn't seem to be used anywhere in Maxima.
580 (defun m2-a*x+b/c*x+d (expr)
581 (m2 expr
582 `((mtimes)
583 ((mplus)
584 ((coeffpt) (a freevar) (var varp))
585 ((coeffpt) (b freevar)))
586 ((mplus)
587 ((coeffpt) (c freevar) (var varp))
588 ((coeffpt) (d freevar))))))
590 (defun optrig (x)
591 (member x '(%sin %cos %sec %tan %csc %cot) :test #'eq))
593 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
595 ;;; Stage I
596 ;;; Implementation of Method 1: Integrate a sum
598 ;;after finding a non-integrable summand usually better to pass rest to risch
599 (defun integrate1 (expr var2)
600 (do ((terms expr (cdr terms)) (ans))
601 ((null terms) (addn ans nil))
602 (let ($liflag) ; don't gen li's for
603 (push (integrator (car terms) var2) ans)) ; parts of integrand
604 (when (and (not *in-risch-p*) ; Not called from rischint
605 (not (free (car ans) '%integrate))
606 (cdr terms))
607 (return (addn (cons (rischint (cons '(mplus) terms) var2) (cdr ans))
608 nil)))))
610 (defun scep (expr var2 &aux trigl ex) ; Product of SIN, COS, EXP
611 (and (mtimesp expr) ; of linear args.
612 (loop for fac in (cdr expr) do
613 (cond ((atom fac) (return nil))
614 ((trig1 (car fac))
615 (if (linearp (cadr fac) var2) (push fac trigl)
616 (return nil)))
617 ((and (mexptp fac)
618 (eq (cadr fac) '$%e)
619 (linearp (caddr fac) var2))
620 ;; should be only one exponential factor
621 (setq ex fac))
622 (t (return nil)))
623 finally (return (cons ex trigl)))))
625 ;; Integrates exponential * sin or cos, all with linear args.
627 (defun sce-int (expr s-c var2) ; EXP is non-trivial
628 (let* ((e-coef (car (islinear (caddr expr) var2)))
629 (sc-coef (car (islinear (cadr s-c) var2)))
630 (sc-arg (cadr s-c))
631 (abs-val (add (power e-coef 2) (power sc-coef 2))))
632 (if (zerop1 abs-val)
633 ;; The numerator is zero. Exponentialize the integrand and try again.
634 (integrator ($exponentialize (mul expr s-c)) var2)
635 (mul (div expr abs-val)
636 (add (mul e-coef s-c)
637 (if (eq (caar s-c) '%sin)
638 (mul* (neg sc-coef) `((%cos) ,sc-arg))
639 (mul* sc-coef `((%sin) ,sc-arg))))))))
641 (defun checkderiv (expr var2)
642 (checkderiv1 (cadr expr) (cddr expr) () var2))
644 ;; CHECKDERIV1 gets called on the expression being differentiated,
645 ;; an alternating list of variables being differentiated with
646 ;; respect to and powers thereof, and a reversed list of the latter
647 ;; that have already been examined. It returns either the antiderivative
648 ;; or (), saying this derivative isn't wrt the variable of integration.
650 (defun checkderiv1 (expr wrt old-wrt var2)
651 (cond ((varp2 (car wrt) var2)
652 (if (equal (cadr wrt) 1) ;Power = 1?
653 (if (null (cddr wrt)) ;single or partial
654 (if (null old-wrt)
655 expr ;single
656 `((%derivative), expr ;partial in old-wrt
657 ,.(nreverse old-wrt)))
658 `((%derivative) ,expr ;Partial, return rest
659 ,.(nreverse old-wrt)
660 ,@(cddr wrt)))
661 `((%derivative) ,expr ;Higher order, reduce order
662 ,.(nreverse old-wrt)
663 ,(car wrt) ,(add* (cadr wrt) -1)
664 ,@ (cddr wrt))))
665 ((null (cddr wrt)) () ) ;Say it doesn't apply here
666 (t (checkderiv1 expr (cddr wrt) ;Else we check later terms
667 (list* (cadr wrt) (car wrt) old-wrt)
668 var2))))
670 (defun integrallookups (expr var2)
671 (let (form dummy-args real-args)
672 (cond
673 ((eq (caar expr) 'mqapply)
674 ;; Transform to functional form and try again.
675 ;; For example:
676 ;; ((MQAPPLY SIMP) (($PSI SIMP ARRAY) 1) $X)
677 ;; => (($PSI) 1 $X)
678 (integrallookups `((,(caaadr expr)) ,@(cdadr expr) ,@(cddr expr))
679 var2))
681 ;; Lookup algorithm for integral of a special function.
682 ;; The integral form is put on the property list, and can be a
683 ;; lisp function of the args. If the form is nil, or evaluates
684 ;; to nil, then return noun form unevaluated.
685 ((and (not (atom (car expr)))
686 (setq form (get (caar expr) 'integral))
687 (setq dummy-args (car form))
688 (setq real-args (cdr expr))
689 ;; search through the args of expr and find the arg containing var2
690 ;; look up the integral wrt this arg from form
691 (setq form
692 (do ((x real-args (cdr x))
693 (y (cdr form) (cdr y)))
694 ((or (null x) (null y)) nil)
695 (if (not (freevar2 (car x) var2)) (return (car y)))))
696 ;; If form is a function then evaluate it with actual args
697 (or (not (functionp form))
698 (setq form (apply form real-args))))
699 (when *debug-integrate*
700 (format t "~&INTEGRALLOOKUPS: Found integral ~A.~%" (caar expr)))
701 (substitutel real-args dummy-args form))
703 ((eq (caar expr) 'mplus)
704 (muln (list '((rat simp) 1 2) expr expr) nil))
706 (t nil))))
708 ;; Define the antiderivatives of some elementary special functions.
709 ;; This may not be the best place for this definition, but it is close
710 ;; to the original code.
711 ;; Antiderivatives that depend on the logabs flag are defined further below.
712 (defprop %log ((x) ((mplus) ((mtimes) x ((%log) x)) ((mtimes) -1 x))) integral)
713 (defprop %sin ((x) ((mtimes) -1 ((%cos) x))) integral)
714 (defprop %cos ((x) ((%sin) x)) integral)
715 (defprop %sinh ((x) ((%cosh) x)) integral)
716 (defprop %cosh ((x) ((%sinh) x)) integral)
717 ;; No need to take logabs into account for tanh(x), because cosh(x) is positive.
718 (defprop %tanh ((x) ((%log) ((%cosh) x))) integral)
719 (defprop %sech ((x) ((%atan) ((%sinh) x))) integral)
720 (defprop %asin ((x) ((mplus) ((mexpt) ((mplus) 1 ((mtimes) -1 ((mexpt) x 2))) ((rat) 1 2)) ((mtimes) x ((%asin) x)))) integral)
721 (defprop %acos ((x) ((mplus) ((mtimes) -1 ((mexpt) ((mplus) 1 ((mtimes) -1 ((mexpt) x 2))) ((rat) 1 2))) ((mtimes) x ((%acos) x)))) integral)
722 (defprop %atan ((x) ((mplus) ((mtimes) x ((%atan) x)) ((mtimes) ((rat) -1 2) ((%log) ((mplus) 1 ((mexpt) x 2)))))) integral)
723 (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)
724 (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)
725 (defprop %acot ((x) ((mplus) ((mtimes) x ((%acot) x)) ((mtimes) ((rat) 1 2) ((%log) ((mplus) 1 ((mexpt) x 2)))))) integral)
726 (defprop %asinh ((x) ((mplus) ((mtimes) -1 ((mexpt) ((mplus) 1 ((mexpt) x 2)) ((rat) 1 2))) ((mtimes) x ((%asinh) x)))) integral)
727 (defprop %acosh ((x) ((mplus) ((mtimes) -1 ((mexpt) ((mplus) -1 ((mexpt) x 2)) ((rat) 1 2))) ((mtimes) x ((%acosh) x)))) integral)
728 (defprop %atanh ((x) ((mplus) ((mtimes) x ((%atanh) x)) ((mtimes) ((rat) 1 2) ((%log) ((mplus) 1 ((mtimes) -1 ((mexpt) x 2))))))) integral)
729 (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)
730 (defprop %asech ((x) ((mplus) ((mtimes) -1 ((%atan) ((mexpt) ((mplus) -1 ((mexpt) x -2)) ((rat) 1 2)))) ((mtimes) x ((%asech) x)))) integral)
731 (defprop %acoth ((x) ((mplus) ((mtimes) x ((%acoth) x)) ((mtimes) ((rat) 1 2) ((%log) ((mplus) 1 ((mtimes) -1 ((mexpt) x 2))))))) integral)
733 ;; Define a little helper function to be used in antiderivatives.
734 ;; Depending on the logabs flag, it either returns log(x) or log(abs(x)).
735 (defun log-or-logabs (x)
736 (take '(%log) (if $logabs (take '(mabs) x) x)))
738 ;; Define the antiderivative of tan(x), taking logabs into account.
739 (defun integrate-tan (x)
740 (log-or-logabs (take '(%sec) x)))
741 (putprop '%tan `((x) ,'integrate-tan) 'integral)
743 ;; ... the same for csc(x) ...
744 (defun integrate-csc (x)
745 (mul -1 (log-or-logabs (add (take '(%csc) x) (take '(%cot) x)))))
746 (putprop '%csc `((x) ,'integrate-csc) 'integral)
748 ;; ... the same for sec(x) ...
749 (defun integrate-sec (x)
750 (log-or-logabs (add (take '(%sec) x) (take '(%tan) x))))
751 (putprop '%sec `((x) ,'integrate-sec) 'integral)
753 ;; ... the same for cot(x) ...
754 (defun integrate-cot (x)
755 (log-or-logabs (take '(%sin) x)))
756 (putprop '%cot `((x) ,'integrate-cot) 'integral)
758 ;; ... the same for coth(x) ...
759 (defun integrate-coth (x)
760 (log-or-logabs (take '(%sinh) x)))
761 (putprop '%coth `((x) ,'integrate-coth) 'integral)
763 ;; ... the same for csch(x) ...
764 (defun integrate-csch (x)
765 (log-or-logabs (take '(%tanh) (mul '((rat simp) 1 2) x))))
766 (putprop '%csch `((x) ,'integrate-csch) 'integral)
768 ;; integrate(x^n,x) = if n # -1 then x^(n+1)/(n+1) else log-or-logabs(x).
769 (defun integrate-mexpt-1 (x n)
770 (let ((n-is-minus-one ($askequal n -1)))
771 (cond ((eq '$yes n-is-minus-one)
772 (log-or-logabs x))
774 (setq n (add n 1))
775 (div (take '(mexpt) x n) n)))))
777 ;; integrate(a^x,x) = a^x/log(a).
778 (defun integrate-mexpt-2 (a x)
779 (div (take '(mexpt) a x) (take '(%log) a)))
781 (putprop 'mexpt `((x n) ,'integrate-mexpt-1 ,'integrate-mexpt-2) 'integral)
783 (defun integrate5 (ex var2)
784 (if (rat8 ex var2)
785 (ratint ex var2)
786 (integrator ex var2)))
788 (defun denomfind (x)
789 (cond ((ratnump x) (caddr x))
790 ((not (numberp x)) nil)
791 ((not (floatp x)) 1)
792 (t (cdr (maxima-rationalize x)))))
794 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
796 ;;; Stage II
797 ;;; Implementation of Method 1: Elementary function of exponentials
799 ;;; The following examples are integrated with this method:
801 ;;; integrate(exp(x)/(2+3*exp(2*x)),x)
802 ;;; integrate(exp(x+1)/(1+exp(x)),x)
803 ;;; integrate(10^x*exp(x),x)
805 (let ((base nil) ; The common base.
806 (pow nil) ; The common power of the form b*x+a. The values are
807 ; stored in a list which is returned from m2.
808 (exptflag nil)) ; When T, the substitution is not possible.
810 (defun superexpt (expr var2 bas1 pow1)
811 (prog (y ($logabs nil) (new-var (gensym "NEW-VAR-")))
812 (putprop new-var t 'internal)
813 (setq base bas1
814 pow pow1
815 exptflag nil)
816 ;; Transform the integrand. At this point resimplify, because it is not
817 ;; guaranteed, that a correct simplified expression is returned.
818 ;; Use a new variable to prevent facts on the old variable to be wrongly used.
819 (setq y (resimplify (maxima-substitute new-var var2 (elemxpt expr var2))))
820 (when exptflag (return nil))
821 ;; Integrate the transformed integrand and substitute back.
822 (return
823 ($multthru
824 (substint (list '(mexpt) base
825 (list '(mplus) (cdras 'a pow)
826 (list '(mtimes) (cdras 'b pow) var2)))
827 new-var
828 (integrator (div y
829 (mul new-var
830 (cdras 'b pow)
831 (take '(%log) base)))
832 new-var)
833 var2
834 expr)))))
836 ;; Transform expressions like g^(b*x+a) to the common base base and
837 ;; do the substitution y = base^(b*x+a) in the expr.
838 (defun elemxpt (expr var2 &aux w)
839 (cond ((freevar2 expr var2) expr)
840 ;; var2 is the base of a subexpression. The transformation fails.
841 ((atom expr) (setq exptflag t))
842 ((not (eq (caar expr) 'mexpt))
843 (cons (car expr)
844 (mapcar #'(lambda (c)
845 (elemxpt c var2))
846 (cdr expr))))
847 ((not (freevar2 (cadr expr) var2))
848 (list '(mexpt)
849 (elemxpt (cadr expr) var2)
850 (elemxpt (caddr expr) var2)))
851 ;; Transform the expression to the common base.
852 ((not (eq (cadr expr) base))
853 (elemxpt (list '(mexpt)
854 base
855 (mul (power (take '(%log) base) -1)
856 (take '(%log) (cadr expr))
857 (caddr expr)))
858 var2))
859 ;; The exponent must be linear in the variable of integration.
860 ((not (setq w (m2-b*x+a (caddr expr) var2)))
861 (list (car expr) base (elemxpt (caddr expr) var2)))
862 ;; Do the substitution y = g^(b*x+a).
864 (setq w (cons (cons 'bb (cdras 'b pow)) w))
865 (setq w (cons (cons 'aa (cdras 'a pow)) w))
866 (setq w (cons (cons 'base base) w))
867 (subliss w '((mtimes)
868 ((mexpt) base a)
869 ((mexpt)
870 base
871 ((mquotient)
872 ((mtimes) -1 aa b) bb))
873 ((mexpt)
875 ((mquotient) b bb)))))))
876 ) ; End of let
878 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
880 ;;; Stage II
881 ;;; Implementation of Method 3:
882 ;;; Substitution for a rational root of a linear fraction of x
884 ;;; This method is applicable when the integrand is of the form:
886 ;;; /
887 ;;; [ a x + b n1/m1 a x + b n1/m2
888 ;;; I R(x, (-------) , (-------) , ...) dx
889 ;;; ] c x + d c x + d
890 ;;; /
892 ;;; Substitute
894 ;;; (1) t = ((a*x+b)/(c*x+d))^(1/k), or
896 ;;; (2) x = (b-d*t^k)/(c*t^k-a)
898 ;;; where k is the least common multiplier of m1, m2, ... and
900 ;;; (3) dx = k*(a*d-b*c)*t^(k-1)/(a-c*t^k)^2 * dt
902 ;;; First, the algorithm calls the routine RAT3 to collect the roots of the
903 ;;; form ((a*x+b)/(c*x+d))^(n/m) in the list ROOTLIST.
904 ;;; search for the least common multiplier of m1, m2, ... then the
905 ;;; substitutions (2) and (3) are done and the new problem is integrated.
906 ;;; As always, W is an alist which associates to the coefficients
907 ;;; a, b... (and to VAR) their values.
909 ;; ratroot2 is an expression of the form (a*x+b)/(c*x+d)
910 (defun ratroot (expr var2 ratroot2 w)
911 (prog (rootlist k y w1)
912 ;; List of powers of the expression ratroot2.
914 ;; Check if the integrand has a chebyform, if so return the result.
915 (when (setq y (chebyf expr var2)) (return y))
916 ;; Check if the integrand has a suitably form and collect the roots
917 ;; in the global special variable *ROOTLIST*.
918 (labels
919 ((rat3 (ex ind var2 ratroot2)
920 (cond ((freevar2 ex var2) t)
921 ((atom ex) ind)
922 ((member (caar ex) '(mtimes mplus) :test #'eq)
923 (do ((u (cdr ex) (cdr u)))
924 ((null u) t)
925 (if (not (rat3 (car u) ind var2 ratroot2))
926 (return nil))))
927 ((not (eq (caar ex) 'mexpt))
928 (rat3 (car (margs ex)) t var2 ratroot2))
929 ((freevar2 (cadr ex) var2)
930 (rat3 (caddr ex) t var2 ratroot2))
931 ((integerp (caddr ex))
932 (rat3 (cadr ex) ind var2 ratroot2))
933 ((and (m2 (cadr ex) ratroot2)
934 (denomfind (caddr ex)))
935 (setq rootlist (cons (denomfind (caddr ex)) rootlist)))
936 (t (rat3 (cadr ex) nil var2 ratroot2)))))
937 (unless (rat3 expr t var2 ratroot2) (return nil)))
938 ;; Get the least common multiplier of m1, m2, ...
939 (setq k (apply #'lcm rootlist))
940 (setq w1 (cons (cons 'k k) w))
941 ;; Substitute for the roots.
942 (setq y
943 (subst41 expr
944 (subliss w1
945 `((mquotient)
946 ((mplus) ((mtimes) b e)
947 ((mtimes) -1 d ((mexpt) ,var2 k)))
948 ((mplus) ((mtimes) c ((mexpt) ,var2 k))
949 ((mtimes) -1 e a))))
950 var2
952 ratroot2))
953 ;; Integrate the new problem.
954 (setq y
955 (integrator
956 (mul y
957 (subliss w1
958 `((mquotient)
959 ((mtimes) e
960 ((mplus)
961 ((mtimes) a d k
962 ((mexpt) ,var2 ((mplus) -1 k)))
963 ((mtimes) -1
964 ((mtimes) b c k
965 ((mexpt) ,var2 ((mplus) -1 k))))))
966 ((mexpt) ((mplus)
967 ((mtimes) c ((mexpt) ,var2 k))
968 ((mtimes) -1 a e))
969 2))))
970 var2))
971 ;; Substitute back and return the result.
972 (return (substint (power ratroot2 (power k -1)) var2 y var2 expr))))
974 (let ((rootform nil) ; Expression of the form x = (b*e-d*t^k)/(c*t^k-e*a).
975 (rootvar nil)) ; The variable we substitute for the root.
977 (defun subst4 (ex k ratroot2)
978 (cond ((freevar2 ex rootvar)
979 ;; SUBST4 is called from SUBST41 with ROOTVAR equal to VAR
980 ;; (from RATROOT). Hence we can use FREEVAR2 to see if EX
981 ;; is free of ROOTVAR instead of using FREEVAR.
983 ((atom ex) rootform)
984 ((not (eq (caar ex) 'mexpt))
985 (mapcar #'(lambda (u) (subst4 u k ratroot2)) ex))
986 ((m2 (cadr ex) ratroot2)
987 (list (car ex) rootvar (integerp2 (timesk k (caddr ex)))))
988 (t (list (car ex) (subst4 (cadr ex) k ratroot2) (subst4 (caddr ex) k ratroot2)))))
990 (defun subst41 (expr a b k ratroot2)
991 ;; Note: SUBST41 is only called from RATROOT, and the arg B is VAR.
992 (setq rootform a
993 rootvar b)
994 ;; At this point resimplify, because it is not guaranteed, that a correct
995 ;; simplified expression is returned.
996 (resimplify (subst4 expr k ratroot2)))
997 ) ; End of let
999 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1001 ;;; Stage II
1002 ;;; Implementation of Method 4: Binomial Chebyschev
1004 ;; exp = a*t^r1*(c1+c2*t^q)^r2, where var2 = t.
1006 ;; G&S 2.202 has says this integral can be expressed by elementary
1007 ;; functions ii:
1009 ;; 1. q is an integer
1010 ;; 2. (r1+1)/q is an integer
1011 ;; 3. (r1+1)/q+r2 is an integer.
1013 ;; I (rtoy) think that for this code to work, r1, r2, and q must be numbers.
1014 (defun chebyf (expr var2)
1015 (prog (r1 r2 d1 d2 n1 n2 w q)
1016 ;; Return NIL if the expression doesn't match.
1017 (when (not (setq w (m2-chebyform expr var2)))
1018 (return nil))
1019 #+nil
1020 (format t "w = ~A~%" w)
1021 (when (zerop1 (cdr (assoc 'c1 w :test #'eq)))
1022 ;; rtoy: Is it really possible to be in this routine with c1 =
1023 ;; 0?
1024 (return
1025 (mul*
1026 ;; This factor is locally constant as long as t and
1027 ;; c2*t^q avoid log's branch cut.
1028 (subliss w `((mtimes) a ((mexpt) ,var2 ((mtimes) -1 q r2))
1029 ((mexpt) ((mtimes) c2 ((mexpt) ,var2 q)) r2)))
1030 (integrator
1031 (subliss w `((mexpt) ,var2 ((mplus) r1 ((mtimes) q r2))))
1032 var2))))
1033 (setq q (cdr (assoc 'q w :test #'eq)))
1034 ;; Reset parameters. a = a/q, r1 = (1 - q + r1)/q
1035 (setq w
1036 (list* (cons 'a (div* (cdr (assoc 'a w :test #'eq)) q))
1037 (cons
1039 (div* (addn (list 1 (neg (simplify q)) (cdr (assoc 'r1 w :test #'eq))) nil) q))
1041 #+nil
1042 (format t "new w = ~A~%" w)
1043 (setq r1 (cdr (assoc 'r1 w :test #'eq))
1044 r2 (cdr (assoc 'r2 w :test #'eq)))
1045 #+nil
1046 (progn
1047 (format t "new r1 = ~A~%" r1)
1048 (format t "r2 = ~A~%" r2))
1049 ;; Write r1 = d1/n1, r2 = d2/n2, if possible. Update w with
1050 ;; these values, if so. If we can't, give up. I (rtoy) think
1051 ;; this only happens if r1 or r2 can't be expressed as rational
1052 ;; numbers. Hence, r1 and r2 have to be numbers, not variables.
1053 (cond
1054 ((not (and (setq d1 (denomfind r1))
1055 (setq d2 (denomfind r2))
1056 (setq n1 (integerp2 (timesk r1 d1)))
1057 (setq n2 (integerp2 (timesk r2 d2)))
1058 (setq w (list* (cons 'd1 d1) (cons 'd2 d2)
1059 (cons 'n1 n1) (cons 'n2 n2)
1060 w))))
1061 #+nil
1062 (progn
1063 (format t "cheby can't find one of d1,d2,n1,n2:~%")
1064 (format t " d1 = ~A~%" d1)
1065 (format t " d2 = ~A~%" d2)
1066 (format t " n1 = ~A~%" n1)
1067 (format t " n2 = ~A~%" n2))
1068 (return nil))
1069 ((and (integerp2 r1) (> r1 0))
1070 #+nil (format t "integer r1 > 0~%")
1071 ;; (r1+q-1)/q is positive integer.
1073 ;; I (rtoy) think we are using the substitution z=(c1+c2*t^q).
1074 ;; Maxima thinks the resulting integral should then be
1076 ;; a/q*c2^(-r1/q-1/q)*integrate(z^r2*(z-c1)^(r1/q+1/q-1),z)
1078 (return
1079 (substint
1080 (subliss w `((mplus) c1 ((mtimes) c2 ((mexpt) ,var2 q))))
1081 var2
1082 (integrator
1083 (expands (list (subliss w
1084 ;; a*t^r2*c2^(-r1-1)
1085 `((mtimes)
1087 ((mexpt) ,var2 r2)
1088 ((mexpt)
1090 ((mtimes)
1092 ((mplus) r1 1))))))
1093 (cdr
1094 ;; (t-c1)^r1
1095 (expandexpt (subliss w
1096 `((mplus)
1097 ,var2
1098 ((mtimes) -1 c1)))
1099 r1)))
1100 var2)
1101 var2
1102 expr)))
1103 ((integerp2 r2)
1104 #+nil (format t "integer r2~%")
1105 ;; I (rtoy) think this is using the substitution z = t^(q/d1).
1107 ;; The integral (as maxima will tell us) becomes
1109 ;; a*d1/q*integrate(z^(n1/q+d1/q-1)*(c1+c2*z^d1)^r2,z)
1111 ;; But be careful because the variable A in the code is
1112 ;; actually a/q.
1113 (return
1114 (substint (subliss w `((mexpt) ,var2 ((mquotient) q d1)))
1115 var2
1116 (ratint (simplify (subliss w
1117 `((mtimes)
1118 d1 a
1119 ((mexpt)
1120 ,var2
1121 ((mplus)
1122 n1 d1 -1))
1123 ((mexpt)
1124 ((mplus)
1125 ((mtimes)
1127 ((mexpt)
1128 ,var2 d1))
1130 r2))))
1131 var2)
1132 var2
1133 expr)))
1134 ((and (integerp2 r1) (< r1 0))
1135 #+nil (format t "integer r1 < 0~%")
1136 ;; I (rtoy) think this is using the substitution
1138 ;; z = (c1+c2*t^q)^(1/d2)
1140 ;; With this substitution, maxima says the resulting integral
1141 ;; is
1143 ;; a/q*c2^(-r1/q-1/q)*d2*
1144 ;; integrate(z^(n2+d2-1)*(z^d2-c1)^(r1/q+1/q-1),z)
1145 (return
1146 (substint (subliss w
1147 ;; (c1+c2*t^q)^(1/d2)
1148 `((mexpt)
1149 ((mplus)
1151 ((mtimes) c2 ((mexpt) ,var2 q)))
1152 ((mquotient) 1 d2)))
1153 var2
1154 (ratint (simplify (subliss w
1155 ;; This is essentially
1156 ;; the integrand above,
1157 ;; except A and R1 here
1158 ;; are not the same as
1159 ;; derived above.
1160 `((mtimes)
1161 a d2
1162 ((mexpt)
1164 ((mtimes)
1166 ((mplus)
1167 r1 1)))
1168 ((mexpt)
1169 ,var2
1170 ((mplus)
1171 n2 d2 -1))
1172 ((mexpt)
1173 ((mplus)
1174 ((mexpt)
1175 ,var2 d2)
1176 ((mtimes) -1 c1))
1177 r1))))
1178 var2)
1179 var2
1180 expr)))
1181 ((integerp2 (add* r1 r2))
1182 #+nil (format t "integer r1+r2~%")
1183 ;; If we're here, (r1-q+1)/q+r2 is an integer.
1185 ;; I (rtoy) think this is using the substitution
1187 ;; z = ((c1+c2*t^q)/t^q)^(1/d1)
1189 ;; With this substitution, maxima says the resulting integral
1190 ;; is
1192 ;; a*d2/q*c1^(r2+r1/q+1/q)*
1193 ;; integrate(z^(d2*r2+d2-1)*(z^d2-c2)^(-r2-r1/q-1/q-1),z)
1194 (return
1195 (substint (let (($radexpand '$all))
1196 ;; Setting $radexpand to $all here gets rid of
1197 ;; ABS in the substitution. I think that's ok in
1198 ;; this case. See Bug 1654183.
1199 (subliss w
1200 `((mexpt)
1201 ((mquotient)
1202 ((mplus)
1204 ((mtimes) c2 ((mexpt) ,var2 q)))
1205 ((mexpt) ,var2 q))
1206 ((mquotient) 1 d1))))
1207 var2
1208 (ratint (simplify (subliss w
1209 `((mtimes)
1210 -1 a d1
1211 ((mexpt)
1213 ((mplus)
1214 r1 r2 1))
1215 ((mexpt)
1216 ,var2
1217 ((mplus)
1218 n2 d1 -1))
1219 ((mexpt)
1220 ((mplus)
1221 ((mexpt)
1222 ,var2 d1)
1223 ((mtimes)
1224 -1 c2))
1225 ((mtimes)
1227 ((mplus)
1228 r1 r2
1229 2))))))
1230 var2)
1231 var2
1232 expr)))
1233 (t (return (list '(%integrate) expr var2))))))
1235 (defun greaterratp (x1 x2)
1236 (cond ((and (numberp x1) (numberp x2))
1237 (> x1 x2))
1238 ((ratnump x1)
1239 (greaterratp (quotient (float (cadr x1))
1240 (caddr x1))
1241 x2))
1242 ((ratnump x2)
1243 (greaterratp x1
1244 (quotient (float (cadr x2))
1245 (caddr x2))))))
1247 (defun trig1 (x)
1248 (member (car x) '(%sin %cos) :test #'eq))
1250 (defun supertrig (expr var2 trigarg)
1251 (declare (special *notsame*))
1252 (cond ((freevar2 expr var2) t)
1253 ((atom expr) nil)
1254 ((member (caar expr) '(mplus mtimes) :test #'eq)
1255 (and (supertrig (cadr expr) var2 trigarg)
1256 (or (null (cddr expr))
1257 (supertrig (cons (car expr)
1258 (cddr expr))
1259 var2 trigarg))))
1260 ((eq (caar expr) 'mexpt)
1261 (and (supertrig (cadr expr) var2 trigarg)
1262 (supertrig (caddr expr) var2 trigarg)))
1263 ((eq (caar expr) '%log)
1264 (supertrig (cadr expr) var2 trigarg))
1265 ((member (caar expr)
1266 '(%sin %cos %tan %sec %cot %csc) :test #'eq)
1267 (cond ((m2 (cadr expr) trigarg) t)
1268 ((m2-b*x+a (cadr expr) var2)
1269 (and (setq *notsame* t) nil))
1270 (t (supertrig (cadr expr) var2 trigarg))))
1271 (t (supertrig (cadr expr) var2 trigarg))))
1273 (defun subst2s (ex pat var2)
1274 (cond ((null ex) nil)
1275 ((m2 ex pat) var2)
1276 ((atom ex) ex)
1277 (t (cons (subst2s (car ex) pat var2)
1278 (subst2s (cdr ex) pat var2)))))
1280 ;; Match (c*x+b), where c and b are free of x
1281 (defun simple-trig-arg (expr var2)
1282 (m2 expr `((mplus) ((mtimes)
1283 ((coefftt) (c freevar2 ,var2))
1284 ((coefftt) (v varp2 ,var2)))
1285 ((coeffpp) (b freevar2 ,var2)))))
1287 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1289 ;;; Stage II
1290 ;;; Implementation of Method 6: Elementary function of trigonometric functions
1292 (defun monstertrig (expr var2 trigarg)
1293 (prog (*notsame* w a b y d)
1294 (declare (special *notsame*))
1295 (cond
1296 ((supertrig expr var2 trigarg)
1297 (go a))
1298 ((null *notsame*) (return nil))
1299 ;; Check for an expression like a*trig1(m*x)*trig2(n*x),
1300 ;; where trig1 and trig2 are sin or cos.
1301 ((not (setq y (m2 expr
1302 `((mtimes)
1303 ((coefftt) (a freevar2 ,var2))
1304 (((b trig1))
1305 ((mtimes)
1306 (x varp2 ,var2)
1307 ((coefftt) (m freevar2 ,var2))))
1308 (((d trig1))
1309 ((mtimes)
1310 (x varp2 ,var2)
1311 ((coefftt) (n freevar2 ,var2))))))))
1312 (go b))
1313 ; This check has been done with the pattern match.
1314 ; ((not (and (member (car (setq b (cdr (assoc 'b y :test #'eq)))) '(%sin %cos) :test #'eq)
1315 ; (member (car (setq d (cdr (assoc 'd y :test #'eq)))) '(%sin %cos) :test #'eq)))
1316 ; (return nil))
1317 ((progn
1318 ;; The tests after this depend on values of b and d being
1319 ;; set. Set them here unconditionally, before doing the
1320 ;; tests.
1321 (setq b (cdras 'b y))
1322 (setq d (cdras 'd y))
1323 (and (eq (car b) '%sin)
1324 (eq (car d) '%sin)))
1325 ;; We have a*sin(m*x)*sin(n*x).
1327 ;; The integral is:
1328 ;; a*(sin((m-n)*x)/(2*(m-n))-sin((m+n)*x)/(2*(m+n)). But if n
1329 ;; = m, the integral is x/2-sin(2*n*x)/(4*n).
1330 (let ((n (cdras 'n y))
1331 (m (cdras 'm y)))
1332 (cond
1333 ((eq ($askequal n m) '$yes)
1334 ;; n=m, so we have the integral of a*sin(n*x)^2 which is
1335 (return (subliss y
1336 `((mtimes) a
1337 ((mplus)
1338 ((mquotient) x 2)
1339 ((mtimes) -1
1340 ((mquotient)
1341 ((%sin) ((mtimes) 2 n x))
1342 ((mtimes) 4 n))))))))
1344 (return (subliss y
1345 '((mtimes) a
1346 ((mplus)
1347 ((mquotient)
1348 ((%sin) ((mtimes) ((mplus) m ((mtimes) -1 n)) x))
1349 ((mtimes) 2 ((mplus) m ((mtimes) -1 n))))
1350 ((mtimes) -1
1351 ((mquotient)
1352 ((%sin) ((mtimes) ((mplus) m n) x))
1353 ((mtimes) 2 ((mplus) m n))))))))))))
1354 ((and (eq (car b) '%cos) (eq (car d) '%cos))
1355 ;; We have a*cos(m*x)*cos(n*x).
1357 ;; The integral is:
1358 ;; a*(sin((m-n)*x)/(2*(m-n))+sin((m+n)*x)/(2*(m+n)). But when
1359 ;; n = m, the integral is sin(2*m*x)/(4*m)+x/2.
1360 (let ((n (cdras 'n y))
1361 (m (cdras 'm y)))
1362 (cond
1363 ((eq ($askequal n m) '$yes)
1364 (return (subliss y
1365 '((mtimes) a
1366 ((mplus)
1367 ((mquotient)
1368 ((%sin) ((mtimes) 2 n x))
1369 ((mtimes) 4 n))
1370 ((mquotient)
1371 x 2))))))
1373 (return (subliss y
1374 '((mtimes) a
1375 ((mplus)
1376 ((mquotient)
1377 ((%sin) ((mtimes) ((mplus) m ((mtimes) -1 n)) x))
1378 ((mtimes) 2
1379 ((mplus) m ((mtimes) -1 n))))
1380 ((mquotient)
1381 ((%sin) ((mtimes) ((mplus) m n) x))
1382 ((mtimes) 2 ((mplus) m n)))))))))))
1383 ((or (and (eq (car b) '%cos)
1384 ;; The following (destructively!) swaps the values of
1385 ;; m and n if first trig term is sin. I (rtoy) don't
1386 ;; understand why this is needed. The formula
1387 ;; doesn't depend on that.
1388 (setq w (cdras 'm y ))
1389 (rplacd (assoc 'm y) (cdras 'n y))
1390 (rplacd (assoc 'n y) w))
1392 ;; We have a*cos(n*x)*sin(m*x).
1394 ;; The integral is:
1395 ;; -a*(cos((m-n)*x)/(2*(m-n))+cos((m+n)*x)/(2*(m+n)). But
1396 ;; if n = m, the integral is -cos(n*x)^2/(2*n).
1397 (let ((n (cdras 'n y))
1398 (m (cdras 'm y)))
1399 (cond
1400 ((eq ($askequal n m) '$yes)
1401 ;; This needs work. For example
1402 ;; integrate(cos(m*x)*sin(2*m*x),x). We ask if 2*m = m.
1403 ;; If the answer is yes, we return -cos(m*x)^2/(2*m).
1404 ;; But if 2*m=m, then m=0 and the integral must be 0.
1405 (return (subliss y
1406 '((mquotient)
1407 ((mtimes) -1 a
1408 ((mexpt)
1409 ((%cos) ((mtimes) n x))
1411 ((mtimes) 2 n)))))
1413 (return (subliss y
1414 '((mtimes) -1 a
1415 ((mplus)
1416 ((mquotient)
1417 ((%cos) ((mtimes) ((mplus) m ((mtimes) -1 n)) x))
1418 ((mtimes) 2 ((mplus) m ((mtimes) -1 n))))
1419 ((mquotient)
1420 ((%cos) ((mtimes) ((mplus) m n) x))
1421 ((mtimes) 2 ((mplus) m n))))))))))))
1422 b ;; At this point we have trig functions with different arguments,
1423 ;; but not a product of sin and cos.
1424 (cond ((not (setq y (prog2
1425 (setq trigarg var2)
1426 (m2 expr
1427 `((mtimes)
1428 ((coefftt) (a freevar2 ,var2))
1429 (((b trig1))
1430 ((mtimes)
1431 (x varp2 ,var2)
1432 ((coefftt) (n integerp2))))
1433 ((coefftt) (c supertrig ,var2 ,trigarg)))))))
1434 (return nil)))
1435 ;; We have a product of trig functions: trig1(n*x)*trig2(y).
1436 ;; trig1 is sin or cos, where n is a numerical integer. trig2 is not a sin
1437 ;; or cos. The cos or sin function is expanded.
1438 (return
1439 (integrator
1440 ($expand
1441 (list '(mtimes)
1442 (cdras 'a y) ; constant factor
1443 (cdras 'c y) ; trig functions
1444 (cond ((eq (car (cdras 'b y)) '%cos) ; expand cos(n*x)
1445 (maxima-substitute var2
1447 (supercosnx (cdras 'n y))))
1448 (t ; expand sin(x*x)
1449 (maxima-substitute var2
1451 (supersinx (cdras 'n y)))))))
1452 var2))
1453 a ;; A product of trig functions and all trig functions have the same
1454 ;; argument trigarg. Maxima substitutes trigarg with the variable var2
1455 ;; of integration and calls trigint to integrate the new problem.
1456 (setq w (subst2s expr trigarg var2))
1457 (setq b (cdras 'b (m2-b*x+a trigarg var2)))
1458 (setq a (substint trigarg var2 (trigint (div* w b) var2) var2 expr))
1459 (return (if (isinop a '%integrate)
1460 (list '(%integrate) expr var2)
1461 a))))
1463 (defun trig2 (x)
1464 (member (car x) '(%sin %cos %tan %cot %sec %csc) :test #'eq))
1466 ;; sin(n*x) for integer n /= 0. Result not simplified.
1467 (defun supersinx (n)
1468 (let ((i (if (< n 0) -1 1)))
1469 ($expand (list '(mtimes) i (sinnx (timesk i n))))))
1471 ;; cos(n*x) for integer n /= 0. Result not simplified.
1472 (defun supercosnx (n)
1473 ($expand (cosnx (timesk (if (< n 0) -1 1) n))))
1475 ;; sin(n*x) for integer n >= 1. Result is not simplified.
1476 (defun sinnx (n)
1477 (if (equal n 1)
1478 '((%sin) x)
1479 (list '(mplus)
1480 (list '(mtimes) '((%sin) x) (cosnx (1- n)))
1481 (list '(mtimes) '((%cos) x) (sinnx (1- n))))))
1483 ;; cos(n*x) for integer n >= 1. Result is not simplified.
1484 (defun cosnx (n)
1485 (if (equal n 1)
1486 '((%cos) x)
1487 (list '(mplus)
1488 (list '(mtimes) '((%cos) x) (cosnx (1- n)))
1489 (list '(mtimes) -1 '((%sin) x) (sinnx (1- n))))))
1491 (defun poseven (x)
1492 (and (even x) (> x -1)))
1494 (defun trigfree (x)
1495 (if (atom x)
1496 (not (member x '(sin* cos* sec* tan*) :test #'eq))
1497 (and (trigfree (car x)) (trigfree (cdr x)))))
1499 (defun rat1 (expr aa bb cc)
1500 (prog (b1 *notsame*)
1501 (declare (special *yy* *notsame*))
1502 (when (and (numberp expr) (zerop expr))
1503 (return nil))
1504 (setq b1 (subst bb 'b '((mexpt) b (n even))))
1505 (return (prog2
1506 (setq *yy* (rats expr aa b1 cc))
1507 (cond ((not *notsame*) *yy*))))))
1509 (defun rats (expr aa b1 cc)
1510 (prog (y)
1511 (declare (special *notsame*))
1512 (return
1513 (cond ((eq expr aa) 'x)
1514 ((atom expr)
1515 (cond ((member expr '(sin* cos* sec* tan*) :test #'eq)
1516 (setq *notsame* t))
1517 (t expr)))
1518 ((setq y (m2 expr b1))
1519 (f3 y cc))
1520 (t (cons (car expr) (mapcar #'(lambda (g) (rats g aa b1 cc))
1521 (cdr expr))))))))
1523 (defun f3 (y cc)
1524 (maxima-substitute cc
1526 (maxima-substitute (quotient (cdr (assoc 'n y :test #'eq)) 2)
1528 '((mexpt)
1529 ((mplus)
1531 ((mtimes)
1533 ((mexpt) x 2)))
1534 n))))
1536 (defun odd1 (n cc)
1537 (declare (special *yz*))
1538 (cond ((not (numberp n)) nil)
1539 ((not (equal (rem n 2) 0))
1540 (setq *yz*
1541 (maxima-substitute cc
1543 (list '(mexpt)
1544 '((mplus) 1 ((mtimes) c ((mexpt) x 2)))
1545 (quotient (1- n) 2)))))
1546 (t nil)))
1548 (defun subvar (x var2)
1549 (maxima-substitute var2 'x x))
1551 (defun subvardlg (x var2)
1552 (mapcar #'(lambda (m)
1553 (cons (maxima-substitute var2 'x (car m)) (cdr m)))
1556 ;; This appears to be the implementation of Method 6, pp.82 in Moses' thesis.
1558 (defun trigint (expr var2)
1559 (prog (y repl y1 y2 *yy* z m n *yz*)
1560 (declare (special *yy* *yz*))
1561 ;; Transform trig(x) into trig* (for simplicity?) Convert cot to
1562 ;; tan and csc to sin.
1563 (setq y2
1564 (subliss (subvardlg '((((%sin) x) . sin*)
1565 (((%cos) x) . cos*)
1566 (((%tan) x) . tan*)
1567 (((%cot) x) . ((mexpt) tan* -1))
1568 (((%sec) x) . sec*)
1569 (((%csc) x) . ((mexpt) sin* -1)))
1570 var2)
1571 expr))
1573 (when *debug-integrate*
1574 (format t "~& in TRIGINT:~%")
1575 (format t "~& : y2 = ~A~%" y2))
1577 ;; Now transform tan to sin/cos and sec to 1/cos.
1578 (setq y1 (setq y (subliss '((tan* . ((mtimes) sin*
1579 ((mexpt) cos* -1)))
1580 (sec* . ((mexpt) cos* -1)))
1581 y2)))
1583 (when *debug-integrate* (format t "~& : y = ~A~%" y))
1585 (when (null (setq z
1586 (m2 y
1587 '((mtimes)
1588 ((coefftt) (b trigfree))
1589 ((mexpt) sin* (m poseven))
1590 ((mexpt) cos* (n poseven))))))
1591 ;; Go if y is not of the form sin^m*cos^n for positive even m and n.
1592 (go l1))
1594 ;; Case III:
1595 ;; Handle the case of sin^m*cos^n, m, n both non-negative and even.
1597 (setq m (cdras 'm z))
1598 (setq n (cdras 'n z))
1599 (let ((aa (integerp2 (* 0.5 (if (< m n) 1 -1) (+ n (* -1 m))))))
1600 (setq z (cons (cons 'a aa) z))
1601 (setq z (cons (cons 'x var2) z))
1603 (when *debug-integrate*
1604 (format t "~& CASE III:~%")
1605 (format t "~& : m, n = ~A ~A~%" m n)
1606 (format t "~& : a = ~A~%" aa)
1607 (format t "~& : z = ~A~%" z)))
1609 ;; integrate(sin(y)^m*cos(y)^n,y) is transformed to the following form:
1611 ;; m < n: integrate((sin(2*y)/2)^n*(1/2+1/2*cos(2*y)^((n-m)/2),y)
1612 ;; m >= n: integrate((sin(2*y)/2)^n*(1/2-1/2*cos(2*y)^((m-n)/2),y)
1613 (return
1614 (mul (cdras 'b z)
1615 (div 1 2)
1616 (substint
1617 (mul 2 var2)
1618 var2
1619 (integrator
1620 (cond ((< m n)
1621 (subliss z
1622 '((mtimes)
1623 ((mexpt)
1624 ((mtimes) ((rat simp) 1 2) ((%sin) x))
1626 ((mexpt)
1627 ((mplus)
1628 ((rat simp) 1 2)
1629 ((mtimes)
1630 ((rat simp) 1 2) ((%cos) x))) a))))
1632 (subliss z
1633 '((mtimes)
1634 ((mexpt)
1635 ((mtimes) ((rat simp) 1 2) ((%sin) x))
1637 ((mexpt)
1638 ((mplus)
1639 ((rat simp) 1 2)
1640 ((mtimes)
1641 ((rat simp) -1 2)
1642 ((%cos) x))) a)))))
1643 var2)
1644 var2
1645 expr)))
1647 ;; Case IV:
1648 ;; I think this is case IV, working on the expression in terms of
1649 ;; sin and cos.
1651 ;; Elem(x) means constants, x, trig functions of x, log and
1652 ;; inverse trig functions of x, and which are closed under
1653 ;; addition, multiplication, exponentiation, and substitution.
1655 ;; Elem(f(x)) is the same as Elem(x), but f(x) replaces x in the
1656 ;; definition.
1658 (when *debug-integrate* (format t "~& Case IV:~%"))
1660 (when (and (m2 y '((coeffpt) (c rat1 sin* cos* -1) ((mexpt) cos* (n odd1 -1))))
1661 (setq repl (list '(%sin) var2)))
1662 ;; The case cos^(2*n+1)*Elem(cos^2,sin). Use the substitution z = sin.
1663 (go getout))
1665 (when (and (m2 y '((coeffpt) (c rat1 cos* sin* -1) ((mexpt) sin* (n odd1 -1))))
1666 (setq repl (list '(%cos) var2)))
1667 ;; The case sin^(2*n+1)*Elem(sin^2,cos). Use the substitution z = cos.
1668 (go get3))
1670 ;; Case V:
1671 ;; Transform sin and cos to tan and sec to see if the integral is
1672 ;; of the form Elem(tan, sec^2). If so, use the substitution z = tan.
1674 (when *debug-integrate* (format t "~& Case V:~%"))
1676 (setq y (subliss '((sin* (mtimes) tan* ((mexpt) sec* -1))
1677 (cos* (mexpt) sec* -1))
1678 y2))
1679 (when (and (rat1 y 'tan* 'sec* 1) (setq repl (list '(%tan) var2)))
1680 (go get1))
1682 (when (and (m2 y '((coeffpt) (c rat1 sec* tan* 1) ((mexpt) tan* (n odd1 1))))
1683 (setq repl (list '(%sec) var2)))
1684 (go getout))
1685 (when (not (alike1 (setq repl ($expand expr)) expr))
1686 (return (integrator repl var2)))
1687 (setq y (subliss '((sin* (mtimes) 2 x
1688 ((mexpt) ((mplus) 1 ((mexpt) x 2)) -1))
1689 (cos* (mtimes)
1690 ((mplus) 1 ((mtimes) -1 ((mexpt) x 2)))
1691 ((mexpt) ((mplus) 1 ((mexpt) x 2)) -1)))
1692 y1))
1693 (setq y (list '(mtimes)
1695 '((mtimes) 2 ((mexpt) ((mplus) 1 ((mexpt) x 2)) -1))))
1696 (setq repl (subvar '((mquotient) ((%sin) x) ((mplus) 1 ((%cos) x)))
1697 var2))
1698 (go get2)
1699 get3
1700 (setq y (list '(mtimes) -1 *yy* *yz*))
1701 (go get2)
1702 get1
1703 (setq y (list '(mtimes) '((mexpt) ((mplus) 1 ((mexpt) x 2)) -1) *yy*))
1704 (go get2)
1705 getout
1706 (setq y (list '(mtimes) *yy* *yz*))
1707 get2
1708 (when *debug-integrate*
1709 (format t "~& Call the INTEGRATOR with:~%")
1710 (format t "~& : y = ~A~%" y)
1711 (format t "~& : repl = ~A~%" repl))
1712 ;; See Bug 2880797. We want atan(tan(x)) to simplify to x, so
1713 ;; set $triginverses to '$all.
1714 (return
1715 ;; Do not integrate for the global variable VAR, but substitute it.
1716 ;; This way possible assumptions on VAR are no longer present. The
1717 ;; algorithm of DEFINT depends on this behavior. See Bug 3085498.
1718 (let (($triginverses '$all) (newvar (gensym)))
1719 (substint repl
1720 newvar
1721 (integrator (maxima-substitute newvar 'x y) newvar)
1722 var2
1723 expr)))))
1725 (defmvar $integration_constant_counter 0)
1726 (defmvar $integration_constant '$%c)
1728 ;; This is the top level of the integrator
1729 (defun sinint (expr var2)
1730 ;; *integrator-level* is a recursion counter for INTEGRATOR. See
1731 ;; INTEGRATOR for more details. Initialize it here.
1732 (let ((*integrator-level* 0))
1733 (declare (special *integrator-level*))
1735 ;; Sanity checks for variables
1736 (when (mnump var2)
1737 (merror (intl:gettext "integrate: variable must not be a number; found: ~:M") var2))
1738 (when ($ratp var2) (setf var2 (ratdisrep var2)))
1739 (when ($ratp expr) (setf expr (ratdisrep expr)))
1741 (cond
1742 ;; Distribute over lists and matrices
1743 ((mxorlistp expr)
1744 (cons (car expr)
1745 (mapcar #'(lambda (y) (sinint y var2)) (cdr expr))))
1747 ;; The symbolic integration code doesn't really deal very well with
1748 ;; subscripted variables, so if we have one then replace occurrences of var2
1749 ;; with an atomic gensym and recurse.
1750 ((and (not (atom var2))
1751 (member 'array (cdar var2)))
1752 (let ((dummy-var2 (gensym)))
1753 (maxima-substitute var2 dummy-var2
1754 (sinint (maxima-substitute dummy-var2 var2 expr) dummy-var2))))
1756 ;; If expr is an equality, integrate both sides and add an integration
1757 ;; constant
1758 ((mequalp expr)
1759 (list (car expr) (sinint (cadr expr) var2)
1760 (add (sinint (caddr expr) var2)
1761 ($concat $integration_constant (incf $integration_constant_counter)))))
1763 ;; If var2 is an atom which occurs as an operator in expr, then return a noun form.
1764 ((and (atom var2)
1765 (isinop expr var2))
1766 (list '(%integrate) expr var2))
1768 ((zerop1 expr) ;; special case because 0 will not pass sum-of-intsp test
1771 ((let ((ans (simplify
1772 (let ($opsubst varlist genvar)
1773 (integrator expr var2 nil)))))
1774 (if (sum-of-intsp ans var2)
1775 (list '(%integrate) expr var2)
1776 ans))))))
1778 ;; SUM-OF-INTSP
1780 ;; This is a heuristic that SININT uses to work out whether the result from
1781 ;; INTEGRATOR is worth returning or whether just to return a noun form. If this
1782 ;; function returns T, then SININT will return a noun form.
1784 ;; The logic, as I understand it (Rupert 01/2014):
1786 ;; (1) If I integrate f(x) wrt x and get an atom other than x or 0, either
1787 ;; something's gone horribly wrong, or this is part of a larger
1788 ;; expression. In the latter case, we can return T here because hopefully
1789 ;; something else interesting will make the top-level return NIL.
1791 ;; (2) If I get a sum, return a noun form if every one of the summands is no
1792 ;; better than what I started with. (Presumably this is where the name
1793 ;; came from)
1795 ;; (3) If this is a noun form, it doesn't convey much information on its own,
1796 ;; so return T.
1798 ;; (4) If this is a product, something interesting has probably happened. But
1799 ;; I still want a noun form if the result is like 2*'integrate(f(x),x), so
1800 ;; I'm only interested in terms in the product that are not free of
1801 ;; VAR. If one of those terms is worthy of report, that's great: return
1802 ;; NIL. Otherwise, return T if we saw at least two things (eg splitting an
1803 ;; integral into a product of two integrals)
1805 ;; (5) If the result is free of VAR, we're in a similar position to (1).
1807 ;; (6) Otherwise something interesting (and hopefully useful) has
1808 ;; happened. Return NIL to tell SININT to report it.
1809 (defun sum-of-intsp (ans var2)
1810 (cond ((atom ans)
1811 ;; Result of integration should never be a constant other than zero.
1812 ;; If the result of integration is zero, it is either because:
1813 ;; 1) a subroutine inside integration failed and returned nil,
1814 ;; and (mul 0 nil) yielded 0, meaning that the result is wrong, or
1815 ;; 2) the original integrand was actually zero - this is handled
1816 ;; with a separate special case in sinint
1817 (not (eq ans var2)))
1818 ((mplusp ans) (every #'(lambda (e)
1819 (sum-of-intsp e var2))
1820 (cdr ans)))
1821 ((eq (caar ans) '%integrate) t)
1822 ((mtimesp ans)
1823 (let ((int-factors 0))
1824 (not (or (dolist (factor (cdr ans))
1825 (unless (freeof var2 factor)
1826 (if (sum-of-intsp factor var2)
1827 (incf int-factors)
1828 (return t))))
1829 (<= 2 int-factors)))))
1830 ((freeof var2 ans) t)
1831 (t nil)))
1833 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1835 ;;; Stage I
1836 ;;; Implementation of Method 2: Integrate a summation
1838 (defun intsum (form var2)
1839 (prog (expr idx ll ul pair val)
1840 (setq expr (cadr form)
1841 idx (caddr form)
1842 ll (cadddr form)
1843 ul (car (cddddr form)))
1844 (if (or (not (atom var2))
1845 (not (free idx var2))
1846 (not (free ll var2))
1847 (not (free ul var2)))
1848 (return (list '(%integrate) form var2)))
1849 (setq pair (partition expr var2 1))
1850 (when (and (mexptp (cdr pair))
1851 (eq (caddr pair) var2))
1852 (setq val (maxima-substitute ll idx (cadddr pair)))
1853 (cond ((equal val -1)
1854 (return (add (integrator (maxima-substitute ll idx expr) var2)
1855 (intsum1 expr idx (add 1 ll) ul var2))))
1856 ((mlsp val -1)
1857 (return (list '(%integrate) form var2)))))
1858 (return (intsum1 expr idx ll ul var2))))
1860 (defun intsum1 (expr idx ll ul var2)
1861 (assume (list '(mgeqp) idx ll))
1862 (if (not (eq ul '$inf))
1863 (assume (list '(mgeqp) ul idx)))
1864 (simplifya (list '(%sum) (integrator expr var2) idx ll ul) t))
1866 (defun finds (x)
1867 (if (atom x)
1868 (member x '(%log %integrate %atan) :test #'eq)
1869 (or (finds (car x)) (finds (cdr x)))))
1871 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1873 ;;; Stage II
1874 ;;; Implementation of Method 9:
1875 ;;; Rational function times a log or arctric function
1877 ;;; ratlog is called for an expression containing a log or arctrig function
1878 ;;; The integrand is like log(x)*f'(x). To obtain the result the technique of
1879 ;;; partial integration is applied: log(x)*f(x)-integrate(1/x*f(x),x)
1881 ;;; Only called by intform.
1882 (defun ratlog (var2 form)
1883 (prog (b c d y z)
1884 (setq y form)
1885 (setq b (cdr (assoc 'b y :test #'eq)))
1886 (setq c (cdr (assoc 'c y :test #'eq)))
1887 (setq y (integrator c var2))
1888 (when (finds y) (return nil))
1889 (setq d (sdiff (cdr (assoc 'a form :test #'eq)) var2))
1891 (setq z (integrator (mul2* y d) var2))
1892 (setq d (cdr (assoc 'a form :test #'eq)))
1893 (return (simplify (list '(mplus)
1894 (list '(mtimes) y d)
1895 (list '(mtimes) -1 z))))))
1897 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1899 ;;; partial-integration is an extension of the algorithm of ratlog to support
1900 ;;; the technique of partial integration for more cases. The integrand
1901 ;;; is like g(x)*f'(x) and the result is g(x)*f(x)-integrate(g'(x)*f(x),x).
1903 ;;; Adding integrals properties for elementary functions led to infinite recursion
1904 ;;; with integrate(z*expintegral_shi(z),z). This was resolved by limiting the
1905 ;;; recursion depth. *integrator-level* needs to be at least 3 to solve
1906 ;;; o integrate(expintegral_ei(1/sqrt(x)),x)
1907 ;;; o integrate(sqrt(z)*expintegral_li(z),z)
1908 ;;; while a value of 4 causes testsuite regressions with
1909 ;;; o integrate(z*expintegral_shi(z),z)
1910 (defun partial-integration (form var2)
1911 (declare (special *integrator-level*))
1912 (let ((g (cdr (assoc 'a form))) ; part g(x)
1913 (df (cdr (assoc 'c form))) ; part f'(x)
1914 (f nil))
1915 (setq f (integrator df var2)) ; integrate f'(x) wrt var2
1916 (cond
1917 ((or (isinop f '%integrate) ; no result or
1918 (isinop f (caar g)) ; g in result
1919 (> *integrator-level* 3))
1920 nil) ; we return nil
1922 ;; Build the result: g(x)*f(x)-integrate(g'(x)*f(x))
1923 (add (mul f g)
1924 (mul -1 (integrator (mul f (sdiff g var2)) var2)))))))
1926 ;; returns t if argument of every trig operation in y matches arg
1927 (defun every-trigarg-alike (y arg)
1928 (cond ((atom y) t)
1929 ((optrig (caar y)) (alike1 arg (cadr y)))
1930 (t (every (lambda (expr)
1931 (every-trigarg-alike expr arg))
1932 (cdr y)))))
1934 ;; return argument of first trig operation encountered in y
1935 (defun find-first-trigarg (y)
1936 (cond ((atom y) nil)
1937 ((optrig (caar y)) (cadr y))
1938 (t (some (lambda (expr)
1939 (find-first-trigarg expr))
1940 (cdr y)))))
1942 ;; return constant factor that makes elements of alist match elements of blist
1943 ;; or nil if no match found
1944 ;; (we could replace this using rat package to divide alist and blist)
1945 (defun matchsum (alist blist var2)
1946 (prog (r s cc dd)
1947 (setq s (m2 (car alist) ;; find coeff for first term of alist
1948 `((mtimes)
1949 ((coefftt) (a freevar2 ,var2))
1950 ((coefftt) (c true)))))
1951 (setq cc (cdr (assoc 'c s :test #'eq)))
1952 (cond ((not (setq r ;; find coeff for first term of blist
1953 (m2 (car blist)
1954 (cons '(mtimes)
1955 (cons `((coefftt) (b free12 ,var2))
1956 (cond ((mtimesp cc)
1957 (cdr cc))
1958 (t (list cc))))))))
1959 (return nil)))
1960 (setq dd (simplify (list '(mtimes)
1961 (subliss s 'a)
1962 (list '(mexpt)
1963 (subliss r 'b)
1964 -1))))
1965 (cond ((m2 (cons '(mplus) alist) ;; check that all terms match
1966 (timesloop dd blist))
1967 (return dd))
1968 (t (return nil)))))
1970 (defun timesloop (a b)
1971 (cons '(mplus) (mapcar #'(lambda (c) (mul2* a c)) b)))
1973 (defun expands (arg1 arg2)
1974 (addn (mapcar #'(lambda (c) (timesloop c arg1)) arg2) nil))
1976 ;; possibly a bug: For var2 = x and dd =3, we have expand(?subst10(x^9 * (x+x^6))) --> x^5+x^4, but
1977 ;; ?subst10(expand(x^9 * (x+x^6))) --> x^5+x^3. (Barton Willis)
1979 (defun subst10 (ex var2 dd)
1980 (cond ((atom ex) ex)
1981 ((and (eq (caar ex) 'mexpt) (eq (cadr ex) var2))
1982 (list '(mexpt) var2 (integerp2 (quotient (caddr ex) dd))))
1983 (t (cons (remove 'simp (car ex))
1984 (mapcar #'(lambda (c)
1985 (subst10 c var2 dd))
1986 (cdr ex))))))
1988 (defun powerlist (expr var2)
1989 (prog (y cc dd power-list bb)
1990 (setq y (m2 expr
1991 `((mtimes)
1992 ((mexpt) (var varp2 ,var2) (c integerp2))
1993 ((coefftt) (a freevar2 ,var2))
1994 ((coefftt) (b true)))))
1995 (setq bb (cdr (assoc 'b y :test #'eq)))
1996 (setq cc (cdr (assoc 'c y :test #'eq)))
1997 (labels
1998 ((rat10 (ex)
1999 (cond ((freevar2 ex var2)
2001 ((varp2 ex var2)
2002 nil)
2003 ((eq (caar ex) 'mexpt)
2004 (if (varp2 (cadr ex) var2)
2005 (if (integerp2 (caddr ex))
2006 (setq power-list (cons (caddr ex) power-list)))
2007 (and (rat10 (cadr ex))
2008 (rat10 (caddr ex)))))
2009 ((member (caar ex) '(mplus mtimes) :test #'eq)
2010 (do ((u (cdr ex) (cdr u)))
2011 ((null u) t)
2012 (if (not (rat10 (car u)))
2013 (return nil)))))))
2014 (unless (rat10 bb) (return nil))
2015 (setq dd (apply #'gcd (cons (1+ cc) power-list))))
2016 (when (or (eql 1 dd) (zerop dd)) (return nil))
2017 (return
2018 (substint
2019 (list '(mexpt) var2 dd)
2020 var2
2021 (integrate5 (simplify (list '(mtimes)
2022 (power* dd -1)
2023 (cdr (assoc 'a y :test #'eq))
2024 (list '(mexpt) var2 (1- (quotient (1+ cc) dd)))
2025 (subst10 bb var2 dd)))
2026 var2)
2027 var2
2028 expr))))
2030 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2032 ;;; Stage I
2033 ;;; Implementation of Method 3: Derivative-divides algorithm
2035 ;; This is the derivative-divides algorithm of Moses.
2037 ;; /
2038 ;; [
2039 ;; Look for form I c * op(u(x)) * u'(x) dx
2040 ;; ]
2041 ;; /
2043 ;; where: c is a constant
2044 ;; u(x) is an elementary expression in x
2045 ;; u'(x) is its derivative
2046 ;; op is an elementary operator:
2047 ;; - the identity, or
2048 ;; - any function that can be integrated by INTEGRALLOOKUPS
2050 ;; The method of solution, once the problem has been determined to
2051 ;; posses the form above, is to look up OP in a table and substitute
2052 ;; u(x) for each occurrence of x in the expression given in the table.
2053 ;; In other words, the method performs an implicit substitution y = u(x),
2054 ;; and obtains the integral of op(y)dy by a table look up.
2056 (defun diffdiv (expr var2)
2057 (prog (y x v dd z w r)
2058 (cond ((and (mexptp expr)
2059 (mplusp (cadr expr))
2060 (integerp (caddr expr))
2061 (< (caddr expr) 6)
2062 (> (caddr expr) 0))
2063 (return (integrator (expandexpt (cadr expr) (caddr expr)) var2))))
2065 ;; If not a product, transform to a product with one term
2066 (setq expr (cond ((mtimesp expr) expr) (t (list '(mtimes) expr))))
2068 ;; Loop over the terms in expr
2069 (setq z (cdr expr))
2070 a (setq y (car z))
2072 ;; This m2 pattern matches const*(exp/y)
2073 (setq r (list '(mplus)
2074 (cons '(coeffpt)
2075 (cons `(c free12 ,var2)
2076 (remove y (cdr expr) :count 1)))))
2077 (cond
2078 ;; Case u(var2) is the identity function. y is a term in exp.
2079 ;; Match if diff(y,var2) == c*(exp/y).
2080 ;; This even works when y is a function with multiple args.
2081 ((setq w (m2 (sdiff y var2) r))
2082 (return (muln (list y y (power* (mul2* 2 (cdr (assoc 'c w :test #'eq))) -1)) nil))))
2084 ;; w is the arg in y.
2085 (let ((arg-freevar))
2086 (setq w
2087 (cond
2088 ((or (atom y) (member (caar y) '(mplus mtimes) :test #'eq)) y)
2089 ;; Take the argument of a function with one value.
2090 ((= (length (cdr y)) 1) (cadr y))
2091 ;; A function has multiple args, and exactly one arg depends on var2
2092 ((= (count-if #'null (setq arg-freevar (mapcar #'(lambda (v)
2093 (freevar2 v var2))
2094 (cdr y))))
2096 (do ((args (cdr y) (cdr args))
2097 (argf arg-freevar (cdr argf)))
2098 ((if (not (car argf)) (return (car args))))))
2099 (t 0))))
2101 (cond
2102 ((setq w (cond ((and (setq x (sdiff w var2))
2103 (mplusp x)
2104 (setq dd (remove y (cdr expr) :count 1))
2105 (setq v (car dd))
2106 (mplusp v)
2107 (not (cdr dd)))
2108 (cond ((setq dd (matchsum (cdr x) (cdr v) var2))
2109 (list (cons 'c dd)))
2110 (t nil)))
2111 (t (m2 x r))))
2112 (return (cond ((null (setq x (integrallookups y var2))) nil)
2113 ((eq w t) x)
2114 (t (mul2* x (power* (cdr (assoc 'c w :test #'eq)) -1)))))))
2115 (setq z (cdr z))
2116 (when (null z) (return nil))
2117 (go a)))
2119 (defun subliss (alist expr)
2120 "Alist is an alist consisting of a variable (symbol) and its value. expr is
2121 an expression. For each entry in alist, substitute the corresponding
2122 value into expr."
2123 (let ((x expr))
2124 (dolist (a alist x)
2125 (setq x (maxima-substitute (cdr a) (car a) x)))))
2127 (defun substint (x y expres var2 expr)
2128 (if (and (not (atom expres)) (eq (caar expres) '%integrate))
2129 (list (car expres) expr var2)
2130 (substint1 (maxima-substitute x y expres) var2)))
2132 (defun substint1 (expr var2)
2133 (cond ((atom expr) expr)
2134 ((and (eq (caar expr) '%integrate)
2135 (null (cdddr expr))
2136 (not (symbolp (caddr expr)))
2137 (not (free (caddr expr) var2)))
2138 (simplify (list '(%integrate)
2139 (mul2 (cadr expr) (sdiff (caddr expr) var2))
2140 var2)))
2141 (t (recur-apply #'(lambda (e)
2142 (substint1 e var2))
2143 expr))))
2145 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2147 ;:; Extension of the integrator for more integrals with power functions
2149 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2151 ;;; Recognize (a^(c*(z^r)^p+d)^v
2153 (defun m2-exp-type-1a (expr var2)
2154 (m2 expr
2155 `((mexpt)
2156 ((mexpt)
2157 (a freevar02 ,var2)
2158 ((mplus)
2159 ;; The order of the pattern is critical. If we change it,
2160 ;; we do not get the expected match.
2161 ((coeffpp) (d freevar2 ,var2))
2162 ((coefft) (c freevar02 ,var2)
2163 ((mexpt)
2164 ((mexpt) (z varp2 ,var2) (r freevar02 ,var2))
2165 (p freevar2 ,var2)))))
2166 (v freevar2 ,var2))))
2168 ;;; Recognize z^v*a^(b*z^r+d)
2170 (defun m2-exp-type-2 (expr var2)
2171 (m2 expr
2172 `((mtimes)
2173 ((mexpt) (z varp2 ,var2) (v freevar02 ,var2))
2174 ((mexpt)
2175 (a freevar02 ,var2)
2176 ((mplus)
2177 ((coeffpp) (d freevar2 ,var2))
2178 ((coefft) (b freevar02 ,var2) ((mexpt) (z varp2 ,var2) (r freevar02 ,var2))))))))
2180 ;;; Recognize z^v*%e^(a*z^r+b)^u
2182 (defun m2-exp-type-2-1 (expr var2)
2183 (m2 expr
2184 `((mtimes)
2185 ((mexpt) (z varp2 ,var2) (v freevar02 ,var2))
2186 ((mexpt)
2187 ((mexpt)
2189 ((mplus)
2190 ((coeffpp) (b freevar2 ,var2))
2191 ((coefft) (a freevar02 ,var2) ((mexpt) (z varp2 ,var2) (r freevar02 ,var2)))))
2192 (u freevar2 ,var2)))))
2194 ;;; Recognize (a*z+b)^p*%e^(c*z+d)
2196 (defun m2-exp-type-3 (expr var2)
2197 (m2 expr
2198 `((mtimes)
2199 ((mexpt)
2200 ((mplus)
2201 ((coefft) (a freevar02 ,var2) (z varp2 ,var2))
2202 ((coeffpp) (b freevar2 ,var2)))
2203 (p freevar02 ,var2))
2204 ((mexpt)
2206 ((mplus)
2207 ((coefft) (c freevar02 ,var2) (z varp2 ,var2))
2208 ((coeffpp) (d freevar2 ,var2)))))))
2210 ;;; Recognize d^(a*z^2+b/z^2+c)
2212 (defun m2-exp-type-4 (expr var2)
2213 (m2 expr
2214 `((mexpt)
2215 (d freevar02 ,var2)
2216 ((mplus)
2217 ((coefft) (a freevar02 ,var2) ((mexpt) (z varp2 ,var2) 2))
2218 ((coefft) (b freevar02 ,var2) ((mexpt) (z varp2 ,var2) -2))
2219 ((coeffpp) (c freevar2 ,var2))))))
2221 ;;; Recognize z^(2*n)*d^(a*z^2+b/z^2+c)
2223 (defun m2-exp-type-4-1 (expr var2)
2224 (m2 expr
2225 `((mtimes)
2226 ((mexpt) (z varp2 ,var2) (n freevar02 ,var2))
2227 ((mexpt)
2228 (d freevar02 ,var2)
2229 ((mplus)
2230 ((coefft) (a freevar02 ,var2) ((mexpt) (z varp2 ,var2) 2))
2231 ((coefft) (b freevar02 ,var2) ((mexpt) (z varp2 ,var2) -2))
2232 ((coeffpp) (c freevar2 ,var2)))))))
2234 ;;; Recognize z^n*d^(a*z^2+b*z+c)
2236 (defun m2-exp-type-5 (expr var2)
2237 (m2 expr
2238 `((mtimes)
2239 ((mexpt) (z varp2 ,var2) (n freevar2 ,var2))
2240 ((mexpt)
2241 (d freevar02 ,var2)
2242 ((mplus)
2243 ((coeffpt) (a freevar2 ,var2) ((mexpt) (z varp2 ,var2) 2))
2244 ((coeffpt) (b freevar2 ,var2) (z varp2 ,var2))
2245 ((coeffpp) (c freevar2 ,var2)))))))
2247 ;;; Recognize z^n*(%e^(a*z^2+b*z+c))^u
2249 (defun m2-exp-type-5-1 (expr var2)
2250 (m2 expr
2251 `((mtimes)
2252 ((mexpt) (z varp2 ,var2) (n freevar02 ,var2))
2253 ((mexpt)
2254 ((mexpt)
2256 ((mplus)
2257 ((coeffpp) (c freevar2 ,var2))
2258 ((coefft) (a freevar02 ,var2) ((mexpt) (z varp2 ,var2) 2))
2259 ((coefft) (b freevar02 ,var2) (z varp2 ,var2))))
2260 (u freevar2 ,var2)))))
2262 ;;; Recognize z^n*d^(a*sqrt(z)+b*z+c)
2264 (defun m2-exp-type-6 (expr var2)
2265 (m2 expr
2266 `((mtimes)
2267 ((mexpt) (z varp2 ,var2) (n freevar02 ,var2))
2268 ((mexpt)
2269 (d freevar02 ,var2)
2270 ((mplus)
2271 ((coefft) (a freevar02 ,var2) ((mexpt) (z varp2 ,var2) ((rat) 1 2)))
2272 ((coefft) (b freevar02 ,var2) (z varp2 ,var2))
2273 ((coeffpp) (c freevar2 ,var2)))))))
2275 ;;; Recognize z^n*(%e^(a*sqrt(z)+b*z+c))^u
2277 (defun m2-exp-type-6-1 (expr var2)
2278 (m2 expr
2279 `((mtimes)
2280 ((mexpt) (z varp2 ,var2) (n freevar02 ,var2))
2281 ((mexpt)
2282 ((mexpt)
2284 ((mplus)
2285 ((coeffpp) (c freevar2 ,var2))
2286 ((coefft) (a freevar02 ,var2) ((mexpt) (z varp2 ,var2) ((rat) 1 2)))
2287 ((coefft) (b freevar02 ,var2) (z varp2 ,var2))))
2288 (u freevar2 ,var2)))))
2290 ;;; Recognize z^n*a^(b*z^r+e)*h^(c*z^r+g)
2292 (defun m2-exp-type-7 (expr var2)
2293 (m2 expr
2294 `((mtimes)
2295 ((mexpt) (z varp2 ,var2) (n freevar2 ,var2))
2296 ((mexpt)
2297 (a freevar02 ,var2)
2298 ((mplus)
2299 ((coefft)
2300 (b freevar02 ,var2)
2301 ((mexpt) (z varp2 ,var2) (r freevar02 ,var2)))
2302 ((coeffpp) (e freevar2 ,var2))))
2303 ((mexpt)
2304 (h freevar02 ,var2)
2305 ((mplus)
2306 ((coefft)
2307 (c freevar02 ,var2)
2308 ((mexpt) (z varp2 ,var2) (r1 freevar02 ,var2)))
2309 ((coeffpp) (g freevar2 ,var2)))))))
2311 ;;; Recognize z^v*(%e^(b*z^r+e))^q*(%e^(c*z^r+g))^u
2313 (defun m2-exp-type-7-1 (expr var2)
2314 (m2 expr
2315 `((mtimes)
2316 ((mexpt) (z varp2 ,var2) (v freevar2 ,var2))
2317 ((mexpt)
2318 ((mexpt)
2320 ((mplus)
2321 ((coeffpp) (e freevar2 ,var2))
2322 ((coefft) (b freevar02 ,var2) ((mexpt) (z varp2 ,var2) (r freevar02 ,var2)))))
2323 (q freevar2 ,var2))
2324 ((mexpt)
2325 ((mexpt)
2327 ((mplus)
2328 ((coeffpp) (g freevar2 ,var2))
2329 ((coefft) (c freevar02 ,var2) ((mexpt) (z varp2 ,var2) (r1 freevar02 ,var2)))))
2330 (u freevar2 ,var2)))))
2332 ;;; Recognize a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z)+f*z+g)
2334 (defun m2-exp-type-8 (expr var2)
2335 (m2 expr
2336 `((mtimes)
2337 ((mexpt)
2338 (a freevar02 ,var2)
2339 ((mplus)
2340 ((coeffpt) (b freevar2 ,var2) ((mexpt) (z varp2 ,var2) ((rat) 1 2)))
2341 ((coeffpt) (d freevar2 ,var2) (z varp2 ,var2))
2342 ((coeffpp) (e freevar2 ,var2))))
2343 ((mexpt)
2344 (h freevar02 ,var2)
2345 ((mplus)
2346 ((coeffpt) (c freevar2 ,var2) ((mexpt) (z varp2 ,var2) ((rat) 1 2)))
2347 ((coeffpt) (f freevar2 ,var2) (z varp2 ,var2))
2348 ((coeffpp) (g freevar2 ,var2)))))))
2350 ;;; Recognize (%e^(b*sqrt(z)+d*z+e))^u*(%e^(c*sqrt(z)+f*z+g))^v
2352 (defun m2-exp-type-8-1 (expr var2)
2353 (m2 expr
2354 `((mtimes)
2355 ((mexpt)
2356 ((mexpt)
2358 ((mplus)
2359 ((coeffpp) (e freevar2 ,var2))
2360 ((coeffpt) (b freevar2 ,var2) ((mexpt) (z varp2 ,var2) ((rat) 1 2)))
2361 ((coeffpt) (d freevar2 ,var2) (z varp2 ,var2))))
2362 (u freevar2 ,var2))
2363 ((mexpt)
2364 ((mexpt)
2366 ((mplus)
2367 ((coeffpp) (g freevar2 ,var2))
2368 ((coeffpt) (c freevar2 ,var2) ((mexpt) (z varp2 ,var2) ((rat) 1 2)))
2369 ((coeffpt) (f freevar2 ,var2) (z varp2 ,var2))))
2370 (v freevar2 ,var2)))))
2372 ;;; Recognize (%e^(b*z^r+e))^u*(%e^(c*z^r+g))^v
2374 (defun m2-exp-type-8-2 (expr var2)
2375 (m2 expr
2376 `((mtimes)
2377 ((mexpt)
2378 ((mexpt)
2380 ((mplus)
2381 ((coeffpp) (e freevar2 ,var2))
2382 ((coefft) (b freevar2 ,var2) ((mexpt) (z varp2 ,var2) (r freevar02 ,var2)))))
2383 (u freevar2 ,var2))
2384 ((mexpt)
2385 ((mexpt)
2387 ((mplus)
2388 ((coeffpp) (g freevar2 ,var2))
2389 ((coefft) (c freevar2 ,var2) ((mexpt) (z varp2 ,var2) (r1 freevar02 ,var2)))))
2390 (v freevar2 ,var2)))))
2392 ;;; Recognize z^n*a^(b*z^2+d*z+e)*h^(c*z^2+f*z+g)
2394 (defun m2-exp-type-9 (expr var2)
2395 (m2 expr
2396 `((mtimes)
2397 ((mexpt) (z varp2 ,var2) (n freevar2 ,var2))
2398 ((mexpt)
2399 (a freevar02 ,var2)
2400 ((mplus)
2401 ((coeffpt) (b freevar2 ,var2) ((mexpt) (z varp2 ,var2) 2))
2402 ((coeffpt) (d freevar2 ,var2) (z varp2 ,var2))
2403 ((coeffpp) (e freevar2 ,var2))))
2404 ((mexpt)
2405 (h freevar02 ,var2)
2406 ((mplus)
2407 ((coeffpt) (c freevar2 ,var2) ((mexpt) (z varp2 ,var2) 2))
2408 ((coeffpt) (f freevar2 ,var2) (z varp2 ,var2))
2409 ((coeffpp) (g freevar2 ,var2)))))))
2411 ;;; Recognize z^n*(%e^(b*z^2+d*z+e))^q*(%e^(c*z^2+f*z+g))^u
2413 (defun m2-exp-type-9-1 (expr var2)
2414 (m2 expr
2415 `((mtimes)
2416 ((mexpt) (z varp2 ,var2) (n freevar2 ,var2))
2417 ((mexpt)
2418 ((mexpt)
2420 ((mplus)
2421 ((coeffpp) (e freevar2 ,var2))
2422 ((coeffpt) (b freevar2 ,var2) ((mexpt) (z varp2 ,var2) 2))
2423 ((coeffpt) (d freevar2 ,var2) (z varp2 ,var2))))
2424 (q freevar2 ,var2))
2425 ((mexpt)
2426 ((mexpt)
2428 ((mplus)
2429 ((coeffpp) (g freevar2 ,var2))
2430 ((coeffpt) (c freevar2 ,var2) ((mexpt) (z varp2 ,var2) 2))
2431 ((coeffpt) (f freevar2 ,var2) (z varp2 ,var2))))
2432 (u freevar2 ,var2)))))
2434 ;;; Recognize z^n*a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z+)f*z+g)
2436 (defun m2-exp-type-10 (expr var2)
2437 (m2 expr
2438 `((mtimes)
2439 ((mexpt) (z varp2 ,var2) (n freevar2 ,var2))
2440 ((mexpt)
2441 (a freevar02 ,var2)
2442 ((mplus)
2443 ((coeffpt) (b freevar2 ,var2) ((mexpt) (z varp2 ,var2) ((rat) 1 2)))
2444 ((coeffpt) (d freevar2 ,var2) (z varp2 ,var2))
2445 ((coeffpp) (e freevar2 ,var2))))
2446 ((mexpt)
2447 (h freevar02 ,var2)
2448 ((mplus)
2449 ((coeffpt) (c freevar2 ,var2) ((mexpt) (z varp2 ,var2) ((rat) 1 2)))
2450 ((coeffpt) (f freevar2 ,var2) (z varp2 ,var2))
2451 ((coeffpp) (g freevar2 ,var2)))))))
2453 ;;; Recognize z^n*(%e^(b*sqrt(z)+d*z+e))^q*(%e^(c*sqrt(z)+f*z+g))^u
2455 (defun m2-exp-type-10-1 (expr var2)
2456 (m2 expr
2457 `((mtimes)
2458 ((mexpt) (z varp2 ,var2) (n freevar2 ,var2))
2459 ((mexpt)
2460 ((mexpt)
2462 ((mplus)
2463 ((coeffpp) (e freevar2 ,var2))
2464 ((coeffpt) (b freevar2 ,var2) ((mexpt) (z varp2 ,var2) ((rat) 1 2)))
2465 ((coeffpt) (d freevar2 ,var2) (z varp2 ,var2))))
2466 (q freevar2 ,var2))
2467 ((mexpt)
2468 ((mexpt)
2470 ((mplus)
2471 ((coeffpp) (g freevar2 ,var2))
2472 ((coeffpt) (c freevar2 ,var2) ((mexpt) (z varp2 ,var2) ((rat) 1 2)))
2473 ((coeffpt) (f freevar2 ,var2) (z varp2 ,var2))))
2474 (u freevar2 ,var2)))))
2476 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2478 (defun integrate-exp-special (expr var2 &aux w const)
2480 ;; First factor the expression.
2481 (setq expr ($factor expr))
2483 ;; Remove constant factors.
2484 (setq w (partition expr var2 1))
2485 (setq const (car w))
2486 (setq expr (cdr w))
2488 (schatchen-cond w
2489 ((m2-exp-type-1a (facsum-exponent expr var2) var2)
2490 (a c d r p v)
2491 (when *debug-integrate*
2492 (format t "~&Type 1a: (a^(c*(z^r)^p+d)^v : w = ~A~%" w))
2494 (mul -1
2495 const
2496 ;; 1/(p*r*(a^(c*v*(var2^r)^p)))
2497 (inv (mul p r (power a (mul c v (power (power var2 r) p)))))
2498 var2
2499 ;; (a^(d+c*(var2^r)^p))^v
2500 (power (power a (add d (mul c (power (power var2 r) p)))) v)
2501 ;; gamma_incomplete(1/(p*r), -c*v*(var2^r)^p*log(a))
2502 (take '(%gamma_incomplete)
2503 (inv (mul p r))
2504 (mul -1 c v (power (power var2 r) p) (take '(%log) a)))
2505 ;; (-c*v*(var2^r)^p*log(a))^(-1/(p*r))
2506 (power (mul -1 c v (power (power var2 r) p) (take '(%log) a))
2507 (div -1 (mul p r)))))
2509 ((m2-exp-type-2 (facsum-exponent expr var2) var2)
2510 (a b d v r)
2512 (when *debug-integrate*
2513 (format t "~&Type 2: z^v*a^(b*z^r+d) : w = ~A~%" w))
2515 (mul
2516 const
2517 (div -1 r)
2518 (power a d)
2519 (power var2 (add v 1))
2520 ($gamma_incomplete
2521 (div (add v 1) r)
2522 (mul -1 b (power var2 r) ($log a)))
2523 (power
2524 (mul -1 b (power var2 r) ($log a))
2525 (mul -1 (div (add v 1) r)))))
2527 ((m2-exp-type-2-1 (facsum-exponent expr var2) var2)
2528 (a b v r u)
2529 (when *debug-integrate*
2530 (format t "~&Type 2-1: z^v*(%e^(a*z^r+b))^u : w = ~A~%" w))
2532 (mul const
2534 (inv r)
2535 (power '$%e (mul -1 a u (power var2 r)))
2536 (power (power '$%e (add (mul a (power var2 r)) b)) u)
2537 (power var2 (add v 1))
2538 (power (mul -1 a u (power var2 r)) (div (mul -1 (add v 1)) r))
2539 (take '(%gamma_incomplete)
2540 (div (add v 1) r)
2541 (mul -1 a u (power var2 r)))))
2543 ((m2-exp-type-3 (facsum-exponent expr var2) var2)
2544 (a b c d p)
2545 (when *debug-integrate*
2546 (format t "~&Type 3: (a*z+b)^p*%e^(c*z+d) : w = ~A~%" w))
2547 (mul
2548 const
2549 (div -1 a)
2550 (power '$%e (sub d (div (mul b c) a)))
2551 (power (add b (mul a var2)) (add p 1))
2552 (ftake '%expintegral_e (mul -1 p) (mul (div -1 a) c (add b (mul a var2))))))
2554 ((m2-exp-type-4 expr var2)
2555 (a b c d)
2556 (let (($trigsign nil)) ; Do not simplify erfc(-x) !
2557 (when *debug-integrate*
2558 (format t "~&Type 4: d^(a*z^2+b/z^2+c) : w = ~A~%" w))
2560 (mul
2561 const
2562 (div 1 (mul 4 (power (mul -1 a ($log d)) (div 1 2))))
2563 (mul
2564 (power d c)
2565 (power '$%pi (div 1 2))
2566 (power '$%e
2567 (mul -2
2568 (power (mul -1 a ($log d)) (div 1 2))
2569 (power (mul -1 b ($log d)) (div 1 2))))
2570 (add
2571 ($erfc
2572 (add
2573 (div (power (mul -1 b ($log d)) (div 1 2)) var2)
2574 (mul -1 var2 (power (mul -1 a ($log d)) (div 1 2)))))
2575 (mul -1
2576 (power '$%e
2577 (mul 4
2578 (power (mul -1 a ($log d)) (div 1 2))
2579 (power (mul -1 b ($log d)) (div 1 2))))
2580 ($erfc
2581 (add
2582 (mul var2 (power (mul -1 a ($log d)) (div 1 2)))
2583 (div (power (mul -1 b ($log d)) (div 1 2)) var2)))))))))
2585 ((and (m2-exp-type-4-1 expr var2)
2586 (poseven (cdras 'n w)) ; only for n a positive, even integer
2587 (symbolp (cdras 'a w))) ; a has to be a symbol
2588 (a b c d n)
2589 (let (($trigsign nil)) ; Do not simplify erfc(-x) !
2591 (when *debug-integrate*
2592 (format t "~&Type 4-1: z^(2*n)*d^(a*z^2+b/z^2+c) : w = ~A~%" w))
2594 (setq n (div n 2))
2596 (mul const
2597 (div 1 4)
2598 (power d c)
2599 (power '$%pi (div 1 2))
2600 (simplify (list '(%derivative)
2601 (div
2602 (sub
2603 (mul
2604 (power ($log d) (mul -1 n))
2605 (add
2606 (mul
2607 (power
2608 '$%e
2609 (mul -2
2610 (power (mul -1 a ($log d)) (div 1 2))
2611 (power (mul -1 b ($log d)) (div 1 2))))
2612 ($erfc
2613 (sub
2614 (div
2615 (power (mul -1 b ($log d)) (div 1 2))
2616 var2)
2617 (mul var2 (power (mul -1 ($log d)) (div 1 2))))))))
2618 (mul
2619 (power
2620 '$%e
2621 (mul 2
2622 (power (mul -1 a ($log d)) (div 1 2))
2623 (power (mul -1 b ($log d)) (div 1 2))))
2624 ($erfc
2625 (add
2626 (power (mul -1 a ($log d)) (div 1 2))
2627 (div (power (mul -1 b ($log d)) (div 1 2)) var2)))))
2628 (power (mul -1 a ($log d)) (div 1 2)))
2629 a n)))))
2631 ((and (m2-exp-type-5 (facsum-exponent expr var2) var2)
2632 (maxima-integerp (cdras 'n w))
2633 (eq ($sign (cdras 'n w)) '$pos))
2634 (a b c d n)
2636 (when *debug-integrate*
2637 (format t "~&Type 5: z^n*d^(a*z^2+b*z+c) : w = ~A~%" w))
2639 (mul
2640 const
2641 (div -1 (mul 2 (power (mul a ($log d)) (div 1 2))))
2642 (mul
2643 (power d (sub c (div (mul b b) (mul 4 a))))
2644 (let ((index (gensumindex))
2645 ($simpsum t))
2646 (mfuncall '$sum
2647 (mul
2648 (power 2 (sub index n))
2649 (ftake '%binomial n index)
2650 ($gamma_incomplete
2651 (div (add index 1) 2)
2652 (mul
2653 (div -1 (mul 4 a))
2654 (power (add b (mul 2 a var2)) 2)
2655 ($log d)))
2656 (power (mul a ($log d)) (mul -1 (add n (div 1 2))))
2657 (power (mul -1 b ($log d)) (sub n index))
2658 (power (mul (add b (mul 2 a var2)) ($log d)) (add index 1))
2659 (power
2660 (mul (div -1 a) (power (add b (mul 2 a var2)) 2) ($log d))
2661 (mul (div -1 2) (add index 1))))
2662 index 0 n)))))
2664 ((and (m2-exp-type-5-1 (facsum-exponent expr var2) var2)
2665 (maxima-integerp (cdras 'n w))
2666 (eq ($sign (cdras 'n w)) '$pos))
2667 (a b c u n)
2668 (when *debug-integrate*
2669 (format t "~&Type 5-1: z^n*(%e^(a*z^2+b*z+c))^u : w = ~A~%" w))
2671 (mul const
2672 (div -1 2)
2673 (power '$%e
2674 (add (mul -1 (div (mul b b u) (mul 4 a)))
2675 (mul -1 u (add (mul a var2 var2) (mul b var2)))))
2676 (power a (mul -1 (add n 1)))
2677 (power (power '$%e
2678 (add (mul a var2 var2) (mul b var2) c))
2680 (let ((index (gensumindex))
2681 ($simpsum t))
2682 (dosum
2683 (mul (power 2 (sub index n))
2684 (power (mul -1 b) (sub n index))
2685 (power (add b (mul 2 a var2)) (add index 1))
2686 (power (div (mul -1 u (power (add b (mul 2 a var2)) 2)) a)
2687 (mul (div -1 2) (add index 1)))
2688 (take '(%binomial) n index)
2689 (take '(%gamma_incomplete)
2690 (div (add index 1) 2)
2691 (div (mul -1 u (power (add b (mul 2 a var2)) 2))
2692 (mul 4 a))))
2693 index 0 n t))))
2695 ((and (m2-exp-type-6 (facsum-exponent expr var2) var2)
2696 (maxima-integerp (cdras 'n w))
2697 (eq ($sign (cdras 'n w)) '$pos))
2698 (a b c d n)
2699 (when *debug-integrate*
2700 (format t "~&Type 6: z^n*d^(a*sqrt(z)+b*z+c) : w = ~A~%" w))
2702 (mul
2703 const
2704 (power 2 (mul -1 (add n 1)))
2705 (power d (sub c (div (mul a a) (mul 4 b))))
2706 (power (mul b ($log d)) (mul -2 (add n 1)))
2707 (let ((index1 (gensumindex))
2708 (index2 (gensumindex))
2709 ($simpsum t))
2710 (mfuncall '$sum
2711 (mfuncall '$sum
2712 (mul
2713 (power -1 (sub index1 index2))
2714 (power 4 index1)
2715 (ftake '%binomial index1 index2)
2716 (ftake '%binomial n index1)
2717 ($log d)
2718 (power (mul a ($log d)) (sub (mul 2 n) (add index1 index2)))
2719 (power
2720 (mul (add a (mul 2 b (power var2 (div 1 2)))) ($log d))
2721 (add index1 index2))
2722 (power
2723 (mul
2724 (div -1 b)
2725 (power (add a (mul 2 b (power var2 (div 1 2)))) 2)
2726 ($log d))
2727 (mul (div -1 2) (add index1 index2 1)))
2728 (add
2729 (mul 2 b
2730 (power
2731 (mul
2732 (div -1 b)
2733 (power (add a (mul 2 b (power var2 (div 1 2)))) 2)
2734 ($log d))
2735 (div 1 2))
2736 ($gamma_incomplete
2737 (div (add index1 index2 2) 2)
2738 (mul
2739 (div -1 (mul 4 b))
2740 (power (add a (mul 2 b (power var2 (div 1 2)))) 2)
2741 ($log d))))
2742 (mul a
2743 (add a (mul 2 b (power var2 (div 1 2))))
2744 ($log d)
2745 ($gamma_incomplete
2746 (div (add index1 index2 1) 2)
2747 (mul
2748 (div -1 (mul 4 b))
2749 (power (add a (mul 2 b (power var2 (div 1 2)))) 2)
2750 ($log d))))))
2751 index2 0 index1)
2752 index1 0 n))))
2754 ((and (m2-exp-type-6-1 (facsum-exponent expr var2) var2)
2755 (maxima-integerp (cdras 'n w))
2756 (eq ($sign (cdras 'n w)) '$pos))
2757 (a b c u n)
2758 (when *debug-integrate*
2759 (format t "~&Type 6-1: z^n*(%e^(a*sqrt(z)+b*z+c))^u : w = ~A~%" w))
2761 (mul const
2762 (power 2 (mul -1 (add (mul 2 n) 1)))
2763 (power '$%e
2764 (add (div (mul -1 u a a) (mul 4 b))
2765 (mul u (add (mul a (power var2 (div 1 2)))
2766 (mul b var2)
2767 c))))
2768 (power b (mul -2 (add n 1)))
2769 (power (power '$%e
2770 (add (mul a (power var2 (div 1 2)))
2771 (mul b var2)))
2773 (let ((index1 (gensumindex))
2774 (index2 (gensumindex))
2775 ($simpsum t))
2776 (dosum
2777 (dosum
2778 (mul (power -1 (sub index1 index2))
2779 (power 4 index1)
2780 (power a (add (neg index2) (neg index1) (mul 2 n)))
2781 (power (add a (mul 2 b (power var2 (div 1 2))))
2782 (add index1 index2))
2783 (power (div (mul -1 u
2784 (power (add a
2785 (mul 2
2787 (power var2 (div 1 2))))
2790 (mul (div -1 2) (add index1 index2 1)))
2791 (take '(%binomial) index1 index2)
2792 (take '(%binomial) n index1)
2793 (add (mul a
2794 (add a (mul 2 b (power var2 (div 1 2))))
2795 (take '(%gamma_incomplete)
2796 (div (add index1 index2 1) 2)
2797 (div (mul -1 u
2798 (power (add a
2799 (mul 2 b
2800 (power var2
2801 (div 1 2))))
2803 (mul 4 b))))
2804 (mul (inv u)
2805 (power (div (mul -1 u
2806 (power (add a
2807 (mul 2 b
2808 (power var2
2809 (div 1 2))))
2812 (div 1 2))
2813 (mul 2 b)
2814 (take '(%gamma_incomplete)
2815 (div (add index1 index2 2) 2)
2816 (div (mul -1 u
2817 (power (add a
2818 (mul 2 b
2819 (power var2 (div 1 2))))
2821 (mul 4 b))))))
2822 index2 0 index1 t)
2823 index1 0 n t))))
2825 ((and (m2-exp-type-7 (facsum-exponent expr var2) var2)
2826 (eq ($sign (sub (cdras 'r w) (cdras 'r1 w))) '$zero))
2827 (a b c e g h r n)
2828 (when *debug-integrate*
2829 (format t "~&Type 7: z^n*a^(b*z^r+e)*h^(c*z^r+g) : w = ~A~%" w))
2831 (setq n (add n 1))
2833 (mul
2834 const
2835 (power var2 n)
2836 (div -1 r)
2837 (power a e)
2838 (power h g)
2839 (power
2840 (mul -1
2841 (power var2 r)
2842 (add (mul b ($log a)) (mul c ($log h))))
2843 (div (mul -1 n) r))
2844 ($gamma_incomplete
2845 (div n r)
2846 (mul -1 (power var2 r) (add (mul b ($log a)) (mul c ($log h)))))))
2848 ((and (m2-exp-type-7-1 (facsum-exponent expr var2) var2)
2849 (eq ($sign (sub (cdras 'r w) (cdras 'r1 w))) '$zero))
2850 (b c e g r v q u)
2851 (when *debug-integrate*
2852 (format t "~&Type 7-1: z^v*(%e^(b*z^r+e))^q*(%e^(c*z^r+g))^u : w = ~A~%" w))
2854 (mul const
2855 (div -1 r)
2856 (power '$%e (mul -1 (power var2 r) (add (mul b q) (mul c u))))
2857 (power (power '$%e (add e (mul b (power var2 r)))) q)
2858 (power (power '$%e (add g (mul c (power var2 r)))) u)
2859 (power var2 (add v 1))
2860 (power (mul -1 (power var2 r) (add (mul b q) (mul c u)))
2861 (div (mul -1 (add v 1)) r))
2862 (take '(%gamma_incomplete)
2863 (div (add v 1) r)
2864 (mul -1 (power var2 r) (add (mul b q) (mul c u))))))
2866 ((m2-exp-type-8 (facsum-exponent expr var2) var2)
2867 (a b c d e f g h)
2868 (when *debug-integrate*
2869 (format t "~&Type 8: a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z)+f*z+g)")
2870 (format t "~& : w = ~A~%" w))
2872 (mul
2873 const
2874 (div 1 2)
2875 (power a e)
2876 (power h g)
2877 (add
2878 (mul 2
2879 (power a (add (mul b (power var2 (div 1 2))) (mul d var2)))
2880 (power h (add (mul c (power var2 (div 1 2))) (mul f var2)))
2881 (div 1 (add (mul d ($log a)) (mul f ($log h)))))
2882 (mul -1
2883 (power '$%pi (div 1 2))
2884 (power '$%e
2885 (mul -1
2886 (div
2887 (power (add (mul b ($log a)) (mul c ($log h))) 2)
2888 (mul 4 (add (mul d ($log a)) (mul f ($log h)))))))
2889 ($erfi
2890 (div
2891 (add
2892 (mul b ($log a))
2893 (mul c ($log h))
2894 (mul 2
2895 (power var2 (div 1 2))
2896 (add (mul d ($log a)) (mul f ($log h)))))
2897 (mul 2
2898 (power (add (mul d ($log a)) (mul f ($log h))) (div 1 2)))))
2899 (add (mul b ($log a)) (mul c ($log h)))
2900 (power (add (mul d ($log a)) (mul f ($log h))) (div -3 2))))))
2902 ((m2-exp-type-8-1 (facsum-exponent expr var2) var2)
2903 (b c d e f g u v)
2904 (when *debug-integrate*
2905 (format t "~&Type 8-1: (%e^(b*sqrt(z)+d*z+e))^u*(%e^(c*sqrt(z)+f*z+g))^v")
2906 (format t "~& : w = ~A~%" w))
2908 (mul const
2909 (div 1 2)
2910 (power (add (mul d u) (mul f v)) (div -3 2))
2911 (mul (power '$%e
2912 (mul -1
2913 (power (add (mul b u)
2914 (mul 2 d u (power var2 (div 1 2)))
2915 (mul v (add c (mul 2 f (power var2 (div 1 2))))))
2917 (inv (mul 4 (add (mul d u) (mul f v))))))
2918 (power (power '$%e
2919 (add (mul b (power var2 (div 1 2)))
2921 (mul d var2)))
2923 (power (power '$%e
2924 (add (mul c (power var2 (div 1 2)))
2926 (mul f var2)))
2928 (add (mul 2
2929 (power '$%e
2930 (mul (power (add (mul b u)
2931 (mul 2 d u (power var2 (div 1 2)))
2932 (mul v (add c (mul 2 f (power var2 (div 1 2))))))
2934 (inv (mul 4 (add (mul d u) (mul f v))))))
2935 (power (add (mul d u) (mul f v)) (div 1 2)))
2936 (mul -1
2937 (power '$%pi (div 1 2))
2938 (add (mul b u) (mul c v))
2939 (take '(%erfi)
2940 (div (add (mul b u)
2941 (mul 2 d u (power var2 (div 1 2)))
2942 (mul c v)
2943 (mul 2 f v (power var2 (div 1 2))))
2944 (mul 2
2945 (power (add (mul d u) (mul f v))
2946 (div 1 2))))))))))
2948 ((and (m2-exp-type-8-2 (facsum-exponent expr var2) var2)
2949 (eq ($sign (sub (cdras 'r w) (cdras 'r1 w))) '$zero))
2950 (b c e g r u v)
2951 (when *debug-integrate*
2952 (format t "~&Type 8-2: (%e^(b*z^r+e))^u*(%e^(c*z^r+g))^v")
2953 (format t "~& : w = ~A~%" w))
2955 (mul const
2957 (inv r)
2958 (power '$%e
2959 (mul -1
2960 (power var2 r)
2961 (add (mul b u) (mul c v))))
2962 (power (power '$%e
2963 (add (power var2 r) e))
2965 (power (power '$%e
2966 (add (power var2 r) g))
2968 var2
2969 (power (mul -1
2970 (power var2 r)
2971 (add (mul b u) (mul c v)))
2972 (div -1 r))
2973 (take '(%gamma_incomplete)
2974 (div 1 r)
2975 (mul -1 (power var2 r) (add (mul b u) (mul c v))))))
2977 ((and (m2-exp-type-9 (facsum-exponent expr var2) var2)
2978 (maxima-integerp (cdras 'n w))
2979 (eq ($sign (cdras 'n w)) '$pos)
2980 (or (not (eq ($sign (cdras 'b w)) '$zero))
2981 (not (eq ($sign (cdras 'c w)) '$zero))))
2982 (a b c d e f g h n)
2983 (when *debug-integrate*
2984 (format t "~&Type 9: z^n*a^(b*z^2+d*z+e)*h^(c*z^2+f*z+g)")
2985 (format t "~& : w = ~A~%" w))
2987 (mul
2988 const
2989 (div -1 2)
2990 (power a e)
2991 (power h g)
2992 (power '$%e
2993 (div
2994 (power (add (mul d ($log a)) (mul f ($log h))) 2)
2995 (mul -4 (add (mul b ($log a)) (mul c ($log h))))))
2996 (power (add (mul b ($log a)) (mul c ($log h))) (mul -1 (add n 1)))
2997 (let ((index (gensumindex))
2998 ($simpsum t))
2999 (mfuncall '$sum
3000 (mul
3001 (power 2 (sub index n))
3002 (ftake '%binomial n index)
3003 (power
3004 (add (mul -1 d ($log a)) (mul -1 f ($log h)))
3005 (sub n index))
3006 (power
3007 (add
3008 (mul (add d (mul 2 b var2)) ($log a))
3009 (mul (add f (mul 2 c var2)) ($log h)))
3010 (add index 1))
3011 (power
3012 (mul -1
3013 (div
3014 (power
3015 (add
3016 (mul (add d (mul 2 b var2)) ($log a))
3017 (mul (add f (mul 2 c var2)) ($log h)))
3019 (add (mul b ($log a)) (mul c ($log h)))))
3020 (div (add index 1) -2))
3021 ($gamma_incomplete
3022 (div (add index 1) 2)
3023 (mul -1
3024 (div
3025 (power
3026 (add
3027 (mul (add d (mul 2 b var2)) ($log a))
3028 (mul (add f (mul 2 c var2)) ($log h)))
3030 (mul 4 (add (mul b ($log a)) (mul c ($log h))))))))
3031 index 0 n))))
3033 ((and (m2-exp-type-9-1 (facsum-exponent expr var2) var2)
3034 (maxima-integerp (cdras 'n w))
3035 (eq ($sign (cdras 'n w)) '$pos)
3036 (or (not (eq ($sign (cdras 'b w)) '$zero))
3037 (not (eq ($sign (cdras 'c w)) '$zero))))
3038 (b c d e f g q u n)
3039 (when *debug-integrate*
3040 (format t "~&Type 9-1: z^n*(%e^(b*z^2+d*z+e))^q*(%e^(c*z^2+f*z+g))^u")
3041 (format t "~& : w = ~A~%" w))
3043 (mul const
3044 (div -1 2)
3045 (power (add (mul b q) (mul c u)) (div -1 2))
3046 (power '$%e
3047 (add (div (power (add (mul d q) (mul f u)) 2)
3048 (mul -4 (add (mul b q) (mul c u))))
3049 (mul -1 var2
3050 (add (mul d q)
3051 (mul b q var2)
3052 (mul f u)
3053 (mul c u var2)))))
3054 (power (power '$%e
3055 (add e
3056 (mul var2 (add d (mul b var2)))))
3058 (power (power '$%e
3059 (add g
3060 (mul var2 (add f (mul c var2)))))
3062 (let ((index (gensumindex))
3063 ($simpsum t))
3064 (dosum
3065 (mul (power 2 (sub index n))
3066 (power (add (mul b q) (mul c u)) (neg (add n (div 1 2))))
3067 (power (add (neg (mul d q)) (neg (mul f u)))
3068 (sub n index))
3069 (power (add (mul d q)
3070 (mul f u)
3071 (mul 2 var2 (add (mul b q) (mul c u))))
3072 (add index 1))
3073 (power (div (power (add (mul d q)
3074 (mul f u)
3075 (mul 2
3076 (add (mul b q)
3077 (mul c u))
3078 var2))
3080 (neg (add (mul b q) (mul c u))))
3081 (mul (div -1 2) (add index 1)))
3082 (take '(%binomial) n index)
3083 (take '(%gamma_incomplete)
3084 (div (add index 1) 2)
3085 (div (power (add (mul d q)
3086 (mul f u)
3087 (mul 2
3088 (add (mul b q)
3089 (mul c u))
3090 var2))
3092 (mul -4 (add (mul b q) (mul c u))))))
3093 index 0 n t))))
3095 ((and (m2-exp-type-10 (facsum-exponent expr var2) var2)
3096 (maxima-integerp (cdras 'n w))
3097 (eq ($sign (cdras 'n w)) '$pos)
3098 (or (not (eq ($sign (cdras 'b w)) '$zero))
3099 (not (eq ($sign (cdras 'c w)) '$zero))))
3100 (a b c d e f g h n)
3101 (when *debug-integrate*
3102 (format t "~&Type 10: z^n*a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z)+f*z+g)")
3103 (format t "~& : w = ~A~%" w))
3105 (mul const
3106 (power 2 (add (mul -2 n) -1))
3107 (power a e)
3108 (power h g)
3109 (power '$%e
3110 (div (power (add (mul b ($log a)) (mul c ($log h))) 2)
3111 (mul -4 (add (mul d ($log a)) (mul f ($log h))))))
3112 (power (add (mul d ($log a)) (mul f ($log h))) (mul -2 (add n 1)))
3113 (let ((index1 (gensumindex))
3114 (index2 (gensumindex))
3115 ($simpsum t))
3116 (dosum
3117 (dosum
3118 (mul (power -1 (sub index1 index2))
3119 (power 4 index1)
3120 (ftake '%binomial index1 index2)
3121 (ftake '%binomial n index1)
3122 (power (add (mul b ($log a)) (mul c ($log h)))
3123 (sub (mul 2 n) (add index1 index2)))
3124 (power (add (mul b ($log a))
3125 (mul c ($log h))
3126 (mul 2
3127 (power var2 (div 1 2))
3128 (add (mul d ($log a)) (mul f ($log h)))))
3129 (add index1 index2))
3130 (power (mul -1
3131 (div (power (add (mul b ($log a))
3132 (mul c ($log h))
3133 (mul 2
3134 (power var2 (div 1 2))
3135 (add (mul d ($log a))
3136 (mul f ($log h)))))
3138 (add (mul d ($log a)) (mul f ($log h)))))
3139 (mul (div -1 2) (add index1 index2 1)))
3140 (add (mul ($gamma_incomplete (mul (div 1 2)
3141 (add index1 index2 1))
3142 (mul (div -1 4)
3143 (div (power (add (mul b ($log a))
3144 (mul c ($log h))
3145 (mul 2
3146 (power var2 (div 1 2))
3147 (add (mul d ($log a)) (mul f ($log h)))))
3149 (add (mul d ($log a)) (mul f ($log h))))))
3150 (add (mul b ($log a)) (mul c ($log h)))
3151 (add (mul b ($log a))
3152 (mul c ($log h))
3153 (mul 2
3154 (power var2 (div 1 2))
3155 (add (mul d ($log a)) (mul f ($log h))))))
3156 (mul 2
3157 ($gamma_incomplete (mul (div 1 2)
3158 (add index1 index2 2))
3159 (mul (div -1 4)
3160 (div (power (add (mul b ($log a))
3161 (mul c ($log h))
3162 (mul 2
3163 (power var2 (div 1 2))
3164 (add (mul d ($log a))
3165 (mul f ($log h)))))
3167 (add (mul d ($log a))
3168 (mul f ($log h))))))
3169 (add (mul d ($log a)) (mul f ($log h)))
3170 (power (mul -1
3171 (div (power (add (mul b ($log a))
3172 (mul c ($log h))
3173 (mul 2
3174 (power var2 (div 1 2))
3175 (add (mul d ($log a))
3176 (mul f ($log h)))))
3178 (add (mul d ($log a))
3179 (mul f ($log h)))))
3180 (div 1 2)))))
3181 index2 0 index1 t)
3182 index1 0 n t))))
3184 ((and (m2-exp-type-10-1 (facsum-exponent expr var2) var2)
3185 (maxima-integerp (cdras 'n w))
3186 (eq ($sign (cdras 'n w)) '$pos)
3187 (or (not (eq ($sign (cdras 'b w)) '$zero))
3188 (not (eq ($sign (cdras 'c w)) '$zero))))
3189 (b c d e f g q u n)
3190 (let ((bq+cu (add (mul b q) (mul c u)))
3191 (dq+fu (add (mul d q) (mul f u))))
3192 (when *debug-integrate*
3193 (format t "~&Type 10-1: z^n*(%e^(b*sqrt(z)+d*z+e))^q*(%e^(c*sqrt(z)+f*z+g))^u")
3194 (format t "~& : w = ~A~%" w))
3196 (mul const
3197 (power 2 (mul -1 (add (mul 2 n) 1)))
3198 (power '$%e
3199 (add (div (mul -1 (power bq+cu 2)) (mul 4 dq+fu))
3200 (mul -1 d var2 q)
3201 (mul -1 b (power var2 (div 1 2)) q)
3202 (mul -1 f var2 u)
3203 (mul -1 c (power var2 (div 1 2)) u)))
3204 (power (power '$%e
3205 (add (mul b (power var2 (div 1 2)))
3206 (mul d var2)
3209 (power (power '$%e
3210 (add (mul c (power var2 (div 1 2)))
3211 (mul f var2)
3214 (power dq+fu (mul -2 (add n 1)))
3215 (let ((index1 (gensumindex))
3216 (index2 (gensumindex))
3217 ($simpsum t))
3218 (dosum
3219 (dosum
3220 (mul (power -1 (sub index1 index2))
3221 (power 4 index1)
3222 (power bq+cu
3223 (add (neg index1) (neg index2) (mul 2 n)))
3224 (power (add bq+cu
3225 (mul 2 (power var2 (div 1 2)) dq+fu))
3226 (add index1 index2))
3227 (power (div (power (add bq+cu
3228 (mul 2
3229 (power var2 (div 1 2))
3230 dq+fu))
3232 (mul -1 dq+fu))
3233 (mul (div -1 2)
3234 (add index1 index2 1)))
3235 (take '(%binomial) index1 index2)
3236 (take '(%binomial) n index1)
3237 (add (mul bq+cu
3238 (add bq+cu
3239 (mul 2
3240 (power var2 (div 1 2))
3241 dq+fu))
3242 (take '(%gamma_incomplete)
3243 (mul (div 1 2)
3244 (add index1 index2 1))
3245 (div (power (add (mul b q)
3246 (mul c u)
3247 (mul 2
3248 (power var2 (div 1 2))
3249 dq+fu))
3251 (mul -4
3252 dq+fu))))
3253 (mul 2
3254 (power (div (power (add bq+cu
3255 (mul 2
3256 (power var2 (div 1 2))
3257 dq+fu))
3259 (mul 1 dq+fu))
3260 (div 1 2))
3261 dq+fu
3262 (take '(%gamma_incomplete)
3263 (mul (div 1 2)
3264 (add index1 index2 2))
3265 (div (power (add bq+cu
3266 (mul 2
3267 (power var2 (div 1 2))
3268 dq+fu))
3270 (mul -4
3271 dq+fu))))))
3272 index2 0 index1 t)
3273 index1 0 n t)))))))
3275 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3277 ;;; Do a facsum for the exponent of power functions.
3278 ;;; This is necessary to integrate all general forms. The pattern matcher is
3279 ;;; not powerful enough to do the job.
3281 (defun facsum-exponent (expr var2)
3282 ;; Make sure that expr has the form ((mtimes) factor1 factor2 ...)
3283 (when (not (mtimesp expr)) (setq expr (list '(mtimes) expr)))
3284 (do ((result nil)
3285 (l (cdr expr) (cdr l)))
3286 ((null l) (cons (list 'mtimes) result))
3287 (cond
3288 ((mexptp (car l))
3289 ;; Found an power function. Factor the exponent with facsum.
3290 (let* ((fac (mfuncall '$facsum (caddr (car l)) var2))
3291 (num ($num fac))
3292 (den ($denom fac)))
3293 (setq result
3294 (cons (cons (list 'mexpt)
3295 (cons (cadr (car l))
3296 (if (equal 1 den)
3297 (list num)
3298 (list ($multthru (inv den) num)))))
3299 result))))
3301 ;; Nothing to do.
3302 (setq result (cons (car l) result))))))
3304 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;