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