(calc-user-invocation): Check if calc-invocation-macro is non-nil.
[bpt/emacs.git] / lisp / calc / calc-arith.el
CommitLineData
3132f345 1;;; calc-arith.el --- arithmetic functions for Calc
a1506d29 2
a42e94ca 3;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2005 Free Software Foundation, Inc.
3132f345
CW
4
5;; Author: David Gillespie <daveg@synaptics.com>
67549a85 6;; Maintainer: Jay Belanger <belanger@truman.edu>
136211a9
EZ
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is distributed in the hope that it will be useful,
11;; but WITHOUT ANY WARRANTY. No author or distributor
12;; accepts responsibility to anyone for the consequences of using it
13;; or for whether it serves any particular purpose or works at all,
14;; unless he says so in writing. Refer to the GNU Emacs General Public
15;; License for full details.
16
17;; Everyone is granted permission to copy, modify and redistribute
18;; GNU Emacs, but only under the conditions described in the
19;; GNU Emacs General Public License. A copy of this license is
20;; supposed to have been given to you along with GNU Emacs so you
21;; can know your rights and responsibilities. It should be in a
22;; file named COPYING. Among other things, the copyright notice
23;; and this notice must be preserved on all copies.
24
3132f345 25;;; Commentary:
136211a9 26
3132f345 27;;; Code:
136211a9
EZ
28
29;; This file is autoloaded from calc-ext.el.
136211a9 30
5e30155b 31(require 'calc-ext)
136211a9
EZ
32(require 'calc-macs)
33
67549a85
JB
34;;; The following lists are not exhaustive.
35(defvar math-scalar-functions '(calcFunc-det
36 calcFunc-cnorm calcFunc-rnorm
37 calcFunc-vlen calcFunc-vcount
38 calcFunc-vsum calcFunc-vprod
39 calcFunc-vmin calcFunc-vmax))
40
41(defvar math-nonscalar-functions '(vec calcFunc-idn calcFunc-diag
42 calcFunc-cvec calcFunc-index
43 calcFunc-trn
44 | calcFunc-append
45 calcFunc-cons calcFunc-rcons
46 calcFunc-tail calcFunc-rhead))
47
48(defvar math-scalar-if-args-functions '(+ - * / neg))
49
50(defvar math-real-functions '(calcFunc-arg
51 calcFunc-re calcFunc-im
52 calcFunc-floor calcFunc-ceil
53 calcFunc-trunc calcFunc-round
54 calcFunc-rounde calcFunc-roundu
55 calcFunc-ffloor calcFunc-fceil
56 calcFunc-ftrunc calcFunc-fround
57 calcFunc-frounde calcFunc-froundu))
58
59(defvar math-positive-functions '())
60
61(defvar math-nonnegative-functions '(calcFunc-cnorm calcFunc-rnorm
62 calcFunc-vlen calcFunc-vcount))
63
64(defvar math-real-scalar-functions '(% calcFunc-idiv calcFunc-abs
65 calcFunc-choose calcFunc-perm
66 calcFunc-eq calcFunc-neq
67 calcFunc-lt calcFunc-gt
68 calcFunc-leq calcFunc-geq
69 calcFunc-lnot
70 calcFunc-max calcFunc-min))
71
72(defvar math-real-if-arg-functions '(calcFunc-sin calcFunc-cos
e3e6f095
JB
73 calcFunc-tan calcFunc-sec
74 calcFunc-csc calcFunc-cot
75 calcFunc-arctan
67549a85 76 calcFunc-sinh calcFunc-cosh
e3e6f095
JB
77 calcFunc-tanh calcFunc-sech
78 calcFunc-csch calcFunc-coth
79 calcFunc-exp
67549a85
JB
80 calcFunc-gamma calcFunc-fact))
81
82(defvar math-integer-functions '(calcFunc-idiv
83 calcFunc-isqrt calcFunc-ilog
84 calcFunc-vlen calcFunc-vcount))
85
86(defvar math-num-integer-functions '())
87
88(defvar math-rounding-functions '(calcFunc-floor
89 calcFunc-ceil
90 calcFunc-round calcFunc-trunc
91 calcFunc-rounde calcFunc-roundu))
92
93(defvar math-float-rounding-functions '(calcFunc-ffloor
94 calcFunc-fceil
95 calcFunc-fround calcFunc-ftrunc
96 calcFunc-frounde calcFunc-froundu))
97
98(defvar math-integer-if-args-functions '(+ - * % neg calcFunc-abs
99 calcFunc-min calcFunc-max
100 calcFunc-choose calcFunc-perm))
101
136211a9
EZ
102
103;;; Arithmetic.
104
105(defun calc-min (arg)
106 (interactive "P")
107 (calc-slow-wrapper
898ea5c0 108 (calc-binary-op "min" 'calcFunc-min arg '(var inf var-inf))))
136211a9
EZ
109
110(defun calc-max (arg)
111 (interactive "P")
112 (calc-slow-wrapper
898ea5c0 113 (calc-binary-op "max" 'calcFunc-max arg '(neg (var inf var-inf)))))
136211a9
EZ
114
115(defun calc-abs (arg)
116 (interactive "P")
117 (calc-slow-wrapper
898ea5c0 118 (calc-unary-op "abs" 'calcFunc-abs arg)))
136211a9
EZ
119
120
121(defun calc-idiv (arg)
122 (interactive "P")
123 (calc-slow-wrapper
898ea5c0 124 (calc-binary-op "\\" 'calcFunc-idiv arg 1)))
136211a9
EZ
125
126
127(defun calc-floor (arg)
128 (interactive "P")
129 (calc-slow-wrapper
130 (if (calc-is-inverse)
131 (if (calc-is-hyperbolic)
132 (calc-unary-op "ceil" 'calcFunc-fceil arg)
133 (calc-unary-op "ceil" 'calcFunc-ceil arg))
134 (if (calc-is-hyperbolic)
135 (calc-unary-op "flor" 'calcFunc-ffloor arg)
898ea5c0 136 (calc-unary-op "flor" 'calcFunc-floor arg)))))
136211a9
EZ
137
138(defun calc-ceiling (arg)
139 (interactive "P")
140 (calc-invert-func)
898ea5c0 141 (calc-floor arg))
136211a9
EZ
142
143(defun calc-round (arg)
144 (interactive "P")
145 (calc-slow-wrapper
146 (if (calc-is-inverse)
147 (if (calc-is-hyperbolic)
148 (calc-unary-op "trnc" 'calcFunc-ftrunc arg)
149 (calc-unary-op "trnc" 'calcFunc-trunc arg))
150 (if (calc-is-hyperbolic)
151 (calc-unary-op "rond" 'calcFunc-fround arg)
898ea5c0 152 (calc-unary-op "rond" 'calcFunc-round arg)))))
136211a9
EZ
153
154(defun calc-trunc (arg)
155 (interactive "P")
156 (calc-invert-func)
898ea5c0 157 (calc-round arg))
136211a9
EZ
158
159(defun calc-mant-part (arg)
160 (interactive "P")
161 (calc-slow-wrapper
898ea5c0 162 (calc-unary-op "mant" 'calcFunc-mant arg)))
136211a9
EZ
163
164(defun calc-xpon-part (arg)
165 (interactive "P")
166 (calc-slow-wrapper
898ea5c0 167 (calc-unary-op "xpon" 'calcFunc-xpon arg)))
136211a9
EZ
168
169(defun calc-scale-float (arg)
170 (interactive "P")
171 (calc-slow-wrapper
898ea5c0 172 (calc-binary-op "scal" 'calcFunc-scf arg)))
136211a9
EZ
173
174(defun calc-abssqr (arg)
175 (interactive "P")
176 (calc-slow-wrapper
898ea5c0 177 (calc-unary-op "absq" 'calcFunc-abssqr arg)))
136211a9
EZ
178
179(defun calc-sign (arg)
180 (interactive "P")
181 (calc-slow-wrapper
898ea5c0 182 (calc-unary-op "sign" 'calcFunc-sign arg)))
136211a9
EZ
183
184(defun calc-increment (arg)
185 (interactive "p")
186 (calc-wrapper
898ea5c0 187 (calc-enter-result 1 "incr" (list 'calcFunc-incr (calc-top-n 1) arg))))
136211a9
EZ
188
189(defun calc-decrement (arg)
190 (interactive "p")
191 (calc-wrapper
898ea5c0 192 (calc-enter-result 1 "decr" (list 'calcFunc-decr (calc-top-n 1) arg))))
136211a9
EZ
193
194
195(defun math-abs-approx (a)
196 (cond ((Math-negp a)
197 (math-neg a))
198 ((Math-anglep a)
199 a)
200 ((eq (car a) 'cplx)
201 (math-add (math-abs (nth 1 a)) (math-abs (nth 2 a))))
202 ((eq (car a) 'polar)
203 (nth 1 a))
204 ((eq (car a) 'sdev)
205 (math-abs-approx (nth 1 a)))
206 ((eq (car a) 'intv)
207 (math-max (math-abs (nth 2 a)) (math-abs (nth 3 a))))
208 ((eq (car a) 'date)
209 a)
210 ((eq (car a) 'vec)
211 (math-reduce-vec 'math-add-abs-approx a))
212 ((eq (car a) 'calcFunc-abs)
213 (car a))
898ea5c0 214 (t a)))
136211a9
EZ
215
216(defun math-add-abs-approx (a b)
898ea5c0 217 (math-add (math-abs-approx a) (math-abs-approx b)))
136211a9
EZ
218
219
220;;;; Declarations.
221
3132f345
CW
222(defvar math-decls-cache-tag nil)
223(defvar math-decls-cache nil)
224(defvar math-decls-all nil)
136211a9
EZ
225
226;;; Math-decls-cache is an a-list where each entry is a list of the form:
227;;; (VAR TYPES RANGE)
228;;; where VAR is a variable name (with var- prefix) or function name;
229;;; TYPES is a list of type symbols (any, int, frac, ...)
230;;; RANGE is a sorted vector of intervals describing the range.
231
67549a85
JB
232(defvar math-super-types
233 '((int numint rat real number)
234 (numint real number)
235 (frac rat real number)
236 (rat real number)
237 (float real number)
238 (real number)
239 (number)
240 (scalar)
241 (matrix vector)
242 (vector)
243 (const)))
244
136211a9
EZ
245(defun math-setup-declarations ()
246 (or (eq math-decls-cache-tag (calc-var-value 'var-Decls))
247 (let ((p (calc-var-value 'var-Decls))
248 vec type range)
249 (setq math-decls-cache-tag p
250 math-decls-cache nil)
251 (and (eq (car-safe p) 'vec)
252 (while (setq p (cdr p))
253 (and (eq (car-safe (car p)) 'vec)
254 (setq vec (nth 2 (car p)))
255 (condition-case err
256 (let ((v (nth 1 (car p))))
257 (setq type nil range nil)
258 (or (eq (car-safe vec) 'vec)
259 (setq vec (list 'vec vec)))
260 (while (and (setq vec (cdr vec))
261 (not (Math-objectp (car vec))))
262 (and (eq (car-safe (car vec)) 'var)
263 (let ((st (assq (nth 1 (car vec))
264 math-super-types)))
265 (cond (st (setq type (append type st)))
266 ((eq (nth 1 (car vec)) 'pos)
267 (setq type (append type
268 '(real number))
269 range
270 '(intv 1 0 (var inf var-inf))))
271 ((eq (nth 1 (car vec)) 'nonneg)
272 (setq type (append type
273 '(real number))
274 range
275 '(intv 3 0
276 (var inf var-inf))))))))
277 (if vec
278 (setq type (append type '(real number))
279 range (math-prepare-set (cons 'vec vec))))
280 (setq type (list type range))
281 (or (eq (car-safe v) 'vec)
282 (setq v (list 'vec v)))
283 (while (setq v (cdr v))
284 (if (or (eq (car-safe (car v)) 'var)
285 (not (Math-primp (car v))))
286 (setq math-decls-cache
287 (cons (cons (if (eq (car (car v)) 'var)
288 (nth 2 (car v))
289 (car (car v)))
290 type)
291 math-decls-cache)))))
292 (error nil)))))
898ea5c0 293 (setq math-decls-all (assq 'var-All math-decls-cache)))))
136211a9 294
136211a9
EZ
295(defun math-known-scalarp (a &optional assume-scalar)
296 (math-setup-declarations)
297 (if (if calc-matrix-mode
298 (eq calc-matrix-mode 'scalar)
299 assume-scalar)
300 (not (math-check-known-matrixp a))
898ea5c0 301 (math-check-known-scalarp a)))
136211a9
EZ
302
303(defun math-known-matrixp (a)
304 (and (not (Math-scalarp a))
898ea5c0 305 (not (math-known-scalarp a t))))
136211a9
EZ
306
307;;; Try to prove that A is a scalar (i.e., a non-vector).
308(defun math-check-known-scalarp (a)
309 (cond ((Math-objectp a) t)
310 ((memq (car a) math-scalar-functions)
311 t)
312 ((memq (car a) math-real-scalar-functions)
313 t)
314 ((memq (car a) math-scalar-if-args-functions)
315 (while (and (setq a (cdr a))
316 (math-check-known-scalarp (car a))))
317 (null a))
318 ((eq (car a) '^)
319 (math-check-known-scalarp (nth 1 a)))
320 ((math-const-var a) t)
321 (t
322 (let ((decl (if (eq (car a) 'var)
323 (or (assq (nth 2 a) math-decls-cache)
324 math-decls-all)
325 (assq (car a) math-decls-cache))))
898ea5c0 326 (memq 'scalar (nth 1 decl))))))
136211a9
EZ
327
328;;; Try to prove that A is *not* a scalar.
329(defun math-check-known-matrixp (a)
330 (cond ((Math-objectp a) nil)
331 ((memq (car a) math-nonscalar-functions)
332 t)
333 ((memq (car a) math-scalar-if-args-functions)
334 (while (and (setq a (cdr a))
335 (not (math-check-known-matrixp (car a)))))
336 a)
337 ((eq (car a) '^)
338 (math-check-known-matrixp (nth 1 a)))
339 ((math-const-var a) nil)
340 (t
341 (let ((decl (if (eq (car a) 'var)
342 (or (assq (nth 2 a) math-decls-cache)
343 math-decls-all)
344 (assq (car a) math-decls-cache))))
898ea5c0 345 (memq 'vector (nth 1 decl))))))
136211a9
EZ
346
347
348;;; Try to prove that A is a real (i.e., not complex).
349(defun math-known-realp (a)
898ea5c0 350 (< (math-possible-signs a) 8))
136211a9
EZ
351
352;;; Try to prove that A is real and positive.
353(defun math-known-posp (a)
898ea5c0 354 (eq (math-possible-signs a) 4))
136211a9
EZ
355
356;;; Try to prove that A is real and negative.
357(defun math-known-negp (a)
898ea5c0 358 (eq (math-possible-signs a) 1))
136211a9
EZ
359
360;;; Try to prove that A is real and nonnegative.
361(defun math-known-nonnegp (a)
898ea5c0 362 (memq (math-possible-signs a) '(2 4 6)))
136211a9
EZ
363
364;;; Try to prove that A is real and nonpositive.
365(defun math-known-nonposp (a)
898ea5c0 366 (memq (math-possible-signs a) '(1 2 3)))
136211a9
EZ
367
368;;; Try to prove that A is nonzero.
369(defun math-known-nonzerop (a)
898ea5c0 370 (memq (math-possible-signs a) '(1 4 5 8 9 12 13)))
136211a9
EZ
371
372;;; Return true if A is negative, or looks negative but we don't know.
373(defun math-guess-if-neg (a)
374 (let ((sgn (math-possible-signs a)))
375 (if (memq sgn '(1 3))
376 t
377 (if (memq sgn '(2 4 6))
378 nil
898ea5c0 379 (math-looks-negp a)))))
136211a9
EZ
380
381;;; Find the possible signs of A, assuming A is a number of some kind.
382;;; Returns an integer with bits: 1 may be negative,
383;;; 2 may be zero,
384;;; 4 may be positive,
385;;; 8 may be nonreal.
386
387(defun math-possible-signs (a &optional origin)
388 (cond ((Math-objectp a)
389 (if origin (setq a (math-sub a origin)))
390 (cond ((Math-posp a) 4)
391 ((Math-negp a) 1)
392 ((Math-zerop a) 2)
393 ((eq (car a) 'intv)
773a144d
JB
394 (cond
395 ((math-known-posp (nth 2 a)) 4)
396 ((math-known-negp (nth 3 a)) 1)
397 ((Math-zerop (nth 2 a)) 6)
398 ((Math-zerop (nth 3 a)) 3)
399 (t 7)))
136211a9
EZ
400 ((eq (car a) 'sdev)
401 (if (math-known-realp (nth 1 a)) 7 15))
402 (t 8)))
403 ((memq (car a) '(+ -))
404 (cond ((Math-realp (nth 1 a))
405 (if (eq (car a) '-)
406 (math-neg-signs
407 (math-possible-signs (nth 2 a)
408 (if origin
409 (math-add origin (nth 1 a))
410 (nth 1 a))))
411 (math-possible-signs (nth 2 a)
412 (if origin
413 (math-sub origin (nth 1 a))
414 (math-neg (nth 1 a))))))
415 ((Math-realp (nth 2 a))
416 (let ((org (if (eq (car a) '-)
417 (nth 2 a)
418 (math-neg (nth 2 a)))))
419 (math-possible-signs (nth 1 a)
420 (if origin
421 (math-add origin org)
422 org))))
423 (t
424 (let ((s1 (math-possible-signs (nth 1 a) origin))
425 (s2 (math-possible-signs (nth 2 a))))
426 (if (eq (car a) '-) (setq s2 (math-neg-signs s2)))
427 (cond ((eq s1 s2) s1)
428 ((eq s1 2) s2)
429 ((eq s2 2) s1)
430 ((>= s1 8) 15)
431 ((>= s2 8) 15)
432 ((and (eq s1 4) (eq s2 6)) 4)
433 ((and (eq s2 4) (eq s1 6)) 4)
434 ((and (eq s1 1) (eq s2 3)) 1)
435 ((and (eq s2 1) (eq s1 3)) 1)
436 (t 7))))))
437 ((eq (car a) 'neg)
438 (math-neg-signs (math-possible-signs
439 (nth 1 a)
440 (and origin (math-neg origin)))))
441 ((and origin (Math-zerop origin) (setq origin nil)
442 nil))
443 ((and (or (eq (car a) '*)
444 (and (eq (car a) '/) origin))
445 (Math-realp (nth 1 a)))
446 (let ((s (if (eq (car a) '*)
447 (if (Math-zerop (nth 1 a))
448 (math-possible-signs 0 origin)
449 (math-possible-signs (nth 2 a)
450 (math-div (or origin 0)
451 (nth 1 a))))
452 (math-neg-signs
453 (math-possible-signs (nth 2 a)
454 (math-div (nth 1 a)
455 origin))))))
456 (if (Math-negp (nth 1 a)) (math-neg-signs s) s)))
457 ((and (memq (car a) '(* /)) (Math-realp (nth 2 a)))
458 (let ((s (math-possible-signs (nth 1 a)
459 (if (eq (car a) '*)
460 (math-mul (or origin 0) (nth 2 a))
461 (math-div (or origin 0) (nth 2 a))))))
462 (if (Math-negp (nth 2 a)) (math-neg-signs s) s)))
463 ((eq (car a) 'vec)
464 (let ((signs 0))
465 (while (and (setq a (cdr a)) (< signs 15))
466 (setq signs (logior signs (math-possible-signs
467 (car a) origin))))
468 signs))
469 (t (let ((sign
470 (cond
471 ((memq (car a) '(* /))
472 (let ((s1 (math-possible-signs (nth 1 a)))
473 (s2 (math-possible-signs (nth 2 a))))
474 (cond ((>= s1 8) 15)
475 ((>= s2 8) 15)
476 ((and (eq (car a) '/) (memq s2 '(2 3 6 7))) 15)
477 (t
478 (logior (if (memq s1 '(4 5 6 7)) s2 0)
479 (if (memq s1 '(2 3 6 7)) 2 0)
480 (if (memq s1 '(1 3 5 7))
481 (math-neg-signs s2) 0))))))
482 ((eq (car a) '^)
483 (let ((s1 (math-possible-signs (nth 1 a)))
484 (s2 (math-possible-signs (nth 2 a))))
485 (cond ((>= s1 8) 15)
486 ((>= s2 8) 15)
487 ((eq s1 4) 4)
488 ((eq s1 2) (if (eq s2 4) 2 15))
489 ((eq s2 2) (if (memq s1 '(1 5)) 2 15))
490 ((Math-integerp (nth 2 a))
491 (if (math-evenp (nth 2 a))
492 (if (memq s1 '(3 6 7)) 6 4)
493 s1))
494 ((eq s1 6) (if (eq s2 4) 6 15))
495 (t 7))))
496 ((eq (car a) '%)
497 (let ((s2 (math-possible-signs (nth 2 a))))
498 (cond ((>= s2 8) 7)
499 ((eq s2 2) 2)
500 ((memq s2 '(4 6)) 6)
501 ((memq s2 '(1 3)) 3)
502 (t 7))))
503 ((and (memq (car a) '(calcFunc-abs calcFunc-abssqr))
504 (= (length a) 2))
505 (let ((s1 (math-possible-signs (nth 1 a))))
506 (cond ((eq s1 2) 2)
507 ((memq s1 '(1 4 5)) 4)
508 (t 6))))
509 ((and (eq (car a) 'calcFunc-exp) (= (length a) 2))
510 (let ((s1 (math-possible-signs (nth 1 a))))
511 (if (>= s1 8)
512 15
513 (if (or (not origin) (math-negp origin))
514 4
515 (setq origin (math-sub (or origin 0) 1))
516 (if (Math-zerop origin) (setq origin nil))
517 s1))))
518 ((or (and (memq (car a) '(calcFunc-ln calcFunc-log10))
519 (= (length a) 2))
520 (and (eq (car a) 'calcFunc-log)
521 (= (length a) 3)
522 (math-known-posp (nth 2 a))))
523 (if (math-known-nonnegp (nth 1 a))
524 (math-possible-signs (nth 1 a) 1)
525 15))
526 ((and (eq (car a) 'calcFunc-sqrt) (= (length a) 2))
527 (let ((s1 (math-possible-signs (nth 1 a))))
528 (if (memq s1 '(2 4 6)) s1 15)))
529 ((memq (car a) math-nonnegative-functions) 6)
530 ((memq (car a) math-positive-functions) 4)
531 ((memq (car a) math-real-functions) 7)
532 ((memq (car a) math-real-scalar-functions) 7)
533 ((and (memq (car a) math-real-if-arg-functions)
534 (= (length a) 2))
535 (if (math-known-realp (nth 1 a)) 7 15)))))
536 (cond (sign
537 (if origin
538 (+ (logand sign 8)
539 (if (Math-posp origin)
540 (if (memq sign '(1 2 3 8 9 10 11)) 1 7)
541 (if (memq sign '(2 4 6 8 10 12 14)) 4 7)))
542 sign))
543 ((math-const-var a)
544 (cond ((eq (nth 2 a) 'var-pi)
545 (if origin
546 (math-possible-signs (math-pi) origin)
547 4))
548 ((eq (nth 2 a) 'var-e)
549 (if origin
550 (math-possible-signs (math-e) origin)
551 4))
552 ((eq (nth 2 a) 'var-inf) 4)
553 ((eq (nth 2 a) 'var-uinf) 13)
554 ((eq (nth 2 a) 'var-i) 8)
555 (t 15)))
556 (t
557 (math-setup-declarations)
558 (let ((decl (if (eq (car a) 'var)
559 (or (assq (nth 2 a) math-decls-cache)
560 math-decls-all)
561 (assq (car a) math-decls-cache))))
562 (if (and origin
563 (memq 'int (nth 1 decl))
564 (not (Math-num-integerp origin)))
565 5
566 (if (nth 2 decl)
567 (math-possible-signs (nth 2 decl) origin)
568 (if (memq 'real (nth 1 decl))
569 7
898ea5c0 570 15))))))))))
136211a9
EZ
571
572(defun math-neg-signs (s1)
573 (if (>= s1 8)
574 (+ 8 (math-neg-signs (- s1 8)))
575 (+ (if (memq s1 '(1 3 5 7)) 4 0)
576 (if (memq s1 '(2 3 6 7)) 2 0)
898ea5c0 577 (if (memq s1 '(4 5 6 7)) 1 0))))
136211a9
EZ
578
579
580;;; Try to prove that A is an integer.
581(defun math-known-integerp (a)
898ea5c0 582 (eq (math-possible-types a) 1))
136211a9
EZ
583
584(defun math-known-num-integerp (a)
898ea5c0 585 (<= (math-possible-types a t) 3))
136211a9
EZ
586
587(defun math-known-imagp (a)
898ea5c0 588 (= (math-possible-types a) 16))
136211a9
EZ
589
590
591;;; Find the possible types of A.
592;;; Returns an integer with bits: 1 may be integer.
593;;; 2 may be integer-valued float.
594;;; 4 may be fraction.
595;;; 8 may be non-integer-valued float.
596;;; 16 may be imaginary.
597;;; 32 may be non-real, non-imaginary.
598;;; Real infinities count as integers for the purposes of this function.
599(defun math-possible-types (a &optional num)
600 (cond ((Math-objectp a)
601 (cond ((Math-integerp a) (if num 3 1))
602 ((Math-messy-integerp a) (if num 3 2))
603 ((eq (car a) 'frac) (if num 12 4))
604 ((eq (car a) 'float) (if num 12 8))
605 ((eq (car a) 'intv)
606 (if (equal (nth 2 a) (nth 3 a))
607 (math-possible-types (nth 2 a))
608 15))
609 ((eq (car a) 'sdev)
610 (if (math-known-realp (nth 1 a)) 15 63))
611 ((eq (car a) 'cplx)
612 (if (math-zerop (nth 1 a)) 16 32))
613 ((eq (car a) 'polar)
614 (if (or (Math-equal (nth 2 a) (math-quarter-circle nil))
615 (Math-equal (nth 2 a)
616 (math-neg (math-quarter-circle nil))))
617 16 48))
618 (t 63)))
619 ((eq (car a) '/)
620 (let* ((t1 (math-possible-types (nth 1 a) num))
621 (t2 (math-possible-types (nth 2 a) num))
622 (t12 (logior t1 t2)))
623 (if (< t12 16)
624 (if (> (logand t12 10) 0)
625 10
626 (if (or (= t1 4) (= t2 4) calc-prefer-frac)
627 5
628 15))
629 (if (< t12 32)
630 (if (= t1 16)
631 (if (= t2 16) 15
632 (if (< t2 16) 16 31))
633 (if (= t2 16)
634 (if (< t1 16) 16 31)
635 31))
636 63))))
637 ((memq (car a) '(+ - * %))
638 (let* ((t1 (math-possible-types (nth 1 a) num))
639 (t2 (math-possible-types (nth 2 a) num))
640 (t12 (logior t1 t2)))
641 (if (eq (car a) '%)
642 (setq t1 (logand t1 15) t2 (logand t2 15) t12 (logand t12 15)))
643 (if (< t12 16)
644 (let ((mask (if (<= t12 3)
645 1
646 (if (and (or (and (<= t1 3) (= (logand t2 3) 0))
647 (and (<= t2 3) (= (logand t1 3) 0)))
648 (memq (car a) '(+ -)))
649 4
650 5))))
651 (if num
652 (* mask 3)
653 (logior (if (and (> (logand t1 5) 0) (> (logand t2 5) 0))
654 mask 0)
655 (if (> (logand t12 10) 0)
656 (* mask 2) 0))))
657 (if (< t12 32)
658 (if (eq (car a) '*)
659 (if (= t1 16)
660 (if (= t2 16) 15
661 (if (< t2 16) 16 31))
662 (if (= t2 16)
663 (if (< t1 16) 16 31)
664 31))
665 (if (= t12 16) 16
666 (if (or (and (= t1 16) (< t2 16))
667 (and (= t2 16) (< t1 16))) 32 63)))
668 63))))
669 ((eq (car a) 'neg)
670 (math-possible-types (nth 1 a)))
671 ((eq (car a) '^)
672 (let* ((t1 (math-possible-types (nth 1 a) num))
673 (t2 (math-possible-types (nth 2 a) num))
674 (t12 (logior t1 t2)))
675 (if (and (<= t2 3) (math-known-nonnegp (nth 2 a)) (< t1 16))
676 (let ((mask (logior (if (> (logand t1 3) 0) 1 0)
677 (logand t1 4)
678 (if (> (logand t1 12) 0) 5 0))))
679 (if num
680 (* mask 3)
681 (logior (if (and (> (logand t1 5) 0) (> (logand t2 5) 0))
682 mask 0)
683 (if (> (logand t12 10) 0)
684 (* mask 2) 0))))
685 (if (and (math-known-nonnegp (nth 1 a))
686 (math-known-posp (nth 2 a)))
687 15
688 63))))
689 ((eq (car a) 'calcFunc-sqrt)
690 (let ((t1 (math-possible-signs (nth 1 a))))
691 (logior (if (> (logand t1 2) 0) 3 0)
692 (if (> (logand t1 1) 0) 16 0)
693 (if (> (logand t1 4) 0) 15 0)
694 (if (> (logand t1 8) 0) 32 0))))
695 ((eq (car a) 'vec)
696 (let ((types 0))
697 (while (and (setq a (cdr a)) (< types 63))
698 (setq types (logior types (math-possible-types (car a) t))))
699 types))
700 ((or (memq (car a) math-integer-functions)
701 (and (memq (car a) math-rounding-functions)
702 (math-known-nonnegp (or (nth 2 a) 0))))
703 1)
704 ((or (memq (car a) math-num-integer-functions)
705 (and (memq (car a) math-float-rounding-functions)
706 (math-known-nonnegp (or (nth 2 a) 0))))
707 2)
708 ((eq (car a) 'calcFunc-frac)
709 5)
710 ((and (eq (car a) 'calcFunc-float) (= (length a) 2))
711 (let ((t1 (math-possible-types (nth 1 a))))
712 (logior (if (> (logand t1 3) 0) 2 0)
713 (if (> (logand t1 12) 0) 8 0)
714 (logand t1 48))))
715 ((and (memq (car a) '(calcFunc-abs calcFunc-abssqr))
716 (= (length a) 2))
717 (let ((t1 (math-possible-types (nth 1 a))))
718 (if (>= t1 16)
719 15
720 t1)))
721 ((math-const-var a)
722 (cond ((memq (nth 2 a) '(var-e var-pi var-phi var-gamma)) 8)
723 ((eq (nth 2 a) 'var-inf) 1)
724 ((eq (nth 2 a) 'var-i) 16)
725 (t 63)))
726 (t
727 (math-setup-declarations)
728 (let ((decl (if (eq (car a) 'var)
729 (or (assq (nth 2 a) math-decls-cache)
730 math-decls-all)
731 (assq (car a) math-decls-cache))))
732 (cond ((memq 'int (nth 1 decl))
733 1)
734 ((memq 'numint (nth 1 decl))
735 3)
736 ((memq 'frac (nth 1 decl))
737 4)
738 ((memq 'rat (nth 1 decl))
739 5)
740 ((memq 'float (nth 1 decl))
741 10)
742 ((nth 2 decl)
743 (math-possible-types (nth 2 decl)))
744 ((memq 'real (nth 1 decl))
745 15)
898ea5c0 746 (t 63))))))
136211a9
EZ
747
748(defun math-known-evenp (a)
749 (cond ((Math-integerp a)
750 (math-evenp a))
751 ((Math-messy-integerp a)
752 (or (> (nth 2 a) 0)
753 (math-evenp (math-trunc a))))
754 ((eq (car a) '*)
755 (if (math-known-evenp (nth 1 a))
756 (math-known-num-integerp (nth 2 a))
757 (if (math-known-num-integerp (nth 1 a))
758 (math-known-evenp (nth 2 a)))))
759 ((memq (car a) '(+ -))
760 (or (and (math-known-evenp (nth 1 a))
761 (math-known-evenp (nth 2 a)))
762 (and (math-known-oddp (nth 1 a))
763 (math-known-oddp (nth 2 a)))))
764 ((eq (car a) 'neg)
898ea5c0 765 (math-known-evenp (nth 1 a)))))
136211a9
EZ
766
767(defun math-known-oddp (a)
768 (cond ((Math-integerp a)
769 (math-oddp a))
770 ((Math-messy-integerp a)
771 (and (<= (nth 2 a) 0)
772 (math-oddp (math-trunc a))))
773 ((memq (car a) '(+ -))
774 (or (and (math-known-evenp (nth 1 a))
775 (math-known-oddp (nth 2 a)))
776 (and (math-known-oddp (nth 1 a))
777 (math-known-evenp (nth 2 a)))))
778 ((eq (car a) 'neg)
898ea5c0 779 (math-known-oddp (nth 1 a)))))
136211a9
EZ
780
781
782(defun calcFunc-dreal (expr)
783 (let ((types (math-possible-types expr)))
784 (if (< types 16) 1
785 (if (= (logand types 15) 0) 0
898ea5c0 786 (math-reject-arg expr 'realp 'quiet)))))
136211a9
EZ
787
788(defun calcFunc-dimag (expr)
789 (let ((types (math-possible-types expr)))
790 (if (= types 16) 1
791 (if (= (logand types 16) 0) 0
898ea5c0 792 (math-reject-arg expr "Expected an imaginary number")))))
136211a9
EZ
793
794(defun calcFunc-dpos (expr)
795 (let ((signs (math-possible-signs expr)))
796 (if (eq signs 4) 1
797 (if (memq signs '(1 2 3)) 0
898ea5c0 798 (math-reject-arg expr 'posp 'quiet)))))
136211a9
EZ
799
800(defun calcFunc-dneg (expr)
801 (let ((signs (math-possible-signs expr)))
802 (if (eq signs 1) 1
803 (if (memq signs '(2 4 6)) 0
898ea5c0 804 (math-reject-arg expr 'negp 'quiet)))))
136211a9
EZ
805
806(defun calcFunc-dnonneg (expr)
807 (let ((signs (math-possible-signs expr)))
808 (if (memq signs '(2 4 6)) 1
809 (if (eq signs 1) 0
898ea5c0 810 (math-reject-arg expr 'posp 'quiet)))))
136211a9
EZ
811
812(defun calcFunc-dnonzero (expr)
813 (let ((signs (math-possible-signs expr)))
814 (if (memq signs '(1 4 5 8 9 12 13)) 1
815 (if (eq signs 2) 0
898ea5c0 816 (math-reject-arg expr 'nonzerop 'quiet)))))
136211a9
EZ
817
818(defun calcFunc-dint (expr)
819 (let ((types (math-possible-types expr)))
820 (if (= types 1) 1
821 (if (= (logand types 1) 0) 0
898ea5c0 822 (math-reject-arg expr 'integerp 'quiet)))))
136211a9
EZ
823
824(defun calcFunc-dnumint (expr)
825 (let ((types (math-possible-types expr t)))
826 (if (<= types 3) 1
827 (if (= (logand types 3) 0) 0
898ea5c0 828 (math-reject-arg expr 'integerp 'quiet)))))
136211a9
EZ
829
830(defun calcFunc-dnatnum (expr)
831 (let ((res (calcFunc-dint expr)))
832 (if (eq res 1)
833 (calcFunc-dnonneg expr)
898ea5c0 834 res)))
136211a9
EZ
835
836(defun calcFunc-deven (expr)
837 (if (math-known-evenp expr)
838 1
839 (if (or (math-known-oddp expr)
840 (= (logand (math-possible-types expr) 3) 0))
841 0
898ea5c0 842 (math-reject-arg expr "Can't tell if expression is odd or even"))))
136211a9
EZ
843
844(defun calcFunc-dodd (expr)
845 (if (math-known-oddp expr)
846 1
847 (if (or (math-known-evenp expr)
848 (= (logand (math-possible-types expr) 3) 0))
849 0
898ea5c0 850 (math-reject-arg expr "Can't tell if expression is odd or even"))))
136211a9
EZ
851
852(defun calcFunc-drat (expr)
853 (let ((types (math-possible-types expr)))
854 (if (memq types '(1 4 5)) 1
855 (if (= (logand types 5) 0) 0
898ea5c0 856 (math-reject-arg expr "Rational number expected")))))
136211a9
EZ
857
858(defun calcFunc-drange (expr)
859 (math-setup-declarations)
860 (let (range)
861 (if (Math-realp expr)
862 (list 'vec expr)
863 (if (eq (car-safe expr) 'intv)
864 expr
865 (if (eq (car-safe expr) 'var)
866 (setq range (nth 2 (or (assq (nth 2 expr) math-decls-cache)
867 math-decls-all)))
868 (setq range (nth 2 (assq (car-safe expr) math-decls-cache))))
869 (if range
870 (math-clean-set (copy-sequence range))
871 (setq range (math-possible-signs expr))
872 (if (< range 8)
873 (aref [(vec)
874 (intv 2 (neg (var inf var-inf)) 0)
875 (vec 0)
876 (intv 3 (neg (var inf var-inf)) 0)
877 (intv 1 0 (var inf var-inf))
878 (vec (intv 2 (neg (var inf var-inf)) 0)
879 (intv 1 0 (var inf var-inf)))
880 (intv 3 0 (var inf var-inf))
881 (intv 3 (neg (var inf var-inf)) (var inf var-inf))] range)
898ea5c0 882 (math-reject-arg expr 'realp 'quiet)))))))
136211a9
EZ
883
884(defun calcFunc-dscalar (a)
885 (if (math-known-scalarp a) 1
886 (if (math-known-matrixp a) 0
898ea5c0 887 (math-reject-arg a 'objectp 'quiet))))
136211a9
EZ
888
889
136211a9
EZ
890;;;; Arithmetic.
891
3132f345 892(defsubst calcFunc-neg (a)
898ea5c0 893 (math-normalize (list 'neg a)))
136211a9
EZ
894
895(defun math-neg-fancy (a)
896 (cond ((eq (car a) 'polar)
897 (list 'polar
898 (nth 1 a)
899 (if (math-posp (nth 2 a))
900 (math-sub (nth 2 a) (math-half-circle nil))
901 (math-add (nth 2 a) (math-half-circle nil)))))
902 ((eq (car a) 'mod)
903 (if (math-zerop (nth 1 a))
904 a
905 (list 'mod (math-sub (nth 2 a) (nth 1 a)) (nth 2 a))))
906 ((eq (car a) 'sdev)
907 (list 'sdev (math-neg (nth 1 a)) (nth 2 a)))
908 ((eq (car a) 'intv)
909 (math-make-intv (aref [0 2 1 3] (nth 1 a))
910 (math-neg (nth 3 a))
911 (math-neg (nth 2 a))))
912 ((and math-simplify-only
913 (not (equal a math-simplify-only)))
914 (list 'neg a))
915 ((eq (car a) '+)
916 (math-sub (math-neg (nth 1 a)) (nth 2 a)))
917 ((eq (car a) '-)
918 (math-sub (nth 2 a) (nth 1 a)))
919 ((and (memq (car a) '(* /))
920 (math-okay-neg (nth 1 a)))
921 (list (car a) (math-neg (nth 1 a)) (nth 2 a)))
922 ((and (memq (car a) '(* /))
923 (math-okay-neg (nth 2 a)))
924 (list (car a) (nth 1 a) (math-neg (nth 2 a))))
925 ((and (memq (car a) '(* /))
926 (or (math-objectp (nth 1 a))
927 (and (eq (car (nth 1 a)) '*)
928 (math-objectp (nth 1 (nth 1 a))))))
929 (list (car a) (math-neg (nth 1 a)) (nth 2 a)))
930 ((and (eq (car a) '/)
931 (or (math-objectp (nth 2 a))
932 (and (eq (car (nth 2 a)) '*)
933 (math-objectp (nth 1 (nth 2 a))))))
934 (list (car a) (nth 1 a) (math-neg (nth 2 a))))
935 ((and (eq (car a) 'var) (memq (nth 2 a) '(var-uinf var-nan)))
936 a)
937 ((eq (car a) 'neg)
938 (nth 1 a))
898ea5c0 939 (t (list 'neg a))))
136211a9
EZ
940
941(defun math-okay-neg (a)
942 (or (math-looks-negp a)
898ea5c0 943 (eq (car-safe a) '-)))
136211a9
EZ
944
945(defun math-neg-float (a)
898ea5c0 946 (list 'float (Math-integer-neg (nth 1 a)) (nth 2 a)))
136211a9
EZ
947
948
949(defun calcFunc-add (&rest rest)
950 (if rest
951 (let ((a (car rest)))
952 (while (setq rest (cdr rest))
953 (setq a (list '+ a (car rest))))
954 (math-normalize a))
898ea5c0 955 0))
136211a9
EZ
956
957(defun calcFunc-sub (&rest rest)
958 (if rest
959 (let ((a (car rest)))
960 (while (setq rest (cdr rest))
961 (setq a (list '- a (car rest))))
962 (math-normalize a))
898ea5c0 963 0))
136211a9
EZ
964
965(defun math-add-objects-fancy (a b)
966 (cond ((and (Math-numberp a) (Math-numberp b))
967 (let ((aa (math-complex a))
968 (bb (math-complex b)))
969 (math-normalize
970 (let ((res (list 'cplx
971 (math-add (nth 1 aa) (nth 1 bb))
972 (math-add (nth 2 aa) (nth 2 bb)))))
973 (if (math-want-polar a b)
974 (math-polar res)
975 res)))))
976 ((or (Math-vectorp a) (Math-vectorp b))
977 (math-map-vec-2 'math-add a b))
978 ((eq (car-safe a) 'sdev)
979 (if (eq (car-safe b) 'sdev)
980 (math-make-sdev (math-add (nth 1 a) (nth 1 b))
981 (math-hypot (nth 2 a) (nth 2 b)))
982 (and (or (Math-scalarp b)
983 (not (Math-objvecp b)))
984 (math-make-sdev (math-add (nth 1 a) b) (nth 2 a)))))
985 ((and (eq (car-safe b) 'sdev)
986 (or (Math-scalarp a)
987 (not (Math-objvecp a))))
988 (math-make-sdev (math-add a (nth 1 b)) (nth 2 b)))
989 ((eq (car-safe a) 'intv)
990 (if (eq (car-safe b) 'intv)
991 (math-make-intv (logior (logand (nth 1 a) (nth 1 b))
992 (if (equal (nth 2 a)
993 '(neg (var inf var-inf)))
994 (logand (nth 1 a) 2) 0)
995 (if (equal (nth 2 b)
996 '(neg (var inf var-inf)))
997 (logand (nth 1 b) 2) 0)
998 (if (equal (nth 3 a) '(var inf var-inf))
999 (logand (nth 1 a) 1) 0)
1000 (if (equal (nth 3 b) '(var inf var-inf))
1001 (logand (nth 1 b) 1) 0))
1002 (math-add (nth 2 a) (nth 2 b))
1003 (math-add (nth 3 a) (nth 3 b)))
1004 (and (or (Math-anglep b)
1005 (eq (car b) 'date)
1006 (not (Math-objvecp b)))
1007 (math-make-intv (nth 1 a)
1008 (math-add (nth 2 a) b)
1009 (math-add (nth 3 a) b)))))
1010 ((and (eq (car-safe b) 'intv)
1011 (or (Math-anglep a)
1012 (eq (car a) 'date)
1013 (not (Math-objvecp a))))
1014 (math-make-intv (nth 1 b)
1015 (math-add a (nth 2 b))
1016 (math-add a (nth 3 b))))
1017 ((eq (car-safe a) 'date)
1018 (cond ((eq (car-safe b) 'date)
1019 (math-add (nth 1 a) (nth 1 b)))
1020 ((eq (car-safe b) 'hms)
1021 (let ((parts (math-date-parts (nth 1 a))))
1022 (list 'date
1023 (math-add (car parts) ; this minimizes roundoff
1024 (math-div (math-add
1025 (math-add (nth 1 parts)
1026 (nth 2 parts))
1027 (math-add
1028 (math-mul (nth 1 b) 3600)
1029 (math-add (math-mul (nth 2 b) 60)
1030 (nth 3 b))))
1031 86400)))))
1032 ((Math-realp b)
1033 (list 'date (math-add (nth 1 a) b)))
1034 (t nil)))
1035 ((eq (car-safe b) 'date)
1036 (math-add-objects-fancy b a))
1037 ((and (eq (car-safe a) 'mod)
1038 (eq (car-safe b) 'mod)
1039 (equal (nth 2 a) (nth 2 b)))
1040 (math-make-mod (math-add (nth 1 a) (nth 1 b)) (nth 2 a)))
1041 ((and (eq (car-safe a) 'mod)
1042 (Math-anglep b))
1043 (math-make-mod (math-add (nth 1 a) b) (nth 2 a)))
1044 ((and (eq (car-safe b) 'mod)
1045 (Math-anglep a))
1046 (math-make-mod (math-add a (nth 1 b)) (nth 2 b)))
1047 ((and (or (eq (car-safe a) 'hms) (eq (car-safe b) 'hms))
1048 (and (Math-anglep a) (Math-anglep b)))
1049 (or (eq (car-safe a) 'hms) (setq a (math-to-hms a)))
1050 (or (eq (car-safe b) 'hms) (setq b (math-to-hms b)))
1051 (math-normalize
1052 (if (math-negp a)
1053 (math-neg (math-add (math-neg a) (math-neg b)))
1054 (if (math-negp b)
1055 (let* ((s (math-add (nth 3 a) (nth 3 b)))
1056 (m (math-add (nth 2 a) (nth 2 b)))
1057 (h (math-add (nth 1 a) (nth 1 b))))
1058 (if (math-negp s)
1059 (setq s (math-add s 60)
1060 m (math-add m -1)))
1061 (if (math-negp m)
1062 (setq m (math-add m 60)
1063 h (math-add h -1)))
1064 (if (math-negp h)
1065 (math-add b a)
1066 (list 'hms h m s)))
1067 (let* ((s (math-add (nth 3 a) (nth 3 b)))
1068 (m (math-add (nth 2 a) (nth 2 b)))
1069 (h (math-add (nth 1 a) (nth 1 b))))
1070 (list 'hms h m s))))))
898ea5c0 1071 (t (calc-record-why "*Incompatible arguments for +" a b))))
136211a9
EZ
1072
1073(defun math-add-symb-fancy (a b)
1074 (or (and math-simplify-only
1075 (not (equal a math-simplify-only))
1076 (list '+ a b))
1077 (and (eq (car-safe b) '+)
1078 (math-add (math-add a (nth 1 b))
1079 (nth 2 b)))
1080 (and (eq (car-safe b) '-)
1081 (math-sub (math-add a (nth 1 b))
1082 (nth 2 b)))
1083 (and (eq (car-safe b) 'neg)
1084 (eq (car-safe (nth 1 b)) '+)
1085 (math-sub (math-sub a (nth 1 (nth 1 b)))
1086 (nth 2 (nth 1 b))))
1087 (and (or (and (Math-vectorp a) (math-known-scalarp b))
1088 (and (Math-vectorp b) (math-known-scalarp a)))
1089 (math-map-vec-2 'math-add a b))
1090 (let ((inf (math-infinitep a)))
1091 (cond
1092 (inf
1093 (let ((inf2 (math-infinitep b)))
1094 (if inf2
1095 (if (or (memq (nth 2 inf) '(var-uinf var-nan))
1096 (memq (nth 2 inf2) '(var-uinf var-nan)))
1097 '(var nan var-nan)
1098 (let ((dir (math-infinite-dir a inf))
1099 (dir2 (math-infinite-dir b inf2)))
1100 (if (and (Math-objectp dir) (Math-objectp dir2))
1101 (if (Math-equal dir dir2)
1102 a
1103 '(var nan var-nan)))))
1104 (if (and (equal a '(var inf var-inf))
1105 (eq (car-safe b) 'intv)
1106 (memq (nth 1 b) '(2 3))
1107 (equal (nth 2 b) '(neg (var inf var-inf))))
1108 (list 'intv 3 (nth 2 b) a)
1109 (if (and (equal a '(neg (var inf var-inf)))
1110 (eq (car-safe b) 'intv)
1111 (memq (nth 1 b) '(1 3))
1112 (equal (nth 3 b) '(var inf var-inf)))
1113 (list 'intv 3 a (nth 3 b))
1114 a)))))
1115 ((math-infinitep b)
1116 (if (eq (car-safe a) 'intv)
1117 (math-add b a)
1118 b))
1119 ((eq (car-safe a) '+)
1120 (let ((temp (math-combine-sum (nth 2 a) b nil nil t)))
1121 (and temp
1122 (math-add (nth 1 a) temp))))
1123 ((eq (car-safe a) '-)
1124 (let ((temp (math-combine-sum (nth 2 a) b t nil t)))
1125 (and temp
1126 (math-add (nth 1 a) temp))))
1127 ((and (Math-objectp a) (Math-objectp b))
1128 nil)
1129 (t
1130 (math-combine-sum a b nil nil nil))))
1131 (and (Math-looks-negp b)
1132 (list '- a (math-neg b)))
1133 (and (Math-looks-negp a)
1134 (list '- b (math-neg a)))
1135 (and (eq (car-safe a) 'calcFunc-idn)
1136 (= (length a) 2)
1137 (or (and (eq (car-safe b) 'calcFunc-idn)
1138 (= (length b) 2)
1139 (list 'calcFunc-idn (math-add (nth 1 a) (nth 1 b))))
1140 (and (math-square-matrixp b)
1141 (math-add (math-mimic-ident (nth 1 a) b) b))
1142 (and (math-known-scalarp b)
1143 (math-add (nth 1 a) b))))
1144 (and (eq (car-safe b) 'calcFunc-idn)
1145 (= (length a) 2)
1146 (or (and (math-square-matrixp a)
1147 (math-add a (math-mimic-ident (nth 1 b) a)))
1148 (and (math-known-scalarp a)
1149 (math-add a (nth 1 b)))))
898ea5c0 1150 (list '+ a b)))
136211a9
EZ
1151
1152
1153(defun calcFunc-mul (&rest rest)
1154 (if rest
1155 (let ((a (car rest)))
1156 (while (setq rest (cdr rest))
1157 (setq a (list '* a (car rest))))
1158 (math-normalize a))
898ea5c0 1159 1))
136211a9
EZ
1160
1161(defun math-mul-objects-fancy (a b)
1162 (cond ((and (Math-numberp a) (Math-numberp b))
1163 (math-normalize
1164 (if (math-want-polar a b)
1165 (let ((a (math-polar a))
1166 (b (math-polar b)))
1167 (list 'polar
1168 (math-mul (nth 1 a) (nth 1 b))
1169 (math-fix-circular (math-add (nth 2 a) (nth 2 b)))))
1170 (setq a (math-complex a)
1171 b (math-complex b))
1172 (list 'cplx
1173 (math-sub (math-mul (nth 1 a) (nth 1 b))
1174 (math-mul (nth 2 a) (nth 2 b)))
1175 (math-add (math-mul (nth 1 a) (nth 2 b))
1176 (math-mul (nth 2 a) (nth 1 b)))))))
1177 ((Math-vectorp a)
1178 (if (Math-vectorp b)
1179 (if (math-matrixp a)
1180 (if (math-matrixp b)
1181 (if (= (length (nth 1 a)) (length b))
1182 (math-mul-mats a b)
1183 (math-dimension-error))
1184 (if (= (length (nth 1 a)) 2)
1185 (if (= (length a) (length b))
1186 (math-mul-mats a (list 'vec b))
1187 (math-dimension-error))
1188 (if (= (length (nth 1 a)) (length b))
1189 (math-mul-mat-vec a b)
1190 (math-dimension-error))))
1191 (if (math-matrixp b)
1192 (if (= (length a) (length b))
1193 (nth 1 (math-mul-mats (list 'vec a) b))
1194 (math-dimension-error))
1195 (if (= (length a) (length b))
1196 (math-dot-product a b)
1197 (math-dimension-error))))
1198 (math-map-vec-2 'math-mul a b)))
1199 ((Math-vectorp b)
1200 (math-map-vec-2 'math-mul a b))
1201 ((eq (car-safe a) 'sdev)
1202 (if (eq (car-safe b) 'sdev)
1203 (math-make-sdev (math-mul (nth 1 a) (nth 1 b))
1204 (math-hypot (math-mul (nth 2 a) (nth 1 b))
1205 (math-mul (nth 2 b) (nth 1 a))))
1206 (and (or (Math-scalarp b)
1207 (not (Math-objvecp b)))
1208 (math-make-sdev (math-mul (nth 1 a) b)
1209 (math-mul (nth 2 a) b)))))
1210 ((and (eq (car-safe b) 'sdev)
1211 (or (Math-scalarp a)
1212 (not (Math-objvecp a))))
1213 (math-make-sdev (math-mul a (nth 1 b)) (math-mul a (nth 2 b))))
1214 ((and (eq (car-safe a) 'intv) (Math-anglep b))
1215 (if (Math-negp b)
1216 (math-neg (math-mul a (math-neg b)))
1217 (math-make-intv (nth 1 a)
1218 (math-mul (nth 2 a) b)
1219 (math-mul (nth 3 a) b))))
1220 ((and (eq (car-safe b) 'intv) (Math-anglep a))
1221 (math-mul b a))
1222 ((and (eq (car-safe a) 'intv) (math-intv-constp a)
1223 (eq (car-safe b) 'intv) (math-intv-constp b))
1224 (let ((lo (math-mul a (nth 2 b)))
1225 (hi (math-mul a (nth 3 b))))
1226 (or (eq (car-safe lo) 'intv)
1227 (setq lo (list 'intv (if (memq (nth 1 b) '(2 3)) 3 0) lo lo)))
1228 (or (eq (car-safe hi) 'intv)
1229 (setq hi (list 'intv (if (memq (nth 1 b) '(1 3)) 3 0) hi hi)))
1230 (math-combine-intervals
1231 (nth 2 lo) (and (or (memq (nth 1 b) '(2 3))
1232 (math-infinitep (nth 2 lo)))
1233 (memq (nth 1 lo) '(2 3)))
1234 (nth 3 lo) (and (or (memq (nth 1 b) '(2 3))
1235 (math-infinitep (nth 3 lo)))
1236 (memq (nth 1 lo) '(1 3)))
1237 (nth 2 hi) (and (or (memq (nth 1 b) '(1 3))
1238 (math-infinitep (nth 2 hi)))
1239 (memq (nth 1 hi) '(2 3)))
1240 (nth 3 hi) (and (or (memq (nth 1 b) '(1 3))
1241 (math-infinitep (nth 3 hi)))
1242 (memq (nth 1 hi) '(1 3))))))
1243 ((and (eq (car-safe a) 'mod)
1244 (eq (car-safe b) 'mod)
1245 (equal (nth 2 a) (nth 2 b)))
1246 (math-make-mod (math-mul (nth 1 a) (nth 1 b)) (nth 2 a)))
1247 ((and (eq (car-safe a) 'mod)
1248 (Math-anglep b))
1249 (math-make-mod (math-mul (nth 1 a) b) (nth 2 a)))
1250 ((and (eq (car-safe b) 'mod)
1251 (Math-anglep a))
1252 (math-make-mod (math-mul a (nth 1 b)) (nth 2 b)))
1253 ((and (eq (car-safe a) 'hms) (Math-realp b))
1254 (math-with-extra-prec 2
1255 (math-to-hms (math-mul (math-from-hms a 'deg) b) 'deg)))
1256 ((and (eq (car-safe b) 'hms) (Math-realp a))
1257 (math-mul b a))
898ea5c0 1258 (t (calc-record-why "*Incompatible arguments for *" a b))))
136211a9
EZ
1259
1260;;; Fast function to multiply floating-point numbers.
1261(defun math-mul-float (a b) ; [F F F]
1262 (math-make-float (math-mul (nth 1 a) (nth 1 b))
898ea5c0 1263 (+ (nth 2 a) (nth 2 b))))
136211a9
EZ
1264
1265(defun math-sqr-float (a) ; [F F]
1266 (math-make-float (math-mul (nth 1 a) (nth 1 a))
898ea5c0 1267 (+ (nth 2 a) (nth 2 a))))
136211a9
EZ
1268
1269(defun math-intv-constp (a &optional finite)
1270 (and (or (Math-anglep (nth 2 a))
1271 (and (equal (nth 2 a) '(neg (var inf var-inf)))
1272 (or (not finite)
1273 (memq (nth 1 a) '(0 1)))))
1274 (or (Math-anglep (nth 3 a))
1275 (and (equal (nth 3 a) '(var inf var-inf))
1276 (or (not finite)
898ea5c0 1277 (memq (nth 1 a) '(0 2)))))))
136211a9
EZ
1278
1279(defun math-mul-zero (a b)
1280 (if (math-known-matrixp b)
1281 (if (math-vectorp b)
1282 (math-map-vec-2 'math-mul a b)
1283 (math-mimic-ident 0 b))
1284 (if (math-infinitep b)
1285 '(var nan var-nan)
1286 (let ((aa nil) (bb nil))
1287 (if (and (eq (car-safe b) 'intv)
1288 (progn
1289 (and (equal (nth 2 b) '(neg (var inf var-inf)))
1290 (memq (nth 1 b) '(2 3))
1291 (setq aa (nth 2 b)))
1292 (and (equal (nth 3 b) '(var inf var-inf))
1293 (memq (nth 1 b) '(1 3))
1294 (setq bb (nth 3 b)))
1295 (or aa bb)))
1296 (if (or (math-posp a)
1297 (and (math-zerop a)
1298 (or (memq calc-infinite-mode '(-1 1))
1299 (setq aa '(neg (var inf var-inf))
1300 bb '(var inf var-inf)))))
1301 (list 'intv 3 (or aa 0) (or bb 0))
1302 (if (math-negp a)
1303 (math-neg (list 'intv 3 (or aa 0) (or bb 0)))
1304 '(var nan var-nan)))
898ea5c0 1305 (if (or (math-floatp a) (math-floatp b)) '(float 0 0) 0))))))
136211a9
EZ
1306
1307
1308(defun math-mul-symb-fancy (a b)
1309 (or (and math-simplify-only
1310 (not (equal a math-simplify-only))
1311 (list '* a b))
1312 (and (Math-equal-int a 1)
1313 b)
1314 (and (Math-equal-int a -1)
1315 (math-neg b))
1316 (and (or (and (Math-vectorp a) (math-known-scalarp b))
1317 (and (Math-vectorp b) (math-known-scalarp a)))
1318 (math-map-vec-2 'math-mul a b))
1319 (and (Math-objectp b) (not (Math-objectp a))
1320 (math-mul b a))
1321 (and (eq (car-safe a) 'neg)
1322 (math-neg (math-mul (nth 1 a) b)))
1323 (and (eq (car-safe b) 'neg)
1324 (math-neg (math-mul a (nth 1 b))))
1325 (and (eq (car-safe a) '*)
1326 (math-mul (nth 1 a)
1327 (math-mul (nth 2 a) b)))
1328 (and (eq (car-safe a) '^)
1329 (Math-looks-negp (nth 2 a))
1330 (not (and (eq (car-safe b) '^) (Math-looks-negp (nth 2 b))))
1331 (math-known-scalarp b t)
1332 (math-div b (math-normalize
1333 (list '^ (nth 1 a) (math-neg (nth 2 a))))))
1334 (and (eq (car-safe b) '^)
1335 (Math-looks-negp (nth 2 b))
1336 (not (and (eq (car-safe a) '^) (Math-looks-negp (nth 2 a))))
1337 (math-div a (math-normalize
1338 (list '^ (nth 1 b) (math-neg (nth 2 b))))))
1339 (and (eq (car-safe a) '/)
1340 (or (math-known-scalarp a t) (math-known-scalarp b t))
1341 (let ((temp (math-combine-prod (nth 2 a) b t nil t)))
1342 (if temp
1343 (math-mul (nth 1 a) temp)
1344 (math-div (math-mul (nth 1 a) b) (nth 2 a)))))
1345 (and (eq (car-safe b) '/)
1346 (math-div (math-mul a (nth 1 b)) (nth 2 b)))
1347 (and (eq (car-safe b) '+)
1348 (Math-numberp a)
1349 (or (Math-numberp (nth 1 b))
1350 (Math-numberp (nth 2 b)))
1351 (math-add (math-mul a (nth 1 b))
1352 (math-mul a (nth 2 b))))
1353 (and (eq (car-safe b) '-)
1354 (Math-numberp a)
1355 (or (Math-numberp (nth 1 b))
1356 (Math-numberp (nth 2 b)))
1357 (math-sub (math-mul a (nth 1 b))
1358 (math-mul a (nth 2 b))))
1359 (and (eq (car-safe b) '*)
1360 (Math-numberp (nth 1 b))
1361 (not (Math-numberp a))
1362 (math-mul (nth 1 b) (math-mul a (nth 2 b))))
1363 (and (eq (car-safe a) 'calcFunc-idn)
1364 (= (length a) 2)
1365 (or (and (eq (car-safe b) 'calcFunc-idn)
1366 (= (length b) 2)
1367 (list 'calcFunc-idn (math-mul (nth 1 a) (nth 1 b))))
1368 (and (math-known-scalarp b)
1369 (list 'calcFunc-idn (math-mul (nth 1 a) b)))
1370 (and (math-known-matrixp b)
1371 (math-mul (nth 1 a) b))))
1372 (and (eq (car-safe b) 'calcFunc-idn)
1373 (= (length b) 2)
1374 (or (and (math-known-scalarp a)
1375 (list 'calcFunc-idn (math-mul a (nth 1 b))))
1376 (and (math-known-matrixp a)
1377 (math-mul a (nth 1 b)))))
1378 (and (math-looks-negp b)
1379 (math-mul (math-neg a) (math-neg b)))
1380 (and (eq (car-safe b) '-)
1381 (math-looks-negp a)
1382 (math-mul (math-neg a) (math-neg b)))
1383 (cond
1384 ((eq (car-safe b) '*)
1385 (let ((temp (math-combine-prod a (nth 1 b) nil nil t)))
1386 (and temp
1387 (math-mul temp (nth 2 b)))))
1388 (t
1389 (math-combine-prod a b nil nil nil)))
1390 (and (equal a '(var nan var-nan))
1391 a)
1392 (and (equal b '(var nan var-nan))
1393 b)
1394 (and (equal a '(var uinf var-uinf))
1395 a)
1396 (and (equal b '(var uinf var-uinf))
1397 b)
1398 (and (equal b '(var inf var-inf))
1399 (let ((s1 (math-possible-signs a)))
1400 (cond ((eq s1 4)
1401 b)
1402 ((eq s1 6)
1403 '(intv 3 0 (var inf var-inf)))
1404 ((eq s1 1)
1405 (math-neg b))
1406 ((eq s1 3)
1407 '(intv 3 (neg (var inf var-inf)) 0))
1408 ((and (eq (car a) 'intv) (math-intv-constp a))
1409 '(intv 3 (neg (var inf var-inf)) (var inf var-inf)))
1410 ((and (eq (car a) 'cplx)
1411 (math-zerop (nth 1 a)))
1412 (list '* (list 'cplx 0 (calcFunc-sign (nth 2 a))) b))
1413 ((eq (car a) 'polar)
1414 (list '* (list 'polar 1 (nth 2 a)) b)))))
1415 (and (equal a '(var inf var-inf))
1416 (math-mul b a))
898ea5c0 1417 (list '* a b)))
136211a9
EZ
1418
1419
1420(defun calcFunc-div (a &rest rest)
1421 (while rest
1422 (setq a (list '/ a (car rest))
1423 rest (cdr rest)))
898ea5c0 1424 (math-normalize a))
136211a9
EZ
1425
1426(defun math-div-objects-fancy (a b)
1427 (cond ((and (Math-numberp a) (Math-numberp b))
1428 (math-normalize
1429 (cond ((math-want-polar a b)
1430 (let ((a (math-polar a))
1431 (b (math-polar b)))
1432 (list 'polar
1433 (math-div (nth 1 a) (nth 1 b))
1434 (math-fix-circular (math-sub (nth 2 a)
1435 (nth 2 b))))))
1436 ((Math-realp b)
1437 (setq a (math-complex a))
1438 (list 'cplx (math-div (nth 1 a) b)
1439 (math-div (nth 2 a) b)))
1440 (t
1441 (setq a (math-complex a)
1442 b (math-complex b))
1443 (math-div
1444 (list 'cplx
1445 (math-add (math-mul (nth 1 a) (nth 1 b))
1446 (math-mul (nth 2 a) (nth 2 b)))
1447 (math-sub (math-mul (nth 2 a) (nth 1 b))
1448 (math-mul (nth 1 a) (nth 2 b))))
1449 (math-add (math-sqr (nth 1 b))
1450 (math-sqr (nth 2 b))))))))
1451 ((math-matrixp b)
1452 (if (math-square-matrixp b)
1453 (let ((n1 (length b)))
1454 (if (Math-vectorp a)
1455 (if (math-matrixp a)
1456 (if (= (length a) n1)
1457 (math-lud-solve (math-matrix-lud b) a b)
1458 (if (= (length (nth 1 a)) n1)
1459 (math-transpose
1460 (math-lud-solve (math-matrix-lud
1461 (math-transpose b))
1462 (math-transpose a) b))
1463 (math-dimension-error)))
1464 (if (= (length a) n1)
1465 (math-mat-col (math-lud-solve (math-matrix-lud b)
1466 (math-col-matrix a) b)
1467 1)
1468 (math-dimension-error)))
1469 (if (Math-equal-int a 1)
1470 (calcFunc-inv b)
1471 (math-mul a (calcFunc-inv b)))))
1472 (math-reject-arg b 'square-matrixp)))
1473 ((and (Math-vectorp a) (Math-objectp b))
1474 (math-map-vec-2 'math-div a b))
1475 ((eq (car-safe a) 'sdev)
1476 (if (eq (car-safe b) 'sdev)
1477 (let ((x (math-div (nth 1 a) (nth 1 b))))
1478 (math-make-sdev x
1479 (math-div (math-hypot (nth 2 a)
1480 (math-mul (nth 2 b) x))
1481 (nth 1 b))))
1482 (if (or (Math-scalarp b)
1483 (not (Math-objvecp b)))
1484 (math-make-sdev (math-div (nth 1 a) b) (math-div (nth 2 a) b))
1485 (math-reject-arg 'realp b))))
1486 ((and (eq (car-safe b) 'sdev)
1487 (or (Math-scalarp a)
1488 (not (Math-objvecp a))))
1489 (let ((x (math-div a (nth 1 b))))
1490 (math-make-sdev x
1491 (math-div (math-mul (nth 2 b) x) (nth 1 b)))))
1492 ((and (eq (car-safe a) 'intv) (Math-anglep b))
1493 (if (Math-negp b)
1494 (math-neg (math-div a (math-neg b)))
1495 (math-make-intv (nth 1 a)
1496 (math-div (nth 2 a) b)
1497 (math-div (nth 3 a) b))))
1498 ((and (eq (car-safe b) 'intv) (Math-anglep a))
1499 (if (or (Math-posp (nth 2 b))
1500 (and (Math-zerop (nth 2 b)) (or (memq (nth 1 b) '(0 1))
1501 calc-infinite-mode)))
1502 (if (Math-negp a)
1503 (math-neg (math-div (math-neg a) b))
1504 (let ((calc-infinite-mode 1))
1505 (math-make-intv (aref [0 2 1 3] (nth 1 b))
1506 (math-div a (nth 3 b))
1507 (math-div a (nth 2 b)))))
1508 (if (or (Math-negp (nth 3 b))
1509 (and (Math-zerop (nth 3 b)) (or (memq (nth 1 b) '(0 2))
1510 calc-infinite-mode)))
1511 (math-neg (math-div a (math-neg b)))
1512 (if calc-infinite-mode
1513 '(intv 3 (neg (var inf var-inf)) (var inf var-inf))
1514 (math-reject-arg b "*Division by zero")))))
1515 ((and (eq (car-safe a) 'intv) (math-intv-constp a)
1516 (eq (car-safe b) 'intv) (math-intv-constp b))
1517 (if (or (Math-posp (nth 2 b))
1518 (and (Math-zerop (nth 2 b)) (or (memq (nth 1 b) '(0 1))
1519 calc-infinite-mode)))
1520 (let* ((calc-infinite-mode 1)
1521 (lo (math-div a (nth 2 b)))
1522 (hi (math-div a (nth 3 b))))
1523 (or (eq (car-safe lo) 'intv)
1524 (setq lo (list 'intv (if (memq (nth 1 b) '(2 3)) 3 0)
1525 lo lo)))
1526 (or (eq (car-safe hi) 'intv)
1527 (setq hi (list 'intv (if (memq (nth 1 b) '(1 3)) 3 0)
1528 hi hi)))
1529 (math-combine-intervals
1530 (nth 2 lo) (and (or (memq (nth 1 b) '(2 3))
1531 (and (math-infinitep (nth 2 lo))
1532 (not (math-zerop (nth 2 b)))))
1533 (memq (nth 1 lo) '(2 3)))
1534 (nth 3 lo) (and (or (memq (nth 1 b) '(2 3))
1535 (and (math-infinitep (nth 3 lo))
1536 (not (math-zerop (nth 2 b)))))
1537 (memq (nth 1 lo) '(1 3)))
1538 (nth 2 hi) (and (or (memq (nth 1 b) '(1 3))
1539 (and (math-infinitep (nth 2 hi))
1540 (not (math-zerop (nth 3 b)))))
1541 (memq (nth 1 hi) '(2 3)))
1542 (nth 3 hi) (and (or (memq (nth 1 b) '(1 3))
1543 (and (math-infinitep (nth 3 hi))
1544 (not (math-zerop (nth 3 b)))))
1545 (memq (nth 1 hi) '(1 3)))))
1546 (if (or (Math-negp (nth 3 b))
1547 (and (Math-zerop (nth 3 b)) (or (memq (nth 1 b) '(0 2))
1548 calc-infinite-mode)))
1549 (math-neg (math-div a (math-neg b)))
1550 (if calc-infinite-mode
1551 '(intv 3 (neg (var inf var-inf)) (var inf var-inf))
1552 (math-reject-arg b "*Division by zero")))))
1553 ((and (eq (car-safe a) 'mod)
1554 (eq (car-safe b) 'mod)
1555 (equal (nth 2 a) (nth 2 b)))
1556 (math-make-mod (math-div-mod (nth 1 a) (nth 1 b) (nth 2 a))
1557 (nth 2 a)))
1558 ((and (eq (car-safe a) 'mod)
1559 (Math-anglep b))
1560 (math-make-mod (math-div-mod (nth 1 a) b (nth 2 a)) (nth 2 a)))
1561 ((and (eq (car-safe b) 'mod)
1562 (Math-anglep a))
1563 (math-make-mod (math-div-mod a (nth 1 b) (nth 2 b)) (nth 2 b)))
1564 ((eq (car-safe a) 'hms)
1565 (if (eq (car-safe b) 'hms)
1566 (math-with-extra-prec 1
1567 (math-div (math-from-hms a 'deg)
1568 (math-from-hms b 'deg)))
1569 (math-with-extra-prec 2
1570 (math-to-hms (math-div (math-from-hms a 'deg) b) 'deg))))
898ea5c0 1571 (t (calc-record-why "*Incompatible arguments for /" a b))))
136211a9
EZ
1572
1573(defun math-div-by-zero (a b)
1574 (if (math-infinitep a)
1575 (if (or (equal a '(var nan var-nan))
1576 (equal b '(var uinf var-uinf))
1577 (memq calc-infinite-mode '(-1 1)))
1578 a
1579 '(var uinf var-uinf))
1580 (if calc-infinite-mode
1581 (if (math-zerop a)
1582 '(var nan var-nan)
1583 (if (eq calc-infinite-mode 1)
1584 (math-mul a '(var inf var-inf))
1585 (if (eq calc-infinite-mode -1)
1586 (math-mul a '(neg (var inf var-inf)))
1587 (if (eq (car-safe a) 'intv)
1588 '(intv 3 (neg (var inf var-inf)) (var inf var-inf))
1589 '(var uinf var-uinf)))))
898ea5c0 1590 (math-reject-arg a "*Division by zero"))))
136211a9
EZ
1591
1592(defun math-div-zero (a b)
1593 (if (math-known-matrixp b)
1594 (if (math-vectorp b)
1595 (math-map-vec-2 'math-div a b)
1596 (math-mimic-ident 0 b))
1597 (if (equal b '(var nan var-nan))
1598 b
1599 (if (and (eq (car-safe b) 'intv) (math-intv-constp b)
1600 (not (math-posp b)) (not (math-negp b)))
1601 (if calc-infinite-mode
1602 (list 'intv 3
1603 (if (and (math-zerop (nth 2 b))
1604 (memq calc-infinite-mode '(1 -1)))
1605 (nth 2 b) '(neg (var inf var-inf)))
1606 (if (and (math-zerop (nth 3 b))
1607 (memq calc-infinite-mode '(1 -1)))
1608 (nth 3 b) '(var inf var-inf)))
1609 (math-reject-arg b "*Division by zero"))
898ea5c0 1610 a))))
136211a9 1611
7db3d0d5
JB
1612;; For math-div-symb-fancy
1613(defvar math-trig-inverses
1614 '((calcFunc-sin . calcFunc-csc)
1615 (calcFunc-cos . calcFunc-sec)
1616 (calcFunc-tan . calcFunc-cot)
1617 (calcFunc-sec . calcFunc-cos)
1618 (calcFunc-csc . calcFunc-sin)
1619 (calcFunc-cot . calcFunc-tan)
1620 (calcFunc-sinh . calcFunc-csch)
1621 (calcFunc-cosh . calcFunc-sech)
1622 (calcFunc-tanh . calcFunc-coth)
1623 (calcFunc-sech . calcFunc-cosh)
1624 (calcFunc-csch . calcFunc-sinh)
1625 (calcFunc-coth . calcFunc-tanh)))
1626
1627(defvar math-div-trig)
1628(defvar math-div-non-trig)
1629
1630(defun math-div-new-trig (tr)
1631 (if math-div-trig
1632 (setq math-div-trig
1633 (list '* tr math-div-trig))
1634 (setq math-div-trig tr)))
1635
1636(defun math-div-new-non-trig (ntr)
1637 (if math-div-non-trig
1638 (setq math-div-non-trig
1639 (list '* ntr math-div-non-trig))
1640 (setq math-div-non-trig ntr)))
1641
1642(defun math-div-isolate-trig (expr)
1643 (if (eq (car-safe expr) '*)
1644 (progn
1645 (math-div-isolate-trig-term (nth 1 expr))
1646 (math-div-isolate-trig (nth 2 expr)))
1647 (math-div-isolate-trig-term expr)))
1648
1649(defun math-div-isolate-trig-term (term)
1650 (let ((fn (assoc (car-safe term) math-trig-inverses)))
1651 (if fn
1652 (math-div-new-trig
1653 (cons (cdr fn) (cdr term)))
1654 (math-div-new-non-trig term))))
1655
136211a9
EZ
1656(defun math-div-symb-fancy (a b)
1657 (or (and math-simplify-only
1658 (not (equal a math-simplify-only))
1659 (list '/ a b))
1660 (and (Math-equal-int b 1) a)
1661 (and (Math-equal-int b -1) (math-neg a))
1662 (and (Math-vectorp a) (math-known-scalarp b)
1663 (math-map-vec-2 'math-div a b))
1664 (and (eq (car-safe b) '^)
1665 (or (Math-looks-negp (nth 2 b)) (Math-equal-int a 1))
1666 (math-mul a (math-normalize
1667 (list '^ (nth 1 b) (math-neg (nth 2 b))))))
1668 (and (eq (car-safe a) 'neg)
1669 (math-neg (math-div (nth 1 a) b)))
1670 (and (eq (car-safe b) 'neg)
1671 (math-neg (math-div a (nth 1 b))))
1672 (and (eq (car-safe a) '/)
1673 (math-div (nth 1 a) (math-mul (nth 2 a) b)))
1674 (and (eq (car-safe b) '/)
1675 (or (math-known-scalarp (nth 1 b) t)
1676 (math-known-scalarp (nth 2 b) t))
1677 (math-div (math-mul a (nth 2 b)) (nth 1 b)))
1678 (and (eq (car-safe b) 'frac)
1679 (math-mul (math-make-frac (nth 2 b) (nth 1 b)) a))
1680 (and (eq (car-safe a) '+)
1681 (or (Math-numberp (nth 1 a))
1682 (Math-numberp (nth 2 a)))
1683 (Math-numberp b)
1684 (math-add (math-div (nth 1 a) b)
1685 (math-div (nth 2 a) b)))
1686 (and (eq (car-safe a) '-)
1687 (or (Math-numberp (nth 1 a))
1688 (Math-numberp (nth 2 a)))
1689 (Math-numberp b)
1690 (math-sub (math-div (nth 1 a) b)
1691 (math-div (nth 2 a) b)))
1692 (and (or (eq (car-safe a) '-)
1693 (math-looks-negp a))
1694 (math-looks-negp b)
1695 (math-div (math-neg a) (math-neg b)))
1696 (and (eq (car-safe b) '-)
1697 (math-looks-negp a)
1698 (math-div (math-neg a) (math-neg b)))
1699 (and (eq (car-safe a) 'calcFunc-idn)
1700 (= (length a) 2)
1701 (or (and (eq (car-safe b) 'calcFunc-idn)
1702 (= (length b) 2)
1703 (list 'calcFunc-idn (math-div (nth 1 a) (nth 1 b))))
1704 (and (math-known-scalarp b)
1705 (list 'calcFunc-idn (math-div (nth 1 a) b)))
1706 (and (math-known-matrixp b)
1707 (math-div (nth 1 a) b))))
1708 (and (eq (car-safe b) 'calcFunc-idn)
1709 (= (length b) 2)
1710 (or (and (math-known-scalarp a)
1711 (list 'calcFunc-idn (math-div a (nth 1 b))))
1712 (and (math-known-matrixp a)
1713 (math-div a (nth 1 b)))))
7db3d0d5
JB
1714 (and math-simplifying
1715 (let ((math-div-trig nil)
1716 (math-div-non-trig nil))
1717 (math-div-isolate-trig b)
1718 (if math-div-trig
1719 (if math-div-non-trig
1720 (math-div (math-mul a math-div-trig) math-div-non-trig)
1721 (math-mul a math-div-trig))
1722 nil)))
136211a9
EZ
1723 (if (and calc-matrix-mode
1724 (or (math-known-matrixp a) (math-known-matrixp b)))
1725 (math-combine-prod a b nil t nil)
1726 (if (eq (car-safe a) '*)
1727 (if (eq (car-safe b) '*)
1728 (let ((c (math-combine-prod (nth 1 a) (nth 1 b) nil t t)))
1729 (and c
1730 (math-div (math-mul c (nth 2 a)) (nth 2 b))))
1731 (let ((c (math-combine-prod (nth 1 a) b nil t t)))
1732 (and c
1733 (math-mul c (nth 2 a)))))
1734 (if (eq (car-safe b) '*)
1735 (let ((c (math-combine-prod a (nth 1 b) nil t t)))
1736 (and c
1737 (math-div c (nth 2 b))))
1738 (math-combine-prod a b nil t nil))))
1739 (and (math-infinitep a)
1740 (if (math-infinitep b)
1741 '(var nan var-nan)
1742 (if (or (equal a '(var nan var-nan))
1743 (equal a '(var uinf var-uinf)))
1744 a
1745 (if (equal a '(var inf var-inf))
1746 (if (or (math-posp b)
1747 (and (eq (car-safe b) 'intv)
1748 (math-zerop (nth 2 b))))
1749 (if (and (eq (car-safe b) 'intv)
1750 (not (math-intv-constp b t)))
1751 '(intv 3 0 (var inf var-inf))
1752 a)
1753 (if (or (math-negp b)
1754 (and (eq (car-safe b) 'intv)
1755 (math-zerop (nth 3 b))))
1756 (if (and (eq (car-safe b) 'intv)
1757 (not (math-intv-constp b t)))
1758 '(intv 3 (neg (var inf var-inf)) 0)
1759 (math-neg a))
1760 (if (and (eq (car-safe b) 'intv)
1761 (math-negp (nth 2 b)) (math-posp (nth 3 b)))
1762 '(intv 3 (neg (var inf var-inf))
1763 (var inf var-inf)))))))))
1764 (and (math-infinitep b)
1765 (if (equal b '(var nan var-nan))
1766 b
1767 (let ((calc-infinite-mode 1))
1768 (math-mul-zero b a))))
898ea5c0 1769 (list '/ a b)))
136211a9
EZ
1770
1771
1772(defun calcFunc-mod (a b)
898ea5c0 1773 (math-normalize (list '% a b)))
136211a9
EZ
1774
1775(defun math-mod-fancy (a b)
1776 (cond ((equal b '(var inf var-inf))
1777 (if (or (math-posp a) (math-zerop a))
1778 a
1779 (if (math-negp a)
1780 b
1781 (if (eq (car-safe a) 'intv)
1782 (if (math-negp (nth 2 a))
1783 '(intv 3 0 (var inf var-inf))
1784 a)
1785 (list '% a b)))))
1786 ((and (eq (car-safe a) 'mod) (Math-realp b) (math-posp b))
1787 (math-make-mod (nth 1 a) b))
1788 ((and (eq (car-safe a) 'intv) (math-intv-constp a t) (math-posp b))
1789 (math-mod-intv a b))
1790 (t
1791 (if (Math-anglep a)
1792 (calc-record-why 'anglep b)
1793 (calc-record-why 'anglep a))
898ea5c0 1794 (list '% a b))))
136211a9
EZ
1795
1796
1797(defun calcFunc-pow (a b)
898ea5c0 1798 (math-normalize (list '^ a b)))
136211a9
EZ
1799
1800(defun math-pow-of-zero (a b)
6adaed78
JB
1801 "Raise A to the power of B, where A is a form of zero."
1802 (if (math-floatp b) (setq a (math-float a)))
1803 (cond
1804 ;; 0^0 = 1
1805 ((eq b 0)
1806 1)
1807 ;; 0^0.0, etc., are undetermined
1808 ((Math-zerop b)
1809 (if calc-infinite-mode
1810 '(var nan var-nan)
1811 (math-reject-arg (list '^ a b) "*Indeterminate form")))
1812 ;; 0^positive = 0
773a144d 1813 ((math-known-posp b)
6adaed78
JB
1814 a)
1815 ;; 0^negative is undefined (let math-div handle it)
773a144d 1816 ((math-known-negp b)
6adaed78
JB
1817 (math-div 1 a))
1818 ;; 0^infinity is undefined
1819 ((math-infinitep b)
1820 '(var nan var-nan))
1821 ;; Some intervals
1822 ((and (eq (car b) 'intv)
1823 calc-infinite-mode
1824 (math-negp (nth 2 b))
1825 (math-posp (nth 3 b)))
1826 '(intv 3 (neg (var inf var-inf)) (var inf var-inf)))
1827 ;; If none of the above, leave it alone.
1828 (t
1829 (list '^ a b))))
136211a9
EZ
1830
1831(defun math-pow-zero (a b)
1832 (if (eq (car-safe a) 'mod)
1833 (math-make-mod 1 (nth 2 a))
1834 (if (math-known-matrixp a)
1835 (math-mimic-ident 1 a)
1836 (if (math-infinitep a)
1837 '(var nan var-nan)
1838 (if (and (eq (car a) 'intv) (math-intv-constp a)
1839 (or (and (not (math-posp a)) (not (math-negp a)))
1840 (not (math-intv-constp a t))))
1841 '(intv 3 (neg (var inf var-inf)) (var inf var-inf))
1842 (if (or (math-floatp a) (math-floatp b))
898ea5c0 1843 '(float 1 0) 1))))))
136211a9
EZ
1844
1845(defun math-pow-fancy (a b)
1846 (cond ((and (Math-numberp a) (Math-numberp b))
1847 (or (if (memq (math-quarter-integer b) '(1 2 3))
1848 (let ((sqrt (math-sqrt (if (math-floatp b)
1849 (math-float a) a))))
1850 (and (Math-numberp sqrt)
1851 (math-pow sqrt (math-mul 2 b))))
1852 (and (eq (car b) 'frac)
1853 (integerp (nth 2 b))
1854 (<= (nth 2 b) 10)
1855 (let ((root (math-nth-root a (nth 2 b))))
1856 (and root (math-ipow root (nth 1 b))))))
1857 (and (or (eq a 10) (equal a '(float 1 1)))
1858 (math-num-integerp b)
1859 (calcFunc-scf '(float 1 0) b))
1860 (and calc-symbolic-mode
1861 (list '^ a b))
1862 (math-with-extra-prec 2
1863 (math-exp-raw
1864 (math-float (math-mul b (math-ln-raw (math-float a))))))))
1865 ((or (not (Math-objvecp a))
1866 (not (Math-objectp b)))
1867 (let (temp)
1868 (cond ((and math-simplify-only
1869 (not (equal a math-simplify-only)))
1870 (list '^ a b))
1871 ((and (eq (car-safe a) '*)
1872 (or (math-known-num-integerp b)
1873 (math-known-nonnegp (nth 1 a))
1874 (math-known-nonnegp (nth 2 a))))
1875 (math-mul (math-pow (nth 1 a) b)
1876 (math-pow (nth 2 a) b)))
1877 ((and (eq (car-safe a) '/)
1878 (or (math-known-num-integerp b)
1879 (math-known-nonnegp (nth 2 a))))
1880 (math-div (math-pow (nth 1 a) b)
1881 (math-pow (nth 2 a) b)))
1882 ((and (eq (car-safe a) '/)
1883 (math-known-nonnegp (nth 1 a))
1884 (not (math-equal-int (nth 1 a) 1)))
1885 (math-mul (math-pow (nth 1 a) b)
1886 (math-pow (math-div 1 (nth 2 a)) b)))
1887 ((and (eq (car-safe a) '^)
1888 (or (math-known-num-integerp b)
1889 (math-known-nonnegp (nth 1 a))))
1890 (math-pow (nth 1 a) (math-mul (nth 2 a) b)))
1891 ((and (eq (car-safe a) 'calcFunc-sqrt)
1892 (or (math-known-num-integerp b)
1893 (math-known-nonnegp (nth 1 a))))
1894 (math-pow (nth 1 a) (math-div b 2)))
1895 ((and (eq (car-safe a) '^)
1896 (math-known-evenp (nth 2 a))
1897 (memq (math-quarter-integer b) '(1 2 3))
1898 (math-known-realp (nth 1 a)))
1899 (math-abs (math-pow (nth 1 a) (math-mul (nth 2 a) b))))
1900 ((and (math-looks-negp a)
1901 (math-known-integerp b)
1902 (setq temp (or (and (math-known-evenp b)
1903 (math-pow (math-neg a) b))
1904 (and (math-known-oddp b)
1905 (math-neg (math-pow (math-neg a)
1906 b))))))
1907 temp)
1908 ((and (eq (car-safe a) 'calcFunc-abs)
1909 (math-known-realp (nth 1 a))
1910 (math-known-evenp b))
1911 (math-pow (nth 1 a) b))
1912 ((math-infinitep a)
1913 (cond ((equal a '(var nan var-nan))
1914 a)
1915 ((eq (car a) 'neg)
1916 (math-mul (math-pow -1 b) (math-pow (nth 1 a) b)))
1917 ((math-posp b)
1918 a)
1919 ((math-negp b)
1920 (if (math-floatp b) '(float 0 0) 0))
1921 ((and (eq (car-safe b) 'intv)
1922 (math-intv-constp b))
1923 '(intv 3 0 (var inf var-inf)))
1924 (t
1925 '(var nan var-nan))))
1926 ((math-infinitep b)
1927 (let (scale)
1928 (cond ((math-negp b)
1929 (math-pow (math-div 1 a) (math-neg b)))
1930 ((not (math-posp b))
1931 '(var nan var-nan))
1932 ((math-equal-int (setq scale (calcFunc-abssqr a)) 1)
1933 '(var nan var-nan))
1934 ((Math-lessp scale 1)
1935 (if (math-floatp a) '(float 0 0) 0))
1936 ((Math-lessp 1 a)
1937 b)
1938 ((Math-lessp a -1)
1939 '(var uinf var-uinf))
1940 ((and (eq (car a) 'intv)
1941 (math-intv-constp a))
1942 (if (Math-lessp -1 a)
1943 (if (math-equal-int (nth 3 a) 1)
1944 '(intv 3 0 1)
1945 '(intv 3 0 (var inf var-inf)))
1946 '(intv 3 (neg (var inf var-inf))
1947 (var inf var-inf))))
1948 (t (list '^ a b)))))
1949 ((and (eq (car-safe a) 'calcFunc-idn)
1950 (= (length a) 2)
1951 (math-known-num-integerp b))
1952 (list 'calcFunc-idn (math-pow (nth 1 a) b)))
1953 (t (if (Math-objectp a)
1954 (calc-record-why 'objectp b)
1955 (calc-record-why 'objectp a))
1956 (list '^ a b)))))
1957 ((and (eq (car-safe a) 'sdev) (eq (car-safe b) 'sdev))
1958 (if (and (math-constp a) (math-constp b))
1959 (math-with-extra-prec 2
1960 (let* ((ln (math-ln-raw (math-float (nth 1 a))))
1961 (pow (math-exp-raw
1962 (math-float (math-mul (nth 1 b) ln)))))
1963 (math-make-sdev
1964 pow
1965 (math-mul
1966 pow
1967 (math-hypot (math-mul (nth 2 a)
1968 (math-div (nth 1 b) (nth 1 a)))
1969 (math-mul (nth 2 b) ln))))))
1970 (let ((pow (math-pow (nth 1 a) (nth 1 b))))
1971 (math-make-sdev
1972 pow
1973 (math-mul pow
1974 (math-hypot (math-mul (nth 2 a)
1975 (math-div (nth 1 b) (nth 1 a)))
1976 (math-mul (nth 2 b) (calcFunc-ln
1977 (nth 1 a)))))))))
1978 ((and (eq (car-safe a) 'sdev) (Math-numberp b))
1979 (if (math-constp a)
1980 (math-with-extra-prec 2
1981 (let ((pow (math-pow (nth 1 a) (math-sub b 1))))
1982 (math-make-sdev (math-mul pow (nth 1 a))
1983 (math-mul pow (math-mul (nth 2 a) b)))))
1984 (math-make-sdev (math-pow (nth 1 a) b)
1985 (math-mul (math-pow (nth 1 a) (math-add b -1))
1986 (math-mul (nth 2 a) b)))))
1987 ((and (eq (car-safe b) 'sdev) (Math-numberp a))
1988 (math-with-extra-prec 2
1989 (let* ((ln (math-ln-raw (math-float a)))
1990 (pow (calcFunc-exp (math-mul (nth 1 b) ln))))
1991 (math-make-sdev pow (math-mul pow (math-mul (nth 2 b) ln))))))
1992 ((and (eq (car-safe a) 'intv) (math-intv-constp a)
1993 (Math-realp b)
1994 (or (Math-natnump b)
1995 (Math-posp (nth 2 a))
1996 (and (math-zerop (nth 2 a))
1997 (or (Math-posp b)
1998 (and (Math-integerp b) calc-infinite-mode)))
1999 (Math-negp (nth 3 a))
2000 (and (math-zerop (nth 3 a))
2001 (or (Math-posp b)
2002 (and (Math-integerp b) calc-infinite-mode)))))
2003 (if (math-evenp b)
2004 (setq a (math-abs a)))
2005 (let ((calc-infinite-mode (if (math-zerop (nth 3 a)) -1 1)))
2006 (math-sort-intv (nth 1 a)
2007 (math-pow (nth 2 a) b)
2008 (math-pow (nth 3 a) b))))
2009 ((and (eq (car-safe b) 'intv) (math-intv-constp b)
2010 (Math-realp a) (Math-posp a))
2011 (math-sort-intv (nth 1 b)
2012 (math-pow a (nth 2 b))
2013 (math-pow a (nth 3 b))))
2014 ((and (eq (car-safe a) 'intv) (math-intv-constp a)
2015 (eq (car-safe b) 'intv) (math-intv-constp b)
2016 (or (and (not (Math-negp (nth 2 a)))
2017 (not (Math-negp (nth 2 b))))
2018 (and (Math-posp (nth 2 a))
2019 (not (Math-posp (nth 3 b))))))
2020 (let ((lo (math-pow a (nth 2 b)))
2021 (hi (math-pow a (nth 3 b))))
2022 (or (eq (car-safe lo) 'intv)
2023 (setq lo (list 'intv (if (memq (nth 1 b) '(2 3)) 3 0) lo lo)))
2024 (or (eq (car-safe hi) 'intv)
2025 (setq hi (list 'intv (if (memq (nth 1 b) '(1 3)) 3 0) hi hi)))
2026 (math-combine-intervals
2027 (nth 2 lo) (and (or (memq (nth 1 b) '(2 3))
2028 (math-infinitep (nth 2 lo)))
2029 (memq (nth 1 lo) '(2 3)))
2030 (nth 3 lo) (and (or (memq (nth 1 b) '(2 3))
2031 (math-infinitep (nth 3 lo)))
2032 (memq (nth 1 lo) '(1 3)))
2033 (nth 2 hi) (and (or (memq (nth 1 b) '(1 3))
2034 (math-infinitep (nth 2 hi)))
2035 (memq (nth 1 hi) '(2 3)))
2036 (nth 3 hi) (and (or (memq (nth 1 b) '(1 3))
2037 (math-infinitep (nth 3 hi)))
2038 (memq (nth 1 hi) '(1 3))))))
2039 ((and (eq (car-safe a) 'mod) (eq (car-safe b) 'mod)
2040 (equal (nth 2 a) (nth 2 b)))
2041 (math-make-mod (math-pow-mod (nth 1 a) (nth 1 b) (nth 2 a))
2042 (nth 2 a)))
2043 ((and (eq (car-safe a) 'mod) (Math-anglep b))
2044 (math-make-mod (math-pow-mod (nth 1 a) b (nth 2 a)) (nth 2 a)))
2045 ((and (eq (car-safe b) 'mod) (Math-anglep a))
2046 (math-make-mod (math-pow-mod a (nth 1 b) (nth 2 b)) (nth 2 b)))
2047 ((not (Math-numberp a))
2048 (math-reject-arg a 'numberp))
2049 (t
898ea5c0 2050 (math-reject-arg b 'numberp))))
136211a9
EZ
2051
2052(defun math-quarter-integer (x)
2053 (if (Math-integerp x)
2054 0
2055 (if (math-negp x)
2056 (progn
2057 (setq x (math-quarter-integer (math-neg x)))
2058 (and x (- 4 x)))
2059 (if (eq (car x) 'frac)
2060 (if (eq (nth 2 x) 2)
2061 2
2062 (and (eq (nth 2 x) 4)
2063 (progn
2064 (setq x (nth 1 x))
2065 (% (if (consp x) (nth 1 x) x) 4))))
2066 (if (eq (car x) 'float)
2067 (if (>= (nth 2 x) 0)
2068 0
2069 (if (= (nth 2 x) -1)
2070 (progn
2071 (setq x (nth 1 x))
2072 (and (= (% (if (consp x) (nth 1 x) x) 10) 5) 2))
2073 (if (= (nth 2 x) -2)
2074 (progn
2075 (setq x (nth 1 x)
2076 x (% (if (consp x) (nth 1 x) x) 100))
2077 (if (= x 25) 1
898ea5c0 2078 (if (= x 75) 3)))))))))))
136211a9
EZ
2079
2080;;; This assumes A < M and M > 0.
2081(defun math-pow-mod (a b m) ; [R R R R]
2082 (if (and (Math-integerp a) (Math-integerp b) (Math-integerp m))
2083 (if (Math-negp b)
2084 (math-div-mod 1 (math-pow-mod a (Math-integer-neg b) m) m)
2085 (if (eq m 1)
2086 0
2087 (math-pow-mod-step a b m)))
898ea5c0 2088 (math-mod (math-pow a b) m)))
136211a9
EZ
2089
2090(defun math-pow-mod-step (a n m) ; [I I I I]
2091 (math-working "pow" a)
2092 (let ((val (cond
2093 ((eq n 0) 1)
2094 ((eq n 1) a)
2095 (t
2096 (let ((rest (math-pow-mod-step
2097 (math-imod (math-mul a a) m)
2098 (math-div2 n)
2099 m)))
2100 (if (math-evenp n)
2101 rest
2102 (math-mod (math-mul a rest) m)))))))
2103 (math-working "pow" val)
898ea5c0 2104 val))
136211a9
EZ
2105
2106
2107;;; Compute the minimum of two real numbers. [R R R] [Public]
2108(defun math-min (a b)
2109 (if (and (consp a) (eq (car a) 'intv))
2110 (if (and (consp b) (eq (car b) 'intv))
2111 (let ((lo (nth 2 a))
2112 (lom (memq (nth 1 a) '(2 3)))
2113 (hi (nth 3 a))
2114 (him (memq (nth 1 a) '(1 3)))
2115 res)
2116 (if (= (setq res (math-compare (nth 2 b) lo)) -1)
2117 (setq lo (nth 2 b) lom (memq (nth 1 b) '(2 3)))
2118 (if (= res 0)
2119 (setq lom (or lom (memq (nth 1 b) '(2 3))))))
2120 (if (= (setq res (math-compare (nth 3 b) hi)) -1)
2121 (setq hi (nth 3 b) him (memq (nth 1 b) '(1 3)))
2122 (if (= res 0)
2123 (setq him (or him (memq (nth 1 b) '(1 3))))))
2124 (math-make-intv (+ (if lom 2 0) (if him 1 0)) lo hi))
2125 (math-min a (list 'intv 3 b b)))
2126 (if (and (consp b) (eq (car b) 'intv))
2127 (math-min (list 'intv 3 a a) b)
2128 (let ((res (math-compare a b)))
2129 (if (= res 1)
2130 b
2131 (if (= res 2)
2132 '(var nan var-nan)
898ea5c0 2133 a))))))
136211a9
EZ
2134
2135(defun calcFunc-min (&optional a &rest b)
2136 (if (not a)
2137 '(var inf var-inf)
2138 (if (not (or (Math-anglep a) (eq (car a) 'date)
2139 (and (eq (car a) 'intv) (math-intv-constp a))
2140 (math-infinitep a)))
2141 (math-reject-arg a 'anglep))
898ea5c0 2142 (math-min-list a b)))
136211a9
EZ
2143
2144(defun math-min-list (a b)
2145 (if b
2146 (if (or (Math-anglep (car b)) (eq (car b) 'date)
2147 (and (eq (car (car b)) 'intv) (math-intv-constp (car b)))
2148 (math-infinitep (car b)))
2149 (math-min-list (math-min a (car b)) (cdr b))
2150 (math-reject-arg (car b) 'anglep))
898ea5c0 2151 a))
136211a9
EZ
2152
2153;;; Compute the maximum of two real numbers. [R R R] [Public]
2154(defun math-max (a b)
2155 (if (or (and (consp a) (eq (car a) 'intv))
2156 (and (consp b) (eq (car b) 'intv)))
2157 (math-neg (math-min (math-neg a) (math-neg b)))
2158 (let ((res (math-compare a b)))
2159 (if (= res -1)
2160 b
2161 (if (= res 2)
2162 '(var nan var-nan)
898ea5c0 2163 a)))))
136211a9
EZ
2164
2165(defun calcFunc-max (&optional a &rest b)
2166 (if (not a)
2167 '(neg (var inf var-inf))
2168 (if (not (or (Math-anglep a) (eq (car a) 'date)
2169 (and (eq (car a) 'intv) (math-intv-constp a))
2170 (math-infinitep a)))
2171 (math-reject-arg a 'anglep))
898ea5c0 2172 (math-max-list a b)))
136211a9
EZ
2173
2174(defun math-max-list (a b)
2175 (if b
2176 (if (or (Math-anglep (car b)) (eq (car b) 'date)
2177 (and (eq (car (car b)) 'intv) (math-intv-constp (car b)))
2178 (math-infinitep (car b)))
2179 (math-max-list (math-max a (car b)) (cdr b))
2180 (math-reject-arg (car b) 'anglep))
898ea5c0 2181 a))
136211a9
EZ
2182
2183
2184;;; Compute the absolute value of A. [O O; r r] [Public]
2185(defun math-abs (a)
2186 (cond ((Math-negp a)
2187 (math-neg a))
2188 ((Math-anglep a)
2189 a)
2190 ((eq (car a) 'cplx)
2191 (math-hypot (nth 1 a) (nth 2 a)))
2192 ((eq (car a) 'polar)
2193 (nth 1 a))
2194 ((eq (car a) 'vec)
2195 (if (cdr (cdr (cdr a)))
2196 (math-sqrt (calcFunc-abssqr a))
2197 (if (cdr (cdr a))
2198 (math-hypot (nth 1 a) (nth 2 a))
2199 (if (cdr a)
2200 (math-abs (nth 1 a))
2201 a))))
2202 ((eq (car a) 'sdev)
2203 (list 'sdev (math-abs (nth 1 a)) (nth 2 a)))
2204 ((and (eq (car a) 'intv) (math-intv-constp a))
2205 (if (Math-posp a)
2206 a
2207 (let* ((nlo (math-neg (nth 2 a)))
2208 (res (math-compare nlo (nth 3 a))))
2209 (cond ((= res 1)
2210 (math-make-intv (if (memq (nth 1 a) '(0 1)) 2 3) 0 nlo))
2211 ((= res 0)
2212 (math-make-intv (if (eq (nth 1 a) 0) 2 3) 0 nlo))
2213 (t
2214 (math-make-intv (if (memq (nth 1 a) '(0 2)) 2 3)
2215 0 (nth 3 a)))))))
2216 ((math-looks-negp a)
2217 (list 'calcFunc-abs (math-neg a)))
2218 ((let ((signs (math-possible-signs a)))
2219 (or (and (memq signs '(2 4 6)) a)
2220 (and (memq signs '(1 3)) (math-neg a)))))
2221 ((let ((inf (math-infinitep a)))
2222 (and inf
2223 (if (equal inf '(var nan var-nan))
2224 inf
2225 '(var inf var-inf)))))
2226 (t (calc-record-why 'numvecp a)
898ea5c0 2227 (list 'calcFunc-abs a))))
136211a9 2228
898ea5c0 2229(defalias 'calcFunc-abs 'math-abs)
136211a9
EZ
2230
2231(defun math-float-fancy (a)
2232 (cond ((eq (car a) 'intv)
2233 (cons (car a) (cons (nth 1 a) (mapcar 'math-float (nthcdr 2 a)))))
2234 ((and (memq (car a) '(* /))
2235 (math-numberp (nth 1 a)))
2236 (list (car a) (math-float (nth 1 a))
2237 (list 'calcFunc-float (nth 2 a))))
2238 ((and (eq (car a) '/)
2239 (eq (car (nth 1 a)) '*)
2240 (math-numberp (nth 1 (nth 1 a))))
2241 (list '* (math-float (nth 1 (nth 1 a)))
2242 (list 'calcFunc-float (list '/ (nth 2 (nth 1 a)) (nth 2 a)))))
2243 ((math-infinitep a) a)
2244 ((eq (car a) 'calcFunc-float) a)
2245 ((let ((func (assq (car a) '((calcFunc-floor . calcFunc-ffloor)
2246 (calcFunc-ceil . calcFunc-fceil)
2247 (calcFunc-trunc . calcFunc-ftrunc)
2248 (calcFunc-round . calcFunc-fround)
2249 (calcFunc-rounde . calcFunc-frounde)
2250 (calcFunc-roundu . calcFunc-froundu)))))
2251 (and func (cons (cdr func) (cdr a)))))
898ea5c0 2252 (t (math-reject-arg a 'objectp))))
136211a9 2253
898ea5c0 2254(defalias 'calcFunc-float 'math-float)
136211a9 2255
67549a85
JB
2256;; The variable math-trunc-prec is local to math-trunc in calc-misc.el,
2257;; but used by math-trunc-fancy which is called by math-trunc.
2258(defvar math-trunc-prec)
2259
136211a9
EZ
2260(defun math-trunc-fancy (a)
2261 (cond ((eq (car a) 'frac) (math-quotient (nth 1 a) (nth 2 a)))
2262 ((eq (car a) 'cplx) (math-trunc (nth 1 a)))
2263 ((eq (car a) 'polar) (math-trunc (math-complex a)))
2264 ((eq (car a) 'hms) (list 'hms (nth 1 a) 0 0))
2265 ((eq (car a) 'date) (list 'date (math-trunc (nth 1 a))))
2266 ((eq (car a) 'mod)
2267 (if (math-messy-integerp (nth 2 a))
2268 (math-trunc (math-make-mod (nth 1 a) (math-trunc (nth 2 a))))
2269 (math-make-mod (math-trunc (nth 1 a)) (nth 2 a))))
2270 ((eq (car a) 'intv)
2271 (math-make-intv (+ (if (and (equal (nth 2 a) '(neg (var inf var-inf)))
2272 (memq (nth 1 a) '(0 1)))
2273 0 2)
2274 (if (and (equal (nth 3 a) '(var inf var-inf))
2275 (memq (nth 1 a) '(0 2)))
2276 0 1))
2277 (if (and (Math-negp (nth 2 a))
2278 (Math-num-integerp (nth 2 a))
2279 (memq (nth 1 a) '(0 1)))
2280 (math-add (math-trunc (nth 2 a)) 1)
2281 (math-trunc (nth 2 a)))
2282 (if (and (Math-posp (nth 3 a))
2283 (Math-num-integerp (nth 3 a))
2284 (memq (nth 1 a) '(0 2)))
2285 (math-add (math-trunc (nth 3 a)) -1)
2286 (math-trunc (nth 3 a)))))
2287 ((math-provably-integerp a) a)
2288 ((Math-vectorp a)
67549a85 2289 (math-map-vec (function (lambda (x) (math-trunc x math-trunc-prec))) a))
136211a9
EZ
2290 ((math-infinitep a)
2291 (if (or (math-posp a) (math-negp a))
2292 a
2293 '(var nan var-nan)))
2294 ((math-to-integer a))
898ea5c0 2295 (t (math-reject-arg a 'numberp))))
136211a9
EZ
2296
2297(defun math-trunc-special (a prec)
2298 (if (Math-messy-integerp prec)
2299 (setq prec (math-trunc prec)))
2300 (or (integerp prec)
2301 (math-reject-arg prec 'fixnump))
2302 (if (and (<= prec 0)
2303 (math-provably-integerp a))
2304 a
2305 (calcFunc-scf (math-trunc (let ((calc-prefer-frac t))
2306 (calcFunc-scf a prec)))
898ea5c0 2307 (- prec))))
136211a9
EZ
2308
2309(defun math-to-integer (a)
2310 (let ((func (assq (car-safe a) '((calcFunc-ffloor . calcFunc-floor)
2311 (calcFunc-fceil . calcFunc-ceil)
2312 (calcFunc-ftrunc . calcFunc-trunc)
2313 (calcFunc-fround . calcFunc-round)
2314 (calcFunc-frounde . calcFunc-rounde)
2315 (calcFunc-froundu . calcFunc-roundu)))))
2316 (and func (= (length a) 2)
898ea5c0 2317 (cons (cdr func) (cdr a)))))
136211a9
EZ
2318
2319(defun calcFunc-ftrunc (a &optional prec)
2320 (if (and (Math-messy-integerp a)
2321 (or (not prec) (and (integerp prec)
2322 (<= prec 0))))
2323 a
898ea5c0 2324 (math-float (math-trunc a prec))))
136211a9 2325
67549a85
JB
2326;; The variable math-floor-prec is local to math-floor in calc-misc.el,
2327;; but used by math-floor-fancy which is called by math-floor.
2328(defvar math-floor-prec)
2329
136211a9
EZ
2330(defun math-floor-fancy (a)
2331 (cond ((math-provably-integerp a) a)
2332 ((eq (car a) 'hms)
2333 (if (or (math-posp a)
2334 (and (math-zerop (nth 2 a))
2335 (math-zerop (nth 3 a))))
2336 (math-trunc a)
2337 (math-add (math-trunc a) -1)))
2338 ((eq (car a) 'date) (list 'date (math-floor (nth 1 a))))
2339 ((eq (car a) 'intv)
2340 (math-make-intv (+ (if (and (equal (nth 2 a) '(neg (var inf var-inf)))
2341 (memq (nth 1 a) '(0 1)))
2342 0 2)
2343 (if (and (equal (nth 3 a) '(var inf var-inf))
2344 (memq (nth 1 a) '(0 2)))
2345 0 1))
2346 (math-floor (nth 2 a))
2347 (if (and (Math-num-integerp (nth 3 a))
2348 (memq (nth 1 a) '(0 2)))
2349 (math-add (math-floor (nth 3 a)) -1)
2350 (math-floor (nth 3 a)))))
2351 ((Math-vectorp a)
95d91710 2352 (math-map-vec (function (lambda (x) (math-floor x math-floor-prec))) a))
136211a9
EZ
2353 ((math-infinitep a)
2354 (if (or (math-posp a) (math-negp a))
2355 a
2356 '(var nan var-nan)))
2357 ((math-to-integer a))
898ea5c0 2358 (t (math-reject-arg a 'anglep))))
136211a9
EZ
2359
2360(defun math-floor-special (a prec)
2361 (if (Math-messy-integerp prec)
2362 (setq prec (math-trunc prec)))
2363 (or (integerp prec)
2364 (math-reject-arg prec 'fixnump))
2365 (if (and (<= prec 0)
2366 (math-provably-integerp a))
2367 a
2368 (calcFunc-scf (math-floor (let ((calc-prefer-frac t))
2369 (calcFunc-scf a prec)))
898ea5c0 2370 (- prec))))
136211a9
EZ
2371
2372(defun calcFunc-ffloor (a &optional prec)
2373 (if (and (Math-messy-integerp a)
2374 (or (not prec) (and (integerp prec)
2375 (<= prec 0))))
2376 a
898ea5c0 2377 (math-float (math-floor a prec))))
136211a9
EZ
2378
2379;;; Coerce A to be an integer (by truncation toward plus infinity). [I N]
2380(defun math-ceiling (a &optional prec) ; [Public]
2381 (cond (prec
2382 (if (Math-messy-integerp prec)
2383 (setq prec (math-trunc prec)))
2384 (or (integerp prec)
2385 (math-reject-arg prec 'fixnump))
2386 (if (and (<= prec 0)
2387 (math-provably-integerp a))
2388 a
2389 (calcFunc-scf (math-ceiling (let ((calc-prefer-frac t))
2390 (calcFunc-scf a prec)))
2391 (- prec))))
2392 ((Math-integerp a) a)
2393 ((Math-messy-integerp a) (math-trunc a))
2394 ((Math-realp a)
2395 (if (Math-posp a)
2396 (math-add (math-trunc a) 1)
2397 (math-trunc a)))
2398 ((math-provably-integerp a) a)
2399 ((eq (car a) 'hms)
2400 (if (or (math-negp a)
2401 (and (math-zerop (nth 2 a))
2402 (math-zerop (nth 3 a))))
2403 (math-trunc a)
2404 (math-add (math-trunc a) 1)))
2405 ((eq (car a) 'date) (list 'date (math-ceiling (nth 1 a))))
2406 ((eq (car a) 'intv)
2407 (math-make-intv (+ (if (and (equal (nth 2 a) '(neg (var inf var-inf)))
2408 (memq (nth 1 a) '(0 1)))
2409 0 2)
2410 (if (and (equal (nth 3 a) '(var inf var-inf))
2411 (memq (nth 1 a) '(0 2)))
2412 0 1))
2413 (if (and (Math-num-integerp (nth 2 a))
2414 (memq (nth 1 a) '(0 1)))
2415 (math-add (math-floor (nth 2 a)) 1)
2416 (math-ceiling (nth 2 a)))
2417 (math-ceiling (nth 3 a))))
2418 ((Math-vectorp a)
2419 (math-map-vec (function (lambda (x) (math-ceiling x prec))) a))
2420 ((math-infinitep a)
2421 (if (or (math-posp a) (math-negp a))
2422 a
2423 '(var nan var-nan)))
2424 ((math-to-integer a))
898ea5c0
CW
2425 (t (math-reject-arg a 'anglep))))
2426
2427(defalias 'calcFunc-ceil 'math-ceiling)
136211a9
EZ
2428
2429(defun calcFunc-fceil (a &optional prec)
2430 (if (and (Math-messy-integerp a)
2431 (or (not prec) (and (integerp prec)
2432 (<= prec 0))))
2433 a
898ea5c0 2434 (math-float (math-ceiling a prec))))
136211a9 2435
3132f345 2436(defvar math-rounding-mode nil)
136211a9
EZ
2437
2438;;; Coerce A to be an integer (by rounding to nearest integer). [I N] [Public]
2439(defun math-round (a &optional prec)
2440 (cond (prec
2441 (if (Math-messy-integerp prec)
2442 (setq prec (math-trunc prec)))
2443 (or (integerp prec)
2444 (math-reject-arg prec 'fixnump))
2445 (if (and (<= prec 0)
2446 (math-provably-integerp a))
2447 a
2448 (calcFunc-scf (math-round (let ((calc-prefer-frac t))
2449 (calcFunc-scf a prec)))
2450 (- prec))))
2451 ((Math-anglep a)
2452 (if (Math-num-integerp a)
2453 (math-trunc a)
2454 (if (and (Math-negp a) (not (eq math-rounding-mode 'up)))
2455 (math-neg (math-round (math-neg a)))
2456 (setq a (let ((calc-angle-mode 'deg)) ; in case of HMS forms
2457 (math-add a (if (Math-ratp a)
2458 '(frac 1 2)
2459 '(float 5 -1)))))
2460 (if (and (Math-num-integerp a) (eq math-rounding-mode 'even))
2461 (progn
2462 (setq a (math-floor a))
2463 (or (math-evenp a)
2464 (setq a (math-sub a 1)))
2465 a)
2466 (math-floor a)))))
2467 ((math-provably-integerp a) a)
2468 ((eq (car a) 'date) (list 'date (math-round (nth 1 a))))
2469 ((eq (car a) 'intv)
2470 (math-floor (math-add a '(frac 1 2))))
2471 ((Math-vectorp a)
2472 (math-map-vec (function (lambda (x) (math-round x prec))) a))
2473 ((math-infinitep a)
2474 (if (or (math-posp a) (math-negp a))
2475 a
2476 '(var nan var-nan)))
2477 ((math-to-integer a))
898ea5c0 2478 (t (math-reject-arg a 'anglep))))
136211a9 2479
898ea5c0
CW
2480(defalias 'calcFunc-round 'math-round)
2481
2482(defsubst calcFunc-rounde (a &optional prec)
136211a9 2483 (let ((math-rounding-mode 'even))
898ea5c0 2484 (math-round a prec)))
136211a9 2485
898ea5c0 2486(defsubst calcFunc-roundu (a &optional prec)
136211a9 2487 (let ((math-rounding-mode 'up))
898ea5c0 2488 (math-round a prec)))
136211a9
EZ
2489
2490(defun calcFunc-fround (a &optional prec)
2491 (if (and (Math-messy-integerp a)
2492 (or (not prec) (and (integerp prec)
2493 (<= prec 0))))
2494 a
898ea5c0 2495 (math-float (math-round a prec))))
136211a9 2496
898ea5c0 2497(defsubst calcFunc-frounde (a &optional prec)
136211a9 2498 (let ((math-rounding-mode 'even))
898ea5c0 2499 (calcFunc-fround a prec)))
136211a9 2500
898ea5c0 2501(defsubst calcFunc-froundu (a &optional prec)
136211a9 2502 (let ((math-rounding-mode 'up))
898ea5c0 2503 (calcFunc-fround a prec)))
136211a9
EZ
2504
2505;;; Pull floating-point values apart into mantissa and exponent.
2506(defun calcFunc-mant (x)
2507 (if (Math-realp x)
2508 (if (or (Math-ratp x)
2509 (eq (nth 1 x) 0))
2510 x
2511 (list 'float (nth 1 x) (- 1 (math-numdigs (nth 1 x)))))
2512 (calc-record-why 'realp x)
898ea5c0 2513 (list 'calcFunc-mant x)))
136211a9
EZ
2514
2515(defun calcFunc-xpon (x)
2516 (if (Math-realp x)
2517 (if (or (Math-ratp x)
2518 (eq (nth 1 x) 0))
2519 0
2520 (math-normalize (+ (nth 2 x) (1- (math-numdigs (nth 1 x))))))
2521 (calc-record-why 'realp x)
898ea5c0 2522 (list 'calcFunc-xpon x)))
136211a9
EZ
2523
2524(defun calcFunc-scf (x n)
2525 (if (integerp n)
2526 (cond ((eq n 0)
2527 x)
2528 ((Math-integerp x)
2529 (if (> n 0)
2530 (math-scale-int x n)
2531 (math-div x (math-scale-int 1 (- n)))))
2532 ((eq (car x) 'frac)
2533 (if (> n 0)
2534 (math-make-frac (math-scale-int (nth 1 x) n) (nth 2 x))
2535 (math-make-frac (nth 1 x) (math-scale-int (nth 2 x) (- n)))))
2536 ((eq (car x) 'float)
2537 (math-make-float (nth 1 x) (+ (nth 2 x) n)))
2538 ((memq (car x) '(cplx sdev))
2539 (math-normalize
2540 (list (car x)
2541 (calcFunc-scf (nth 1 x) n)
2542 (calcFunc-scf (nth 2 x) n))))
2543 ((memq (car x) '(polar mod))
2544 (math-normalize
2545 (list (car x)
2546 (calcFunc-scf (nth 1 x) n)
2547 (nth 2 x))))
2548 ((eq (car x) 'intv)
2549 (math-normalize
2550 (list (car x)
2551 (nth 1 x)
2552 (calcFunc-scf (nth 2 x) n)
2553 (calcFunc-scf (nth 3 x) n))))
2554 ((eq (car x) 'vec)
2555 (math-map-vec (function (lambda (x) (calcFunc-scf x n))) x))
2556 ((math-infinitep x)
2557 x)
2558 (t
2559 (calc-record-why 'realp x)
2560 (list 'calcFunc-scf x n)))
2561 (if (math-messy-integerp n)
2562 (if (< (nth 2 n) 10)
2563 (calcFunc-scf x (math-trunc n))
2564 (math-overflow n))
2565 (if (math-integerp n)
2566 (math-overflow n)
2567 (calc-record-why 'integerp n)
898ea5c0 2568 (list 'calcFunc-scf x n)))))
136211a9
EZ
2569
2570
2571(defun calcFunc-incr (x &optional step relative-to)
2572 (or step (setq step 1))
2573 (cond ((not (Math-integerp step))
2574 (math-reject-arg step 'integerp))
2575 ((Math-integerp x)
2576 (math-add x step))
2577 ((eq (car x) 'float)
2578 (if (and (math-zerop x)
2579 (eq (car-safe relative-to) 'float))
2580 (math-mul step
2581 (calcFunc-scf relative-to (- 1 calc-internal-prec)))
2582 (math-add-float x (math-make-float
2583 step
2584 (+ (nth 2 x)
2585 (- (math-numdigs (nth 1 x))
2586 calc-internal-prec))))))
2587 ((eq (car x) 'date)
2588 (if (Math-integerp (nth 1 x))
2589 (math-add x step)
2590 (math-add x (list 'hms 0 0 step))))
2591 (t
898ea5c0 2592 (math-reject-arg x 'realp))))
136211a9 2593
898ea5c0
CW
2594(defsubst calcFunc-decr (x &optional step relative-to)
2595 (calcFunc-incr x (math-neg (or step 1)) relative-to))
136211a9
EZ
2596
2597(defun calcFunc-percent (x)
2598 (if (math-objectp x)
2599 (let ((calc-prefer-frac nil))
2600 (math-div x 100))
898ea5c0 2601 (list 'calcFunc-percent x)))
136211a9
EZ
2602
2603(defun calcFunc-relch (x y)
2604 (if (and (math-objectp x) (math-objectp y))
2605 (math-div (math-sub y x) x)
898ea5c0 2606 (list 'calcFunc-relch x y)))
136211a9
EZ
2607
2608;;; Compute the absolute value squared of A. [F N] [Public]
2609(defun calcFunc-abssqr (a)
2610 (cond ((Math-realp a)
2611 (math-mul a a))
2612 ((eq (car a) 'cplx)
2613 (math-add (math-sqr (nth 1 a))
2614 (math-sqr (nth 2 a))))
2615 ((eq (car a) 'polar)
2616 (math-sqr (nth 1 a)))
2617 ((and (memq (car a) '(sdev intv)) (math-constp a))
2618 (math-sqr (math-abs a)))
2619 ((eq (car a) 'vec)
2620 (math-reduce-vec 'math-add (math-map-vec 'calcFunc-abssqr a)))
2621 ((math-known-realp a)
2622 (math-pow a 2))
2623 ((let ((inf (math-infinitep a)))
2624 (and inf
2625 (math-mul (calcFunc-abssqr (math-infinite-dir a inf)) inf))))
2626 (t (calc-record-why 'numvecp a)
898ea5c0 2627 (list 'calcFunc-abssqr a))))
136211a9 2628
898ea5c0
CW
2629(defsubst math-sqr (a)
2630 (math-mul a a))
136211a9
EZ
2631
2632;;;; Number theory.
2633
2634(defun calcFunc-idiv (a b) ; [I I I] [Public]
2635 (cond ((and (Math-natnump a) (Math-natnump b) (not (eq b 0)))
2636 (math-quotient a b))
2637 ((Math-realp a)
2638 (if (Math-realp b)
2639 (let ((calc-prefer-frac t))
2640 (math-floor (math-div a b)))
2641 (math-reject-arg b 'realp)))
2642 ((eq (car-safe a) 'hms)
2643 (if (eq (car-safe b) 'hms)
2644 (let ((calc-prefer-frac t))
2645 (math-floor (math-div a b)))
2646 (math-reject-arg b 'hmsp)))
2647 ((and (or (eq (car-safe a) 'intv) (Math-realp a))
2648 (or (eq (car-safe b) 'intv) (Math-realp b)))
2649 (math-floor (math-div a b)))
2650 ((or (math-infinitep a)
2651 (math-infinitep b))
2652 (math-div a b))
898ea5c0 2653 (t (math-reject-arg a 'anglep))))
136211a9
EZ
2654
2655
2656;;; Combine two terms being added, if possible.
2657(defun math-combine-sum (a b nega negb scalar-okay)
2658 (if (and scalar-okay (Math-objvecp a) (Math-objvecp b))
2659 (math-add-or-sub a b nega negb)
2660 (let ((amult 1) (bmult 1))
2661 (and (consp a)
2662 (cond ((and (eq (car a) '*)
2663 (Math-objectp (nth 1 a)))
2664 (setq amult (nth 1 a)
2665 a (nth 2 a)))
2666 ((and (eq (car a) '/)
2667 (Math-objectp (nth 2 a)))
2668 (setq amult (if (Math-integerp (nth 2 a))
2669 (list 'frac 1 (nth 2 a))
2670 (math-div 1 (nth 2 a)))
2671 a (nth 1 a)))
2672 ((eq (car a) 'neg)
2673 (setq amult -1
2674 a (nth 1 a)))))
2675 (and (consp b)
2676 (cond ((and (eq (car b) '*)
2677 (Math-objectp (nth 1 b)))
2678 (setq bmult (nth 1 b)
2679 b (nth 2 b)))
2680 ((and (eq (car b) '/)
2681 (Math-objectp (nth 2 b)))
2682 (setq bmult (if (Math-integerp (nth 2 b))
2683 (list 'frac 1 (nth 2 b))
2684 (math-div 1 (nth 2 b)))
2685 b (nth 1 b)))
2686 ((eq (car b) 'neg)
2687 (setq bmult -1
2688 b (nth 1 b)))))
2689 (and (if math-simplifying
2690 (Math-equal a b)
2691 (equal a b))
2692 (progn
2693 (if nega (setq amult (math-neg amult)))
2694 (if negb (setq bmult (math-neg bmult)))
2695 (setq amult (math-add amult bmult))
898ea5c0 2696 (math-mul amult a))))))
136211a9
EZ
2697
2698(defun math-add-or-sub (a b aneg bneg)
2699 (if aneg (setq a (math-neg a)))
2700 (if bneg (setq b (math-neg b)))
2701 (if (or (Math-vectorp a) (Math-vectorp b))
2702 (math-normalize (list '+ a b))
898ea5c0 2703 (math-add a b)))
136211a9 2704
3132f345
CW
2705(defvar math-combine-prod-e '(var e var-e))
2706
136211a9 2707;;; The following is expanded out four ways for speed.
67549a85
JB
2708
2709;; math-unit-prefixes is defined in calc-units.el,
2710;; but used here.
2711(defvar math-unit-prefixes)
2712
136211a9
EZ
2713(defun math-combine-prod (a b inva invb scalar-okay)
2714 (cond
2715 ((or (and inva (Math-zerop a))
2716 (and invb (Math-zerop b)))
2717 nil)
2718 ((and scalar-okay (Math-objvecp a) (Math-objvecp b))
2719 (setq a (math-mul-or-div a b inva invb))
2720 (and (Math-objvecp a)
2721 a))
2722 ((and (eq (car-safe a) '^)
2723 inva
2724 (math-looks-negp (nth 2 a)))
2725 (math-mul (math-pow (nth 1 a) (math-neg (nth 2 a))) b))
2726 ((and (eq (car-safe b) '^)
2727 invb
2728 (math-looks-negp (nth 2 b)))
2729 (math-mul a (math-pow (nth 1 b) (math-neg (nth 2 b)))))
7db3d0d5
JB
2730 ((and math-simplifying
2731 (math-combine-prod-trig a b)))
136211a9
EZ
2732 (t (let ((apow 1) (bpow 1))
2733 (and (consp a)
2734 (cond ((and (eq (car a) '^)
2735 (or math-simplifying
2736 (Math-numberp (nth 2 a))))
2737 (setq apow (nth 2 a)
2738 a (nth 1 a)))
2739 ((eq (car a) 'calcFunc-sqrt)
2740 (setq apow '(frac 1 2)
2741 a (nth 1 a)))
2742 ((and (eq (car a) 'calcFunc-exp)
2743 (or math-simplifying
2744 (Math-numberp (nth 1 a))))
2745 (setq apow (nth 1 a)
2746 a math-combine-prod-e))))
2747 (and (consp a) (eq (car a) 'frac)
2748 (Math-lessp (nth 1 a) (nth 2 a))
2749 (setq a (math-div 1 a) apow (math-neg apow)))
2750 (and (consp b)
2751 (cond ((and (eq (car b) '^)
2752 (or math-simplifying
2753 (Math-numberp (nth 2 b))))
2754 (setq bpow (nth 2 b)
2755 b (nth 1 b)))
2756 ((eq (car b) 'calcFunc-sqrt)
2757 (setq bpow '(frac 1 2)
2758 b (nth 1 b)))
2759 ((and (eq (car b) 'calcFunc-exp)
2760 (or math-simplifying
2761 (Math-numberp (nth 1 b))))
2762 (setq bpow (nth 1 b)
2763 b math-combine-prod-e))))
2764 (and (consp b) (eq (car b) 'frac)
2765 (Math-lessp (nth 1 b) (nth 2 b))
2766 (setq b (math-div 1 b) bpow (math-neg bpow)))
2767 (if inva (setq apow (math-neg apow)))
2768 (if invb (setq bpow (math-neg bpow)))
2769 (or (and (if math-simplifying
2770 (math-commutative-equal a b)
2771 (equal a b))
2772 (let ((sumpow (math-add apow bpow)))
2773 (and (or (not (Math-integerp a))
2774 (Math-zerop sumpow)
2775 (eq (eq (car-safe apow) 'frac)
2776 (eq (car-safe bpow) 'frac)))
2777 (progn
2778 (and (math-looks-negp sumpow)
2779 (Math-ratp a) (Math-posp a)
2780 (setq a (math-div 1 a)
2781 sumpow (math-neg sumpow)))
2782 (cond ((equal sumpow '(frac 1 2))
2783 (list 'calcFunc-sqrt a))
2784 ((equal sumpow '(frac -1 2))
2785 (math-div 1 (list 'calcFunc-sqrt a)))
2786 ((and (eq a math-combine-prod-e)
2787 (eq a b))
2788 (list 'calcFunc-exp sumpow))
2789 (t
2790 (condition-case err
2791 (math-pow a sumpow)
2792 (inexact-result (list '^ a sumpow)))))))))
2793 (and math-simplifying-units
2794 math-combining-units
2795 (let* ((ua (math-check-unit-name a))
2796 ub)
2797 (and ua
2798 (eq ua (setq ub (math-check-unit-name b)))
2799 (progn
2800 (setq ua (if (eq (nth 1 a) (car ua))
2801 1
2802 (nth 1 (assq (aref (symbol-name (nth 1 a))
2803 0)
2804 math-unit-prefixes)))
2805 ub (if (eq (nth 1 b) (car ub))
2806 1
2807 (nth 1 (assq (aref (symbol-name (nth 1 b))
2808 0)
2809 math-unit-prefixes))))
2810 (if (Math-lessp ua ub)
2811 (let (temp)
2812 (setq temp a a b b temp
2813 temp ua ua ub ub temp
2814 temp apow apow bpow bpow temp)))
2815 (math-mul (math-pow (math-div ua ub) apow)
2816 (math-pow b (math-add apow bpow)))))))
2817 (and (equal apow bpow)
2818 (Math-natnump a) (Math-natnump b)
2819 (cond ((equal apow '(frac 1 2))
2820 (list 'calcFunc-sqrt (math-mul a b)))
2821 ((equal apow '(frac -1 2))
2822 (math-div 1 (list 'calcFunc-sqrt (math-mul a b))))
2823 (t
2824 (setq a (math-mul a b))
2825 (condition-case err
2826 (math-pow a apow)
898ea5c0 2827 (inexact-result (list '^ a apow)))))))))))
136211a9 2828
7db3d0d5
JB
2829(defun math-combine-prod-trig (a b)
2830 (cond
2831 ((and (eq (car-safe a) 'calcFunc-sin)
2832 (eq (car-safe b) 'calcFunc-csc)
2833 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2834 1)
2835 ((and (eq (car-safe a) 'calcFunc-sin)
2836 (eq (car-safe b) 'calcFunc-sec)
2837 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2838 (cons 'calcFunc-tan (cdr a)))
2839 ((and (eq (car-safe a) 'calcFunc-sin)
2840 (eq (car-safe b) 'calcFunc-cot)
2841 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2842 (cons 'calcFunc-cos (cdr a)))
2843 ((and (eq (car-safe a) 'calcFunc-cos)
2844 (eq (car-safe b) 'calcFunc-sec)
2845 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2846 1)
2847 ((and (eq (car-safe a) 'calcFunc-cos)
2848 (eq (car-safe b) 'calcFunc-csc)
2849 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2850 (cons 'calcFunc-cot (cdr a)))
2851 ((and (eq (car-safe a) 'calcFunc-cos)
2852 (eq (car-safe b) 'calcFunc-tan)
2853 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2854 (cons 'calcFunc-sin (cdr a)))
2855 ((and (eq (car-safe a) 'calcFunc-tan)
2856 (eq (car-safe b) 'calcFunc-cot)
2857 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2858 1)
2859 ((and (eq (car-safe a) 'calcFunc-tan)
2860 (eq (car-safe b) 'calcFunc-csc)
2861 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2862 (cons 'calcFunc-sec (cdr a)))
2863 ((and (eq (car-safe a) 'calcFunc-sec)
2864 (eq (car-safe b) 'calcFunc-cot)
2865 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2866 (cons 'calcFunc-csc (cdr a)))
2867 ((and (eq (car-safe a) 'calcFunc-sinh)
2868 (eq (car-safe b) 'calcFunc-csch)
2869 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2870 1)
2871 ((and (eq (car-safe a) 'calcFunc-sinh)
2872 (eq (car-safe b) 'calcFunc-sech)
2873 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2874 (cons 'calcFunc-tanh (cdr a)))
2875 ((and (eq (car-safe a) 'calcFunc-sinh)
2876 (eq (car-safe b) 'calcFunc-coth)
2877 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2878 (cons 'calcFunc-cosh (cdr a)))
2879 ((and (eq (car-safe a) 'calcFunc-cosh)
2880 (eq (car-safe b) 'calcFunc-sech)
2881 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2882 1)
2883 ((and (eq (car-safe a) 'calcFunc-cosh)
2884 (eq (car-safe b) 'calcFunc-csch)
2885 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2886 (cons 'calcFunc-coth (cdr a)))
2887 ((and (eq (car-safe a) 'calcFunc-cosh)
2888 (eq (car-safe b) 'calcFunc-tanh)
2889 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2890 (cons 'calcFunc-sinh (cdr a)))
2891 ((and (eq (car-safe a) 'calcFunc-tanh)
2892 (eq (car-safe b) 'calcFunc-coth)
2893 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2894 1)
2895 ((and (eq (car-safe a) 'calcFunc-tanh)
2896 (eq (car-safe b) 'calcFunc-csch)
2897 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2898 (cons 'calcFunc-sech (cdr a)))
2899 ((and (eq (car-safe a) 'calcFunc-sech)
2900 (eq (car-safe b) 'calcFunc-coth)
2901 (= 0 (math-simplify (math-sub (cdr a) (cdr b)))))
2902 (cons 'calcFunc-csch (cdr a)))
2903 (t
2904 nil)))
2905
136211a9
EZ
2906(defun math-mul-or-div (a b ainv binv)
2907 (if (or (Math-vectorp a) (Math-vectorp b))
2908 (math-normalize
2909 (if ainv
2910 (if binv
2911 (list '/ (math-div 1 a) b)
2912 (list '/ b a))
2913 (if binv
2914 (list '/ a b)
2915 (list '* a b))))
2916 (if ainv
2917 (if binv
2918 (math-div (math-div 1 a) b)
2919 (math-div b a))
2920 (if binv
2921 (math-div a b)
898ea5c0 2922 (math-mul a b)))))
136211a9 2923
67549a85
JB
2924;; The variable math-com-bterms is local to math-commutative-equal,
2925;; but is used by math-commutative collect, which is called by
2926;; math-commutative-equal.
2927(defvar math-com-bterms)
2928
136211a9
EZ
2929(defun math-commutative-equal (a b)
2930 (if (memq (car-safe a) '(+ -))
2931 (and (memq (car-safe b) '(+ -))
67549a85 2932 (let ((math-com-bterms nil) aterms p)
136211a9 2933 (math-commutative-collect b nil)
67549a85 2934 (setq aterms math-com-bterms math-com-bterms nil)
136211a9 2935 (math-commutative-collect a nil)
67549a85 2936 (and (= (length aterms) (length math-com-bterms))
136211a9
EZ
2937 (progn
2938 (while (and aterms
2939 (progn
67549a85 2940 (setq p math-com-bterms)
136211a9
EZ
2941 (while (and p (not (equal (car aterms)
2942 (car p))))
2943 (setq p (cdr p)))
2944 p))
67549a85 2945 (setq math-com-bterms (delq (car p) math-com-bterms)
136211a9
EZ
2946 aterms (cdr aterms)))
2947 (not aterms)))))
898ea5c0 2948 (equal a b)))
136211a9
EZ
2949
2950(defun math-commutative-collect (b neg)
2951 (if (eq (car-safe b) '+)
2952 (progn
2953 (math-commutative-collect (nth 1 b) neg)
2954 (math-commutative-collect (nth 2 b) neg))
2955 (if (eq (car-safe b) '-)
2956 (progn
2957 (math-commutative-collect (nth 1 b) neg)
2958 (math-commutative-collect (nth 2 b) (not neg)))
67549a85 2959 (setq math-com-bterms (cons (if neg (math-neg b) b) math-com-bterms)))))
136211a9 2960
5e30155b
JB
2961(provide 'calc-arith)
2962
ab5796a9 2963;;; arch-tag: 6c396b5b-14c6-40ed-bb2a-7cc2e8111465
898ea5c0 2964;;; calc-arith.el ends here