(Auto Save Files): Mention auto-save-file-name-transforms.
[emacs.git] / lisp / calc / calcalg2.el
blob34d801bc276040a21fdbd42b5b87df1ff931c1c9
1 ;;; calcalg2.el --- more algebraic functions for Calc
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc.
5 ;; Author: David Gillespie <daveg@synaptics.com>
6 ;; Maintainer: Colin Walters <walters@debian.org>
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is distributed in the hope that it will be useful,
11 ;; but WITHOUT ANY WARRANTY. No author or distributor
12 ;; accepts responsibility to anyone for the consequences of using it
13 ;; or for whether it serves any particular purpose or works at all,
14 ;; unless he says so in writing. Refer to the GNU Emacs General Public
15 ;; License for full details.
17 ;; Everyone is granted permission to copy, modify and redistribute
18 ;; GNU Emacs, but only under the conditions described in the
19 ;; GNU Emacs General Public License. A copy of this license is
20 ;; supposed to have been given to you along with GNU Emacs so you
21 ;; can know your rights and responsibilities. It should be in a
22 ;; file named COPYING. Among other things, the copyright notice
23 ;; and this notice must be preserved on all copies.
25 ;;; Commentary:
27 ;;; Code:
29 ;; This file is autoloaded from calc-ext.el.
30 (require 'calc-ext)
32 (require 'calc-macs)
34 (defun calc-Need-calc-alg-2 () nil)
37 (defun calc-derivative (var num)
38 (interactive "sDifferentiate with respect to: \np")
39 (calc-slow-wrapper
40 (when (< num 0)
41 (error "Order of derivative must be positive"))
42 (let ((func (if (calc-is-hyperbolic) 'calcFunc-tderiv 'calcFunc-deriv))
43 n expr)
44 (if (or (equal var "") (equal var "$"))
45 (setq n 2
46 expr (calc-top-n 2)
47 var (calc-top-n 1))
48 (setq var (math-read-expr var))
49 (when (eq (car-safe var) 'error)
50 (error "Bad format in expression: %s" (nth 1 var)))
51 (setq n 1
52 expr (calc-top-n 1)))
53 (while (>= (setq num (1- num)) 0)
54 (setq expr (list func expr var)))
55 (calc-enter-result n "derv" expr))))
57 (defun calc-integral (var)
58 (interactive "sIntegration variable: ")
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))))))
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))
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))
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))
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))
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))
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)))))))
154 (defun calc-solve-for (var)
155 (interactive "sVariable 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)))))))
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))))))
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)
200 (prefix-numeric-value nterms))))))
203 (defun math-derivative (expr) ; uses global values: deriv-var, deriv-total.
204 (cond ((equal expr deriv-var)
206 ((or (Math-scalarp expr)
207 (eq (car expr) 'sdev)
208 (and (eq (car expr) 'var)
209 (or (not deriv-total)
210 (math-const-var expr)
211 (progn
212 (math-setup-declarations)
213 (memq 'const (nth 1 (or (assq (nth 2 expr)
214 math-decls-cache)
215 math-decls-all)))))))
217 ((eq (car expr) '+)
218 (math-add (math-derivative (nth 1 expr))
219 (math-derivative (nth 2 expr))))
220 ((eq (car expr) '-)
221 (math-sub (math-derivative (nth 1 expr))
222 (math-derivative (nth 2 expr))))
223 ((memq (car expr) '(calcFunc-eq calcFunc-neq calcFunc-lt
224 calcFunc-gt calcFunc-leq calcFunc-geq))
225 (list (car expr)
226 (math-derivative (nth 1 expr))
227 (math-derivative (nth 2 expr))))
228 ((eq (car expr) 'neg)
229 (math-neg (math-derivative (nth 1 expr))))
230 ((eq (car expr) '*)
231 (math-add (math-mul (nth 2 expr)
232 (math-derivative (nth 1 expr)))
233 (math-mul (nth 1 expr)
234 (math-derivative (nth 2 expr)))))
235 ((eq (car expr) '/)
236 (math-sub (math-div (math-derivative (nth 1 expr))
237 (nth 2 expr))
238 (math-div (math-mul (nth 1 expr)
239 (math-derivative (nth 2 expr)))
240 (math-sqr (nth 2 expr)))))
241 ((eq (car expr) '^)
242 (let ((du (math-derivative (nth 1 expr)))
243 (dv (math-derivative (nth 2 expr))))
244 (or (Math-zerop du)
245 (setq du (math-mul (nth 2 expr)
246 (math-mul (math-normalize
247 (list '^
248 (nth 1 expr)
249 (math-add (nth 2 expr) -1)))
250 du))))
251 (or (Math-zerop dv)
252 (setq dv (math-mul (math-normalize
253 (list 'calcFunc-ln (nth 1 expr)))
254 (math-mul expr dv))))
255 (math-add du dv)))
256 ((eq (car expr) '%)
257 (math-derivative (nth 1 expr))) ; a reasonable definition
258 ((eq (car expr) 'vec)
259 (math-map-vec 'math-derivative expr))
260 ((and (memq (car expr) '(calcFunc-conj calcFunc-re calcFunc-im))
261 (= (length expr) 2))
262 (list (car expr) (math-derivative (nth 1 expr))))
263 ((and (memq (car expr) '(calcFunc-subscr calcFunc-mrow calcFunc-mcol))
264 (= (length expr) 3))
265 (let ((d (math-derivative (nth 1 expr))))
266 (if (math-numberp d)
267 0 ; assume x and x_1 are independent vars
268 (list (car expr) d (nth 2 expr)))))
269 (t (or (and (symbolp (car expr))
270 (if (= (length expr) 2)
271 (let ((handler (get (car expr) 'math-derivative)))
272 (and handler
273 (let ((deriv (math-derivative (nth 1 expr))))
274 (if (Math-zerop deriv)
275 deriv
276 (math-mul (funcall handler (nth 1 expr))
277 deriv)))))
278 (let ((handler (get (car expr) 'math-derivative-n)))
279 (and handler
280 (funcall handler expr)))))
281 (and (not (eq deriv-symb 'pre-expand))
282 (let ((exp (math-expand-formula expr)))
283 (and exp
284 (or (let ((deriv-symb 'pre-expand))
285 (catch 'math-deriv (math-derivative expr)))
286 (math-derivative exp)))))
287 (if (or (Math-objvecp expr)
288 (eq (car expr) 'var)
289 (not (symbolp (car expr))))
290 (if deriv-symb
291 (throw 'math-deriv nil)
292 (list (if deriv-total 'calcFunc-tderiv 'calcFunc-deriv)
293 expr
294 deriv-var))
295 (let ((accum 0)
296 (arg expr)
297 (n 1)
298 derv)
299 (while (setq arg (cdr arg))
300 (or (Math-zerop (setq derv (math-derivative (car arg))))
301 (let ((func (intern (concat (symbol-name (car expr))
303 (if (> n 1)
304 (int-to-string n)
305 ""))))
306 (prop (cond ((= (length expr) 2)
307 'math-derivative-1)
308 ((= (length expr) 3)
309 'math-derivative-2)
310 ((= (length expr) 4)
311 'math-derivative-3)
312 ((= (length expr) 5)
313 'math-derivative-4)
314 ((= (length expr) 6)
315 'math-derivative-5))))
316 (setq accum
317 (math-add
318 accum
319 (math-mul
320 derv
321 (let ((handler (get func prop)))
322 (or (and prop handler
323 (apply handler (cdr expr)))
324 (if (and deriv-symb
325 (not (get func
326 'calc-user-defn)))
327 (throw 'math-deriv nil)
328 (cons func (cdr expr))))))))))
329 (setq n (1+ n)))
330 accum))))))
332 (defun calcFunc-deriv (expr deriv-var &optional deriv-value deriv-symb)
333 (let* ((deriv-total nil)
334 (res (catch 'math-deriv (math-derivative expr))))
335 (or (eq (car-safe res) 'calcFunc-deriv)
336 (null res)
337 (setq res (math-normalize res)))
338 (and res
339 (if deriv-value
340 (math-expr-subst res deriv-var deriv-value)
341 res))))
343 (defun calcFunc-tderiv (expr deriv-var &optional deriv-value deriv-symb)
344 (math-setup-declarations)
345 (let* ((deriv-total t)
346 (res (catch 'math-deriv (math-derivative expr))))
347 (or (eq (car-safe res) 'calcFunc-tderiv)
348 (null res)
349 (setq res (math-normalize res)))
350 (and res
351 (if deriv-value
352 (math-expr-subst res deriv-var deriv-value)
353 res))))
355 (put 'calcFunc-inv\' 'math-derivative-1
356 (function (lambda (u) (math-neg (math-div 1 (math-sqr u))))))
358 (put 'calcFunc-sqrt\' 'math-derivative-1
359 (function (lambda (u) (math-div 1 (math-mul 2 (list 'calcFunc-sqrt u))))))
361 (put 'calcFunc-deg\' 'math-derivative-1
362 (function (lambda (u) (math-div-float '(float 18 1) (math-pi)))))
364 (put 'calcFunc-rad\' 'math-derivative-1
365 (function (lambda (u) (math-pi-over-180))))
367 (put 'calcFunc-ln\' 'math-derivative-1
368 (function (lambda (u) (math-div 1 u))))
370 (put 'calcFunc-log10\' 'math-derivative-1
371 (function (lambda (u)
372 (math-div (math-div 1 (math-normalize '(calcFunc-ln 10)))
373 u))))
375 (put 'calcFunc-lnp1\' 'math-derivative-1
376 (function (lambda (u) (math-div 1 (math-add u 1)))))
378 (put 'calcFunc-log\' 'math-derivative-2
379 (function (lambda (x b)
380 (and (not (Math-zerop b))
381 (let ((lnv (math-normalize
382 (list 'calcFunc-ln b))))
383 (math-div 1 (math-mul lnv x)))))))
385 (put 'calcFunc-log\'2 'math-derivative-2
386 (function (lambda (x b)
387 (let ((lnv (list 'calcFunc-ln b)))
388 (math-neg (math-div (list 'calcFunc-log x b)
389 (math-mul lnv b)))))))
391 (put 'calcFunc-exp\' 'math-derivative-1
392 (function (lambda (u) (math-normalize (list 'calcFunc-exp u)))))
394 (put 'calcFunc-expm1\' 'math-derivative-1
395 (function (lambda (u) (math-normalize (list 'calcFunc-expm1 u)))))
397 (put 'calcFunc-sin\' 'math-derivative-1
398 (function (lambda (u) (math-to-radians-2 (math-normalize
399 (list 'calcFunc-cos u))))))
401 (put 'calcFunc-cos\' 'math-derivative-1
402 (function (lambda (u) (math-neg (math-to-radians-2
403 (math-normalize
404 (list 'calcFunc-sin u)))))))
406 (put 'calcFunc-tan\' 'math-derivative-1
407 (function (lambda (u) (math-to-radians-2
408 (math-div 1 (math-sqr
409 (math-normalize
410 (list 'calcFunc-cos u))))))))
412 (put 'calcFunc-arcsin\' 'math-derivative-1
413 (function (lambda (u)
414 (math-from-radians-2
415 (math-div 1 (math-normalize
416 (list 'calcFunc-sqrt
417 (math-sub 1 (math-sqr u)))))))))
419 (put 'calcFunc-arccos\' 'math-derivative-1
420 (function (lambda (u)
421 (math-from-radians-2
422 (math-div -1 (math-normalize
423 (list 'calcFunc-sqrt
424 (math-sub 1 (math-sqr u)))))))))
426 (put 'calcFunc-arctan\' 'math-derivative-1
427 (function (lambda (u) (math-from-radians-2
428 (math-div 1 (math-add 1 (math-sqr u)))))))
430 (put 'calcFunc-sinh\' 'math-derivative-1
431 (function (lambda (u) (math-normalize (list 'calcFunc-cosh u)))))
433 (put 'calcFunc-cosh\' 'math-derivative-1
434 (function (lambda (u) (math-normalize (list 'calcFunc-sinh u)))))
436 (put 'calcFunc-tanh\' 'math-derivative-1
437 (function (lambda (u) (math-div 1 (math-sqr
438 (math-normalize
439 (list 'calcFunc-cosh u)))))))
441 (put 'calcFunc-arcsinh\' 'math-derivative-1
442 (function (lambda (u)
443 (math-div 1 (math-normalize
444 (list 'calcFunc-sqrt
445 (math-add (math-sqr u) 1)))))))
447 (put 'calcFunc-arccosh\' 'math-derivative-1
448 (function (lambda (u)
449 (math-div 1 (math-normalize
450 (list 'calcFunc-sqrt
451 (math-add (math-sqr u) -1)))))))
453 (put 'calcFunc-arctanh\' 'math-derivative-1
454 (function (lambda (u) (math-div 1 (math-sub 1 (math-sqr u))))))
456 (put 'calcFunc-bern\'2 'math-derivative-2
457 (function (lambda (n x)
458 (math-mul n (list 'calcFunc-bern (math-add n -1) x)))))
460 (put 'calcFunc-euler\'2 'math-derivative-2
461 (function (lambda (n x)
462 (math-mul n (list 'calcFunc-euler (math-add n -1) x)))))
464 (put 'calcFunc-gammag\'2 'math-derivative-2
465 (function (lambda (a x) (math-deriv-gamma a x 1))))
467 (put 'calcFunc-gammaG\'2 'math-derivative-2
468 (function (lambda (a x) (math-deriv-gamma a x -1))))
470 (put 'calcFunc-gammaP\'2 'math-derivative-2
471 (function (lambda (a x) (math-deriv-gamma a x
472 (math-div
473 1 (math-normalize
474 (list 'calcFunc-gamma
475 a)))))))
477 (put 'calcFunc-gammaQ\'2 'math-derivative-2
478 (function (lambda (a x) (math-deriv-gamma a x
479 (math-div
480 -1 (math-normalize
481 (list 'calcFunc-gamma
482 a)))))))
484 (defun math-deriv-gamma (a x scale)
485 (math-mul scale
486 (math-mul (math-pow x (math-add a -1))
487 (list 'calcFunc-exp (math-neg x)))))
489 (put 'calcFunc-betaB\' 'math-derivative-3
490 (function (lambda (x a b) (math-deriv-beta x a b 1))))
492 (put 'calcFunc-betaI\' 'math-derivative-3
493 (function (lambda (x a b) (math-deriv-beta x a b
494 (math-div
495 1 (list 'calcFunc-beta
496 a b))))))
498 (defun math-deriv-beta (x a b scale)
499 (math-mul (math-mul (math-pow x (math-add a -1))
500 (math-pow (math-sub 1 x) (math-add b -1)))
501 scale))
503 (put 'calcFunc-erf\' 'math-derivative-1
504 (function (lambda (x) (math-div 2
505 (math-mul (list 'calcFunc-exp
506 (math-sqr x))
507 (if calc-symbolic-mode
508 '(calcFunc-sqrt
509 (var pi var-pi))
510 (math-sqrt-pi)))))))
512 (put 'calcFunc-erfc\' 'math-derivative-1
513 (function (lambda (x) (math-div -2
514 (math-mul (list 'calcFunc-exp
515 (math-sqr x))
516 (if calc-symbolic-mode
517 '(calcFunc-sqrt
518 (var pi var-pi))
519 (math-sqrt-pi)))))))
521 (put 'calcFunc-besJ\'2 'math-derivative-2
522 (function (lambda (v z) (math-div (math-sub (list 'calcFunc-besJ
523 (math-add v -1)
525 (list 'calcFunc-besJ
526 (math-add v 1)
528 2))))
530 (put 'calcFunc-besY\'2 'math-derivative-2
531 (function (lambda (v z) (math-div (math-sub (list 'calcFunc-besY
532 (math-add v -1)
534 (list 'calcFunc-besY
535 (math-add v 1)
537 2))))
539 (put 'calcFunc-sum 'math-derivative-n
540 (function
541 (lambda (expr)
542 (if (math-expr-contains (cons 'vec (cdr (cdr expr))) deriv-var)
543 (throw 'math-deriv nil)
544 (cons 'calcFunc-sum
545 (cons (math-derivative (nth 1 expr))
546 (cdr (cdr expr))))))))
548 (put 'calcFunc-prod 'math-derivative-n
549 (function
550 (lambda (expr)
551 (if (math-expr-contains (cons 'vec (cdr (cdr expr))) deriv-var)
552 (throw 'math-deriv nil)
553 (math-mul expr
554 (cons 'calcFunc-sum
555 (cons (math-div (math-derivative (nth 1 expr))
556 (nth 1 expr))
557 (cdr (cdr expr)))))))))
559 (put 'calcFunc-integ 'math-derivative-n
560 (function
561 (lambda (expr)
562 (if (= (length expr) 3)
563 (if (equal (nth 2 expr) deriv-var)
564 (nth 1 expr)
565 (math-normalize
566 (list 'calcFunc-integ
567 (math-derivative (nth 1 expr))
568 (nth 2 expr))))
569 (if (= (length expr) 5)
570 (let ((lower (math-expr-subst (nth 1 expr) (nth 2 expr)
571 (nth 3 expr)))
572 (upper (math-expr-subst (nth 1 expr) (nth 2 expr)
573 (nth 4 expr))))
574 (math-add (math-sub (math-mul upper
575 (math-derivative (nth 4 expr)))
576 (math-mul lower
577 (math-derivative (nth 3 expr))))
578 (if (equal (nth 2 expr) deriv-var)
580 (math-normalize
581 (list 'calcFunc-integ
582 (math-derivative (nth 1 expr)) (nth 2 expr)
583 (nth 3 expr) (nth 4 expr)))))))))))
585 (put 'calcFunc-if 'math-derivative-n
586 (function
587 (lambda (expr)
588 (and (= (length expr) 4)
589 (list 'calcFunc-if (nth 1 expr)
590 (math-derivative (nth 2 expr))
591 (math-derivative (nth 3 expr)))))))
593 (put 'calcFunc-subscr 'math-derivative-n
594 (function
595 (lambda (expr)
596 (and (= (length expr) 3)
597 (list 'calcFunc-subscr (nth 1 expr)
598 (math-derivative (nth 2 expr)))))))
601 (defvar math-integ-var '(var X ---))
602 (defvar math-integ-var-2 '(var Y ---))
603 (defvar math-integ-vars (list 'f math-integ-var math-integ-var-2))
604 (defvar math-integ-var-list (list math-integ-var))
605 (defvar math-integ-var-list-list (list math-integ-var-list))
607 (defmacro math-tracing-integral (&rest parts)
608 (list 'and
609 'trace-buffer
610 (list 'save-excursion
611 '(set-buffer trace-buffer)
612 '(goto-char (point-max))
613 (list 'and
614 '(bolp)
615 '(insert (make-string (- math-integral-limit
616 math-integ-level) 32)
617 (format "%2d " math-integ-depth)
618 (make-string math-integ-level 32)))
619 ;;(list 'condition-case 'err
620 (cons 'insert parts)
621 ;; '(error (insert (prin1-to-string err))))
622 '(sit-for 0))))
624 ;;; The following wrapper caches results and avoids infinite recursion.
625 ;;; Each cache entry is: ( A B ) Integral of A is B;
626 ;;; ( A N ) Integral of A failed at level N;
627 ;;; ( A busy ) Currently working on integral of A;
628 ;;; ( A parts ) Currently working, integ-by-parts;
629 ;;; ( A parts2 ) Currently working, integ-by-parts;
630 ;;; ( A cancelled ) Ignore this cache entry;
631 ;;; ( A [B] ) Same result as for cur-record = B.
632 (defun math-integral (expr &optional simplify same-as-above)
633 (let* ((simp cur-record)
634 (cur-record (assoc expr math-integral-cache))
635 (math-integ-depth (1+ math-integ-depth))
636 (val 'cancelled))
637 (math-tracing-integral "Integrating "
638 (math-format-value expr 1000)
639 "...\n")
640 (and cur-record
641 (progn
642 (math-tracing-integral "Found "
643 (math-format-value (nth 1 cur-record) 1000))
644 (and (consp (nth 1 cur-record))
645 (math-replace-integral-parts cur-record))
646 (math-tracing-integral " => "
647 (math-format-value (nth 1 cur-record) 1000)
648 "\n")))
649 (or (and cur-record
650 (not (eq (nth 1 cur-record) 'cancelled))
651 (or (not (integerp (nth 1 cur-record)))
652 (>= (nth 1 cur-record) math-integ-level)))
653 (and (math-integral-contains-parts expr)
654 (progn
655 (setq val nil)
657 (unwind-protect
658 (progn
659 (let (math-integ-msg)
660 (if (eq calc-display-working-message 'lots)
661 (progn
662 (calc-set-command-flag 'clear-message)
663 (setq math-integ-msg (format
664 "Working... Integrating %s"
665 (math-format-flat-expr expr 0)))
666 (message math-integ-msg)))
667 (if cur-record
668 (setcar (cdr cur-record)
669 (if same-as-above (vector simp) 'busy))
670 (setq cur-record
671 (list expr (if same-as-above (vector simp) 'busy))
672 math-integral-cache (cons cur-record
673 math-integral-cache)))
674 (if (eq simplify 'yes)
675 (progn
676 (math-tracing-integral "Simplifying...")
677 (setq simp (math-simplify expr))
678 (setq val (if (equal simp expr)
679 (progn
680 (math-tracing-integral " no change\n")
681 (math-do-integral expr))
682 (math-tracing-integral " simplified\n")
683 (math-integral simp 'no t))))
684 (or (setq val (math-do-integral expr))
685 (eq simplify 'no)
686 (let ((simp (math-simplify expr)))
687 (or (equal simp expr)
688 (progn
689 (math-tracing-integral "Trying again after "
690 "simplification...\n")
691 (setq val (math-integral simp 'no t))))))))
692 (if (eq calc-display-working-message 'lots)
693 (message math-integ-msg)))
694 (setcar (cdr cur-record) (or val
695 (if (or math-enable-subst
696 (not math-any-substs))
697 math-integ-level
698 'cancelled)))))
699 (setq val cur-record)
700 (while (vectorp (nth 1 val))
701 (setq val (aref (nth 1 val) 0)))
702 (setq val (if (memq (nth 1 val) '(parts parts2))
703 (progn
704 (setcar (cdr val) 'parts2)
705 (list 'var 'PARTS val))
706 (and (consp (nth 1 val))
707 (nth 1 val))))
708 (math-tracing-integral "Integral of "
709 (math-format-value expr 1000)
710 " is "
711 (math-format-value val 1000)
712 "\n")
713 val))
714 (defvar math-integral-cache nil)
715 (defvar math-integral-cache-state nil)
717 (defun math-integral-contains-parts (expr)
718 (if (Math-primp expr)
719 (and (eq (car-safe expr) 'var)
720 (eq (nth 1 expr) 'PARTS)
721 (listp (nth 2 expr)))
722 (while (and (setq expr (cdr expr))
723 (not (math-integral-contains-parts (car expr)))))
724 expr))
726 (defun math-replace-integral-parts (expr)
727 (or (Math-primp expr)
728 (while (setq expr (cdr expr))
729 (and (consp (car expr))
730 (if (eq (car (car expr)) 'var)
731 (and (eq (nth 1 (car expr)) 'PARTS)
732 (consp (nth 2 (car expr)))
733 (if (listp (nth 1 (nth 2 (car expr))))
734 (progn
735 (setcar expr (nth 1 (nth 2 (car expr))))
736 (math-replace-integral-parts (cons 'foo expr)))
737 (setcar (cdr cur-record) 'cancelled)))
738 (math-replace-integral-parts (car expr)))))))
740 (defun math-do-integral (expr)
741 (let (t1 t2)
742 (or (cond ((not (math-expr-contains expr math-integ-var))
743 (math-mul expr math-integ-var))
744 ((equal expr math-integ-var)
745 (math-div (math-sqr expr) 2))
746 ((eq (car expr) '+)
747 (and (setq t1 (math-integral (nth 1 expr)))
748 (setq t2 (math-integral (nth 2 expr)))
749 (math-add t1 t2)))
750 ((eq (car expr) '-)
751 (and (setq t1 (math-integral (nth 1 expr)))
752 (setq t2 (math-integral (nth 2 expr)))
753 (math-sub t1 t2)))
754 ((eq (car expr) 'neg)
755 (and (setq t1 (math-integral (nth 1 expr)))
756 (math-neg t1)))
757 ((eq (car expr) '*)
758 (cond ((not (math-expr-contains (nth 1 expr) math-integ-var))
759 (and (setq t1 (math-integral (nth 2 expr)))
760 (math-mul (nth 1 expr) t1)))
761 ((not (math-expr-contains (nth 2 expr) math-integ-var))
762 (and (setq t1 (math-integral (nth 1 expr)))
763 (math-mul t1 (nth 2 expr))))
764 ((memq (car-safe (nth 1 expr)) '(+ -))
765 (math-integral (list (car (nth 1 expr))
766 (math-mul (nth 1 (nth 1 expr))
767 (nth 2 expr))
768 (math-mul (nth 2 (nth 1 expr))
769 (nth 2 expr)))
770 'yes t))
771 ((memq (car-safe (nth 2 expr)) '(+ -))
772 (math-integral (list (car (nth 2 expr))
773 (math-mul (nth 1 (nth 2 expr))
774 (nth 1 expr))
775 (math-mul (nth 2 (nth 2 expr))
776 (nth 1 expr)))
777 'yes t))))
778 ((eq (car expr) '/)
779 (cond ((and (not (math-expr-contains (nth 1 expr)
780 math-integ-var))
781 (not (math-equal-int (nth 1 expr) 1)))
782 (and (setq t1 (math-integral (math-div 1 (nth 2 expr))))
783 (math-mul (nth 1 expr) t1)))
784 ((not (math-expr-contains (nth 2 expr) math-integ-var))
785 (and (setq t1 (math-integral (nth 1 expr)))
786 (math-div t1 (nth 2 expr))))
787 ((and (eq (car-safe (nth 1 expr)) '*)
788 (not (math-expr-contains (nth 1 (nth 1 expr))
789 math-integ-var)))
790 (and (setq t1 (math-integral
791 (math-div (nth 2 (nth 1 expr))
792 (nth 2 expr))))
793 (math-mul t1 (nth 1 (nth 1 expr)))))
794 ((and (eq (car-safe (nth 1 expr)) '*)
795 (not (math-expr-contains (nth 2 (nth 1 expr))
796 math-integ-var)))
797 (and (setq t1 (math-integral
798 (math-div (nth 1 (nth 1 expr))
799 (nth 2 expr))))
800 (math-mul t1 (nth 2 (nth 1 expr)))))
801 ((and (eq (car-safe (nth 2 expr)) '*)
802 (not (math-expr-contains (nth 1 (nth 2 expr))
803 math-integ-var)))
804 (and (setq t1 (math-integral
805 (math-div (nth 1 expr)
806 (nth 2 (nth 2 expr)))))
807 (math-div t1 (nth 1 (nth 2 expr)))))
808 ((and (eq (car-safe (nth 2 expr)) '*)
809 (not (math-expr-contains (nth 2 (nth 2 expr))
810 math-integ-var)))
811 (and (setq t1 (math-integral
812 (math-div (nth 1 expr)
813 (nth 1 (nth 2 expr)))))
814 (math-div t1 (nth 2 (nth 2 expr)))))
815 ((eq (car-safe (nth 2 expr)) 'calcFunc-exp)
816 (math-integral
817 (math-mul (nth 1 expr)
818 (list 'calcFunc-exp
819 (math-neg (nth 1 (nth 2 expr)))))))))
820 ((eq (car expr) '^)
821 (cond ((not (math-expr-contains (nth 1 expr) math-integ-var))
822 (or (and (setq t1 (math-is-polynomial (nth 2 expr)
823 math-integ-var 1))
824 (math-div expr
825 (math-mul (nth 1 t1)
826 (math-normalize
827 (list 'calcFunc-ln
828 (nth 1 expr))))))
829 (math-integral
830 (list 'calcFunc-exp
831 (math-mul (nth 2 expr)
832 (math-normalize
833 (list 'calcFunc-ln
834 (nth 1 expr)))))
835 'yes t)))
836 ((not (math-expr-contains (nth 2 expr) math-integ-var))
837 (if (and (integerp (nth 2 expr)) (< (nth 2 expr) 0))
838 (math-integral
839 (list '/ 1 (math-pow (nth 1 expr) (- (nth 2 expr))))
840 nil t)
841 (or (and (setq t1 (math-is-polynomial (nth 1 expr)
842 math-integ-var
844 (setq t2 (math-add (nth 2 expr) 1))
845 (math-div (math-pow (nth 1 expr) t2)
846 (math-mul t2 (nth 1 t1))))
847 (and (Math-negp (nth 2 expr))
848 (math-integral
849 (math-div 1
850 (math-pow (nth 1 expr)
851 (math-neg
852 (nth 2 expr))))
853 nil t))
854 nil))))))
856 ;; Integral of a polynomial.
857 (and (setq t1 (math-is-polynomial expr math-integ-var 20))
858 (let ((accum 0)
859 (n 1))
860 (while t1
861 (if (setq accum (math-add accum
862 (math-div (math-mul (car t1)
863 (math-pow
864 math-integ-var
867 t1 (cdr t1))
868 (setq n (1+ n))))
869 accum))
871 ;; Try looking it up!
872 (cond ((= (length expr) 2)
873 (and (symbolp (car expr))
874 (setq t1 (get (car expr) 'math-integral))
875 (progn
876 (while (and t1
877 (not (setq t2 (funcall (car t1)
878 (nth 1 expr)))))
879 (setq t1 (cdr t1)))
880 (and t2 (math-normalize t2)))))
881 ((= (length expr) 3)
882 (and (symbolp (car expr))
883 (setq t1 (get (car expr) 'math-integral-2))
884 (progn
885 (while (and t1
886 (not (setq t2 (funcall (car t1)
887 (nth 1 expr)
888 (nth 2 expr)))))
889 (setq t1 (cdr t1)))
890 (and t2 (math-normalize t2))))))
892 ;; Integral of a rational function.
893 (and (math-ratpoly-p expr math-integ-var)
894 (setq t1 (calcFunc-apart expr math-integ-var))
895 (not (equal t1 expr))
896 (math-integral t1))
898 ;; Try user-defined integration rules.
899 (and has-rules
900 (let ((math-old-integ (symbol-function 'calcFunc-integ))
901 (input (list 'calcFunc-integtry expr math-integ-var))
902 res part)
903 (unwind-protect
904 (progn
905 (fset 'calcFunc-integ 'math-sub-integration)
906 (setq res (math-rewrite input
907 '(var IntegRules var-IntegRules)
909 (fset 'calcFunc-integ math-old-integ)
910 (and (not (equal res input))
911 (if (setq part (math-expr-calls
912 res '(calcFunc-integsubst)))
913 (and (memq (length part) '(3 4 5))
914 (let ((parts (mapcar
915 (function
916 (lambda (x)
917 (math-expr-subst
918 x (nth 2 part)
919 math-integ-var)))
920 (cdr part))))
921 (math-integrate-by-substitution
922 expr (car parts) t
923 (or (nth 2 parts)
924 (list 'calcFunc-integfailed
925 math-integ-var))
926 (nth 3 parts))))
927 (if (not (math-expr-calls res
928 '(calcFunc-integtry
929 calcFunc-integfailed)))
930 res))))
931 (fset 'calcFunc-integ math-old-integ))))
933 ;; See if the function is a symbolic derivative.
934 (and (string-match "'" (symbol-name (car expr)))
935 (let ((name (symbol-name (car expr)))
936 (p expr) (n 0) (which nil) (bad nil))
937 (while (setq n (1+ n) p (cdr p))
938 (if (equal (car p) math-integ-var)
939 (if which (setq bad t) (setq which n))
940 (if (math-expr-contains (car p) math-integ-var)
941 (setq bad t))))
942 (and which (not bad)
943 (let ((prime (if (= which 1) "'" (format "'%d" which))))
944 (and (string-match (concat prime "\\('['0-9]*\\|$\\)")
945 name)
946 (cons (intern
947 (concat
948 (substring name 0 (match-beginning 0))
949 (substring name (+ (match-beginning 0)
950 (length prime)))))
951 (cdr expr)))))))
953 ;; Try transformation methods (parts, substitutions).
954 (and (> math-integ-level 0)
955 (math-do-integral-methods expr))
957 ;; Try expanding the function's definition.
958 (let ((res (math-expand-formula expr)))
959 (and res
960 (math-integral res))))))
962 (defun math-sub-integration (expr &rest rest)
963 (or (if (or (not rest)
964 (and (< math-integ-level math-integral-limit)
965 (eq (car rest) math-integ-var)))
966 (math-integral expr)
967 (let ((res (apply math-old-integ expr rest)))
968 (and (or (= math-integ-level math-integral-limit)
969 (not (math-expr-calls res 'calcFunc-integ)))
970 res)))
971 (list 'calcFunc-integfailed expr)))
973 (defun math-do-integral-methods (expr)
974 (let ((so-far math-integ-var-list-list)
975 rat-in)
977 ;; Integration by substitution, for various likely sub-expressions.
978 ;; (In first pass, we look only for sub-exprs that are linear in X.)
979 (or (if math-enable-subst
980 (math-integ-try-substitutions expr)
981 (math-integ-try-linear-substitutions expr))
983 ;; If function has sines and cosines, try tan(x/2) substitution.
984 (and (let ((p (setq rat-in (math-expr-rational-in expr))))
985 (while (and p
986 (memq (car (car p)) '(calcFunc-sin
987 calcFunc-cos
988 calcFunc-tan))
989 (equal (nth 1 (car p)) math-integ-var))
990 (setq p (cdr p)))
991 (null p))
992 (or (and (math-integ-parts-easy expr)
993 (math-integ-try-parts expr t))
994 (math-integrate-by-good-substitution
995 expr (list 'calcFunc-tan (math-div math-integ-var 2)))))
997 ;; If function has sinh and cosh, try tanh(x/2) substitution.
998 (and (let ((p rat-in))
999 (while (and p
1000 (memq (car (car p)) '(calcFunc-sinh
1001 calcFunc-cosh
1002 calcFunc-tanh
1003 calcFunc-exp))
1004 (equal (nth 1 (car p)) math-integ-var))
1005 (setq p (cdr p)))
1006 (null p))
1007 (or (and (math-integ-parts-easy expr)
1008 (math-integ-try-parts expr t))
1009 (math-integrate-by-good-substitution
1010 expr (list 'calcFunc-tanh (math-div math-integ-var 2)))))
1012 ;; If function has square roots, try sin, tan, or sec substitution.
1013 (and (let ((p rat-in))
1014 (setq t1 nil)
1015 (while (and p
1016 (or (equal (car p) math-integ-var)
1017 (and (eq (car (car p)) 'calcFunc-sqrt)
1018 (setq t1 (math-is-polynomial
1019 (nth 1 (setq t2 (car p)))
1020 math-integ-var 2)))))
1021 (setq p (cdr p)))
1022 (and (null p) t1))
1023 (if (cdr (cdr t1))
1024 (if (math-guess-if-neg (nth 2 t1))
1025 (let* ((c (math-sqrt (math-neg (nth 2 t1))))
1026 (d (math-div (nth 1 t1) (math-mul -2 c)))
1027 (a (math-sqrt (math-add (car t1) (math-sqr d)))))
1028 (math-integrate-by-good-substitution
1029 expr (list 'calcFunc-arcsin
1030 (math-div-thru
1031 (math-add (math-mul c math-integ-var) d)
1032 a))))
1033 (let* ((c (math-sqrt (nth 2 t1)))
1034 (d (math-div (nth 1 t1) (math-mul 2 c)))
1035 (aa (math-sub (car t1) (math-sqr d))))
1036 (if (and nil (not (and (eq d 0) (eq c 1))))
1037 (math-integrate-by-good-substitution
1038 expr (math-add (math-mul c math-integ-var) d))
1039 (if (math-guess-if-neg aa)
1040 (math-integrate-by-good-substitution
1041 expr (list 'calcFunc-arccosh
1042 (math-div-thru
1043 (math-add (math-mul c math-integ-var)
1045 (math-sqrt (math-neg aa)))))
1046 (math-integrate-by-good-substitution
1047 expr (list 'calcFunc-arcsinh
1048 (math-div-thru
1049 (math-add (math-mul c math-integ-var)
1051 (math-sqrt aa))))))))
1052 (math-integrate-by-good-substitution expr t2)) )
1054 ;; Try integration by parts.
1055 (math-integ-try-parts expr)
1057 ;; Give up.
1058 nil)))
1060 (defun math-integ-parts-easy (expr)
1061 (cond ((Math-primp expr) t)
1062 ((memq (car expr) '(+ - *))
1063 (and (math-integ-parts-easy (nth 1 expr))
1064 (math-integ-parts-easy (nth 2 expr))))
1065 ((eq (car expr) '/)
1066 (and (math-integ-parts-easy (nth 1 expr))
1067 (math-atomic-factorp (nth 2 expr))))
1068 ((eq (car expr) '^)
1069 (and (natnump (nth 2 expr))
1070 (math-integ-parts-easy (nth 1 expr))))
1071 ((eq (car expr) 'neg)
1072 (math-integ-parts-easy (nth 1 expr)))
1073 (t t)))
1075 (defun math-integ-try-parts (expr &optional math-good-parts)
1076 ;; Integration by parts:
1077 ;; integ(f(x) g(x),x) = f(x) h(x) - integ(h(x) f'(x),x)
1078 ;; where h(x) = integ(g(x),x).
1079 (or (let ((exp (calcFunc-expand expr)))
1080 (and (not (equal exp expr))
1081 (math-integral exp)))
1082 (and (eq (car expr) '*)
1083 (let ((first-bad (or (math-polynomial-p (nth 1 expr)
1084 math-integ-var)
1085 (equal (nth 2 expr) math-prev-parts-v))))
1086 (or (and first-bad ; so try this one first
1087 (math-integrate-by-parts (nth 1 expr) (nth 2 expr)))
1088 (math-integrate-by-parts (nth 2 expr) (nth 1 expr))
1089 (and (not first-bad)
1090 (math-integrate-by-parts (nth 1 expr) (nth 2 expr))))))
1091 (and (eq (car expr) '/)
1092 (math-expr-contains (nth 1 expr) math-integ-var)
1093 (let ((recip (math-div 1 (nth 2 expr))))
1094 (or (math-integrate-by-parts (nth 1 expr) recip)
1095 (math-integrate-by-parts recip (nth 1 expr)))))
1096 (and (eq (car expr) '^)
1097 (math-integrate-by-parts (math-pow (nth 1 expr)
1098 (math-sub (nth 2 expr) 1))
1099 (nth 1 expr)))))
1101 (defun math-integrate-by-parts (u vprime)
1102 (let ((math-integ-level (if (or math-good-parts
1103 (math-polynomial-p u math-integ-var))
1104 math-integ-level
1105 (1- math-integ-level)))
1106 (math-doing-parts t)
1107 v temp)
1108 (and (>= math-integ-level 0)
1109 (unwind-protect
1110 (progn
1111 (setcar (cdr cur-record) 'parts)
1112 (math-tracing-integral "Integrating by parts, u = "
1113 (math-format-value u 1000)
1114 ", v' = "
1115 (math-format-value vprime 1000)
1116 "\n")
1117 (and (setq v (math-integral vprime))
1118 (setq temp (calcFunc-deriv u math-integ-var nil t))
1119 (setq temp (let ((math-prev-parts-v v))
1120 (math-integral (math-mul v temp) 'yes)))
1121 (setq temp (math-sub (math-mul u v) temp))
1122 (if (eq (nth 1 cur-record) 'parts)
1123 (calcFunc-expand temp)
1124 (setq v (list 'var 'PARTS cur-record)
1125 var-thing (list 'vec (math-sub v temp) v)
1126 temp (let (calc-next-why)
1127 (math-solve-for (math-sub v temp) 0 v nil)))
1128 (and temp (not (integerp temp))
1129 (math-simplify-extended temp)))))
1130 (setcar (cdr cur-record) 'busy)))))
1132 ;;; This tries two different formulations, hoping the algebraic simplifier
1133 ;;; will be strong enough to handle at least one.
1134 (defun math-integrate-by-substitution (expr u &optional user uinv uinvprime)
1135 (and (> math-integ-level 0)
1136 (let ((math-integ-level (max (- math-integ-level 2) 0)))
1137 (math-integrate-by-good-substitution expr u user uinv uinvprime))))
1139 (defun math-integrate-by-good-substitution (expr u &optional user
1140 uinv uinvprime)
1141 (let ((math-living-dangerously t)
1142 deriv temp)
1143 (and (setq uinv (if uinv
1144 (math-expr-subst uinv math-integ-var
1145 math-integ-var-2)
1146 (let (calc-next-why)
1147 (math-solve-for u
1148 math-integ-var-2
1149 math-integ-var nil))))
1150 (progn
1151 (math-tracing-integral "Integrating by substitution, u = "
1152 (math-format-value u 1000)
1153 "\n")
1154 (or (and (setq deriv (calcFunc-deriv u
1155 math-integ-var nil
1156 (not user)))
1157 (setq temp (math-integral (math-expr-subst
1158 (math-expr-subst
1159 (math-expr-subst
1160 (math-div expr deriv)
1162 math-integ-var-2)
1163 math-integ-var
1164 uinv)
1165 math-integ-var-2
1166 math-integ-var)
1167 'yes)))
1168 (and (setq deriv (or uinvprime
1169 (calcFunc-deriv uinv
1170 math-integ-var-2
1171 math-integ-var
1172 (not user))))
1173 (setq temp (math-integral (math-mul
1174 (math-expr-subst
1175 (math-expr-subst
1176 (math-expr-subst
1177 expr
1179 math-integ-var-2)
1180 math-integ-var
1181 uinv)
1182 math-integ-var-2
1183 math-integ-var)
1184 deriv)
1185 'yes)))))
1186 (math-simplify-extended
1187 (math-expr-subst temp math-integ-var u)))))
1189 ;;; Look for substitutions of the form u = a x + b.
1190 (defun math-integ-try-linear-substitutions (sub-expr)
1191 (and (not (Math-primp sub-expr))
1192 (or (and (not (memq (car sub-expr) '(+ - * / neg)))
1193 (not (and (eq (car sub-expr) '^)
1194 (integerp (nth 2 sub-expr))))
1195 (math-expr-contains sub-expr math-integ-var)
1196 (let ((res nil))
1197 (while (and (setq sub-expr (cdr sub-expr))
1198 (or (not (math-linear-in (car sub-expr)
1199 math-integ-var))
1200 (assoc (car sub-expr) so-far)
1201 (progn
1202 (setq so-far (cons (list (car sub-expr))
1203 so-far))
1204 (not (setq res
1205 (math-integrate-by-substitution
1206 expr (car sub-expr))))))))
1207 res))
1208 (let ((res nil))
1209 (while (and (setq sub-expr (cdr sub-expr))
1210 (not (setq res (math-integ-try-linear-substitutions
1211 (car sub-expr))))))
1212 res))))
1214 ;;; Recursively try different substitutions based on various sub-expressions.
1215 (defun math-integ-try-substitutions (sub-expr &optional allow-rat)
1216 (and (not (Math-primp sub-expr))
1217 (not (assoc sub-expr so-far))
1218 (math-expr-contains sub-expr math-integ-var)
1219 (or (and (if (and (not (memq (car sub-expr) '(+ - * / neg)))
1220 (not (and (eq (car sub-expr) '^)
1221 (integerp (nth 2 sub-expr)))))
1222 (setq allow-rat t)
1223 (prog1 allow-rat (setq allow-rat nil)))
1224 (not (eq sub-expr expr))
1225 (or (math-integrate-by-substitution expr sub-expr)
1226 (and (eq (car sub-expr) '^)
1227 (integerp (nth 2 sub-expr))
1228 (< (nth 2 sub-expr) 0)
1229 (math-integ-try-substitutions
1230 (math-pow (nth 1 sub-expr) (- (nth 2 sub-expr)))
1231 t))))
1232 (let ((res nil))
1233 (setq so-far (cons (list sub-expr) so-far))
1234 (while (and (setq sub-expr (cdr sub-expr))
1235 (not (setq res (math-integ-try-substitutions
1236 (car sub-expr) allow-rat)))))
1237 res))))
1239 (defun math-expr-rational-in (expr)
1240 (let ((parts nil))
1241 (math-expr-rational-in-rec expr)
1242 (mapcar 'car parts)))
1244 (defun math-expr-rational-in-rec (expr)
1245 (cond ((Math-primp expr)
1246 (and (equal expr math-integ-var)
1247 (not (assoc expr parts))
1248 (setq parts (cons (list expr) parts))))
1249 ((or (memq (car expr) '(+ - * / neg))
1250 (and (eq (car expr) '^) (integerp (nth 2 expr))))
1251 (math-expr-rational-in-rec (nth 1 expr))
1252 (and (nth 2 expr) (math-expr-rational-in-rec (nth 2 expr))))
1253 ((and (eq (car expr) '^)
1254 (eq (math-quarter-integer (nth 2 expr)) 2))
1255 (math-expr-rational-in-rec (list 'calcFunc-sqrt (nth 1 expr))))
1257 (and (not (assoc expr parts))
1258 (math-expr-contains expr math-integ-var)
1259 (setq parts (cons (list expr) parts))))))
1261 (defun math-expr-calls (expr funcs &optional arg-contains)
1262 (if (consp expr)
1263 (if (or (memq (car expr) funcs)
1264 (and (eq (car expr) '^) (eq (car funcs) 'calcFunc-sqrt)
1265 (eq (math-quarter-integer (nth 2 expr)) 2)))
1266 (and (or (not arg-contains)
1267 (math-expr-contains expr arg-contains))
1268 expr)
1269 (and (not (Math-primp expr))
1270 (let ((res nil))
1271 (while (and (setq expr (cdr expr))
1272 (not (setq res (math-expr-calls
1273 (car expr) funcs arg-contains)))))
1274 res)))))
1276 (defun math-fix-const-terms (expr except-vars)
1277 (cond ((not (math-expr-depends expr except-vars)) 0)
1278 ((Math-primp expr) expr)
1279 ((eq (car expr) '+)
1280 (math-add (math-fix-const-terms (nth 1 expr) except-vars)
1281 (math-fix-const-terms (nth 2 expr) except-vars)))
1282 ((eq (car expr) '-)
1283 (math-sub (math-fix-const-terms (nth 1 expr) except-vars)
1284 (math-fix-const-terms (nth 2 expr) except-vars)))
1285 (t expr)))
1287 ;; Command for debugging the Calculator's symbolic integrator.
1288 (defun calc-dump-integral-cache (&optional arg)
1289 (interactive "P")
1290 (let ((buf (current-buffer)))
1291 (unwind-protect
1292 (let ((p math-integral-cache)
1293 cur-record)
1294 (display-buffer (get-buffer-create "*Integral Cache*"))
1295 (set-buffer (get-buffer "*Integral Cache*"))
1296 (erase-buffer)
1297 (while p
1298 (setq cur-record (car p))
1299 (or arg (math-replace-integral-parts cur-record))
1300 (insert (math-format-flat-expr (car cur-record) 0)
1301 " --> "
1302 (if (symbolp (nth 1 cur-record))
1303 (concat "(" (symbol-name (nth 1 cur-record)) ")")
1304 (math-format-flat-expr (nth 1 cur-record) 0))
1305 "\n")
1306 (setq p (cdr p)))
1307 (goto-char (point-min)))
1308 (set-buffer buf))))
1310 (defun math-try-integral (expr)
1311 (let ((math-integ-level math-integral-limit)
1312 (math-integ-depth 0)
1313 (math-integ-msg "Working...done")
1314 (cur-record nil) ; a technicality
1315 (math-integrating t)
1316 (calc-prefer-frac t)
1317 (calc-symbolic-mode t)
1318 (has-rules (calc-has-rules 'var-IntegRules)))
1319 (or (math-integral expr 'yes)
1320 (and math-any-substs
1321 (setq math-enable-subst t)
1322 (math-integral expr 'yes))
1323 (and (> math-max-integral-limit math-integral-limit)
1324 (setq math-integral-limit math-max-integral-limit
1325 math-integ-level math-integral-limit)
1326 (math-integral expr 'yes)))))
1328 (defun calcFunc-integ (expr var &optional low high)
1329 (cond
1330 ;; Do these even if the parts turn out not to be integrable.
1331 ((eq (car-safe expr) '+)
1332 (math-add (calcFunc-integ (nth 1 expr) var low high)
1333 (calcFunc-integ (nth 2 expr) var low high)))
1334 ((eq (car-safe expr) '-)
1335 (math-sub (calcFunc-integ (nth 1 expr) var low high)
1336 (calcFunc-integ (nth 2 expr) var low high)))
1337 ((eq (car-safe expr) 'neg)
1338 (math-neg (calcFunc-integ (nth 1 expr) var low high)))
1339 ((and (eq (car-safe expr) '*)
1340 (not (math-expr-contains (nth 1 expr) var)))
1341 (math-mul (nth 1 expr) (calcFunc-integ (nth 2 expr) var low high)))
1342 ((and (eq (car-safe expr) '*)
1343 (not (math-expr-contains (nth 2 expr) var)))
1344 (math-mul (calcFunc-integ (nth 1 expr) var low high) (nth 2 expr)))
1345 ((and (eq (car-safe expr) '/)
1346 (not (math-expr-contains (nth 1 expr) var))
1347 (not (math-equal-int (nth 1 expr) 1)))
1348 (math-mul (nth 1 expr)
1349 (calcFunc-integ (math-div 1 (nth 2 expr)) var low high)))
1350 ((and (eq (car-safe expr) '/)
1351 (not (math-expr-contains (nth 2 expr) var)))
1352 (math-div (calcFunc-integ (nth 1 expr) var low high) (nth 2 expr)))
1353 ((and (eq (car-safe expr) '/)
1354 (eq (car-safe (nth 1 expr)) '*)
1355 (not (math-expr-contains (nth 1 (nth 1 expr)) var)))
1356 (math-mul (nth 1 (nth 1 expr))
1357 (calcFunc-integ (math-div (nth 2 (nth 1 expr)) (nth 2 expr))
1358 var low high)))
1359 ((and (eq (car-safe expr) '/)
1360 (eq (car-safe (nth 1 expr)) '*)
1361 (not (math-expr-contains (nth 2 (nth 1 expr)) var)))
1362 (math-mul (nth 2 (nth 1 expr))
1363 (calcFunc-integ (math-div (nth 1 (nth 1 expr)) (nth 2 expr))
1364 var low high)))
1365 ((and (eq (car-safe expr) '/)
1366 (eq (car-safe (nth 2 expr)) '*)
1367 (not (math-expr-contains (nth 1 (nth 2 expr)) var)))
1368 (math-div (calcFunc-integ (math-div (nth 1 expr) (nth 2 (nth 2 expr)))
1369 var low high)
1370 (nth 1 (nth 2 expr))))
1371 ((and (eq (car-safe expr) '/)
1372 (eq (car-safe (nth 2 expr)) '*)
1373 (not (math-expr-contains (nth 2 (nth 2 expr)) var)))
1374 (math-div (calcFunc-integ (math-div (nth 1 expr) (nth 1 (nth 2 expr)))
1375 var low high)
1376 (nth 2 (nth 2 expr))))
1377 ((eq (car-safe expr) 'vec)
1378 (cons 'vec (mapcar (function (lambda (x) (calcFunc-integ x var low high)))
1379 (cdr expr))))
1381 (let ((state (list calc-angle-mode
1382 ;;calc-symbolic-mode
1383 ;;calc-prefer-frac
1384 calc-internal-prec
1385 (calc-var-value 'var-IntegRules)
1386 (calc-var-value 'var-IntegSimpRules))))
1387 (or (equal state math-integral-cache-state)
1388 (setq math-integral-cache-state state
1389 math-integral-cache nil)))
1390 (let* ((math-max-integral-limit (or (and (boundp 'var-IntegLimit)
1391 (natnump var-IntegLimit)
1392 var-IntegLimit)
1394 (math-integral-limit 1)
1395 (sexpr (math-expr-subst expr var math-integ-var))
1396 (trace-buffer (get-buffer "*Trace*"))
1397 (calc-language (if (eq calc-language 'big) nil calc-language))
1398 (math-any-substs t)
1399 (math-enable-subst nil)
1400 (math-prev-parts-v nil)
1401 (math-doing-parts nil)
1402 (math-good-parts nil)
1403 (res
1404 (if trace-buffer
1405 (let ((calcbuf (current-buffer))
1406 (calcwin (selected-window)))
1407 (unwind-protect
1408 (progn
1409 (if (get-buffer-window trace-buffer)
1410 (select-window (get-buffer-window trace-buffer)))
1411 (set-buffer trace-buffer)
1412 (goto-char (point-max))
1413 (or (assq 'scroll-stop (buffer-local-variables))
1414 (progn
1415 (make-local-variable 'scroll-step)
1416 (setq scroll-step 3)))
1417 (insert "\n\n\n")
1418 (set-buffer calcbuf)
1419 (math-try-integral sexpr))
1420 (select-window calcwin)
1421 (set-buffer calcbuf)))
1422 (math-try-integral sexpr))))
1423 (if res
1424 (progn
1425 (if (calc-has-rules 'var-IntegAfterRules)
1426 (setq res (math-rewrite res '(var IntegAfterRules
1427 var-IntegAfterRules))))
1428 (math-simplify
1429 (if (and low high)
1430 (math-sub (math-expr-subst res math-integ-var high)
1431 (math-expr-subst res math-integ-var low))
1432 (setq res (math-fix-const-terms res math-integ-vars))
1433 (if low
1434 (math-expr-subst res math-integ-var low)
1435 (math-expr-subst res math-integ-var var)))))
1436 (append (list 'calcFunc-integ expr var)
1437 (and low (list low))
1438 (and high (list high))))))))
1441 (math-defintegral calcFunc-inv
1442 (math-integral (math-div 1 u)))
1444 (math-defintegral calcFunc-conj
1445 (let ((int (math-integral u)))
1446 (and int
1447 (list 'calcFunc-conj int))))
1449 (math-defintegral calcFunc-deg
1450 (let ((int (math-integral u)))
1451 (and int
1452 (list 'calcFunc-deg int))))
1454 (math-defintegral calcFunc-rad
1455 (let ((int (math-integral u)))
1456 (and int
1457 (list 'calcFunc-rad int))))
1459 (math-defintegral calcFunc-re
1460 (let ((int (math-integral u)))
1461 (and int
1462 (list 'calcFunc-re int))))
1464 (math-defintegral calcFunc-im
1465 (let ((int (math-integral u)))
1466 (and int
1467 (list 'calcFunc-im int))))
1469 (math-defintegral calcFunc-sqrt
1470 (and (equal u math-integ-var)
1471 (math-mul '(frac 2 3)
1472 (list 'calcFunc-sqrt (math-pow u 3)))))
1474 (math-defintegral calcFunc-exp
1475 (or (and (equal u math-integ-var)
1476 (list 'calcFunc-exp u))
1477 (let ((p (math-is-polynomial u math-integ-var 2)))
1478 (and (nth 2 p)
1479 (let ((sqa (math-sqrt (math-neg (nth 2 p)))))
1480 (math-div
1481 (math-mul
1482 (math-mul (math-div (list 'calcFunc-sqrt '(var pi var-pi))
1483 sqa)
1484 (math-normalize
1485 (list 'calcFunc-exp
1486 (math-div (math-sub (math-mul (car p)
1487 (nth 2 p))
1488 (math-div
1489 (math-sqr (nth 1 p))
1491 (nth 2 p)))))
1492 (list 'calcFunc-erf
1493 (math-sub (math-mul sqa math-integ-var)
1494 (math-div (nth 1 p) (math-mul 2 sqa)))))
1495 2))))))
1497 (math-defintegral calcFunc-ln
1498 (or (and (equal u math-integ-var)
1499 (math-sub (math-mul u (list 'calcFunc-ln u)) u))
1500 (and (eq (car u) '*)
1501 (math-integral (math-add (list 'calcFunc-ln (nth 1 u))
1502 (list 'calcFunc-ln (nth 2 u)))))
1503 (and (eq (car u) '/)
1504 (math-integral (math-sub (list 'calcFunc-ln (nth 1 u))
1505 (list 'calcFunc-ln (nth 2 u)))))
1506 (and (eq (car u) '^)
1507 (math-integral (math-mul (nth 2 u)
1508 (list 'calcFunc-ln (nth 1 u)))))))
1510 (math-defintegral calcFunc-log10
1511 (and (equal u math-integ-var)
1512 (math-sub (math-mul u (list 'calcFunc-ln u))
1513 (math-div u (list 'calcFunc-ln 10)))))
1515 (math-defintegral-2 calcFunc-log
1516 (math-integral (math-div (list 'calcFunc-ln u)
1517 (list 'calcFunc-ln v))))
1519 (math-defintegral calcFunc-sin
1520 (or (and (equal u math-integ-var)
1521 (math-neg (math-from-radians-2 (list 'calcFunc-cos u))))
1522 (and (nth 2 (math-is-polynomial u math-integ-var 2))
1523 (math-integral (math-to-exponentials (list 'calcFunc-sin u))))))
1525 (math-defintegral calcFunc-cos
1526 (or (and (equal u math-integ-var)
1527 (math-from-radians-2 (list 'calcFunc-sin u)))
1528 (and (nth 2 (math-is-polynomial u math-integ-var 2))
1529 (math-integral (math-to-exponentials (list 'calcFunc-cos u))))))
1531 (math-defintegral calcFunc-tan
1532 (and (equal u math-integ-var)
1533 (math-neg (math-from-radians-2
1534 (list 'calcFunc-ln (list 'calcFunc-cos u))))))
1536 (math-defintegral calcFunc-arcsin
1537 (and (equal u math-integ-var)
1538 (math-add (math-mul u (list 'calcFunc-arcsin u))
1539 (math-from-radians-2
1540 (list 'calcFunc-sqrt (math-sub 1 (math-sqr u)))))))
1542 (math-defintegral calcFunc-arccos
1543 (and (equal u math-integ-var)
1544 (math-sub (math-mul u (list 'calcFunc-arccos u))
1545 (math-from-radians-2
1546 (list 'calcFunc-sqrt (math-sub 1 (math-sqr u)))))))
1548 (math-defintegral calcFunc-arctan
1549 (and (equal u math-integ-var)
1550 (math-sub (math-mul u (list 'calcFunc-arctan u))
1551 (math-from-radians-2
1552 (math-div (list 'calcFunc-ln (math-add 1 (math-sqr u)))
1553 2)))))
1555 (math-defintegral calcFunc-sinh
1556 (and (equal u math-integ-var)
1557 (list 'calcFunc-cosh u)))
1559 (math-defintegral calcFunc-cosh
1560 (and (equal u math-integ-var)
1561 (list 'calcFunc-sinh u)))
1563 (math-defintegral calcFunc-tanh
1564 (and (equal u math-integ-var)
1565 (list 'calcFunc-ln (list 'calcFunc-cosh u))))
1567 (math-defintegral calcFunc-arcsinh
1568 (and (equal u math-integ-var)
1569 (math-sub (math-mul u (list 'calcFunc-arcsinh u))
1570 (list 'calcFunc-sqrt (math-add (math-sqr u) 1)))))
1572 (math-defintegral calcFunc-arccosh
1573 (and (equal u math-integ-var)
1574 (math-sub (math-mul u (list 'calcFunc-arccosh u))
1575 (list 'calcFunc-sqrt (math-sub 1 (math-sqr u))))))
1577 (math-defintegral calcFunc-arctanh
1578 (and (equal u math-integ-var)
1579 (math-sub (math-mul u (list 'calcFunc-arctan u))
1580 (math-div (list 'calcFunc-ln
1581 (math-add 1 (math-sqr u)))
1582 2))))
1584 ;;; (Ax + B) / (ax^2 + bx + c)^n forms.
1585 (math-defintegral-2 /
1586 (math-integral-rational-funcs u v))
1588 (defun math-integral-rational-funcs (u v)
1589 (let ((pu (math-is-polynomial u math-integ-var 1))
1590 (vpow 1) pv)
1591 (and pu
1592 (catch 'int-rat
1593 (if (and (eq (car-safe v) '^) (natnump (nth 2 v)))
1594 (setq vpow (nth 2 v)
1595 v (nth 1 v)))
1596 (and (setq pv (math-is-polynomial v math-integ-var 2))
1597 (let ((int (math-mul-thru
1598 (car pu)
1599 (math-integral-q02 (car pv) (nth 1 pv)
1600 (nth 2 pv) v vpow))))
1601 (if (cdr pu)
1602 (setq int (math-add int
1603 (math-mul-thru
1604 (nth 1 pu)
1605 (math-integral-q12
1606 (car pv) (nth 1 pv)
1607 (nth 2 pv) v vpow)))))
1608 int))))))
1610 (defun math-integral-q12 (a b c v vpow)
1611 (let (q)
1612 (cond ((not c)
1613 (cond ((= vpow 1)
1614 (math-sub (math-div math-integ-var b)
1615 (math-mul (math-div a (math-sqr b))
1616 (list 'calcFunc-ln v))))
1617 ((= vpow 2)
1618 (math-div (math-add (list 'calcFunc-ln v)
1619 (math-div a v))
1620 (math-sqr b)))
1622 (let ((nm1 (math-sub vpow 1))
1623 (nm2 (math-sub vpow 2)))
1624 (math-div (math-sub
1625 (math-div a (math-mul nm1 (math-pow v nm1)))
1626 (math-div 1 (math-mul nm2 (math-pow v nm2))))
1627 (math-sqr b))))))
1628 ((math-zerop
1629 (setq q (math-sub (math-mul 4 (math-mul a c)) (math-sqr b))))
1630 (let ((part (math-div b (math-mul 2 c))))
1631 (math-mul-thru (math-pow c vpow)
1632 (math-integral-q12 part 1 nil
1633 (math-add math-integ-var part)
1634 (* vpow 2)))))
1635 ((= vpow 1)
1636 (and (math-ratp q) (math-negp q)
1637 (let ((calc-symbolic-mode t))
1638 (math-ratp (math-sqrt (math-neg q))))
1639 (throw 'int-rat nil)) ; should have used calcFunc-apart first
1640 (math-sub (math-div (list 'calcFunc-ln v) (math-mul 2 c))
1641 (math-mul-thru (math-div b (math-mul 2 c))
1642 (math-integral-q02 a b c v 1))))
1644 (let ((n (1- vpow)))
1645 (math-sub (math-neg (math-div
1646 (math-add (math-mul b math-integ-var)
1647 (math-mul 2 a))
1648 (math-mul n (math-mul q (math-pow v n)))))
1649 (math-mul-thru (math-div (math-mul b (1- (* 2 n)))
1650 (math-mul n q))
1651 (math-integral-q02 a b c v n))))))))
1653 (defun math-integral-q02 (a b c v vpow)
1654 (let (q rq part)
1655 (cond ((not c)
1656 (cond ((= vpow 1)
1657 (math-div (list 'calcFunc-ln v) b))
1659 (math-div (math-pow v (- 1 vpow))
1660 (math-mul (- 1 vpow) b)))))
1661 ((math-zerop
1662 (setq q (math-sub (math-mul 4 (math-mul a c)) (math-sqr b))))
1663 (let ((part (math-div b (math-mul 2 c))))
1664 (math-mul-thru (math-pow c vpow)
1665 (math-integral-q02 part 1 nil
1666 (math-add math-integ-var part)
1667 (* vpow 2)))))
1668 ((progn
1669 (setq part (math-add (math-mul 2 (math-mul c math-integ-var)) b))
1670 (> vpow 1))
1671 (let ((n (1- vpow)))
1672 (math-add (math-div part (math-mul n (math-mul q (math-pow v n))))
1673 (math-mul-thru (math-div (math-mul (- (* 4 n) 2) c)
1674 (math-mul n q))
1675 (math-integral-q02 a b c v n)))))
1676 ((math-guess-if-neg q)
1677 (setq rq (list 'calcFunc-sqrt (math-neg q)))
1678 ;;(math-div-thru (list 'calcFunc-ln
1679 ;; (math-div (math-sub part rq)
1680 ;; (math-add part rq)))
1681 ;; rq)
1682 (math-div (math-mul -2 (list 'calcFunc-arctanh
1683 (math-div part rq)))
1684 rq))
1686 (setq rq (list 'calcFunc-sqrt q))
1687 (math-div (math-mul 2 (math-to-radians-2
1688 (list 'calcFunc-arctan
1689 (math-div part rq))))
1690 rq)))))
1693 (math-defintegral calcFunc-erf
1694 (and (equal u math-integ-var)
1695 (math-add (math-mul u (list 'calcFunc-erf u))
1696 (math-div 1 (math-mul (list 'calcFunc-exp (math-sqr u))
1697 (list 'calcFunc-sqrt
1698 '(var pi var-pi)))))))
1700 (math-defintegral calcFunc-erfc
1701 (and (equal u math-integ-var)
1702 (math-sub (math-mul u (list 'calcFunc-erfc u))
1703 (math-div 1 (math-mul (list 'calcFunc-exp (math-sqr u))
1704 (list 'calcFunc-sqrt
1705 '(var pi var-pi)))))))
1710 (defvar math-tabulate-initial nil)
1711 (defvar math-tabulate-function nil)
1712 (defun calcFunc-table (expr var &optional low high step)
1713 (or low (setq low '(neg (var inf var-inf)) high '(var inf var-inf)))
1714 (or high (setq high low low 1))
1715 (and (or (math-infinitep low) (math-infinitep high))
1716 (not step)
1717 (math-scan-for-limits expr))
1718 (and step (math-zerop step) (math-reject-arg step 'nonzerop))
1719 (let ((known (+ (if (Math-objectp low) 1 0)
1720 (if (Math-objectp high) 1 0)
1721 (if (or (null step) (Math-objectp step)) 1 0)))
1722 (count '(var inf var-inf))
1723 vec)
1724 (or (= known 2) ; handy optimization
1725 (equal high '(var inf var-inf))
1726 (progn
1727 (setq count (math-div (math-sub high low) (or step 1)))
1728 (or (Math-objectp count)
1729 (setq count (math-simplify count)))
1730 (if (Math-messy-integerp count)
1731 (setq count (math-trunc count)))))
1732 (if (Math-negp count)
1733 (setq count -1))
1734 (if (integerp count)
1735 (let ((var-DUMMY nil)
1736 (vec math-tabulate-initial)
1737 (math-working-step-2 (1+ count))
1738 (math-working-step 0))
1739 (setq expr (math-evaluate-expr
1740 (math-expr-subst expr var '(var DUMMY var-DUMMY))))
1741 (while (>= count 0)
1742 (setq math-working-step (1+ math-working-step)
1743 var-DUMMY low
1744 vec (cond ((eq math-tabulate-function 'calcFunc-sum)
1745 (math-add vec (math-evaluate-expr expr)))
1746 ((eq math-tabulate-function 'calcFunc-prod)
1747 (math-mul vec (math-evaluate-expr expr)))
1749 (cons (math-evaluate-expr expr) vec)))
1750 low (math-add low (or step 1))
1751 count (1- count)))
1752 (if math-tabulate-function
1754 (cons 'vec (nreverse vec))))
1755 (if (Math-integerp count)
1756 (calc-record-why 'fixnump high)
1757 (if (Math-num-integerp low)
1758 (if (Math-num-integerp high)
1759 (calc-record-why 'integerp step)
1760 (calc-record-why 'integerp high))
1761 (calc-record-why 'integerp low)))
1762 (append (list (or math-tabulate-function 'calcFunc-table)
1763 expr var)
1764 (and (not (and (equal low '(neg (var inf var-inf)))
1765 (equal high '(var inf var-inf))))
1766 (list low high))
1767 (and step (list step))))))
1769 (defun math-scan-for-limits (x)
1770 (cond ((Math-primp x))
1771 ((and (eq (car x) 'calcFunc-subscr)
1772 (Math-vectorp (nth 1 x))
1773 (math-expr-contains (nth 2 x) var))
1774 (let* ((calc-next-why nil)
1775 (low-val (math-solve-for (nth 2 x) 1 var nil))
1776 (high-val (math-solve-for (nth 2 x) (1- (length (nth 1 x)))
1777 var nil))
1778 temp)
1779 (and low-val (math-realp low-val)
1780 high-val (math-realp high-val))
1781 (and (Math-lessp high-val low-val)
1782 (setq temp low-val low-val high-val high-val temp))
1783 (setq low (math-max low (math-ceiling low-val))
1784 high (math-min high (math-floor high-val)))))
1786 (while (setq x (cdr x))
1787 (math-scan-for-limits (car x))))))
1790 (defvar math-disable-sums nil)
1791 (defun calcFunc-sum (expr var &optional low high step)
1792 (if math-disable-sums (math-reject-arg))
1793 (let* ((res (let* ((calc-internal-prec (+ calc-internal-prec 2)))
1794 (math-sum-rec expr var low high step)))
1795 (math-disable-sums t))
1796 (math-normalize res)))
1798 (defun math-sum-rec (expr var &optional low high step)
1799 (or low (setq low '(neg (var inf var-inf)) high '(var inf var-inf)))
1800 (and low (not high) (setq high low low 1))
1801 (let (t1 t2 val)
1802 (setq val
1803 (cond
1804 ((not (math-expr-contains expr var))
1805 (math-mul expr (math-add (math-div (math-sub high low) (or step 1))
1806 1)))
1807 ((and step (not (math-equal-int step 1)))
1808 (if (math-negp step)
1809 (math-sum-rec expr var high low (math-neg step))
1810 (let ((lo (math-simplify (math-div low step))))
1811 (if (math-known-num-integerp lo)
1812 (math-sum-rec (math-normalize
1813 (math-expr-subst expr var
1814 (math-mul step var)))
1815 var lo (math-simplify (math-div high step)))
1816 (math-sum-rec (math-normalize
1817 (math-expr-subst expr var
1818 (math-add (math-mul step var)
1819 low)))
1820 var 0
1821 (math-simplify (math-div (math-sub high low)
1822 step)))))))
1823 ((memq (setq t1 (math-compare low high)) '(0 1))
1824 (if (eq t1 0)
1825 (math-expr-subst expr var low)
1827 ((setq t1 (math-is-polynomial expr var 20))
1828 (let ((poly nil)
1829 (n 0))
1830 (while t1
1831 (setq poly (math-poly-mix poly 1
1832 (math-sum-integer-power n) (car t1))
1833 n (1+ n)
1834 t1 (cdr t1)))
1835 (setq n (math-build-polynomial-expr poly high))
1836 (if (memq low '(0 1))
1838 (math-sub n (math-build-polynomial-expr poly
1839 (math-sub low 1))))))
1840 ((and (memq (car expr) '(+ -))
1841 (setq t1 (math-sum-rec (nth 1 expr) var low high)
1842 t2 (math-sum-rec (nth 2 expr) var low high))
1843 (not (and (math-expr-calls t1 '(calcFunc-sum))
1844 (math-expr-calls t2 '(calcFunc-sum)))))
1845 (list (car expr) t1 t2))
1846 ((and (eq (car expr) '*)
1847 (setq t1 (math-sum-const-factors expr var)))
1848 (math-mul (car t1) (math-sum-rec (cdr t1) var low high)))
1849 ((and (eq (car expr) '*) (memq (car-safe (nth 1 expr)) '(+ -)))
1850 (math-sum-rec (math-add-or-sub (math-mul (nth 1 (nth 1 expr))
1851 (nth 2 expr))
1852 (math-mul (nth 2 (nth 1 expr))
1853 (nth 2 expr))
1854 nil (eq (car (nth 1 expr)) '-))
1855 var low high))
1856 ((and (eq (car expr) '*) (memq (car-safe (nth 2 expr)) '(+ -)))
1857 (math-sum-rec (math-add-or-sub (math-mul (nth 1 expr)
1858 (nth 1 (nth 2 expr)))
1859 (math-mul (nth 1 expr)
1860 (nth 2 (nth 2 expr)))
1861 nil (eq (car (nth 2 expr)) '-))
1862 var low high))
1863 ((and (eq (car expr) '/)
1864 (not (math-primp (nth 1 expr)))
1865 (setq t1 (math-sum-const-factors (nth 1 expr) var)))
1866 (math-mul (car t1)
1867 (math-sum-rec (math-div (cdr t1) (nth 2 expr))
1868 var low high)))
1869 ((and (eq (car expr) '/)
1870 (setq t1 (math-sum-const-factors (nth 2 expr) var)))
1871 (math-div (math-sum-rec (math-div (nth 1 expr) (cdr t1))
1872 var low high)
1873 (car t1)))
1874 ((eq (car expr) 'neg)
1875 (math-neg (math-sum-rec (nth 1 expr) var low high)))
1876 ((and (eq (car expr) '^)
1877 (not (math-expr-contains (nth 1 expr) var))
1878 (setq t1 (math-is-polynomial (nth 2 expr) var 1)))
1879 (let ((x (math-pow (nth 1 expr) (nth 1 t1))))
1880 (math-div (math-mul (math-sub (math-pow x (math-add 1 high))
1881 (math-pow x low))
1882 (math-pow (nth 1 expr) (car t1)))
1883 (math-sub x 1))))
1884 ((and (setq t1 (math-to-exponentials expr))
1885 (setq t1 (math-sum-rec t1 var low high))
1886 (not (math-expr-calls t1 '(calcFunc-sum))))
1887 (math-to-exps t1))
1888 ((memq (car expr) '(calcFunc-ln calcFunc-log10))
1889 (list (car expr) (calcFunc-prod (nth 1 expr) var low high)))
1890 ((and (eq (car expr) 'calcFunc-log)
1891 (= (length expr) 3)
1892 (not (math-expr-contains (nth 2 expr) var)))
1893 (list 'calcFunc-log
1894 (calcFunc-prod (nth 1 expr) var low high)
1895 (nth 2 expr)))))
1896 (if (equal val '(var nan var-nan)) (setq val nil))
1897 (or val
1898 (let* ((math-tabulate-initial 0)
1899 (math-tabulate-function 'calcFunc-sum))
1900 (calcFunc-table expr var low high)))))
1902 (defun calcFunc-asum (expr var low &optional high step no-mul-flag)
1903 (or high (setq high low low 1))
1904 (if (and step (not (math-equal-int step 1)))
1905 (if (math-negp step)
1906 (math-mul (math-pow -1 low)
1907 (calcFunc-asum expr var high low (math-neg step) t))
1908 (let ((lo (math-simplify (math-div low step))))
1909 (if (math-num-integerp lo)
1910 (calcFunc-asum (math-normalize
1911 (math-expr-subst expr var
1912 (math-mul step var)))
1913 var lo (math-simplify (math-div high step)))
1914 (calcFunc-asum (math-normalize
1915 (math-expr-subst expr var
1916 (math-add (math-mul step var)
1917 low)))
1918 var 0
1919 (math-simplify (math-div (math-sub high low)
1920 step))))))
1921 (math-mul (if no-mul-flag 1 (math-pow -1 low))
1922 (calcFunc-sum (math-mul (math-pow -1 var) expr) var low high))))
1924 (defun math-sum-const-factors (expr var)
1925 (let ((const nil)
1926 (not-const nil)
1927 (p expr))
1928 (while (eq (car-safe p) '*)
1929 (if (math-expr-contains (nth 1 p) var)
1930 (setq not-const (cons (nth 1 p) not-const))
1931 (setq const (cons (nth 1 p) const)))
1932 (setq p (nth 2 p)))
1933 (if (math-expr-contains p var)
1934 (setq not-const (cons p not-const))
1935 (setq const (cons p const)))
1936 (and const
1937 (cons (let ((temp (car const)))
1938 (while (setq const (cdr const))
1939 (setq temp (list '* (car const) temp)))
1940 temp)
1941 (let ((temp (or (car not-const) 1)))
1942 (while (setq not-const (cdr not-const))
1943 (setq temp (list '* (car not-const) temp)))
1944 temp)))))
1946 (defvar math-sum-int-pow-cache (list '(0 1)))
1947 ;; Following is from CRC Math Tables, 27th ed, pp. 52-53.
1948 (defun math-sum-integer-power (pow)
1949 (let ((calc-prefer-frac t)
1950 (n (length math-sum-int-pow-cache)))
1951 (while (<= n pow)
1952 (let* ((new (list 0 0))
1953 (lin new)
1954 (pp (cdr (nth (1- n) math-sum-int-pow-cache)))
1955 (p 2)
1956 (sum 0)
1958 (while pp
1959 (setq q (math-div (car pp) p)
1960 new (cons (math-mul q n) new)
1961 sum (math-add sum q)
1962 p (1+ p)
1963 pp (cdr pp)))
1964 (setcar lin (math-sub 1 (math-mul n sum)))
1965 (setq math-sum-int-pow-cache
1966 (nconc math-sum-int-pow-cache (list (nreverse new)))
1967 n (1+ n))))
1968 (nth pow math-sum-int-pow-cache)))
1970 (defun math-to-exponentials (expr)
1971 (and (consp expr)
1972 (= (length expr) 2)
1973 (let ((x (nth 1 expr))
1974 (pi (if calc-symbolic-mode '(var pi var-pi) (math-pi)))
1975 (i (if calc-symbolic-mode '(var i var-i) '(cplx 0 1))))
1976 (cond ((eq (car expr) 'calcFunc-exp)
1977 (list '^ '(var e var-e) x))
1978 ((eq (car expr) 'calcFunc-sin)
1979 (or (eq calc-angle-mode 'rad)
1980 (setq x (list '/ (list '* x pi) 180)))
1981 (list '/ (list '-
1982 (list '^ '(var e var-e) (list '* x i))
1983 (list '^ '(var e var-e)
1984 (list 'neg (list '* x i))))
1985 (list '* 2 i)))
1986 ((eq (car expr) 'calcFunc-cos)
1987 (or (eq calc-angle-mode 'rad)
1988 (setq x (list '/ (list '* x pi) 180)))
1989 (list '/ (list '+
1990 (list '^ '(var e var-e)
1991 (list '* x i))
1992 (list '^ '(var e var-e)
1993 (list 'neg (list '* x i))))
1995 ((eq (car expr) 'calcFunc-sinh)
1996 (list '/ (list '-
1997 (list '^ '(var e var-e) x)
1998 (list '^ '(var e var-e) (list 'neg x)))
2000 ((eq (car expr) 'calcFunc-cosh)
2001 (list '/ (list '+
2002 (list '^ '(var e var-e) x)
2003 (list '^ '(var e var-e) (list 'neg x)))
2005 (t nil)))))
2007 (defun math-to-exps (expr)
2008 (cond (calc-symbolic-mode expr)
2009 ((Math-primp expr)
2010 (if (equal expr '(var e var-e)) (math-e) expr))
2011 ((and (eq (car expr) '^)
2012 (equal (nth 1 expr) '(var e var-e)))
2013 (list 'calcFunc-exp (nth 2 expr)))
2015 (cons (car expr) (mapcar 'math-to-exps (cdr expr))))))
2018 (defvar math-disable-prods nil)
2019 (defun calcFunc-prod (expr var &optional low high step)
2020 (if math-disable-prods (math-reject-arg))
2021 (let* ((res (let* ((calc-internal-prec (+ calc-internal-prec 2)))
2022 (math-prod-rec expr var low high step)))
2023 (math-disable-prods t))
2024 (math-normalize res)))
2026 (defun math-prod-rec (expr var &optional low high step)
2027 (or low (setq low '(neg (var inf var-inf)) high '(var inf var-inf)))
2028 (and low (not high) (setq high '(var inf var-inf)))
2029 (let (t1 t2 t3 val)
2030 (setq val
2031 (cond
2032 ((not (math-expr-contains expr var))
2033 (math-pow expr (math-add (math-div (math-sub high low) (or step 1))
2034 1)))
2035 ((and step (not (math-equal-int step 1)))
2036 (if (math-negp step)
2037 (math-prod-rec expr var high low (math-neg step))
2038 (let ((lo (math-simplify (math-div low step))))
2039 (if (math-known-num-integerp lo)
2040 (math-prod-rec (math-normalize
2041 (math-expr-subst expr var
2042 (math-mul step var)))
2043 var lo (math-simplify (math-div high step)))
2044 (math-prod-rec (math-normalize
2045 (math-expr-subst expr var
2046 (math-add (math-mul step
2047 var)
2048 low)))
2049 var 0
2050 (math-simplify (math-div (math-sub high low)
2051 step)))))))
2052 ((and (memq (car expr) '(* /))
2053 (setq t1 (math-prod-rec (nth 1 expr) var low high)
2054 t2 (math-prod-rec (nth 2 expr) var low high))
2055 (not (and (math-expr-calls t1 '(calcFunc-prod))
2056 (math-expr-calls t2 '(calcFunc-prod)))))
2057 (list (car expr) t1 t2))
2058 ((and (eq (car expr) '^)
2059 (not (math-expr-contains (nth 2 expr) var)))
2060 (math-pow (math-prod-rec (nth 1 expr) var low high)
2061 (nth 2 expr)))
2062 ((and (eq (car expr) '^)
2063 (not (math-expr-contains (nth 1 expr) var)))
2064 (math-pow (nth 1 expr)
2065 (calcFunc-sum (nth 2 expr) var low high)))
2066 ((eq (car expr) 'sqrt)
2067 (math-normalize (list 'calcFunc-sqrt
2068 (list 'calcFunc-prod (nth 1 expr)
2069 var low high))))
2070 ((eq (car expr) 'neg)
2071 (math-mul (math-pow -1 (math-add (math-sub high low) 1))
2072 (math-prod-rec (nth 1 expr) var low high)))
2073 ((eq (car expr) 'calcFunc-exp)
2074 (list 'calcFunc-exp (calcFunc-sum (nth 1 expr) var low high)))
2075 ((and (setq t1 (math-is-polynomial expr var 1))
2076 (setq t2
2077 (cond
2078 ((or (and (math-equal-int (nth 1 t1) 1)
2079 (setq low (math-simplify
2080 (math-add low (car t1)))
2081 high (math-simplify
2082 (math-add high (car t1)))))
2083 (and (math-equal-int (nth 1 t1) -1)
2084 (setq t2 low
2085 low (math-simplify
2086 (math-sub (car t1) high))
2087 high (math-simplify
2088 (math-sub (car t1) t2)))))
2089 (if (or (math-zerop low) (math-zerop high))
2091 (if (and (or (math-negp low) (math-negp high))
2092 (or (math-num-integerp low)
2093 (math-num-integerp high)))
2094 (if (math-posp high)
2096 (math-mul (math-pow -1
2097 (math-add
2098 (math-add low high) 1))
2099 (list '/
2100 (list 'calcFunc-fact
2101 (math-neg low))
2102 (list 'calcFunc-fact
2103 (math-sub -1 high)))))
2104 (list '/
2105 (list 'calcFunc-fact high)
2106 (list 'calcFunc-fact (math-sub low 1))))))
2107 ((and (or (and (math-equal-int (nth 1 t1) 2)
2108 (setq t2 (math-simplify
2109 (math-add (math-mul low 2)
2110 (car t1)))
2111 t3 (math-simplify
2112 (math-add (math-mul high 2)
2113 (car t1)))))
2114 (and (math-equal-int (nth 1 t1) -2)
2115 (setq t2 (math-simplify
2116 (math-sub (car t1)
2117 (math-mul high 2)))
2118 t3 (math-simplify
2119 (math-sub (car t1)
2120 (math-mul low
2121 2))))))
2122 (or (math-integerp t2)
2123 (and (math-messy-integerp t2)
2124 (setq t2 (math-trunc t2)))
2125 (math-integerp t3)
2126 (and (math-messy-integerp t3)
2127 (setq t3 (math-trunc t3)))))
2128 (if (or (math-zerop t2) (math-zerop t3))
2130 (if (or (math-evenp t2) (math-evenp t3))
2131 (if (or (math-negp t2) (math-negp t3))
2132 (if (math-posp high)
2134 (list '/
2135 (list 'calcFunc-dfact
2136 (math-neg t2))
2137 (list 'calcFunc-dfact
2138 (math-sub -2 t3))))
2139 (list '/
2140 (list 'calcFunc-dfact t3)
2141 (list 'calcFunc-dfact
2142 (math-sub t2 2))))
2143 (if (math-negp t3)
2144 (list '*
2145 (list '^ -1
2146 (list '/ (list '- (list '- t2 t3)
2149 (list '/
2150 (list 'calcFunc-dfact
2151 (math-neg t2))
2152 (list 'calcFunc-dfact
2153 (math-sub -2 t3))))
2154 (if (math-posp t2)
2155 (list '/
2156 (list 'calcFunc-dfact t3)
2157 (list 'calcFunc-dfact
2158 (math-sub t2 2)))
2159 nil))))))))
2160 t2)))
2161 (if (equal val '(var nan var-nan)) (setq val nil))
2162 (or val
2163 (let* ((math-tabulate-initial 1)
2164 (math-tabulate-function 'calcFunc-prod))
2165 (calcFunc-table expr var low high)))))
2170 (defvar math-solve-ranges nil)
2171 ;;; Attempt to reduce lhs = rhs to solve-var = rhs', where solve-var appears
2172 ;;; in lhs but not in rhs or rhs'; return rhs'.
2173 ;;; Uses global values: solve-*.
2174 (defun math-try-solve-for (lhs rhs &optional sign no-poly)
2175 (let (t1 t2 t3)
2176 (cond ((equal lhs solve-var)
2177 (setq math-solve-sign sign)
2178 (if (eq solve-full 'all)
2179 (let ((vec (list 'vec (math-evaluate-expr rhs)))
2180 newvec var p)
2181 (while math-solve-ranges
2182 (setq p (car math-solve-ranges)
2183 var (car p)
2184 newvec (list 'vec))
2185 (while (setq p (cdr p))
2186 (setq newvec (nconc newvec
2187 (cdr (math-expr-subst
2188 vec var (car p))))))
2189 (setq vec newvec
2190 math-solve-ranges (cdr math-solve-ranges)))
2191 (math-normalize vec))
2192 rhs))
2193 ((Math-primp lhs)
2194 nil)
2195 ((and (eq (car lhs) '-)
2196 (eq (car-safe (nth 1 lhs)) (car-safe (nth 2 lhs)))
2197 (Math-zerop rhs)
2198 (= (length (nth 1 lhs)) 2)
2199 (= (length (nth 2 lhs)) 2)
2200 (setq t1 (get (car (nth 1 lhs)) 'math-inverse))
2201 (setq t2 (funcall t1 '(var SOLVEDUM SOLVEDUM)))
2202 (eq (math-expr-contains-count t2 '(var SOLVEDUM SOLVEDUM)) 1)
2203 (setq t3 (math-solve-above-dummy t2))
2204 (setq t1 (math-try-solve-for (math-sub (nth 1 (nth 1 lhs))
2205 (math-expr-subst
2206 t2 t3
2207 (nth 1 (nth 2 lhs))))
2208 0)))
2210 ((eq (car lhs) 'neg)
2211 (math-try-solve-for (nth 1 lhs) (math-neg rhs)
2212 (and sign (- sign))))
2213 ((and (not (eq solve-full 't)) (math-try-solve-prod)))
2214 ((and (not no-poly)
2215 (setq t2 (math-decompose-poly lhs solve-var 15 rhs)))
2216 (setq t1 (cdr (nth 1 t2))
2217 t1 (let ((math-solve-ranges math-solve-ranges))
2218 (cond ((= (length t1) 5)
2219 (apply 'math-solve-quartic (car t2) t1))
2220 ((= (length t1) 4)
2221 (apply 'math-solve-cubic (car t2) t1))
2222 ((= (length t1) 3)
2223 (apply 'math-solve-quadratic (car t2) t1))
2224 ((= (length t1) 2)
2225 (apply 'math-solve-linear (car t2) sign t1))
2226 (solve-full
2227 (math-poly-all-roots (car t2) t1))
2228 (calc-symbolic-mode nil)
2230 (math-try-solve-for
2231 (car t2)
2232 (math-poly-any-root (reverse t1) 0 t)
2233 nil t)))))
2234 (if t1
2235 (if (eq (nth 2 t2) 1)
2237 (math-solve-prod t1 (math-try-solve-for (nth 2 t2) 0 nil t)))
2238 (calc-record-why "*Unable to find a symbolic solution")
2239 nil))
2240 ((and (math-solve-find-root-term lhs nil)
2241 (eq (math-expr-contains-count lhs t1) 1)) ; just in case
2242 (math-try-solve-for (math-simplify
2243 (math-sub (if (or t3 (math-evenp t2))
2244 (math-pow t1 t2)
2245 (math-neg (math-pow t1 t2)))
2246 (math-expand-power
2247 (math-sub (math-normalize
2248 (math-expr-subst
2249 lhs t1 0))
2250 rhs)
2251 t2 solve-var)))
2253 ((eq (car lhs) '+)
2254 (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
2255 (math-try-solve-for (nth 2 lhs)
2256 (math-sub rhs (nth 1 lhs))
2257 sign))
2258 ((not (math-expr-contains (nth 2 lhs) solve-var))
2259 (math-try-solve-for (nth 1 lhs)
2260 (math-sub rhs (nth 2 lhs))
2261 sign))))
2262 ((eq (car lhs) 'calcFunc-eq)
2263 (math-try-solve-for (math-sub (nth 1 lhs) (nth 2 lhs))
2264 rhs sign no-poly))
2265 ((eq (car lhs) '-)
2266 (cond ((or (and (eq (car-safe (nth 1 lhs)) 'calcFunc-sin)
2267 (eq (car-safe (nth 2 lhs)) 'calcFunc-cos))
2268 (and (eq (car-safe (nth 1 lhs)) 'calcFunc-cos)
2269 (eq (car-safe (nth 2 lhs)) 'calcFunc-sin)))
2270 (math-try-solve-for (math-sub (nth 1 lhs)
2271 (list (car (nth 1 lhs))
2272 (math-sub
2273 (math-quarter-circle t)
2274 (nth 1 (nth 2 lhs)))))
2275 rhs))
2276 ((not (math-expr-contains (nth 1 lhs) solve-var))
2277 (math-try-solve-for (nth 2 lhs)
2278 (math-sub (nth 1 lhs) rhs)
2279 (and sign (- sign))))
2280 ((not (math-expr-contains (nth 2 lhs) solve-var))
2281 (math-try-solve-for (nth 1 lhs)
2282 (math-add rhs (nth 2 lhs))
2283 sign))))
2284 ((and (eq solve-full 't) (math-try-solve-prod)))
2285 ((and (eq (car lhs) '%)
2286 (not (math-expr-contains (nth 2 lhs) solve-var)))
2287 (math-try-solve-for (nth 1 lhs) (math-add rhs
2288 (math-solve-get-int
2289 (nth 2 lhs)))))
2290 ((eq (car lhs) 'calcFunc-log)
2291 (cond ((not (math-expr-contains (nth 2 lhs) solve-var))
2292 (math-try-solve-for (nth 1 lhs) (math-pow (nth 2 lhs) rhs)))
2293 ((not (math-expr-contains (nth 1 lhs) solve-var))
2294 (math-try-solve-for (nth 2 lhs) (math-pow
2295 (nth 1 lhs)
2296 (math-div 1 rhs))))))
2297 ((and (= (length lhs) 2)
2298 (symbolp (car lhs))
2299 (setq t1 (get (car lhs) 'math-inverse))
2300 (setq t2 (funcall t1 rhs)))
2301 (setq t1 (get (car lhs) 'math-inverse-sign))
2302 (math-try-solve-for (nth 1 lhs) (math-normalize t2)
2303 (and sign t1
2304 (if (integerp t1)
2305 (* t1 sign)
2306 (funcall t1 lhs sign)))))
2307 ((and (symbolp (car lhs))
2308 (setq t1 (get (car lhs) 'math-inverse-n))
2309 (setq t2 (funcall t1 lhs rhs)))
2311 ((setq t1 (math-expand-formula lhs))
2312 (math-try-solve-for t1 rhs sign))
2314 (calc-record-why "*No inverse known" lhs)
2315 nil))))
2318 (defun math-try-solve-prod ()
2319 (cond ((eq (car lhs) '*)
2320 (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
2321 (math-try-solve-for (nth 2 lhs)
2322 (math-div rhs (nth 1 lhs))
2323 (math-solve-sign sign (nth 1 lhs))))
2324 ((not (math-expr-contains (nth 2 lhs) solve-var))
2325 (math-try-solve-for (nth 1 lhs)
2326 (math-div rhs (nth 2 lhs))
2327 (math-solve-sign sign (nth 2 lhs))))
2328 ((Math-zerop rhs)
2329 (math-solve-prod (let ((math-solve-ranges math-solve-ranges))
2330 (math-try-solve-for (nth 2 lhs) 0))
2331 (math-try-solve-for (nth 1 lhs) 0)))))
2332 ((eq (car lhs) '/)
2333 (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
2334 (math-try-solve-for (nth 2 lhs)
2335 (math-div (nth 1 lhs) rhs)
2336 (math-solve-sign sign (nth 1 lhs))))
2337 ((not (math-expr-contains (nth 2 lhs) solve-var))
2338 (math-try-solve-for (nth 1 lhs)
2339 (math-mul rhs (nth 2 lhs))
2340 (math-solve-sign sign (nth 2 lhs))))
2341 ((setq t1 (math-try-solve-for (math-sub (nth 1 lhs)
2342 (math-mul (nth 2 lhs)
2343 rhs))
2345 t1)))
2346 ((eq (car lhs) '^)
2347 (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
2348 (math-try-solve-for
2349 (nth 2 lhs)
2350 (math-add (math-normalize
2351 (list 'calcFunc-log rhs (nth 1 lhs)))
2352 (math-div
2353 (math-mul 2
2354 (math-mul '(var pi var-pi)
2355 (math-solve-get-int
2356 '(var i var-i))))
2357 (math-normalize
2358 (list 'calcFunc-ln (nth 1 lhs)))))))
2359 ((not (math-expr-contains (nth 2 lhs) solve-var))
2360 (cond ((and (integerp (nth 2 lhs))
2361 (>= (nth 2 lhs) 2)
2362 (setq t1 (math-integer-log2 (nth 2 lhs))))
2363 (setq t2 rhs)
2364 (if (and (eq solve-full t)
2365 (math-known-realp (nth 1 lhs)))
2366 (progn
2367 (while (>= (setq t1 (1- t1)) 0)
2368 (setq t2 (list 'calcFunc-sqrt t2)))
2369 (setq t2 (math-solve-get-sign t2)))
2370 (while (>= (setq t1 (1- t1)) 0)
2371 (setq t2 (math-solve-get-sign
2372 (math-normalize
2373 (list 'calcFunc-sqrt t2))))))
2374 (math-try-solve-for
2375 (nth 1 lhs)
2376 (math-normalize t2)))
2377 ((math-looks-negp (nth 2 lhs))
2378 (math-try-solve-for
2379 (list '^ (nth 1 lhs) (math-neg (nth 2 lhs)))
2380 (math-div 1 rhs)))
2381 ((and (eq solve-full t)
2382 (Math-integerp (nth 2 lhs))
2383 (math-known-realp (nth 1 lhs)))
2384 (setq t1 (math-normalize
2385 (list 'calcFunc-nroot rhs (nth 2 lhs))))
2386 (if (math-evenp (nth 2 lhs))
2387 (setq t1 (math-solve-get-sign t1)))
2388 (math-try-solve-for
2389 (nth 1 lhs) t1
2390 (and sign
2391 (math-oddp (nth 2 lhs))
2392 (math-solve-sign sign (nth 2 lhs)))))
2393 (t (math-try-solve-for
2394 (nth 1 lhs)
2395 (math-mul
2396 (math-normalize
2397 (list 'calcFunc-exp
2398 (if (Math-realp (nth 2 lhs))
2399 (math-div (math-mul
2400 '(var pi var-pi)
2401 (math-solve-get-int
2402 '(var i var-i)
2403 (and (integerp (nth 2 lhs))
2404 (math-abs
2405 (nth 2 lhs)))))
2406 (math-div (nth 2 lhs) 2))
2407 (math-div (math-mul
2409 (math-mul
2410 '(var pi var-pi)
2411 (math-solve-get-int
2412 '(var i var-i)
2413 (and (integerp (nth 2 lhs))
2414 (math-abs
2415 (nth 2 lhs))))))
2416 (nth 2 lhs)))))
2417 (math-normalize
2418 (list 'calcFunc-nroot
2420 (nth 2 lhs))))
2421 (and sign
2422 (math-oddp (nth 2 lhs))
2423 (math-solve-sign sign (nth 2 lhs)))))))))
2424 (t nil)))
2426 (defun math-solve-prod (lsoln rsoln)
2427 (cond ((null lsoln)
2428 rsoln)
2429 ((null rsoln)
2430 lsoln)
2431 ((eq solve-full 'all)
2432 (cons 'vec (append (cdr lsoln) (cdr rsoln))))
2433 (solve-full
2434 (list 'calcFunc-if
2435 (list 'calcFunc-gt (math-solve-get-sign 1) 0)
2436 lsoln
2437 rsoln))
2438 (t lsoln)))
2440 ;;; This deals with negative, fractional, and symbolic powers of "x".
2441 (defun math-solve-poly-funny-powers (sub-rhs) ; uses "t1", "t2"
2442 (setq t1 lhs)
2443 (let ((pp math-poly-neg-powers)
2444 fac)
2445 (while pp
2446 (setq fac (math-pow (car pp) (or math-poly-mult-powers 1))
2447 t1 (math-mul t1 fac)
2448 rhs (math-mul rhs fac)
2449 pp (cdr pp))))
2450 (if sub-rhs (setq t1 (math-sub t1 rhs)))
2451 (let ((math-poly-neg-powers nil))
2452 (setq t2 (math-mul (or math-poly-mult-powers 1)
2453 (let ((calc-prefer-frac t))
2454 (math-div 1 math-poly-frac-powers)))
2455 t1 (math-is-polynomial (math-simplify (calcFunc-expand t1)) b 50))))
2457 ;;; This converts "a x^8 + b x^5 + c x^2" to "(a (x^3)^2 + b (x^3) + c) * x^2".
2458 (defun math-solve-crunch-poly (max-degree) ; uses "t1", "t3"
2459 (let ((count 0))
2460 (while (and t1 (Math-zerop (car t1)))
2461 (setq t1 (cdr t1)
2462 count (1+ count)))
2463 (and t1
2464 (let* ((degree (1- (length t1)))
2465 (scale degree))
2466 (while (and (> scale 1) (= (car t3) 1))
2467 (and (= (% degree scale) 0)
2468 (let ((p t1)
2469 (n 0)
2470 (new-t1 nil)
2471 (okay t))
2472 (while (and p okay)
2473 (if (= (% n scale) 0)
2474 (setq new-t1 (nconc new-t1 (list (car p))))
2475 (or (Math-zerop (car p))
2476 (setq okay nil)))
2477 (setq p (cdr p)
2478 n (1+ n)))
2479 (if okay
2480 (setq t3 (cons scale (cdr t3))
2481 t1 new-t1))))
2482 (setq scale (1- scale)))
2483 (setq t3 (list (math-mul (car t3) t2) (math-mul count t2)))
2484 (<= (1- (length t1)) max-degree)))))
2486 (defun calcFunc-poly (expr var &optional degree)
2487 (if degree
2488 (or (natnump degree) (math-reject-arg degree 'fixnatnump))
2489 (setq degree 50))
2490 (let ((p (math-is-polynomial expr var degree 'gen)))
2491 (if p
2492 (if (equal p '(0))
2493 (list 'vec)
2494 (cons 'vec p))
2495 (math-reject-arg expr "Expected a polynomial"))))
2497 (defun calcFunc-gpoly (expr var &optional degree)
2498 (if degree
2499 (or (natnump degree) (math-reject-arg degree 'fixnatnump))
2500 (setq degree 50))
2501 (let* ((math-poly-base-variable var)
2502 (d (math-decompose-poly expr var degree nil)))
2503 (if d
2504 (cons 'vec d)
2505 (math-reject-arg expr "Expected a polynomial"))))
2507 (defun math-decompose-poly (lhs solve-var degree sub-rhs)
2508 (let ((rhs (or sub-rhs 1))
2509 t1 t2 t3)
2510 (setq t2 (math-polynomial-base
2512 (function
2513 (lambda (b)
2514 (let ((math-poly-neg-powers '(1))
2515 (math-poly-mult-powers nil)
2516 (math-poly-frac-powers 1)
2517 (math-poly-exp-base t))
2518 (and (not (equal b lhs))
2519 (or (not (memq (car-safe b) '(+ -))) sub-rhs)
2520 (setq t3 '(1 0) t2 1
2521 t1 (math-is-polynomial lhs b 50))
2522 (if (and (equal math-poly-neg-powers '(1))
2523 (memq math-poly-mult-powers '(nil 1))
2524 (eq math-poly-frac-powers 1)
2525 sub-rhs)
2526 (setq t1 (cons (math-sub (car t1) rhs)
2527 (cdr t1)))
2528 (math-solve-poly-funny-powers sub-rhs))
2529 (math-solve-crunch-poly degree)
2530 (or (math-expr-contains b solve-var)
2531 (math-expr-contains (car t3) solve-var))))))))
2532 (if t2
2533 (list (math-pow t2 (car t3))
2534 (cons 'vec t1)
2535 (if sub-rhs
2536 (math-pow t2 (nth 1 t3))
2537 (math-div (math-pow t2 (nth 1 t3)) rhs))))))
2539 (defun math-solve-linear (var sign b a)
2540 (math-try-solve-for var
2541 (math-div (math-neg b) a)
2542 (math-solve-sign sign a)
2545 (defun math-solve-quadratic (var c b a)
2546 (math-try-solve-for
2548 (if (math-looks-evenp b)
2549 (let ((halfb (math-div b 2)))
2550 (math-div
2551 (math-add
2552 (math-neg halfb)
2553 (math-solve-get-sign
2554 (math-normalize
2555 (list 'calcFunc-sqrt
2556 (math-add (math-sqr halfb)
2557 (math-mul (math-neg c) a))))))
2559 (math-div
2560 (math-add
2561 (math-neg b)
2562 (math-solve-get-sign
2563 (math-normalize
2564 (list 'calcFunc-sqrt
2565 (math-add (math-sqr b)
2566 (math-mul 4 (math-mul (math-neg c) a)))))))
2567 (math-mul 2 a)))
2568 nil t))
2570 (defun math-solve-cubic (var d c b a)
2571 (let* ((p (math-div b a))
2572 (q (math-div c a))
2573 (r (math-div d a))
2574 (psqr (math-sqr p))
2575 (aa (math-sub q (math-div psqr 3)))
2576 (bb (math-add r
2577 (math-div (math-sub (math-mul 2 (math-mul psqr p))
2578 (math-mul 9 (math-mul p q)))
2579 27)))
2581 (if (Math-zerop aa)
2582 (math-try-solve-for (math-pow (math-add var (math-div p 3)) 3)
2583 (math-neg bb) nil t)
2584 (if (Math-zerop bb)
2585 (math-try-solve-for
2586 (math-mul (math-add var (math-div p 3))
2587 (math-add (math-sqr (math-add var (math-div p 3)))
2588 aa))
2589 0 nil t)
2590 (setq m (math-mul 2 (list 'calcFunc-sqrt (math-div aa -3))))
2591 (math-try-solve-for
2593 (math-sub
2594 (math-normalize
2595 (math-mul
2597 (list 'calcFunc-cos
2598 (math-div
2599 (math-sub (list 'calcFunc-arccos
2600 (math-div (math-mul 3 bb)
2601 (math-mul aa m)))
2602 (math-mul 2
2603 (math-mul
2604 (math-add 1 (math-solve-get-int
2605 1 3))
2606 (math-half-circle
2607 calc-symbolic-mode))))
2608 3))))
2609 (math-div p 3))
2610 nil t)))))
2612 (defun math-solve-quartic (var d c b a aa)
2613 (setq a (math-div a aa))
2614 (setq b (math-div b aa))
2615 (setq c (math-div c aa))
2616 (setq d (math-div d aa))
2617 (math-try-solve-for
2619 (let* ((asqr (math-sqr a))
2620 (asqr4 (math-div asqr 4))
2621 (y (let ((solve-full nil)
2622 calc-next-why)
2623 (math-solve-cubic solve-var
2624 (math-sub (math-sub
2625 (math-mul 4 (math-mul b d))
2626 (math-mul asqr d))
2627 (math-sqr c))
2628 (math-sub (math-mul a c)
2629 (math-mul 4 d))
2630 (math-neg b)
2631 1)))
2632 (rsqr (math-add (math-sub asqr4 b) y))
2633 (r (list 'calcFunc-sqrt rsqr))
2634 (sign1 (math-solve-get-sign 1))
2635 (de (list 'calcFunc-sqrt
2636 (math-add
2637 (math-sub (math-mul 3 asqr4)
2638 (math-mul 2 b))
2639 (if (Math-zerop rsqr)
2640 (math-mul
2642 (math-mul sign1
2643 (list 'calcFunc-sqrt
2644 (math-sub (math-sqr y)
2645 (math-mul 4 d)))))
2646 (math-sub
2647 (math-mul sign1
2648 (math-div
2649 (math-sub (math-sub
2650 (math-mul 4 (math-mul a b))
2651 (math-mul 8 c))
2652 (math-mul asqr a))
2653 (math-mul 4 r)))
2654 rsqr))))))
2655 (math-normalize
2656 (math-sub (math-add (math-mul sign1 (math-div r 2))
2657 (math-solve-get-sign (math-div de 2)))
2658 (math-div a 4))))
2659 nil t))
2661 (defvar math-symbolic-solve nil)
2662 (defvar math-int-coefs nil)
2663 (defun math-poly-all-roots (var p &optional math-factoring)
2664 (catch 'ouch
2665 (let* ((math-symbolic-solve calc-symbolic-mode)
2666 (roots nil)
2667 (deg (1- (length p)))
2668 (orig-p (reverse p))
2669 (math-int-coefs nil)
2670 (math-int-scale nil)
2671 (math-double-roots nil)
2672 (math-int-factors nil)
2673 (math-int-threshold nil)
2674 (pp p))
2675 ;; If rational coefficients, look for exact rational factors.
2676 (while (and pp (Math-ratp (car pp)))
2677 (setq pp (cdr pp)))
2678 (if pp
2679 (if (or math-factoring math-symbolic-solve)
2680 (throw 'ouch nil))
2681 (let ((lead (car orig-p))
2682 (calc-prefer-frac t)
2683 (scale (apply 'math-lcm-denoms p)))
2684 (setq math-int-scale (math-abs (math-mul scale lead))
2685 math-int-threshold (math-div '(float 5 -2) math-int-scale)
2686 math-int-coefs (cdr (math-div (cons 'vec orig-p) lead)))))
2687 (if (> deg 4)
2688 (let ((calc-prefer-frac nil)
2689 (calc-symbolic-mode nil)
2690 (pp p)
2691 (def-p (copy-sequence orig-p)))
2692 (while pp
2693 (if (Math-numberp (car pp))
2694 (setq pp (cdr pp))
2695 (throw 'ouch nil)))
2696 (while (> deg (if math-symbolic-solve 2 4))
2697 (let* ((x (math-poly-any-root def-p '(float 0 0) nil))
2698 b c pp)
2699 (if (and (eq (car-safe x) 'cplx)
2700 (math-nearly-zerop (nth 2 x) (nth 1 x)))
2701 (setq x (calcFunc-re x)))
2702 (or math-factoring
2703 (setq roots (cons x roots)))
2704 (or (math-numberp x)
2705 (setq x (math-evaluate-expr x)))
2706 (setq pp def-p
2707 b (car def-p))
2708 (while (setq pp (cdr pp))
2709 (setq c (car pp))
2710 (setcar pp b)
2711 (setq b (math-add (math-mul x b) c)))
2712 (setq def-p (cdr def-p)
2713 deg (1- deg))))
2714 (setq p (reverse def-p))))
2715 (if (> deg 1)
2716 (let ((solve-var '(var DUMMY var-DUMMY))
2717 (math-solve-sign nil)
2718 (math-solve-ranges nil)
2719 (solve-full 'all))
2720 (if (= (length p) (length math-int-coefs))
2721 (setq p (reverse math-int-coefs)))
2722 (setq roots (append (cdr (apply (cond ((= deg 2)
2723 'math-solve-quadratic)
2724 ((= deg 3)
2725 'math-solve-cubic)
2727 'math-solve-quartic))
2728 solve-var p))
2729 roots)))
2730 (if (> deg 0)
2731 (setq roots (cons (math-div (math-neg (car p)) (nth 1 p))
2732 roots))))
2733 (if math-factoring
2734 (progn
2735 (while roots
2736 (math-poly-integer-root (car roots))
2737 (setq roots (cdr roots)))
2738 (list math-int-factors (nreverse math-int-coefs) math-int-scale))
2739 (let ((vec nil) res)
2740 (while roots
2741 (let ((root (car roots))
2742 (solve-full (and solve-full 'all)))
2743 (if (math-floatp root)
2744 (setq root (math-poly-any-root orig-p root t)))
2745 (setq vec (append vec
2746 (cdr (or (math-try-solve-for var root nil t)
2747 (throw 'ouch nil))))))
2748 (setq roots (cdr roots)))
2749 (setq vec (cons 'vec (nreverse vec)))
2750 (if math-symbolic-solve
2751 (setq vec (math-normalize vec)))
2752 (if (eq solve-full t)
2753 (list 'calcFunc-subscr
2755 (math-solve-get-int 1 (1- (length orig-p)) 1))
2756 vec))))))
2758 (defun math-lcm-denoms (&rest fracs)
2759 (let ((den 1))
2760 (while fracs
2761 (if (eq (car-safe (car fracs)) 'frac)
2762 (setq den (calcFunc-lcm den (nth 2 (car fracs)))))
2763 (setq fracs (cdr fracs)))
2764 den))
2766 (defun math-poly-any-root (p x polish) ; p is a reverse poly coeff list
2767 (let* ((newt (if (math-zerop x)
2768 (math-poly-newton-root
2769 p '(cplx (float 123 -6) (float 1 -4)) 4)
2770 (math-poly-newton-root p x 4)))
2771 (res (if (math-zerop (cdr newt))
2772 (car newt)
2773 (if (and (math-lessp (cdr newt) '(float 1 -3)) (not polish))
2774 (setq newt (math-poly-newton-root p (car newt) 30)))
2775 (if (math-zerop (cdr newt))
2776 (car newt)
2777 (math-poly-laguerre-root p x polish)))))
2778 (and math-symbolic-solve (math-floatp res)
2779 (throw 'ouch nil))
2780 res))
2782 (defun math-poly-newton-root (p x iters)
2783 (let* ((calc-prefer-frac nil)
2784 (calc-symbolic-mode nil)
2785 (try-integer math-int-coefs)
2786 (dx x) b d)
2787 (while (and (> (setq iters (1- iters)) 0)
2788 (let ((pp p))
2789 (math-working "newton" x)
2790 (setq b (car p)
2791 d 0)
2792 (while (setq pp (cdr pp))
2793 (setq d (math-add (math-mul x d) b)
2794 b (math-add (math-mul x b) (car pp))))
2795 (not (math-zerop d)))
2796 (progn
2797 (setq dx (math-div b d)
2798 x (math-sub x dx))
2799 (if try-integer
2800 (let ((adx (math-abs-approx dx)))
2801 (and (math-lessp adx math-int-threshold)
2802 (let ((iroot (math-poly-integer-root x)))
2803 (if iroot
2804 (setq x iroot dx 0)
2805 (setq try-integer nil))))))
2806 (or (not (or (eq dx 0)
2807 (math-nearly-zerop dx (math-abs-approx x))))
2808 (progn (setq dx 0) nil)))))
2809 (cons x (if (math-zerop x)
2810 1 (math-div (math-abs-approx dx) (math-abs-approx x))))))
2812 (defun math-poly-integer-root (x)
2813 (and (math-lessp (calcFunc-xpon (math-abs-approx x)) calc-internal-prec)
2814 math-int-coefs
2815 (let* ((calc-prefer-frac t)
2816 (xre (calcFunc-re x))
2817 (xim (calcFunc-im x))
2818 (xresq (math-sqr xre))
2819 (ximsq (math-sqr xim)))
2820 (if (math-lessp ximsq (calcFunc-scf xresq -1))
2821 ;; Look for linear factor
2822 (let* ((rnd (math-div (math-round (math-mul xre math-int-scale))
2823 math-int-scale))
2824 (icp math-int-coefs)
2825 (rem (car icp))
2826 (newcoef nil))
2827 (while (setq icp (cdr icp))
2828 (setq newcoef (cons rem newcoef)
2829 rem (math-add (car icp)
2830 (math-mul rem rnd))))
2831 (and (math-zerop rem)
2832 (progn
2833 (setq math-int-coefs (nreverse newcoef)
2834 math-int-factors (cons (list (math-neg rnd))
2835 math-int-factors))
2836 rnd)))
2837 ;; Look for irreducible quadratic factor
2838 (let* ((rnd1 (math-div (math-round
2839 (math-mul xre (math-mul -2 math-int-scale)))
2840 math-int-scale))
2841 (sqscale (math-sqr math-int-scale))
2842 (rnd0 (math-div (math-round (math-mul (math-add xresq ximsq)
2843 sqscale))
2844 sqscale))
2845 (rem1 (car math-int-coefs))
2846 (icp (cdr math-int-coefs))
2847 (rem0 (car icp))
2848 (newcoef nil)
2849 (found (assoc (list rnd0 rnd1 (math-posp xim))
2850 math-double-roots))
2851 this)
2852 (if found
2853 (setq math-double-roots (delq found math-double-roots)
2854 rem0 0 rem1 0)
2855 (while (setq icp (cdr icp))
2856 (setq this rem1
2857 newcoef (cons rem1 newcoef)
2858 rem1 (math-sub rem0 (math-mul this rnd1))
2859 rem0 (math-sub (car icp) (math-mul this rnd0)))))
2860 (and (math-zerop rem0)
2861 (math-zerop rem1)
2862 (let ((aa (math-div rnd1 -2)))
2863 (or found (setq math-int-coefs (reverse newcoef)
2864 math-double-roots (cons (list
2865 (list
2866 rnd0 rnd1
2867 (math-negp xim)))
2868 math-double-roots)
2869 math-int-factors (cons (cons rnd0 rnd1)
2870 math-int-factors)))
2871 (math-add aa
2872 (let ((calc-symbolic-mode math-symbolic-solve))
2873 (math-mul (math-sqrt (math-sub (math-sqr aa)
2874 rnd0))
2875 (if (math-negp xim) -1 1)))))))))))
2877 ;;; The following routine is from Numerical Recipes, section 9.5.
2878 (defun math-poly-laguerre-root (p x polish)
2879 (let* ((calc-prefer-frac nil)
2880 (calc-symbolic-mode nil)
2881 (iters 0)
2882 (m (1- (length p)))
2883 (try-newt (not polish))
2884 (tried-newt nil)
2885 b d f x1 dx dxold)
2886 (while
2887 (and (or (< (setq iters (1+ iters)) 50)
2888 (math-reject-arg x "*Laguerre's method failed to converge"))
2889 (let ((err (math-abs-approx (car p)))
2890 (abx (math-abs-approx x))
2891 (pp p))
2892 (setq b (car p)
2893 d 0 f 0)
2894 (while (setq pp (cdr pp))
2895 (setq f (math-add (math-mul x f) d)
2896 d (math-add (math-mul x d) b)
2897 b (math-add (math-mul x b) (car pp))
2898 err (math-add (math-abs-approx b) (math-mul abx err))))
2899 (math-lessp (calcFunc-scf err (- -2 calc-internal-prec))
2900 (math-abs-approx b)))
2901 (or (not (math-zerop d))
2902 (not (math-zerop f))
2903 (progn
2904 (setq x (math-pow (math-neg b) (list 'frac 1 m)))
2905 nil))
2906 (let* ((g (math-div d b))
2907 (g2 (math-sqr g))
2908 (h (math-sub g2 (math-mul 2 (math-div f b))))
2909 (sq (math-sqrt
2910 (math-mul (1- m) (math-sub (math-mul m h) g2))))
2911 (gp (math-add g sq))
2912 (gm (math-sub g sq)))
2913 (if (math-lessp (calcFunc-abssqr gp) (calcFunc-abssqr gm))
2914 (setq gp gm))
2915 (setq dx (math-div m gp)
2916 x1 (math-sub x dx))
2917 (if (and try-newt
2918 (math-lessp (math-abs-approx dx)
2919 (calcFunc-scf (math-abs-approx x) -3)))
2920 (let ((newt (math-poly-newton-root p x1 7)))
2921 (setq tried-newt t
2922 try-newt nil)
2923 (if (math-zerop (cdr newt))
2924 (setq x (car newt) x1 x)
2925 (if (math-lessp (cdr newt) '(float 1 -6))
2926 (let ((newt2 (math-poly-newton-root
2927 p (car newt) 20)))
2928 (if (math-zerop (cdr newt2))
2929 (setq x (car newt2) x1 x)
2930 (setq x (car newt))))))))
2931 (not (or (eq x x1)
2932 (math-nearly-equal x x1))))
2933 (let ((cdx (math-abs-approx dx)))
2934 (setq x x1
2935 tried-newt nil)
2936 (prog1
2937 (or (<= iters 6)
2938 (math-lessp cdx dxold)
2939 (progn
2940 (if polish
2941 (let ((digs (calcFunc-xpon
2942 (math-div (math-abs-approx x) cdx))))
2943 (calc-record-why
2944 "*Could not attain full precision")
2945 (if (natnump digs)
2946 (let ((calc-internal-prec (max 3 digs)))
2947 (setq x (math-normalize x))))))
2948 nil))
2949 (setq dxold cdx)))
2950 (or polish
2951 (math-lessp (calcFunc-scf (math-abs-approx x)
2952 (- calc-internal-prec))
2953 dxold))))
2954 (or (and (math-floatp x)
2955 (math-poly-integer-root x))
2956 x)))
2958 (defun math-solve-above-dummy (x)
2959 (and (not (Math-primp x))
2960 (if (and (equal (nth 1 x) '(var SOLVEDUM SOLVEDUM))
2961 (= (length x) 2))
2963 (let ((res nil))
2964 (while (and (setq x (cdr x))
2965 (not (setq res (math-solve-above-dummy (car x))))))
2966 res))))
2968 (defun math-solve-find-root-term (x neg) ; sets "t2", "t3"
2969 (if (math-solve-find-root-in-prod x)
2970 (setq t3 neg
2971 t1 x)
2972 (and (memq (car-safe x) '(+ -))
2973 (or (math-solve-find-root-term (nth 1 x) neg)
2974 (math-solve-find-root-term (nth 2 x)
2975 (if (eq (car x) '-) (not neg) neg))))))
2977 (defun math-solve-find-root-in-prod (x)
2978 (and (consp x)
2979 (math-expr-contains x solve-var)
2980 (or (and (eq (car x) 'calcFunc-sqrt)
2981 (setq t2 2))
2982 (and (eq (car x) '^)
2983 (or (and (memq (math-quarter-integer (nth 2 x)) '(1 2 3))
2984 (setq t2 2))
2985 (and (eq (car-safe (nth 2 x)) 'frac)
2986 (eq (nth 2 (nth 2 x)) 3)
2987 (setq t2 3))))
2988 (and (memq (car x) '(* /))
2989 (or (and (not (math-expr-contains (nth 1 x) solve-var))
2990 (math-solve-find-root-in-prod (nth 2 x)))
2991 (and (not (math-expr-contains (nth 2 x) solve-var))
2992 (math-solve-find-root-in-prod (nth 1 x))))))))
2995 (defun math-solve-system (exprs solve-vars solve-full)
2996 (setq exprs (mapcar 'list (if (Math-vectorp exprs)
2997 (cdr exprs)
2998 (list exprs)))
2999 solve-vars (if (Math-vectorp solve-vars)
3000 (cdr solve-vars)
3001 (list solve-vars)))
3002 (or (let ((math-solve-simplifying nil))
3003 (math-solve-system-rec exprs solve-vars nil))
3004 (let ((math-solve-simplifying t))
3005 (math-solve-system-rec exprs solve-vars nil))))
3007 ;;; The following backtracking solver works by choosing a variable
3008 ;;; and equation, and trying to solve the equation for the variable.
3009 ;;; If it succeeds it calls itself recursively with that variable and
3010 ;;; equation removed from their respective lists, and with the solution
3011 ;;; added to solns as well as being substituted into all existing
3012 ;;; equations. The algorithm terminates when any solution path
3013 ;;; manages to remove all the variables from var-list.
3015 ;;; To support calcFunc-roots, entries in eqn-list and solns are
3016 ;;; actually lists of equations.
3018 (defun math-solve-system-rec (eqn-list var-list solns)
3019 (if var-list
3020 (let ((v var-list)
3021 (res nil))
3023 ;; Try each variable in turn.
3024 (while
3025 (and
3027 (let* ((vv (car v))
3028 (e eqn-list)
3029 (elim (eq (car-safe vv) 'calcFunc-elim)))
3030 (if elim
3031 (setq vv (nth 1 vv)))
3033 ;; Try each equation in turn.
3034 (while
3035 (and
3037 (let ((e2 (car e))
3038 (eprev nil)
3039 res2)
3040 (setq res nil)
3042 ;; Try to solve for vv the list of equations e2.
3043 (while (and e2
3044 (setq res2 (or (and (eq (car e2) eprev)
3045 res2)
3046 (math-solve-for (car e2) 0 vv
3047 solve-full))))
3048 (setq eprev (car e2)
3049 res (cons (if (eq solve-full 'all)
3050 (cdr res2)
3051 (list res2))
3052 res)
3053 e2 (cdr e2)))
3054 (if e2
3055 (setq res nil)
3057 ;; Found a solution. Now try other variables.
3058 (setq res (nreverse res)
3059 res (math-solve-system-rec
3060 (mapcar
3061 'math-solve-system-subst
3062 (delq (car e)
3063 (copy-sequence eqn-list)))
3064 (delq (car v) (copy-sequence var-list))
3065 (let ((math-solve-simplifying nil)
3066 (s (mapcar
3067 (function
3068 (lambda (x)
3069 (cons
3070 (car x)
3071 (math-solve-system-subst
3072 (cdr x)))))
3073 solns)))
3074 (if elim
3076 (cons (cons vv (apply 'append res))
3077 s)))))
3078 (not res))))
3079 (setq e (cdr e)))
3080 (not res)))
3081 (setq v (cdr v)))
3082 res)
3084 ;; Eliminated all variables, so now put solution into the proper format.
3085 (setq solns (sort solns
3086 (function
3087 (lambda (x y)
3088 (not (memq (car x) (memq (car y) solve-vars)))))))
3089 (if (eq solve-full 'all)
3090 (math-transpose
3091 (math-normalize
3092 (cons 'vec
3093 (if solns
3094 (mapcar (function (lambda (x) (cons 'vec (cdr x)))) solns)
3095 (mapcar (function (lambda (x) (cons 'vec x))) eqn-list)))))
3096 (math-normalize
3097 (cons 'vec
3098 (if solns
3099 (mapcar (function (lambda (x) (cons 'calcFunc-eq x))) solns)
3100 (mapcar 'car eqn-list)))))))
3102 (defun math-solve-system-subst (x) ; uses "res" and "v"
3103 (let ((accum nil)
3104 (res2 res))
3105 (while x
3106 (setq accum (nconc accum
3107 (mapcar (function
3108 (lambda (r)
3109 (if math-solve-simplifying
3110 (math-simplify
3111 (math-expr-subst (car x) vv r))
3112 (math-expr-subst (car x) vv r))))
3113 (car res2)))
3114 x (cdr x)
3115 res2 (cdr res2)))
3116 accum))
3119 (defun math-get-from-counter (name)
3120 (let ((ctr (assq name calc-command-flags)))
3121 (if ctr
3122 (setcdr ctr (1+ (cdr ctr)))
3123 (setq ctr (cons name 1)
3124 calc-command-flags (cons ctr calc-command-flags)))
3125 (cdr ctr)))
3127 (defun math-solve-get-sign (val)
3128 (setq val (math-simplify val))
3129 (if (and (eq (car-safe val) '*)
3130 (Math-numberp (nth 1 val)))
3131 (list '* (nth 1 val) (math-solve-get-sign (nth 2 val)))
3132 (and (eq (car-safe val) 'calcFunc-sqrt)
3133 (eq (car-safe (nth 1 val)) '^)
3134 (setq val (math-normalize (list '^
3135 (nth 1 (nth 1 val))
3136 (math-div (nth 2 (nth 1 val)) 2)))))
3137 (if solve-full
3138 (if (and (calc-var-value 'var-GenCount)
3139 (Math-natnump var-GenCount)
3140 (not (eq solve-full 'all)))
3141 (prog1
3142 (math-mul (list 'calcFunc-as var-GenCount) val)
3143 (setq var-GenCount (math-add var-GenCount 1))
3144 (calc-refresh-evaltos 'var-GenCount))
3145 (let* ((var (concat "s" (int-to-string (math-get-from-counter 'solve-sign))))
3146 (var2 (list 'var (intern var) (intern (concat "var-" var)))))
3147 (if (eq solve-full 'all)
3148 (setq math-solve-ranges (cons (list var2 1 -1)
3149 math-solve-ranges)))
3150 (math-mul var2 val)))
3151 (calc-record-why "*Choosing positive solution")
3152 val)))
3154 (defun math-solve-get-int (val &optional range first)
3155 (if solve-full
3156 (if (and (calc-var-value 'var-GenCount)
3157 (Math-natnump var-GenCount)
3158 (not (eq solve-full 'all)))
3159 (prog1
3160 (math-mul val (list 'calcFunc-an var-GenCount))
3161 (setq var-GenCount (math-add var-GenCount 1))
3162 (calc-refresh-evaltos 'var-GenCount))
3163 (let* ((var (concat "n" (int-to-string
3164 (math-get-from-counter 'solve-int))))
3165 (var2 (list 'var (intern var) (intern (concat "var-" var)))))
3166 (if (and range (eq solve-full 'all))
3167 (setq math-solve-ranges (cons (cons var2
3168 (cdr (calcFunc-index
3169 range (or first 0))))
3170 math-solve-ranges)))
3171 (math-mul val var2)))
3172 (calc-record-why "*Choosing 0 for arbitrary integer in solution")
3175 (defun math-solve-sign (sign expr)
3176 (and sign
3177 (let ((s1 (math-possible-signs expr)))
3178 (cond ((memq s1 '(4 6))
3179 sign)
3180 ((memq s1 '(1 3))
3181 (- sign))))))
3183 (defun math-looks-evenp (expr)
3184 (if (Math-integerp expr)
3185 (math-evenp expr)
3186 (if (memq (car expr) '(* /))
3187 (math-looks-evenp (nth 1 expr)))))
3189 (defun math-solve-for (lhs rhs solve-var solve-full &optional sign)
3190 (if (math-expr-contains rhs solve-var)
3191 (math-solve-for (math-sub lhs rhs) 0 solve-var solve-full)
3192 (and (math-expr-contains lhs solve-var)
3193 (math-with-extra-prec 1
3194 (let* ((math-poly-base-variable solve-var)
3195 (res (math-try-solve-for lhs rhs sign)))
3196 (if (and (eq solve-full 'all)
3197 (math-known-realp solve-var))
3198 (let ((old-len (length res))
3199 new-len)
3200 (setq res (delq nil
3201 (mapcar (function
3202 (lambda (x)
3203 (and (not (memq (car-safe x)
3204 '(cplx polar)))
3205 x)))
3206 res))
3207 new-len (length res))
3208 (if (< new-len old-len)
3209 (calc-record-why (if (= new-len 1)
3210 "*All solutions were complex"
3211 (format
3212 "*Omitted %d complex solutions"
3213 (- old-len new-len)))))))
3214 res)))))
3216 (defun math-solve-eqn (expr var full)
3217 (if (memq (car-safe expr) '(calcFunc-neq calcFunc-lt calcFunc-gt
3218 calcFunc-leq calcFunc-geq))
3219 (let ((res (math-solve-for (cons '- (cdr expr))
3220 0 var full
3221 (if (eq (car expr) 'calcFunc-neq) nil 1))))
3222 (and res
3223 (if (eq math-solve-sign 1)
3224 (list (car expr) var res)
3225 (if (eq math-solve-sign -1)
3226 (list (car expr) res var)
3227 (or (eq (car expr) 'calcFunc-neq)
3228 (calc-record-why
3229 "*Can't determine direction of inequality"))
3230 (and (memq (car expr) '(calcFunc-neq calcFunc-lt calcFunc-gt))
3231 (list 'calcFunc-neq var res))))))
3232 (let ((res (math-solve-for expr 0 var full)))
3233 (and res
3234 (list 'calcFunc-eq var res)))))
3236 (defun math-reject-solution (expr var func)
3237 (if (math-expr-contains expr var)
3238 (or (equal (car calc-next-why) '(* "Unable to find a symbolic solution"))
3239 (calc-record-why "*Unable to find a solution")))
3240 (list func expr var))
3242 (defun calcFunc-solve (expr var)
3243 (or (if (or (Math-vectorp expr) (Math-vectorp var))
3244 (math-solve-system expr var nil)
3245 (math-solve-eqn expr var nil))
3246 (math-reject-solution expr var 'calcFunc-solve)))
3248 (defun calcFunc-fsolve (expr var)
3249 (or (if (or (Math-vectorp expr) (Math-vectorp var))
3250 (math-solve-system expr var t)
3251 (math-solve-eqn expr var t))
3252 (math-reject-solution expr var 'calcFunc-fsolve)))
3254 (defun calcFunc-roots (expr var)
3255 (let ((math-solve-ranges nil))
3256 (or (if (or (Math-vectorp expr) (Math-vectorp var))
3257 (math-solve-system expr var 'all)
3258 (math-solve-for expr 0 var 'all))
3259 (math-reject-solution expr var 'calcFunc-roots))))
3261 (defun calcFunc-finv (expr var)
3262 (let ((res (math-solve-for expr math-integ-var var nil)))
3263 (if res
3264 (math-normalize (math-expr-subst res math-integ-var var))
3265 (math-reject-solution expr var 'calcFunc-finv))))
3267 (defun calcFunc-ffinv (expr var)
3268 (let ((res (math-solve-for expr math-integ-var var t)))
3269 (if res
3270 (math-normalize (math-expr-subst res math-integ-var var))
3271 (math-reject-solution expr var 'calcFunc-finv))))
3274 (put 'calcFunc-inv 'math-inverse
3275 (function (lambda (x) (math-div 1 x))))
3276 (put 'calcFunc-inv 'math-inverse-sign -1)
3278 (put 'calcFunc-sqrt 'math-inverse
3279 (function (lambda (x) (math-sqr x))))
3281 (put 'calcFunc-conj 'math-inverse
3282 (function (lambda (x) (list 'calcFunc-conj x))))
3284 (put 'calcFunc-abs 'math-inverse
3285 (function (lambda (x) (math-solve-get-sign x))))
3287 (put 'calcFunc-deg 'math-inverse
3288 (function (lambda (x) (list 'calcFunc-rad x))))
3289 (put 'calcFunc-deg 'math-inverse-sign 1)
3291 (put 'calcFunc-rad 'math-inverse
3292 (function (lambda (x) (list 'calcFunc-deg x))))
3293 (put 'calcFunc-rad 'math-inverse-sign 1)
3295 (put 'calcFunc-ln 'math-inverse
3296 (function (lambda (x) (list 'calcFunc-exp x))))
3297 (put 'calcFunc-ln 'math-inverse-sign 1)
3299 (put 'calcFunc-log10 'math-inverse
3300 (function (lambda (x) (list 'calcFunc-exp10 x))))
3301 (put 'calcFunc-log10 'math-inverse-sign 1)
3303 (put 'calcFunc-lnp1 'math-inverse
3304 (function (lambda (x) (list 'calcFunc-expm1 x))))
3305 (put 'calcFunc-lnp1 'math-inverse-sign 1)
3307 (put 'calcFunc-exp 'math-inverse
3308 (function (lambda (x) (math-add (math-normalize (list 'calcFunc-ln x))
3309 (math-mul 2
3310 (math-mul '(var pi var-pi)
3311 (math-solve-get-int
3312 '(var i var-i))))))))
3313 (put 'calcFunc-exp 'math-inverse-sign 1)
3315 (put 'calcFunc-expm1 'math-inverse
3316 (function (lambda (x) (math-add (math-normalize (list 'calcFunc-lnp1 x))
3317 (math-mul 2
3318 (math-mul '(var pi var-pi)
3319 (math-solve-get-int
3320 '(var i var-i))))))))
3321 (put 'calcFunc-expm1 'math-inverse-sign 1)
3323 (put 'calcFunc-sin 'math-inverse
3324 (function (lambda (x) (let ((n (math-solve-get-int 1)))
3325 (math-add (math-mul (math-normalize
3326 (list 'calcFunc-arcsin x))
3327 (math-pow -1 n))
3328 (math-mul (math-half-circle t)
3329 n))))))
3331 (put 'calcFunc-cos 'math-inverse
3332 (function (lambda (x) (math-add (math-solve-get-sign
3333 (math-normalize
3334 (list 'calcFunc-arccos x)))
3335 (math-solve-get-int
3336 (math-full-circle t))))))
3338 (put 'calcFunc-tan 'math-inverse
3339 (function (lambda (x) (math-add (math-normalize (list 'calcFunc-arctan x))
3340 (math-solve-get-int
3341 (math-half-circle t))))))
3343 (put 'calcFunc-arcsin 'math-inverse
3344 (function (lambda (x) (math-normalize (list 'calcFunc-sin x)))))
3346 (put 'calcFunc-arccos 'math-inverse
3347 (function (lambda (x) (math-normalize (list 'calcFunc-cos x)))))
3349 (put 'calcFunc-arctan 'math-inverse
3350 (function (lambda (x) (math-normalize (list 'calcFunc-tan x)))))
3352 (put 'calcFunc-sinh 'math-inverse
3353 (function (lambda (x) (let ((n (math-solve-get-int 1)))
3354 (math-add (math-mul (math-normalize
3355 (list 'calcFunc-arcsinh x))
3356 (math-pow -1 n))
3357 (math-mul (math-half-circle t)
3358 (math-mul
3359 '(var i var-i)
3360 n)))))))
3361 (put 'calcFunc-sinh 'math-inverse-sign 1)
3363 (put 'calcFunc-cosh 'math-inverse
3364 (function (lambda (x) (math-add (math-solve-get-sign
3365 (math-normalize
3366 (list 'calcFunc-arccosh x)))
3367 (math-mul (math-full-circle t)
3368 (math-solve-get-int
3369 '(var i var-i)))))))
3371 (put 'calcFunc-tanh 'math-inverse
3372 (function (lambda (x) (math-add (math-normalize
3373 (list 'calcFunc-arctanh x))
3374 (math-mul (math-half-circle t)
3375 (math-solve-get-int
3376 '(var i var-i)))))))
3377 (put 'calcFunc-tanh 'math-inverse-sign 1)
3379 (put 'calcFunc-arcsinh 'math-inverse
3380 (function (lambda (x) (math-normalize (list 'calcFunc-sinh x)))))
3381 (put 'calcFunc-arcsinh 'math-inverse-sign 1)
3383 (put 'calcFunc-arccosh 'math-inverse
3384 (function (lambda (x) (math-normalize (list 'calcFunc-cosh x)))))
3386 (put 'calcFunc-arctanh 'math-inverse
3387 (function (lambda (x) (math-normalize (list 'calcFunc-tanh x)))))
3388 (put 'calcFunc-arctanh 'math-inverse-sign 1)
3392 (defun calcFunc-taylor (expr var num)
3393 (let ((x0 0) (v var))
3394 (if (memq (car-safe var) '(+ - calcFunc-eq))
3395 (setq x0 (if (eq (car var) '+) (math-neg (nth 2 var)) (nth 2 var))
3396 v (nth 1 var)))
3397 (or (and (eq (car-safe v) 'var)
3398 (math-expr-contains expr v)
3399 (natnump num)
3400 (let ((accum (math-expr-subst expr v x0))
3401 (var2 (if (eq (car var) 'calcFunc-eq)
3402 (cons '- (cdr var))
3403 var))
3404 (n 0)
3405 (nfac 1)
3406 (fprime expr))
3407 (while (and (<= (setq n (1+ n)) num)
3408 (setq fprime (calcFunc-deriv fprime v nil t)))
3409 (setq fprime (math-simplify fprime)
3410 nfac (math-mul nfac n)
3411 accum (math-add accum
3412 (math-div (math-mul (math-pow var2 n)
3413 (math-expr-subst
3414 fprime v x0))
3415 nfac))))
3416 (and fprime
3417 (math-normalize accum))))
3418 (list 'calcFunc-taylor expr var num))))
3420 ;;; calcalg2.el ends here