Commit 4e58e53c authored by Raymond Toy's avatar Raymond Toy
Browse files

Be more careful in computing the decode-float bounds

If 0 is the lower bound then the smallest exponent is not for 0, but
for the least positive float because of denormals.

Also handle exclusive bounds.
parent 2292400e
Loading
Loading
Loading
Loading
+23 −19
Original line number Diff line number Diff line
@@ -2031,29 +2031,33 @@
  (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))
	   (bound-func #'(lambda (arg)
			   (nth-value 1 (decode-float arg)))
		       x)))
       (min-exp (interval)
	 ;; (decode-float 0d0) returns an exponent of -1022.  But
	 ;; (decode-float least-positive-double-float returns -1073.
	 ;; Hence, if the low value is less than this, we need to
	 ;; return the exponent of the least positive number.
	 (let ((least (if (eq 'single-float (numeric-type-format arg))
			  least-positive-single-float
			  least-positive-double-float)))
       (max-exp ()
	   (if (or (interval-contains-p 0 interval)
		   (interval-contains-p least interval))
	     (calc-exp least)
	     (calc-exp (bound-value (interval-low interval))))))
       (max-exp (interval)
	 ;; 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).
	 (or (calc-exp (bound-value (interval-high interval)))
	     (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 (interval-high interval)
		   (max-exp))))
			   most-positive-double-float)))))
    (let* ((interval (interval-abs (numeric-type->interval arg)))
	   (lo (min-exp interval))
	   (hi (max-exp interval)))
      (specifier-type `(integer ,(or lo '*) ,(or hi '*))))))

(defun decode-float-sign-derive-type-aux (arg)