1.0.37.62: More robust reciprocal exactitude test
authorPaul Khuong <pvk@pvk.ca>
Mon, 26 Apr 2010 21:12:33 +0000 (21:12 +0000)
committerPaul Khuong <pvk@pvk.ca>
Mon, 26 Apr 2010 21:12:33 +0000 (21:12 +0000)
 * Trying to divide by tiny powers of 2 could result in compile-time
   errors.

NEWS
src/compiler/float-tran.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index 5499d30..4805c10 100644 (file)
--- 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
index 648f2f5..a5680e2 100644 (file)
 ;;; 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.
index b4d6617..10b7429 100644 (file)
@@ -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"