fix bounds checking in flonum->fixnum

The comparison was off for 32-bit plaforms, because it didn't allow
fractional increments, The comparison was off for 64-bit platforms,
bbecause it didn't account for round-trip failure when starting from
the largest fixnum.

original commit: 74eb0583ae1b6212fbde459d7486c3d4a0498401
This commit is contained in:
Matthew Flatt 2020-06-10 07:56:37 -06:00
parent 69b597e496
commit 4e808d249a
3 changed files with 25 additions and 4 deletions

View File

@ -26,6 +26,13 @@
(flonum->fixnum (* (+ (ash (most-positive-fixnum) -1) 1) 1.0))) (flonum->fixnum (* (+ (ash (most-positive-fixnum) -1) 1) 1.0)))
(eq? (most-negative-fixnum) (eq? (most-negative-fixnum)
(flonum->fixnum (* (most-negative-fixnum) 1.0))) (flonum->fixnum (* (most-negative-fixnum) 1.0)))
(eq? (+ (ash (most-positive-fixnum) -1) 1)
(flonum->fixnum (fl+ (* (+ (ash (most-positive-fixnum) -1) 1) 1.0) 0.5)))
(or (not (fixnum? (inexact->exact (exact->inexact (most-positive-fixnum)))))
(eq? (most-positive-fixnum)
(flonum->fixnum (fl+ (* (most-positive-fixnum) 1.0) 0.5))))
(eq? (most-negative-fixnum)
(flonum->fixnum (fl- (* (most-negative-fixnum) 1.0) 0.5)))
(eq? (flonum->fixnum 0.0) 0) (eq? (flonum->fixnum 0.0) 0)
(eq? (flonum->fixnum 1.0) 1) (eq? (flonum->fixnum 1.0) 1)
(eq? (flonum->fixnum +4.5) +4) (eq? (flonum->fixnum +4.5) +4)

View File

@ -7411,7 +7411,7 @@
(%inline sll ,body (immediate ,(fx- 0 cnt))) (%inline sll ,body (immediate ,(fx- 0 cnt)))
body))) body)))
(immediate ,mask))))) (immediate ,mask)))))
<
(define-inline 3 fllp (define-inline 3 fllp
[(e) (build-flonum-extractor 19 12 e)]) [(e) (build-flonum-extractor 19 12 e)])

View File

@ -317,11 +317,25 @@
($flonum-sign x))) ($flonum-sign x)))
(set-who! flonum->fixnum (set-who! flonum->fixnum
(let ([flmnf (fixnum->flonum (most-negative-fixnum))] (let ([flmnf (meta-cond
[flmpf (fixnum->flonum (most-positive-fixnum))]) ;; 64-bit fixnums: -1.0 is the same flonum
[(fl= (fixnum->flonum (most-negative-fixnum))
(fl- (fixnum->flonum (most-negative-fixnum)) 1.0))
;; Find the next lower flonum:
(let loop ([amt 2.0])
(let ([v (fl- (fixnum->flonum (most-negative-fixnum)) amt)])
(if (fl= v (fixnum->flonum (most-negative-fixnum)))
(loop (fl* 2.0 amt))
v)))]
[else
(fl- (fixnum->flonum (most-negative-fixnum)) 1.0)])]
;; Although adding 1.0 doesn't change the flonum for
;; 64-bit fixnums, the flonum doesn't fit in a fixnum, so
;; this is the upper bbound we want either way:
[flmpf (fl+ (fixnum->flonum (most-positive-fixnum)) 1.0)])
(lambda (x) (lambda (x)
(unless (flonum? x) (flargerr who x)) (unless (flonum? x) (flargerr who x))
(unless (fl<= flmnf x flmpf) (unless (fl< flmnf x flmpf)
($oops who "result for ~s would be outside of fixnum range" x)) ($oops who "result for ~s would be outside of fixnum range" x))
(#3%flonum->fixnum x)))) (#3%flonum->fixnum x))))
) )