root/trunk/lisp/calc/calcalg2.el

Revision 4220, 123.1 kB (checked in by miyoshi, 9 months ago)

Sync up with Emacs22.2.

Line 
1 ;;; calcalg2.el --- more algebraic functions for Calc
2
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004,
4 ;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5
6 ;; Author: David Gillespie <daveg@synaptics.com>
7 ;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25
26 ;;; Commentary:
27
28 ;;; Code:
29
30 ;; This file is autoloaded from calc-ext.el.
31
32 (require 'calc-ext)
33 (require 'calc-macs)
34
35 (defun calc-derivative (var num)
36   (interactive "sDifferentiate with respect to: \np")
37   (calc-slow-wrapper
38    (when (< num 0)
39      (error "Order of derivative must be positive"))
40    (let ((func (if (calc-is-hyperbolic) 'calcFunc-tderiv 'calcFunc-deriv))
41          n expr)
42      (if (or (equal var "") (equal var "$"))
43          (setq n 2
44                expr (calc-top-n 2)
45                var (calc-top-n 1))
46        (setq var (math-read-expr var))
47        (when (eq (car-safe var) 'error)
48          (error "Bad format in expression: %s" (nth 1 var)))
49        (setq n 1
50              expr (calc-top-n 1)))
51      (while (>= (setq num (1- num)) 0)
52        (setq expr (list func expr var)))
53      (calc-enter-result n "derv" expr))))
54
55 (defun calc-integral (var &optional arg)
56   (interactive "sIntegration variable: \nP")
57   (if arg
58       (calc-tabular-command 'calcFunc-integ "Integration" "intg" nil var nil nil)
59     (calc-slow-wrapper
60      (if (or (equal var "") (equal var "$"))
61          (calc-enter-result 2 "intg" (list 'calcFunc-integ
62                                            (calc-top-n 2)
63                                            (calc-top-n 1)))
64        (let ((var (math-read-expr var)))
65          (if (eq (car-safe var) 'error)
66              (error "Bad format in expression: %s" (nth 1 var)))
67          (calc-enter-result 1 "intg" (list 'calcFunc-integ
68                                            (calc-top-n 1)
69                                            var)))))))
70
71 (defun calc-num-integral (&optional varname lowname highname)
72   (interactive "sIntegration variable: ")
73   (calc-tabular-command 'calcFunc-ninteg "Integration" "nint"
74                         nil varname lowname highname))
75
76 (defun calc-summation (arg &optional varname lowname highname)
77   (interactive "P\nsSummation variable: ")
78   (calc-tabular-command 'calcFunc-sum "Summation" "sum"
79                         arg varname lowname highname))
80
81 (defun calc-alt-summation (arg &optional varname lowname highname)
82   (interactive "P\nsSummation variable: ")
83   (calc-tabular-command 'calcFunc-asum "Summation" "asum"
84                         arg varname lowname highname))
85
86 (defun calc-product (arg &optional varname lowname highname)
87   (interactive "P\nsIndex variable: ")
88   (calc-tabular-command 'calcFunc-prod "Index" "prod"
89                         arg varname lowname highname))
90
91 (defun calc-tabulate (arg &optional varname lowname highname)
92   (interactive "P\nsIndex variable: ")
93   (calc-tabular-command 'calcFunc-table "Index" "tabl"
94                         arg varname lowname highname))
95
96 (defun calc-tabular-command (func prompt prefix arg varname lowname highname)
97   (calc-slow-wrapper
98    (let (var (low nil) (high nil) (step nil) stepname stepnum (num 1) expr)
99      (if (consp arg)
100          (setq stepnum 1)
101        (setq stepnum 0))
102      (if (or (equal varname "") (equal varname "$") (null varname))
103          (setq high (calc-top-n (+ stepnum 1))
104                low (calc-top-n (+ stepnum 2))
105                var (calc-top-n (+ stepnum 3))
106                num (+ stepnum 4))
107        (setq var (if (stringp varname) (math-read-expr varname) varname))
108        (if (eq (car-safe var) 'error)
109            (error "Bad format in expression: %s" (nth 1 var)))
110        (or lowname
111            (setq lowname (read-string (concat prompt " variable: " varname
112                                               ", from: "))))
113        (if (or (equal lowname "") (equal lowname "$"))
114            (setq high (calc-top-n (+ stepnum 1))
115                  low (calc-top-n (+ stepnum 2))
116                  num (+ stepnum 3))
117          (setq low (if (stringp lowname) (math-read-expr lowname) lowname))
118          (if (eq (car-safe low) 'error)
119              (error "Bad format in expression: %s" (nth 1 low)))
120          (or highname
121              (setq highname (read-string (concat prompt " variable: " varname
122                                                  ", from: " lowname
123                                                  ", to: "))))
124          (if (or (equal highname "") (equal highname "$"))
125              (setq high (calc-top-n (+ stepnum 1))
126                    num (+ stepnum 2))
127            (setq high (if (stringp highname) (math-read-expr highname)
128                         highname))
129            (if (eq (car-safe high) 'error)
130                (error "Bad format in expression: %s" (nth 1 high)))
131            (if (consp arg)
132                (progn
133                  (setq stepname (read-string (concat prompt " variable: "
134                                                      varname
135                                                      ", from: " lowname
136                                                      ", to: " highname
137                                                      ", step: ")))
138                  (if (or (equal stepname "") (equal stepname "$"))
139                      (setq step (calc-top-n 1)
140                            num 2)
141                    (setq step (math-read-expr stepname))
142                    (if (eq (car-safe step) 'error)
143                        (error "Bad format in expression: %s"
144                               (nth 1 step)))))))))
145      (or step
146          (if (consp arg)
147              (setq step (calc-top-n 1))
148            (if arg
149                (setq step (prefix-numeric-value arg)))))
150      (setq expr (calc-top-n num))
151      (calc-enter-result num prefix (append (list func expr var low high)
152                                            (and step (list step)))))))
153
154 (defun calc-solve-for (var)
155   (interactive "sVariable(s) to solve for: ")
156   (calc-slow-wrapper
157    (let ((func (if (calc-is-inverse)
158                    (if (calc-is-hyperbolic) 'calcFunc-ffinv 'calcFunc-finv)
159                  (if (calc-is-hyperbolic) 'calcFunc-fsolve 'calcFunc-solve))))
160      (if (or (equal var "") (equal var "$"))
161          (calc-enter-result 2 "solv" (list func
162                                            (calc-top-n 2)
163                                            (calc-top-n 1)))
164        (let ((var (if (and (string-match ",\\|[^ ] +[^ ]" var)
165                            (not (string-match "\\[" var)))
166                       (math-read-expr (concat "[" var "]"))
167                     (math-read-expr var))))
168          (if (eq (car-safe var) 'error)
169              (error "Bad format in expression: %s" (nth 1 var)))
170          (calc-enter-result 1 "solv" (list func
171                                            (calc-top-n 1)
172                                            var)))))))
173
174 (defun calc-poly-roots (var)
175   (interactive "sVariable to solve for: ")
176   (calc-slow-wrapper
177    (if (or (equal var "") (equal var "$"))
178        (calc-enter-result 2 "prts" (list 'calcFunc-roots
179                                          (calc-top-n 2)
180                                          (calc-top-n 1)))
181      (let ((var (if (and (string-match ",\\|[^ ] +[^ ]" var)
182                          (not (string-match "\\[" var)))
183                     (math-read-expr (concat "[" var "]"))
184                   (math-read-expr var))))
185        (if (eq (car-safe var) 'error)
186            (error "Bad format in expression: %s" (nth 1 var)))
187        (calc-enter-result 1 "prts" (list 'calcFunc-roots
188                                          (calc-top-n 1)
189                                          var))))))
190
191 (defun calc-taylor (var nterms)
192   (interactive "sTaylor expansion variable: \nNNumber of terms: ")
193   (calc-slow-wrapper
194    (let ((var (math-read-expr var)))
195      (if (eq (car-safe var) 'error)
196          (error "Bad format in expression: %s" (nth 1 var)))
197      (calc-enter-result 1 "tylr" (list 'calcFunc-taylor
198                                        (calc-top-n 1)
199                                        var
200                                        (prefix-numeric-value nterms))))))
201
202
203 ;; The following are global variables used by math-derivative and some
204 ;; related functions
205 (defvar math-deriv-var)
206 (defvar math-deriv-total)
207 (defvar math-deriv-symb)
208 (defvar math-decls-cache)
209 (defvar math-decls-all)
210
211 (defun math-derivative (expr)
212   (cond ((equal expr math-deriv-var)
213          1)
214         ((or (Math-scalarp expr)
215              (eq (car expr) 'sdev)
216              (and (eq (car expr) 'var)
217                   (or (not math-deriv-total)
218                       (math-const-var expr)
219                       (progn
220                         (math-setup-declarations)
221                         (memq 'const (nth 1 (or (assq (nth 2 expr)
222                                                       math-decls-cache)
223                                                 math-decls-all)))))))
224          0)
225         ((eq (car expr) '+)
226          (math-add (math-derivative (nth 1 expr))
227                    (math-derivative (nth 2 expr))))
228         ((eq (car expr) '-)
229          (math-sub (math-derivative (nth 1 expr))
230                    (math-derivative (nth 2 expr))))
231         ((memq (car expr) '(calcFunc-eq calcFunc-neq calcFunc-lt
232                                         calcFunc-gt calcFunc-leq calcFunc-geq))
233          (list (car expr)
234                (math-derivative (nth 1 expr))
235                (math-derivative (nth 2 expr))))
236         ((eq (car expr) 'neg)
237          (math-neg (math-derivative (nth 1 expr))))
238         ((eq (car expr) '*)
239          (math-add (math-mul (nth 2 expr)
240                              (math-derivative (nth 1 expr)))
241                    (math-mul (nth 1 expr)
242                              (math-derivative (nth 2 expr)))))
243         ((eq (car expr) '/)
244          (math-sub (math-div (math-derivative (nth 1 expr))
245                              (nth 2 expr))
246                    (math-div (math-mul (nth 1 expr)
247                                        (math-derivative (nth 2 expr)))
248                              (math-sqr (nth 2 expr)))))
249         ((eq (car expr) '^)
250          (let ((du (math-derivative (nth 1 expr)))
251                (dv (math-derivative (nth 2 expr))))
252            (or (Math-zerop du)
253                (setq du (math-mul (nth 2 expr)
254                                   (math-mul (math-normalize
255                                              (list '^
256                                                    (nth 1 expr)
257                                                    (math-add (nth 2 expr) -1)))
258                                             du))))
259            (or (Math-zerop dv)
260                (setq dv (math-mul (math-normalize
261                                    (list 'calcFunc-ln (nth 1 expr)))
262                                   (math-mul expr dv))))
263            (math-add du dv)))
264         ((eq (car expr) '%)
265          (math-derivative (nth 1 expr)))   ; a reasonable definition
266         ((eq (car expr) 'vec)
267          (math-map-vec 'math-derivative expr))
268         ((and (memq (car expr) '(calcFunc-conj calcFunc-re calcFunc-im))
269               (= (length expr) 2))
270          (list (car expr) (math-derivative (nth 1 expr))))
271         ((and (memq (car expr) '(calcFunc-subscr calcFunc-mrow calcFunc-mcol))
272               (= (length expr) 3))
273          (let ((d (math-derivative (nth 1 expr))))
274            (if (math-numberp d)
275                0    ; assume x and x_1 are independent vars
276              (list (car expr) d (nth 2 expr)))))
277         (t (or (and (symbolp (car expr))
278                     (if (= (length expr) 2)
279                         (let ((handler (get (car expr) 'math-derivative)))
280                           (and handler
281                                (let ((deriv (math-derivative (nth 1 expr))))
282                                  (if (Math-zerop deriv)
283                                      deriv
284                                    (math-mul (funcall handler (nth 1 expr))
285                                              deriv)))))
286                       (let ((handler (get (car expr) 'math-derivative-n)))
287                         (and handler
288                              (funcall handler expr)))))
289                (and (not (eq math-deriv-symb 'pre-expand))
290                     (let ((exp (math-expand-formula expr)))
291                       (and exp
292                            (or (let ((math-deriv-symb 'pre-expand))
293                                  (catch 'math-deriv (math-derivative expr)))
294                                (math-derivative exp)))))
295                (if (or (Math-objvecp expr)
296                        (eq (car expr) 'var)
297                        (not (symbolp (car expr))))
298                    (if math-deriv-symb
299                        (throw 'math-deriv nil)
300                      (list (if math-deriv-total 'calcFunc-tderiv 'calcFunc-deriv)
301                            expr
302                            math-deriv-var))
303                  (let ((accum 0)
304                        (arg expr)
305                        (n 1)
306                        derv)
307                    (while (setq arg (cdr arg))
308                      (or (Math-zerop (setq derv (math-derivative (car arg))))
309                          (let ((func (intern (concat (symbol-name (car expr))
310                                                      "'"
311                                                      (if (> n 1)
312                                                          (int-to-string n)
313                                                        ""))))
314                                (prop (cond ((= (length expr) 2)
315                                             'math-derivative-1)
316                                            ((= (length expr) 3)
317                                             'math-derivative-2)
318                                            ((= (length expr) 4)
319                                             'math-derivative-3)
320                                            ((= (length expr) 5)
321                                             'math-derivative-4)
322                                            ((= (length expr) 6)
323                                             'math-derivative-5))))
324                            (setq accum
325                                  (math-add
326                                   accum
327                                   (math-mul
328                                    derv
329                                    (let ((handler (get func prop)))
330                                      (or (and prop handler
331                                               (apply handler (cdr expr)))
332                                          (if (and math-deriv-symb
333                                                   (not (get func
334                                                             'calc-user-defn)))
335                                              (throw 'math-deriv nil)
336                                            (cons func (cdr expr))))))))))
337                      (setq n (1+ n)))
338                    accum))))))
339
340 (defun calcFunc-deriv (expr math-deriv-var &optional deriv-value math-deriv-symb)
341   (let* ((math-deriv-total nil)
342          (res (catch 'math-deriv (math-derivative expr))))
343     (or (eq (car-safe res) 'calcFunc-deriv)
344         (null res)
345         (setq res (math-normalize res)))
346     (and res
347          (if deriv-value
348              (math-expr-subst res math-deriv-var deriv-value)
349            res))))
350
351 (defun calcFunc-tderiv (expr math-deriv-var &optional deriv-value math-deriv-symb)
352   (math-setup-declarations)
353   (let* ((math-deriv-total t)
354          (res (catch 'math-deriv (math-derivative expr))))
355     (or (eq (car-safe res) 'calcFunc-tderiv)
356         (null res)
357         (setq res (math-normalize res)))
358     (and res
359          (if deriv-value
360              (math-expr-subst res math-deriv-var deriv-value)
361            res))))
362
363 (put 'calcFunc-inv\' 'math-derivative-1
364      (function (lambda (u) (math-neg (math-div 1 (math-sqr u))))))
365
366 (put 'calcFunc-sqrt\' 'math-derivative-1
367      (function (lambda (u) (math-div 1 (math-mul 2 (list 'calcFunc-sqrt u))))))
368
369 (put 'calcFunc-deg\' 'math-derivative-1
370      (function (lambda (u) (math-div-float '(float 18 1) (math-pi)))))
371
372 (put 'calcFunc-rad\' 'math-derivative-1
373      (function (lambda (u) (math-pi-over-180))))
374
375 (put 'calcFunc-ln\' 'math-derivative-1
376      (function (lambda (u) (math-div 1 u))))
377
378 (put 'calcFunc-log10\' 'math-derivative-1
379      (function (lambda (u)
380                  (math-div (math-div 1 (math-normalize '(calcFunc-ln 10)))
381                            u))))
382
383 (put 'calcFunc-lnp1\' 'math-derivative-1
384      (function (lambda (u) (math-div 1 (math-add u 1)))))
385
386 (put 'calcFunc-log\' 'math-derivative-2
387      (function (lambda (x b)
388                  (and (not (Math-zerop b))
389                       (let ((lnv (math-normalize
390                                   (list 'calcFunc-ln b))))
391                         (math-div 1 (math-mul lnv x)))))))
392
393 (put 'calcFunc-log\'2 'math-derivative-2
394      (function (lambda (x b)
395                  (let ((lnv (list 'calcFunc-ln b)))
396                    (math-neg (math-div (list 'calcFunc-log x b)
397                                        (math-mul lnv b)))))))
398
399 (put 'calcFunc-exp\' 'math-derivative-1
400      (function (lambda (u) (math-normalize (list 'calcFunc-exp u)))))
401
402 (put 'calcFunc-expm1\' 'math-derivative-1
403      (function (lambda (u) (math-normalize (list 'calcFunc-expm1 u)))))
404
405 (put 'calcFunc-sin\' 'math-derivative-1
406      (function (lambda (u) (math-to-radians-2 (math-normalize
407                                                (list 'calcFunc-cos u))))))
408
409 (put 'calcFunc-cos\' 'math-derivative-1
410      (function (lambda (u) (math-neg (math-to-radians-2
411                                       (math-normalize
412                                        (list 'calcFunc-sin u)))))))
413
414 (put 'calcFunc-tan\' 'math-derivative-1
415      (function (lambda (u) (math-to-radians-2
416                             (math-sqr
417                              (math-normalize
418                               (list 'calcFunc-sec u)))))))
419
420 (put 'calcFunc-sec\' 'math-derivative-1
421      (function (lambda (u) (math-to-radians-2
422                             (math-mul
423                              (math-normalize
424                               (list 'calcFunc-sec u))
425                              (math-normalize
426                               (list 'calcFunc-tan u)))))))
427
428 (put 'calcFunc-csc\' 'math-derivative-1
429      (function (lambda (u) (math-neg
430                             (math-to-radians-2
431                              (math-mul
432                               (math-normalize
433                                (list 'calcFunc-csc u))
434                               (math-normalize
435                                (list 'calcFunc-cot u))))))))
436
437 (put 'calcFunc-cot\' 'math-derivative-1
438      (function (lambda (u) (math-neg
439                             (math-to-radians-2
440                              (math-sqr
441                               (math-normalize
442                                (list 'calcFunc-csc u))))))))
443
444 (put 'calcFunc-arcsin\' 'math-derivative-1
445      (function (lambda (u)
446                  (math-from-radians-2
447                   (math-div 1 (math-normalize
448                                (list 'calcFunc-sqrt
449                                      (math-sub 1 (math-sqr u)))))))))
450
451 (put 'calcFunc-arccos\' 'math-derivative-1
452      (function (lambda (u)
453                  (math-from-radians-2
454                   (math-div -1 (math-normalize
455                                 (list 'calcFunc-sqrt
456                                       (math-sub 1 (math-sqr u)))))))))
457
458 (put 'calcFunc-arctan\' 'math-derivative-1
459      (function (lambda (u) (math-from-radians-2
460                             (math-div 1 (math-add 1 (math-sqr u)))))))
461
462 (put 'calcFunc-sinh\' 'math-derivative-1
463      (function (lambda (u) (math-normalize (list 'calcFunc-cosh u)))))
464
465 (put 'calcFunc-cosh\' 'math-derivative-1
466      (function (lambda (u) (math-normalize (list 'calcFunc-sinh u)))))
467
468 (put 'calcFunc-tanh\' 'math-derivative-1
469      (function (lambda (u) (math-sqr
470                             (math-normalize
471                              (list 'calcFunc-sech u))))))
472
473 (put 'calcFunc-sech\' 'math-derivative-1
474      (function (lambda (u) (math-neg
475                             (math-mul
476                              (math-normalize (list 'calcFunc-sech u))
477                              (math-normalize (list 'calcFunc-tanh u)))))))
478
479 (put 'calcFunc-csch\' 'math-derivative-1
480      (function (lambda (u) (math-neg
481                             (math-mul
482                              (math-normalize (list 'calcFunc-csch u))
483                              (math-normalize (list 'calcFunc-coth u)))))))
484
485 (put 'calcFunc-coth\' 'math-derivative-1
486      (function (lambda (u) (math-neg
487                             (math-sqr
488                              (math-normalize
489                               (list 'calcFunc-csch u)))))))
490
491 (put 'calcFunc-arcsinh\' 'math-derivative-1
492      (function (lambda (u)
493                  (math-div 1 (math-normalize
494                               (list 'calcFunc-sqrt
495                                     (math-add (math-sqr u) 1)))))))
496
497 (put 'calcFunc-arccosh\' 'math-derivative-1
498      (function (lambda (u)
499                   (math-div 1 (math-normalize
500                                (list 'calcFunc-sqrt
501                                      (math-add (math-sqr u) -1)))))))
502
503 (put 'calcFunc-arctanh\' 'math-derivative-1
504      (function (lambda (u) (math-div 1 (math-sub 1 (math-sqr u))))))
505
506 (put 'calcFunc-bern\'2 'math-derivative-2
507      (function (lambda (n x)
508                  (math-mul n (list 'calcFunc-bern (math-add n -1) x)))))
509
510 (put 'calcFunc-euler\'2 'math-derivative-2
511      (function (lambda (n x)
512                  (math-mul n (list 'calcFunc-euler (math-add n -1) x)))))
513
514 (put 'calcFunc-gammag\'2 'math-derivative-2
515      (function (lambda (a x) (math-deriv-gamma a x 1))))
516
517 (put 'calcFunc-gammaG\'2 'math-derivative-2
518      (function (lambda (a x) (math-deriv-gamma a x -1))))
519
520 (put 'calcFunc-gammaP\'2 'math-derivative-2
521      (function (lambda (a x) (math-deriv-gamma a x
522                                                (math-div
523                                                 1 (math-normalize
524                                                    (list 'calcFunc-gamma
525                                                          a)))))))
526
527 (put 'calcFunc-gammaQ\'2 'math-derivative-2
528      (function (lambda (a x) (math-deriv-gamma a x
529                                                (math-div
530                                                 -1 (math-normalize
531                                                     (list 'calcFunc-gamma
532                                                           a)))))))
533
534 (defun math-deriv-gamma (a x scale)
535   (math-mul scale
536             (math-mul (math-pow x (math-add a -1))
537                       (list 'calcFunc-exp (math-neg x)))))
538
539 (put 'calcFunc-betaB\' 'math-derivative-3
540      (function (lambda (x a b) (math-deriv-beta x a b 1))))
541
542 (put 'calcFunc-betaI\' 'math-derivative-3
543      (function (lambda (x a b) (math-deriv-beta x a b
544                                                 (math-div
545                                                  1 (list 'calcFunc-beta
546                                                          a b))))))
547
548 (defun math-deriv-beta (x a b scale)
549   (math-mul (math-mul (math-pow x (math-add a -1))
550                       (math-pow (math-sub 1 x) (math-add b -1)))
551             scale))
552
553 (put 'calcFunc-erf\' 'math-derivative-1
554      (function (lambda (x) (math-div 2
555                                      (math-mul (list 'calcFunc-exp
556                                                      (math-sqr x))
557                                                (if calc-symbolic-mode
558                                                    '(calcFunc-sqrt
559                                                      (var pi var-pi))
560                                                  (math-sqrt-pi)))))))
561
562 (put 'calcFunc-erfc\' 'math-derivative-1
563      (function (lambda (x) (math-div -2
564                                      (math-mul (list 'calcFunc-exp
565                                                      (math-sqr x))
566                                                (if calc-symbolic-mode
567                                                    '(calcFunc-sqrt
568                                                      (var pi var-pi))
569                                                  (math-sqrt-pi)))))))
570
571 (put 'calcFunc-besJ\'2 'math-derivative-2
572      (function (lambda (v z) (math-div (math-sub (list 'calcFunc-besJ
573                                                        (math-add v -1)
574                                                        z)
575                                                  (list 'calcFunc-besJ
576                                                        (math-add v 1)
577                                                        z))
578                                        2))))
579
580 (put 'calcFunc-besY\'2 'math-derivative-2
581      (function (lambda (v z) (math-div (math-sub (list 'calcFunc-besY
582                                                        (math-add v -1)
583                                                        z)
584                                                  (list 'calcFunc-besY
585                                                        (math-add v 1)
586                                                        z))
587                                        2))))
588
589 (put 'calcFunc-sum 'math-derivative-n
590      (function
591       (lambda (expr)
592         (if (math-expr-contains (cons 'vec (cdr (cdr expr))) math-deriv-var)
593             (throw 'math-deriv nil)
594           (cons 'calcFunc-sum
595                 (cons (math-derivative (nth 1 expr))
596                       (cdr (cdr expr))))))))
597
598 (put 'calcFunc-prod 'math-derivative-n
599      (function
600       (lambda (expr)
601         (if (math-expr-contains (cons 'vec (cdr (cdr expr))) math-deriv-var)
602             (throw 'math-deriv nil)
603           (math-mul expr
604                     (cons 'calcFunc-sum
605                           (cons (math-div (math-derivative (nth 1 expr))
606                                           (nth 1 expr))
607                                 (cdr (cdr expr)))))))))
608
609 (put 'calcFunc-integ 'math-derivative-n
610      (function
611       (lambda (expr)
612         (if (= (length expr) 3)
613             (if (equal (nth 2 expr) math-deriv-var)
614                 (nth 1 expr)
615               (math-normalize
616                (list 'calcFunc-integ
617                      (math-derivative (nth 1 expr))
618                      (nth 2 expr))))
619           (if (= (length expr) 5)
620               (let ((lower (math-expr-subst (nth 1 expr) (nth 2 expr)
621                                             (nth 3 expr)))
622                     (upper (math-expr-subst (nth 1 expr) (nth 2 expr)
623                                             (nth 4 expr))))
624                 (math-add (math-sub (math-mul upper
625                                               (math-derivative (nth 4 expr)))
626                                     (math-mul lower
627                                               (math-derivative (nth 3 expr))))
628                           (if (equal (nth 2 expr) math-deriv-var)
629                               0
630                             (math-normalize
631                              (list 'calcFunc-integ
632                                    (math-derivative (nth 1 expr)) (nth 2 expr)
633                                    (nth 3 expr) (nth 4 expr)))))))))))
634
635 (put 'calcFunc-if 'math-derivative-n
636      (function
637       (lambda (expr)
638         (and (= (length expr) 4)
639              (list 'calcFunc-if (nth 1 expr)
640                    (math-derivative (nth 2 expr))
641                    (math-derivative (nth 3 expr)))))))
642
643 (put 'calcFunc-subscr 'math-derivative-n
644      (function
645       (lambda (expr)
646         (and (= (length expr) 3)
647              (list 'calcFunc-subscr (nth 1 expr)
648                    (math-derivative (nth 2 expr)))))))
649
650
651 (defvar math-integ-var '(var X ---))
652 (defvar math-integ-var-2 '(var Y ---))
653 (defvar math-integ-vars (list 'f math-integ-var math-integ-var-2))
654 (defvar math-integ-var-list (list math-integ-var))
655 (defvar math-integ-var-list-list (list math-integ-var-list))
656
657 ;; math-integ-depth is a local variable for math-try-integral, but is used
658 ;; by math-integral and math-tracing-integral
659 ;; which are called (directly or indirectly) by math-try-integral.
660 (defvar math-integ-depth)
661 ;; math-integ-level is a local variable for math-try-integral, but is used
662 ;; by math-integral, math-do-integral, math-tracing-integral,
663 ;; math-sub-integration, math-integrate-by-parts and
664 ;; math-integrate-by-substitution, which are called (directly or
665 ;; indirectly) by math-try-integral.
666 (defvar math-integ-level)
667 ;; math-integral-limit is a local variable for calcFunc-integ, but is
668 ;; used by math-tracing-integral, math-sub-integration and
669 ;; math-try-integration.
670 (defvar math-integral-limit)
671
672 (defmacro math-tracing-integral (&rest parts)
673   (list 'and
674         'trace-buffer
675         (list 'save-excursion
676               '(set-buffer trace-buffer)
677               '(goto-char (point-max))
678               (list 'and
679                     '(bolp)
680                     '(insert (make-string (- math-integral-limit
681                                              math-integ-level) 32)
682                              (format "%2d " math-integ-depth)
683                              (make-string math-integ-level 32)))
684               ;;(list 'condition-case 'err
685                     (cons 'insert parts)
686                 ;;    '(error (insert (prin1-to-string err))))
687               '(sit-for 0))))
688
689 ;;; The following wrapper caches results and avoids infinite recursion.
690 ;;; Each cache entry is: ( A B )          Integral of A is B;
691 ;;;                      ( A N )          Integral of A failed at level N;
692 ;;;                      ( A busy )       Currently working on integral of A;
693 ;;;                      ( A parts )      Currently working, integ-by-parts;
694 ;;;                      ( A parts2 )     Currently working, integ-by-parts;
695 ;;;                      ( A cancelled )  Ignore this cache entry;
696 ;;;                      ( A [B] )        Same result as for math-cur-record = B.
697
698 ;; math-cur-record is a local variable for math-try-integral, but is used
699 ;; by math-integral, math-replace-integral-parts and math-integrate-by-parts
700 ;; which are called (directly or indirectly) by math-try-integral, as well as
701 ;; by calc-dump-integral-cache
702 (defvar math-cur-record)
703 ;; math-enable-subst and math-any-substs are local variables for
704 ;; calcFunc-integ, but are used by math-integral and math-try-integral.
705 (defvar math-enable-subst)
706 (defvar math-any-substs)
707
708 ;; math-integ-msg is a local variable for math-try-integral, but is
709 ;; used (both locally and non-locally) by math-integral.
710 (defvar math-integ-msg)
711
712 (defvar math-integral-cache nil)
713 (defvar math-integral-cache-state nil)
714
715 (defun math-integral (expr &optional simplify same-as-above)
716   (let* ((simp math-cur-record)
717          (math-cur-record (assoc expr math-integral-cache))
718          (math-integ-depth (1+ math-integ-depth))
719          (val 'cancelled))
720     (math-tracing-integral "Integrating "
721                            (math-format-value expr 1000)
722                            "...\n")
723     (and math-cur-record
724          (progn
725            (math-tracing-integral "Found "
726                                   (math-format-value (nth 1 math-cur-record) 1000))
727            (and (consp (nth 1 math-cur-record))
728                 (math-replace-integral-parts math-cur-record))
729            (math-tracing-integral " => "
730                                   (math-format-value (nth 1 math-cur-record) 1000)
731                                   "\n")))
732     (or (and math-cur-record
733              (not (eq (nth 1 math-cur-record) 'cancelled))
734              (or (not (integerp (nth 1 math-cur-record)))
735                  (>= (nth 1 math-cur-record) math-integ-level)))
736         (and (math-integral-contains-parts expr)
737              (progn
738                (setq val nil)
739                t))
740         (unwind-protect
741             (progn
742               (let (math-integ-msg)
743                 (if (eq calc-display-working-message 'lots)
744                     (progn
745                       (calc-set-command-flag 'clear-message)
746                       (setq math-integ-msg (format
747                                             "Working... Integrating %s"
748                                             (math-format-flat-expr expr 0)))
749       &nbs