]> code.delx.au - gnu-emacs/blob - lisp/calc/calc-alg.el
Update copyright year to 2015
[gnu-emacs] / lisp / calc / calc-alg.el
1 ;;; calc-alg.el --- algebraic functions for Calc
2
3 ;; Copyright (C) 1990-1993, 2001-2015 Free Software Foundation, Inc.
4
5 ;; Author: David Gillespie <daveg@synaptics.com>
6 ;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23 ;;; Commentary:
24
25 ;;; Code:
26
27 ;; This file is autoloaded from calc-ext.el.
28
29 (require 'calc-ext)
30 (require 'calc-macs)
31
32 ;;; Algebra commands.
33
34 (defun calc-alg-evaluate (arg)
35 (interactive "p")
36 (calc-slow-wrapper
37 (calc-with-default-simplification
38 (let ((math-simplify-only nil))
39 (calc-modify-simplify-mode arg)
40 (calc-enter-result 1 "dsmp" (calc-top 1))))))
41
42 (defun calc-modify-simplify-mode (arg)
43 (if (= (math-abs arg) 2)
44 (setq calc-simplify-mode 'alg)
45 (if (>= (math-abs arg) 3)
46 (setq calc-simplify-mode 'ext)))
47 (if (< arg 0)
48 (setq calc-simplify-mode (list calc-simplify-mode))))
49
50 (defun calc-simplify ()
51 (interactive)
52 (calc-slow-wrapper
53 (let ((top (calc-top-n 1)))
54 (if (calc-is-inverse)
55 (setq top
56 (let ((calc-simplify-mode nil))
57 (math-normalize (math-trig-rewrite top)))))
58 (if (calc-is-hyperbolic)
59 (setq top
60 (let ((calc-simplify-mode nil))
61 (math-normalize (math-hyperbolic-trig-rewrite top)))))
62 (calc-with-default-simplification
63 (calc-enter-result 1 "simp" (math-simplify top))))))
64
65 (defun calc-simplify-extended ()
66 (interactive)
67 (calc-slow-wrapper
68 (calc-with-default-simplification
69 (calc-enter-result 1 "esmp" (math-simplify-extended (calc-top-n 1))))))
70
71 (defun calc-expand-formula (arg)
72 (interactive "p")
73 (calc-slow-wrapper
74 (calc-with-default-simplification
75 (let ((math-simplify-only nil))
76 (calc-modify-simplify-mode arg)
77 (calc-enter-result 1 "expf"
78 (if (> arg 0)
79 (let ((math-expand-formulas t))
80 (calc-top-n 1))
81 (let ((top (calc-top-n 1)))
82 (or (math-expand-formula top)
83 top))))))))
84
85 (defun calc-factor (arg)
86 (interactive "P")
87 (calc-slow-wrapper
88 (calc-unary-op "fctr" (if (calc-is-hyperbolic)
89 'calcFunc-factors 'calcFunc-factor)
90 arg)))
91
92 (defun calc-expand (n)
93 (interactive "P")
94 (calc-slow-wrapper
95 (calc-enter-result 1 "expa"
96 (append (list 'calcFunc-expand
97 (calc-top-n 1))
98 (and n (list (prefix-numeric-value n)))))))
99
100 ;;; Write out powers (a*b*...)^n as a*b*...*a*b*...
101 (defun calcFunc-powerexpand (expr)
102 (math-normalize (math-map-tree 'math-powerexpand expr)))
103
104 (defun math-powerexpand (expr)
105 (if (eq (car-safe expr) '^)
106 (let ((n (nth 2 expr)))
107 (cond ((and (integerp n)
108 (> n 0))
109 (let ((i 1)
110 (a (nth 1 expr))
111 (prod (nth 1 expr)))
112 (while (< i n)
113 (setq prod (math-mul prod a))
114 (setq i (1+ i)))
115 prod))
116 ((and (integerp n)
117 (< n 0))
118 (let ((i -1)
119 (a (math-pow (nth 1 expr) -1))
120 (prod (math-pow (nth 1 expr) -1)))
121 (while (> i n)
122 (setq prod (math-mul a prod))
123 (setq i (1- i)))
124 prod))
125 (t
126 expr)))
127 expr))
128
129 (defun calc-powerexpand ()
130 (interactive)
131 (calc-slow-wrapper
132 (calc-enter-result 1 "pexp"
133 (calcFunc-powerexpand (calc-top-n 1)))))
134
135 (defun calc-collect (&optional var)
136 (interactive "sCollect terms involving: ")
137 (calc-slow-wrapper
138 (if (or (equal var "") (equal var "$") (null var))
139 (calc-enter-result 2 "clct" (cons 'calcFunc-collect
140 (calc-top-list-n 2)))
141 (let ((var (math-read-expr var)))
142 (if (eq (car-safe var) 'error)
143 (error "Bad format in expression: %s" (nth 1 var)))
144 (calc-enter-result 1 "clct" (list 'calcFunc-collect
145 (calc-top-n 1)
146 var))))))
147
148 (defun calc-apart (arg)
149 (interactive "P")
150 (calc-slow-wrapper
151 (calc-unary-op "aprt" 'calcFunc-apart arg)))
152
153 (defun calc-normalize-rat (arg)
154 (interactive "P")
155 (calc-slow-wrapper
156 (calc-unary-op "nrat" 'calcFunc-nrat arg)))
157
158 (defun calc-poly-gcd (arg)
159 (interactive "P")
160 (calc-slow-wrapper
161 (calc-binary-op "pgcd" 'calcFunc-pgcd arg)))
162
163
164 (defun calc-poly-div (arg)
165 (interactive "P")
166 (calc-slow-wrapper
167 (let ((calc-poly-div-remainder nil))
168 (calc-binary-op "pdiv" 'calcFunc-pdiv arg)
169 (if (and calc-poly-div-remainder (null arg))
170 (progn
171 (calc-clear-command-flag 'clear-message)
172 (calc-record calc-poly-div-remainder "prem")
173 (if (not (Math-zerop calc-poly-div-remainder))
174 (message "(Remainder was %s)"
175 (math-format-flat-expr calc-poly-div-remainder 0))
176 (message "(No remainder)")))))))
177
178 (defun calc-poly-rem (arg)
179 (interactive "P")
180 (calc-slow-wrapper
181 (calc-binary-op "prem" 'calcFunc-prem arg)))
182
183 (defun calc-poly-div-rem (arg)
184 (interactive "P")
185 (calc-slow-wrapper
186 (if (calc-is-hyperbolic)
187 (calc-binary-op "pdvr" 'calcFunc-pdivide arg)
188 (calc-binary-op "pdvr" 'calcFunc-pdivrem arg))))
189
190 (defun calc-substitute (&optional oldname newname)
191 (interactive "sSubstitute old: ")
192 (calc-slow-wrapper
193 (let (old new (num 1) expr)
194 (if (or (equal oldname "") (equal oldname "$") (null oldname))
195 (setq new (calc-top-n 1)
196 old (calc-top-n 2)
197 expr (calc-top-n 3)
198 num 3)
199 (or newname
200 (progn (calc-unread-command ?\C-a)
201 (setq newname (read-string (concat "Substitute old: "
202 oldname
203 ", new: ")
204 oldname))))
205 (if (or (equal newname "") (equal newname "$") (null newname))
206 (setq new (calc-top-n 1)
207 expr (calc-top-n 2)
208 num 2)
209 (setq new (if (stringp newname) (math-read-expr newname) newname))
210 (if (eq (car-safe new) 'error)
211 (error "Bad format in expression: %s" (nth 1 new)))
212 (setq expr (calc-top-n 1)))
213 (setq old (if (stringp oldname) (math-read-expr oldname) oldname))
214 (if (eq (car-safe old) 'error)
215 (error "Bad format in expression: %s" (nth 1 old)))
216 (or (math-expr-contains expr old)
217 (error "No occurrences found")))
218 (calc-enter-result num "sbst" (math-expr-subst expr old new)))))
219
220
221 (defun calc-has-rules (name)
222 (setq name (calc-var-value name))
223 (and (consp name)
224 (memq (car name) '(vec calcFunc-assign calcFunc-condition))
225 name))
226
227 ;; math-eval-rules-cache and math-eval-rules-cache-other are
228 ;; declared in calc.el, but are used here by math-recompile-eval-rules.
229 (defvar math-eval-rules-cache)
230 (defvar math-eval-rules-cache-other)
231
232 (defun math-recompile-eval-rules ()
233 (setq math-eval-rules-cache (and (calc-has-rules 'var-EvalRules)
234 (math-compile-rewrites
235 '(var EvalRules var-EvalRules)))
236 math-eval-rules-cache-other (assq nil math-eval-rules-cache)
237 math-eval-rules-cache-tag (calc-var-value 'var-EvalRules)))
238
239
240 ;;; Try to expand a formula according to its definition.
241 (defun math-expand-formula (expr)
242 (and (consp expr)
243 (symbolp (car expr))
244 (or (get (car expr) 'calc-user-defn)
245 (get (car expr) 'math-expandable))
246 (let ((res (let ((math-expand-formulas t))
247 (apply (car expr) (cdr expr)))))
248 (and (not (eq (car-safe res) (car expr)))
249 res))))
250
251
252
253
254 ;;; True if A comes before B in a canonical ordering of expressions. [P X X]
255 (defun math-beforep (a b) ; [Public]
256 (cond ((and (Math-realp a) (Math-realp b))
257 (let ((comp (math-compare a b)))
258 (or (eq comp -1)
259 (and (eq comp 0)
260 (not (equal a b))
261 (> (length (memq (car-safe a)
262 '(bigneg nil bigpos frac float)))
263 (length (memq (car-safe b)
264 '(bigneg nil bigpos frac float))))))))
265 ((equal b '(neg (var inf var-inf))) nil)
266 ((equal a '(neg (var inf var-inf))) t)
267 ((equal a '(var inf var-inf)) nil)
268 ((equal b '(var inf var-inf)) t)
269 ((Math-realp a)
270 (if (and (eq (car-safe b) 'intv) (math-intv-constp b))
271 (if (or (math-beforep a (nth 2 b)) (Math-equal a (nth 2 b)))
272 t
273 nil)
274 t))
275 ((Math-realp b)
276 (if (and (eq (car-safe a) 'intv) (math-intv-constp a))
277 (if (math-beforep (nth 2 a) b)
278 t
279 nil)
280 nil))
281 ((and (eq (car a) 'intv) (eq (car b) 'intv)
282 (math-intv-constp a) (math-intv-constp b))
283 (let ((comp (math-compare (nth 2 a) (nth 2 b))))
284 (cond ((eq comp -1) t)
285 ((eq comp 1) nil)
286 ((and (memq (nth 1 a) '(2 3)) (memq (nth 1 b) '(0 1))) t)
287 ((and (memq (nth 1 a) '(0 1)) (memq (nth 1 b) '(2 3))) nil)
288 ((eq (setq comp (math-compare (nth 3 a) (nth 3 b))) -1) t)
289 ((eq comp 1) nil)
290 ((and (memq (nth 1 a) '(0 2)) (memq (nth 1 b) '(1 3))) t)
291 (t nil))))
292 ((not (eq (not (Math-objectp a)) (not (Math-objectp b))))
293 (Math-objectp a))
294 ((eq (car a) 'var)
295 (if (eq (car b) 'var)
296 (string-lessp (nth 1 a) (nth 1 b))
297 (not (Math-numberp b))))
298 ((eq (car b) 'var) (Math-numberp a))
299 ((eq (car a) (car b))
300 (while (and (setq a (cdr a) b (cdr b)) a
301 (equal (car a) (car b))))
302 (and b
303 (or (null a)
304 (math-beforep (car a) (car b)))))
305 (t (string-lessp (car a) (car b)))))
306
307
308 (defsubst math-simplify-extended (a)
309 (let ((math-living-dangerously t))
310 (math-simplify a)))
311
312 (defalias 'calcFunc-esimplify 'math-simplify-extended)
313
314 ;;; Rewrite the trig functions in a form easier to simplify.
315 (defun math-trig-rewrite (fn)
316 "Rewrite trigonometric functions in terms of sines and cosines."
317 (cond
318 ((not (consp fn))
319 fn)
320 ((eq (car-safe fn) 'calcFunc-sec)
321 (list '/ 1 (cons 'calcFunc-cos (math-trig-rewrite (cdr fn)))))
322 ((eq (car-safe fn) 'calcFunc-csc)
323 (list '/ 1 (cons 'calcFunc-sin (math-trig-rewrite (cdr fn)))))
324 ((eq (car-safe fn) 'calcFunc-tan)
325 (let ((newfn (math-trig-rewrite (cdr fn))))
326 (list '/ (cons 'calcFunc-sin newfn)
327 (cons 'calcFunc-cos newfn))))
328 ((eq (car-safe fn) 'calcFunc-cot)
329 (let ((newfn (math-trig-rewrite (cdr fn))))
330 (list '/ (cons 'calcFunc-cos newfn)
331 (cons 'calcFunc-sin newfn))))
332 (t
333 (mapcar 'math-trig-rewrite fn))))
334
335 (defun math-hyperbolic-trig-rewrite (fn)
336 "Rewrite hyperbolic functions in terms of sinhs and coshs."
337 (cond
338 ((not (consp fn))
339 fn)
340 ((eq (car-safe fn) 'calcFunc-sech)
341 (list '/ 1 (cons 'calcFunc-cosh (math-hyperbolic-trig-rewrite (cdr fn)))))
342 ((eq (car-safe fn) 'calcFunc-csch)
343 (list '/ 1 (cons 'calcFunc-sinh (math-hyperbolic-trig-rewrite (cdr fn)))))
344 ((eq (car-safe fn) 'calcFunc-tanh)
345 (let ((newfn (math-hyperbolic-trig-rewrite (cdr fn))))
346 (list '/ (cons 'calcFunc-sinh newfn)
347 (cons 'calcFunc-cosh newfn))))
348 ((eq (car-safe fn) 'calcFunc-coth)
349 (let ((newfn (math-hyperbolic-trig-rewrite (cdr fn))))
350 (list '/ (cons 'calcFunc-cosh newfn)
351 (cons 'calcFunc-sinh newfn))))
352 (t
353 (mapcar 'math-hyperbolic-trig-rewrite fn))))
354
355 ;; math-top-only is local to math-simplify, but is used by
356 ;; math-simplify-step, which is called by math-simplify.
357 (defvar math-top-only)
358
359 ;; math-normalize-error is declared in calc.el.
360 (defvar math-normalize-error)
361 (defun math-simplify (top-expr)
362 (let ((math-simplifying t)
363 (math-top-only (consp calc-simplify-mode))
364 (simp-rules (append (and (calc-has-rules 'var-AlgSimpRules)
365 '((var AlgSimpRules var-AlgSimpRules)))
366 (and math-living-dangerously
367 (calc-has-rules 'var-ExtSimpRules)
368 '((var ExtSimpRules var-ExtSimpRules)))
369 (and math-simplifying-units
370 (calc-has-rules 'var-UnitSimpRules)
371 '((var UnitSimpRules var-UnitSimpRules)))
372 (and math-integrating
373 (calc-has-rules 'var-IntegSimpRules)
374 '((var IntegSimpRules var-IntegSimpRules)))))
375 res)
376 (if math-top-only
377 (let ((r simp-rules))
378 (setq res (math-simplify-step (math-normalize top-expr))
379 calc-simplify-mode '(nil)
380 top-expr (math-normalize res))
381 (while r
382 (setq top-expr (math-rewrite top-expr (car r)
383 '(neg (var inf var-inf)))
384 r (cdr r))))
385 (calc-with-default-simplification
386 (while (let ((r simp-rules))
387 (setq res (math-normalize top-expr))
388 (if (not math-normalize-error)
389 (progn
390 (while r
391 (setq res (math-rewrite res (car r))
392 r (cdr r)))
393 (not (equal top-expr (setq res (math-simplify-step res)))))))
394 (setq top-expr res)))))
395 top-expr)
396
397 (defalias 'calcFunc-simplify 'math-simplify)
398
399 ;;; The following has a "bug" in that if any recursive simplifications
400 ;;; occur only the first handler will be tried; this doesn't really
401 ;;; matter, since math-simplify-step is iterated to a fixed point anyway.
402 (defun math-simplify-step (a)
403 (if (Math-primp a)
404 a
405 (let ((aa (if (or math-top-only
406 (memq (car a) '(calcFunc-quote calcFunc-condition
407 calcFunc-evalto)))
408 a
409 (cons (car a) (mapcar 'math-simplify-step (cdr a))))))
410 (and (symbolp (car aa))
411 (let ((handler (get (car aa) 'math-simplify)))
412 (and handler
413 (while (and handler
414 (equal (setq aa (or (funcall (car handler) aa)
415 aa))
416 a))
417 (setq handler (cdr handler))))))
418 aa)))
419
420
421 (defmacro math-defsimplify (funcs &rest code)
422 (cons 'progn
423 (mapcar #'(lambda (func)
424 `(put ',func 'math-simplify
425 (nconc
426 (get ',func 'math-simplify)
427 (list
428 #'(lambda (math-simplify-expr) ,@code)))))
429 (if (symbolp funcs) (list funcs) funcs))))
430 (put 'math-defsimplify 'lisp-indent-hook 1)
431
432 ;; The function created by math-defsimplify uses the variable
433 ;; math-simplify-expr, and so is used by functions in math-defsimplify
434 (defvar math-simplify-expr)
435
436 (math-defsimplify (+ -)
437 (math-simplify-plus))
438
439 (defun math-simplify-plus ()
440 (cond ((and (memq (car-safe (nth 1 math-simplify-expr)) '(+ -))
441 (Math-numberp (nth 2 (nth 1 math-simplify-expr)))
442 (not (Math-numberp (nth 2 math-simplify-expr))))
443 (let ((x (nth 2 math-simplify-expr))
444 (op (car math-simplify-expr)))
445 (setcar (cdr (cdr math-simplify-expr)) (nth 2 (nth 1 math-simplify-expr)))
446 (setcar math-simplify-expr (car (nth 1 math-simplify-expr)))
447 (setcar (cdr (cdr (nth 1 math-simplify-expr))) x)
448 (setcar (nth 1 math-simplify-expr) op)))
449 ((and (eq (car math-simplify-expr) '+)
450 (Math-numberp (nth 1 math-simplify-expr))
451 (not (Math-numberp (nth 2 math-simplify-expr))))
452 (let ((x (nth 2 math-simplify-expr)))
453 (setcar (cdr (cdr math-simplify-expr)) (nth 1 math-simplify-expr))
454 (setcar (cdr math-simplify-expr) x))))
455 (let ((aa math-simplify-expr)
456 aaa temp)
457 (while (memq (car-safe (setq aaa (nth 1 aa))) '(+ -))
458 (if (setq temp (math-combine-sum (nth 2 aaa) (nth 2 math-simplify-expr)
459 (eq (car aaa) '-)
460 (eq (car math-simplify-expr) '-) t))
461 (progn
462 (setcar (cdr (cdr math-simplify-expr)) temp)
463 (setcar math-simplify-expr '+)
464 (setcar (cdr (cdr aaa)) 0)))
465 (setq aa (nth 1 aa)))
466 (if (setq temp (math-combine-sum aaa (nth 2 math-simplify-expr)
467 nil (eq (car math-simplify-expr) '-) t))
468 (progn
469 (setcar (cdr (cdr math-simplify-expr)) temp)
470 (setcar math-simplify-expr '+)
471 (setcar (cdr aa) 0)))
472 math-simplify-expr))
473
474 (math-defsimplify *
475 (math-simplify-times))
476
477 (defun math-simplify-times ()
478 (if (eq (car-safe (nth 2 math-simplify-expr)) '*)
479 (and (math-beforep (nth 1 (nth 2 math-simplify-expr)) (nth 1 math-simplify-expr))
480 (or (math-known-scalarp (nth 1 math-simplify-expr) t)
481 (math-known-scalarp (nth 1 (nth 2 math-simplify-expr)) t))
482 (let ((x (nth 1 math-simplify-expr)))
483 (setcar (cdr math-simplify-expr) (nth 1 (nth 2 math-simplify-expr)))
484 (setcar (cdr (nth 2 math-simplify-expr)) x)))
485 (and (math-beforep (nth 2 math-simplify-expr) (nth 1 math-simplify-expr))
486 (or (math-known-scalarp (nth 1 math-simplify-expr) t)
487 (math-known-scalarp (nth 2 math-simplify-expr) t))
488 (let ((x (nth 2 math-simplify-expr)))
489 (setcar (cdr (cdr math-simplify-expr)) (nth 1 math-simplify-expr))
490 (setcar (cdr math-simplify-expr) x))))
491 (let ((aa math-simplify-expr)
492 aaa temp
493 (safe t) (scalar (math-known-scalarp (nth 1 math-simplify-expr))))
494 (if (and (Math-ratp (nth 1 math-simplify-expr))
495 (setq temp (math-common-constant-factor (nth 2 math-simplify-expr))))
496 (progn
497 (setcar (cdr (cdr math-simplify-expr))
498 (math-cancel-common-factor (nth 2 math-simplify-expr) temp))
499 (setcar (cdr math-simplify-expr) (math-mul (nth 1 math-simplify-expr) temp))))
500 (while (and (eq (car-safe (setq aaa (nth 2 aa))) '*)
501 safe)
502 (if (setq temp (math-combine-prod (nth 1 math-simplify-expr)
503 (nth 1 aaa) nil nil t))
504 (progn
505 (setcar (cdr math-simplify-expr) temp)
506 (setcar (cdr aaa) 1)))
507 (setq safe (or scalar (math-known-scalarp (nth 1 aaa) t))
508 aa (nth 2 aa)))
509 (if (and (setq temp (math-combine-prod aaa (nth 1 math-simplify-expr) nil nil t))
510 safe)
511 (progn
512 (setcar (cdr math-simplify-expr) temp)
513 (setcar (cdr (cdr aa)) 1)))
514 (if (and (eq (car-safe (nth 1 math-simplify-expr)) 'frac)
515 (memq (nth 1 (nth 1 math-simplify-expr)) '(1 -1)))
516 (math-div (math-mul (nth 2 math-simplify-expr)
517 (nth 1 (nth 1 math-simplify-expr)))
518 (nth 2 (nth 1 math-simplify-expr)))
519 math-simplify-expr)))
520
521 (math-defsimplify /
522 (math-simplify-divide))
523
524 (defun math-simplify-divide ()
525 (let ((np (cdr math-simplify-expr))
526 (nover nil)
527 (nn (and (or (eq (car math-simplify-expr) '/)
528 (not (Math-realp (nth 2 math-simplify-expr))))
529 (math-common-constant-factor (nth 2 math-simplify-expr))))
530 n op)
531 (if nn
532 (progn
533 (setq n (and (or (eq (car math-simplify-expr) '/)
534 (not (Math-realp (nth 1 math-simplify-expr))))
535 (math-common-constant-factor (nth 1 math-simplify-expr))))
536 (if (and (eq (car-safe nn) 'frac) (eq (nth 1 nn) 1) (not n))
537 (unless (and (eq (car-safe math-simplify-expr) 'calcFunc-eq)
538 (eq (car-safe (nth 1 math-simplify-expr)) 'var)
539 (not (math-expr-contains (nth 2 math-simplify-expr)
540 (nth 1 math-simplify-expr))))
541 (setcar (cdr math-simplify-expr)
542 (math-mul (nth 2 nn) (nth 1 math-simplify-expr)))
543 (setcar (cdr (cdr math-simplify-expr))
544 (math-cancel-common-factor (nth 2 math-simplify-expr) nn))
545 (if (and (math-negp nn)
546 (setq op (assq (car math-simplify-expr) calc-tweak-eqn-table)))
547 (setcar math-simplify-expr (nth 1 op))))
548 (if (and n (not (eq (setq n (math-frac-gcd n nn)) 1)))
549 (progn
550 (setcar (cdr math-simplify-expr)
551 (math-cancel-common-factor (nth 1 math-simplify-expr) n))
552 (setcar (cdr (cdr math-simplify-expr))
553 (math-cancel-common-factor (nth 2 math-simplify-expr) n))
554 (if (and (math-negp n)
555 (setq op (assq (car math-simplify-expr)
556 calc-tweak-eqn-table)))
557 (setcar math-simplify-expr (nth 1 op))))))))
558 (if (and (eq (car-safe (car np)) '/)
559 (math-known-scalarp (nth 2 math-simplify-expr) t))
560 (progn
561 (setq np (cdr (nth 1 math-simplify-expr)))
562 (while (eq (car-safe (setq n (car np))) '*)
563 (and (math-known-scalarp (nth 2 n) t)
564 (math-simplify-divisor (cdr n) (cdr (cdr math-simplify-expr)) nil t))
565 (setq np (cdr (cdr n))))
566 (math-simplify-divisor np (cdr (cdr math-simplify-expr)) nil t)
567 (setq nover t
568 np (cdr (cdr (nth 1 math-simplify-expr))))))
569 (while (eq (car-safe (setq n (car np))) '*)
570 (and (math-known-scalarp (nth 2 n) t)
571 (math-simplify-divisor (cdr n) (cdr (cdr math-simplify-expr)) nover t))
572 (setq np (cdr (cdr n))))
573 (math-simplify-divisor np (cdr (cdr math-simplify-expr)) nover t)
574 math-simplify-expr))
575
576 ;; The variables math-simplify-divisor-nover and math-simplify-divisor-dover
577 ;; are local variables for math-simplify-divisor, but are used by
578 ;; math-simplify-one-divisor.
579 (defvar math-simplify-divisor-nover)
580 (defvar math-simplify-divisor-dover)
581
582 (defun math-simplify-divisor (np dp math-simplify-divisor-nover
583 math-simplify-divisor-dover)
584 (cond ((eq (car-safe (car dp)) '/)
585 (math-simplify-divisor np (cdr (car dp))
586 math-simplify-divisor-nover
587 math-simplify-divisor-dover)
588 (and (math-known-scalarp (nth 1 (car dp)) t)
589 (math-simplify-divisor np (cdr (cdr (car dp)))
590 math-simplify-divisor-nover
591 (not math-simplify-divisor-dover))))
592 ((or (or (eq (car math-simplify-expr) '/)
593 (let ((signs (math-possible-signs (car np))))
594 (or (memq signs '(1 4))
595 (and (memq (car math-simplify-expr) '(calcFunc-eq calcFunc-neq))
596 (eq signs 5))
597 math-living-dangerously)))
598 (math-numberp (car np)))
599 (let (d
600 (safe t)
601 (scalar (math-known-scalarp (car np))))
602 (while (and (eq (car-safe (setq d (car dp))) '*)
603 safe)
604 (math-simplify-one-divisor np (cdr d))
605 (setq safe (or scalar (math-known-scalarp (nth 1 d) t))
606 dp (cdr (cdr d))))
607 (if safe
608 (math-simplify-one-divisor np dp))))))
609
610 (defun math-simplify-one-divisor (np dp)
611 (let ((temp (math-combine-prod (car np) (car dp) math-simplify-divisor-nover
612 math-simplify-divisor-dover t))
613 op)
614 (if temp
615 (progn
616 (and (not (memq (car math-simplify-expr) '(/ calcFunc-eq calcFunc-neq)))
617 (math-known-negp (car dp))
618 (setq op (assq (car math-simplify-expr) calc-tweak-eqn-table))
619 (setcar math-simplify-expr (nth 1 op)))
620 (setcar np (if math-simplify-divisor-nover (math-div 1 temp) temp))
621 (setcar dp 1))
622 (and math-simplify-divisor-dover (not math-simplify-divisor-nover)
623 (eq (car math-simplify-expr) '/)
624 (eq (car-safe (car dp)) 'calcFunc-sqrt)
625 (Math-integerp (nth 1 (car dp)))
626 (progn
627 (setcar np (math-mul (car np)
628 (list 'calcFunc-sqrt (nth 1 (car dp)))))
629 (setcar dp (nth 1 (car dp))))))))
630
631 (defun math-common-constant-factor (expr)
632 (if (Math-realp expr)
633 (if (Math-ratp expr)
634 (and (not (memq expr '(0 1 -1)))
635 (math-abs expr))
636 (if (math-ratp (setq expr (math-to-simple-fraction expr)))
637 (math-common-constant-factor expr)))
638 (if (memq (car expr) '(+ - cplx sdev))
639 (let ((f1 (math-common-constant-factor (nth 1 expr)))
640 (f2 (math-common-constant-factor (nth 2 expr))))
641 (and f1 f2
642 (not (eq (setq f1 (math-frac-gcd f1 f2)) 1))
643 f1))
644 (if (memq (car expr) '(* polar))
645 (math-common-constant-factor (nth 1 expr))
646 (if (eq (car expr) '/)
647 (or (math-common-constant-factor (nth 1 expr))
648 (and (Math-integerp (nth 2 expr))
649 (list 'frac 1 (math-abs (nth 2 expr))))))))))
650
651 (defun math-cancel-common-factor (expr val)
652 (if (memq (car-safe expr) '(+ - cplx sdev))
653 (progn
654 (setcar (cdr expr) (math-cancel-common-factor (nth 1 expr) val))
655 (setcar (cdr (cdr expr)) (math-cancel-common-factor (nth 2 expr) val))
656 expr)
657 (if (eq (car-safe expr) '*)
658 (math-mul (math-cancel-common-factor (nth 1 expr) val) (nth 2 expr))
659 (math-div expr val))))
660
661 (defun math-frac-gcd (a b)
662 (if (Math-zerop a)
663 b
664 (if (Math-zerop b)
665 a
666 (if (and (Math-integerp a)
667 (Math-integerp b))
668 (math-gcd a b)
669 (and (Math-integerp a) (setq a (list 'frac a 1)))
670 (and (Math-integerp b) (setq b (list 'frac b 1)))
671 (math-make-frac (math-gcd (nth 1 a) (nth 1 b))
672 (math-gcd (nth 2 a) (nth 2 b)))))))
673
674 (math-defsimplify %
675 (math-simplify-mod))
676
677 (defun math-simplify-mod ()
678 (and (Math-realp (nth 2 math-simplify-expr))
679 (Math-posp (nth 2 math-simplify-expr))
680 (let ((lin (math-is-linear (nth 1 math-simplify-expr)))
681 t1 t2 t3)
682 (or (and lin
683 (or (math-negp (car lin))
684 (not (Math-lessp (car lin) (nth 2 math-simplify-expr))))
685 (list '%
686 (list '+
687 (math-mul (nth 1 lin) (nth 2 lin))
688 (math-mod (car lin) (nth 2 math-simplify-expr)))
689 (nth 2 math-simplify-expr)))
690 (and lin
691 (not (math-equal-int (nth 1 lin) 1))
692 (math-num-integerp (nth 1 lin))
693 (math-num-integerp (nth 2 math-simplify-expr))
694 (setq t1 (calcFunc-gcd (nth 1 lin) (nth 2 math-simplify-expr)))
695 (not (math-equal-int t1 1))
696 (list '*
697 t1
698 (list '%
699 (list '+
700 (math-mul (math-div (nth 1 lin) t1)
701 (nth 2 lin))
702 (let ((calc-prefer-frac t))
703 (math-div (car lin) t1)))
704 (math-div (nth 2 math-simplify-expr) t1))))
705 (and (math-equal-int (nth 2 math-simplify-expr) 1)
706 (math-known-integerp (if lin
707 (math-mul (nth 1 lin) (nth 2 lin))
708 (nth 1 math-simplify-expr)))
709 (if lin (math-mod (car lin) 1) 0))))))
710
711 (math-defsimplify (calcFunc-eq calcFunc-neq calcFunc-lt
712 calcFunc-gt calcFunc-leq calcFunc-geq)
713 (if (= (length math-simplify-expr) 3)
714 (math-simplify-ineq)))
715
716 (defun math-simplify-ineq ()
717 (let ((np (cdr math-simplify-expr))
718 n)
719 (while (memq (car-safe (setq n (car np))) '(+ -))
720 (math-simplify-add-term (cdr (cdr n)) (cdr (cdr math-simplify-expr))
721 (eq (car n) '-) nil)
722 (setq np (cdr n)))
723 (math-simplify-add-term np (cdr (cdr math-simplify-expr)) nil
724 (eq np (cdr math-simplify-expr)))
725 (math-simplify-divide)
726 (let ((signs (math-possible-signs (cons '- (cdr math-simplify-expr)))))
727 (or (cond ((eq (car math-simplify-expr) 'calcFunc-eq)
728 (or (and (eq signs 2) 1)
729 (and (memq signs '(1 4 5)) 0)))
730 ((eq (car math-simplify-expr) 'calcFunc-neq)
731 (or (and (eq signs 2) 0)
732 (and (memq signs '(1 4 5)) 1)))
733 ((eq (car math-simplify-expr) 'calcFunc-lt)
734 (or (and (eq signs 1) 1)
735 (and (memq signs '(2 4 6)) 0)))
736 ((eq (car math-simplify-expr) 'calcFunc-gt)
737 (or (and (eq signs 4) 1)
738 (and (memq signs '(1 2 3)) 0)))
739 ((eq (car math-simplify-expr) 'calcFunc-leq)
740 (or (and (eq signs 4) 0)
741 (and (memq signs '(1 2 3)) 1)))
742 ((eq (car math-simplify-expr) 'calcFunc-geq)
743 (or (and (eq signs 1) 0)
744 (and (memq signs '(2 4 6)) 1))))
745 math-simplify-expr))))
746
747 (defun math-simplify-add-term (np dp minus lplain)
748 (or (math-vectorp (car np))
749 (let ((rplain t)
750 n d dd temp)
751 (while (memq (car-safe (setq n (car np) d (car dp))) '(+ -))
752 (setq rplain nil)
753 (if (setq temp (math-combine-sum n (nth 2 d)
754 minus (eq (car d) '+) t))
755 (if (or lplain (eq (math-looks-negp temp) minus))
756 (progn
757 (setcar np (setq n (if minus (math-neg temp) temp)))
758 (setcar (cdr (cdr d)) 0))
759 (progn
760 (setcar np 0)
761 (setcar (cdr (cdr d)) (setq n (if (eq (car d) '+)
762 (math-neg temp)
763 temp))))))
764 (setq dp (cdr d)))
765 (if (setq temp (math-combine-sum n d minus t t))
766 (if (or lplain
767 (and (not rplain)
768 (eq (math-looks-negp temp) minus)))
769 (progn
770 (setcar np (setq n (if minus (math-neg temp) temp)))
771 (setcar dp 0))
772 (progn
773 (setcar np 0)
774 (setcar dp (setq n (math-neg temp)))))))))
775
776 (math-defsimplify calcFunc-sin
777 (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsin)
778 (nth 1 (nth 1 math-simplify-expr)))
779 (and (math-looks-negp (nth 1 math-simplify-expr))
780 (math-neg (list 'calcFunc-sin (math-neg (nth 1 math-simplify-expr)))))
781 (and (eq calc-angle-mode 'rad)
782 (let ((n (math-linear-in (nth 1 math-simplify-expr) '(var pi var-pi))))
783 (and n
784 (math-known-sin (car n) (nth 1 n) 120 0))))
785 (and (eq calc-angle-mode 'deg)
786 (let ((n (math-integer-plus (nth 1 math-simplify-expr))))
787 (and n
788 (math-known-sin (car n) (nth 1 n) '(frac 2 3) 0))))
789 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccos)
790 (list 'calcFunc-sqrt (math-sub 1 (math-sqr
791 (nth 1 (nth 1 math-simplify-expr))))))
792 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctan)
793 (math-div (nth 1 (nth 1 math-simplify-expr))
794 (list 'calcFunc-sqrt
795 (math-add 1 (math-sqr
796 (nth 1 (nth 1 math-simplify-expr)))))))
797 (let ((m (math-should-expand-trig (nth 1 math-simplify-expr))))
798 (and m (integerp (car m))
799 (let ((n (car m)) (a (nth 1 m)))
800 (list '+
801 (list '* (list 'calcFunc-sin (list '* (1- n) a))
802 (list 'calcFunc-cos a))
803 (list '* (list 'calcFunc-cos (list '* (1- n) a))
804 (list 'calcFunc-sin a))))))))
805
806 (math-defsimplify calcFunc-cos
807 (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccos)
808 (nth 1 (nth 1 math-simplify-expr)))
809 (and (math-looks-negp (nth 1 math-simplify-expr))
810 (list 'calcFunc-cos (math-neg (nth 1 math-simplify-expr))))
811 (and (eq calc-angle-mode 'rad)
812 (let ((n (math-linear-in (nth 1 math-simplify-expr) '(var pi var-pi))))
813 (and n
814 (math-known-sin (car n) (nth 1 n) 120 300))))
815 (and (eq calc-angle-mode 'deg)
816 (let ((n (math-integer-plus (nth 1 math-simplify-expr))))
817 (and n
818 (math-known-sin (car n) (nth 1 n) '(frac 2 3) 300))))
819 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsin)
820 (list 'calcFunc-sqrt
821 (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr))))))
822 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctan)
823 (math-div 1
824 (list 'calcFunc-sqrt
825 (math-add 1
826 (math-sqr (nth 1 (nth 1 math-simplify-expr)))))))
827 (let ((m (math-should-expand-trig (nth 1 math-simplify-expr))))
828 (and m (integerp (car m))
829 (let ((n (car m)) (a (nth 1 m)))
830 (list '-
831 (list '* (list 'calcFunc-cos (list '* (1- n) a))
832 (list 'calcFunc-cos a))
833 (list '* (list 'calcFunc-sin (list '* (1- n) a))
834 (list 'calcFunc-sin a))))))))
835
836 (math-defsimplify calcFunc-sec
837 (or (and (math-looks-negp (nth 1 math-simplify-expr))
838 (list 'calcFunc-sec (math-neg (nth 1 math-simplify-expr))))
839 (and (eq calc-angle-mode 'rad)
840 (let ((n (math-linear-in (nth 1 math-simplify-expr) '(var pi var-pi))))
841 (and n
842 (math-div 1 (math-known-sin (car n) (nth 1 n) 120 300)))))
843 (and (eq calc-angle-mode 'deg)
844 (let ((n (math-integer-plus (nth 1 math-simplify-expr))))
845 (and n
846 (math-div 1 (math-known-sin (car n) (nth 1 n) '(frac 2 3) 300)))))
847 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsin)
848 (math-div
849 1
850 (list 'calcFunc-sqrt
851 (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr)))))))
852 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccos)
853 (math-div
854 1
855 (nth 1 (nth 1 math-simplify-expr))))
856 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctan)
857 (list 'calcFunc-sqrt
858 (math-add 1
859 (math-sqr (nth 1 (nth 1 math-simplify-expr))))))))
860
861 (math-defsimplify calcFunc-csc
862 (or (and (math-looks-negp (nth 1 math-simplify-expr))
863 (math-neg (list 'calcFunc-csc (math-neg (nth 1 math-simplify-expr)))))
864 (and (eq calc-angle-mode 'rad)
865 (let ((n (math-linear-in (nth 1 math-simplify-expr) '(var pi var-pi))))
866 (and n
867 (math-div 1 (math-known-sin (car n) (nth 1 n) 120 0)))))
868 (and (eq calc-angle-mode 'deg)
869 (let ((n (math-integer-plus (nth 1 math-simplify-expr))))
870 (and n
871 (math-div 1 (math-known-sin (car n) (nth 1 n) '(frac 2 3) 0)))))
872 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsin)
873 (math-div 1 (nth 1 (nth 1 math-simplify-expr))))
874 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccos)
875 (math-div
876 1
877 (list 'calcFunc-sqrt (math-sub 1 (math-sqr
878 (nth 1 (nth 1 math-simplify-expr)))))))
879 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctan)
880 (math-div (list 'calcFunc-sqrt
881 (math-add 1 (math-sqr
882 (nth 1 (nth 1 math-simplify-expr)))))
883 (nth 1 (nth 1 math-simplify-expr))))))
884
885 (defun math-should-expand-trig (x &optional hyperbolic)
886 (let ((m (math-is-multiple x)))
887 (and math-living-dangerously
888 m (or (and (integerp (car m)) (> (car m) 1))
889 (equal (car m) '(frac 1 2)))
890 (or math-integrating
891 (memq (car-safe (nth 1 m))
892 (if hyperbolic
893 '(calcFunc-arcsinh calcFunc-arccosh calcFunc-arctanh)
894 '(calcFunc-arcsin calcFunc-arccos calcFunc-arctan)))
895 (and (eq (car-safe (nth 1 m)) 'calcFunc-ln)
896 (eq hyperbolic 'exp)))
897 m)))
898
899 (defun math-known-sin (plus n mul off)
900 (setq n (math-mul n mul))
901 (and (math-num-integerp n)
902 (setq n (math-mod (math-add (math-trunc n) off) 240))
903 (if (>= n 120)
904 (and (setq n (math-known-sin plus (- n 120) 1 0))
905 (math-neg n))
906 (if (> n 60)
907 (setq n (- 120 n)))
908 (if (math-zerop plus)
909 (and (or calc-symbolic-mode
910 (memq n '(0 20 60)))
911 (cdr (assq n
912 '( (0 . 0)
913 (10 . (/ (calcFunc-sqrt
914 (- 2 (calcFunc-sqrt 3))) 2))
915 (12 . (/ (- (calcFunc-sqrt 5) 1) 4))
916 (15 . (/ (calcFunc-sqrt
917 (- 2 (calcFunc-sqrt 2))) 2))
918 (20 . (/ 1 2))
919 (24 . (* (^ (/ 1 2) (/ 3 2))
920 (calcFunc-sqrt
921 (- 5 (calcFunc-sqrt 5)))))
922 (30 . (/ (calcFunc-sqrt 2) 2))
923 (36 . (/ (+ (calcFunc-sqrt 5) 1) 4))
924 (40 . (/ (calcFunc-sqrt 3) 2))
925 (45 . (/ (calcFunc-sqrt
926 (+ 2 (calcFunc-sqrt 2))) 2))
927 (48 . (* (^ (/ 1 2) (/ 3 2))
928 (calcFunc-sqrt
929 (+ 5 (calcFunc-sqrt 5)))))
930 (50 . (/ (calcFunc-sqrt
931 (+ 2 (calcFunc-sqrt 3))) 2))
932 (60 . 1)))))
933 (cond ((eq n 0) (math-normalize (list 'calcFunc-sin plus)))
934 ((eq n 60) (math-normalize (list 'calcFunc-cos plus)))
935 (t nil))))))
936
937 (math-defsimplify calcFunc-tan
938 (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctan)
939 (nth 1 (nth 1 math-simplify-expr)))
940 (and (math-looks-negp (nth 1 math-simplify-expr))
941 (math-neg (list 'calcFunc-tan (math-neg (nth 1 math-simplify-expr)))))
942 (and (eq calc-angle-mode 'rad)
943 (let ((n (math-linear-in (nth 1 math-simplify-expr) '(var pi var-pi))))
944 (and n
945 (math-known-tan (car n) (nth 1 n) 120))))
946 (and (eq calc-angle-mode 'deg)
947 (let ((n (math-integer-plus (nth 1 math-simplify-expr))))
948 (and n
949 (math-known-tan (car n) (nth 1 n) '(frac 2 3)))))
950 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsin)
951 (math-div (nth 1 (nth 1 math-simplify-expr))
952 (list 'calcFunc-sqrt
953 (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr)))))))
954 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccos)
955 (math-div (list 'calcFunc-sqrt
956 (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr)))))
957 (nth 1 (nth 1 math-simplify-expr))))
958 (let ((m (math-should-expand-trig (nth 1 math-simplify-expr))))
959 (and m
960 (if (equal (car m) '(frac 1 2))
961 (math-div (math-sub 1 (list 'calcFunc-cos (nth 1 m)))
962 (list 'calcFunc-sin (nth 1 m)))
963 (math-div (list 'calcFunc-sin (nth 1 math-simplify-expr))
964 (list 'calcFunc-cos (nth 1 math-simplify-expr))))))))
965
966 (math-defsimplify calcFunc-cot
967 (or (and (math-looks-negp (nth 1 math-simplify-expr))
968 (math-neg (list 'calcFunc-cot (math-neg (nth 1 math-simplify-expr)))))
969 (and (eq calc-angle-mode 'rad)
970 (let ((n (math-linear-in (nth 1 math-simplify-expr) '(var pi var-pi))))
971 (and n
972 (math-div 1 (math-known-tan (car n) (nth 1 n) 120)))))
973 (and (eq calc-angle-mode 'deg)
974 (let ((n (math-integer-plus (nth 1 math-simplify-expr))))
975 (and n
976 (math-div 1 (math-known-tan (car n) (nth 1 n) '(frac 2 3))))))
977 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsin)
978 (math-div (list 'calcFunc-sqrt
979 (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr)))))
980 (nth 1 (nth 1 math-simplify-expr))))
981 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccos)
982 (math-div (nth 1 (nth 1 math-simplify-expr))
983 (list 'calcFunc-sqrt
984 (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr)))))))
985 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctan)
986 (math-div 1 (nth 1 (nth 1 math-simplify-expr))))))
987
988 (defun math-known-tan (plus n mul)
989 (setq n (math-mul n mul))
990 (and (math-num-integerp n)
991 (setq n (math-mod (math-trunc n) 120))
992 (if (> n 60)
993 (and (setq n (math-known-tan plus (- 120 n) 1))
994 (math-neg n))
995 (if (math-zerop plus)
996 (and (or calc-symbolic-mode
997 (memq n '(0 30 60)))
998 (cdr (assq n '( (0 . 0)
999 (10 . (- 2 (calcFunc-sqrt 3)))
1000 (12 . (calcFunc-sqrt
1001 (- 1 (* (/ 2 5) (calcFunc-sqrt 5)))))
1002 (15 . (- (calcFunc-sqrt 2) 1))
1003 (20 . (/ (calcFunc-sqrt 3) 3))
1004 (24 . (calcFunc-sqrt
1005 (- 5 (* 2 (calcFunc-sqrt 5)))))
1006 (30 . 1)
1007 (36 . (calcFunc-sqrt
1008 (+ 1 (* (/ 2 5) (calcFunc-sqrt 5)))))
1009 (40 . (calcFunc-sqrt 3))
1010 (45 . (+ (calcFunc-sqrt 2) 1))
1011 (48 . (calcFunc-sqrt
1012 (+ 5 (* 2 (calcFunc-sqrt 5)))))
1013 (50 . (+ 2 (calcFunc-sqrt 3)))
1014 (60 . (var uinf var-uinf))))))
1015 (cond ((eq n 0) (math-normalize (list 'calcFunc-tan plus)))
1016 ((eq n 60) (math-normalize (list '/ -1
1017 (list 'calcFunc-tan plus))))
1018 (t nil))))))
1019
1020 (math-defsimplify calcFunc-sinh
1021 (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsinh)
1022 (nth 1 (nth 1 math-simplify-expr)))
1023 (and (math-looks-negp (nth 1 math-simplify-expr))
1024 (math-neg (list 'calcFunc-sinh (math-neg (nth 1 math-simplify-expr)))))
1025 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccosh)
1026 math-living-dangerously
1027 (list 'calcFunc-sqrt
1028 (math-sub (math-sqr (nth 1 (nth 1 math-simplify-expr))) 1)))
1029 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctanh)
1030 math-living-dangerously
1031 (math-div (nth 1 (nth 1 math-simplify-expr))
1032 (list 'calcFunc-sqrt
1033 (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr)))))))
1034 (let ((m (math-should-expand-trig (nth 1 math-simplify-expr) t)))
1035 (and m (integerp (car m))
1036 (let ((n (car m)) (a (nth 1 m)))
1037 (if (> n 1)
1038 (list '+
1039 (list '* (list 'calcFunc-sinh (list '* (1- n) a))
1040 (list 'calcFunc-cosh a))
1041 (list '* (list 'calcFunc-cosh (list '* (1- n) a))
1042 (list 'calcFunc-sinh a)))))))))
1043
1044 (math-defsimplify calcFunc-cosh
1045 (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccosh)
1046 (nth 1 (nth 1 math-simplify-expr)))
1047 (and (math-looks-negp (nth 1 math-simplify-expr))
1048 (list 'calcFunc-cosh (math-neg (nth 1 math-simplify-expr))))
1049 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsinh)
1050 math-living-dangerously
1051 (list 'calcFunc-sqrt
1052 (math-add (math-sqr (nth 1 (nth 1 math-simplify-expr))) 1)))
1053 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctanh)
1054 math-living-dangerously
1055 (math-div 1
1056 (list 'calcFunc-sqrt
1057 (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr)))))))
1058 (let ((m (math-should-expand-trig (nth 1 math-simplify-expr) t)))
1059 (and m (integerp (car m))
1060 (let ((n (car m)) (a (nth 1 m)))
1061 (if (> n 1)
1062 (list '+
1063 (list '* (list 'calcFunc-cosh (list '* (1- n) a))
1064 (list 'calcFunc-cosh a))
1065 (list '* (list 'calcFunc-sinh (list '* (1- n) a))
1066 (list 'calcFunc-sinh a)))))))))
1067
1068 (math-defsimplify calcFunc-tanh
1069 (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctanh)
1070 (nth 1 (nth 1 math-simplify-expr)))
1071 (and (math-looks-negp (nth 1 math-simplify-expr))
1072 (math-neg (list 'calcFunc-tanh (math-neg (nth 1 math-simplify-expr)))))
1073 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsinh)
1074 math-living-dangerously
1075 (math-div (nth 1 (nth 1 math-simplify-expr))
1076 (list 'calcFunc-sqrt
1077 (math-add (math-sqr (nth 1 (nth 1 math-simplify-expr))) 1))))
1078 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccosh)
1079 math-living-dangerously
1080 (math-div (list 'calcFunc-sqrt
1081 (math-sub (math-sqr (nth 1 (nth 1 math-simplify-expr))) 1))
1082 (nth 1 (nth 1 math-simplify-expr))))
1083 (let ((m (math-should-expand-trig (nth 1 math-simplify-expr) t)))
1084 (and m
1085 (if (equal (car m) '(frac 1 2))
1086 (math-div (math-sub (list 'calcFunc-cosh (nth 1 m)) 1)
1087 (list 'calcFunc-sinh (nth 1 m)))
1088 (math-div (list 'calcFunc-sinh (nth 1 math-simplify-expr))
1089 (list 'calcFunc-cosh (nth 1 math-simplify-expr))))))))
1090
1091 (math-defsimplify calcFunc-sech
1092 (or (and (math-looks-negp (nth 1 math-simplify-expr))
1093 (list 'calcFunc-sech (math-neg (nth 1 math-simplify-expr))))
1094 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsinh)
1095 math-living-dangerously
1096 (math-div
1097 1
1098 (list 'calcFunc-sqrt
1099 (math-add (math-sqr (nth 1 (nth 1 math-simplify-expr))) 1))))
1100 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccosh)
1101 math-living-dangerously
1102 (math-div 1 (nth 1 (nth 1 math-simplify-expr))) 1)
1103 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctanh)
1104 math-living-dangerously
1105 (list 'calcFunc-sqrt
1106 (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr))))))))
1107
1108 (math-defsimplify calcFunc-csch
1109 (or (and (math-looks-negp (nth 1 math-simplify-expr))
1110 (math-neg (list 'calcFunc-csch (math-neg (nth 1 math-simplify-expr)))))
1111 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsinh)
1112 math-living-dangerously
1113 (math-div 1 (nth 1 (nth 1 math-simplify-expr))))
1114 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccosh)
1115 math-living-dangerously
1116 (math-div
1117 1
1118 (list 'calcFunc-sqrt
1119 (math-sub (math-sqr (nth 1 (nth 1 math-simplify-expr))) 1))))
1120 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctanh)
1121 math-living-dangerously
1122 (math-div (list 'calcFunc-sqrt
1123 (math-sub 1 (math-sqr (nth 1 (nth 1 math-simplify-expr)))))
1124 (nth 1 (nth 1 math-simplify-expr))))))
1125
1126 (math-defsimplify calcFunc-coth
1127 (or (and (math-looks-negp (nth 1 math-simplify-expr))
1128 (math-neg (list 'calcFunc-coth (math-neg (nth 1 math-simplify-expr)))))
1129 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arcsinh)
1130 math-living-dangerously
1131 (math-div (list 'calcFunc-sqrt
1132 (math-add (math-sqr (nth 1 (nth 1 math-simplify-expr))) 1))
1133 (nth 1 (nth 1 math-simplify-expr))))
1134 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arccosh)
1135 math-living-dangerously
1136 (math-div (nth 1 (nth 1 math-simplify-expr))
1137 (list 'calcFunc-sqrt
1138 (math-sub (math-sqr (nth 1 (nth 1 math-simplify-expr))) 1))))
1139 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-arctanh)
1140 math-living-dangerously
1141 (math-div 1 (nth 1 (nth 1 math-simplify-expr))))))
1142
1143 (math-defsimplify calcFunc-arcsin
1144 (or (and (math-looks-negp (nth 1 math-simplify-expr))
1145 (math-neg (list 'calcFunc-arcsin (math-neg (nth 1 math-simplify-expr)))))
1146 (and (eq (nth 1 math-simplify-expr) 1)
1147 (math-quarter-circle t))
1148 (and (equal (nth 1 math-simplify-expr) '(frac 1 2))
1149 (math-div (math-half-circle t) 6))
1150 (and math-living-dangerously
1151 (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-sin)
1152 (nth 1 (nth 1 math-simplify-expr)))
1153 (and math-living-dangerously
1154 (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-cos)
1155 (math-sub (math-quarter-circle t)
1156 (nth 1 (nth 1 math-simplify-expr))))))
1157
1158 (math-defsimplify calcFunc-arccos
1159 (or (and (eq (nth 1 math-simplify-expr) 0)
1160 (math-quarter-circle t))
1161 (and (eq (nth 1 math-simplify-expr) -1)
1162 (math-half-circle t))
1163 (and (equal (nth 1 math-simplify-expr) '(frac 1 2))
1164 (math-div (math-half-circle t) 3))
1165 (and (equal (nth 1 math-simplify-expr) '(frac -1 2))
1166 (math-div (math-mul (math-half-circle t) 2) 3))
1167 (and math-living-dangerously
1168 (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-cos)
1169 (nth 1 (nth 1 math-simplify-expr)))
1170 (and math-living-dangerously
1171 (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-sin)
1172 (math-sub (math-quarter-circle t)
1173 (nth 1 (nth 1 math-simplify-expr))))))
1174
1175 (math-defsimplify calcFunc-arctan
1176 (or (and (math-looks-negp (nth 1 math-simplify-expr))
1177 (math-neg (list 'calcFunc-arctan (math-neg (nth 1 math-simplify-expr)))))
1178 (and (eq (nth 1 math-simplify-expr) 1)
1179 (math-div (math-half-circle t) 4))
1180 (and math-living-dangerously
1181 (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-tan)
1182 (nth 1 (nth 1 math-simplify-expr)))))
1183
1184 (math-defsimplify calcFunc-arcsinh
1185 (or (and (math-looks-negp (nth 1 math-simplify-expr))
1186 (math-neg (list 'calcFunc-arcsinh (math-neg (nth 1 math-simplify-expr)))))
1187 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-sinh)
1188 (or math-living-dangerously
1189 (math-known-realp (nth 1 (nth 1 math-simplify-expr))))
1190 (nth 1 (nth 1 math-simplify-expr)))))
1191
1192 (math-defsimplify calcFunc-arccosh
1193 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-cosh)
1194 (or math-living-dangerously
1195 (math-known-realp (nth 1 (nth 1 math-simplify-expr))))
1196 (nth 1 (nth 1 math-simplify-expr))))
1197
1198 (math-defsimplify calcFunc-arctanh
1199 (or (and (math-looks-negp (nth 1 math-simplify-expr))
1200 (math-neg (list 'calcFunc-arctanh (math-neg (nth 1 math-simplify-expr)))))
1201 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-tanh)
1202 (or math-living-dangerously
1203 (math-known-realp (nth 1 (nth 1 math-simplify-expr))))
1204 (nth 1 (nth 1 math-simplify-expr)))))
1205
1206 (math-defsimplify calcFunc-sqrt
1207 (math-simplify-sqrt))
1208
1209 (defun math-simplify-sqrt ()
1210 (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'frac)
1211 (math-div (list 'calcFunc-sqrt
1212 (math-mul (nth 1 (nth 1 math-simplify-expr))
1213 (nth 2 (nth 1 math-simplify-expr))))
1214 (nth 2 (nth 1 math-simplify-expr))))
1215 (let ((fac (if (math-objectp (nth 1 math-simplify-expr))
1216 (math-squared-factor (nth 1 math-simplify-expr))
1217 (math-common-constant-factor (nth 1 math-simplify-expr)))))
1218 (and fac (not (eq fac 1))
1219 (math-mul (math-normalize (list 'calcFunc-sqrt fac))
1220 (math-normalize
1221 (list 'calcFunc-sqrt
1222 (math-cancel-common-factor
1223 (nth 1 math-simplify-expr) fac))))))
1224 (and math-living-dangerously
1225 (or (and (eq (car-safe (nth 1 math-simplify-expr)) '-)
1226 (math-equal-int (nth 1 (nth 1 math-simplify-expr)) 1)
1227 (eq (car-safe (nth 2 (nth 1 math-simplify-expr))) '^)
1228 (math-equal-int (nth 2 (nth 2 (nth 1 math-simplify-expr))) 2)
1229 (or (and (eq (car-safe (nth 1 (nth 2 (nth 1 math-simplify-expr))))
1230 'calcFunc-sin)
1231 (list 'calcFunc-cos
1232 (nth 1 (nth 1 (nth 2 (nth 1 math-simplify-expr))))))
1233 (and (eq (car-safe (nth 1 (nth 2 (nth 1 math-simplify-expr))))
1234 'calcFunc-cos)
1235 (list 'calcFunc-sin
1236 (nth 1 (nth 1 (nth 2
1237 (nth 1 math-simplify-expr))))))))
1238 (and (eq (car-safe (nth 1 math-simplify-expr)) '-)
1239 (math-equal-int (nth 2 (nth 1 math-simplify-expr)) 1)
1240 (eq (car-safe (nth 1 (nth 1 math-simplify-expr))) '^)
1241 (math-equal-int (nth 2 (nth 1 (nth 1 math-simplify-expr))) 2)
1242 (and (eq (car-safe (nth 1 (nth 1 (nth 1 math-simplify-expr))))
1243 'calcFunc-cosh)
1244 (list 'calcFunc-sinh
1245 (nth 1 (nth 1 (nth 1 (nth 1 math-simplify-expr)))))))
1246 (and (eq (car-safe (nth 1 math-simplify-expr)) '+)
1247 (let ((a (nth 1 (nth 1 math-simplify-expr)))
1248 (b (nth 2 (nth 1 math-simplify-expr))))
1249 (and (or (and (math-equal-int a 1)
1250 (setq a b b (nth 1 (nth 1 math-simplify-expr))))
1251 (math-equal-int b 1))
1252 (eq (car-safe a) '^)
1253 (math-equal-int (nth 2 a) 2)
1254 (or (and (eq (car-safe (nth 1 a)) 'calcFunc-sinh)
1255 (list 'calcFunc-cosh (nth 1 (nth 1 a))))
1256 (and (eq (car-safe (nth 1 a)) 'calcFunc-csch)
1257 (list 'calcFunc-coth (nth 1 (nth 1 a))))
1258 (and (eq (car-safe (nth 1 a)) 'calcFunc-tan)
1259 (list '/ 1 (list 'calcFunc-cos
1260 (nth 1 (nth 1 a)))))
1261 (and (eq (car-safe (nth 1 a)) 'calcFunc-cot)
1262 (list '/ 1 (list 'calcFunc-sin
1263 (nth 1 (nth 1 a)))))))))
1264 (and (eq (car-safe (nth 1 math-simplify-expr)) '^)
1265 (list '^
1266 (nth 1 (nth 1 math-simplify-expr))
1267 (math-div (nth 2 (nth 1 math-simplify-expr)) 2)))
1268 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-sqrt)
1269 (list '^ (nth 1 (nth 1 math-simplify-expr)) (math-div 1 4)))
1270 (and (memq (car-safe (nth 1 math-simplify-expr)) '(* /))
1271 (list (car (nth 1 math-simplify-expr))
1272 (list 'calcFunc-sqrt (nth 1 (nth 1 math-simplify-expr)))
1273 (list 'calcFunc-sqrt (nth 2 (nth 1 math-simplify-expr)))))
1274 (and (memq (car-safe (nth 1 math-simplify-expr)) '(+ -))
1275 (not (math-any-floats (nth 1 math-simplify-expr)))
1276 (let ((f (calcFunc-factors (calcFunc-expand
1277 (nth 1 math-simplify-expr)))))
1278 (and (math-vectorp f)
1279 (or (> (length f) 2)
1280 (> (nth 2 (nth 1 f)) 1))
1281 (let ((out 1) (rest 1) (sums 1) fac pow)
1282 (while (setq f (cdr f))
1283 (setq fac (nth 1 (car f))
1284 pow (nth 2 (car f)))
1285 (if (> pow 1)
1286 (setq out (math-mul out (math-pow
1287 fac (/ pow 2)))
1288 pow (% pow 2)))
1289 (if (> pow 0)
1290 (if (memq (car-safe fac) '(+ -))
1291 (setq sums (math-mul-thru sums fac))
1292 (setq rest (math-mul rest fac)))))
1293 (and (not (and (eq out 1) (memq rest '(1 -1))))
1294 (math-mul
1295 out
1296 (list 'calcFunc-sqrt
1297 (math-mul sums rest))))))))))))
1298
1299 ;;; Rather than factoring x into primes, just check for the first ten primes.
1300 (defun math-squared-factor (x)
1301 (if (Math-integerp x)
1302 (let ((prsqr '(4 9 25 49 121 169 289 361 529 841))
1303 (fac 1)
1304 res)
1305 (while prsqr
1306 (if (eq (cdr (setq res (math-idivmod x (car prsqr)))) 0)
1307 (setq x (car res)
1308 fac (math-mul fac (car prsqr)))
1309 (setq prsqr (cdr prsqr))))
1310 fac)))
1311
1312 (math-defsimplify calcFunc-exp
1313 (math-simplify-exp (nth 1 math-simplify-expr)))
1314
1315 (defun math-simplify-exp (x)
1316 (or (and (eq (car-safe x) 'calcFunc-ln)
1317 (nth 1 x))
1318 (and math-living-dangerously
1319 (or (and (eq (car-safe x) 'calcFunc-arcsinh)
1320 (math-add (nth 1 x)
1321 (list 'calcFunc-sqrt
1322 (math-add (math-sqr (nth 1 x)) 1))))
1323 (and (eq (car-safe x) 'calcFunc-arccosh)
1324 (math-add (nth 1 x)
1325 (list 'calcFunc-sqrt
1326 (math-sub (math-sqr (nth 1 x)) 1))))
1327 (and (eq (car-safe x) 'calcFunc-arctanh)
1328 (math-div (list 'calcFunc-sqrt (math-add 1 (nth 1 x)))
1329 (list 'calcFunc-sqrt (math-sub 1 (nth 1 x)))))
1330 (let ((m (math-should-expand-trig x 'exp)))
1331 (and m (integerp (car m))
1332 (list '^ (list 'calcFunc-exp (nth 1 m)) (car m))))))
1333 (and calc-symbolic-mode
1334 (math-known-imagp x)
1335 (let* ((ip (calcFunc-im x))
1336 (n (math-linear-in ip '(var pi var-pi)))
1337 s c)
1338 (and n
1339 (setq s (math-known-sin (car n) (nth 1 n) 120 0))
1340 (setq c (math-known-sin (car n) (nth 1 n) 120 300))
1341 (list '+ c (list '* s '(var i var-i))))))))
1342
1343 (math-defsimplify calcFunc-ln
1344 (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-exp)
1345 (or math-living-dangerously
1346 (math-known-realp (nth 1 (nth 1 math-simplify-expr))))
1347 (nth 1 (nth 1 math-simplify-expr)))
1348 (and (eq (car-safe (nth 1 math-simplify-expr)) '^)
1349 (equal (nth 1 (nth 1 math-simplify-expr)) '(var e var-e))
1350 (or math-living-dangerously
1351 (math-known-realp (nth 2 (nth 1 math-simplify-expr))))
1352 (nth 2 (nth 1 math-simplify-expr)))
1353 (and calc-symbolic-mode
1354 (math-known-negp (nth 1 math-simplify-expr))
1355 (math-add (list 'calcFunc-ln (math-neg (nth 1 math-simplify-expr)))
1356 '(* (var pi var-pi) (var i var-i))))
1357 (and calc-symbolic-mode
1358 (math-known-imagp (nth 1 math-simplify-expr))
1359 (let* ((ip (calcFunc-im (nth 1 math-simplify-expr)))
1360 (ips (math-possible-signs ip)))
1361 (or (and (memq ips '(4 6))
1362 (math-add (list 'calcFunc-ln ip)
1363 '(/ (* (var pi var-pi) (var i var-i)) 2)))
1364 (and (memq ips '(1 3))
1365 (math-sub (list 'calcFunc-ln (math-neg ip))
1366 '(/ (* (var pi var-pi) (var i var-i)) 2))))))))
1367
1368 (math-defsimplify ^
1369 (math-simplify-pow))
1370
1371 (defun math-simplify-pow ()
1372 (or (and math-living-dangerously
1373 (or (and (eq (car-safe (nth 1 math-simplify-expr)) '^)
1374 (list '^
1375 (nth 1 (nth 1 math-simplify-expr))
1376 (math-mul (nth 2 math-simplify-expr)
1377 (nth 2 (nth 1 math-simplify-expr)))))
1378 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-sqrt)
1379 (list '^
1380 (nth 1 (nth 1 math-simplify-expr))
1381 (math-div (nth 2 math-simplify-expr) 2)))
1382 (and (memq (car-safe (nth 1 math-simplify-expr)) '(* /))
1383 (list (car (nth 1 math-simplify-expr))
1384 (list '^ (nth 1 (nth 1 math-simplify-expr))
1385 (nth 2 math-simplify-expr))
1386 (list '^ (nth 2 (nth 1 math-simplify-expr))
1387 (nth 2 math-simplify-expr))))))
1388 (and (math-equal-int (nth 1 math-simplify-expr) 10)
1389 (eq (car-safe (nth 2 math-simplify-expr)) 'calcFunc-log10)
1390 (nth 1 (nth 2 math-simplify-expr)))
1391 (and (equal (nth 1 math-simplify-expr) '(var e var-e))
1392 (math-simplify-exp (nth 2 math-simplify-expr)))
1393 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-exp)
1394 (not math-integrating)
1395 (list 'calcFunc-exp (math-mul (nth 1 (nth 1 math-simplify-expr))
1396 (nth 2 math-simplify-expr))))
1397 (and (equal (nth 1 math-simplify-expr) '(var i var-i))
1398 (math-imaginary-i)
1399 (math-num-integerp (nth 2 math-simplify-expr))
1400 (let ((x (math-mod (math-trunc (nth 2 math-simplify-expr)) 4)))
1401 (cond ((eq x 0) 1)
1402 ((eq x 1) (nth 1 math-simplify-expr))
1403 ((eq x 2) -1)
1404 ((eq x 3) (math-neg (nth 1 math-simplify-expr))))))
1405 (and math-integrating
1406 (integerp (nth 2 math-simplify-expr))
1407 (>= (nth 2 math-simplify-expr) 2)
1408 (or (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-cos)
1409 (math-mul (math-pow (nth 1 math-simplify-expr)
1410 (- (nth 2 math-simplify-expr) 2))
1411 (math-sub 1
1412 (math-sqr
1413 (list 'calcFunc-sin
1414 (nth 1 (nth 1 math-simplify-expr)))))))
1415 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-cosh)
1416 (math-mul (math-pow (nth 1 math-simplify-expr)
1417 (- (nth 2 math-simplify-expr) 2))
1418 (math-add 1
1419 (math-sqr
1420 (list 'calcFunc-sinh
1421 (nth 1 (nth 1 math-simplify-expr)))))))))
1422 (and (eq (car-safe (nth 2 math-simplify-expr)) 'frac)
1423 (Math-ratp (nth 1 math-simplify-expr))
1424 (Math-posp (nth 1 math-simplify-expr))
1425 (if (equal (nth 2 math-simplify-expr) '(frac 1 2))
1426 (list 'calcFunc-sqrt (nth 1 math-simplify-expr))
1427 (let ((flr (math-floor (nth 2 math-simplify-expr))))
1428 (and (not (Math-zerop flr))
1429 (list '* (list '^ (nth 1 math-simplify-expr) flr)
1430 (list '^ (nth 1 math-simplify-expr)
1431 (math-sub (nth 2 math-simplify-expr) flr)))))))
1432 (and (eq (math-quarter-integer (nth 2 math-simplify-expr)) 2)
1433 (let ((temp (math-simplify-sqrt)))
1434 (and temp
1435 (list '^ temp (math-mul (nth 2 math-simplify-expr) 2)))))))
1436
1437 (math-defsimplify calcFunc-log10
1438 (and (eq (car-safe (nth 1 math-simplify-expr)) '^)
1439 (math-equal-int (nth 1 (nth 1 math-simplify-expr)) 10)
1440 (or math-living-dangerously
1441 (math-known-realp (nth 2 (nth 1 math-simplify-expr))))
1442 (nth 2 (nth 1 math-simplify-expr))))
1443
1444
1445 (math-defsimplify calcFunc-erf
1446 (or (and (math-looks-negp (nth 1 math-simplify-expr))
1447 (math-neg (list 'calcFunc-erf (math-neg (nth 1 math-simplify-expr)))))
1448 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-conj)
1449 (list 'calcFunc-conj
1450 (list 'calcFunc-erf (nth 1 (nth 1 math-simplify-expr)))))))
1451
1452 (math-defsimplify calcFunc-erfc
1453 (or (and (math-looks-negp (nth 1 math-simplify-expr))
1454 (math-sub 2 (list 'calcFunc-erfc (math-neg (nth 1 math-simplify-expr)))))
1455 (and (eq (car-safe (nth 1 math-simplify-expr)) 'calcFunc-conj)
1456 (list 'calcFunc-conj
1457 (list 'calcFunc-erfc (nth 1 (nth 1 math-simplify-expr)))))))
1458
1459
1460 (defun math-linear-in (expr term &optional always)
1461 (if (math-expr-contains expr term)
1462 (let* ((calc-prefer-frac t)
1463 (p (math-is-polynomial expr term 1)))
1464 (and (cdr p)
1465 p))
1466 (and always (list expr 0))))
1467
1468 (defun math-multiple-of (expr term)
1469 (let ((p (math-linear-in expr term)))
1470 (and p
1471 (math-zerop (car p))
1472 (nth 1 p))))
1473
1474 ; not perfect, but it'll do
1475 (defun math-integer-plus (expr)
1476 (cond ((Math-integerp expr)
1477 (list 0 expr))
1478 ((and (memq (car expr) '(+ -))
1479 (Math-integerp (nth 1 expr)))
1480 (list (if (eq (car expr) '+) (nth 2 expr) (math-neg (nth 2 expr)))
1481 (nth 1 expr)))
1482 ((and (memq (car expr) '(+ -))
1483 (Math-integerp (nth 2 expr)))
1484 (list (nth 1 expr)
1485 (if (eq (car expr) '+) (nth 2 expr) (math-neg (nth 2 expr)))))
1486 (t nil)))
1487
1488 (defun math-is-linear (expr &optional always)
1489 (let ((offset nil)
1490 (coef nil))
1491 (if (eq (car-safe expr) '+)
1492 (if (Math-objectp (nth 1 expr))
1493 (setq offset (nth 1 expr)
1494 expr (nth 2 expr))
1495 (if (Math-objectp (nth 2 expr))
1496 (setq offset (nth 2 expr)
1497 expr (nth 1 expr))))
1498 (if (eq (car-safe expr) '-)
1499 (if (Math-objectp (nth 1 expr))
1500 (setq offset (nth 1 expr)
1501 expr (math-neg (nth 2 expr)))
1502 (if (Math-objectp (nth 2 expr))
1503 (setq offset (math-neg (nth 2 expr))
1504 expr (nth 1 expr))))))
1505 (setq coef (math-is-multiple expr always))
1506 (if offset
1507 (list offset (or (car coef) 1) (or (nth 1 coef) expr))
1508 (if coef
1509 (cons 0 coef)))))
1510
1511 (defun math-is-multiple (expr &optional always)
1512 (or (if (eq (car-safe expr) '*)
1513 (if (Math-objectp (nth 1 expr))
1514 (list (nth 1 expr) (nth 2 expr)))
1515 (if (eq (car-safe expr) '/)
1516 (if (and (Math-objectp (nth 1 expr))
1517 (not (math-equal-int (nth 1 expr) 1)))
1518 (list (nth 1 expr) (math-div 1 (nth 2 expr)))
1519 (if (Math-objectp (nth 2 expr))
1520 (list (math-div 1 (nth 2 expr)) (nth 1 expr))
1521 (let ((res (math-is-multiple (nth 1 expr))))
1522 (if res
1523 (list (car res)
1524 (math-div (nth 2 (nth 1 expr)) (nth 2 expr)))
1525 (setq res (math-is-multiple (nth 2 expr)))
1526 (if res
1527 (list (math-div 1 (car res))
1528 (math-div (nth 1 expr)
1529 (nth 2 (nth 2 expr)))))))))
1530 (if (eq (car-safe expr) 'neg)
1531 (list -1 (nth 1 expr)))))
1532 (if (Math-objvecp expr)
1533 (and (eq always 1)
1534 (list expr 1))
1535 (and always
1536 (list 1 expr)))))
1537
1538 (defun calcFunc-lin (expr &optional var)
1539 (if var
1540 (let ((res (math-linear-in expr var t)))
1541 (or res (math-reject-arg expr "Linear term expected"))
1542 (list 'vec (car res) (nth 1 res) var))
1543 (let ((res (math-is-linear expr t)))
1544 (or res (math-reject-arg expr "Linear term expected"))
1545 (cons 'vec res))))
1546
1547 (defun calcFunc-linnt (expr &optional var)
1548 (if var
1549 (let ((res (math-linear-in expr var)))
1550 (or res (math-reject-arg expr "Linear term expected"))
1551 (list 'vec (car res) (nth 1 res) var))
1552 (let ((res (math-is-linear expr)))
1553 (or res (math-reject-arg expr "Linear term expected"))
1554 (cons 'vec res))))
1555
1556 (defun calcFunc-islin (expr &optional var)
1557 (if (and (Math-objvecp expr) (not var))
1558 0
1559 (calcFunc-lin expr var)
1560 1))
1561
1562 (defun calcFunc-islinnt (expr &optional var)
1563 (if (Math-objvecp expr)
1564 0
1565 (calcFunc-linnt expr var)
1566 1))
1567
1568
1569
1570
1571 ;;; Simple operations on expressions.
1572
1573 ;;; Return number of occurrences of thing in expr, or nil if none.
1574 (defun math-expr-contains-count (expr thing)
1575 (cond ((equal expr thing) 1)
1576 ((Math-primp expr) nil)
1577 (t
1578 (let ((num 0))
1579 (while (setq expr (cdr expr))
1580 (setq num (+ num (or (math-expr-contains-count
1581 (car expr) thing) 0))))
1582 (and (> num 0)
1583 num)))))
1584
1585 (defun math-expr-contains (expr thing)
1586 (cond ((equal expr thing) 1)
1587 ((Math-primp expr) nil)
1588 (t
1589 (while (and (setq expr (cdr expr))
1590 (not (math-expr-contains (car expr) thing))))
1591 expr)))
1592
1593 ;;; Return non-nil if any variable of thing occurs in expr.
1594 (defun math-expr-depends (expr thing)
1595 (if (Math-primp thing)
1596 (and (eq (car-safe thing) 'var)
1597 (math-expr-contains expr thing))
1598 (while (and (setq thing (cdr thing))
1599 (not (math-expr-depends expr (car thing)))))
1600 thing))
1601
1602 ;;; Substitute all occurrences of old for new in expr (non-destructive).
1603
1604 ;; The variables math-expr-subst-old and math-expr-subst-new are local
1605 ;; for math-expr-subst, but used by math-expr-subst-rec.
1606 (defvar math-expr-subst-old)
1607 (defvar math-expr-subst-new)
1608
1609 (defun math-expr-subst (expr math-expr-subst-old math-expr-subst-new)
1610 (math-expr-subst-rec expr))
1611
1612 (defalias 'calcFunc-subst 'math-expr-subst)
1613
1614 (defun math-expr-subst-rec (expr)
1615 (cond ((equal expr math-expr-subst-old) math-expr-subst-new)
1616 ((Math-primp expr) expr)
1617 ((memq (car expr) '(calcFunc-deriv
1618 calcFunc-tderiv))
1619 (if (= (length expr) 2)
1620 (if (equal (nth 1 expr) math-expr-subst-old)
1621 (append expr (list math-expr-subst-new))
1622 expr)
1623 (list (car expr) (nth 1 expr)
1624 (math-expr-subst-rec (nth 2 expr)))))
1625 (t
1626 (cons (car expr)
1627 (mapcar 'math-expr-subst-rec (cdr expr))))))
1628
1629 ;;; Various measures of the size of an expression.
1630 (defun math-expr-weight (expr)
1631 (if (Math-primp expr)
1632 1
1633 (let ((w 1))
1634 (while (setq expr (cdr expr))
1635 (setq w (+ w (math-expr-weight (car expr)))))
1636 w)))
1637
1638 (defun math-expr-height (expr)
1639 (if (Math-primp expr)
1640 0
1641 (let ((h 0))
1642 (while (setq expr (cdr expr))
1643 (setq h (max h (math-expr-height (car expr)))))
1644 (1+ h))))
1645
1646
1647
1648
1649 ;;; Polynomial operations (to support the integrator and solve-for).
1650
1651 (defun calcFunc-collect (expr base)
1652 (let ((p (math-is-polynomial expr base 50 t)))
1653 (if (cdr p)
1654 (math-build-polynomial-expr (mapcar 'math-normalize p) base)
1655 (car p))))
1656
1657 ;;; If expr is of the form "a + bx + cx^2 + ...", return the list (a b c ...),
1658 ;;; else return nil if not in polynomial form. If "loose" (math-is-poly-loose),
1659 ;;; coefficients may contain x, e.g., sin(x) + cos(x) x^2 is a loose polynomial in x.
1660
1661 ;; These variables are local to math-is-polynomial, but are used by
1662 ;; math-is-poly-rec.
1663 (defvar math-is-poly-degree)
1664 (defvar math-is-poly-loose)
1665 (defvar math-var)
1666
1667 (defun math-is-polynomial (expr math-var &optional math-is-poly-degree math-is-poly-loose)
1668 (let* ((math-poly-base-variable (if math-is-poly-loose
1669 (if (eq math-is-poly-loose 'gen) math-var '(var XXX XXX))
1670 math-poly-base-variable))
1671 (poly (math-is-poly-rec expr math-poly-neg-powers)))
1672 (and (or (null math-is-poly-degree)
1673 (<= (length poly) (1+ math-is-poly-degree)))
1674 poly)))
1675
1676 (defun math-is-poly-rec (expr negpow)
1677 (math-poly-simplify
1678 (or (cond ((or (equal expr math-var)
1679 (eq (car-safe expr) '^))
1680 (let ((pow 1)
1681 (expr expr))
1682 (or (equal expr math-var)
1683 (setq pow (nth 2 expr)
1684 expr (nth 1 expr)))
1685 (or (eq math-poly-mult-powers 1)
1686 (setq pow (let ((m (math-is-multiple pow 1)))
1687 (and (eq (car-safe (car m)) 'cplx)
1688 (Math-zerop (nth 1 (car m)))
1689 (setq m (list (nth 2 (car m))
1690 (math-mul (nth 1 m)
1691 '(var i var-i)))))
1692 (and (if math-poly-mult-powers
1693 (equal math-poly-mult-powers
1694 (nth 1 m))
1695 (setq math-poly-mult-powers (nth 1 m)))
1696 (or (equal expr math-var)
1697 (eq math-poly-mult-powers 1))
1698 (car m)))))
1699 (if (consp pow)
1700 (progn
1701 (setq pow (math-to-simple-fraction pow))
1702 (and (eq (car-safe pow) 'frac)
1703 math-poly-frac-powers
1704 (equal expr math-var)
1705 (setq math-poly-frac-powers
1706 (calcFunc-lcm math-poly-frac-powers
1707 (nth 2 pow))))))
1708 (or (memq math-poly-frac-powers '(1 nil))
1709 (setq pow (math-mul pow math-poly-frac-powers)))
1710 (if (integerp pow)
1711 (if (and (= pow 1)
1712 (equal expr math-var))
1713 (list 0 1)
1714 (if (natnump pow)
1715 (let ((p1 (if (equal expr math-var)
1716 (list 0 1)
1717 (math-is-poly-rec expr nil)))
1718 (n pow)
1719 (accum (list 1)))
1720 (and p1
1721 (or (null math-is-poly-degree)
1722 (<= (* (1- (length p1)) n) math-is-poly-degree))
1723 (progn
1724 (while (>= n 1)
1725 (setq accum (math-poly-mul accum p1)
1726 n (1- n)))
1727 accum)))
1728 (and negpow
1729 (math-is-poly-rec expr nil)
1730 (setq math-poly-neg-powers
1731 (cons (math-pow expr (- pow))
1732 math-poly-neg-powers))
1733 (list (list '^ expr pow))))))))
1734 ((Math-objectp expr)
1735 (list expr))
1736 ((memq (car expr) '(+ -))
1737 (let ((p1 (math-is-poly-rec (nth 1 expr) negpow)))
1738 (and p1
1739 (let ((p2 (math-is-poly-rec (nth 2 expr) negpow)))
1740 (and p2
1741 (math-poly-mix p1 1 p2
1742 (if (eq (car expr) '+) 1 -1)))))))
1743 ((eq (car expr) 'neg)
1744 (mapcar 'math-neg (math-is-poly-rec (nth 1 expr) negpow)))
1745 ((eq (car expr) '*)
1746 (let ((p1 (math-is-poly-rec (nth 1 expr) negpow)))
1747 (and p1
1748 (let ((p2 (math-is-poly-rec (nth 2 expr) negpow)))
1749 (and p2
1750 (or (null math-is-poly-degree)
1751 (<= (- (+ (length p1) (length p2)) 2)
1752 math-is-poly-degree))
1753 (math-poly-mul p1 p2))))))
1754 ((eq (car expr) '/)
1755 (and (or (not (math-poly-depends (nth 2 expr) math-var))
1756 (and negpow
1757 (math-is-poly-rec (nth 2 expr) nil)
1758 (setq math-poly-neg-powers
1759 (cons (nth 2 expr) math-poly-neg-powers))))
1760 (not (Math-zerop (nth 2 expr)))
1761 (let ((p1 (math-is-poly-rec (nth 1 expr) negpow)))
1762 (mapcar (function (lambda (x) (math-div x (nth 2 expr))))
1763 p1))))
1764 ((and (eq (car expr) 'calcFunc-exp)
1765 (equal math-var '(var e var-e)))
1766 (math-is-poly-rec (list '^ math-var (nth 1 expr)) negpow))
1767 ((and (eq (car expr) 'calcFunc-sqrt)
1768 math-poly-frac-powers)
1769 (math-is-poly-rec (list '^ (nth 1 expr) '(frac 1 2)) negpow))
1770 (t nil))
1771 (and (or (not (math-poly-depends expr math-var))
1772 math-is-poly-loose)
1773 (not (eq (car expr) 'vec))
1774 (list expr)))))
1775
1776 ;;; Check if expr is a polynomial in var; if so, return its degree.
1777 (defun math-polynomial-p (expr var)
1778 (cond ((equal expr var) 1)
1779 ((Math-primp expr) 0)
1780 ((memq (car expr) '(+ -))
1781 (let ((p1 (math-polynomial-p (nth 1 expr) var))
1782 p2)
1783 (and p1 (setq p2 (math-polynomial-p (nth 2 expr) var))
1784 (max p1 p2))))
1785 ((eq (car expr) '*)
1786 (let ((p1 (math-polynomial-p (nth 1 expr) var))
1787 p2)
1788 (and p1 (setq p2 (math-polynomial-p (nth 2 expr) var))
1789 (+ p1 p2))))
1790 ((eq (car expr) 'neg)
1791 (math-polynomial-p (nth 1 expr) var))
1792 ((and (eq (car expr) '/)
1793 (not (math-poly-depends (nth 2 expr) var)))
1794 (math-polynomial-p (nth 1 expr) var))
1795 ((and (eq (car expr) '^)
1796 (natnump (nth 2 expr)))
1797 (let ((p1 (math-polynomial-p (nth 1 expr) var)))
1798 (and p1 (* p1 (nth 2 expr)))))
1799 ((math-poly-depends expr var) nil)
1800 (t 0)))
1801
1802 (defun math-poly-depends (expr var)
1803 (if math-poly-base-variable
1804 (math-expr-contains expr math-poly-base-variable)
1805 (math-expr-depends expr var)))
1806
1807 ;;; Find the variable (or sub-expression) which is the base of polynomial expr.
1808 ;; The variables math-poly-base-const-ok and math-poly-base-pred are
1809 ;; local to math-polynomial-base, but are used by math-polynomial-base-rec.
1810 (defvar math-poly-base-const-ok)
1811 (defvar math-poly-base-pred)
1812
1813 ;; The variable math-poly-base-top-expr is local to math-polynomial-base,
1814 ;; but is used by math-polynomial-p1 in calc-poly.el, which is called
1815 ;; by math-polynomial-base.
1816
1817 (defun math-polynomial-base (math-poly-base-top-expr &optional math-poly-base-pred)
1818 (or math-poly-base-pred
1819 (setq math-poly-base-pred (function (lambda (base) (math-polynomial-p
1820 math-poly-base-top-expr base)))))
1821 (or (let ((math-poly-base-const-ok nil))
1822 (math-polynomial-base-rec math-poly-base-top-expr))
1823 (let ((math-poly-base-const-ok t))
1824 (math-polynomial-base-rec math-poly-base-top-expr))))
1825
1826 (defun math-polynomial-base-rec (mpb-expr)
1827 (and (not (Math-objvecp mpb-expr))
1828 (or (and (memq (car mpb-expr) '(+ - *))
1829 (or (math-polynomial-base-rec (nth 1 mpb-expr))
1830 (math-polynomial-base-rec (nth 2 mpb-expr))))
1831 (and (memq (car mpb-expr) '(/ neg))
1832 (math-polynomial-base-rec (nth 1 mpb-expr)))
1833 (and (eq (car mpb-expr) '^)
1834 (math-polynomial-base-rec (nth 1 mpb-expr)))
1835 (and (eq (car mpb-expr) 'calcFunc-exp)
1836 (math-polynomial-base-rec '(var e var-e)))
1837 (and (or math-poly-base-const-ok (math-expr-contains-vars mpb-expr))
1838 (funcall math-poly-base-pred mpb-expr)
1839 mpb-expr))))
1840
1841 ;;; Return non-nil if expr refers to any variables.
1842 (defun math-expr-contains-vars (expr)
1843 (or (eq (car-safe expr) 'var)
1844 (and (not (Math-primp expr))
1845 (progn
1846 (while (and (setq expr (cdr expr))
1847 (not (math-expr-contains-vars (car expr)))))
1848 expr))))
1849
1850 ;;; Simplify a polynomial in list form by stripping off high-end zeros.
1851 ;;; This always leaves the constant part, i.e., nil->nil and non-nil->non-nil.
1852 (defun math-poly-simplify (p)
1853 (and p
1854 (if (Math-zerop (nth (1- (length p)) p))
1855 (let ((pp (copy-sequence p)))
1856 (while (and (cdr pp)
1857 (Math-zerop (nth (1- (length pp)) pp)))
1858 (setcdr (nthcdr (- (length pp) 2) pp) nil))
1859 pp)
1860 p)))
1861
1862 ;;; Compute ac*a + bc*b for polynomials in list form a, b and
1863 ;;; coefficients ac, bc. Result may be unsimplified.
1864 (defun math-poly-mix (a ac b bc)
1865 (and (or a b)
1866 (cons (math-add (math-mul (or (car a) 0) ac)
1867 (math-mul (or (car b) 0) bc))
1868 (math-poly-mix (cdr a) ac (cdr b) bc))))
1869
1870 (defun math-poly-zerop (a)
1871 (or (null a)
1872 (and (null (cdr a)) (Math-zerop (car a)))))
1873
1874 ;;; Multiply two polynomials in list form.
1875 (defun math-poly-mul (a b)
1876 (and a b
1877 (math-poly-mix b (car a)
1878 (math-poly-mul (cdr a) (cons 0 b)) 1)))
1879
1880 ;;; Build an expression from a polynomial list.
1881 (defun math-build-polynomial-expr (p var)
1882 (if p
1883 (if (Math-numberp var)
1884 (math-with-extra-prec 1
1885 (let* ((rp (reverse p))
1886 (accum (car rp)))
1887 (while (setq rp (cdr rp))
1888 (setq accum (math-add (car rp) (math-mul accum var))))
1889 accum))
1890 (let* ((rp (reverse p))
1891 (n (1- (length rp)))
1892 (accum (math-mul (car rp) (math-pow var n)))
1893 term)
1894 (while (setq rp (cdr rp))
1895 (setq n (1- n))
1896 (or (math-zerop (car rp))
1897 (setq accum (list (if (math-looks-negp (car rp)) '- '+)
1898 accum
1899 (math-mul (if (math-looks-negp (car rp))
1900 (math-neg (car rp))
1901 (car rp))
1902 (math-pow var n))))))
1903 accum))
1904 0))
1905
1906
1907 (defun math-to-simple-fraction (f)
1908 (or (and (eq (car-safe f) 'float)
1909 (or (and (>= (nth 2 f) 0)
1910 (math-scale-int (nth 1 f) (nth 2 f)))
1911 (and (integerp (nth 1 f))
1912 (> (nth 1 f) -1000)
1913 (< (nth 1 f) 1000)
1914 (math-make-frac (nth 1 f)
1915 (math-scale-int 1 (- (nth 2 f)))))))
1916 f))
1917
1918 (provide 'calc-alg)
1919
1920 ;;; calc-alg.el ends here