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