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

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
......@@ -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))
least-positive-single-float
least-positive-double-float)))
(max-exp ()
(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)))
(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).
(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))))
(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-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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment