From: Paul Khuong Date: Mon, 26 Apr 2010 21:12:33 +0000 (+0000) Subject: 1.0.37.62: More robust reciprocal exactitude test X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=16169f9db2c4b14218b541884b97109988ef2e21;p=sbcl.git 1.0.37.62: More robust reciprocal exactitude test * Trying to divide by tiny powers of 2 could result in compile-time errors. --- diff --git a/NEWS b/NEWS index 5499d30..4805c10 100644 --- a/NEWS +++ b/NEWS @@ -62,7 +62,9 @@ changes relative to sbcl-1.0.37: :SB-DOC feature. (lp#552564) * bug fix: SB-INTROSPECT build issues on GENGC/PPC. (lp#490490) * bug fix: more robust runtime executable path detection. (lp#375549) - * bug fix: GCD always returns positive values. (lp#413680)) + * bug fix: GCD always returns positive values. (lp#413680) + * bug fix: Converting division to multiplication by reciprocal handles + denormals. changes in sbcl-1.0.37 relative to sbcl-1.0.36: * enhancement: Backtrace from THROW to uncaught tag on x86oids now shows diff --git a/src/compiler/float-tran.lisp b/src/compiler/float-tran.lisp index 648f2f5..a5680e2 100644 --- a/src/compiler/float-tran.lisp +++ b/src/compiler/float-tran.lisp @@ -349,15 +349,20 @@ ;;; Return the reciprocal of X if it can be represented exactly, NIL otherwise. (defun maybe-exact-reciprocal (x) (unless (zerop x) - (multiple-value-bind (significand exponent sign) - ;; Signals an error for NaNs and infinities. - (handler-case (integer-decode-float x) - (error () (return-from maybe-exact-reciprocal nil))) - (let ((expected (/ sign significand (expt 2 exponent)))) - (let ((reciprocal (/ 1 x))) - (multiple-value-bind (significand exponent sign) (integer-decode-float reciprocal) - (when (eql expected (* sign significand (expt 2 exponent))) - reciprocal))))))) + (handler-case + (multiple-value-bind (significand exponent sign) + (integer-decode-float x) + ;; only powers of 2 can be inverted exactly + (unless (zerop (logand significand (1- significand))) + (return-from maybe-exact-reciprocal nil)) + (let ((expected (/ sign significand (expt 2 exponent))) + (reciprocal (/ x))) + (multiple-value-bind (significand exponent sign) + (integer-decode-float reciprocal) + ;; Denorms can't be inverted safely. + (and (eql expected (* sign significand (expt 2 exponent))) + reciprocal)))) + (error () (return-from maybe-exact-reciprocal nil))))) ;;; Replace constant division by multiplication with exact reciprocal, ;;; if one exists. diff --git a/version.lisp-expr b/version.lisp-expr index b4d6617..10b7429 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"1.0.37.61" +"1.0.37.62"