X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Ffloat.lisp;h=14c1a790599dd4fe4bcde5729cebcaaf703c01d6;hb=1c91b0bc7eb814af6a8c58a99a83a024716138e8;hp=6e71f91d4382bac1e030f738385bbb60fe8c8469;hpb=c8af15e61b030c8d4b0e950bc9b7618530044618;p=sbcl.git diff --git a/src/code/float.lisp b/src/code/float.lisp index 6e71f91..14c1a79 100644 --- a/src/code/float.lisp +++ b/src/code/float.lisp @@ -1,7 +1,7 @@ -;;;; This file contains the definitions of float specific number +;;;; This file contains the definitions of float-specific number ;;;; support (other than irrational stuff, which is in irrat.) There is ;;;; code in here that assumes there are only two float formats: IEEE -;;;; single and double. (Long-float support has been added, but bugs +;;;; single and double. (LONG-FLOAT support has been added, but bugs ;;;; may still remain due to old code which assumes this dichotomy.) ;;;; This software is part of the SBCL system. See the README file for @@ -19,9 +19,10 @@ (eval-when (:compile-toplevel :load-toplevel :execute) -;;; These functions let us create floats from bits with the significand -;;; uniformly represented as an integer. This is less efficient for double -;;; floats, but is more convenient when making special values, etc. +;;; These functions let us create floats from bits with the +;;; significand uniformly represented as an integer. This is less +;;; efficient for double floats, but is more convenient when making +;;; special values, etc. (defun single-from-bits (sign exp sig) (declare (type bit sign) (type (unsigned-byte 24) sig) (type (unsigned-byte 8) exp)) @@ -33,7 +34,8 @@ (declare (type bit sign) (type (unsigned-byte 53) sig) (type (unsigned-byte 11) exp)) (make-double-float (dpb exp sb!vm:double-float-exponent-byte - (dpb (ash sig -32) sb!vm:double-float-significand-byte + (dpb (ash sig -32) + sb!vm:double-float-significand-byte (if (zerop sign) 0 -1))) (ldb (byte 32 0) sig))) #!+(and long-float x86) @@ -43,7 +45,7 @@ (make-long-float (logior (ash sign 15) exp) (ldb (byte 32 32) sig) (ldb (byte 32 0) sig))) - + ) ; EVAL-WHEN ;;;; float parameters @@ -54,12 +56,12 @@ (defconstant least-negative-short-float least-negative-single-float) (defconstant least-positive-double-float (double-from-bits 0 0 1)) #!-long-float -(defconstant least-positive-long-float least-positive-double-float) +(defconstant least-positive-long-float (double-from-bits 0 0 1)) #!+(and long-float x86) (defconstant least-positive-long-float (long-from-bits 0 0 1)) (defconstant least-negative-double-float (double-from-bits 1 0 1)) #!-long-float -(defconstant least-negative-long-float least-negative-double-float) +(defconstant least-negative-long-float (double-from-bits 1 0 1)) #!+(and long-float x86) (defconstant least-negative-long-float (long-from-bits 1 0 1)) @@ -119,8 +121,10 @@ ;;; We don't want to do these DEFCONSTANTs at cross-compilation time, ;;; because the cross-compilation host might not support floating -;;; point infinities. -(eval-when (:load-toplevel :execute) +;;; point infinities. Putting them inside a LET removes +;;; toplevel-formness, so that any EVAL-WHEN trickiness in the +;;; DEFCONSTANT forms is suppressed. +(let () (defconstant single-float-positive-infinity (single-from-bits 0 (1+ sb!vm:single-float-normal-exponent-max) 0)) (defconstant short-float-positive-infinity single-float-positive-infinity) @@ -143,7 +147,7 @@ (defconstant long-float-negative-infinity (long-from-bits 1 (1+ sb!vm:long-float-normal-exponent-max) (ash sb!vm:long-float-hidden-bit 32))) -) ; EVAL-WHEN +) ; LET-to-suppress-possible-EVAL-WHENs (defconstant single-float-epsilon (single-from-bits 0 (- sb!vm:single-float-bias @@ -192,59 +196,60 @@ (and (zerop (ldb sb!vm:long-float-exponent-byte (long-float-exp-bits x))) (not (zerop x)))))) -(macrolet ((def-frob (name doc single double #!+(and long-float x86) long) - `(defun ,name (x) - ,doc - (number-dispatch ((x float)) - ((single-float) - (let ((bits (single-float-bits x))) - (and (> (ldb sb!vm:single-float-exponent-byte bits) - sb!vm:single-float-normal-exponent-max) - ,single))) - ((double-float) - (let ((hi (double-float-high-bits x)) - (lo (double-float-low-bits x))) - (declare (ignorable lo)) - (and (> (ldb sb!vm:double-float-exponent-byte hi) - sb!vm:double-float-normal-exponent-max) - ,double))) - #!+(and long-float x86) - ((long-float) - (let ((exp (long-float-exp-bits x)) - (hi (long-float-high-bits x)) - (lo (long-float-low-bits x))) - (declare (ignorable lo)) - (and (> (ldb sb!vm:long-float-exponent-byte exp) - sb!vm:long-float-normal-exponent-max) - ,long))))))) - - (def-frob float-infinity-p - "Return true if the float X is an infinity (+ or -)." - (zerop (ldb sb!vm:single-float-significand-byte bits)) - (and (zerop (ldb sb!vm:double-float-significand-byte hi)) - (zerop lo)) - #!+(and long-float x86) - (and (zerop (ldb sb!vm:long-float-significand-byte hi)) - (zerop lo))) - - (def-frob float-nan-p - "Return true if the float X is a NaN (Not a Number)." - (not (zerop (ldb sb!vm:single-float-significand-byte bits))) - (or (not (zerop (ldb sb!vm:double-float-significand-byte hi))) - (not (zerop lo))) - #!+(and long-float x86) - (or (not (zerop (ldb sb!vm:long-float-significand-byte hi))) - (not (zerop lo)))) - - (def-frob float-trapping-nan-p - "Return true if the float X is a trapping NaN (Not a Number)." - (zerop (logand (ldb sb!vm:single-float-significand-byte bits) - sb!vm:single-float-trapping-nan-bit)) - (zerop (logand (ldb sb!vm:double-float-significand-byte hi) - sb!vm:double-float-trapping-nan-bit)) - #!+(and long-float x86) - (zerop (logand (ldb sb!vm:long-float-significand-byte hi) - sb!vm:long-float-trapping-nan-bit)))) +(defmacro !define-float-dispatching-function + (name doc single double #!+(and long-float x86) long) + `(defun ,name (x) + ,doc + (number-dispatch ((x float)) + ((single-float) + (let ((bits (single-float-bits x))) + (and (> (ldb sb!vm:single-float-exponent-byte bits) + sb!vm:single-float-normal-exponent-max) + ,single))) + ((double-float) + (let ((hi (double-float-high-bits x)) + (lo (double-float-low-bits x))) + (declare (ignorable lo)) + (and (> (ldb sb!vm:double-float-exponent-byte hi) + sb!vm:double-float-normal-exponent-max) + ,double))) + #!+(and long-float x86) + ((long-float) + (let ((exp (long-float-exp-bits x)) + (hi (long-float-high-bits x)) + (lo (long-float-low-bits x))) + (declare (ignorable lo)) + (and (> (ldb sb!vm:long-float-exponent-byte exp) + sb!vm:long-float-normal-exponent-max) + ,long)))))) + +(!define-float-dispatching-function float-infinity-p + "Return true if the float X is an infinity (+ or -)." + (zerop (ldb sb!vm:single-float-significand-byte bits)) + (and (zerop (ldb sb!vm:double-float-significand-byte hi)) + (zerop lo)) + #!+(and long-float x86) + (and (zerop (ldb sb!vm:long-float-significand-byte hi)) + (zerop lo))) + +(!define-float-dispatching-function float-nan-p + "Return true if the float X is a NaN (Not a Number)." + (not (zerop (ldb sb!vm:single-float-significand-byte bits))) + (or (not (zerop (ldb sb!vm:double-float-significand-byte hi))) + (not (zerop lo))) + #!+(and long-float x86) + (or (not (zerop (ldb sb!vm:long-float-significand-byte hi))) + (not (zerop lo)))) + +(!define-float-dispatching-function float-trapping-nan-p + "Return true if the float X is a trapping NaN (Not a Number)." + (zerop (logand (ldb sb!vm:single-float-significand-byte bits) + sb!vm:single-float-trapping-nan-bit)) + (zerop (logand (ldb sb!vm:double-float-significand-byte hi) + sb!vm:double-float-trapping-nan-bit)) + #!+(and long-float x86) + (zerop (logand (ldb sb!vm:long-float-significand-byte hi) + sb!vm:long-float-trapping-nan-bit))) ;;; If denormalized, use a subfunction from INTEGER-DECODE-FLOAT to find the ;;; actual exponent (and hence how denormalized it is), otherwise we just @@ -252,7 +257,7 @@ #!-sb-fluid (declaim (maybe-inline float-precision)) (defun float-precision (f) #!+sb-doc - "Returns a non-negative number of significant digits in its float argument. + "Return a non-negative number of significant digits in its float argument. Will be less than FLOAT-DIGITS if denormalized or zero." (macrolet ((frob (digits bias decode) `(cond ((zerop f) 0) @@ -277,9 +282,9 @@ (defun float-sign (float1 &optional (float2 (float 1 float1))) #!+sb-doc - "Returns a floating-point number that has the same sign as - float1 and, if float2 is given, has the same absolute value - as float2." + "Return a floating-point number that has the same sign as + FLOAT1 and, if FLOAT2 is given, has the same absolute value + as FLOAT2." (declare (float float1 float2)) (* (if (etypecase float1 (single-float (minusp (single-float-bits float1))) @@ -308,9 +313,7 @@ (defun float-radix (x) #!+sb-doc - "Returns (as an integer) the radix b of its floating-point - argument." - (declare (type float x) (ignore x)) + "Return (as an integer) the radix b of its floating-point argument." 2) ;;;; INTEGER-DECODE-FLOAT and DECODE-FLOAT @@ -357,7 +360,7 @@ (t (values (logior sig sb!vm:single-float-hidden-bit) biased sign))))) -;;; Like INTEGER-DECODE-SINGLE-DENORM, only doubly so. +;;; like INTEGER-DECODE-SINGLE-DENORM, only doubly so (defun integer-decode-double-denorm (x) (declare (type double-float x)) (let* ((high-bits (double-float-high-bits (abs x))) @@ -389,7 +392,7 @@ (truly-the fixnum (- biased extra-bias)) sign))))) -;;; Like INTEGER-DECODE-SINGLE-FLOAT, only doubly so. +;;; like INTEGER-DECODE-SINGLE-FLOAT, only doubly so (defun integer-decode-double-float (x) (declare (double-float x)) (let* ((abs (abs x)) @@ -468,7 +471,7 @@ ;;; Dispatch to the correct type-specific i-d-f function. (defun integer-decode-float (x) #!+sb-doc - "Returns three values: + "Return three values: 1) an integer representation of the significand. 2) the exponent for the power of 2 that the significand must be multiplied by to get the actual value. This differs from the DECODE-FLOAT exponent @@ -521,7 +524,7 @@ bits)) biased sign))))) -;;; Like DECODE-SINGLE-DENORM, only doubly so. +;;; like DECODE-SINGLE-DENORM, only doubly so (defun decode-double-denorm (x) (declare (double-float x)) (multiple-value-bind (sig exp sign) (integer-decode-double-denorm x) @@ -534,7 +537,7 @@ (truly-the fixnum (+ exp sb!vm:double-float-digits)) (float sign x)))) -;;; Like DECODE-SINGLE-FLOAT, only doubly so. +;;; like DECODE-SINGLE-FLOAT, only doubly so (defun decode-double-float (x) (declare (double-float x)) (let* ((abs (abs x)) @@ -593,7 +596,7 @@ ;;; Dispatch to the appropriate type-specific function. (defun decode-float (f) #!+sb-doc - "Returns three values: + "Return three values: 1) a floating-point number representing the significand. This is always between 0.5 (inclusive) and 1.0 (exclusive). 2) an integer representing the exponent. @@ -715,7 +718,7 @@ ;;; Dispatch to the correct type-specific scale-float function. (defun scale-float (f ex) #!+sb-doc - "Returns the value (* f (expt (float 2 f) ex)), but with no unnecessary loss + "Return the value (* f (expt (float 2 f) ex)), but with no unnecessary loss of precision or overflow." (number-dispatch ((f float)) ((single-float) @@ -824,9 +827,9 @@ (incf scale))))))) #| -These might be useful if we ever have a machine w/o float/integer conversion -hardware. For now, we'll use special ops that uninterruptibly frob the -rounding modes & do ieee round-to-integer. +These might be useful if we ever have a machine without float/integer +conversion hardware. For now, we'll use special ops that +uninterruptibly frob the rounding modes & do ieee round-to-integer. ;;; The compiler compiles a call to this when we are doing %UNARY-TRUNCATE ;;; and the result is known to be a fixnum. We can avoid some generic @@ -858,19 +861,19 @@ rounding modes & do ieee round-to-integer. (exp (ldb sb!vm:double-float-exponent-byte hi-bits)) (frac (logior (ldb sb!vm:double-float-significand-byte hi-bits) sb!vm:double-float-hidden-bit)) - (shift (- exp (- sb!vm:double-float-digits sb!vm:word-bits) + (shift (- exp (- sb!vm:double-float-digits sb!vm:n-word-bits) sb!vm:double-float-bias))) (when (> exp sb!vm:double-float-normal-exponent-max) (error 'floating-point-invalid-operation :operator 'truncate :operands (list x))) - (if (<= shift (- sb!vm:word-bits sb!vm:double-float-digits)) + (if (<= shift (- sb!vm:n-word-bits sb!vm:double-float-digits)) 0 (let* ((res-hi (ash frac shift)) (res (if (plusp shift) (logior res-hi (the fixnum (ash (double-float-low-bits x) - (- shift sb!vm:word-bits)))) + (- shift sb!vm:n-word-bits)))) res-hi))) (declare (type (unsigned-byte 31) res-hi res)) (if (minusp hi-bits)