Skip to content

Commit dc27457

Browse files
committed
Fix bugs in floating point optimizations
This commit addresses correctness issues in float optimization: 1. Fix type of (/ 0.0): Changed the division type from (-> -NonPosReal -NonPosReal) to (-> -NegReal -NonPosReal) to correctly handle cases like (/ (min 0.0 0)) which returns +inf.0. 2. Avoid optimizing float exprs when conversion can change result: Added safe-to-convert? check to prevent converting large exact numbers to infinity before operations. For example, (- (expt 10 309) +inf.0) should yield -inf.0, but premature conversion to float would give +nan.0. 3. Added tests for these fixes plus a test for make-polar with NaN arguments to ensure complex NaN is preserved. Based on PR racket#1381. Fixes racket#1042. https://claude.ai/code/session_01UKyzYRFQ9Zm7KsDor34VoY
1 parent 5197377 commit dc27457

File tree

3 files changed

+24
-4
lines changed

3 files changed

+24
-4
lines changed

typed-racket-lib/typed-racket/base-env/base-env-numeric.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,7 @@
12481248
(varop-1+ -InexactReal)
12491249
;; reals
12501250
(varop-1+ -PosReal -NonNegReal)
1251-
(-> -NonPosReal -NonPosReal)
1251+
(-> -NegReal -NonPosReal)
12521252
(-> -NegReal -NegReal -NonNegReal) ; 0.0 is non-neg, but doesn't preserve sign
12531253
(-> -NegReal -PosReal -NonPosReal) ; idem
12541254
(-> -PosReal -NegReal -NonPosReal) ; idem

typed-racket-lib/typed-racket/optimizer/float.rkt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,14 @@
112112
(not (subtypeof? stx -SingleFlonum))
113113
(not (subtypeof? stx -Int))))
114114

115+
;; Check whether an expression can be safely converted to flonum without
116+
;; changing the result (e.g., a large finite number becoming infinity)
117+
(define (safe-to-convert? a)
118+
(or (subtypeof? a -Fixnum)
119+
(syntax-parse a #:literals (quote)
120+
[(quote n) #:when (flonum? (syntax-e #'n)) #t]
121+
[(quote n) #:when (rational? (real->double-flonum (syntax-e #'n))) #t]
122+
[_ #f])))
115123

116124
(define-syntax-class float-opt-expr
117125
#:commit
@@ -144,8 +152,11 @@
144152
(and (subtypeof? this-syntax -Flonum)
145153
(for/and ([a (in-syntax #'(fs ...))])
146154
;; flonum or provably non-zero
155+
;; also need to make sure that coercing to float won't change
156+
;; a large finite number to infinity, altering the result
147157
(or (subtypeof? a -Flonum)
148-
(subtypeof? a (Un -PosReal -NegReal))))
158+
(and (subtypeof? a (Un -PosReal -NegReal))
159+
(safe-to-convert? a))))
149160
(>= 1
150161
(for/sum ([a (in-syntax #'(fs ...))]
151162
#:when (not (subtypeof? a -Flonum)))

typed-racket-test/optimizer/known-bugs.rkt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
(define (mk-eval lang)
2020
(call-with-trusted-sandbox-configuration
2121
(λ ()
22-
(parameterize ([sandbox-memory-limit 300])
22+
(parameterize ([sandbox-memory-limit 3000])
2323
(make-evaluator lang)))))
2424
(define racket-eval (mk-eval 'racket))
2525
(define tr-eval (mk-eval 'typed/racket))
@@ -99,7 +99,16 @@
9999
(good-opt (conjugate 0.0+0.0i))
100100

101101
;; Magnitude should always return positive results
102-
(good-opt (magnitude -1.0-2i))))
102+
(good-opt (magnitude -1.0-2i))
103+
104+
;; Division of 0.0 should return correct sign
105+
(good-opt (/ (min 0.0 0)))
106+
107+
;; Subtraction should not convert large numbers to infinity prematurely
108+
(good-opt (- (expt 10 309) +inf.0))
109+
110+
;; make-polar with NaN should return complex NaN, not real NaN
111+
(good-opt (+ 1.0 (make-polar +nan.0 1.0)))))
103112

104113
(module+ main
105114
(require rackunit/text-ui)

0 commit comments

Comments
 (0)