From 3acdd1b7d05d9a90c877167e882bf77b22606366 Mon Sep 17 00:00:00 2001
From: Raymond Toy <toy.raymond@gmail.com>
Date: Sat, 3 Feb 2018 08:57:28 -0800
Subject: [PATCH] Fix #59: type derivation for decode-float exponent

Type derivation for exponent part of decode-float was incorrect.  We
need to take the absolute value of the argument before deriving the
type since the exponent is, of course, independent of the sign of the
number.  In the test case, the negative interval caused the lower and
upper bounds to be reversed, resulting in an invalid interval.
---
 src/compiler/float-tran.lisp | 47 ++++++++++++++++++------------------
 1 file changed, 24 insertions(+), 23 deletions(-)

diff --git a/src/compiler/float-tran.lisp b/src/compiler/float-tran.lisp
index e89952790..1ee030bd0 100644
--- a/src/compiler/float-tran.lisp
+++ b/src/compiler/float-tran.lisp
@@ -2028,30 +2028,31 @@
 (defun decode-float-exp-derive-type-aux (arg)
   ;; Derive the exponent part of the float.  It's always an integer
   ;; type.
-  (flet ((calc-exp (x)
-	   (when x
-	     (nth-value 1 (decode-float x))))
-	 (min-exp ()
-	   ;; Use decode-float on the least positive float of the
-	   ;; appropriate type to find the min exponent.  If we don't
-	   ;; know the actual number format, use double, which has the
-	   ;; widest range (including double-double-float).
-	   (nth-value 1 (decode-float (if (eq 'single-float (numeric-type-format arg))
-					  least-positive-single-float
-					  least-positive-double-float))))
-	 (max-exp ()
-	   ;; Use decode-float on the most postive number of the
-	   ;; appropriate type to find the max exponent.  If we don't
-	   ;; know the actual number format, use double, which has the
-	   ;; widest range (including double-double-float).
-	   (if (eq (numeric-type-format arg) 'single-float)
-	       (nth-value 1 (decode-float most-positive-single-float))
-	       (nth-value 1 (decode-float most-positive-double-float)))))
-    (let* ((lo (or (bound-func #'calc-exp
-			       (numeric-type-low arg))
+  (labels
+      ((calc-exp (x)
+	 (when x
+	   (nth-value 1 (decode-float x))))
+       (min-exp ()
+	 ;; Use decode-float on the least positive float of the
+	 ;; appropriate type to find the min exponent.  If we don't
+	 ;; know the actual number format, use double, which has the
+	 ;; widest range (including double-double-float).
+	 (calc-exp (if (eq 'single-float (numeric-type-format arg))
+		       least-positive-single-float
+		       least-positive-double-float)))
+       (max-exp ()
+	 ;; Use decode-float on the most postive number of the
+	 ;; appropriate type to find the max exponent.  If we don't
+	 ;; know the actual number format, use double, which has the
+	 ;; widest range (including double-double-float).
+	 (calc-exp (if (eq 'single-float (numeric-type-format arg))
+		       most-positive-single-float
+		       most-positive-double-float))))
+    (let* ((interval (interval-func #'calc-exp
+				    (interval-abs (numeric-type->interval arg))))
+	   (lo (or (interval-low interval)
 		   (min-exp)))
-	   (hi (or (bound-func #'calc-exp
-			       (numeric-type-high arg))
+	   (hi (or (interval-high interval)
 		   (max-exp))))
       (specifier-type `(integer ,(or lo '*) ,(or hi '*))))))
 
-- 
GitLab