1 ;;; calc-math.el --- mathematical functions for Calc
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc.
5 ;; Author: David Gillespie <daveg@synaptics.com>
6 ;; Maintainers: D. Goel <deego@gnufans.org>
7 ;; Colin Walters <walters@debian.org>
9 ;; This file is part of GNU Emacs.
11 ;; GNU Emacs is distributed in the hope that it will be useful,
12 ;; but WITHOUT ANY WARRANTY. No author or distributor
13 ;; accepts responsibility to anyone for the consequences of using it
14 ;; or for whether it serves any particular purpose or works at all,
15 ;; unless he says so in writing. Refer to the GNU Emacs General Public
16 ;; License for full details.
18 ;; Everyone is granted permission to copy, modify and redistribute
19 ;; GNU Emacs, but only under the conditions described in the
20 ;; GNU Emacs General Public License. A copy of this license is
21 ;; supposed to have been given to you along with GNU Emacs so you
22 ;; can know your rights and responsibilities. It should be in a
23 ;; file named COPYING. Among other things, the copyright notice
24 ;; and this notice must be preserved on all copies.
30 ;; This file is autoloaded from calc-ext.el.
35 (defun calc-Need-calc-math () nil
)
38 (defun calc-sqrt (arg)
42 (calc-unary-op "^2" 'calcFunc-sqr arg
)
43 (calc-unary-op "sqrt" 'calcFunc-sqrt arg
))))
45 (defun calc-isqrt (arg)
49 (calc-unary-op "^2" 'calcFunc-sqr arg
)
50 (calc-unary-op "isqt" 'calcFunc-isqrt arg
))))
53 (defun calc-hypot (arg)
56 (calc-binary-op "hypt" 'calcFunc-hypot arg
)))
63 (defun calc-log10 (arg)
65 (calc-hyperbolic-func)
72 (calc-binary-op "alog" 'calcFunc-alog arg
)
73 (calc-binary-op "log" 'calcFunc-log arg
))))
75 (defun calc-ilog (arg)
79 (calc-binary-op "alog" 'calcFunc-alog arg
)
80 (calc-binary-op "ilog" 'calcFunc-ilog arg
))))
82 (defun calc-lnp1 (arg)
90 (if (calc-is-hyperbolic)
92 (calc-unary-op "lg10" 'calcFunc-log10 arg
)
93 (calc-unary-op "10^" 'calcFunc-exp10 arg
))
95 (calc-unary-op "ln" 'calcFunc-ln arg
)
96 (calc-unary-op "exp" 'calcFunc-exp arg
)))))
98 (defun calc-expm1 (arg)
101 (if (calc-is-inverse)
102 (calc-unary-op "ln+1" 'calcFunc-lnp1 arg
)
103 (calc-unary-op "ex-1" 'calcFunc-expm1 arg
))))
108 (if (calc-is-inverse)
109 (if (calc-is-hyperbolic)
110 (if calc-symbolic-mode
111 (calc-pop-push-record 0 "phi" '(var phi var-phi
))
112 (calc-pop-push-record 0 "phi" (math-phi)))
113 (if calc-symbolic-mode
114 (calc-pop-push-record 0 "gmma" '(var gamma var-gamma
))
115 (calc-pop-push-record 0 "gmma" (math-gamma-const))))
116 (if (calc-is-hyperbolic)
117 (if calc-symbolic-mode
118 (calc-pop-push-record 0 "e" '(var e var-e
))
119 (calc-pop-push-record 0 "e" (math-e)))
120 (if calc-symbolic-mode
121 (calc-pop-push-record 0 "pi" '(var pi var-pi
))
122 (calc-pop-push-record 0 "pi" (math-pi)))))))
124 (defun calc-sin (arg)
127 (if (calc-is-hyperbolic)
128 (if (calc-is-inverse)
129 (calc-unary-op "asnh" 'calcFunc-arcsinh arg
)
130 (calc-unary-op "sinh" 'calcFunc-sinh arg
))
131 (if (calc-is-inverse)
132 (calc-unary-op "asin" 'calcFunc-arcsin arg
)
133 (calc-unary-op "sin" 'calcFunc-sin arg
)))))
135 (defun calc-arcsin (arg)
140 (defun calc-sinh (arg)
142 (calc-hyperbolic-func)
145 (defun calc-arcsinh (arg)
148 (calc-hyperbolic-func)
151 (defun calc-cos (arg)
154 (if (calc-is-hyperbolic)
155 (if (calc-is-inverse)
156 (calc-unary-op "acsh" 'calcFunc-arccosh arg
)
157 (calc-unary-op "cosh" 'calcFunc-cosh arg
))
158 (if (calc-is-inverse)
159 (calc-unary-op "acos" 'calcFunc-arccos arg
)
160 (calc-unary-op "cos" 'calcFunc-cos arg
)))))
162 (defun calc-arccos (arg)
167 (defun calc-cosh (arg)
169 (calc-hyperbolic-func)
172 (defun calc-arccosh (arg)
175 (calc-hyperbolic-func)
178 (defun calc-sincos ()
181 (if (calc-is-inverse)
182 (calc-enter-result 1 "asnc" (list 'calcFunc-arcsincos
(calc-top-n 1)))
183 (calc-enter-result 1 "sncs" (list 'calcFunc-sincos
(calc-top-n 1))))))
185 (defun calc-tan (arg)
188 (if (calc-is-hyperbolic)
189 (if (calc-is-inverse)
190 (calc-unary-op "atnh" 'calcFunc-arctanh arg
)
191 (calc-unary-op "tanh" 'calcFunc-tanh arg
))
192 (if (calc-is-inverse)
193 (calc-unary-op "atan" 'calcFunc-arctan arg
)
194 (calc-unary-op "tan" 'calcFunc-tan arg
)))))
196 (defun calc-arctan (arg)
201 (defun calc-tanh (arg)
203 (calc-hyperbolic-func)
206 (defun calc-arctanh (arg)
209 (calc-hyperbolic-func)
212 (defun calc-arctan2 ()
215 (calc-enter-result 2 "atn2" (cons 'calcFunc-arctan2
(calc-top-list-n 2)))))
217 (defun calc-conj (arg)
220 (calc-unary-op "conj" 'calcFunc-conj arg
)))
222 (defun calc-imaginary ()
225 (calc-pop-push-record 1 "i*" (math-imaginary (calc-top-n 1)))))
229 (defun calc-to-degrees (arg)
232 (calc-unary-op ">deg" 'calcFunc-deg arg
)))
234 (defun calc-to-radians (arg)
237 (calc-unary-op ">rad" 'calcFunc-rad arg
)))
240 (defun calc-degrees-mode (arg)
244 (calc-change-mode 'calc-angle-mode
'deg
)
245 (message "Angles measured in degrees")))
246 ((= arg
2) (calc-radians-mode))
247 ((= arg
3) (calc-hms-mode))
248 (t (error "Prefix argument out of range"))))
250 (defun calc-radians-mode ()
253 (calc-change-mode 'calc-angle-mode
'rad
)
254 (message "Angles measured in radians")))
257 ;;; Compute the integer square-root floor(sqrt(A)). A > 0. [I I] [Public]
258 ;;; This method takes advantage of the fact that Newton's method starting
259 ;;; with an overestimate always works, even using truncating integer division!
260 (defun math-isqrt (a)
261 (cond ((Math-zerop a
) a
)
262 ((not (math-natnump a
))
263 (math-reject-arg a
'natnump
))
265 (math-isqrt-small a
))
267 (math-normalize (cons 'bigpos
(cdr (math-isqrt-bignum (cdr a
))))))))
269 (defun calcFunc-isqrt (a)
271 (math-isqrt (math-floor a
))
272 (math-floor (math-sqrt a
))))
275 ;;; This returns (flag . result) where the flag is t if A is a perfect square.
276 (defun math-isqrt-bignum (a) ; [P.l L]
277 (let ((len (length a
)))
279 (let* ((top (nthcdr (- len
2) a
)))
280 (math-isqrt-bignum-iter
284 (1+ (math-isqrt-small
285 (+ (* (nth 1 top
) 1000) (car top
)))))
287 (let* ((top (nth (1- len
) a
)))
288 (math-isqrt-bignum-iter
291 (list (1+ (math-isqrt-small top
)))
294 (defun math-isqrt-bignum-iter (a guess
) ; [l L l]
295 (math-working "isqrt" (cons 'bigpos guess
))
296 (let* ((q (math-div-bignum a guess
))
297 (s (math-add-bignum (car q
) guess
))
298 (g2 (math-div2-bignum s
))
299 (comp (math-compare-bignum g2 guess
)))
301 (math-isqrt-bignum-iter a g2
)
302 (cons (and (= comp
0)
303 (math-zerop-bignum (cdr q
))
307 (defun math-zerop-bignum (a)
310 (while (eq (car (setq a
(cdr a
))) 0))
313 (defun math-scale-bignum-3 (a n
) ; [L L S]
319 (defun math-isqrt-small (a) ; A > 0. [S S]
320 (let ((g (cond ((>= a
10000) 1000)
324 (while (< (setq g2
(/ (+ g
(/ a g
)) 2)) g
)
331 ;;; Compute the square root of a number.
332 ;;; [T N] if possible, else [F N] if possible, else [C N]. [Public]
335 (and (Math-zerop a
) a
)
336 (and (math-known-nonposp a
)
337 (math-imaginary (math-sqrt (math-neg a
))))
339 (let ((sqrt (math-isqrt-small a
)))
340 (if (= (* sqrt sqrt
) a
)
342 (if calc-symbolic-mode
343 (list 'calcFunc-sqrt a
)
344 (math-sqrt-float (math-float a
) (math-float sqrt
))))))
345 (and (eq (car-safe a
) 'bigpos
)
346 (let* ((res (math-isqrt-bignum (cdr a
)))
347 (sqrt (math-normalize (cons 'bigpos
(cdr res
)))))
350 (if calc-symbolic-mode
351 (list 'calcFunc-sqrt a
)
352 (math-sqrt-float (math-float a
) (math-float sqrt
))))))
353 (and (eq (car-safe a
) 'frac
)
354 (let* ((num-res (math-isqrt-bignum (cdr (Math-bignum-test (nth 1 a
)))))
355 (num-sqrt (math-normalize (cons 'bigpos
(cdr num-res
))))
356 (den-res (math-isqrt-bignum (cdr (Math-bignum-test (nth 2 a
)))))
357 (den-sqrt (math-normalize (cons 'bigpos
(cdr den-res
)))))
358 (if (and (car num-res
) (car den-res
))
359 (list 'frac num-sqrt den-sqrt
)
360 (if calc-symbolic-mode
361 (if (or (car num-res
) (car den-res
))
362 (math-div (if (car num-res
)
363 num-sqrt
(list 'calcFunc-sqrt
(nth 1 a
)))
365 den-sqrt
(list 'calcFunc-sqrt
(nth 2 a
))))
366 (list 'calcFunc-sqrt a
))
367 (math-sqrt-float (math-float a
)
368 (math-div (math-float num-sqrt
) den-sqrt
))))))
369 (and (eq (car-safe a
) 'float
)
370 (if calc-symbolic-mode
371 (if (= (%
(nth 2 a
) 2) 0)
372 (let ((res (math-isqrt-bignum
373 (cdr (Math-bignum-test (nth 1 a
))))))
375 (math-make-float (math-normalize
376 (cons 'bigpos
(cdr res
)))
378 (signal 'inexact-result nil
)))
379 (signal 'inexact-result nil
))
380 (math-sqrt-float a
)))
381 (and (eq (car-safe a
) 'cplx
)
382 (math-with-extra-prec 2
383 (let* ((d (math-abs a
))
384 (imag (math-sqrt (math-mul (math-sub d
(nth 1 a
))
387 (math-sqrt (math-mul (math-add d
(nth 1 a
)) '(float 5 -
1)))
388 (if (math-negp (nth 2 a
)) (math-neg imag
) imag
)))))
389 (and (eq (car-safe a
) 'polar
)
391 (math-sqrt (nth 1 a
))
392 (math-mul (nth 2 a
) '(float 5 -
1))))
393 (and (eq (car-safe a
) 'sdev
)
394 (let ((sqrt (math-sqrt (nth 1 a
))))
396 (math-div (nth 2 a
) (math-mul sqrt
2)))))
397 (and (eq (car-safe a
) 'intv
)
398 (not (math-negp (nth 2 a
)))
399 (math-make-intv (nth 1 a
) (math-sqrt (nth 2 a
)) (math-sqrt (nth 3 a
))))
400 (and (eq (car-safe a
) '*)
401 (or (math-known-nonnegp (nth 1 a
))
402 (math-known-nonnegp (nth 2 a
)))
403 (math-mul (math-sqrt (nth 1 a
)) (math-sqrt (nth 2 a
))))
404 (and (eq (car-safe a
) '/)
405 (or (and (math-known-nonnegp (nth 2 a
))
406 (math-div (math-sqrt (nth 1 a
)) (math-sqrt (nth 2 a
))))
407 (and (math-known-nonnegp (nth 1 a
))
408 (not (math-equal-int (nth 1 a
) 1))
409 (math-mul (math-sqrt (nth 1 a
))
410 (math-sqrt (math-div 1 (nth 2 a
)))))))
411 (and (eq (car-safe a
) '^
)
412 (math-known-evenp (nth 2 a
))
413 (math-known-realp (nth 1 a
))
414 (math-abs (math-pow (nth 1 a
) (math-div (nth 2 a
) 2))))
415 (let ((inf (math-infinitep a
)))
417 (math-mul (math-sqrt (math-infinite-dir a inf
)) inf
)))
419 (calc-record-why 'numberp a
)
420 (list 'calcFunc-sqrt a
))))
421 (defalias 'calcFunc-sqrt
'math-sqrt
)
423 (defun math-infinite-dir (a &optional inf
)
424 (or inf
(setq inf
(math-infinitep a
)))
425 (math-normalize (math-expr-subst a inf
1)))
427 (defun math-sqrt-float (a &optional guess
) ; [F F F]
428 (if calc-symbolic-mode
429 (signal 'inexact-result nil
)
430 (math-with-extra-prec 1 (math-sqrt-raw a guess
))))
432 (defun math-sqrt-raw (a &optional guess
) ; [F F F]
433 (if (not (Math-posp a
))
436 (let ((ldiff (- (math-numdigs (nth 1 a
)) 6)))
437 (or (= (%
(+ (nth 2 a
) ldiff
) 2) 0) (setq ldiff
(1+ ldiff
)))
438 (setq guess
(math-make-float (math-isqrt-small
439 (math-scale-int (nth 1 a
) (- ldiff
)))
440 (/ (+ (nth 2 a
) ldiff
) 2)))))
441 (math-sqrt-float-iter a guess
)))
443 (defun math-sqrt-float-iter (a guess
) ; [F F F]
444 (math-working "sqrt" guess
)
445 (let ((g2 (math-mul-float (math-add-float guess
(math-div-float a guess
))
447 (if (math-nearly-equal-float g2 guess
)
449 (math-sqrt-float-iter a g2
))))
451 ;;; True if A and B differ only in the last digit of precision. [P F F]
452 (defun math-nearly-equal-float (a b
)
453 (let ((ediff (- (nth 2 a
) (nth 2 b
))))
454 (cond ((= ediff
0) ;; Expanded out for speed
455 (setq ediff
(math-add (Math-integer-neg (nth 1 a
)) (nth 1 b
)))
457 (and (not (consp ediff
))
460 (= (math-numdigs (nth 1 a
)) calc-internal-prec
))))
462 (setq ediff
(math-add (Math-integer-neg (nth 1 b
))
463 (math-scale-int (nth 1 a
) 1)))
464 (and (not (consp ediff
))
467 (= (math-numdigs (nth 1 b
)) calc-internal-prec
)))
469 (setq ediff
(math-add (Math-integer-neg (nth 1 a
))
470 (math-scale-int (nth 1 b
) 1)))
471 (and (not (consp ediff
))
474 (= (math-numdigs (nth 1 a
)) calc-internal-prec
))))))
476 (defun math-nearly-equal (a b
) ; [P N N] [Public]
477 (setq a
(math-float a
))
478 (setq b
(math-float b
))
479 (if (eq (car a
) 'polar
) (setq a
(math-complex a
)))
480 (if (eq (car b
) 'polar
) (setq b
(math-complex b
)))
481 (if (eq (car a
) 'cplx
)
482 (if (eq (car b
) 'cplx
)
483 (and (or (math-nearly-equal-float (nth 1 a
) (nth 1 b
))
484 (and (math-nearly-zerop-float (nth 1 a
) (nth 2 a
))
485 (math-nearly-zerop-float (nth 1 b
) (nth 2 b
))))
486 (or (math-nearly-equal-float (nth 2 a
) (nth 2 b
))
487 (and (math-nearly-zerop-float (nth 2 a
) (nth 1 a
))
488 (math-nearly-zerop-float (nth 2 b
) (nth 1 b
)))))
489 (and (math-nearly-equal-float (nth 1 a
) b
)
490 (math-nearly-zerop-float (nth 2 a
) b
)))
491 (if (eq (car b
) 'cplx
)
492 (and (math-nearly-equal-float a
(nth 1 b
))
493 (math-nearly-zerop-float a
(nth 2 b
)))
494 (math-nearly-equal-float a b
))))
496 ;;; True if A is nearly zero compared to B. [P F F]
497 (defun math-nearly-zerop-float (a b
)
499 (<= (+ (math-numdigs (nth 1 a
)) (nth 2 a
))
500 (1+ (- (+ (math-numdigs (nth 1 b
)) (nth 2 b
)) calc-internal-prec
)))))
502 (defun math-nearly-zerop (a b
) ; [P N R] [Public]
503 (setq a
(math-float a
))
504 (setq b
(math-float b
))
505 (if (eq (car a
) 'cplx
)
506 (and (math-nearly-zerop-float (nth 1 a
) b
)
507 (math-nearly-zerop-float (nth 2 a
) b
))
508 (if (eq (car a
) 'polar
)
509 (math-nearly-zerop-float (nth 1 a
) b
)
510 (math-nearly-zerop-float a b
))))
512 ;;; This implementation could be improved, accuracy-wise.
513 (defun math-hypot (a b
)
514 (cond ((Math-zerop a
) (math-abs b
))
515 ((Math-zerop b
) (math-abs a
))
516 ((not (Math-scalarp a
))
517 (if (math-infinitep a
)
518 (if (math-infinitep b
)
523 (calc-record-why 'scalarp a
)
524 (list 'calcFunc-hypot a b
)))
525 ((not (Math-scalarp b
))
526 (if (math-infinitep b
)
528 (calc-record-why 'scalarp b
)
529 (list 'calcFunc-hypot a b
)))
530 ((and (Math-numberp a
) (Math-numberp b
))
531 (math-with-extra-prec 1
532 (math-sqrt (math-add (calcFunc-abssqr a
) (calcFunc-abssqr b
)))))
533 ((eq (car-safe a
) 'hms
)
534 (if (eq (car-safe b
) 'hms
) ; this helps sdev's of hms forms
535 (math-to-hms (math-hypot (math-from-hms a
'deg
)
536 (math-from-hms b
'deg
)))
537 (math-to-hms (math-hypot (math-from-hms a
'deg
) b
))))
538 ((eq (car-safe b
) 'hms
)
539 (math-to-hms (math-hypot a
(math-from-hms b
'deg
))))
541 (defalias 'calcFunc-hypot
'math-hypot
)
543 (defun calcFunc-sqr (x)
548 (defun math-nth-root (a n
)
549 (cond ((= n
2) (math-sqrt a
))
553 (let ((root (math-nth-root-integer a n
)))
556 (and (not calc-symbolic-mode
)
557 (math-nth-root-float (math-float a
) n
558 (math-float (cdr root
)))))))
559 ((eq (car-safe a
) 'frac
)
560 (let* ((num-root (math-nth-root-integer (nth 1 a
) n
))
561 (den-root (math-nth-root-integer (nth 2 a
) n
)))
562 (if (and (car num-root
) (car den-root
))
563 (list 'frac
(cdr num-root
) (cdr den-root
))
564 (and (not calc-symbolic-mode
)
567 (math-div-float (math-float (cdr num-root
))
568 (math-float (cdr den-root
))))))))
569 ((eq (car-safe a
) 'float
)
570 (and (not calc-symbolic-mode
)
571 (math-nth-root-float a n
)))
572 ((eq (car-safe a
) 'polar
)
573 (let ((root (math-nth-root (nth 1 a
) n
)))
574 (and root
(list 'polar root
(math-div (nth 2 a
) n
)))))
577 (defun math-nth-root-float (a n
&optional guess
)
578 (math-inexact-result)
579 (math-with-extra-prec 1
580 (let ((nf (math-float n
))
581 (nfm1 (math-float (1- n
))))
582 (math-nth-root-float-iter a
(or guess
584 1 (/ (+ (math-numdigs (nth 1 a
))
589 (defun math-nth-root-float-iter (a guess
) ; uses "n", "nf", "nfm1"
590 (math-working "root" guess
)
591 (let ((g2 (math-div-float (math-add-float (math-mul nfm1 guess
)
593 a
(math-ipow guess
(1- n
))))
595 (if (math-nearly-equal-float g2 guess
)
597 (math-nth-root-float-iter a g2
))))
599 (defun math-nth-root-integer (a n
&optional guess
) ; [I I S]
600 (math-nth-root-int-iter a
(or guess
601 (math-scale-int 1 (/ (+ (math-numdigs a
)
605 (defun math-nth-root-int-iter (a guess
) ; uses "n"
606 (math-working "root" guess
)
607 (let* ((q (math-idivmod a
(math-ipow guess
(1- n
))))
608 (s (math-add (car q
) (math-mul (1- n
) guess
)))
609 (g2 (math-idivmod s n
)))
610 (if (Math-natnum-lessp (car g2
) guess
)
611 (math-nth-root-int-iter a
(car g2
))
612 (cons (and (equal (car g2
) guess
)
617 (defun calcFunc-nroot (x n
)
618 (calcFunc-pow x
(if (integerp n
)
625 ;;;; Transcendental functions.
627 ;;; All of these functions are defined on the complex plane.
628 ;;; (Branch cuts, etc. follow Steele's Common Lisp book.)
630 ;;; Most functions increase calc-internal-prec by 2 digits, then round
631 ;;; down afterward. "-raw" functions use the current precision, require
632 ;;; their arguments to be in float (or complex float) format, and always
633 ;;; work in radians (where applicable).
635 (defun math-to-radians (a) ; [N N]
636 (cond ((eq (car-safe a
) 'hms
)
637 (math-from-hms a
'rad
))
638 ((memq calc-angle-mode
'(deg hms
))
639 (math-mul a
(math-pi-over-180)))
642 (defun math-from-radians (a) ; [N N]
643 (cond ((eq calc-angle-mode
'deg
)
645 (math-div a
(math-pi-over-180))
646 (list 'calcFunc-deg a
)))
647 ((eq calc-angle-mode
'hms
)
648 (math-to-hms a
'rad
))
651 (defun math-to-radians-2 (a) ; [N N]
652 (cond ((eq (car-safe a
) 'hms
)
653 (math-from-hms a
'rad
))
654 ((memq calc-angle-mode
'(deg hms
))
655 (if calc-symbolic-mode
656 (math-div (math-mul a
'(var pi var-pi
)) 180)
657 (math-mul a
(math-pi-over-180))))
660 (defun math-from-radians-2 (a) ; [N N]
661 (cond ((memq calc-angle-mode
'(deg hms
))
662 (if calc-symbolic-mode
663 (math-div (math-mul 180 a
) '(var pi var-pi
))
664 (math-div a
(math-pi-over-180))))
669 ;;; Sine, cosine, and tangent.
671 (defun calcFunc-sin (x) ; [N N] [Public]
672 (cond ((and (integerp x
)
673 (if (eq calc-angle-mode
'deg
)
676 (aref [0 1 0 -
1] (math-mod (/ x
90) 4)))
678 (math-with-extra-prec 2
679 (math-sin-raw (math-to-radians (math-float x
)))))
682 (math-with-extra-prec 2
683 (let* ((xx (math-to-radians (math-float (nth 1 x
))))
684 (xs (math-to-radians (math-float (nth 2 x
))))
685 (sc (math-sin-cos-raw xx
)))
686 (math-make-sdev (car sc
) (math-mul xs
(cdr sc
)))))
687 (math-make-sdev (calcFunc-sin (nth 1 x
))
688 (math-mul (nth 2 x
) (calcFunc-cos (nth 1 x
))))))
689 ((and (eq (car x
) 'intv
) (math-intv-constp x
))
690 (calcFunc-cos (math-sub x
(math-quarter-circle nil
))))
691 ((equal x
'(var nan var-nan
))
693 (t (calc-record-why 'scalarp x
)
694 (list 'calcFunc-sin x
))))
696 (defun calcFunc-cos (x) ; [N N] [Public]
697 (cond ((and (integerp x
)
698 (if (eq calc-angle-mode
'deg
)
701 (aref [1 0 -
1 0] (math-mod (/ x
90) 4)))
703 (math-with-extra-prec 2
704 (math-cos-raw (math-to-radians (math-float x
)))))
707 (math-with-extra-prec 2
708 (let* ((xx (math-to-radians (math-float (nth 1 x
))))
709 (xs (math-to-radians (math-float (nth 2 x
))))
710 (sc (math-sin-cos-raw xx
)))
711 (math-make-sdev (cdr sc
) (math-mul xs
(car sc
)))))
712 (math-make-sdev (calcFunc-cos (nth 1 x
))
713 (math-mul (nth 2 x
) (calcFunc-sin (nth 1 x
))))))
714 ((and (eq (car x
) 'intv
) (math-intv-constp x
))
715 (math-with-extra-prec 2
716 (let* ((xx (math-to-radians (math-float x
)))
717 (na (math-floor (math-div (nth 2 xx
) (math-pi))))
718 (nb (math-floor (math-div (nth 3 xx
) (math-pi))))
719 (span (math-sub nb na
)))
720 (if (memq span
'(0 1))
721 (let ((int (math-sort-intv (nth 1 x
)
722 (math-cos-raw (nth 2 xx
))
723 (math-cos-raw (nth 3 xx
)))))
726 (math-make-intv (logior (nth 1 x
) 2)
729 (math-make-intv (logior (nth 1 x
) 1)
733 (list 'intv
3 -
1 1)))))
734 ((equal x
'(var nan var-nan
))
736 (t (calc-record-why 'scalarp x
)
737 (list 'calcFunc-cos x
))))
739 (defun calcFunc-sincos (x) ; [V N] [Public]
741 (math-with-extra-prec 2
742 (let ((sc (math-sin-cos-raw (math-to-radians (math-float x
)))))
743 (list 'vec
(cdr sc
) (car sc
)))) ; the vector [cos, sin]
744 (list 'vec
(calcFunc-sin x
) (calcFunc-cos x
))))
746 (defun calcFunc-tan (x) ; [N N] [Public]
747 (cond ((and (integerp x
)
748 (if (eq calc-angle-mode
'deg
)
753 (math-with-extra-prec 2
754 (math-tan-raw (math-to-radians (math-float x
)))))
757 (math-with-extra-prec 2
758 (let* ((xx (math-to-radians (math-float (nth 1 x
))))
759 (xs (math-to-radians (math-float (nth 2 x
))))
760 (sc (math-sin-cos-raw xx
)))
761 (if (and (math-zerop (cdr sc
)) (not calc-infinite-mode
))
763 (calc-record-why "*Division by zero")
764 (list 'calcFunc-tan x
))
765 (math-make-sdev (math-div-float (car sc
) (cdr sc
))
766 (math-div-float xs
(math-sqr (cdr sc
)))))))
767 (math-make-sdev (calcFunc-tan (nth 1 x
))
769 (math-sqr (calcFunc-cos (nth 1 x
)))))))
770 ((and (eq (car x
) 'intv
) (math-intv-constp x
))
771 (or (math-with-extra-prec 2
772 (let* ((xx (math-to-radians (math-float x
)))
773 (na (math-floor (math-div (math-sub (nth 2 xx
)
776 (nb (math-floor (math-div (math-sub (nth 3 xx
)
780 (math-sort-intv (nth 1 x
)
781 (math-tan-raw (nth 2 xx
))
782 (math-tan-raw (nth 3 xx
))))))
783 '(intv 3 (neg (var inf var-inf
)) (var inf var-inf
))))
784 ((equal x
'(var nan var-nan
))
786 (t (calc-record-why 'scalarp x
)
787 (list 'calcFunc-tan x
))))
789 (defun math-sin-raw (x) ; [N N]
790 (cond ((eq (car x
) 'cplx
)
791 (let* ((expx (math-exp-raw (nth 2 x
)))
792 (expmx (math-div-float '(float 1 0) expx
))
793 (sc (math-sin-cos-raw (nth 1 x
))))
795 (math-mul-float (car sc
)
796 (math-mul-float (math-add-float expx expmx
)
798 (math-mul-float (cdr sc
)
799 (math-mul-float (math-sub-float expx expmx
)
802 (math-polar (math-sin-raw (math-complex x
))))
803 ((Math-integer-negp (nth 1 x
))
804 (math-neg-float (math-sin-raw (math-neg-float x
))))
805 ((math-lessp-float '(float 7 0) x
) ; avoid inf loops due to roundoff
806 (math-sin-raw (math-mod x
(math-two-pi))))
807 (t (math-sin-raw-2 x x
))))
809 (defun math-cos-raw (x) ; [N N]
810 (if (eq (car-safe x
) 'polar
)
811 (math-polar (math-cos-raw (math-complex x
)))
812 (math-sin-raw (math-sub (math-pi-over-2) x
))))
814 ;;; This could use a smarter method: Reduce x as in math-sin-raw, then
815 ;;; compute either sin(x) or cos(x), whichever is smaller, and compute
816 ;;; the other using the identity sin(x)^2 + cos(x)^2 = 1.
817 (defun math-sin-cos-raw (x) ; [F.F F] (result is (sin x . cos x))
818 (cons (math-sin-raw x
) (math-cos-raw x
)))
820 (defun math-tan-raw (x) ; [N N]
821 (cond ((eq (car x
) 'cplx
)
822 (let* ((x (math-mul x
'(float 2 0)))
823 (expx (math-exp-raw (nth 2 x
)))
824 (expmx (math-div-float '(float 1 0) expx
))
825 (sc (math-sin-cos-raw (nth 1 x
)))
826 (d (math-add-float (cdr sc
)
827 (math-mul-float (math-add-float expx expmx
)
829 (and (not (eq (nth 1 d
) 0))
831 (math-div-float (car sc
) d
)
832 (math-div-float (math-mul-float (math-sub-float expx
834 '(float 5 -
1)) d
)))))
836 (math-polar (math-tan-raw (math-complex x
))))
838 (let ((sc (math-sin-cos-raw x
)))
839 (if (eq (nth 1 (cdr sc
)) 0)
840 (math-div (car sc
) 0)
841 (math-div-float (car sc
) (cdr sc
)))))))
843 (defun math-sin-raw-2 (x orgx
) ; This avoids poss of inf recursion. [F F]
844 (let ((xmpo2 (math-sub-float (math-pi-over-2) x
)))
845 (cond ((Math-integer-negp (nth 1 xmpo2
))
846 (math-neg-float (math-sin-raw-2 (math-sub-float x
(math-pi))
848 ((math-lessp-float (math-pi-over-4) x
)
849 (math-cos-raw-2 xmpo2 orgx
))
850 ((math-lessp-float x
(math-neg (math-pi-over-4)))
851 (math-neg (math-cos-raw-2 (math-add (math-pi-over-2) x
) orgx
)))
852 ((math-nearly-zerop-float x orgx
) '(float 0 0))
853 (calc-symbolic-mode (signal 'inexact-result nil
))
854 (t (math-sin-series x
6 4 x
(math-neg-float (math-sqr-float x
)))))))
856 (defun math-cos-raw-2 (x orgx
) ; [F F]
857 (cond ((math-nearly-zerop-float x orgx
) '(float 1 0))
858 (calc-symbolic-mode (signal 'inexact-result nil
))
859 (t (let ((xnegsqr (math-neg-float (math-sqr-float x
))))
861 (math-add-float '(float 1 0)
862 (math-mul-float xnegsqr
'(float 5 -
1)))
863 24 5 xnegsqr xnegsqr
)))))
865 (defun math-sin-series (sum nfac n x xnegsqr
)
866 (math-working "sin" sum
)
867 (let* ((nextx (math-mul-float x xnegsqr
))
868 (nextsum (math-add-float sum
(math-div-float nextx
869 (math-float nfac
)))))
870 (if (math-nearly-equal-float sum nextsum
)
872 (math-sin-series nextsum
(math-mul nfac
(* n
(1+ n
)))
873 (+ n
2) nextx xnegsqr
))))
876 ;;; Inverse sine, cosine, tangent.
878 (defun calcFunc-arcsin (x) ; [N N] [Public]
880 ((and (eq x
1) (eq calc-angle-mode
'deg
)) 90)
881 ((and (eq x -
1) (eq calc-angle-mode
'deg
)) -
90)
882 (calc-symbolic-mode (signal 'inexact-result nil
))
884 (math-with-extra-prec 2
885 (math-from-radians (math-arcsin-raw (math-float x
)))))
887 (math-make-sdev (calcFunc-arcsin (nth 1 x
))
891 (math-sub 1 (math-sqr (nth 1 x
))))))))
893 (math-sort-intv (nth 1 x
)
894 (calcFunc-arcsin (nth 2 x
))
895 (calcFunc-arcsin (nth 3 x
))))
896 ((equal x
'(var nan var-nan
))
898 (t (calc-record-why 'numberp x
)
899 (list 'calcFunc-arcsin x
))))
901 (defun calcFunc-arccos (x) ; [N N] [Public]
903 ((and (eq x
0) (eq calc-angle-mode
'deg
)) 90)
904 ((and (eq x -
1) (eq calc-angle-mode
'deg
)) 180)
905 (calc-symbolic-mode (signal 'inexact-result nil
))
907 (math-with-extra-prec 2
908 (math-from-radians (math-arccos-raw (math-float x
)))))
910 (math-make-sdev (calcFunc-arccos (nth 1 x
))
914 (math-sub 1 (math-sqr (nth 1 x
))))))))
916 (math-sort-intv (nth 1 x
)
917 (calcFunc-arccos (nth 2 x
))
918 (calcFunc-arccos (nth 3 x
))))
919 ((equal x
'(var nan var-nan
))
921 (t (calc-record-why 'numberp x
)
922 (list 'calcFunc-arccos x
))))
924 (defun calcFunc-arctan (x) ; [N N] [Public]
926 ((and (eq x
1) (eq calc-angle-mode
'deg
)) 45)
927 ((and (eq x -
1) (eq calc-angle-mode
'deg
)) -
45)
929 (math-with-extra-prec 2
930 (math-from-radians (math-arctan-raw (math-float x
)))))
932 (math-make-sdev (calcFunc-arctan (nth 1 x
))
935 (math-add 1 (math-sqr (nth 1 x
)))))))
937 (math-sort-intv (nth 1 x
)
938 (calcFunc-arctan (nth 2 x
))
939 (calcFunc-arctan (nth 3 x
))))
940 ((equal x
'(var inf var-inf
))
941 (math-quarter-circle t
))
942 ((equal x
'(neg (var inf var-inf
)))
943 (math-neg (math-quarter-circle t
)))
944 ((equal x
'(var nan var-nan
))
946 (t (calc-record-why 'numberp x
)
947 (list 'calcFunc-arctan x
))))
949 (defun math-arcsin-raw (x) ; [N N]
950 (let ((a (math-sqrt-raw (math-sub '(float 1 0) (math-sqr x
)))))
951 (if (or (memq (car x
) '(cplx polar
))
952 (memq (car a
) '(cplx polar
)))
953 (math-with-extra-prec 2 ; use extra precision for difficult case
954 (math-mul '(cplx 0 -
1)
955 (math-ln-raw (math-add (math-mul '(cplx 0 1) x
) a
))))
956 (math-arctan2-raw x a
))))
958 (defun math-arccos-raw (x) ; [N N]
959 (math-sub (math-pi-over-2) (math-arcsin-raw x
)))
961 (defun math-arctan-raw (x) ; [N N]
962 (cond ((memq (car x
) '(cplx polar
))
963 (math-with-extra-prec 2 ; extra-extra
965 (math-ln-raw (math-add 1 (math-mul '(cplx 0 1) x
)))
966 (math-ln-raw (math-add 1 (math-mul '(cplx 0 -
1) x
))))
968 ((Math-integer-negp (nth 1 x
))
969 (math-neg-float (math-arctan-raw (math-neg-float x
))))
971 (calc-symbolic-mode (signal 'inexact-result nil
))
972 ((math-equal-int x
1) (math-pi-over-4))
973 ((math-equal-int x -
1) (math-neg (math-pi-over-4)))
974 ((math-lessp-float '(float 414214 -
6) x
) ; if x > sqrt(2) - 1, reduce
975 (if (math-lessp-float '(float 1 0) x
)
976 (math-sub-float (math-mul-float (math-pi) '(float 5 -
1))
977 (math-arctan-raw (math-div-float '(float 1 0) x
)))
978 (math-sub-float (math-mul-float (math-pi) '(float 25 -
2))
979 (math-arctan-raw (math-div-float
980 (math-sub-float '(float 1 0) x
)
981 (math-add-float '(float 1 0)
983 (t (math-arctan-series x
3 x
(math-neg-float (math-sqr-float x
))))))
985 (defun math-arctan-series (sum n x xnegsqr
)
986 (math-working "arctan" sum
)
987 (let* ((nextx (math-mul-float x xnegsqr
))
988 (nextsum (math-add-float sum
(math-div-float nextx
(math-float n
)))))
989 (if (math-nearly-equal-float sum nextsum
)
991 (math-arctan-series nextsum
(+ n
2) nextx xnegsqr
))))
993 (defun calcFunc-arctan2 (y x
) ; [F R R] [Public]
996 (math-with-extra-prec 2
997 (math-from-radians (math-arctan2-raw (math-float y
)
999 (calc-record-why 'anglep x
)
1000 (list 'calcFunc-arctan2 y x
))
1001 (if (and (or (math-infinitep x
) (math-anglep x
))
1002 (or (math-infinitep y
) (math-anglep y
)))
1017 (calcFunc-arctan2 y x
)
1018 '(var nan var-nan
)))
1019 (calc-record-why 'anglep y
)
1020 (list 'calcFunc-arctan2 y x
))))
1022 (defun math-arctan2-raw (y x
) ; [F R R]
1023 (cond ((math-zerop y
)
1024 (if (math-negp x
) (math-pi)
1025 (if (or (math-floatp x
) (math-floatp y
)) '(float 0 0) 0)))
1029 (math-neg (math-pi-over-2))))
1031 (math-arctan-raw (math-div-float y x
)))
1033 (math-add-float (math-arctan-raw (math-div-float y x
))
1036 (math-sub-float (math-arctan-raw (math-div-float y x
))
1039 (defun calcFunc-arcsincos (x) ; [V N] [Public]
1040 (if (and (Math-vectorp x
)
1042 (calcFunc-arctan2 (nth 2 x
) (nth 1 x
))
1043 (math-reject-arg x
"*Two-element vector expected")))
1047 ;;; Exponential function.
1049 (defun calcFunc-exp (x) ; [N N] [Public]
1051 ((and (memq x
'(1 -
1)) calc-symbolic-mode
)
1052 (if (eq x
1) '(var e var-e
) (math-div 1 '(var e var-e
))))
1054 (math-with-extra-prec 2 (math-exp-raw (math-float x
))))
1055 ((eq (car-safe x
) 'sdev
)
1056 (let ((ex (calcFunc-exp (nth 1 x
))))
1057 (math-make-sdev ex
(math-mul (nth 2 x
) ex
))))
1058 ((eq (car-safe x
) 'intv
)
1059 (math-make-intv (nth 1 x
) (calcFunc-exp (nth 2 x
))
1060 (calcFunc-exp (nth 3 x
))))
1061 ((equal x
'(var inf var-inf
))
1063 ((equal x
'(neg (var inf var-inf
)))
1065 ((equal x
'(var nan var-nan
))
1067 (t (calc-record-why 'numberp x
)
1068 (list 'calcFunc-exp x
))))
1070 (defun calcFunc-expm1 (x) ; [N N] [Public]
1072 ((math-zerop x
) '(float 0 0))
1073 (calc-symbolic-mode (signal 'inexact-result nil
))
1075 (math-with-extra-prec 2
1076 (let ((x (math-float x
)))
1077 (if (and (eq (car x
) 'float
)
1078 (math-lessp-float x
'(float 1 0))
1079 (math-lessp-float '(float -
1 0) x
))
1080 (math-exp-minus-1-raw x
)
1081 (math-add (math-exp-raw x
) -
1)))))
1082 ((eq (car-safe x
) 'sdev
)
1084 (let ((ex (calcFunc-expm1 (nth 1 x
))))
1085 (math-make-sdev ex
(math-mul (nth 2 x
) (math-add ex
1))))
1086 (math-make-sdev (calcFunc-expm1 (nth 1 x
))
1087 (math-mul (nth 2 x
) (calcFunc-exp (nth 1 x
))))))
1088 ((eq (car-safe x
) 'intv
)
1089 (math-make-intv (nth 1 x
)
1090 (calcFunc-expm1 (nth 2 x
))
1091 (calcFunc-expm1 (nth 3 x
))))
1092 ((equal x
'(var inf var-inf
))
1094 ((equal x
'(neg (var inf var-inf
)))
1096 ((equal x
'(var nan var-nan
))
1098 (t (calc-record-why 'numberp x
)
1099 (list 'calcFunc-expm1 x
))))
1101 (defun calcFunc-exp10 (x) ; [N N] [Public]
1104 (math-pow '(float 1 1) x
)))
1106 (defun math-exp-raw (x) ; [N N]
1107 (cond ((math-zerop x
) '(float 1 0))
1108 (calc-symbolic-mode (signal 'inexact-result nil
))
1110 (let ((expx (math-exp-raw (nth 1 x
)))
1111 (sc (math-sin-cos-raw (nth 2 x
))))
1113 (math-mul-float expx
(cdr sc
))
1114 (math-mul-float expx
(car sc
)))))
1115 ((eq (car x
) 'polar
)
1116 (let ((xc (math-complex x
)))
1118 (math-exp-raw (nth 1 xc
))
1119 (math-from-radians (nth 2 xc
)))))
1120 ((or (math-lessp-float '(float 5 -
1) x
)
1121 (math-lessp-float x
'(float -
5 -
1)))
1122 (if (math-lessp-float '(float 921035 1) x
)
1124 (if (math-lessp-float x
'(float -
921035 1))
1126 (let* ((two-x (math-mul-float x
'(float 2 0)))
1127 (hint (math-scale-int (nth 1 two-x
) (nth 2 two-x
)))
1128 (hfrac (math-sub-float x
(math-mul-float (math-float hint
)
1130 (math-mul-float (math-ipow (math-sqrt-e) hint
)
1131 (math-add-float '(float 1 0)
1132 (math-exp-minus-1-raw hfrac
)))))
1133 (t (math-add-float '(float 1 0) (math-exp-minus-1-raw x
)))))
1135 (defun math-exp-minus-1-raw (x) ; [F F]
1136 (math-exp-series x
2 3 x x
))
1138 (defun math-exp-series (sum nfac n xpow x
)
1139 (math-working "exp" sum
)
1140 (let* ((nextx (math-mul-float xpow x
))
1141 (nextsum (math-add-float sum
(math-div-float nextx
1142 (math-float nfac
)))))
1143 (if (math-nearly-equal-float sum nextsum
)
1145 (math-exp-series nextsum
(math-mul nfac n
) (1+ n
) nextx x
))))
1151 (defun calcFunc-ln (x) ; [N N] [Public]
1152 (cond ((math-zerop x
)
1153 (if calc-infinite-mode
1154 '(neg (var inf var-inf
))
1155 (math-reject-arg x
"*Logarithm of zero")))
1158 (math-with-extra-prec 2 (math-ln-raw (math-float x
))))
1159 ((eq (car-safe x
) 'sdev
)
1160 (math-make-sdev (calcFunc-ln (nth 1 x
))
1161 (math-div (nth 2 x
) (nth 1 x
))))
1162 ((and (eq (car-safe x
) 'intv
) (or (Math-posp (nth 2 x
))
1163 (Math-zerop (nth 2 x
))
1164 (not (math-intv-constp x
))))
1165 (let ((calc-infinite-mode t
))
1166 (math-make-intv (nth 1 x
) (calcFunc-ln (nth 2 x
))
1167 (calcFunc-ln (nth 3 x
)))))
1168 ((equal x
'(var e var-e
))
1170 ((and (eq (car-safe x
) '^
)
1171 (equal (nth 1 x
) '(var e var-e
))
1172 (math-known-realp (nth 2 x
)))
1175 (if (equal x
'(var nan var-nan
))
1177 '(var inf var-inf
)))
1178 (t (calc-record-why 'numberp x
)
1179 (list 'calcFunc-ln x
))))
1181 (defun calcFunc-log10 (x) ; [N N] [Public]
1182 (cond ((math-equal-int x
1)
1183 (if (math-floatp x
) '(float 0 0) 0))
1184 ((and (Math-integerp x
)
1186 (let ((res (math-integer-log x
10)))
1188 (setq x
(cdr res
)))))
1190 ((and (eq (car-safe x
) 'frac
)
1192 (let ((res (math-integer-log (nth 2 x
) 10)))
1194 (setq x
(- (cdr res
))))))
1197 (if calc-infinite-mode
1198 '(neg (var inf var-inf
))
1199 (math-reject-arg x
"*Logarithm of zero")))
1200 (calc-symbolic-mode (signal 'inexact-result nil
))
1202 (math-with-extra-prec 2
1203 (let ((xf (math-float x
)))
1204 (if (eq (nth 1 xf
) 0)
1205 (math-reject-arg x
"*Logarithm of zero"))
1206 (if (Math-integer-posp (nth 1 xf
))
1207 (if (eq (nth 1 xf
) 1) ; log10(1*10^n) = n
1208 (math-float (nth 2 xf
))
1209 (let ((xdigs (1- (math-numdigs (nth 1 xf
)))))
1211 (math-div-float (math-ln-raw-2
1212 (list 'float
(nth 1 xf
) (- xdigs
)))
1214 (math-float (+ (nth 2 xf
) xdigs
)))))
1215 (math-div (calcFunc-ln xf
) (math-ln-10))))))
1216 ((eq (car-safe x
) 'sdev
)
1217 (math-make-sdev (calcFunc-log10 (nth 1 x
))
1219 (math-mul (nth 1 x
) (math-ln-10)))))
1220 ((and (eq (car-safe x
) 'intv
) (or (Math-posp (nth 2 x
))
1221 (not (math-intv-constp x
))))
1222 (math-make-intv (nth 1 x
)
1223 (calcFunc-log10 (nth 2 x
))
1224 (calcFunc-log10 (nth 3 x
))))
1226 (if (equal x
'(var nan var-nan
))
1228 '(var inf var-inf
)))
1229 (t (calc-record-why 'numberp x
)
1230 (list 'calcFunc-log10 x
))))
1232 (defun calcFunc-log (x &optional b
) ; [N N N] [Public]
1233 (cond ((or (null b
) (equal b
'(var e var-e
)))
1234 (math-normalize (list 'calcFunc-ln x
)))
1235 ((or (eq b
10) (equal b
'(float 1 1)))
1236 (math-normalize (list 'calcFunc-log10 x
)))
1238 (if calc-infinite-mode
1239 (math-div (calcFunc-ln x
) (calcFunc-ln b
))
1240 (math-reject-arg x
"*Logarithm of zero")))
1242 (if calc-infinite-mode
1243 (math-div (calcFunc-ln x
) (calcFunc-ln b
))
1244 (math-reject-arg b
"*Logarithm of zero")))
1245 ((math-equal-int b
1)
1246 (if calc-infinite-mode
1247 (math-div (calcFunc-ln x
) 0)
1248 (math-reject-arg b
"*Logarithm base one")))
1249 ((math-equal-int x
1)
1250 (if (or (math-floatp a
) (math-floatp b
)) '(float 0 0) 0))
1251 ((and (Math-ratp x
) (Math-ratp b
)
1252 (math-posp x
) (math-posp b
)
1253 (let* ((sign 1) (inv nil
)
1254 (xx (if (Math-lessp 1 x
)
1258 (bb (if (Math-lessp 1 b
)
1260 (setq sign
(- sign
))
1262 (res (if (Math-lessp xx bb
)
1263 (setq inv
(math-integer-log bb xx
))
1264 (math-integer-log xx bb
))))
1267 (math-div 1 (* sign
(cdr res
)))
1268 (* sign
(cdr res
)))))))
1270 (calc-symbolic-mode (signal 'inexact-result nil
))
1271 ((and (Math-numberp x
) (Math-numberp b
))
1272 (math-with-extra-prec 2
1273 (math-div (math-ln-raw (math-float x
))
1274 (math-log-base-raw b
))))
1275 ((and (eq (car-safe x
) 'sdev
)
1277 (math-make-sdev (calcFunc-log (nth 1 x
) b
)
1280 (math-log-base-raw b
)))))
1281 ((and (eq (car-safe x
) 'intv
) (or (Math-posp (nth 2 x
))
1282 (not (math-intv-constp x
)))
1284 (math-make-intv (nth 1 x
)
1285 (calcFunc-log (nth 2 x
) b
)
1286 (calcFunc-log (nth 3 x
) b
)))
1287 ((or (eq (car-safe x
) 'intv
) (eq (car-safe b
) 'intv
))
1288 (math-div (calcFunc-ln x
) (calcFunc-ln b
)))
1289 ((or (math-infinitep x
)
1291 (math-div (calcFunc-ln x
) (calcFunc-ln b
)))
1292 (t (if (Math-numberp b
)
1293 (calc-record-why 'numberp x
)
1294 (calc-record-why 'numberp b
))
1295 (list 'calcFunc-log x b
))))
1297 (defun calcFunc-alog (x &optional b
)
1298 (cond ((or (null b
) (equal b
'(var e var-e
)))
1299 (math-normalize (list 'calcFunc-exp x
)))
1300 (t (math-pow b x
))))
1302 (defun calcFunc-ilog (x b
)
1303 (if (and (math-natnump x
) (not (eq x
0))
1304 (math-natnump b
) (not (eq b
0)))
1306 (math-reject-arg x
"*Logarithm base one")
1307 (if (Math-natnum-lessp x b
)
1309 (cdr (math-integer-log x b
))))
1310 (math-floor (calcFunc-log x b
))))
1312 (defun math-integer-log (x b
)
1313 (let ((pows (list b
))
1317 (while (not (Math-lessp x pow
))
1318 (setq pows
(cons pow pows
)
1319 pow
(math-sqr pow
)))
1320 (setq n
(lsh 1 (1- (length pows
)))
1323 (while (and (setq pows
(cdr pows
))
1326 next
(math-mul pow
(car pows
)))
1327 (or (Math-lessp x next
)
1330 (cons (equal pow x
) sum
)))
1333 (defvar math-log-base-cache nil
)
1334 (defun math-log-base-raw (b) ; [N N]
1335 (if (not (and (equal (car math-log-base-cache
) b
)
1336 (eq (nth 1 math-log-base-cache
) calc-internal-prec
)))
1337 (setq math-log-base-cache
(list b calc-internal-prec
1338 (math-ln-raw (math-float b
)))))
1339 (nth 2 math-log-base-cache
))
1341 (defun calcFunc-lnp1 (x) ; [N N] [Public]
1342 (cond ((Math-equal-int x -
1)
1343 (if calc-infinite-mode
1344 '(neg (var inf var-inf
))
1345 (math-reject-arg x
"*Logarithm of zero")))
1347 ((math-zerop x
) '(float 0 0))
1348 (calc-symbolic-mode (signal 'inexact-result nil
))
1350 (math-with-extra-prec 2
1351 (let ((x (math-float x
)))
1352 (if (and (eq (car x
) 'float
)
1353 (math-lessp-float x
'(float 5 -
1))
1354 (math-lessp-float '(float -
5 -
1) x
))
1355 (math-ln-plus-1-raw x
)
1356 (math-ln-raw (math-add-float x
'(float 1 0)))))))
1357 ((eq (car-safe x
) 'sdev
)
1358 (math-make-sdev (calcFunc-lnp1 (nth 1 x
))
1359 (math-div (nth 2 x
) (math-add (nth 1 x
) 1))))
1360 ((and (eq (car-safe x
) 'intv
) (or (Math-posp (nth 2 x
))
1361 (not (math-intv-constp x
))))
1362 (math-make-intv (nth 1 x
)
1363 (calcFunc-lnp1 (nth 2 x
))
1364 (calcFunc-lnp1 (nth 3 x
))))
1366 (if (equal x
'(var nan var-nan
))
1368 '(var inf var-inf
)))
1369 (t (calc-record-why 'numberp x
)
1370 (list 'calcFunc-lnp1 x
))))
1372 (defun math-ln-raw (x) ; [N N] --- must be float format!
1373 (cond ((eq (car-safe x
) 'cplx
)
1375 (math-mul-float (math-ln-raw
1376 (math-add-float (math-sqr-float (nth 1 x
))
1377 (math-sqr-float (nth 2 x
))))
1379 (math-arctan2-raw (nth 2 x
) (nth 1 x
))))
1380 ((eq (car x
) 'polar
)
1381 (math-polar (list 'cplx
1382 (math-ln-raw (nth 1 x
))
1383 (math-to-radians (nth 2 x
)))))
1384 ((Math-equal-int x
1)
1386 (calc-symbolic-mode (signal 'inexact-result nil
))
1387 ((math-posp (nth 1 x
)) ; positive and real
1388 (let ((xdigs (1- (math-numdigs (nth 1 x
)))))
1389 (math-add-float (math-ln-raw-2 (list 'float
(nth 1 x
) (- xdigs
)))
1390 (math-mul-float (math-float (+ (nth 2 x
) xdigs
))
1393 (math-reject-arg x
"*Logarithm of zero"))
1394 ((eq calc-complex-mode
'polar
) ; negative and real
1396 (list 'cplx
; negative and real
1397 (math-ln-raw (math-neg-float x
))
1399 (t (list 'cplx
; negative and real
1400 (math-ln-raw (math-neg-float x
))
1403 (defun math-ln-raw-2 (x) ; [F F]
1404 (cond ((math-lessp-float '(float 14 -
1) x
)
1405 (math-add-float (math-ln-raw-2 (math-mul-float x
'(float 5 -
1)))
1407 (t ; now .7 < x <= 1.4
1408 (math-ln-raw-3 (math-div-float (math-sub-float x
'(float 1 0))
1409 (math-add-float x
'(float 1 0)))))))
1411 (defun math-ln-raw-3 (x) ; [F F]
1412 (math-mul-float (math-ln-raw-series x
3 x
(math-sqr-float x
))
1415 ;;; Compute ln((1+x)/(1-x))
1416 (defun math-ln-raw-series (sum n x xsqr
)
1417 (math-working "log" sum
)
1418 (let* ((nextx (math-mul-float x xsqr
))
1419 (nextsum (math-add-float sum
(math-div-float nextx
(math-float n
)))))
1420 (if (math-nearly-equal-float sum nextsum
)
1422 (math-ln-raw-series nextsum
(+ n
2) nextx xsqr
))))
1424 (defun math-ln-plus-1-raw (x)
1425 (math-lnp1-series x
2 x
(math-neg x
)))
1427 (defun math-lnp1-series (sum n xpow x
)
1428 (math-working "lnp1" sum
)
1429 (let* ((nextx (math-mul-float xpow x
))
1430 (nextsum (math-add-float sum
(math-div-float nextx
(math-float n
)))))
1431 (if (math-nearly-equal-float sum nextsum
)
1433 (math-lnp1-series nextsum
(1+ n
) nextx x
))))
1435 (math-defcache math-ln-10
(float (bigpos 018 684 045 994 092 585 302 2) -
21)
1436 (math-ln-raw-2 '(float 1 1)))
1438 (math-defcache math-ln-2
(float (bigpos 417 309 945 559 180 147 693) -
21)
1439 (math-ln-raw-3 (math-float '(frac 1 3))))
1443 ;;; Hyperbolic functions.
1445 (defun calcFunc-sinh (x) ; [N N] [Public]
1447 (math-expand-formulas
1449 (list '/ (list '-
(list 'calcFunc-exp x
)
1450 (list 'calcFunc-exp
(list 'neg x
))) 2)))
1452 (if calc-symbolic-mode
(signal 'inexact-result nil
))
1453 (math-with-extra-prec 2
1454 (let ((expx (math-exp-raw (math-float x
))))
1455 (math-mul (math-add expx
(math-div -
1 expx
)) '(float 5 -
1)))))
1456 ((eq (car-safe x
) 'sdev
)
1457 (math-make-sdev (calcFunc-sinh (nth 1 x
))
1458 (math-mul (nth 2 x
) (calcFunc-cosh (nth 1 x
)))))
1460 (math-sort-intv (nth 1 x
)
1461 (calcFunc-sinh (nth 2 x
))
1462 (calcFunc-sinh (nth 3 x
))))
1463 ((or (equal x
'(var inf var-inf
))
1464 (equal x
'(neg (var inf var-inf
)))
1465 (equal x
'(var nan var-nan
)))
1467 (t (calc-record-why 'numberp x
)
1468 (list 'calcFunc-sinh x
))))
1469 (put 'calcFunc-sinh
'math-expandable t
)
1471 (defun calcFunc-cosh (x) ; [N N] [Public]
1473 (math-expand-formulas
1475 (list '/ (list '+ (list 'calcFunc-exp x
)
1476 (list 'calcFunc-exp
(list 'neg x
))) 2)))
1478 (if calc-symbolic-mode
(signal 'inexact-result nil
))
1479 (math-with-extra-prec 2
1480 (let ((expx (math-exp-raw (math-float x
))))
1481 (math-mul (math-add expx
(math-div 1 expx
)) '(float 5 -
1)))))
1482 ((eq (car-safe x
) 'sdev
)
1483 (math-make-sdev (calcFunc-cosh (nth 1 x
))
1485 (calcFunc-sinh (nth 1 x
)))))
1486 ((and (eq (car x
) 'intv
) (math-intv-constp x
))
1487 (setq x
(math-abs x
))
1488 (math-sort-intv (nth 1 x
)
1489 (calcFunc-cosh (nth 2 x
))
1490 (calcFunc-cosh (nth 3 x
))))
1491 ((or (equal x
'(var inf var-inf
))
1492 (equal x
'(neg (var inf var-inf
)))
1493 (equal x
'(var nan var-nan
)))
1495 (t (calc-record-why 'numberp x
)
1496 (list 'calcFunc-cosh x
))))
1497 (put 'calcFunc-cosh
'math-expandable t
)
1499 (defun calcFunc-tanh (x) ; [N N] [Public]
1501 (math-expand-formulas
1503 (let ((expx (list 'calcFunc-exp x
))
1504 (expmx (list 'calcFunc-exp
(list 'neg x
))))
1506 (list '/ (list '- expx expmx
) (list '+ expx expmx
))))))
1508 (if calc-symbolic-mode
(signal 'inexact-result nil
))
1509 (math-with-extra-prec 2
1510 (let* ((expx (calcFunc-exp (math-float x
)))
1511 (expmx (math-div 1 expx
)))
1512 (math-div (math-sub expx expmx
)
1513 (math-add expx expmx
)))))
1514 ((eq (car-safe x
) 'sdev
)
1515 (math-make-sdev (calcFunc-tanh (nth 1 x
))
1517 (math-sqr (calcFunc-cosh (nth 1 x
))))))
1519 (math-sort-intv (nth 1 x
)
1520 (calcFunc-tanh (nth 2 x
))
1521 (calcFunc-tanh (nth 3 x
))))
1522 ((equal x
'(var inf var-inf
))
1524 ((equal x
'(neg (var inf var-inf
)))
1526 ((equal x
'(var nan var-nan
))
1528 (t (calc-record-why 'numberp x
)
1529 (list 'calcFunc-tanh x
))))
1530 (put 'calcFunc-tanh
'math-expandable t
)
1532 (defun calcFunc-arcsinh (x) ; [N N] [Public]
1534 (math-expand-formulas
1536 (list 'calcFunc-ln
(list '+ x
(list 'calcFunc-sqrt
1537 (list '+ (list '^ x
2) 1))))))
1539 (if calc-symbolic-mode
(signal 'inexact-result nil
))
1540 (math-with-extra-prec 2
1541 (math-ln-raw (math-add x
(math-sqrt-raw (math-add (math-sqr x
)
1543 ((eq (car-safe x
) 'sdev
)
1544 (math-make-sdev (calcFunc-arcsinh (nth 1 x
))
1547 (math-add (math-sqr (nth 1 x
)) 1)))))
1549 (math-sort-intv (nth 1 x
)
1550 (calcFunc-arcsinh (nth 2 x
))
1551 (calcFunc-arcsinh (nth 3 x
))))
1552 ((or (equal x
'(var inf var-inf
))
1553 (equal x
'(neg (var inf var-inf
)))
1554 (equal x
'(var nan var-nan
)))
1556 (t (calc-record-why 'numberp x
)
1557 (list 'calcFunc-arcsinh x
))))
1558 (put 'calcFunc-arcsinh
'math-expandable t
)
1560 (defun calcFunc-arccosh (x) ; [N N] [Public]
1562 ((and (eq x -
1) calc-symbolic-mode
)
1564 ((and (eq x
0) calc-symbolic-mode
)
1565 (math-div (math-mul '(var pi var-pi
) '(var i var-i
)) 2))
1566 (math-expand-formulas
1568 (list 'calcFunc-ln
(list '+ x
(list 'calcFunc-sqrt
1569 (list '-
(list '^ x
2) 1))))))
1571 (if calc-symbolic-mode
(signal 'inexact-result nil
))
1572 (if (Math-equal-int x -
1)
1573 (math-imaginary (math-pi))
1574 (math-with-extra-prec 2
1575 (if (or t
; need to do this even in the real case!
1576 (memq (car-safe x
) '(cplx polar
)))
1577 (let ((xp1 (math-add 1 x
))) ; this gets the branch cuts right
1579 (math-add x
(math-mul xp1
1586 (math-add x
(math-sqrt-raw (math-add (math-sqr x
)
1587 '(float -
1 0)))))))))
1588 ((eq (car-safe x
) 'sdev
)
1589 (math-make-sdev (calcFunc-arccosh (nth 1 x
))
1592 (math-add (math-sqr (nth 1 x
)) -
1)))))
1594 (math-sort-intv (nth 1 x
)
1595 (calcFunc-arccosh (nth 2 x
))
1596 (calcFunc-arccosh (nth 3 x
))))
1597 ((or (equal x
'(var inf var-inf
))
1598 (equal x
'(neg (var inf var-inf
)))
1599 (equal x
'(var nan var-nan
)))
1601 (t (calc-record-why 'numberp x
)
1602 (list 'calcFunc-arccosh x
))))
1603 (put 'calcFunc-arccosh
'math-expandable t
)
1605 (defun calcFunc-arctanh (x) ; [N N] [Public]
1607 ((and (Math-equal-int x
1) calc-infinite-mode
)
1609 ((and (Math-equal-int x -
1) calc-infinite-mode
)
1610 '(neg (var inf var-inf
)))
1611 (math-expand-formulas
1613 (list 'calcFunc-ln
(list '+ 1 x
))
1614 (list 'calcFunc-ln
(list '-
1 x
))) 2))
1616 (if calc-symbolic-mode
(signal 'inexact-result nil
))
1617 (math-with-extra-prec 2
1618 (if (or (memq (car-safe x
) '(cplx polar
))
1620 (math-mul (math-sub (math-ln-raw (math-add '(float 1 0) x
))
1621 (math-ln-raw (math-sub '(float 1 0) x
)))
1623 (if (and (math-equal-int x
1) calc-infinite-mode
)
1625 (if (and (math-equal-int x -
1) calc-infinite-mode
)
1626 '(neg (var inf var-inf
))
1627 (math-mul (math-ln-raw (math-div (math-add '(float 1 0) x
)
1630 ((eq (car-safe x
) 'sdev
)
1631 (math-make-sdev (calcFunc-arctanh (nth 1 x
))
1633 (math-sub 1 (math-sqr (nth 1 x
))))))
1635 (math-sort-intv (nth 1 x
)
1636 (calcFunc-arctanh (nth 2 x
))
1637 (calcFunc-arctanh (nth 3 x
))))
1638 ((equal x
'(var nan var-nan
))
1640 (t (calc-record-why 'numberp x
)
1641 (list 'calcFunc-arctanh x
))))
1642 (put 'calcFunc-arctanh
'math-expandable t
)
1645 ;;; Convert A from HMS or degrees to radians.
1646 (defun calcFunc-rad (a) ; [R R] [Public]
1647 (cond ((or (Math-numberp a
)
1649 (math-with-extra-prec 2
1650 (math-mul a
(math-pi-over-180))))
1652 (math-from-hms a
'rad
))
1654 (math-make-sdev (calcFunc-rad (nth 1 a
))
1655 (calcFunc-rad (nth 2 a
))))
1656 (math-expand-formulas
1657 (math-div (math-mul a
'(var pi var-pi
)) 180))
1658 ((math-infinitep a
) a
)
1659 (t (list 'calcFunc-rad a
))))
1660 (put 'calcFunc-rad
'math-expandable t
)
1662 ;;; Convert A from HMS or radians to degrees.
1663 (defun calcFunc-deg (a) ; [R R] [Public]
1664 (cond ((or (Math-numberp a
)
1666 (math-with-extra-prec 2
1667 (math-div a
(math-pi-over-180))))
1669 (math-from-hms a
'deg
))
1671 (math-make-sdev (calcFunc-deg (nth 1 a
))
1672 (calcFunc-deg (nth 2 a
))))
1673 (math-expand-formulas
1674 (math-div (math-mul 180 a
) '(var pi var-pi
)))
1675 ((math-infinitep a
) a
)
1676 (t (list 'calcFunc-deg a
))))
1677 (put 'calcFunc-deg
'math-expandable t
)
1679 ;;; arch-tag: c7367e8e-d0b8-4f70-8577-2fb3f31dbb4c
1680 ;;; calc-math.el ends here