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