v13i034: Emacs Calculator 1.01, part 08/19
David Gillespie
daveg at csvax.caltech.edu
Wed Jun 6 09:31:56 AEST 1990
Posting-number: Volume 13, Issue 34
Submitted-by: daveg at csvax.caltech.edu (David Gillespie)
Archive-name: gmcalc/part08
---- Cut Here and unpack ----
#!/bin/sh
# this is part 8 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file calc-ext.el continued
#
CurArch=8
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file calc-ext.el"
sed 's/^X//' << 'SHAR_EOF' >> calc-ext.el
X (- (+ (math-numdigs (nth 1 a))
X (nth 2 a))
X (1+ tol)))))
X ((not (eq (car tol) 'float))
X (if (Math-realp tol)
X (math-to-fraction a (math-float tol))
X (math-reject-arg tol 'realp)))
X ((Math-negp tol)
X (math-to-fraction a (math-neg tol)))
X ((Math-zerop tol)
X (math-to-fraction a 0))
X ((not (math-lessp-float tol '(float 1 0)))
X (math-trunc a))
X ((Math-zerop a)
X 0)
X (t
X (let ((cfrac (math-continued-fraction a tol))
X (calc-prefer-frac t))
X (math-eval-continued-fraction cfrac))))
X)
X(fset 'calcFunc-frac (symbol-function 'math-to-fraction))
X
X(defun math-continued-fraction (a tol)
X (let ((calc-internal-prec (+ calc-internal-prec 2)))
X (let ((cfrac nil)
X (aa a)
X (calc-prefer-frac nil)
X int)
X (while (or (null cfrac)
X (and (not (Math-zerop aa))
X (not (math-lessp-float
X (math-abs
X (math-sub a
X (let ((f (math-eval-continued-fraction
X cfrac)))
X (math-working "Fractionalize" f)
X f)))
X tol))))
X (setq int (math-trunc aa)
X aa (math-sub aa int)
X cfrac (cons int cfrac))
X (or (Math-zerop aa)
X (setq aa (math-div 1 aa))))
X cfrac))
X)
X
X(defun math-eval-continued-fraction (cf)
X (let ((n (car cf))
X (d 1)
X temp)
X (while (setq cf (cdr cf))
X (setq temp (math-add (math-mul (car cf) n) d)
X d n
X n temp))
X (math-div n d))
X)
X
X
X(defun math-clean-number (a &optional prec) ; [X X S] [Public]
X (if prec
X (cond ((Math-messy-integerp prec)
X (math-clean-number a (math-trunc prec)))
X ((or (not (integerp prec))
X (< prec 3))
X (calc-record-why "Precision must be an integer 3 or above")
X (list 'calcFunc-clean a prec))
X ((not (Math-objvecp a))
X (list 'calcFunc-clean a prec))
X (t (let ((calc-internal-prec prec))
X (math-clean-number (math-normalize a)))))
X (cond ((eq (car-safe a) 'polar)
X (let ((theta (math-mod (nth 2 a)
X (if (eq calc-angle-mode 'rad)
X (math-two-pi)
X 360))))
X (math-neg
X (math-neg
X (math-normalize
X (list 'polar (nth 1 a) theta))))))
X ((Math-vectorp a)
X (math-map-vec 'math-clean-number a))
X ((Math-objectp a) a)
X (t (list 'calcFunc-clean a))))
X)
X(fset 'calcFunc-clean (symbol-function 'math-clean-number))
X
X
X
X
X;;;; Logical operations.
X
X(defun calcFunc-eq (a b)
X (let ((res (math-compare a b)))
X (if (= res 0)
X 1
X (if (= res 2)
X (list 'calcFunc-eq a b)
X 0)))
X)
X
X(defun calcFunc-neq (a b)
X (let ((res (math-compare a b)))
X (if (= res 0)
X 0
X (if (= res 2)
X (list 'calcFunc-neq a b)
X 1)))
X)
X
X(defun calcFunc-lt (a b)
X (let ((res (math-compare a b)))
X (if (= res -1)
X 1
X (if (= res 2)
X (list 'calcFunc-lt a b)
X 0)))
X)
X
X(defun calcFunc-gt (a b)
X (let ((res (math-compare a b)))
X (if (= res 1)
X 1
X (if (= res 2)
X (list 'calcFunc-gt a b)
X 0)))
X)
X
X(defun calcFunc-leq (a b)
X (let ((res (math-compare a b)))
X (if (= res 1)
X 0
X (if (= res 2)
X (list 'calcFunc-leq a b)
X 1)))
X)
X
X(defun calcFunc-geq (a b)
X (let ((res (math-compare a b)))
X (if (= res -1)
X 0
X (if (= res 2)
X (list 'calcFunc-geq a b)
X 1)))
X)
X
X(defun calcFunc-land (a b)
X (cond ((Math-zerop a)
X a)
X ((Math-zerop b)
X b)
X ((Math-numberp a)
X b)
X ((Math-numberp b)
X a)
X (t (list 'calcFunc-land a b)))
X)
X
X(defun calcFunc-lor (a b)
X (cond ((Math-zerop a)
X b)
X ((Math-zerop b)
X a)
X ((Math-numberp a)
X a)
X ((Math-numberp b)
X b)
X (t (list 'calcFunc-lor a b)))
X)
X
X(defun calcFunc-lnot (a)
X (if (Math-zerop a)
X 1
X (if (Math-numberp a)
X 0
X (list 'calcFunc-lnot a)))
X)
X
X(defun calcFunc-if (c e1 e2)
X (if (Math-zerop c)
X e2
X (if (Math-numberp c)
X e1
X (list 'calcFunc-if c e1 e2)))
X)
X
X(defun math-normalize-logical-op (a)
X (or (and (eq (car a) 'calcFunc-if)
X (= (length a) 4)
X (let ((a1 (math-normalize (nth 1 a))))
X (if (Math-zerop a1)
X (math-normalize (nth 3 a))
X (if (Math-numberp a1)
X (math-normalize (nth 2 a))
X (list 'calcFunc-if a1 (nth 2 a) (nth 3 a))))))
X a)
X)
X
X(defun calcFunc-in (a b)
X (or (and (eq (car-safe b) 'vec)
X (let ((bb b))
X (while (and (setq bb (cdr bb))
X (not (if (memq (car-safe (car bb)) '(vec intv))
X (eq (calcFunc-in a (car bb)) 1)
X (math-equal a (car bb))))))
X (if bb 1 (and (math-constp a) (math-constp bb) 0))))
X (and (eq (car-safe b) 'intv)
X (let ((res (math-compare a (nth 2 b))))
X (cond ((= res -1)
X 0)
X ((= res 0)
X (if (memq (nth 1 b) '(2 3)) 1 0))
X ((/= res 1)
X nil)
X ((= (setq res (math-compare a (nth 3 b))) 1)
X 0)
X ((= res 0)
X (if (memq (nth 1 b) '(1 3)) 1 0))
X ((/= res -1)
X nil)
X (t 1))))
X (and (math-equal a b)
X 1)
X (and (math-constp a) (math-constp b)
X 0)
X (list 'calcFunc-in a b))
X)
X
X(defun calcFunc-typeof (a)
X (cond ((Math-integerp a) 1)
X ((eq (car a) 'frac) 2)
X ((eq (car a) 'float) 3)
X ((eq (car a) 'hms) 4)
X ((eq (car a) 'cplx) 5)
X ((eq (car a) 'polar) 6)
X ((eq (car a) 'sdev) 7)
X ((eq (car a) 'intv) 8)
X ((eq (car a) 'mod) 9)
X ((eq (car a) 'var) 100)
X ((eq (car a) 'vec) (if (math-matrixp a) 102 101))
X (t (let ((func (assq (car a) '( ( + . calcFunc-add )
X ( - . calcFunc-sub )
X ( * . calcFunc-mul )
X ( / . calcFunc-div )
X ( ^ . calcFunc-pow )
X ( % . calcFunc-mod )
X ( neg . calcFunc-neg )
X ( | . calcFunc-vconcat ) ))))
X (setq func (if func (cdr func) (car a)))
X (math-calcFunc-to-var func))))
X)
X
X(defun calcFunc-integer (a)
X (if (Math-integerp a)
X 1
X (if (Math-objvecp a)
X 0
X (list 'calcFunc-integer a)))
X)
X
X(defun calcFunc-real (a)
X (if (Math-realp a)
X 1
X (if (Math-objvecp a)
X 0
X (list 'calcFunc-real a)))
X)
X
X(defun calcFunc-constant (a)
X (if (math-constp a)
X 1
X (if (Math-objvecp a)
X 0
X (list 'calcFunc-constant a)))
X)
X
X(defun calcFunc-refers (a b)
X (if (math-expr-contains a b)
X 1
X (if (eq (car-safe a) 'var)
X (list 'calcFunc-refers a b)
X 0))
X)
X
X
X
X
X;;;; Complex numbers.
X
X(defun math-to-polar (a) ; [C N] [Public]
X (cond ((Math-vectorp a)
X (math-map-vec 'math-to-polar a))
X ((Math-realp a) a)
X ((Math-numberp a)
X (math-normalize (math-polar a)))
X (t (list 'calcFunc-polar)))
X)
X(fset 'calcFunc-polar (symbol-function 'math-to-polar))
X
X(defun math-to-rectangular (a) ; [N N] [Public]
X (cond ((Math-vectorp a)
X (math-map-vec 'math-to-rectangular a))
X ((Math-realp a) a)
X ((Math-numberp a)
X (math-normalize (math-complex a)))
X (t (list 'calcFunc-rect)))
X)
X(fset 'calcFunc-rect (symbol-function 'math-to-rectangular))
X
X;;; Compute the complex conjugate of A. [O O] [Public]
X(defun math-conj (a)
X (cond ((math-real-objectp a)
X a)
X ((eq (car a) 'cplx)
X (list 'cplx (nth 1 a) (math-neg (nth 2 a))))
X ((eq (car a) 'polar)
X (list 'polar (nth 1 a) (math-neg (nth 2 a))))
X ((eq (car a) 'vec)
X (math-map-vec 'math-conj a))
X ((eq (car a) 'calcFunc-conj)
X (nth 1 a))
X (t (calc-record-why 'numberp a)
X (list 'calcFunc-conj a)))
X)
X(fset 'calcFunc-conj (symbol-function 'math-conj))
X
X;;; Compute the absolute value squared of A. [F N] [Public]
X(defun math-abssqr (a)
X (cond ((Math-realp a)
X (math-sqr a))
X ((eq (car a) 'cplx)
X (math-add (math-sqr (nth 1 a)) (math-sqr (nth 2 a))))
X ((eq (car a) 'polar)
X (math-sqr (nth 1 a)))
X ((and (memq (car a) '(sdev intv)) (math-constp a))
X (math-sqr (math-abs a)))
X ((eq (car a) 'vec)
X (math-reduce-vec 'math-add (math-map-vec 'math-abssqr a)))
X (t (calc-record-why 'numvecp a)
X (list 'calcFunc-abssqr a)))
X)
X(fset 'calcFunc-abssqr (symbol-function 'math-abssqr))
X
X;;; Compute the complex argument of A. [F N] [Public]
X(defun math-cplx-arg (a)
X (cond ((Math-anglep a)
X (if (math-negp a) (math-half-circle nil) 0))
X ((eq (car-safe a) 'cplx)
X (math-arctan2 (nth 2 a) (nth 1 a)))
X ((eq (car-safe a) 'polar)
X (nth 2 a))
X ((eq (car a) 'vec)
X (math-map-vec 'math-cplx-arg a))
X (t (calc-record-why 'numvecp a)
X (list 'calcFunc-arg a)))
X)
X(fset 'calcFunc-arg (symbol-function 'math-cplx-arg))
X
X;;; Extract the real or complex part of a complex number. [R N] [Public]
X;;; Also extracts the real part of a modulo form.
X(defun math-real-part (a)
X (cond ((memq (car-safe a) '(mod sdev))
X (nth 1 a))
X ((math-real-objectp a) a)
X ((eq (car a) 'cplx)
X (nth 1 a))
X ((eq (car a) 'polar)
X (math-mul (nth 1 a) (math-cos (nth 2 a))))
X ((eq (car a) 'vec)
X (math-map-vec 'math-real-part a))
X (t (calc-record-why 'numberp a)
X (list 'calcFunc-re a)))
X)
X(fset 'calcFunc-re (symbol-function 'math-real-part))
X
X(defun math-imag-part (a)
X (cond ((math-real-objectp a)
X (if (math-floatp a) '(float 0 0) 0))
X ((eq (car a) 'cplx)
X (nth 2 a))
X ((eq (car a) 'polar)
X (math-mul (nth 1 a) (math-sin (nth 2 a))))
X ((eq (car a) 'vec)
X (math-map-vec 'math-imag-part a))
X (t (calc-record-why 'numberp a)
X (list 'calcFunc-im a)))
X)
X(fset 'calcFunc-im (symbol-function 'math-imag-part))
X
X
X
X;;;; Transcendental functions.
X
X;;; All of these functions are defined on the complex plane.
X;;; (Branch cuts, etc. follow Steele's Common Lisp book.)
X
X;;; Most functions increase calc-internal-prec by 2 digits, then round
X;;; down afterward. "-raw" functions use the current precision, require
X;;; their arguments to be in float (or complex float) format, and always
X;;; work in radians (where applicable).
X
X(defun math-to-radians (a) ; [N N]
X (cond ((eq (car-safe a) 'hms)
X (math-from-hms a 'rad))
X ((memq calc-angle-mode '(deg hms))
X (math-mul a (math-pi-over-180)))
X (t a))
X)
X
X(defun math-from-radians (a) ; [N N]
X (cond ((eq calc-angle-mode 'deg)
X (if (math-constp a)
X (math-div a (math-pi-over-180))
X (list 'calcFunc-deg a)))
X ((eq calc-angle-mode 'hms)
X (math-to-hms a 'rad))
X (t a))
X)
X
X(defun math-to-radians-2 (a) ; [N N]
X (cond ((eq (car-safe a) 'hms)
X (math-from-hms a 'rad))
X ((memq calc-angle-mode '(deg hms))
X (if calc-symbolic-mode
X (math-div (math-mul a '(var pi var-pi)) 180)
X (math-mul a (math-pi-over-180))))
X (t a))
X)
X
X(defun math-from-radians-2 (a) ; [N N]
X (cond ((memq calc-angle-mode '(deg hms))
X (if calc-symbolic-mode
X (math-div (math-mul 180 a) '(var pi var-pi))
X (math-div a (math-pi-over-180))))
X (t a))
X)
X
X
X
X;;; Sine, cosine, and tangent.
X
X(defun math-sin (x) ; [N N] [Public]
X (cond ((Math-scalarp x)
X (math-with-extra-prec 2
X (math-sin-raw (math-to-radians (math-float x)))))
X ((eq (car x) 'sdev)
X (if (math-constp x)
X (math-with-extra-prec 2
X (let* ((xx (math-to-radians (math-float (nth 1 x))))
X (xs (math-to-radians (math-float (nth 2 x))))
X (sc (math-sin-cos-raw xx)))
X (math-make-sdev (car sc)
X (math-mul xs (math-abs (cdr sc))))))
X (math-make-sdev (math-sin (nth 1 x))
X (math-mul (nth 2 x)
X (math-abs (math-cos (nth 1 x)))))))
X ((and (eq (car x) 'intv) (math-constp x))
X (math-cos (math-sub x (math-quarter-circle nil))))
X (t (calc-record-why 'scalarp x)
X (list 'calcFunc-sin x)))
X)
X(fset 'calcFunc-sin (symbol-function 'math-sin))
X
X(defun math-cos (x) ; [N N] [Public]
X (cond ((Math-scalarp x)
X (math-with-extra-prec 2
X (math-cos-raw (math-to-radians (math-float x)))))
X ((eq (car x) 'sdev)
X (if (math-constp x)
X (math-with-extra-prec 2
X (let* ((xx (math-to-radians (math-float (nth 1 x))))
X (xs (math-to-radians (math-float (nth 2 x))))
X (sc (math-sin-cos-raw xx)))
X (math-make-sdev (cdr sc)
X (math-mul xs (math-abs (car sc))))))
X (math-make-sdev (math-cos (nth 1 x))
X (math-mul (nth 2 x)
X (math-abs (math-sin (nth 1 x)))))))
X ((and (eq (car x) 'intv) (math-constp x))
X (math-with-extra-prec 2
X (let* ((xx (math-to-radians (math-float x)))
X (na (math-floor (math-div (nth 2 xx) (math-pi))))
X (nb (math-floor (math-div (nth 3 xx) (math-pi))))
X (span (math-sub nb na)))
X (if (memq span '(0 1))
X (let ((int (math-sort-intv (nth 1 x)
X (math-cos-raw (nth 2 xx))
X (math-cos-raw (nth 3 xx)))))
X (if (eq span 1)
X (if (math-evenp na)
X (math-make-intv (logior (nth 1 x) 2)
X -1
X (nth 3 int))
X (math-make-intv (logior (nth 1 x) 1)
X (nth 2 int)
X 1))
X int))
X (list 'intv 3 -1 1)))))
X (t (calc-record-why 'scalarp x)
X (list 'calcFunc-cos x)))
X)
X(fset 'calcFunc-cos (symbol-function 'math-cos))
X
X(defun math-sin-cos (x) ; [V N] [Public]
X (if (Math-scalarp x)
X (math-with-extra-prec 2
X (let ((sc (math-sin-cos-raw (math-to-radians (math-float x)))))
X (list 'vec (cdr sc) (car sc)))) ; the vector [cos, sin]
X (list 'vec (math-sin x) (math-cos x)))
X)
X(fset 'calcFunc-sincos (symbol-function 'math-sin-cos))
X
X(defun math-tan (x) ; [N N] [Public]
X (cond ((Math-scalarp x)
X (math-with-extra-prec 2
X (math-tan-raw (math-to-radians (math-float x)))))
X ((eq (car x) 'sdev)
X (if (math-constp x)
X (math-with-extra-prec 2
X (let* ((xx (math-to-radians (math-float (nth 1 x))))
X (xs (math-to-radians (math-float (nth 2 x))))
X (sc (math-sin-cos-raw xx)))
X (if (math-zerop (cdr sc))
X (progn
X (calc-record-why "Division by zero")
X (list 'calcFunc-tan x))
X (math-make-sdev (math-div-float (car sc) (cdr sc))
X (math-div-float xs (math-sqr (cdr sc)))))))
X (math-make-sdev (math-tan (nth 1 x))
X (math-div (nth 2 x)
X (math-sqr (math-cos (nth 1 x)))))))
X ((and (eq (car x) 'intv) (math-constp x))
X (or (math-with-extra-prec 2
X (let* ((xx (math-to-radians (math-float x)))
X (na (math-floor (math-div (math-sub (nth 2 xx)
X (math-pi-over-2))
X (math-pi))))
X (nb (math-floor (math-div (math-sub (nth 3 xx)
X (math-pi-over-2))
X (math-pi)))))
X (and (equal na nb)
X (math-sort-intv (nth 1 x)
X (math-tan-raw (nth 2 xx))
X (math-tan-raw (nth 3 xx))))))
X (progn
X (calc-record-why "Infinite interval" x)
X (list 'calcFunc-tan x))))
X (t (calc-record-why 'scalarp x)
X (list 'calcFunc-tan x)))
X)
X(fset 'calcFunc-tan (symbol-function 'math-tan))
X
X(defun math-sin-raw (x) ; [N N]
X (cond ((eq (car-safe x) 'cplx)
X (let* ((expx (math-exp-raw (nth 2 x)))
X (expmx (math-div-float '(float 1 0) expx))
X (sc (math-sin-cos-raw (nth 1 x))))
X (list 'cplx
X (math-mul-float (car sc)
X (math-mul-float (math-sub expx expmx)
X '(float 5 -1)))
X (math-mul-float (cdr sc)
X (math-mul-float (math-add-float expx expmx)
X '(float 5 -1))))))
X ((eq (car-safe x) 'polar)
X (math-polar (math-sin-raw (math-complex x))))
X ((Math-integer-negp (nth 1 x))
X (math-neg-float (math-sin-raw (math-neg-float x))))
X ((math-lessp-float '(float 7 0) x) ; avoid inf loops due to roundoff
X (math-sin-raw (math-mod x (math-two-pi))))
X (t (math-sin-raw-2 x x)))
X)
X
X(defun math-cos-raw (x) ; [N N]
X (if (eq (car-safe x) 'polar)
X (math-polar (math-cos-raw (math-complex x)))
X (math-sin-raw (math-sub-float (math-pi-over-2) x)))
X)
X
X;;; This could use a smarter method: Reduce x as in math-sin-raw, then
X;;; compute either sin(x) or cos(x), whichever is smaller, and compute
X;;; the other using the identity sin(x)^2 + cos(x)^2 = 1.
X(defun math-sin-cos-raw (x) ; [F.F F] (result is (sin x . cos x))
X (cons (math-sin-raw x) (math-cos-raw x))
X)
X
X(defun math-tan-raw (x) ; [N N]
X (cond ((eq (car-safe x) 'cplx)
X (let* ((x (math-mul-float x '(float 2 0)))
X (expx (math-exp-raw (nth 2 x)))
X (expmx (math-div-float '(float 1 0) expx))
X (sc (math-sin-cos-raw (nth 1 x)))
X (d (math-add-float (cdr sc)
X (math-mul-float (math-add-float expx expmx)
X '(float 5 -1)))))
X (and (not (eq (nth 1 d) 0))
X (list 'cplx
X (math-div-float (car sc) d)
X (math-div-float (math-mul-float (math-add expx expmx)
X '(float 5 -1)) d)))))
X ((eq (car-safe x) 'polar)
X (math-polar (math-tan-raw (math-complex x))))
X (t
X (let ((sc (math-sin-cos-raw x)))
X (if (eq (nth 1 (cdr sc)) 0)
X (math-reject-arg x "Division by zero")
X (math-div-float (car sc) (cdr sc))))))
X)
X
X(defun math-sin-raw-2 (x orgx) ; This avoids poss of inf recursion. [F F]
X (let ((xmpo2 (math-sub-float (math-pi-over-2) x)))
X (cond ((Math-integer-negp (nth 1 xmpo2))
X (math-neg-float (math-sin-raw-2 (math-sub-float x (math-pi))
X orgx)))
X ((math-lessp-float (math-pi-over-4) x)
X (math-cos-raw-2 xmpo2 orgx))
X ((math-lessp-float x (math-neg (math-pi-over-4)))
X (math-neg (math-cos-raw-2 (math-add (math-pi-over-2) x) orgx)))
X ((math-nearly-zerop-float x orgx) '(float 0 0))
X (calc-symbolic-mode (signal 'inexact-result nil))
X (t (math-sin-series x 6 4 x (math-neg-float (math-sqr-float x))))))
X)
X
X(defun math-cos-raw-2 (x orgx) ; [F F]
X (cond ((math-nearly-zerop-float x orgx) '(float 1 0))
X (calc-symbolic-mode (signal 'inexact-result nil))
X (t (let ((xnegsqr (math-neg-float (math-sqr-float x))))
X (math-sin-series
X (math-add-float '(float 1 0)
X (math-mul-float xnegsqr '(float 5 -1)))
X 24 5 xnegsqr xnegsqr))))
X)
X
X(defun math-sin-series (sum nfac n x xnegsqr)
X (math-working "sin" sum)
X (let* ((nextx (math-mul-float x xnegsqr))
X (nextsum (math-add-float sum (math-div-float nextx
X (math-float nfac)))))
X (if (math-nearly-equal-float sum nextsum)
X sum
X (math-sin-series nextsum (math-mul nfac (* n (1+ n)))
X (+ n 2) nextx xnegsqr)))
X)
X
X
X;;; Inverse sine, cosine, tangent.
X
X(defun math-arcsin (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2
X (math-from-radians (math-arcsin-raw (math-float x)))))
X ((and (eq (car x) 'sdev)
X (or (not (math-constp (nth 1 x)))
X (not (Math-lessp 1 (math-abs (nth 1 x))))))
X (math-make-sdev (math-arcsin (nth 1 x))
X (math-from-radians
X (math-div (nth 2 x)
X (math-sqrt
X (math-sub 1 (math-sqr (nth 1 x))))))))
X ((and (eq (car x) 'intv) (math-constp x))
X (math-sort-intv (nth 1 x)
X (math-arcsin (nth 2 x))
X (math-arcsin (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-arcsin x)))
X)
X(fset 'calcFunc-arcsin (symbol-function 'math-arcsin))
X
X(defun math-arccos (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2
X (math-from-radians (math-arccos-raw (math-float x)))))
X ((and (eq (car x) 'sdev)
X (or (not (math-constp (nth 1 x)))
X (not (Math-lessp 1 (math-abs (nth 1 x))))))
X (math-make-sdev (math-arccos (nth 1 x))
X (math-from-radians
X (math-div (nth 2 x)
X (math-sqrt
X (math-sub 1 (math-sqr (nth 1 x))))))))
X ((and (eq (car x) 'intv) (math-constp x))
X (math-sort-intv (nth 1 x)
X (math-arccos (nth 2 x))
X (math-arccos (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-arccos x)))
X)
X(fset 'calcFunc-arccos (symbol-function 'math-arccos))
X
X(defun math-arctan (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2
X (math-from-radians (math-arctan-raw (math-float x)))))
X ((eq (car x) 'sdev)
X (math-make-sdev (math-arctan (nth 1 x))
X (math-from-radians
X (math-div (nth 2 x)
X (math-add 1 (math-sqr (nth 1 x)))))))
X ((and (eq (car x) 'intv) (math-constp x))
X (math-sort-intv (nth 1 x)
X (math-arctan (nth 2 x))
X (math-arctan (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-arctan x)))
X)
X(fset 'calcFunc-arctan (symbol-function 'math-arctan))
X
X(defun math-arcsin-raw (x) ; [N N]
X (let ((a (math-sqrt-raw (math-sub '(float 1 0) (math-sqr x)))))
X (if (or (memq (car-safe x) '(cplx polar))
X (memq (car-safe a) '(cplx polar)))
X (math-with-extra-prec 2 ; use extra precision for difficult case
X (math-mul '(cplx 0 -1)
X (math-ln-raw (math-add (math-mul '(cplx 0 1) x) a))))
X (math-arctan2-raw x a)))
X)
X
X(defun math-arccos-raw (x) ; [N N]
X (math-sub (math-pi-over-2) (math-arcsin-raw x))
X)
X
X(defun math-arctan-raw (x) ; [N N]
X (cond ((memq (car-safe x) '(cplx polar))
X (math-with-extra-prec 2 ; extra-extra
X (math-mul '(cplx 0 -1)
X (math-ln-raw (math-mul
X (math-add 1 (math-mul '(cplx 0 1) x))
X (math-sqrt-raw
X (math-div 1 (math-add
X 1 (math-sqr x)))))))))
X ((Math-integer-negp (nth 1 x))
X (math-neg-float (math-arctan-raw (math-neg-float x))))
X ((math-zerop x) x)
X ((math-equal-int x 1) (math-pi-over-4))
X ((math-equal-int x -1) (math-neg (math-pi-over-4)))
X (calc-symbolic-mode (signal 'inexact-result nil))
X ((math-lessp-float '(float 414214 -6) x) ; if x > sqrt(2) - 1, reduce
X (if (math-lessp-float '(float 1 0) x)
X (math-sub-float (math-mul-float (math-pi) '(float 5 -1))
X (math-arctan-raw (math-div-float '(float 1 0) x)))
X (math-sub-float (math-mul-float (math-pi) '(float 25 -2))
X (math-arctan-raw (math-div-float
X (math-sub-float '(float 1 0) x)
X (math-add-float '(float 1 0)
X x))))))
X (t (math-arctan-series x 3 x (math-neg-float (math-sqr-float x)))))
X)
X
X(defun math-arctan-series (sum n x xnegsqr)
X (math-working "arctan" sum)
X (let* ((nextx (math-mul-float x xnegsqr))
X (nextsum (math-add-float sum (math-div-float nextx (math-float n)))))
X (if (math-nearly-equal-float sum nextsum)
X sum
X (math-arctan-series nextsum (+ n 2) nextx xnegsqr)))
X)
X
X(defun math-arctan2 (y x) ; [F R R] [Public]
X (if (Math-anglep y)
X (if (Math-anglep x)
X (math-with-extra-prec 2
X (math-from-radians (math-arctan2-raw (math-float y)
X (math-float x))))
X (calc-record-why 'anglep x)
X (list 'calcFunc-arctan2 y x))
X (calc-record-why 'anglep y)
X (list 'calcFunc-arctan2 y x))
X)
X(fset 'calcFunc-arctan2 (symbol-function 'math-arctan2))
X
X(defun math-arctan2-raw (y x) ; [F R R]
X (cond ((math-zerop y)
X (if (math-negp x) (math-pi) 0))
X ((math-zerop x)
X (if (math-posp y)
X (math-pi-over-2)
X (math-neg (math-pi-over-2))))
X ((math-posp x)
X (math-arctan-raw (math-div-float y x)))
X ((math-posp y)
X (math-add-float (math-arctan-raw (math-div-float y x))
X (math-pi)))
X (t
X (math-sub-float (math-arctan-raw (math-div-float y x))
X (math-pi))))
X)
X
X(defun math-arc-sin-cos (x) ; [V N] [Public]
X (if (and (Math-vectorp x)
X (= (length x) 3))
X (math-arctan2 (nth 2 x) (nth 1 x))
X (math-reject-arg x "Two-element vector expected"))
X)
X(fset 'calcFunc-arcsincos (symbol-function 'math-arc-sin-cos))
X
X
X
X;;; Exponential function.
X
X(defun math-exp (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2 (math-exp-raw (math-float x))))
X ((eq (car-safe x) 'sdev)
X (let ((ex (math-exp (nth 1 x))))
X (math-make-sdev ex (math-mul (nth 2 x) ex))))
X ((eq (car-safe x) 'intv)
X (math-make-intv (nth 1 x) (math-exp (nth 2 x)) (math-exp (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-exp x)))
X)
X(fset 'calcFunc-exp (symbol-function 'math-exp))
X
X(defun math-exp-minus-1 (x) ; [N N] [Public]
X (cond ((math-zerop x) '(float 0 0))
X (calc-symbolic-mode (signal 'inexact-result nil))
X ((Math-numberp x)
X (math-with-extra-prec 2
X (let ((x (math-float x)))
X (if (and (eq (car x) 'float)
X (math-lessp-float x '(float 1 0))
X (math-lessp-float '(float -1 0) x))
X (math-exp-minus-1-raw x)
X (math-add (math-exp-raw x) -1)))))
X ((eq (car-safe x) 'sdev)
X (if (math-constp x)
X (let ((ex (math-exp-minus-1 (nth 1 x))))
X (math-make-sdev ex (math-mul (nth 2 x) (math-add ex 1))))
X (math-make-sdev (math-exp-minus-1 (nth 1 x))
X (math-mul (nth 2 x) (math-exp (nth 1 x))))))
X ((eq (car-safe x) 'intv)
X (math-make-intv (nth 1 x)
X (math-exp-minus-1 (nth 2 x))
X (math-exp-minus-1 (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-expm1 x)))
X)
X(fset 'calcFunc-expm1 (symbol-function 'math-exp-minus-1))
X
X(defun math-exp10 (x) ; [N N] [Public]
X (math-pow '(float 1 1) x)
X)
X(fset 'calcFunc-exp10 (symbol-function 'math-exp10))
X
X(defun math-exp-raw (x) ; [N N]
X (cond ((math-zerop x) '(float 1 0))
X (calc-symbolic-mode (signal 'inexact-result nil))
X ((eq (car x) 'cplx)
X (let ((expx (math-exp-raw (nth 1 x)))
X (sc (math-sin-cos-raw (nth 2 x))))
X (list 'cplx
X (math-mul-float expx (cdr sc))
X (math-mul-float expx (car sc)))))
X ((eq (car x) 'polar)
X (let ((xc (math-complex x)))
X (list 'polar
X (math-exp-raw (nth 1 x))
X (nth 2 x))))
X ((or (math-lessp-float '(float 5 -1) x)
X (math-lessp-float x '(float -5 -1)))
X (let* ((two-x (math-mul-float x '(float 2 0)))
X (hint (math-scale-int (nth 1 two-x) (nth 2 two-x)))
X (hfrac (math-sub-float x (math-mul-float (math-float hint)
X '(float 5 -1)))))
X (math-mul-float (math-ipow (math-sqrt-e) hint)
X (math-add-float '(float 1 0)
X (math-exp-minus-1-raw hfrac)))))
X (t (math-add-float '(float 1 0) (math-exp-minus-1-raw x))))
X)
X
X(defun math-exp-minus-1-raw (x) ; [F F]
X (math-exp-series x 2 3 x x)
X)
X
X(defun math-exp-series (sum nfac n xpow x)
X (math-working "exp" sum)
X (let* ((nextx (math-mul-float xpow x))
X (nextsum (math-add-float sum (math-div-float nextx
X (math-float nfac)))))
X (if (math-nearly-equal-float sum nextsum)
X sum
X (math-exp-series nextsum (math-mul nfac n) (1+ n) nextx x)))
X)
X
X
X
X;;; Logarithms.
X
X(defun math-ln (x) ; [N N] [Public]
X (cond ((math-zerop x)
X (math-reject-arg x "Logarithm of zero"))
X ((Math-numberp x)
X (math-with-extra-prec 2 (math-ln-raw (math-float x))))
X ((and (eq (car-safe x) 'sdev)
X (or (not (math-constp (nth 1 x)))
X (math-posp (nth 1 x))))
X (math-make-sdev (math-ln (nth 1 x))
X (math-div (nth 2 x) (nth 1 x))))
X ((and (eq (car-safe x) 'intv) (Math-posp (nth 2 x)))
X (math-make-intv (nth 1 x) (math-ln (nth 2 x)) (math-ln (nth 3 x))))
X ((equal x '(var e var-e))
X 1)
X ((and (eq (car-safe x) '^)
X (equal (nth 1 x) '(var e var-e)))
X (nth 2 x))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-ln x)))
X)
X(fset 'calcFunc-ln (symbol-function 'math-ln))
X
X(defun math-log10 (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2
X (let ((xf (math-float x)))
X (if (eq (nth 1 xf) 0)
X (math-reject-arg x "Logarithm of zero"))
X (if (Math-integer-posp (nth 1 xf))
X (if (eq (nth 1 xf) 1) ; log10(1*10^n) = n
X (math-float (nth 2 xf))
X (let ((xdigs (1- (math-numdigs (nth 1 xf)))))
X (math-add-float
X (math-div-float (math-ln-raw-2
X (list 'float (nth 1 xf) (- xdigs)))
X (math-ln-10))
X (math-float (+ (nth 2 xf) xdigs)))))
X (math-div (math-ln xf) (math-ln-10))))))
X ((and (eq (car-safe x) 'sdev)
X (or (not (math-constp (nth 1 x)))
X (math-posp (nth 1 x))))
X (math-make-sdev (math-log10 (nth 1 x))
X (math-div (nth 2 x)
X (math-mul (nth 1 x) (math-ln 10)))))
X ((and (eq (car-safe x) 'intv) (Math-posp (nth 2 x)))
X (math-make-intv (nth 1 x)
X (math-log10 (nth 2 x))
X (math-log10 (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-log10 x)))
X)
X(fset 'calcFunc-log10 (symbol-function 'math-log10))
X
X(defun calcFunc-pow10 (x)
X (math-pow '(float 1 1) x)
X)
X
X(defun math-log (x b) ; [N N N] [Public]
X (cond ((or (eq b 10) (equal b '(float 1 1)))
X (math-log10 x))
X ((math-zerop x)
X (math-reject-arg x "Logarithm of zero"))
X ((math-zerop b)
X (math-reject-arg b "Logarithm of zero"))
X ((and (Math-numberp x) (Math-numberp b))
X (math-with-extra-prec 2
X (math-div (math-ln-raw (math-float x))
X (math-log-base-raw b))))
X ((and (eq (car-safe x) 'sdev)
X (or (not (math-constp (nth 1 x)))
X (math-posp (nth 1 x)))
X (Math-numberp b))
X (math-make-sdev (math-log (nth 1 x) b)
X (math-div (nth 2 x)
X (math-mul (nth 1 x)
X (math-log-base-raw b)))))
X ((and (eq (car-safe x) 'intv) (Math-posp (nth 2 x)))
X (math-make-intv (nth 1 x)
X (math-log (nth 2 x) b)
X (math-log (nth 3 x) b)))
X (t (if (Math-numberp b)
X (calc-record-why 'numberp x)
X (calc-record-why 'numberp b))
X (list 'calcFunc-log x b)))
X)
X
X(defun calcFunc-log (x &optional b)
X (if b
X (if (or (eq b 10) (equal b '(float 1 1)))
X (math-normalize (list 'calcFunc-log10 x))
X (if (equal b '(var e var-e))
X (math-normalize (list 'calcFunc-ln x))
X (math-log x b)))
X (math-normalize (list 'calcFunc-ln x)))
X)
X(defun calcFunc-ilog (x &optional b)
X (if b
X (if (equal b '(var e var-e))
X (math-normalize (list 'calcFunc-exp x))
X (math-pow b x))
X (math-normalize (list 'calcFunc-exp x)))
X)
X
X
X(defun math-log-base-raw (b) ; [N N]
X (if (not (and (equal (car math-log-base-cache) b)
X (eq (nth 1 math-log-base-cache) calc-internal-prec)))
X (setq math-log-base-cache (list b calc-internal-prec
X (math-ln-raw (math-float b)))))
X (nth 2 math-log-base-cache)
X)
X(setq math-log-base-cache nil)
X
X(defun math-ln-plus-1 (x) ; [N N] [Public]
X (cond ((Math-equal-int x -1) (math-reject-arg x "Logarithm of zero"))
X ((math-zerop x) '(float 0 0))
X (calc-symbolic-mode (signal 'inexact-result nil))
X ((Math-numberp x)
X (math-with-extra-prec 2
X (let ((x (math-float x)))
X (if (and (eq (car x) 'float)
X (math-lessp-float x '(float 5 -1))
X (math-lessp-float '(float -5 -1) x))
X (math-ln-plus-1-raw x)
X (math-ln-raw (math-add-float x '(float 1 0)))))))
X ((and (eq (car-safe x) 'sdev)
X (or (not (math-constp (nth 1 x)))
X (Math-lessp -1 (nth 1 x))))
X (math-make-sdev (math-ln-plus-1 (nth 1 x))
X (math-div (nth 2 x) (math-add (nth 1 x) 1))))
X ((and (eq (car-safe x) 'intv) (Math-posp (nth 2 x)))
X (math-make-intv (nth 1 x)
X (math-ln-plus-1 (nth 2 x))
X (math-ln-plus-1 (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-lnp1 x)))
X)
X(fset 'calcFunc-lnp1 (symbol-function 'math-ln-plus-1))
X
X(defun math-ln-raw (x) ; [N N] --- must be float format!
X (cond ((eq (car-safe x) 'cplx)
X (list 'cplx
X (math-mul-float (math-ln-raw
X (math-add-float (math-sqr-float (nth 1 x))
X (math-sqr-float (nth 2 x))))
X '(float 5 -1))
X (math-arctan2-raw (nth 2 x) (nth 1 x))))
X ((eq (car x) 'polar)
X (math-polar (list 'cplx
X (math-ln-raw (nth 1 x))
X (nth 2 x))))
X ((Math-equal-int x 1)
X '(float 0 0))
X (calc-symbolic-mode (signal 'inexact-result nil))
X ((math-posp (nth 1 x)) ; positive and real
X (let ((xdigs (1- (math-numdigs (nth 1 x)))))
X (math-add-float (math-ln-raw-2 (list 'float (nth 1 x) (- xdigs)))
X (math-mul-float (math-float (+ (nth 2 x) xdigs))
X (math-ln-10)))))
X ((math-zerop x)
X (error "Logarithm of zero"))
X ((eq calc-complex-mode 'polar) ; negative and real
X (math-polar
X (list 'cplx ; negative and real
X (math-ln-raw (math-neg-float x))
X (math-pi))))
X (t (list 'cplx ; negative and real
X (math-ln-raw (math-neg-float x))
X (math-pi))))
X)
X
X(defun math-ln-raw-2 (x) ; [F F]
X (cond ((math-lessp-float '(float 14 -1) x)
X (math-add-float (math-ln-raw-2 (math-mul-float x '(float 5 -1)))
X (math-ln-2)))
X (t ; now .7 < x <= 1.4
X (math-ln-raw-3 (math-div-float (math-sub-float x '(float 1 0))
X (math-add-float x '(float 1 0))))))
X)
X
X(defun math-ln-raw-3 (x) ; [F F]
X (math-mul-float (math-ln-raw-series x 3 x (math-sqr-float x))
X '(float 2 0))
X)
X
X;;; Compute ln((1+x)/(1-x))
X(defun math-ln-raw-series (sum n x xsqr)
X (math-working "log" sum)
X (let* ((nextx (math-mul-float x xsqr))
X (nextsum (math-add-float sum (math-div-float nextx (math-float n)))))
X (if (math-nearly-equal-float sum nextsum)
X sum
X (math-ln-raw-series nextsum (+ n 2) nextx xsqr)))
X)
X
X(defun math-ln-plus-1-raw (x)
X (math-lnp1-series x 2 x (math-neg x))
X)
X
X(defun math-lnp1-series (sum n xpow x)
X (math-working "lnp1" sum)
X (let* ((nextx (math-mul-float xpow x))
X (nextsum (math-add-float sum (math-div-float nextx (math-float n)))))
X (if (math-nearly-equal-float sum nextsum)
X sum
X (math-lnp1-series nextsum (1+ n) nextx x)))
X)
X
X(math-defcache math-ln-10 (float (bigpos 018 684 045 994 092 585 302 2) -21)
X (math-ln-raw-2 '(float 1 1)))
X
X(math-defcache math-ln-2 (float (bigpos 417 309 945 559 180 147 693) -21)
X (math-ln-raw-3 (math-float '(frac 1 3))))
X
X
X
X;;; Hyperbolic functions.
X
X(defun math-sinh (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2
X (let ((expx (math-exp-raw (math-float x))))
X (math-mul (math-add expx (math-div -1 expx)) '(float 5 -1)))))
X ((eq (car-safe x) 'sdev)
X (math-make-sdev (math-sinh (nth 1 x))
X (math-mul (nth 2 x) (math-cosh (nth 1 x)))))
X ((and (eq (car x) 'intv) (math-constp x))
X (math-sort-intv (nth 1 x)
X (math-sinh (nth 2 x))
X (math-sinh (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-sinh x)))
X)
X(fset 'calcFunc-sinh (symbol-function 'math-sinh))
X
X(defun math-cosh (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2
X (let ((expx (math-exp-raw (math-float x))))
X (math-mul (math-add expx (math-div 1 expx)) '(float 5 -1)))))
X ((eq (car-safe x) 'sdev)
X (math-make-sdev (math-cosh (nth 1 x))
X (math-mul (nth 2 x)
X (math-abs (math-sinh (nth 1 x))))))
X ((and (eq (car x) 'intv) (math-constp x))
X (setq x (math-abs x))
X (math-sort-intv (nth 1 x)
X (math-cosh (nth 2 x))
X (math-cosh (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-cosh x)))
X)
X(fset 'calcFunc-cosh (symbol-function 'math-cosh))
X
X(defun math-tanh (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2
X (let* ((expx (math-exp (math-float x)))
X (expmx (math-div 1 expx)))
X (math-div (math-sub expx expmx)
X (math-add expx expmx)))))
X ((eq (car-safe x) 'sdev)
X (math-make-sdev (math-tanh (nth 1 x))
X (math-div (nth 2 x)
X (math-sqr (math-cosh (nth 1 x))))))
X ((and (eq (car x) 'intv) (math-constp x))
X (math-sort-intv (nth 1 x)
X (math-tanh (nth 2 x))
X (math-tanh (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-tanh x)))
X)
X(fset 'calcFunc-tanh (symbol-function 'math-tanh))
X
X(defun math-arcsinh (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2
X (math-ln-raw (math-add x (math-sqrt-raw (math-add (math-sqr x)
X '(float 1 0)))))))
X ((eq (car-safe x) 'sdev)
X (math-make-sdev (math-arcsinh (nth 1 x))
X (math-div (nth 2 x)
X (math-sqrt
X (math-add (math-sqr (nth 1 x)) 1)))))
X ((and (eq (car x) 'intv) (math-constp x))
X (math-sort-intv (nth 1 x)
X (math-arcsinh (nth 2 x))
X (math-arcsinh (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-arcsinh x)))
X)
X(fset 'calcFunc-arcsinh (symbol-function 'math-arcsinh))
X
X(defun math-arccosh (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2
X (if (or t ; need to do this even in the real case!
X (memq (car-safe x) '(cplx polar)))
X (let ((xp1 (math-add 1 x))) ; this gets the branch cuts right
X (math-ln-raw
X (math-add x (math-mul xp1
X (math-sqrt-raw (math-div (math-sub
X x
X '(float 1 0))
X xp1))))))
X (math-ln-raw
X (math-add x (math-sqrt-raw (math-add (math-sqr x)
X '(float -1 0))))))))
X ((and (eq (car-safe x) 'sdev)
X (or (not (math-constp (nth 1 x)))
X (not (Math-lessp (nth 1 x) 1))))
X (math-make-sdev (math-arccosh (nth 1 x))
X (math-div (nth 2 x)
X (math-sqrt
X (math-add (math-sqr (nth 1 x)) -1)))))
X ((and (eq (car x) 'intv) (math-constp x))
X (math-sort-intv (nth 1 x)
X (math-arccosh (nth 2 x))
X (math-arccosh (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-arccosh x)))
X)
X(fset 'calcFunc-arccosh (symbol-function 'math-arccosh))
X
X(defun math-arctanh (x) ; [N N] [Public]
X (cond ((Math-numberp x)
X (math-with-extra-prec 2
X (if (memq (car-safe x) '(cplx polar))
X (math-ln-raw
X (math-mul (math-add 1 x)
X (math-sqrt-raw
X (math-div '(float 1 0) (math-sub 1 (math-sqr x))))))
X (math-mul (math-ln-raw (math-div (math-add '(float 1 0) x)
X (math-sub 1 x)))
X '(float 5 -1)))))
X ((and (eq (car-safe x) 'sdev)
X (or (not (math-constp (nth 1 x)))
X (Math-lessp (math-abs (nth 1 x)) 1)))
X (math-make-sdev (math-arctanh (nth 1 x))
X (math-div (nth 2 x)
X (math-sub 1 (math-sqr (nth 1 x))))))
X ((and (eq (car x) 'intv) (math-constp x))
X (math-sort-intv (nth 1 x)
X (math-arctanh (nth 2 x))
X (math-arctanh (nth 3 x))))
X (t (calc-record-why 'numberp x)
X (list 'calcFunc-arctanh x)))
X)
X(fset 'calcFunc-arctanh (symbol-function 'math-arctanh))
X
X
X;;; Convert A from HMS or degrees to radians.
X(defun math-deg-to-rad (a) ; [R R] [Public]
X (cond ((or (Math-numberp a)
X (eq (car a) 'intv))
X (math-mul a (math-pi-over-180)))
X ((eq (car a) 'hms)
X (math-from-hms a 'rad))
X ((eq (car a) 'sdev)
X (math-make-sdev (math-deg-to-rad (nth 1 a))
X (math-deg-to-rad (nth 2 a))))
X (t (list 'calcFunc-rad a)))
X)
X(fset 'calcFunc-rad (symbol-function 'math-deg-to-rad))
X
X;;; Convert A from HMS or radians to degrees.
X(defun math-rad-to-deg (a) ; [R R] [Public]
X (cond ((or (Math-numberp a)
X (eq (car a) 'intv))
X (math-div a (math-pi-over-180)))
X ((eq (car a) 'hms)
X (math-from-hms a 'deg))
X ((eq (car a) 'sdev)
X (math-make-sdev (math-rad-to-deg (nth 1 a))
X (math-rad-to-deg (nth 2 a))))
X (t (list 'calcFunc-deg a)))
X)
X(fset 'calcFunc-deg (symbol-function 'math-rad-to-deg))
X
X
X
X
X;;;; Number theory.
X
X(defun calcFunc-idiv (a b) ; [I I I] [Public]
X (cond ((and (Math-natnump a) (Math-natnump b) (not (eq b 0)))
X (math-quotient a b))
X ((Math-realp a)
X (if (Math-realp b)
X (let ((calc-prefer-frac t))
X (math-floor (math-div a b)))
X (math-reject-arg b 'realp)))
X ((eq (car-safe a) 'hms)
X (if (eq (car-safe b) 'hms)
X (let ((calc-prefer-frac t))
X (math-floor (math-div a b)))
X (math-reject-arg b 'hmsp)))
X ((and (or (eq (car-safe a) 'intv) (Math-realp a))
X (or (eq (car-safe b) 'intv) (Math-realp b)))
X (math-floor (math-div a b)))
X (t (math-reject-arg a 'anglep)))
X)
X
X(defun calcFunc-fdiv (a b) ; [R I I] [Public]
X (if (Math-num-integerp a)
X (if (Math-num-integerp b)
X (if (Math-zerop b)
X (math-reject-arg a "Division by zero")
X (math-make-frac (math-trunc a) (math-trunc b)))
X (math-reject-arg b 'integerp))
X (math-reject-arg a 'integerp))
X)
X
X(defun math-lcm (a b)
X (let ((g (math-gcd a b)))
X (if (Math-numberp g)
X (math-div (math-mul a b) g)
X (list 'calcFunc-lcm a b)))
X)
X(fset 'calcFunc-lcm (symbol-function 'math-lcm))
X
X(defun math-extended-gcd (a b) ; Knuth section 4.5.2
X (cond
X ((not (Math-integerp a))
X (if (Math-messy-integerp a)
X (math-extended-gcd (math-trunc a) b)
X (calc-record-why 'integerp a)
X (list 'calcFunc-egcd a b)))
X ((not (Math-integerp b))
X (if (Math-messy-integerp b)
X (math-extended-gcd a (math-trunc b))
X (calc-record-why 'integerp b)
X (list 'calcFunc-egcd a b)))
X (t
X (let ((u1 1) (u2 0) (u3 a)
X (v1 0) (v2 1) (v3 b)
X t1 t2 q)
X (while (not (eq v3 0))
X (setq q (math-idivmod u3 v3)
X t1 (math-sub u1 (math-mul v1 (car q)))
X t2 (math-sub u2 (math-mul v2 (car q)))
X u1 v1 u2 v2 u3 v3
X v1 t1 v2 t2 v3 (cdr q)))
X (list 'vec u3 u1 u2))))
X)
X(fset 'calcFunc-egcd (symbol-function 'math-extended-gcd))
X
X
X;;; Factorial and related functions.
X
X(defun math-factorial (n) ; [I I] [F F] [Public]
X (let (temp)
X (cond ((Math-integer-negp n) (list 'calcFunc-fact n))
X ((Math-zerop n) 1)
X ((integerp n) (math-factorial-iter (1- n) 2 1))
X ((and (math-messy-integerp n)
X (Math-lessp (setq temp (math-trunc n)) 100))
X (if (natnump temp)
X (math-with-extra-prec 1
X (math-factorial-iter (1- temp) 2 '(float 1 0)))
X (list 'calcFunc-fact max)))
X ((math-realp n)
X (math-with-extra-prec 3
X (math-gammap1-raw (math-float n))))
X (t (calc-record-why 'realp n)
X (list 'calcFunc-fact n))))
X)
X(fset 'calcFunc-fact (symbol-function 'math-factorial))
X
X(defun math-factorial-iter (count n f)
X (if (= (% n 5) 1)
X (math-working (format "factorial(%d)" (1- n)) f))
X (if (> count 0)
X (math-factorial-iter (1- count) (1+ n) (math-mul n f))
X f)
X)
X
X(math-defcache math-sqrt-two-pi nil
X (math-sqrt (math-two-pi)))
X
X(defun math-gammap1-raw (x) ; compute gamma(1 + x)
X (cond ((math-lessp-float x '(float 1 1))
X (if (math-lessp-float x '(float -10 0))
X (setq x (math-neg-float
X (math-div-float
X (math-pi)
X (math-mul-float (math-gammap1-raw
X (math-add-float (math-neg-float x)
X '(float -1 0)))
X (math-sin-raw
X (math-mul (math-pi) x)))))))
X (let ((xplus1 (math-add-float x '(float 1 0))))
X (math-div-float (math-gammap1-raw xplus1) xplus1)))
X (t ; x now >= 10.0
X (let ((xinv (math-div 1 x))
X (lnx (math-ln-raw x)))
X (math-mul (math-sqrt-two-pi)
X (math-exp-raw
X (math-gamma-series
X (math-sub (math-mul (math-add x '(float 5 -1))
X lnx)
X x)
X xinv
X (math-sqr xinv)
X 2))))))
X)
X
X(defun calcFunc-gamma (x)
X (calcFunc-fact (math-add x -1))
X)
X
X(defun math-gamma-series (sum x xinvsqr n)
X (math-working "gamma" sum)
X (let* ((bn (math-bernoulli-number n)) ; this will always be a "frac" form.
X (next (math-add-float
X sum
X (math-mul-float (math-div-float (math-float (nth 1 bn))
X (math-float (* (nth 2 bn)
X (* n (1- n)))))
X x))))
X (if (math-nearly-equal-float sum next)
X next
X (if (= n 24)
X (progn
X (calc-record-why "Gamma computation stopped early, not all digits may be valid")
X next)
X (math-gamma-series next (math-mul-float x xinvsqr) xinvsqr (+ n 2)))))
X)
X
X(defun math-bernoulli-number (n)
X (if (= n 1)
X '(frac -1 2)
X (if (= (% n 2) 1)
X 0
X (aref '[ 1 (frac 1 6) (frac -1 30) (frac 1 42) (frac -1 30)
X (frac 5 66) (frac -691 2730) (frac 7 6) (frac -3617 510)
X (frac 43867 798) (frac -174611 330) (frac 854513 138)
X (frac (bigneg 91 364 236) 2730) ]
X (/ n 2))))
X)
X;;; To come up with more, we could use this rule:
X;;; Bn = n! bn
X;;; bn = - sum_k=0^n-1 bk / (n-k+1)!
X
X(defun math-double-factorial (n) ; [I I] [F F] [Public]
X (cond ((Math-integer-negp n) (list 'calcFunc-dfact n))
X ((Math-zerop n) 1)
X ((integerp n) (math-double-factorial-iter n (+ 2 (% n 2)) 1))
X ((math-messy-integerp n)
X (let ((temp (math-trunc n)))
X (if (natnump temp)
X (math-with-extra-prec 1
X (math-double-factorial-iter temp (+ 2 (% temp 2))
X '(float 1 0)))
X (list 'calcFunc-dfact max))))
X (t (calc-record-why 'natnump n)
X (list 'calcFunc-dfact n)))
X)
X(fset 'calcFunc-dfact (symbol-function 'math-double-factorial))
X
X(defun math-double-factorial-iter (max n f)
X (if (< (% n 10) 2)
X (math-working (format "dfact(%d)" (- n 2)) f))
X (if (<= n max)
X (math-double-factorial-iter max (+ n 2) (math-mul n f))
X f)
X)
X
X(defun math-permutations (n m) ; [I I I] [F F F] [Public]
X (cond ((and (integerp n) (integerp m) (<= m n) (>= m 0))
X (math-factorial-iter n (1+ (- n m)) 1))
X ((or (not (math-num-integerp n))
X (not (math-num-integerp m)))
X (or (math-realp n) (math-reject-arg n 'realp))
X (or (math-realp m) (math-reject-arg m 'realp))
X (and (math-num-integerp n) (math-negp n) (math-reject-arg n 'range))
X (and (math-num-integerp m) (math-negp m) (math-reject-arg m 'range))
X (math-div (math-factorial n) (math-factorial m)))
X (t
X (let ((tn (math-trunc n))
X (tm (math-trunc m)))
X (or (integerp tn) (math-reject-arg tn 'fixnump))
X (or (integerp tm) (math-reject-arg tm 'fixnump))
X (or (and (<= tm tn) (>= tm 0)) (math-reject-arg tm 'range))
X (math-with-extra-prec 1
X (math-factorial-iter tm (1+ (- tn tm)) '(float 1 0))))))
X)
X(fset 'calcFunc-perm (symbol-function 'math-permutations))
X
X(defun math-choose (n m) ; [I I I] [F F F] [Public]
X (cond ((and (integerp n) (integerp m) (<= m n) (>= m 0))
X (math-choose-iter m n 1 1))
X ((not (math-realp n))
X (math-reject-arg n 'realp))
X ((not (math-realp m))
X (math-reject-arg m 'realp))
X ((not (math-num-integerp m))
X (if (and (math-num-integerp n) (math-negp n))
X (list 'calcFunc-choose n m)
X (math-div (math-factorial (math-float n))
X (math-mul (math-factorial m)
X (math-factorial (math-sub n m))))))
X ((math-negp m) 0)
X ((math-negp n)
X (let ((val (math-choose (math-add (math-add n m) -1) m)))
X (if (math-evenp (math-trunc m))
X val
X (math-neg val))))
X ((and (math-num-integerp n)
X (Math-lessp n m))
X 0)
X (t
X (let ((tm (math-trunc m)))
X (or (integerp tm) (math-reject-arg tm 'fixnump))
X (if (> tm 100)
X (math-div (math-factorial (math-float n))
X (math-mul (math-factorial (math-float m))
X (math-factorial (math-float
X (math-sub n m)))))
X (math-with-extra-prec 1
X (math-choose-float-iter tm n 1 '(float 1 0)))))))
X)
X(fset 'calcFunc-choose (symbol-function 'math-choose))
X
X(defun math-choose-iter (m n i c)
X (if (= (% i 5) 1)
X (math-working (format "choose(%d)" (1- i)) c))
X (if (<= i m)
X (math-choose-iter m (1- n) (1+ i)
X (math-quotient (math-mul c n) i))
X c)
X)
X
X(defun math-choose-float-iter (count n i c)
X (if (= (% i 5) 1)
X (math-working (format "choose(%d)" (1- i)) c))
X (if (> count 0)
X (math-choose-float-iter (1- count) (math-sub n 1) (1+ i)
X (math-div (math-mul c n) i))
X c)
X)
X
X
X;;; Produce a random digit in the range 0..999.
X;;; Avoid various pitfalls that may lurk in the built-in (random) function!
X(defun math-random-digit ()
X (prog1
X (% (lsh (random math-first-random-flag) -4) 1000)
X (setq math-first-random-flag nil))
X)
X(setq math-first-random-flag t)
X
X;;; Produce an N-digit random integer.
X(defun math-random-digits (n)
X (cond ((<= n 6)
X (math-scale-right (+ (* (math-random-digit) 1000) (math-random-digit))
X (- 6 n)))
X (t (let* ((slop (% (- 900003 n) 3))
X (i (/ (+ n slop) 3))
X (digs nil))
X (while (> i 0)
X (setq digs (cons (math-random-digit) digs)
X i (1- i)))
X (math-normalize (math-scale-right (cons 'bigpos digs)
X slop)))))
X)
X
X;;; Produce a uniformly-distributed random float 0 <= N < 1.
X(defun math-random-float ()
X (math-make-float (math-random-digits calc-internal-prec)
X (- calc-internal-prec))
X)
X
X;;; Produce a Gaussian-distributed random float with mean=0, sigma=1.
X(defun math-gaussian-float ()
X (math-with-extra-prec 2
X (if (and math-gaussian-cache
X (= (car math-gaussian-cache) calc-internal-prec))
X (prog1
X (cdr math-gaussian-cache)
X (setq math-gaussian-cache nil))
X (let* ((v1 (math-add (math-mul (math-random-float) 2) -1))
X (v2 (math-add (math-mul (math-random-float) 2) -1))
X (r (math-add (math-sqr v1) (math-sqr v2))))
X (while (or (not (Math-lessp r 1)) (math-zerop r))
X (setq v1 (math-add (math-mul (math-random-float) 2) -1)
X v2 (math-add (math-mul (math-random-float) 2) -1)
X r (math-add (math-sqr v1) (math-sqr v2))))
X (let ((fac (math-sqrt (math-mul (math-div (math-ln r) r) -2))))
X (setq math-gaussian-cache (cons calc-internal-prec
X (math-mul v1 fac)))
X (math-mul v2 fac)))))
X)
X(setq math-gaussian-cache nil)
X
X;;; Produce a random integer or real 0 <= N < MAX.
X(defun math-random (max)
X (cond ((Math-zerop max)
X (math-gaussian-float))
X ((Math-integerp max)
X (let* ((digs (math-numdigs max))
X (r (math-random-digits (+ digs 3))))
X (math-mod r max)))
X ((Math-realp max)
X (math-mul (math-random-float) max))
X ((and (eq (car max) 'intv) (math-constp max)
X (Math-lessp (nth 2 max) (nth 3 max)))
X (if (math-floatp max)
X (let ((val (math-add (math-mul (math-random-float)
X (math-sub (nth 3 max) (nth 2 max)))
X (nth 2 max))))
X (if (or (and (memq (nth 1 max) '(0 1)) ; almost not worth
X (math-equal val (nth 2 max))) ; checking!
X (and (memq (nth 1 max) '(0 2))
X (math-equal val (nth 3 max))))
X (math-random max)
X val))
X (let ((lo (if (memq (nth 1 max) '(0 1))
X (math-add (nth 2 max) 1) (nth 2 max)))
X (hi (if (memq (nth 1 max) '(1 3))
X (math-add (nth 3 max) 1) (nth 3 max))))
X (if (Math-lessp lo hi)
X (math-add (math-random (math-sub hi lo)) lo)
X (math-reject-arg max "Empty interval")))))
X (t (math-reject-arg max 'realp)))
X)
X(fset 'calcFunc-random (symbol-function 'math-random))
X
X
X;;; Check if the integer N is prime. [X I]
X;;; Return (nil) if non-prime,
X;;; (nil N) if non-prime with known factor N,
X;;; (nil unknown) if non-prime with no known factors,
X;;; (t) if prime,
X;;; (maybe N P) if probably prime (after N iters with probability P%)
X(defun math-prime-test (n iters)
X (if (and (Math-vectorp n) (cdr n))
X (setq n (nth (1- (length n)) n)))
X (if (Math-messy-integerp n)
X (setq n (math-trunc n)))
X (let ((res))
X (while (> iters 0)
X (setq res
X (cond ((and (integerp n) (<= n 5003))
X (list (= (math-next-small-prime n) n)))
X ((not (Math-integerp n))
X (error "Argument must be an integer"))
X ((Math-integer-negp n)
X '(nil))
X ((Math-natnum-lessp n '(bigpos 0 0 8))
X (setq n (math-fixnum n))
X (let ((i -1) v)
X (while (and (> (% n (setq v (aref math-primes-table
X (setq i (1+ i)))))
X 0)
X (< (* v v) n)))
X (if (= (% n v) 0)
X (list nil v)
X '(t))))
X ((not (equal n (car math-prime-test-cache)))
X (cond ((= (% (nth 1 n) 2) 0) '(nil 2))
X ((= (% (nth 1 n) 5) 0) '(nil 5))
X (t (let ((dig (cdr n)) (sum 0))
X (while dig
X (if (cdr dig)
X (setq sum (% (+ (+ sum (car dig))
X (* (nth 1 dig) 1000))
X 111111)
X dig (cdr (cdr dig)))
X (setq sum (% (+ sum (car dig)) 111111)
X dig nil)))
X (cond ((= (% sum 3) 0) '(nil 3))
X ((= (% sum 7) 0) '(nil 7))
X ((= (% sum 11) 0) '(nil 11))
X ((= (% sum 13) 0) '(nil 13))
X ((= (% sum 37) 0) '(nil 37))
X (t
X (setq math-prime-test-cache-k 1
X math-prime-test-cache-q
X (math-div2 n)
X math-prime-test-cache-nm1
X (math-add n -1))
X (while (math-evenp
X math-prime-test-cache-q)
X (setq math-prime-test-cache-k
X (1+ math-prime-test-cache-k)
X math-prime-test-cache-q
X (math-div2
X math-prime-test-cache-q)))
X (setq iters (1+ iters))
X (list 'maybe
X 0
X (math-sub
X 100
X (math-div
X '(float 232 0)
X (math-numdigs n))))))))))
X ((not (eq (car (nth 1 math-prime-test-cache)) 'maybe))
X (nth 1 math-prime-test-cache))
X (t ; Fermat step
X (let* ((x (math-add (math-random (math-add n -2)) 2))
X (y (math-pow-mod x math-prime-test-cache-q n))
X (j 0))
X (while (and (not (eq y 1))
X (not (equal y math-prime-test-cache-nm1))
X (< (setq j (1+ j)) math-prime-test-cache-k))
X (setq y (math-mod (math-mul y y) n)))
X (if (or (equal y math-prime-test-cache-nm1)
X (and (eq y 1) (eq j 0)))
X (list 'maybe
X (1+ (nth 1 (nth 1 math-prime-test-cache)))
X (math-mul (nth 2 (nth 1 math-prime-test-cache))
X '(float 25 -2)))
X '(nil unknown))))))
X (setq math-prime-test-cache (list n res)
X iters (if (eq (car res) 'maybe)
X (1- iters)
X 0)))
X res)
X)
X(defvar math-prime-test-cache '(-1))
X
X;;; Theory: summing base-10^6 digits modulo 111111 is "casting out 999999s".
X;;; Initial probability that N is prime is 1/ln(N) = log10(e)/log10(N).
X;;; After culling [2,3,5,7,11,13,37], probability of primality is 5.36 x more.
X;;; Initial reported probability of non-primality is thus 100% - this.
X;;; Each Fermat step multiplies this probability by 25%.
X;;; The Fermat step is algorithm P from Knuth section 4.5.4.
X
X
X(defun math-prime-factors (n)
X (setq math-prime-factors-finished t)
X (if (Math-messy-integerp n)
X (setq n (math-trunc n)))
X (if (and (Math-natnump n) (Math-natnum-lessp 2 n))
X (let (factors res p (i 0))
X (while (and (not (eq n 1))
X (< i (length math-primes-table)))
X (setq p (aref math-primes-table i))
X (while (eq (cdr (setq res (cond ((eq n p) (cons 1 0))
X ((eq n 1) (cons 0 1))
X ((consp n) (math-idivmod n p))
X (t (cons (/ n p) (% n p))))))
X 0)
X (math-working "factor" p)
X (setq factors (nconc factors (list p))
X n (car res)))
X (or (eq n 1)
X (Math-natnum-lessp p (car res))
X (setq factors (nconc factors (list n))
X n 1))
X (setq i (1+ i)))
X (or (setq math-prime-factors-finished (eq n 1))
X (setq factors (nconc factors (list n))))
X (cons 'vec factors))
X (calc-record-why 'integerp n)
X (list 'calcFunc-prfac n))
X)
X(fset 'calcFunc-prfac (symbol-function 'math-prime-factors))
X
X(defun math-totient (n)
X (if (Math-messy-integerp n)
X (setq n (math-trunc n)))
X (if (Math-natnump n)
X (if (Math-natnum-lessp n 2)
X (if (Math-negp n)
X (math-totient (math-abs n))
X n)
X (let ((factors (cdr (math-prime-factors n)))
X p)
X (if math-prime-factors-finished
X (progn
X (while factors
X (setq p (car factors)
X n (math-mul (math-div n p) (math-add p -1)))
X (while (equal p (car factors))
X (setq factors (cdr factors))))
X n)
X (calc-record-why "Number too big to factor" n)
X (list 'calcFunc-totient n))))
X (calc-record-why 'natnump n)
X (list 'calcFunc-totient n))
X)
X(fset 'calcFunc-totient (symbol-function 'math-totient))
X
X(defun math-moebius (n)
X (if (Math-messy-integerp n)
X (setq n (math-trunc n)))
X (if (and (Math-natnump n) (not (eq n 0)))
X (if (Math-natnum-lessp n 2)
X (if (Math-negp n)
X (math-moebius (math-abs n))
X 1)
X (let ((factors (cdr (math-prime-factors n)))
X (mu 1))
X (if math-prime-factors-finished
X (progn
X (while factors
X (setq mu (if (equal (car factors) (nth 1 factors))
X 0 (math-neg mu))
X factors (cdr factors)))
X mu)
X (calc-record-why "Number too big to factor" n)
X (list 'calcFunc-moebius n))))
X (calc-record-why 'natnump n)
X (list 'calcFunc-moebius n))
X)
X(fset 'calcFunc-moebius (symbol-function 'math-moebius))
X
X
X(defun math-next-prime (n iters)
X (if (Math-integerp n)
X (if (Math-integer-negp n)
X 2
X (if (and (integerp n) (< n 5003))
X (math-next-small-prime (1+ n))
X (if (math-evenp n)
X (setq n (math-add n -1)))
X (let (res)
X (while (not (car (setq res (math-prime-test
X (setq n (math-add n 2)) iters)))))
X (if (and calc-verbose-nextprime
X (eq (car res) 'maybe))
X (calc-report-prime-test res)))
X n))
X (if (Math-realp n)
X (math-next-prime (math-trunc n) iters)
X (math-reject-arg n 'integerp)))
X)
X(fset 'calcFunc-nextprime (symbol-function 'math-next-prime))
X(setq calc-verbose-nextprime nil)
X
X(defun math-prev-prime (n iters)
X (if (Math-integerp n)
X (if (Math-lessp n 4)
X 2
X (if (math-evenp n)
X (setq n (math-add n 1)))
X (let (res)
X (while (not (car (setq res (math-prime-test
X (setq n (math-add n -2)) iters)))))
X (if (and calc-verbose-nextprime
X (eq (car res) 'maybe))
X (calc-report-prime-test res)))
X n)
X (if (Math-realp n)
X (math-prev-prime (math-ceiling n) iters)
X (math-reject-arg n 'integerp)))
X)
X(fset 'calcFunc-prevprime (symbol-function 'math-prev-prime))
X
X(defun math-next-small-prime (n)
X (if (and (integerp n) (> n 2))
X (let ((lo -1)
X (hi (length math-primes-table))
X mid)
X (while (> (- hi lo) 1)
X (if (> n (aref math-primes-table
X (setq mid (ash (+ lo hi) -1))))
X (setq lo mid)
X (setq hi mid)))
X (aref math-primes-table hi))
X 2)
X)
X
X(defconst math-primes-table
X [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89
X 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181
X 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277
X 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383
X 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487
X 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601
X 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709
X 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827
X 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947
X 953 967 971 977 983 991 997 1009 1013 1019 1021 1031 1033 1039 1049
X 1051 1061 1063 1069 1087 1091 1093 1097 1103 1109 1117 1123 1129 1151
SHAR_EOF
echo "End of part 8"
echo "File calc-ext.el is continued in part 9"
echo "9" > s2_seq_.tmp
exit 0
More information about the Comp.sources.misc
mailing list