Trailing-Edge - PDP-10 Archives - clisp - clisp/upsala/spirrat.clisp
There are no other files named spirrat.clisp in the archive.
;;; This is a -*-Lisp-*- file.
;;; **********************************************************************
;;; This code was written as part of the Spice Lisp project at
;;; Carnegie-Mellon University, and has been placed in the public domain.
;;; If you want to use this code or any part of Spice Lisp, please contact
;;; Scott Fahlman (FAHLMAN@CMUC). 
;;; **********************************************************************
;;; Functions to implement irrational functions for Spice Lisp 
;;; Written by David Adam.
;;; Maintained by Steven Handerson.
;;; The irrational functions are part of the standard Spicelisp environment.
;;; **********************************************************************

(in-package 'lisp)

(export '(expt isqrt asinh acosh atanh pi))

;;; Integer square root - (<= (expt result 2) input).
;;; Performs in (log input) time.

;;; Successively approximates the result using two bounds and their average,
;;; repeated until the bounds differ by at most 1 (for input=1, both start
;;; equal).

(defun isqrt (x)
  "Returns the integer square root; ie. (<= (expt result 2) input)."
  (if (and (integerp x) (not (minusp x)))
      (if (zerop  x) 0
	  (do* ((p () (<= (* m m) x))
		(b 1 (if p m b))
		(h x (if p h m))
		(m (ash x -1) (ash (+ b h) -1)))
	       ((<= h (1+ b)) b)))
      (error "Isqrt: ~S argument must be a nonnegative integer" x)))
;;; Function calculates the value of x raised to the nth power.
;;; This function calculates the successive squares of base,
;;; storing them in newbase, halving n at the same time.  If
;;; n is odd total is multiplied by base, at any given time (fix later)

;(proclaim '(inline intexp))

(defun intexp (base power)
  (cond ((minusp power)
	 (/ (intexp base (- power))))
	((and (rationalp base)
	      (not (integerp base)))  ; Could be a make-rational.
	 (/ (intexp (numerator base) power)
	    (intexp (denominator base) power)))
	((and (integerp base) (= base 2))
	 (ash 1 power))
	(t (do ((nextn (ash power -1) (ash power -1))
		(total (if (oddp power) base 1)
		       (if (oddp power) (* base total) total)))
	       ((zerop nextn) total)
	     (setq base (* base base))
	     (setq power nextn)))))

;;; This function calculates x raised to the nth power.  It separates
;;; the  cases by the type of n, for efficiency reasons, as powers can
;;; be calculated more efficiently if n is a positive integer,  Therefore,
;;; All integer values of n are calculated as positive integers, and
;;; inverted if negative.

(defun expt (x n)
  "Returns X raised to the Nth power."
  (cond ((and (rationalp x) (integerp n)) (intexp x n))
	((zerop x) (if (plusp n) x
		       (error "~A to a non-positive power ~A." x n)))
	((and (not (integerp n)) (minusp x))
	 (error "Negative number ~A to non-integral power ~A." x n))
	(t (%sp-expt x n))))
;;; The inverse hyperbolic functions will be coded by definition like
;;; the hyperbolic functions.

(defun asinh (x)
  "Returns the hyperbolic arc sine of the argument."
  (log (+ x (sqrt (+ (* x x) 1)))))

(defun acosh (x)
  "Returns the hyperbolic arc cosine of the argument."
  (if (plusp x)
      (log (+ x (sqrt (- (* x x) 1))))
      (error "~S argument out of range." x)))

(defun atanh (x)
  "Returns the hyperbolic arc tangent of the argument."
  (if (< -1 x 1)
      (* 0.5 (log (/ (1+ x) (- 1 x))))
      (error "~S argument out of range." x)))

;;this file gets loaded twice.  We unbind PI so that we won't get
;; a complaint the second time that it is already bound.
(makunbound 'pi)
(defconstant pi 3.1415926535897932384L0 "pi, as a long real.")