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