mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-12 23:00:22 +02:00
Fix range analysis for mul and div
* module/language/cps/types.scm (mul): Avoid producing nans in the resulting range. (div): Fix range analysis.
This commit is contained in:
parent
384d1ec3b2
commit
42b544ebbc
1 changed files with 36 additions and 13 deletions
|
@ -799,13 +799,30 @@ minimum, and maximum."
|
||||||
(define-type-inferrer (mul a b result)
|
(define-type-inferrer (mul a b result)
|
||||||
(let ((min-a (&min a)) (max-a (&max a))
|
(let ((min-a (&min a)) (max-a (&max a))
|
||||||
(min-b (&min b)) (max-b (&max b)))
|
(min-b (&min b)) (max-b (&max b)))
|
||||||
(let ((-- (* min-a min-b))
|
(define (nan* a b)
|
||||||
(-+ (* min-a max-b))
|
;; We only really get +inf.0 at runtime for flonums and compnums.
|
||||||
(++ (* max-a max-b))
|
;; If we have inferred that the arguments are not flonums and not
|
||||||
(+- (* max-a min-b)))
|
;; compnums, then the result of (* +inf.0 0) at range inference
|
||||||
(define-binary-result! a b result #t
|
;; time is 0 and not +nan.0.
|
||||||
(if (eqv? a b) 0 (min -- -+ ++ +-))
|
(if (or (and (inf? a) (zero? b))
|
||||||
(max -- -+ ++ +-)))))
|
(and (zero? a) (inf? b))
|
||||||
|
(not (logtest (logior (&type a) (&type b))
|
||||||
|
(logior &flonum &complex))))
|
||||||
|
0
|
||||||
|
(* a b)))
|
||||||
|
(let ((-- (nan* min-a min-b))
|
||||||
|
(-+ (nan* min-a max-b))
|
||||||
|
(++ (nan* max-a max-b))
|
||||||
|
(+- (nan* max-a min-b)))
|
||||||
|
(let ((has-nan? (or (nan? --) (nan? -+) (nan? ++) (nan? +-))))
|
||||||
|
(define-binary-result! a b result #t
|
||||||
|
(cond
|
||||||
|
((eqv? a b) 0)
|
||||||
|
(has-nan? -inf.0)
|
||||||
|
(else (min -- -+ ++ +-)))
|
||||||
|
(if has-nan?
|
||||||
|
+inf.0
|
||||||
|
(max -- -+ ++ +-)))))))
|
||||||
|
|
||||||
(define-type-checker (div a b)
|
(define-type-checker (div a b)
|
||||||
(and (check-type a &number -inf.0 +inf.0)
|
(and (check-type a &number -inf.0 +inf.0)
|
||||||
|
@ -824,12 +841,18 @@ minimum, and maximum."
|
||||||
(values -inf.0 +inf.0)
|
(values -inf.0 +inf.0)
|
||||||
;; Otherwise min-b and max-b have the same sign, and cannot both
|
;; Otherwise min-b and max-b have the same sign, and cannot both
|
||||||
;; be infinity.
|
;; be infinity.
|
||||||
(let ((-- (if (inf? min-b) 0 (* min-a min-b)))
|
(let ((--- (if (inf? min-b) 0 (floor/ min-a min-b)))
|
||||||
(-+ (if (inf? max-b) 0 (* min-a max-b)))
|
(-+- (if (inf? max-b) 0 (floor/ min-a max-b)))
|
||||||
(++ (if (inf? max-b) 0 (* max-a max-b)))
|
(++- (if (inf? max-b) 0 (floor/ max-a max-b)))
|
||||||
(+- (if (inf? min-b) 0 (* max-a min-b))))
|
(+-- (if (inf? min-b) 0 (floor/ max-a min-b)))
|
||||||
(values (min -- -+ ++ +-)
|
(--+ (if (inf? min-b) 0 (ceiling/ min-a min-b)))
|
||||||
(max -- -+ ++ +-)))))
|
(-++ (if (inf? max-b) 0 (ceiling/ min-a max-b)))
|
||||||
|
(+++ (if (inf? max-b) 0 (ceiling/ max-a max-b)))
|
||||||
|
(+-+ (if (inf? min-b) 0 (ceiling/ max-a min-b))))
|
||||||
|
(values (min (min --- -+- ++- +--)
|
||||||
|
(min --+ -++ +++ +-+))
|
||||||
|
(max (max --- -+- ++- +--)
|
||||||
|
(max --+ -++ +++ +-+))))))
|
||||||
(lambda (min max)
|
(lambda (min max)
|
||||||
(define-binary-result! a b result #f min max)))))
|
(define-binary-result! a b result #f min max)))))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue