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