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