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