1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancments. ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; (c) Copyright 1982 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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.
18 ;;;; Unfortunately, some important pages in the scan are all black.
20 ;;;; A version with the missing pages is available (2008-12-14) from
21 ;;;; http://www.softwarepreservation.org/projects/LISP/MIT
23 (declare-top (special $radexpand $%e_to_numlog ans arcpart coef
24 aa powerlist
*a
* *b
* k stack e w y expres arg var
25 *powerl
* *c
* *d
* exp varlist genvar $liflag $opsubst
))
27 (defvar *debug-integrate
* nil
28 "Enable debugging for the integrator routines.")
30 ;; When T do not call the risch integrator. This flag can be set by the risch
31 ;; integrator to avoid endless loops when calling the integrator from risch.
32 (defvar *in-risch-p
* nil
)
35 `(get ,frob
'operators
))
37 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
39 ;;; Predicate functions
41 (declaim (inline varp
))
46 "Returns 2*x if 2*x is an integer, else nil"
47 (integerp2 (mul2* 2 x
)))
50 "Returns x if x is an integer, else false"
52 (cond ((not (numberp x
)) nil
)
54 ((prog2 (setq u
(maxima-rationalize x
))
55 (equal (cdr u
) 1)) (car u
)))))
57 ;; This predicate is used with m2 pattern matcher.
58 ;; A rational expression in var.
60 (cond ((or (varp ex
) (freevar ex
))
62 ((member (caar ex
) '(mplus mtimes
) :test
#'eq
)
63 (do ((u (cdr ex
) (cdr u
)))
65 (if (not (rat8 (car u
)))
67 ((not (eq (caar ex
) 'mexpt
))
69 ((integerp (caddr ex
))
81 (t (every #'elem
(cdr a
)))))
84 (cond ((atom a
) (not (eq a var
)))
86 ((and (not (atom (car a
)))
87 (member 'array
(cdar a
) :test
#'eq
))
88 (cond ((freevar (cdr a
)) t
)
89 (t (merror "~&FREEVAR: variable of integration appeared in subscript."))))
90 (t (and (freevar (car a
)) (freevar (cdr a
))))))
92 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
94 ;; possibly a bug: For var = x and *d* =3, we have expand(?subst10(x^9 * (x+x^6))) --> x^5+x^4, but
95 ;; ?subst10(expand(x^9 * (x+x^6))) --> x^5+x^3. (Barton Willis)
99 ((and (eq (caar ex
) 'mexpt
) (eq (cadr ex
) var
))
100 (list '(mexpt) var
(integerp2 (quotient (caddr ex
) *d
*))))
101 (t (cons (remove 'simp
(car ex
))
102 (mapcar #'(lambda (c) (subst10 c
)) (cdr ex
))))))
104 (defun rationalizer (x)
105 (let ((ex (simplify ($factor x
))))
106 (if (not (alike1 ex x
)) ex
)))
108 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
110 ;;; Stage II of the Integrator
112 ;;; Check if the problem can be transformed or solved by special methods.
113 ;;; 11 Methods are implemented by Moses, some more have been added.
115 (defun intform (expres &aux w
)
116 (cond ((freevar expres
) nil
)
119 ;; Map the function intform over the arguments of a sum or a product
120 ((member (caar expres
) '(mplus mtimes
) :test
#'eq
)
121 (some #'intform
(cdr expres
)))
123 ((or (eq (caar expres
) '%log
)
124 (arcp (caar expres
)))
126 ;; Method 9: Rational function times a log or arctric function
128 `((mtimes) ((,(caar expres
)) (b rat8
))
129 ((coefftt) (c rat8prime
)))))
130 ;; Integrand is of the form R(x)*F(S(x)) where F is a log, or
131 ;; arctric function and R(x) and S(x) are rational functions.
132 (ratlog exp var
(cons (cons 'a expres
) arg
)))
136 ((setq y
(intform (cadr expres
))) (return y
))
138 ;; Method 10: Rational function times log(b*x+a)
139 ((and (eq (caar expres
) '%log
)
140 (setq z
(m2-b*x
+a
(cadr expres
)))
144 ((coefftt) (d elem
))))))
146 (let ((a (cdr (assoc 'a z
:test
#'eq
)))
147 (b (cdr (assoc 'b z
:test
#'eq
)))
148 (c (cdr (assoc 'c y
:test
#'eq
)))
149 (d (cdr (assoc 'd y
:test
#'eq
)))
150 (newvar (gensym "intform")))
151 ;; keep var from appearing in questions to user
152 (putprop newvar t
'internal
)
153 ;; Substitute y = log(b*x+a) and integrate again
159 (list (maxima-substitute
160 `((mquotient) ((mplus) ((mexpt) $%e
,newvar
)
165 `((mquotient) ((mexpt) $%e
,newvar
) ,b
)
166 (maxima-substitute newvar expres d
))
169 (t (return nil
)))))))
171 ;; We have a special function with an integral on the property list.
172 ;; After the integral property was defined for the trig functions,
173 ;; in rev 1.52, need to exclude trig functions here.
174 ((and (not (atom (car expres
)))
175 (not (optrig (caar expres
)))
176 (not (eq (caar expres
) 'mexpt
))
177 (get (caar expres
) 'integral
))
178 (when *debug-integrate
*
179 (format t
"~&INTFORM: found 'INTEGRAL on property list~%"))
182 (m2 exp
`((mtimes) ((,(caar expres
)) (b rat8
)) ((coefftt) (c rat8prime
)))))
183 ;; A rational function times the special function.
184 ;; Integrate with the method integration-by-parts.
185 (partial-integration (cons (cons 'a expres
) arg
) var
))
186 ;; The method of integration-by-parts can not be applied.
187 ;; Maxima tries to get a clue for the argument of the function which
188 ;; allows a substitution for the argument.
189 ((intform (cadr expres
)))
192 ;; Method 6: Elementary function of trigonometric functions
193 ((optrig (caar expres
))
194 (cond ((not (setq w
(m2-b*x
+a
(cadr expres
))))
195 (intform (cadr expres
)))
199 (monstertrig exp var
(cadr expres
))))))
201 ((and (eq (caar expres
) '%derivative
)
202 (eq (caar exp
) (caar expres
))
205 ;; Stop intform if we have not a power function.
206 ((not (eq (caar expres
) 'mexpt
)) nil
)
208 ;; Method 2: Substitution for an integral power
209 ((integerp (caddr expres
)) (intform (cadr expres
)))
211 ;; Method 1: Elementary function of exponentials
212 ((freevar (cadr expres
))
213 (cond ((setq w
(m2-b*x
+a
(caddr expres
)))
214 (superexpt exp var
(cadr expres
) w
))
215 ((intform (caddr expres
)))
216 ((and (eq '$%e
(cadr expres
))
217 (isinop (caddr expres
) '%log
))
218 ;; Found something like exp(r*log(x))
219 (let* (($%e_to_numlog t
)
220 ($radexpand nil
) ; do not simplify sqrt(x^2) -> abs(x)
221 (nexp (resimplify exp
)))
222 (cond ((alike1 exp nexp
) nil
)
223 (t (integrator (setq exp nexp
) var
)))))
226 ;; The base is not a rational function. Try to get a clue for the base.
227 ((not (rat8 (cadr expres
)))
228 (intform (cadr expres
)))
230 ;; Method 3: Substitution for a rational root
231 ((and (setq w
(m2-ratrootform (cadr expres
))) ; e*(a*x+b) / (c*x+d)
232 (denomfind (caddr expres
))) ; expon is ratnum
235 (ratroot exp var
(cadr expres
) w
))
238 ;; Method 4: Binomial - Chebyschev
239 ((not (integerp1 (caddr expres
))) ; 2*exponent not integer
240 (cond ((m2-chebyform exp
)
242 (t (intform (cadr expres
)))))
244 ;; Method 5: Arctrigonometric substitution
245 ((setq w
(m2-c*x^
2+b
*x
+a
(cadr expres
))) ; sqrt(c*x^2+b*x+a)
247 (format t
"expres = sqrt(c*x^2+b*x+a)~%")
248 ;; I think this is method 5, arctrigonometric substitutions.
249 ;; (Moses, pg 80.) The integrand is of the form
250 ;; R(x,sqrt(c*x^2+b*x+a)). This method first eliminates the b
251 ;; term of the quadratic, and then uses an arctrig substitution.
254 ;; Method 4: Binomial - Chebyschev
259 ;; Substitute the expanded factor into the integrand and try again.
260 ((not (m2 (setq w
($expand
(cadr expres
)))
263 (setq exp
(maxima-substitute w
(cadr expres
) exp
))
264 (intform (simplify (list '(mexpt) w
(caddr expres
))))))
267 ;; Substitute the factored factor into the integrand and try again.
268 ((setq w
(rationalizer (cadr expres
)))
269 ;; The forms below used to have $radexpand set to $all. But I
270 ;; don't think we really want to do that here because that makes
271 ;; sqrt(x^2) become x, which might be totally wrong. This is one
272 ;; reason why we returned -4/3 for the
273 ;; integrate(sqrt(x+1/x-2),x,0,1). We were replacing
274 ;; sqrt((x-1)^2) with x - 1, which is totally wrong since 0 <= x
276 (setq exp
(let (($radexpand $radexpand
))
277 (maxima-substitute w
(cadr expres
) exp
)))
278 (intform (let (($radexpand
'$all
))
279 (simplify (list '(mexpt) w
(caddr expres
))))))))
281 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
284 (cond ((arcfuncp ex
) (setq arcpart ex coef
1))
285 ((and (consp ex
) (eq (caar ex
) 'mtimes
))
287 (setq coef
(cond ((null (cdr coef
)) (car coef
))
288 (t (setq coef
(cons (car ex
) coef
))))))))
290 (defun arclist (list)
291 (cond ((null list
) nil
)
292 ((and (arcfuncp (car list
)) (null arcpart
))
293 (setq arcpart
(car list
)) (arclist (cdr list
)))
294 (t (setq coef
(cons (car list
) coef
))
295 (arclist (cdr list
)))))
300 (eq (caar ex
) '%log
) ; Experimentally treat logs also.
301 (and (eq (caar ex
) 'mexpt
)
302 (integerp2 (caddr ex
))
303 (> (integerp2 (caddr ex
)) 0)
304 (arcfuncp (cadr ex
))))))
306 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
308 ;;; Five pattern for the Integrator and other routines.
310 ;; This is matching the pattern e*(a*x+b)/(c*x+d), where
311 ;; a, b, c, d, and e are free of x, and x is the variable of integration.
312 (defun m2-ratrootform (expr)
315 ((coefftt) (e freevar
))
317 ((coeffpt) (a freevar
) (var varp
))
318 ((coeffpt) (b freevar
)))
321 ((coeffpt) (c freevar
) (var varp
))
322 ((coeffpt) (d freevar
)))
325 ;; This is for matching the pattern a*x^r1*(c1+c2*x^q)^r2.
326 (defun m2-chebyform (expr)
329 ((mexpt) (var varp
) (r1 numberp
))
333 ((coefftt) (c2 freevar
))
334 ((mexpt) (var varp
) (q free1
)))
335 ((coeffpp) (c1 freevar
)))
337 ((coefftt) (a freevar
)))))
339 ;; Pattern to match b*x + a
340 (defun m2-b*x
+a
(expr)
343 ((coeffpt) (b freevar
) (x varp
))
344 ((coeffpt) (a freevar
)))))
346 ;; This is the pattern c*x^2 + b * x + a.
347 (defun m2-c*x^
2+b
*x
+a
(expr)
350 ((coeffpt) (c freevar
) ((mexpt) (x varp
) 2))
351 ((coeffpt) (b freevar
) (x varp
))
352 ((coeffpt) (a freevar
)))))
354 ;; This is the pattern (a*x+b)*(c*x+d)
355 (defun m2-a*x
+b
/c
*x
+d
(expr)
359 ((coeffpt) (a freevar
) (var varp
))
360 ((coeffpt) (b freevar
)))
362 ((coeffpt) (c freevar
) (var varp
))
363 ((coeffpt) (d freevar
))))))
365 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
367 ;;; This is the main integration routine. It is called from sinint.
369 (defun integrator (exp var
)
370 (prog (y arg
*powerl
* const
*b
* w arcpart coef integrand result
)
371 (declare (special *integrator-level
*))
372 ;; Increment recursion counter
373 (incf *integrator-level
*)
375 ;; Trivial case. exp is not a function of var.
376 (if (freevar exp
) (return (mul2* exp var
)))
378 ;; Remove constant factors
379 (setq w
(partition exp var
1))
384 (format t
"w = ~A~%" w
)
385 (format t
"const = ~A~%" const
)
386 (format t
"exp = ~A~%" exp
))
388 (cond ;; First stage, Method I: Integrate a sum.
390 (return (mul2* const
(integrate1 (cdr exp
)))))
392 ;; Convert atan2(a,b) to atan(a/b) and try again.
393 ((setq w
(isinop exp
'$atan2
))
395 (maxima-substitute (take '(%atan
) (div (cadr w
) (caddr w
)))
399 (integrator exp var
))))
401 ;; First stage, Method II: Integrate sums.
402 ((and (not (atom exp
))
403 (eq (caar exp
) '%sum
))
404 (return (mul2* const
(intsum exp var
))))
406 ;; First stage, Method III: Try derivative-divides method.
407 ;; This is the workhorse that solves many integrals.
408 ((setq y
(diffdiv exp var
))
409 (return (mul2* const y
))))
411 ;; At this point, we have EXP as a product of terms. Make Y a
412 ;; list of the terms of the product.
413 (setq y
(cond ((mtimesp exp
)
419 ;; We're looking at each term of the product and check if we can
420 ;; apply one of the special methods.
424 (format t
"car y =~%")
425 (maxima-display (car y
)))
426 (cond ((rat8 (car y
))
428 (format t
"In loop, go skip~%")
430 ((and (setq w
(intform (car y
)))
431 ;; Do not return a noun form as result at this point, because
432 ;; we would like to check for further special integrals.
433 ;; We store the result for later use.
435 (not (isinop w
'%integrate
)))
437 (format t
"In loop, case intform~%")
438 (return (mul2* const w
)))
441 (format t
"In loop, go special~%")
442 ;; Store a possible partial result
448 ;; Method 8: Rational functions
449 (return (mul2* const
(cond ((setq y
(powerlist exp var
)) y
)
450 (t (ratint exp var
)))))))
454 ;; Third stage: Try more general methods
456 ;; SEPARC SETQS ARCPART AND COEF SUCH THAT
457 ;; COEF*ARCEXP=EXP WHERE ARCEXP IS OF THE FORM
458 ;; ARCFUNC^N AND COEF IS ITS ALGEBRAIC COEFFICIENT
463 (format t
"arcpart = ~A~%" arcpart
)
464 (format t
"coef =~%")
465 (maxima-display coef
))
466 (cond ((and (not (null arcpart
))
467 (do ((stacklist stack
(cdr stacklist
)))
469 (cond ((alike1 (car stacklist
) coef
)
471 (not (isinop (setq w
(let ((stack (cons coef stack
)))
472 (integrator coef var
)))
474 (setq integrand
(mul2 w
(sdiff arcpart var
)))
475 (do ((stacklist stack
(cdr stacklist
)))
477 (cond ((alike1 (car stacklist
) integrand
)
480 (setq y
(let ((stack (cons integrand stack
))
482 (integrator integ var
)))
484 (return (add* (list '(mtimes) const w arcpart
)
485 (list '(mtimes) -
1 const y
))))
489 (cond ((setq y
(scep exp var
))
493 (format t
"cddr y =~%")
494 (maxima-display (cddr y
)))
495 (integrator ($trigreduce exp
) var
))
496 (t (sce-int (car y
) (cadr y
) var
))))
497 ;; I don't understand why we do this. This
498 ;; causes the stack overflow in Bug
499 ;; 1487703, because we keep expanding exp
500 ;; into a form that matches the original
501 ;; and therefore we loop forever. To
502 ;; break this we keep track how how many
503 ;; times we've tried this and give up
504 ;; after 4 (arbitrarily selected) times.
505 ((and (< *integrator-level
* 4)
506 (not (alike1 exp
(setq y
($expand exp
)))))
509 (format t
"exp = ~A~%" exp
)
511 (format t
"y = ~A~%" y
)
516 (setq y
(powerlist exp var
)))
518 ((and (not *in-risch-p
*) ; Not called from rischint
519 (setq y
(rischint exp var
))
520 ;; rischint has not found an integral but
521 ;; returns a noun form. Do not return that
522 ;; noun form as result at this point, but
523 ;; store it for later use.
525 (not (isinop y
'%integrate
)))
527 ((setq y
(integrate-exp-special exp var
))
528 ;; Maxima found an integral for a power function
531 ;; Integrate-exp-special has not found an integral
532 ;; We look for a previous result obtained by
533 ;; intform or rischint.
536 (list '(%integrate
) exp var
))))))))))
539 (member x
'(%sin %cos %sec %tan %csc %cot
) :test
#'eq
))
541 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
544 ;;; Implementation of Method 1: Integrate a sum
546 ;;after finding a non-integrable summand usually better to pass rest to risch
547 (defun integrate1 (exp)
548 (do ((terms exp
(cdr terms
)) (ans))
549 ((null terms
) (addn ans nil
))
550 (let ($liflag
) ; don't gen li's for
551 (push (integrator (car terms
) var
) ans
)) ; parts of integrand
552 (when (and (not *in-risch-p
*) ; Not called from rischint
553 (not (free (car ans
) '%integrate
))
555 (return (addn (cons (rischint (cons '(mplus) terms
) var
) (cdr ans
))
558 (defun scep (expr var
&aux trigl exp
) ; Product of SIN, COS, EXP
559 (and (mtimesp expr
) ; of linear args.
560 (loop for fac in
(cdr expr
) do
561 (cond ((atom fac
) (return nil
))
563 (if (linearp (cadr fac
) var
) (push fac trigl
)
567 (linearp (caddr fac
) var
))
568 ;; should be only one exponential factor
571 finally
(return (cons exp trigl
)))))
573 ;; Integrates exponential * sin or cos, all with linear args.
575 (defun sce-int (exp s-c var
) ; EXP is non-trivial
576 (let* ((e-coef (car (islinear (caddr exp
) var
)))
577 (sc-coef (car (islinear (cadr s-c
) var
)))
579 (abs-val (add (power e-coef
2) (power sc-coef
2))))
581 ;; The numerator is zero. Exponentialize the integrand and try again.
582 (integrator ($exponentialize
(mul exp s-c
)) var
)
583 (mul (div exp abs-val
)
584 (add (mul e-coef s-c
)
585 (if (eq (caar s-c
) '%sin
)
586 (mul* (neg sc-coef
) `((%cos
) ,sc-arg
))
587 (mul* sc-coef
`((%sin
) ,sc-arg
))))))))
589 (defun checkderiv (expr)
590 (checkderiv1 (cadr expr
) (cddr expr
) () ))
592 ;; CHECKDERIV1 gets called on the expression being differentiated,
593 ;; an alternating list of variables being differentiated with
594 ;; respect to and powers thereof, and a reversed list of the latter
595 ;; that have already been examined. It returns either the antiderivative
596 ;; or (), saying this derivative isn't wrt the variable of integration.
598 (defun checkderiv1 (expr wrt old-wrt
)
599 (cond ((varp (car wrt
))
600 (if (equal (cadr wrt
) 1) ;Power = 1?
601 (if (null (cddr wrt
)) ;single or partial
604 `((%derivative
), expr
;partial in old-wrt
605 ,.
(nreverse old-wrt
)))
606 `((%derivative
) ,expr
;Partial, return rest
609 `((%derivative
) ,expr
;Higher order, reduce order
611 ,(car wrt
) ,(add* (cadr wrt
) -
1)
613 ((null (cddr wrt
)) () ) ;Say it doesn't apply here
614 (t (checkderiv1 expr
(cddr wrt
) ;Else we check later terms
615 (list* (cadr wrt
) (car wrt
) old-wrt
)))))
617 (defun integrallookups (exp)
618 (let (form dummy-args real-args
)
620 ((eq (caar exp
) 'mqapply
)
621 ;; Transform to functional form and try again.
623 ;; ((MQAPPLY SIMP) (($PSI SIMP ARRAY) 1) $X)
625 (integrallookups `((,(caaadr exp
)) ,@(cdadr exp
) ,@(cddr exp
))))
627 ;; Lookup algorithm for integral of a special function.
628 ;; The integral form is put on the property list, and can be a
629 ;; lisp function of the args. If the form is nil, or evaluates
630 ;; to nil, then return noun form unevaluated.
631 ((and (not (atom (car exp
)))
632 (setq form
(get (caar exp
) 'integral
))
633 (setq dummy-args
(car form
))
634 (setq real-args
(cdr exp
))
635 ;; search through the args of exp and find the arg containing var
636 ;; look up the integral wrt this arg from form
638 (do ((x real-args
(cdr x
))
639 (y (cdr form
) (cdr y
)))
640 ((or (null x
) (null y
)) nil
)
641 (if (not (freevar (car x
))) (return (car y
)))))
642 ;; If form is a function then evaluate it with actual args
643 (or (not (functionp form
))
644 (setq form
(apply form real-args
))))
645 (when *debug-integrate
*
646 (format t
"~&INTEGRALLOOKUPS: Found integral ~A.~%" (caar exp
)))
647 (substitutel real-args dummy-args form
))
649 ((eq (caar exp
) 'mplus
)
650 (muln (list '((rat simp
) 1 2) exp exp
) nil
))
654 ;; Define the antiderivatives of some elementary special functions.
655 ;; This may not be the best place for this definition, but it is close
656 ;; to the original code.
657 ;; Antiderivatives that depend on the logabs flag are defined further below.
658 (defprop %log
((x) ((mplus) ((mtimes) x
((%log
) x
)) ((mtimes) -
1 x
))) integral
)
659 (defprop %sin
((x) ((mtimes) -
1 ((%cos
) x
))) integral
)
660 (defprop %cos
((x) ((%sin
) x
)) integral
)
661 (defprop %sinh
((x) ((%cosh
) x
)) integral
)
662 (defprop %cosh
((x) ((%sinh
) x
)) integral
)
663 ;; No need to take logabs into account for tanh(x), because cosh(x) is positive.
664 (defprop %tanh
((x) ((%log
) ((%cosh
) x
))) integral
)
665 (defprop %sech
((x) ((%atan
) ((%sinh
) x
))) integral
)
666 (defprop %asin
((x) ((mplus) ((mexpt) ((mplus) 1 ((mtimes) -
1 ((mexpt) x
2))) ((rat) 1 2)) ((mtimes) x
((%asin
) x
)))) integral
)
667 (defprop %acos
((x) ((mplus) ((mtimes) -
1 ((mexpt) ((mplus) 1 ((mtimes) -
1 ((mexpt) x
2))) ((rat) 1 2))) ((mtimes) x
((%acos
) x
)))) integral
)
668 (defprop %atan
((x) ((mplus) ((mtimes) x
((%atan
) x
)) ((mtimes) ((rat) -
1 2) ((%log
) ((mplus) 1 ((mexpt) x
2)))))) integral
)
669 (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
)
670 (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
)
671 (defprop %acot
((x) ((mplus) ((mtimes) x
((%acot
) x
)) ((mtimes) ((rat) 1 2) ((%log
) ((mplus) 1 ((mexpt) x
2)))))) integral
)
672 (defprop %asinh
((x) ((mplus) ((mtimes) -
1 ((mexpt) ((mplus) 1 ((mexpt) x
2)) ((rat) 1 2))) ((mtimes) x
((%asinh
) x
)))) integral
)
673 (defprop %acosh
((x) ((mplus) ((mtimes) -
1 ((mexpt) ((mplus) -
1 ((mexpt) x
2)) ((rat) 1 2))) ((mtimes) x
((%acosh
) x
)))) integral
)
674 (defprop %atanh
((x) ((mplus) ((mtimes) x
((%atanh
) x
)) ((mtimes) ((rat) 1 2) ((%log
) ((mplus) 1 ((mtimes) -
1 ((mexpt) x
2))))))) integral
)
675 (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
)
676 (defprop %asech
((x) ((mplus) ((mtimes) -
1 ((%atan
) ((mexpt) ((mplus) -
1 ((mexpt) x -
2)) ((rat) 1 2)))) ((mtimes) x
((%asech
) x
)))) integral
)
677 (defprop %acoth
((x) ((mplus) ((mtimes) x
((%acoth
) x
)) ((mtimes) ((rat) 1 2) ((%log
) ((mplus) 1 ((mtimes) -
1 ((mexpt) x
2))))))) integral
)
679 ;; Define a little helper function to be used in antiderivatives.
680 ;; Depending on the logabs flag, it either returns log(x) or log(abs(x)).
681 (defun log-or-logabs (x)
682 (take '(%log
) (if $logabs
(take '(mabs) x
) x
)))
684 ;; Define the antiderivative of tan(x), taking logabs into account.
685 (defun integrate-tan (x)
686 (log-or-logabs (take '(%sec
) x
)))
687 (putprop '%tan
`((x) ,#'integrate-tan
) 'integral
)
689 ;; ... the same for csc(x) ...
690 (defun integrate-csc (x)
691 (mul -
1 (log-or-logabs (add (take '(%csc
) x
) (take '(%cot
) x
)))))
692 (putprop '%csc
`((x) ,#'integrate-csc
) 'integral
)
694 ;; ... the same for sec(x) ...
695 (defun integrate-sec (x)
696 (log-or-logabs (add (take '(%sec
) x
) (take '(%tan
) x
))))
697 (putprop '%sec
`((x) ,#'integrate-sec
) 'integral
)
699 ;; ... the same for cot(x) ...
700 (defun integrate-cot (x)
701 (log-or-logabs (take '(%sin
) x
)))
702 (putprop '%cot
`((x) ,#'integrate-cot
) 'integral
)
704 ;; ... the same for coth(x) ...
705 (defun integrate-coth (x)
706 (log-or-logabs (take '(%sinh
) x
)))
707 (putprop '%coth
`((x) ,#'integrate-coth
) 'integral
)
709 ;; ... the same for csch(x) ...
710 (defun integrate-csch (x)
711 (log-or-logabs (take '(%tanh
) (mul '((rat simp
) 1 2) x
))))
712 (putprop '%csch
`((x) ,#'integrate-csch
) 'integral
)
714 ;; integrate(x^n,x) = if n # -1 then x^(n+1)/(n+1) else log-or-logabs(x).
715 (defun integrate-mexpt-1 (x n
)
716 (let ((n-is-minus-one ($askequal n -
1)))
717 (cond ((eq '$yes n-is-minus-one
)
721 (div (take '(mexpt) x n
) n
)))))
723 ;; integrate(a^x,x) = a^x/log(a).
724 (defun integrate-mexpt-2 (a x
)
725 (div (take '(mexpt) a x
) (take '(%log
) a
)))
727 (putprop 'mexpt
`((x n
) ,#'integrate-mexpt-1
,#'integrate-mexpt-2
) 'integral
)
730 (cond ((freevar ex
) t
)
732 ((eq (caar ex
) 'mexpt
)
734 (if (integerp2 (caddr ex
))
735 (setq powerlist
(cons (caddr ex
) powerlist
)))
736 (and (rat10 (cadr ex
)) (rat10 (caddr ex
)))))
737 ((member (caar ex
) '(mplus mtimes
) :test
#'eq
)
738 (do ((u (cdr ex
) (cdr u
))) ((null u
) t
)
739 (if (not (rat10 (car u
))) (return nil
))))))
741 (defun integrate5 (ex var
)
744 (integrator ex var
)))
747 (cond ((ratnump x
) (caddr x
))
748 ((not (numberp x
)) nil
)
750 (t (cdr (maxima-rationalize x
)))))
752 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
755 ;;; Implementation of Method 1: Elementary function of exponentials
757 ;;; The following examples are integrated with this method:
759 ;;; integrate(exp(x)/(2+3*exp(2*x)),x)
760 ;;; integrate(exp(x+1)/(1+exp(x)),x)
761 ;;; integrate(10^x*exp(x),x)
763 (let ((base nil
) ; The common base.
764 (pow nil
) ; The common power of the form b*x+a. The values are
765 ; stored in a list which is returned from m2.
766 (exptflag nil
)) ; When T, the substitution is not possible.
768 (defun superexpt (exp var bas1 pow1
)
769 (prog (y (new-var (gensym "NEW-VAR-")))
773 ;; Transform the integrand. At this point resimplify, because it is not
774 ;; guaranteed, that a correct simplified expression is returned.
775 ;; Use a new variable to prevent facts on the old variable to be wrongly used.
776 (setq y
(resimplify (maxima-substitute new-var var
(elemxpt exp
))))
777 (when exptflag
(return nil
))
778 ;; Integrate the transformed integrand and substitute back.
781 (substint (list '(mexpt) base
782 (list '(mplus) (cdras 'a pow
)
783 (list '(mtimes) (cdras 'b pow
) var
)))
788 (take '(%log
) base
))) new-var
))))))
790 ;; Transform expressions like g^(b*x+a) to the common base base and
791 ;; do the substitution y = base^(b*x+a) in the expr.
792 (defun elemxpt (expr &aux w
)
793 (cond ((freevar expr
) expr
)
794 ;; var is the base of a subexpression. The transformation fails.
795 ((atom expr
) (setq exptflag t
))
796 ((not (eq (caar expr
) 'mexpt
))
798 (mapcar #'(lambda (c) (elemxpt c
)) (cdr expr
))))
799 ((not (freevar (cadr expr
)))
801 (elemxpt (cadr expr
))
802 (elemxpt (caddr expr
))))
803 ;; Transform the expression to the common base.
804 ((not (eq (cadr expr
) base
))
805 (elemxpt (list '(mexpt)
807 (mul (power (take '(%log
) base
) -
1)
808 (take '(%log
) (cadr expr
))
810 ;; The exponent must be linear in the variable of integration.
811 ((not (setq w
(m2-b*x
+a
(caddr expr
))))
812 (list (car expr
) base
(elemxpt (caddr expr
))))
813 ;; Do the substitution y = g^(b*x+a).
815 (setq w
(cons (cons 'bb
(cdras 'b pow
)) w
))
816 (setq w
(cons (cons 'aa
(cdras 'a pow
)) w
))
817 (setq w
(cons (cons 'base base
) w
))
818 (subliss w
'((mtimes)
823 ((mtimes) -
1 aa b
) bb
))
826 ((mquotient) b bb
)))))))
829 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
832 ;;; Implementation of Method 3:
833 ;;; Substitution for a rational root of a linear fraction of x
835 ;;; This method is applicable when the integrand is of the form:
838 ;;; [ a x + b n1/m1 a x + b n1/m2
839 ;;; I R(x, (-------) , (-------) , ...) dx
840 ;;; ] c x + d c x + d
845 ;;; (1) t = ((a*x+b)/(c*x+d))^(1/k), or
847 ;;; (2) x = (b-d*t^k)/(c*t^k-a)
849 ;;; where k is the least common multiplier of m1, m2, ... and
851 ;;; (3) dx = k*(a*d-b*c)*t^(k-1)/(a-c*t^k)^2 * dt
853 ;;; First, the algorithm calls the routine RAT3 to collect the roots of the
854 ;;; form ((a*x+b)/(c*x+d))^(n/m) in the list *ROOTLIST*.
855 ;;; search for the least common multiplier of m1, m2, ... then the
856 ;;; substitutions (2) and (3) are done and the new problem is integrated.
857 ;;; As always, W is an alist which associates to the coefficients
858 ;;; a, b... (and to VAR) their values.
860 (defvar *ratroot
* nil
) ; Expression of the form (a*x+b)/(c*x+d)
861 (defvar *rootlist
* nil
) ; List of powers of the expression *ratroot*.
863 (defun ratroot (exp var
*ratroot
* w
)
864 (prog (*rootlist
* k y w1
)
865 ;; Check if the integrand has a chebyform, if so return the result.
866 (when (setq y
(chebyf exp var
)) (return y
))
867 ;; Check if the integrand has a suitably form and collect the roots
868 ;; in the global special variable *ROOTLIST*.
869 (unless (rat3 exp t
) (return nil
))
870 ;; Get the least common multiplier of m1, m2, ...
871 (setq k
(apply #'lcm
*rootlist
*))
872 (setq w1
(cons (cons 'k k
) w
))
873 ;; Substitute for the roots.
878 ((mplus) ((mtimes) b e
)
879 ((mtimes) -
1 d
((mexpt) var k
)))
880 ((mplus) ((mtimes) c
((mexpt) var k
))
883 ;; Integrate the new problem.
892 ((mexpt) var
((mplus) -
1 k
)))
895 ((mexpt) var
((mplus) -
1 k
))))))
897 ((mtimes) c
((mexpt) var k
))
901 ;; Substitute back and return the result.
902 (return (substint (power *ratroot
* (power k -
1)) var y
))))
905 (cond ((freevar ex
) t
)
907 ((member (caar ex
) '(mtimes mplus
) :test
#'eq
)
908 (do ((u (cdr ex
) (cdr u
)))
910 (if (not (rat3 (car u
) ind
))
912 ((not (eq (caar ex
) 'mexpt
))
913 (rat3 (car (margs ex
)) t
))
916 ((integerp (caddr ex
))
917 (rat3 (cadr ex
) ind
))
918 ((and (m2 (cadr ex
) *ratroot
*)
919 (denomfind (caddr ex
)))
920 (setq *rootlist
* (cons (denomfind (caddr ex
)) *rootlist
*)))
921 (t (rat3 (cadr ex
) nil
))))
923 (let ((rootform nil
) ; Expression of the form x = (b*e-d*t^k)/(c*t^k-e*a).
924 (rootvar nil
)) ; The variable we substitute for the root.
927 (cond ((freevar ex
) ex
)
929 ((not (eq (caar ex
) 'mexpt
))
930 (mapcar #'(lambda (u) (subst4 u
)) ex
))
931 ((m2 (cadr ex
) *ratroot
*)
932 (list (car ex
) rootvar
(integerp2 (timesk k
(caddr ex
)))))
933 (t (list (car ex
) (subst4 (cadr ex
)) (subst4 (caddr ex
))))))
935 (defun subst41 (exp a b
)
938 ;; At this point resimplify, because it is not guaranteed, that a correct
939 ;; simplified expression is returned.
940 (resimplify (subst4 exp
)))
943 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
946 ;;; Implementation of Method 4: Binomial Chebyschev
948 ;; exp = a*t^r1*(c1+c2*t^q)^r2, where var = t.
950 ;; G&S 2.202 has says this integral can be expressed by elementary
953 ;; 1. q is an integer
954 ;; 2. (r1+1)/q is an integer
955 ;; 3. (r1+1)/q+r2 is an integer.
957 ;; I (rtoy) think that for this code to work, r1, r2, and q must be numbers.
958 (defun chebyf (exp var
)
959 (prog (r1 r2 d1 d2 n1 n2 w q
)
960 ;; Return NIL if the expression doesn't match.
961 (when (not (setq w
(m2-chebyform exp
)))
964 (format t
"w = ~A~%" w
)
965 (when (zerop1 (cdr (assoc 'c1 w
:test
#'eq
)))
966 ;; rtoy: Is it really possible to be in this routine with c1 =
970 ;; This factor is locally constant as long as t and
971 ;; c2*t^q avoid log's branch cut.
972 (subliss w
'((mtimes) a
((mexpt) var
((mtimes) -
1 q r2
))
973 ((mexpt) ((mtimes) c2
((mexpt) var q
)) r2
)))
975 (subliss w
'((mexpt) var
((mplus) r1
((mtimes) q r2
)))) var
))))
976 (setq q
(cdr (assoc 'q w
:test
#'eq
)))
977 ;; Reset parameters. a = a/q, r1 = (1 - q + r1)/q
979 (list* (cons 'a
(div* (cdr (assoc 'a w
:test
#'eq
)) q
))
982 (div* (addn (list 1 (neg (simplify q
)) (cdr (assoc 'r1 w
:test
#'eq
))) nil
) q
))
985 (format t
"new w = ~A~%" w
)
986 (setq r1
(cdr (assoc 'r1 w
:test
#'eq
))
987 r2
(cdr (assoc 'r2 w
:test
#'eq
)))
990 (format t
"new r1 = ~A~%" r1
)
991 (format t
"r2 = ~A~%" r2
))
992 ;; Write r1 = d1/n1, r2 = d2/n2, if possible. Update w with
993 ;; these values, if so. If we can't, give up. I (rtoy) think
994 ;; this only happens if r1 or r2 can't be expressed as rational
995 ;; numbers. Hence, r1 and r2 have to be numbers, not variables.
997 ((not (and (setq d1
(denomfind r1
))
998 (setq d2
(denomfind r2
))
999 (setq n1
(integerp2 (timesk r1 d1
)))
1000 (setq n2
(integerp2 (timesk r2 d2
)))
1001 (setq w
(list* (cons 'd1 d1
) (cons 'd2 d2
)
1002 (cons 'n1 n1
) (cons 'n2 n2
)
1006 (format t
"cheby can't find one of d1,d2,n1,n2:~%")
1007 (format t
" d1 = ~A~%" d1
)
1008 (format t
" d2 = ~A~%" d2
)
1009 (format t
" n1 = ~A~%" n1
)
1010 (format t
" n2 = ~A~%" n2
))
1012 ((and (integerp2 r1
) (> r1
0))
1013 #+nil
(format t
"integer r1 > 0~%")
1014 ;; (r1+q-1)/q is positive integer.
1016 ;; I (rtoy) think we are using the substitution z=(c1+c2*t^q).
1017 ;; Maxima thinks the resulting integral should then be
1019 ;; a/q*c2^(-r1/q-1/q)*integrate(z^r2*(z-c1)^(r1/q+1/q-1),z)
1023 (subliss w
'((mplus) c1
((mtimes) c2
((mexpt) var q
))))
1026 (expands (list (subliss w
1027 ;; a*t^r2*c2^(-r1-1)
1038 (expandexpt (subliss w
1045 #+nil
(format t
"integer r2~%")
1046 ;; I (rtoy) think this is using the substitution z = t^(q/d1).
1048 ;; The integral (as maxima will tell us) becomes
1050 ;; a*d1/q*integrate(z^(n1/q+d1/q-1)*(c1+c2*z^d1)^r2,z)
1052 ;; But be careful because the variable A in the code is
1055 (substint (subliss w
'((mexpt) var
((mquotient) q d1
)))
1057 (ratint (simplify (subliss w
1073 ((and (integerp2 r1
) (< r1
0))
1074 #+nil
(format t
"integer r1 < 0~%")
1075 ;; I (rtoy) think this is using the substitution
1077 ;; z = (c1+c2*t^q)^(1/d2)
1079 ;; With this substitution, maxima says the resulting integral
1082 ;; a/q*c2^(-r1/q-1/q)*d2*
1083 ;; integrate(z^(n2+d2-1)*(z^d2-c1)^(r1/q+1/q-1),z)
1085 (substint (subliss w
1086 ;; (c1+c2*t^q)^(1/d2)
1090 ((mtimes) c2
((mexpt) var q
)))
1091 ((mquotient) 1 d2
)))
1093 (ratint (simplify (subliss w
1094 ;; This is essentially
1095 ;; the integrand above,
1096 ;; except A and R1 here
1097 ;; are not the same as
1118 ((integerp2 (add* r1 r2
))
1119 #+nil
(format t
"integer r1+r2~%")
1120 ;; If we're here, (r1-q+1)/q+r2 is an integer.
1122 ;; I (rtoy) think this is using the substitution
1124 ;; z = ((c1+c2*t^q)/t^q)^(1/d1)
1126 ;; With this substitution, maxima says the resulting integral
1129 ;; a*d2/q*c1^(r2+r1/q+1/q)*
1130 ;; integrate(z^(d2*r2+d2-1)*(z^d2-c2)^(-r2-r1/q-1/q-1),z)
1132 (substint (let (($radexpand
'$all
))
1133 ;; Setting $radexpand to $all here gets rid of
1134 ;; ABS in the subtitution. I think that's ok in
1135 ;; this case. See Bug 1654183.
1141 ((mtimes) c2
((mexpt) var q
)))
1143 ((mquotient) 1 d1
))))
1145 (ratint (simplify (subliss w
1168 (t (return (list '(%integrate
) exp var
))))))
1170 (defun greaterratp (x1 x2
)
1171 (cond ((and (numberp x1
) (numberp x2
))
1174 (greaterratp (quotient (float (cadr x1
))
1179 (quotient (float (cadr x2
))
1183 (member (car x
) '(%sin %cos
) :test
#'eq
))
1185 (defun supertrig (exp)
1186 (declare (special *notsame
* *trigarg
*))
1187 (cond ((freevar exp
) t
)
1189 ((member (caar exp
) '(mplus mtimes
) :test
#'eq
)
1190 (and (supertrig (cadr exp
))
1191 (or (null (cddr exp
))
1192 (supertrig (cons (car exp
)
1194 ((eq (caar exp
) 'mexpt
)
1195 (and (supertrig (cadr exp
))
1196 (supertrig (caddr exp
))))
1197 ((eq (caar exp
) '%log
)
1198 (supertrig (cadr exp
)))
1200 '(%sin %cos %tan %sec %cot %csc
) :test
#'eq
)
1201 (cond ((m2 (cadr exp
) *trigarg
*) t
)
1202 ((m2-b*x
+a
(cadr exp
))
1203 (and (setq *notsame
* t
) nil
))
1204 (t (supertrig (cadr exp
)))))
1205 (t (supertrig (cadr exp
)))))
1207 (defun subst2s (ex pat
)
1208 (cond ((null ex
) nil
)
1211 (t (cons (subst2s (car ex
) pat
)
1212 (subst2s (cdr ex
) pat
)))))
1214 ;; Match (c*x+b), where c and b are free of x
1215 (defun simple-trig-arg (exp)
1216 (m2 exp
'((mplus) ((mtimes)
1217 ((coefftt) (c freevar
))
1218 ((coefftt) (v varp
)))
1219 ((coeffpp) (b freevar
)))))
1221 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1224 ;;; Implementation of Method 6: Elementary function of trigonometric functions
1226 (defun monstertrig (exp var
*trigarg
*)
1227 (declare (special *trigarg
*))
1228 (when (and (not (atom *trigarg
*))
1229 ;; Do not exute the following code when called from rischint.
1231 (let ((arg (simple-trig-arg *trigarg
*)))
1233 ;; We have trig(c*x+b). Use the substitution y=c*x+b to
1234 ;; try to compute the integral. Why? Because x*sin(n*x)
1235 ;; takes longer and longer as n gets larger and larger.
1236 ;; This is caused by the Risch integrator. This is a
1237 ;; work-around for this issue.
1238 (let* ((c (cdras 'c arg
))
1240 (new-var (gensym "NEW-VAR-"))
1241 (new-exp (maxima-substitute (div (sub new-var b
) c
)
1243 (if (every-trigarg-alike new-exp new-var
)
1244 ;; avoid endless recursion when more than one
1245 ;; trigarg exists or c is a float
1246 (return-from monstertrig
1250 (div (integrator new-exp new-var
) c
))))))
1252 (return-from monstertrig
(rischint exp var
))))))
1253 (prog (*notsame
* w a b y d
)
1254 (declare (special *notsame
*))
1256 ((supertrig exp
) (go a
))
1257 ((null *notsame
*) (return nil
))
1258 ;; Check for an expression like a*trig1(m*x)*trig2(n*x),
1259 ;; where trig1 and trig2 are sin or cos.
1260 ((not (setq y
(m2 exp
1262 ((coefftt) (a freevar
))
1266 ((coefftt) (m freevar
))))
1270 ((coefftt) (n freevar
))))))))
1272 ; This check has been done with the pattern match.
1273 ; ((not (and (member (car (setq b (cdr (assoc 'b y :test #'eq)))) '(%sin %cos) :test #'eq)
1274 ; (member (car (setq d (cdr (assoc 'd y :test #'eq)))) '(%sin %cos) :test #'eq)))
1277 ;; The tests after this depend on values of b and d being
1278 ;; set. Set them here unconditionally, before doing the
1280 (setq b
(cdras 'b y
))
1281 (setq d
(cdras 'd y
))
1282 (and (eq (car b
) '%sin
)
1283 (eq (car d
) '%sin
)))
1284 ;; We have a*sin(m*x)*sin(n*x).
1285 ;; The integral is: a*(sin((m-n)*x)/(2*(m-n))-sin((m+n)*x)/(2*(m+n))
1290 ((%sin
) ((mtimes) ((mplus) m
((mtimes) -
1 n
)) x
))
1291 ((mtimes) 2 ((mplus) m
((mtimes) -
1 n
))))
1294 ((%sin
) ((mtimes) ((mplus) m n
) x
))
1295 ((mtimes) 2 ((mplus) m n
)))))))))
1296 ((and (eq (car b
) '%cos
) (eq (car d
) '%cos
))
1297 ;; We have a*cos(m*x)*cos(n*x).
1298 ;; The integral is: a*(sin((m-n)*x)/(2*(m-n))+sin((m+n)*x)/(2*(m+n))
1303 ((%sin
) ((mtimes) ((mplus) m
((mtimes) -
1 n
)) x
))
1305 ((mplus) m
((mtimes) -
1 n
))))
1307 ((%sin
) ((mtimes) ((mplus) m n
) x
))
1308 ((mtimes) 2 ((mplus) m n
))))))))
1309 ((or (and (eq (car b
) '%cos
)
1310 ;; The following (destructively!) swaps the values of
1311 ;; m and n if first trig term is sin. I (rtoy) don't
1312 ;; understand why this is needed. The formula
1313 ;; doesn't depend on that.
1314 (setq w
(cdras 'm y
))
1315 (rplacd (assoc 'm y
) (cdras 'n y
))
1316 (rplacd (assoc 'n y
) w
))
1318 ;; We have a*cos(n*x)*sin(m*x).
1319 ;; The integral is: -a*(cos((m-n)*x)/(2*(m-n))+cos((m+n)*x)/(2*(m+n))
1324 ((%cos
) ((mtimes) ((mplus) m
((mtimes) -
1 n
)) x
))
1325 ((mtimes) 2 ((mplus) m
((mtimes) -
1 n
))))
1327 ((%cos
) ((mtimes) ((mplus) m n
) x
))
1328 ((mtimes) 2 ((mplus) m n
)))))))))
1329 b
;; At this point we have trig functions with different arguments,
1330 ;; but not a product of sin and cos.
1331 (cond ((not (setq y
(prog2
1332 (setq *trigarg
* var
)
1335 ((coefftt) (a freevar
))
1339 ((coefftt) (n integerp2
))))
1340 ((coefftt) (c supertrig
)))))))
1342 ;; We have a product of trig functions: trig1(n*x)*trig2(y).
1343 ;; trig1 is sin or cos, where n is a numerical integer. trig2 is not a sin
1344 ;; or cos. The cos or sin function is expanded.
1349 (cdras 'a y
) ; constant factor
1350 (cdras 'c y
) ; trig functions
1351 (cond ((eq (car (cdras 'b y
)) '%cos
) ; expand cos(n*x)
1352 (maxima-substitute var
1354 (supercosnx (cdras 'n y
))))
1355 (t ; expand sin(x*x)
1356 (maxima-substitute var
1358 (supersinx (cdras 'n y
)))))))
1360 a
;; A product of trig functions and all trig functions have the same
1361 ;; argument *trigarg*. Maxima substitutes *trigarg* with the variable var
1362 ;; of integration and calls trigint to integrate the new problem.
1363 (setq w
(subst2s exp
*trigarg
*))
1364 (setq b
(cdras 'b
(m2-b*x
+a
*trigarg
*)))
1365 (setq a
(substint *trigarg
* var
(trigint (div* w b
) var
)))
1366 (return (if (isinop a
'%integrate
)
1367 (list '(%integrate
) exp var
)
1371 (member (car x
) '(%sin %cos %tan %cot %sec %csc
) :test
#'eq
))
1373 (defun supersinx (n)
1374 (let ((i (if (< n
0) -
1 1)))
1375 ($expand
(list '(mtimes) i
(sinnx (timesk i n
))))))
1377 (defun supercosnx (n)
1378 ($expand
(cosnx (timesk (if (< n
0) -
1 1) n
))))
1384 (list '(mtimes) '((%sin
) x
) (cosnx (1- n
)))
1385 (list '(mtimes) '((%cos
) x
) (sinnx (1- n
))))))
1391 (list '(mtimes) '((%cos
) x
) (cosnx (1- n
)))
1392 (list '(mtimes) -
1 '((%sin
) x
) (sinnx (1- n
))))))
1395 (and (even x
) (> x -
1)))
1399 (not (member x
'(sin* cos
* sec
* tan
*) :test
#'eq
))
1400 (and (trigfree (car x
)) (trigfree (cdr x
)))))
1403 (prog (*b1
* *notsame
*)
1404 (declare (special *yy
* *b1
* *notsame
*))
1405 (when (and (numberp exp
) (zerop exp
))
1407 (setq *b1
* (subst *b
* 'b
'((mexpt) b
(n even
))))
1409 (setq *yy
* (rats exp
))
1410 (cond ((not *notsame
*) *yy
*))))))
1414 (declare (special *notsame
* *b1
*))
1416 (cond ((eq exp
*a
*) 'x
)
1418 (cond ((member exp
'(sin* cos
* sec
* tan
*) :test
#'eq
)
1421 ((setq y
(m2 exp
*b1
*))
1423 (t (cons (car exp
) (mapcar #'(lambda (g) (rats g
)) (cdr exp
))))))))
1426 (maxima-substitute *c
*
1428 (maxima-substitute (quotient (cdr (assoc 'n y
:test
#'eq
)) 2)
1439 (declare (special *yz
*))
1440 (cond ((not (numberp n
)) nil
)
1441 ((not (equal (rem n
2) 0))
1443 (maxima-substitute *c
*
1446 '((mplus) 1 ((mtimes) c
((mexpt) x
2)))
1447 (quotient (1- n
) 2)))))
1451 (maxima-substitute var
'x x
))
1453 (defun subvardlg (x)
1454 (mapcar #'(lambda (m)
1455 (cons (maxima-substitute var
'x
(car m
)) (cdr m
)))
1458 ;; This appears to be the implementation of Method 6, pp.82 in Moses' thesis.
1460 (defun trigint (exp var
)
1461 (prog (y repl y1 y2
*yy
* z m n
*c
* *yz
* *a
* *b
* )
1462 (declare (special *yy
* *yz
*))
1463 ;; Transform trig(x) into trig* (for simplicity?) Convert cot to
1464 ;; tan and csc to sin.
1466 (subliss (subvardlg '((((%sin
) x
) . sin
*)
1469 (((%cot
) x
) .
((mexpt) tan
* -
1))
1471 (((%csc
) x
) .
((mexpt) sin
* -
1))))
1474 (when *debug-integrate
*
1475 (format t
"~& in TRIGINT:~%")
1476 (format t
"~& : y2 = ~A~%" y2
))
1478 ;; Now transform tan to sin/cos and sec to 1/cos.
1479 (setq y1
(setq y
(subliss '((tan* .
((mtimes) sin
*
1481 (sec* .
((mexpt) cos
* -
1)))
1484 (when *debug-integrate
* (format t
"~& : y = ~A~%" y
))
1489 ((coefftt) (b trigfree
))
1490 ((mexpt) sin
* (m poseven
))
1491 ((mexpt) cos
* (n poseven
))))))
1492 ;; Go if y is not of the form sin^m*cos^n for positive even m and n.
1496 ;; Handle the case of sin^m*cos^n, m, n both non-negative and even.
1498 (setq m
(cdras 'm z
))
1499 (setq n
(cdras 'n z
))
1500 (setq *a
* (integerp2 (* 0.5 (if (< m n
) 1 -
1) (+ n
(* -
1 m
)))))
1501 (setq z
(cons (cons 'a
*a
*) z
))
1502 (setq z
(cons (cons 'x var
) z
))
1504 (when *debug-integrate
*
1505 (format t
"~& CASE III:~%")
1506 (format t
"~& : m, n = ~A ~A~%" m n
)
1507 (format t
"~& : a = ~A~%" *a
*)
1508 (format t
"~& : z = ~A~%" z
))
1510 ;; integrate(sin(y)^m*cos(y)^n,y) is transformed to the following form:
1512 ;; m < n: integrate((sin(2*y)/2)^n*(1/2+1/2*cos(2*y)^((n-m)/2),y)
1513 ;; m >= n: integrate((sin(2*y)/2)^n*(1/2-1/2*cos(2*y)^((m-n)/2),y)
1525 ((mtimes) ((rat simp
) 1 2) ((%sin
) x
))
1531 ((rat simp
) 1 2) ((%cos
) x
))) a
))))
1536 ((mtimes) ((rat simp
) 1 2) ((%sin
) x
))
1547 ;; I think this is case IV, working on the expression in terms of
1550 ;; Elem(x) means constants, x, trig functions of x, log and
1551 ;; inverse trig functions of x, and which are closed under
1552 ;; addition, multiplication, exponentiation, and substitution.
1554 ;; Elem(f(x)) is the same as Elem(x), but f(x) replaces x in the
1557 (when *debug-integrate
* (format t
"~& Case IV:~%"))
1562 (when (and (m2 y
'((coeffpt) (c rat1
) ((mexpt) cos
* (n odd1
))))
1563 (setq repl
(list '(%sin
) var
)))
1564 ;; The case cos^(2*n+1)*Elem(cos^2,sin). Use the substitution z = sin.
1568 (when (and (m2 y
'((coeffpt) (c rat1
) ((mexpt) sin
* (n odd1
))))
1569 (setq repl
(list '(%cos
) var
)))
1570 ;; The case sin^(2*n+1)*Elem(sin^2,cos). Use the substitution z = cos.
1574 ;; Transform sin and cos to tan and sec to see if the integral is
1575 ;; of the form Elem(tan, sec^2). If so, use the substitution z = tan.
1577 (when *debug-integrate
* (format t
"~& Case V:~%"))
1579 (setq y
(subliss '((sin* (mtimes) tan
* ((mexpt) sec
* -
1))
1580 (cos* (mexpt) sec
* -
1))
1585 (when (and (rat1 y
) (setq repl
(list '(%tan
) var
)))
1589 (when (and (m2 y
'((coeffpt) (c rat1
) ((mexpt) tan
* (n odd1
))))
1590 (setq repl
(list '(%sec
) var
)))
1592 (when (not (alike1 (setq repl
($expand exp
)) exp
))
1593 (return (integrator repl var
)))
1594 (setq y
(subliss '((sin* (mtimes) 2 x
1595 ((mexpt) ((mplus) 1 ((mexpt) x
2)) -
1))
1597 ((mplus) 1 ((mtimes) -
1 ((mexpt) x
2)))
1598 ((mexpt) ((mplus) 1 ((mexpt) x
2)) -
1)))
1600 (setq y
(list '(mtimes)
1602 '((mtimes) 2 ((mexpt) ((mplus) 1 ((mexpt) x
2)) -
1))))
1603 (setq repl
(subvar '((mquotient) ((%sin
) x
) ((mplus) 1 ((%cos
) x
)))))
1606 (setq y
(list '(mtimes) -
1 *yy
* *yz
*))
1609 (setq y
(list '(mtimes) '((mexpt) ((mplus) 1 ((mexpt) x
2)) -
1) *yy
*))
1612 (setq y
(list '(mtimes) *yy
* *yz
*))
1614 (when *debug-integrate
*
1615 (format t
"~& Call the INTEGRATOR with:~%")
1616 (format t
"~& : y = ~A~%" y
)
1617 (format t
"~& : repl = ~A~%" repl
))
1618 ;; See Bug 2880797. We want atan(tan(x)) to simplify to x, so
1619 ;; set $triginverses to '$all.
1621 ;; Do not integrate for the global variable VAR, but substitute it.
1622 ;; This way possible assumptions on VAR are no longer present. The
1623 ;; algorithm of DEFINT depends on this behavior. See Bug 3085498.
1624 (let (($triginverses
'$all
) (newvar (gensym)))
1627 (integrator (maxima-substitute newvar
'x y
) newvar
))))))
1629 (defmvar $integration_constant_counter
0)
1630 (defmvar $integration_constant
'$%c
)
1632 ;; This is the top level of the integrator
1633 (defun sinint (exp var
)
1634 ;; *integrator-level* is a recursion counter for INTEGRATOR. See
1635 ;; INTEGRATOR for more details. Initialize it here.
1636 (let ((*integrator-level
* 0))
1637 (declare (special *integrator-level
*))
1639 ;; Sanity checks for variables
1641 (merror (intl:gettext
"integrate: variable must not be a number; found: ~:M") var
))
1642 (when ($ratp var
) (setf var
(ratdisrep var
)))
1643 (when ($ratp exp
) (setf exp
(ratdisrep exp
)))
1646 ;; Distribute over lists and matrices
1649 (mapcar #'(lambda (y) (sinint y var
)) (cdr exp
))))
1651 ;; The symbolic integration code doesn't really deal very well with
1652 ;; subscripted variables, so if we have one then replace occurrences of var
1653 ;; with an atomic gensym and recurse.
1654 ((and (not (atom var
))
1655 (member 'array
(cdar var
)))
1656 (let ((dummy-var (gensym)))
1657 (maxima-substitute var dummy-var
1658 (sinint (maxima-substitute dummy-var var exp
) dummy-var
))))
1660 ;; If exp is an equality, integrate both sides and add an integration
1663 (list (car exp
) (sinint (cadr exp
) var
)
1664 (add (sinint (caddr exp
) var
)
1665 ($concat $integration_constant
(incf $integration_constant_counter
)))))
1667 ;; If var is an atom which occurs as an operator in exp, then return a noun form.
1670 (list '(%integrate
) exp var
))
1672 ((zerop1 exp
) ;; special case because 0 will not pass sum-of-intsp test
1675 ((let ((ans (simplify
1676 (let ($opsubst varlist genvar stack
)
1677 (integrator exp var
)))))
1678 (if (sum-of-intsp ans
)
1679 (list '(%integrate
) exp var
)
1684 ;; This is a heuristic that SININT uses to work out whether the result from
1685 ;; INTEGRATOR is worth returning or whether just to return a noun form. If this
1686 ;; function returns T, then SININT will return a noun form.
1688 ;; The logic, as I understand it (Rupert 01/2014):
1690 ;; (1) If I integrate f(x) wrt x and get an atom other than x or 0, either
1691 ;; something's gone horribly wrong, or this is part of a larger
1692 ;; expression. In the latter case, we can return T here because hopefully
1693 ;; something else interesting will make the top-level return NIL.
1695 ;; (2) If I get a sum, return a noun form if every one of the summands is no
1696 ;; better than what I started with. (Presumably this is where the name
1699 ;; (3) If this is a noun form, it doesn't convey much information on its own,
1702 ;; (4) If this is a product, something interesting has probably happened. But
1703 ;; I still want a noun form if the result is like 2*'integrate(f(x),x), so
1704 ;; I'm only interested in terms in the product that are not free of
1705 ;; VAR. If one of those terms is worthy of report, that's great: return
1706 ;; NIL. Otherwise, return T if we saw at least two things (eg splitting an
1707 ;; integral into a product of two integrals)
1709 ;; (5) If the result is free of VAR, we're in a similar position to (1).
1711 ;; (6) Otherwise something interesting (and hopefully useful) has
1712 ;; happened. Return NIL to tell SININT to report it.
1713 (defun sum-of-intsp (ans)
1715 ;; Result of integration should never be a constant other than zero.
1716 ;; If the result of integration is zero, it is either because:
1717 ;; 1) a subroutine inside integration failed and returned nil,
1718 ;; and (mul 0 nil) yielded 0, meaning that the result is wrong, or
1719 ;; 2) the original integrand was actually zero - this is handled
1720 ;; with a separate special case in sinint
1722 ((mplusp ans
) (every #'sum-of-intsp
(cdr ans
)))
1723 ((eq (caar ans
) '%integrate
) t
)
1725 (let ((int-factors 0))
1726 (not (or (dolist (factor (cdr ans
))
1727 (unless (freeof var factor
)
1728 (if (sum-of-intsp factor
)
1731 (<= 2 int-factors
)))))
1732 ((freeof var ans
) t
)
1735 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1738 ;;; Implementation of Method 2: Integrate a summation
1740 (defun intsum (form var
)
1741 (prog (exp idx ll ul pair val
)
1742 (setq exp
(cadr form
)
1745 ul
(car (cddddr form
)))
1746 (if (or (not (atom var
))
1747 (not (free idx var
))
1749 (not (free ul var
)))
1750 (return (list '(%integrate
) form var
)))
1751 (setq pair
(partition exp var
1))
1752 (when (and (mexptp (cdr pair
))
1753 (eq (caddr pair
) var
))
1754 (setq val
(maxima-substitute ll idx
(cadddr pair
)))
1755 (cond ((equal val -
1)
1756 (return (add (integrator (maxima-substitute ll idx exp
) var
)
1757 (intsum1 exp idx
(add 1 ll
) ul var
))))
1759 (return (list '(%integrate
) form var
)))))
1760 (return (intsum1 exp idx ll ul var
))))
1762 (defun intsum1 (exp idx ll ul var
)
1763 (assume (list '(mgeqp) idx ll
))
1764 (if (not (eq ul
'$inf
))
1765 (assume (list '(mgeqp) ul idx
)))
1766 (simplifya (list '(%sum
) (integrator exp var
) idx ll ul
) t
))
1770 (member x
'(%log %integrate %atan
) :test
#'eq
)
1771 (or (finds (car x
)) (finds (cdr x
)))))
1773 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1776 ;;; Implementation of Method 9:
1777 ;;; Rational function times a log or arctric function
1779 ;;; ratlog is called for an expression containing a log or arctrig function
1780 ;;; The integrand is like log(x)*f'(x). To obtain the result the technique of
1781 ;;; partial integration is applied: log(x)*f(x)-integrate(1/x*f(x),x)
1783 (defun ratlog (exp var form
)
1786 (setq b
(cdr (assoc 'b y
:test
#'eq
)))
1787 (setq c
(cdr (assoc 'c y
:test
#'eq
)))
1788 (setq y
(integrator c var
))
1789 (when (finds y
) (return nil
))
1790 (setq d
(sdiff (cdr (assoc 'a form
:test
#'eq
)) var
))
1792 (setq z
(integrator (mul2* y d
) var
))
1793 (setq d
(cdr (assoc 'a form
:test
#'eq
)))
1794 (return (simplify (list '(mplus)
1795 (list '(mtimes) y d
)
1796 (list '(mtimes) -
1 z
))))))
1798 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1800 ;;; partial-integration is an extension of the algorithm of ratlog to support
1801 ;;; the technique of partial integration for more cases. The integrand
1802 ;;; is like g(x)*f'(x) and the result is g(x)*f(x)-integrate(g'(x)*f(x),x).
1804 ;;; Adding integrals properties for elementary functions led to infinite recursion
1805 ;;; with integrate(z*expintegral_shi(z),z). This was resolved by limiting the
1806 ;;; recursion depth. *integrator-level* needs to be at least 3 to solve
1807 ;;; o integrate(expintegral_ei(1/sqrt(x)),x)
1808 ;;; o integrate(sqrt(z)*expintegral_li(z),z)
1809 ;;; while a value of 4 causes testsuite regressions with
1810 ;;; o integrate(z*expintegral_shi(z),z)
1811 (defun partial-integration (form var
)
1812 (declare (special *integrator-level
*))
1813 (let ((g (cdr (assoc 'a form
))) ; part g(x)
1814 (df (cdr (assoc 'c form
))) ; part f'(x)
1816 (setq f
(integrator df var
)) ; integrate f'(x) wrt var
1818 ((or (isinop f
'%integrate
) ; no result or
1819 (isinop f
(caar g
)) ; g in result
1820 (> *integrator-level
* 3))
1821 nil
) ; we return nil
1823 ;; Build the result: g(x)*f(x)-integrate(g'(x)*f(x))
1825 (mul -
1 (integrator (mul f
(sdiff g var
)) var
)))))))
1827 ;; returns t if argument of every trig operation in y matches arg
1828 (defun every-trigarg-alike (y arg
)
1830 ((optrig (caar y
)) (alike1 arg
(cadr y
)))
1831 (t (every (lambda (exp)
1832 (every-trigarg-alike exp arg
))
1835 ;; return argument of first trig operation encountered in y
1836 (defun find-first-trigarg (y)
1837 (cond ((atom y
) nil
)
1838 ((optrig (caar y
)) (cadr y
))
1839 (t (some (lambda (exp)
1840 (find-first-trigarg exp
))
1843 ;; return constant factor that makes elements of alist match elements of blist
1844 ;; or nil if no match found
1845 ;; (we could replace this using rat package to divide alist and blist)
1846 (defun matchsum (alist blist
)
1848 (setq s
(m2 (car alist
) ;; find coeff for first term of alist
1850 ((coefftt) (a freevar
))
1851 ((coefftt) (c true
)))))
1852 (setq *c
* (cdr (assoc 'c s
:test
#'eq
)))
1853 (cond ((not (setq r
;; find coeff for first term of blist
1856 (cons '((coefftt) (b free1
))
1857 (cond ((mtimesp *c
*)
1859 (t (list *c
*))))))))
1861 (setq *d
* (simplify (list '(mtimes)
1866 (cond ((m2 (cons '(mplus) alist
) ;; check that all terms match
1867 (timesloop *d
* blist
))
1871 (defun timesloop (a b
)
1872 (cons '(mplus) (mapcar #'(lambda (c) (mul2* a c
)) b
)))
1874 (defun expands (aa b
)
1875 (addn (mapcar #'(lambda (c) (timesloop c aa
)) b
) nil
))
1877 (defun powerlist (exp var
)
1878 (prog (y *c
* *d
* powerlist
*b
*)
1881 ((mexpt) (var varp
) (c integerp2
))
1882 ((coefftt) (a freevar
))
1883 ((coefftt) (b true
)))))
1884 (setq *b
* (cdr (assoc 'b y
:test
#'eq
)))
1885 (setq *c
* (cdr (assoc 'c y
:test
#'eq
)))
1886 (unless (rat10 *b
*) (return nil
))
1887 (setq *d
* (apply #'gcd
(cons (1+ *c
*) powerlist
)))
1888 (when (or (eql 1 *d
*) (zerop *d
*)) (return nil
))
1891 (list '(mexpt) var
*d
*)
1893 (integrate5 (simplify (list '(mtimes)
1895 (cdr (assoc 'a y
:test
#'eq
))
1896 (list '(mexpt) var
(1- (quotient (1+ *c
*) *d
*)))
1900 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1903 ;;; Implementation of Method 3: Derivative-divides algorithm
1905 ;; This is the derivative-divides algorithm of Moses.
1909 ;; Look for form I c * op(u(x)) * u'(x) dx
1913 ;; where: c is a constant
1914 ;; u(x) is an elementary expression in x
1915 ;; u'(x) is its derivative
1916 ;; op is an elementary operator:
1917 ;; - the indentity, or
1918 ;; - any function that can be integrated by INTEGRALLOOKUPS
1920 ;; The method of solution, once the problem has been determined to
1921 ;; posses the form above, is to look up OP in a table and substitute
1922 ;; u(x) for each occurrence of x in the expression given in the table.
1923 ;; In other words, the method performs an implicit substitution y = u(x),
1924 ;; and obtains the integral of op(y)dy by a table look up.
1926 (defun diffdiv (exp var
)
1927 (prog (y *a
* x v
*d
* z w r
)
1928 (cond ((and (mexptp exp
)
1930 (integerp (caddr exp
))
1933 (return (integrator (expandexpt (cadr exp
) (caddr exp
)) var
))))
1935 ;; If not a product, transform to a product with one term
1936 (setq exp
(cond ((mtimesp exp
) exp
) (t (list '(mtimes) exp
))))
1938 ;; Loop over the terms in exp
1942 ;; This m2 pattern matches const*(exp/y)
1943 (setq r
(list '(mplus)
1946 (remove y
(cdr exp
) :count
1)))))
1948 ;; Case u(var) is the identity function. y is a term in exp.
1949 ;; Match if diff(y,var) == c*(exp/y).
1950 ;; This even works when y is a function with multiple args.
1951 ((setq w
(m2 (sdiff y var
) r
))
1952 (return (muln (list y y
(power* (mul2* 2 (cdr (assoc 'c w
:test
#'eq
))) -
1)) nil
))))
1954 ;; w is the arg in y.
1955 (let ((arg-freevar))
1958 ((or (atom y
) (member (caar y
) '(mplus mtimes
) :test
#'eq
)) y
)
1959 ;; Take the argument of a function with one value.
1960 ((= (length (cdr y
)) 1) (cadr y
))
1961 ;; A function has multiple args, and exactly one arg depends on var
1962 ((= (count-if #'null
(setq arg-freevar
(mapcar #'freevar
(cdr y
)))) 1)
1963 (do ((args (cdr y
) (cdr args
))
1964 (argf arg-freevar
(cdr argf
)))
1965 ((if (not (car argf
)) (return (car args
))))))
1969 ((setq w
(cond ((and (setq x
(sdiff w var
))
1971 (setq *d
* (remove y
(cdr exp
) :count
1))
1975 (cond ((setq *d
* (matchsum (cdr x
) (cdr v
)))
1976 (list (cons 'c
*d
*)))
1979 (return (cond ((null (setq x
(integrallookups y
))) nil
)
1981 (t (mul2* x
(power* (cdr (assoc 'c w
:test
#'eq
)) -
1)))))))
1983 (when (null z
) (return nil
))
1986 (defun subliss (alist expr
)
1987 "Alist is an alist consisting of a variable (symbol) and its value. expr is
1988 an expression. For each entry in alist, substitute the corresponding
1992 (setq x
(maxima-substitute (cdr a
) (car a
) x
)))))
1994 (defun substint (x y expres
)
1995 (if (and (not (atom expres
)) (eq (caar expres
) '%integrate
))
1996 (list (car expres
) exp var
)
1997 (substint1 (maxima-substitute x y expres
))))
1999 (defun substint1 (exp)
2000 (cond ((atom exp
) exp
)
2001 ((and (eq (caar exp
) '%integrate
)
2003 (not (symbolp (caddr exp
)))
2004 (not (free (caddr exp
) var
)))
2005 (simplify (list '(%integrate
)
2006 (mul2 (cadr exp
) (sdiff (caddr exp
) var
))
2008 (t (recur-apply #'substint1 exp
))))
2010 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2012 ;:; Extension of the integrator for more integrals with power functions
2014 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2016 ;;; Recognize (a^(c*(z^r)^p+d)^v
2018 (defun m2-exp-type-1a (expr)
2024 ;; The order of the pattern is critical. If we change it,
2025 ;; we do not get the expected match.
2026 ((coeffpp) (d freevar
))
2027 ((coefft) (c freevar0
)
2029 ((mexpt) (z varp
) (r freevar0
))
2033 ;;; Recognize z^v*a^(b*z^r+d)
2035 (defun m2-exp-type-2 (expr)
2038 ((mexpt) (z varp
) (v freevar0
))
2042 ((coeffpp) (d freevar
))
2043 ((coefft) (b freevar0
) ((mexpt) (z varp
) (r freevar0
))))))))
2045 ;;; Recognize z^v*%e^(a*z^r+b)^u
2047 (defun m2-exp-type-2-1 (expr)
2050 ((mexpt) (z varp
) (v freevar0
))
2055 ((coeffpp) (b freevar
))
2056 ((coefft) (a freevar0
) ((mexpt) (z varp
) (r freevar0
)))))
2059 ;;; Recognize (a*z+b)^p*%e^(c*z+d)
2061 (defun m2-exp-type-3 (expr)
2066 ((coefft) (a freevar0
) (z varp
))
2067 ((coeffpp) (b freevar
)))
2072 ((coefft) (c freevar0
) (z varp
))
2073 ((coeffpp) (d freevar
)))))))
2075 ;;; Recognize d^(a*z^2+b/z^2+c)
2077 (defun m2-exp-type-4 (expr)
2082 ((coefft) (a freevar0
) ((mexpt) (z varp
) 2))
2083 ((coefft) (b freevar0
) ((mexpt) (z varp
) -
2))
2084 ((coeffpp) (c freevar
))))))
2086 ;;; Recognize z^(2*n)*d^(a*z^2+b/z^2+c)
2088 (defun m2-exp-type-4-1 (expr)
2091 ((mexpt) (z varp
) (n freevar0
))
2095 ((coefft) (a freevar0
) ((mexpt) (z varp
) 2))
2096 ((coefft) (b freevar0
) ((mexpt) (z varp
) -
2))
2097 ((coeffpp) (c freevar
)))))))
2099 ;;; Recognize z^n*d^(a*z^2+b*z+c)
2101 (defun m2-exp-type-5 (expr)
2104 ((mexpt) (z varp
) (n freevar
))
2108 ((coeffpt) (a freevar
) ((mexpt) (z varp
) 2))
2109 ((coeffpt) (b freevar
) (z varp
))
2110 ((coeffpp) (c freevar
)))))))
2112 ;;; Recognize z^n*(%e^(a*z^2+b*z+c))^u
2114 (defun m2-exp-type-5-1 (expr)
2117 ((mexpt) (z varp
) (n freevar0
))
2122 ((coeffpp) (c freevar
))
2123 ((coefft) (a freevar0
) ((mexpt) (z varp
) 2))
2124 ((coefft) (b freevar0
) (z varp
))))
2127 ;;; Recognize z^n*d^(a*sqrt(z)+b*z+c)
2129 (defun m2-exp-type-6 (expr)
2132 ((mexpt) (z varp
) (n freevar0
))
2136 ((coefft) (a freevar0
) ((mexpt) (z varp
) ((rat) 1 2)))
2137 ((coefft) (b freevar0
) (z varp
))
2138 ((coeffpp) (c freevar
)))))))
2140 ;;; Recognize z^n*(%e^(a*sqrt(z)+b*z+c))^u
2142 (defun m2-exp-type-6-1 (expr)
2145 ((mexpt) (z varp
) (n freevar0
))
2150 ((coeffpp) (c freevar
))
2151 ((coefft) (a freevar0
) ((mexpt) (z varp
) ((rat) 1 2)))
2152 ((coefft) (b freevar0
) (z varp
))))
2155 ;;; Recognize z^n*a^(b*z^r+e)*h^(c*z^r+g)
2157 (defun m2-exp-type-7 (expr)
2160 ((mexpt) (z varp
) (n freevar
))
2166 ((mexpt) (z varp
) (r freevar0
)))
2167 ((coeffpp) (e freevar
))))
2173 ((mexpt) (z varp
) (r1 freevar0
)))
2174 ((coeffpp) (g freevar
)))))))
2176 ;;; Recognize z^v*(%e^(b*z^r+e))^q*(%e^(c*z^r+g))^u
2178 (defun m2-exp-type-7-1 (expr)
2181 ((mexpt) (z varp
) (v freevar
))
2186 ((coeffpp) (e freevar
))
2187 ((coefft) (b freevar0
) ((mexpt) (z varp
) (r freevar0
)))))
2193 ((coeffpp) (g freevar
))
2194 ((coefft) (c freevar0
) ((mexpt) (z varp
) (r1 freevar0
)))))
2197 ;;; Recognize a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z)+f*z+g)
2199 (defun m2-exp-type-8 (expr)
2205 ((coeffpt) (b freevar
) ((mexpt) (z varp
) ((rat) 1 2)))
2206 ((coeffpt) (d freevar
) (z varp
))
2207 ((coeffpp) (e freevar
))))
2211 ((coeffpt) (c freevar
) ((mexpt) (z varp
) ((rat) 1 2)))
2212 ((coeffpt) (f freevar
) (z varp
))
2213 ((coeffpp) (g freevar
)))))))
2215 ;;; Recognize (%e^(b*sqrt(z)+d*z+e))^u*(%e^(c*sqrt(z)+f*z+g))^v
2217 (defun m2-exp-type-8-1 (expr)
2224 ((coeffpp) (e freevar
))
2225 ((coeffpt) (b freevar
) ((mexpt) (z varp
) ((rat) 1 2)))
2226 ((coeffpt) (d freevar
) (z varp
))))
2232 ((coeffpp) (g freevar
))
2233 ((coeffpt) (c freevar
) ((mexpt) (z varp
) ((rat) 1 2)))
2234 ((coeffpt) (f freevar
) (z varp
))))
2237 ;;; Recognize (%e^(b*z^r+e))^u*(%e^(c*z^r+g))^v
2239 (defun m2-exp-type-8-2 (expr)
2246 ((coeffpp) (e freevar
))
2247 ((coefft) (b freevar
) ((mexpt) (z varp
) (r freevar0
)))))
2253 ((coeffpp) (g freevar
))
2254 ((coefft) (c freevar
) ((mexpt) (z varp
) (r1 freevar0
)))))
2257 ;;; Recognize z^n*a^(b*z^2+d*z+e)*h^(c*z^2+f*z+g)
2259 (defun m2-exp-type-9 (expr)
2262 ((mexpt) (z varp
) (n freevar
))
2266 ((coeffpt) (b freevar
) ((mexpt) (z varp
) 2))
2267 ((coeffpt) (d freevar
) (z varp
))
2268 ((coeffpp) (e freevar
))))
2272 ((coeffpt) (c freevar
) ((mexpt) (z varp
) 2))
2273 ((coeffpt) (f freevar
) (z varp
))
2274 ((coeffpp) (g freevar
)))))))
2276 ;;; Recognize z^n*(%e^(b*z^2+d*z+e))^q*(%e^(c*z^2+f*z+g))^u
2278 (defun m2-exp-type-9-1 (expr)
2281 ((mexpt) (z varp
) (n freevar
))
2286 ((coeffpp) (e freevar
))
2287 ((coeffpt) (b freevar
) ((mexpt) (z varp
) 2))
2288 ((coeffpt) (d freevar
) (z varp
))))
2294 ((coeffpp) (g freevar
))
2295 ((coeffpt) (c freevar
) ((mexpt) (z varp
) 2))
2296 ((coeffpt) (f freevar
) (z varp
))))
2299 ;;; Recognize z^n*a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z+)f*z+g)
2301 (defun m2-exp-type-10 (expr)
2304 ((mexpt) (z varp
) (n freevar
))
2308 ((coeffpt) (b freevar
) ((mexpt) (z varp
) ((rat) 1 2)))
2309 ((coeffpt) (d freevar
) (z varp
))
2310 ((coeffpp) (e freevar
))))
2314 ((coeffpt) (c freevar
) ((mexpt) (z varp
) ((rat) 1 2)))
2315 ((coeffpt) (f freevar
) (z varp
))
2316 ((coeffpp) (g freevar
)))))))
2318 ;;; Recognize z^n*(%e^(b*sqrt(z)+d*z+e))^q*(%e^(c*sqrt(z)+f*z+g))^u
2320 (defun m2-exp-type-10-1 (expr)
2323 ((mexpt) (z varp
) (n freevar
))
2328 ((coeffpp) (e freevar
))
2329 ((coeffpt) (b freevar
) ((mexpt) (z varp
) ((rat) 1 2)))
2330 ((coeffpt) (d freevar
) (z varp
))))
2336 ((coeffpp) (g freevar
))
2337 ((coeffpt) (c freevar
) ((mexpt) (z varp
) ((rat) 1 2)))
2338 ((coeffpt) (f freevar
) (z varp
))))
2341 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2343 (defun integrate-exp-special (expr var
&aux w const
)
2345 ;; First factor the expression.
2346 (setq expr
($factor expr
))
2348 ;; Remove constant factors.
2349 (setq w
(partition expr var
1))
2350 (setq const
(car w
))
2354 ((m2-exp-type-1a (facsum-exponent expr
))
2356 (when *debug-integrate
*
2357 (format t
"~&Type 1a: (a^(c*(z^r)^p+d)^v : w = ~A~%" w
))
2361 ;; 1/(p*r*(a^(c*v*(var^r)^p)))
2362 (inv (mul p r
(power a
(mul c v
(power (power var r
) p
)))))
2364 ;; (a^(d+c*(var^r)^p))^v
2365 (power (power a
(add d
(mul c
(power (power var r
) p
)))) v
)
2366 ;; gamma_incomplete(1/(p*r), -c*v*(var^r)^p*log(a))
2367 (take '(%gamma_incomplete
)
2369 (mul -
1 c v
(power (power var r
) p
) (take '(%log
) a
)))
2370 ;; (-c*v*(var^r)^p*log(a))^(-1/(p*r))
2371 (power (mul -
1 c v
(power (power var r
) p
) (take '(%log
) a
))
2372 (div -
1 (mul p r
)))))
2374 ((m2-exp-type-2 (facsum-exponent expr
))
2377 (when *debug-integrate
*
2378 (format t
"~&Type 2: z^v*a^(b*z^r+d) : w = ~A~%" w
))
2384 (power var
(add v
1))
2387 (mul -
1 b
(power var r
) ($log a
)))
2389 (mul -
1 b
(power var r
) ($log a
))
2390 (mul -
1 (div (add v
1) r
)))))
2392 ((m2-exp-type-2-1 (facsum-exponent expr
))
2394 (when *debug-integrate
*
2395 (format t
"~&Type 2-1: z^v*(%e^(a*z^r+b))^u : w = ~A~%" w
))
2400 (power '$%e
(mul -
1 a u
(power var r
)))
2401 (power (power '$%e
(add (mul a
(power var r
)) b
)) u
)
2402 (power var
(add v
1))
2403 (power (mul -
1 a u
(power var r
)) (div (mul -
1 (add v
1)) r
))
2404 (take '(%gamma_incomplete
)
2406 (mul -
1 a u
(power var r
)))))
2408 ((m2-exp-type-3 (facsum-exponent expr
))
2410 (when *debug-integrate
*
2411 (format t
"~&Type 3: (a*z+b)^p*%e^(c*z+d) : w = ~A~%" w
))
2415 (power '$%e
(sub d
(div (mul b c
) a
)))
2416 (power (add b
(mul a var
)) (add p
1))
2417 ($expintegral_e
(mul -
1 p
) (mul (div -
1 a
) c
(add b
(mul a var
))))))
2419 ((m2-exp-type-4 expr
)
2421 (let (($trigsign nil
)) ; Do not simplify erfc(-x) !
2422 (when *debug-integrate
*
2423 (format t
"~&Type 4: d^(a*z^2+b/z^2+c) : w = ~A~%" w
))
2427 (div 1 (mul 4 (power (mul -
1 a
($log d
)) (div 1 2))))
2430 (power '$%pi
(div 1 2))
2433 (power (mul -
1 a
($log d
)) (div 1 2))
2434 (power (mul -
1 b
($log d
)) (div 1 2))))
2438 (div (power (mul -
1 b
($log d
)) (div 1 2)) var
)
2439 (mul -
1 var
(power (mul -
1 a
($log d
)) (div 1 2)))))
2443 (power (mul -
1 a
($log d
)) (div 1 2))
2444 (power (mul -
1 b
($log d
)) (div 1 2))))
2447 (mul var
(power (mul -
1 a
($log d
)) (div 1 2)))
2448 (div (power (mul -
1 b
($log d
)) (div 1 2)) var
)))))))))
2450 ((and (m2-exp-type-4-1 expr
)
2451 (poseven (cdras 'n w
)) ; only for n a positive, even integer
2452 (symbolp (cdras 'a w
))) ; a has to be a symbol
2454 (let (($trigsign nil
)) ; Do not simplify erfc(-x) !
2456 (when *debug-integrate
*
2457 (format t
"~&Type 4-1: z^(2*n)*d^(a*z^2+b/z^2+c) : w = ~A~%" w
))
2464 (power '$%pi
(div 1 2))
2465 (simplify (list '(%derivative
)
2469 (power ($log d
) (mul -
1 n
))
2475 (power (mul -
1 a
($log d
)) (div 1 2))
2476 (power (mul -
1 b
($log d
)) (div 1 2))))
2480 (power (mul -
1 b
($log d
)) (div 1 2))
2482 (mul var
(power (mul -
1 ($log d
)) (div 1 2))))))))
2487 (power (mul -
1 a
($log d
)) (div 1 2))
2488 (power (mul -
1 b
($log d
)) (div 1 2))))
2491 (power (mul -
1 a
($log d
)) (div 1 2))
2492 (div (power (mul -
1 b
($log d
)) (div 1 2)) var
)))))
2493 (power (mul -
1 a
($log d
)) (div 1 2)))
2496 ((and (m2-exp-type-5 (facsum-exponent expr
))
2497 (maxima-integerp (cdras 'n w
))
2498 (eq ($sign
(cdras 'n w
)) '$pos
))
2501 (when *debug-integrate
*
2502 (format t
"~&Type 5: z^n*d^(a*z^2+b*z+c) : w = ~A~%" w
))
2506 (div -
1 (mul 2 (power (mul a
($log d
)) (div 1 2))))
2508 (power d
(sub c
(div (mul b b
) (mul 4 a
))))
2509 (let ((index (gensumindex))
2513 (power 2 (sub index n
))
2516 (div (add index
1) 2)
2519 (power (add b
(mul 2 a var
)) 2)
2521 (power (mul a
($log d
)) (mul -
1 (add n
(div 1 2))))
2522 (power (mul -
1 b
($log d
)) (sub n index
))
2523 (power (mul (add b
(mul 2 a var
)) ($log d
)) (add index
1))
2525 (mul (div -
1 a
) (power (add b
(mul 2 a var
)) 2) ($log d
))
2526 (mul (div -
1 2) (add index
1))))
2529 ((and (m2-exp-type-5-1 (facsum-exponent expr
))
2530 (maxima-integerp (cdras 'n w
))
2531 (eq ($sign
(cdras 'n w
)) '$pos
))
2533 (when *debug-integrate
*
2534 (format t
"~&Type 5-1: z^n*(%e^(a*z^2+b*z+c))^u : w = ~A~%" w
))
2539 (add (mul -
1 (div (mul b b u
) (mul 4 a
)))
2540 (mul -
1 u
(add (mul a var var
) (mul b var
)))))
2541 (power a
(mul -
1 (add n
1)))
2543 (add (mul a var var
) (mul b var
) c
))
2545 (let ((index (gensumindex))
2548 (mul (power 2 (sub index n
))
2549 (power (mul -
1 b
) (sub n index
))
2550 (power (add b
(mul 2 a var
)) (add index
1))
2551 (power (div (mul -
1 u
(power (add b
(mul 2 a var
)) 2)) a
)
2552 (mul (div -
1 2) (add index
1)))
2553 (take '(%binomial
) n index
)
2554 (take '(%gamma_incomplete
)
2555 (div (add index
1) 2)
2556 (div (mul -
1 u
(power (add b
(mul 2 a var
)) 2))
2560 ((and (m2-exp-type-6 (facsum-exponent expr
))
2561 (maxima-integerp (cdras 'n w
))
2562 (eq ($sign
(cdras 'n w
)) '$pos
))
2564 (when *debug-integrate
*
2565 (format t
"~&Type 6: z^n*d^(a*sqrt(z)+b*z+c) : w = ~A~%" w
))
2569 (power 2 (mul -
1 (add n
1)))
2570 (power d
(sub c
(div (mul a a
) (mul 4 b
))))
2571 (power (mul b
($log d
)) (mul -
2 (add n
1)))
2572 (let ((index1 (gensumindex))
2573 (index2 (gensumindex))
2578 (power -
1 (sub index1 index2
))
2580 ($binomial index1 index2
)
2581 ($binomial n index1
)
2583 (power (mul a
($log d
)) (sub (mul 2 n
) (add index1 index2
)))
2585 (mul (add a
(mul 2 b
(power var
(div 1 2)))) ($log d
))
2586 (add index1 index2
))
2590 (power (add a
(mul 2 b
(power var
(div 1 2)))) 2)
2592 (mul (div -
1 2) (add index1 index2
1)))
2598 (power (add a
(mul 2 b
(power var
(div 1 2)))) 2)
2602 (div (add index1 index2
2) 2)
2605 (power (add a
(mul 2 b
(power var
(div 1 2)))) 2)
2608 (add a
(mul 2 b
(power var
(div 1 2))))
2611 (div (add index1 index2
1) 2)
2614 (power (add a
(mul 2 b
(power var
(div 1 2)))) 2)
2619 ((and (m2-exp-type-6-1 (facsum-exponent expr
))
2620 (maxima-integerp (cdras 'n w
))
2621 (eq ($sign
(cdras 'n w
)) '$pos
))
2623 (when *debug-integrate
*
2624 (format t
"~&Type 6-1: z^n*(%e^(a*sqrt(z)+b*z+c))^u : w = ~A~%" w
))
2627 (power 2 (mul -
1 (add (mul 2 n
) 1)))
2629 (add (div (mul -
1 u a a
) (mul 4 b
))
2630 (mul u
(add (mul a
(power var
(div 1 2)))
2633 (power b
(mul -
2 (add n
1)))
2635 (add (mul a
(power var
(div 1 2)))
2638 (let ((index1 (gensumindex))
2639 (index2 (gensumindex))
2643 (mul (power -
1 (sub index1 index2
))
2645 (power a
(add (neg index2
) (neg index1
) (mul 2 n
)))
2646 (power (add a
(mul 2 b
(power var
(div 1 2))))
2647 (add index1 index2
))
2648 (power (div (mul -
1 u
2652 (power var
(div 1 2))))
2655 (mul (div -
1 2) (add index1 index2
1)))
2656 (take '(%binomial
) index1 index2
)
2657 (take '(%binomial
) n index1
)
2659 (add a
(mul 2 b
(power var
(div 1 2))))
2660 (take '(%gamma_incomplete
)
2661 (div (add index1 index2
1) 2)
2670 (power (div (mul -
1 u
2679 (take '(%gamma_incomplete
)
2680 (div (add index1 index2
2) 2)
2684 (power var
(div 1 2))))
2690 ((and (m2-exp-type-7 (facsum-exponent expr
))
2691 (eq ($sign
(sub (cdras 'r w
) (cdras 'r1 w
))) '$zero
))
2693 (when *debug-integrate
*
2694 (format t
"~&Type 7: z^n*a^(b*z^r+e)*h^(c*z^r+g) : w = ~A~%" w
))
2707 (add (mul b
($log a
)) (mul c
($log h
))))
2711 (mul -
1 (power var r
) (add (mul b
($log a
)) (mul c
($log h
)))))))
2713 ((and (m2-exp-type-7-1 (facsum-exponent expr
))
2714 (eq ($sign
(sub (cdras 'r w
) (cdras 'r1 w
))) '$zero
))
2716 (when *debug-integrate
*
2717 (format t
"~&Type 7-1: z^v*(%e^(b*z^r+e))^q*(%e^(c*z^r+g))^u : w = ~A~%" w
))
2721 (power '$%e
(mul -
1 (power var r
) (add (mul b q
) (mul c u
))))
2722 (power (power '$%e
(add e
(mul b
(power var r
)))) q
)
2723 (power (power '$%e
(add g
(mul c
(power var r
)))) u
)
2724 (power var
(add v
1))
2725 (power (mul -
1 (power var r
) (add (mul b q
) (mul c u
)))
2726 (div (mul -
1 (add v
1)) r
))
2727 (take '(%gamma_incomplete
)
2729 (mul -
1 (power var r
) (add (mul b q
) (mul c u
))))))
2731 ((m2-exp-type-8 (facsum-exponent expr
))
2733 (when *debug-integrate
*
2734 (format t
"~&Type 8: a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z)+f*z+g)")
2735 (format t
"~& : w = ~A~%" w
))
2744 (power a
(add (mul b
(power var
(div 1 2))) (mul d var
)))
2745 (power h
(add (mul c
(power var
(div 1 2))) (mul f var
)))
2746 (div 1 (add (mul d
($log a
)) (mul f
($log h
)))))
2748 (power '$%pi
(div 1 2))
2752 (power (add (mul b
($log a
)) (mul c
($log h
))) 2)
2753 (mul 4 (add (mul d
($log a
)) (mul f
($log h
)))))))
2760 (power var
(div 1 2))
2761 (add (mul d
($log a
)) (mul f
($log h
)))))
2763 (power (add (mul d
($log a
)) (mul f
($log h
))) (div 1 2)))))
2764 (add (mul b
($log a
)) (mul c
($log h
)))
2765 (power (add (mul d
($log a
)) (mul f
($log h
))) (div -
3 2))))))
2767 ((m2-exp-type-8-1 (facsum-exponent expr
))
2769 (when *debug-integrate
*
2770 (format t
"~&Type 8-1: (%e^(b*sqrt(z)+d*z+e))^u*(%e^(c*sqrt(z)+f*z+g))^v")
2771 (format t
"~& : w = ~A~%" w
))
2775 (power (add (mul d u
) (mul f v
)) (div -
3 2))
2778 (power (add (mul b u
)
2779 (mul 2 d u
(power var
(div 1 2)))
2780 (mul v
(add c
(mul 2 f
(power var
(div 1 2))))))
2782 (inv (mul 4 (add (mul d u
) (mul f v
))))))
2784 (add (mul b
(power var
(div 1 2)))
2789 (add (mul c
(power var
(div 1 2)))
2795 (mul (power (add (mul b u
)
2796 (mul 2 d u
(power var
(div 1 2)))
2797 (mul v
(add c
(mul 2 f
(power var
(div 1 2))))))
2799 (inv (mul 4 (add (mul d u
) (mul f v
))))))
2800 (power (add (mul d u
) (mul f v
)) (div 1 2)))
2802 (power '$%pi
(div 1 2))
2803 (add (mul b u
) (mul c v
))
2806 (mul 2 d u
(power var
(div 1 2)))
2808 (mul 2 f v
(power var
(div 1 2))))
2810 (power (add (mul d u
) (mul f v
))
2813 ((and (m2-exp-type-8-2 (facsum-exponent expr
))
2814 (eq ($sign
(sub (cdras 'r w
) (cdras 'r1 w
))) '$zero
))
2816 (when *debug-integrate
*
2817 (format t
"~&Type 8-2: (%e^(b*z^r+e))^u*(%e^(c*z^r+g))^v")
2818 (format t
"~& : w = ~A~%" w
))
2826 (add (mul b u
) (mul c v
))))
2828 (add (power var r
) e
))
2831 (add (power var r
) g
))
2836 (add (mul b u
) (mul c v
)))
2838 (take '(%gamma_incomplete
)
2840 (mul -
1 (power var r
) (add (mul b u
) (mul c v
))))))
2842 ((and (m2-exp-type-9 (facsum-exponent expr
))
2843 (maxima-integerp (cdras 'n w
))
2844 (eq ($sign
(cdras 'n w
)) '$pos
)
2845 (or (not (eq ($sign
(cdras 'b w
)) '$zero
))
2846 (not (eq ($sign
(cdras 'c w
)) '$zero
))))
2848 (when *debug-integrate
*
2849 (format t
"~&Type 9: z^n*a^(b*z^2+d*z+e)*h^(c*z^2+f*z+g)")
2850 (format t
"~& : w = ~A~%" w
))
2859 (power (add (mul d
($log a
)) (mul f
($log h
))) 2)
2860 (mul -
4 (add (mul b
($log a
)) (mul c
($log h
))))))
2861 (power (add (mul b
($log a
)) (mul c
($log h
))) (mul -
1 (add n
1)))
2862 (let ((index (gensumindex))
2866 (power 2 (sub index n
))
2869 (add (mul -
1 d
($log a
)) (mul -
1 f
($log h
)))
2873 (mul (add d
(mul 2 b var
)) ($log a
))
2874 (mul (add f
(mul 2 c var
)) ($log h
)))
2881 (mul (add d
(mul 2 b var
)) ($log a
))
2882 (mul (add f
(mul 2 c var
)) ($log h
)))
2884 (add (mul b
($log a
)) (mul c
($log h
)))))
2885 (div (add index
1) -
2))
2887 (div (add index
1) 2)
2892 (mul (add d
(mul 2 b var
)) ($log a
))
2893 (mul (add f
(mul 2 c var
)) ($log h
)))
2895 (mul 4 (add (mul b
($log a
)) (mul c
($log h
))))))))
2898 ((and (m2-exp-type-9-1 (facsum-exponent expr
))
2899 (maxima-integerp (cdras 'n w
))
2900 (eq ($sign
(cdras 'n w
)) '$pos
)
2901 (or (not (eq ($sign
(cdras 'b w
)) '$zero
))
2902 (not (eq ($sign
(cdras 'c w
)) '$zero
))))
2904 (when *debug-integrate
*
2905 (format t
"~&Type 9-1: z^n*(%e^(b*z^2+d*z+e))^q*(%e^(c*z^2+f*z+g))^u")
2906 (format t
"~& : w = ~A~%" w
))
2910 (power (add (mul b q
) (mul c u
)) (div -
1 2))
2912 (add (div (power (add (mul d q
) (mul f u
)) 2)
2913 (mul -
4 (add (mul b q
) (mul c u
))))
2921 (mul var
(add d
(mul b var
)))))
2925 (mul var
(add f
(mul c var
)))))
2927 (let ((index (gensumindex))
2930 (mul (power 2 (sub index n
))
2931 (power (add (mul b q
) (mul c u
)) (neg (add n
(div 1 2))))
2932 (power (add (neg (mul d q
)) (neg (mul f u
)))
2934 (power (add (mul d q
)
2936 (mul 2 var
(add (mul b q
) (mul c u
))))
2938 (power (div (power (add (mul d q
)
2945 (neg (add (mul b q
) (mul c u
))))
2946 (mul (div -
1 2) (add index
1)))
2947 (take '(%binomial
) n index
)
2948 (take '(%gamma_incomplete
)
2949 (div (add index
1) 2)
2950 (div (power (add (mul d q
)
2957 (mul -
4 (add (mul b q
) (mul c u
))))))
2960 ((and (m2-exp-type-10 (facsum-exponent expr
))
2961 (maxima-integerp (cdras 'n w
))
2962 (eq ($sign
(cdras 'n w
)) '$pos
)
2963 (or (not (eq ($sign
(cdras 'b w
)) '$zero
))
2964 (not (eq ($sign
(cdras 'c w
)) '$zero
))))
2966 (when *debug-integrate
*
2967 (format t
"~&Type 10: z^n*a^(b*sqrt(z)+d*z+e)*h^(c*sqrt(z)+f*z+g)")
2968 (format t
"~& : w = ~A~%" w
))
2971 (power 2 (add (mul -
2 n
) -
1))
2975 (div (power (add (mul b
($log a
)) (mul c
($log h
))) 2)
2976 (mul -
4 (add (mul d
($log a
)) (mul f
($log h
))))))
2977 (power (add (mul d
($log a
)) (mul f
($log h
))) (mul -
2 (add n
1)))
2978 (let ((index1 (gensumindex))
2979 (index2 (gensumindex))
2983 (mul (power -
1 (sub index1 index2
))
2985 ($binomial index1 index2
)
2986 ($binomial n index1
)
2987 (power (add (mul b
($log a
)) (mul c
($log h
)))
2988 (sub (mul 2 n
) (add index1 index2
)))
2989 (power (add (mul b
($log a
))
2992 (power var
(div 1 2))
2993 (add (mul d
($log a
)) (mul f
($log h
)))))
2994 (add index1 index2
))
2996 (div (power (add (mul b
($log a
))
2999 (power var
(div 1 2))
3000 (add (mul d
($log a
))
3003 (add (mul d
($log a
)) (mul f
($log h
)))))
3004 (mul (div -
1 2) (add index1 index2
1)))
3005 (add (mul ($gamma_incomplete
(mul (div 1 2)
3006 (add index1 index2
1))
3008 (div (power (add (mul b
($log a
))
3011 (power var
(div 1 2))
3012 (add (mul d
($log a
)) (mul f
($log h
)))))
3014 (add (mul d
($log a
)) (mul f
($log h
))))))
3015 (add (mul b
($log a
)) (mul c
($log h
)))
3016 (add (mul b
($log a
))
3019 (power var
(div 1 2))
3020 (add (mul d
($log a
)) (mul f
($log h
))))))
3022 ($gamma_incomplete
(mul (div 1 2)
3023 (add index1 index2
2))
3025 (div (power (add (mul b
($log a
))
3028 (power var
(div 1 2))
3029 (add (mul d
($log a
))
3032 (add (mul d
($log a
))
3033 (mul f
($log h
))))))
3034 (add (mul d
($log a
)) (mul f
($log h
)))
3036 (div (power (add (mul b
($log a
))
3039 (power var
(div 1 2))
3040 (add (mul d
($log a
))
3043 (add (mul d
($log a
))
3049 ((and (m2-exp-type-10-1 (facsum-exponent expr
))
3050 (maxima-integerp (cdras 'n w
))
3051 (eq ($sign
(cdras 'n w
)) '$pos
)
3052 (or (not (eq ($sign
(cdras 'b w
)) '$zero
))
3053 (not (eq ($sign
(cdras 'c w
)) '$zero
))))
3055 (let ((bq+cu
(add (mul b q
) (mul c u
)))
3056 (dq+fu
(add (mul d q
) (mul f u
))))
3057 (when *debug-integrate
*
3058 (format t
"~&Type 10-1: z^n*(%e^(b*sqrt(z)+d*z+e))^q*(%e^(c*sqrt(z)+f*z+g))^u")
3059 (format t
"~& : w = ~A~%" w
))
3062 (power 2 (mul -
1 (add (mul 2 n
) 1)))
3064 (add (div (mul -
1 (power bq
+cu
2)) (mul 4 dq
+fu
))
3066 (mul -
1 b
(power var
(div 1 2)) q
)
3068 (mul -
1 c
(power var
(div 1 2)) u
)))
3070 (add (mul b
(power var
(div 1 2)))
3075 (add (mul c
(power var
(div 1 2)))
3079 (power dq
+fu
(mul -
2 (add n
1)))
3080 (let ((index1 (gensumindex))
3081 (index2 (gensumindex))
3085 (mul (power -
1 (sub index1 index2
))
3088 (add (neg index1
) (neg index2
) (mul 2 n
)))
3090 (mul 2 (power var
(div 1 2)) dq
+fu
))
3091 (add index1 index2
))
3092 (power (div (power (add bq
+cu
3094 (power var
(div 1 2))
3099 (add index1 index2
1)))
3100 (take '(%binomial
) index1 index2
)
3101 (take '(%binomial
) n index1
)
3105 (power var
(div 1 2))
3107 (take '(%gamma_incomplete
)
3109 (add index1 index2
1))
3110 (div (power (add (mul b q
)
3113 (power var
(div 1 2))
3119 (power (div (power (add bq
+cu
3121 (power var
(div 1 2))
3127 (take '(%gamma_incomplete
)
3129 (add index1 index2
2))
3130 (div (power (add bq
+cu
3132 (power var
(div 1 2))
3140 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3142 ;;; Do a facsum for the exponent of power functions.
3143 ;;; This is necessary to integrate all general forms. The pattern matcher is
3144 ;;; not powerful enough to do the job.
3146 (defun facsum-exponent (expr)
3147 ;; Make sure that expr has the form ((mtimes) factor1 factor2 ...)
3148 (when (not (mtimesp expr
)) (setq expr
(list '(mtimes) expr
)))
3150 (l (cdr expr
) (cdr l
)))
3151 ((null l
) (cons (list 'mtimes
) result
))
3154 ;; Found an power function. Factor the exponent with facsum.
3155 (let* ((fac (mfuncall '$facsum
(caddr (car l
)) var
))
3159 (cons (cons (list 'mexpt
)
3160 (cons (cadr (car l
))
3163 (list ($multthru
(inv den
) num
)))))
3167 (setq result
(cons (car l
) result
))))))
3169 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;