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