diff --git a/typed-racket-lib/typed-racket/optimizer/float-complex.rkt b/typed-racket-lib/typed-racket/optimizer/float-complex.rkt index e936784c..fde85dc2 100644 --- a/typed-racket-lib/typed-racket/optimizer/float-complex.rkt +++ b/typed-racket-lib/typed-racket/optimizer/float-complex.rkt @@ -247,6 +247,8 @@ (define o-real? (was-real? o2)) (define e-real? (was-real? (car e2))) (define both-real? (and o-real? e-real?)) + (define o-nf (as-non-float o1)) + (define e-nf (as-non-float (car e1))) (define new-imag-id (if both-real? (mark-as-real (car is)) (car is))) @@ -261,11 +263,22 @@ #`(unsafe-fl+ (unsafe-fl* #,o2 #,(car e1)) (unsafe-fl* #,o1 #,(car e2)))))) #`((#,(car rs)) - #,(cond ((or o-real? e-real?) - #`(unsafe-fl* #,o1 #,(car e1))) - (else + #,(cond [(and o-nf e-nf) + ;; we haven't seen float operands yet, so + ;; shouldn't prematurely convert to floats + ;; (implies that they're both real) + (mark-as-non-float (car rs) (car rs)) + #`(* #,o-nf #,e-nf)] + [(or o-real? e-real?) + #`(unsafe-fl* + #,(if (as-non-float o1) + ;; we hit floats, need to coerce + #`(real->double-flonum #,o1) + o1) + #,(car e1))] + [else #`(unsafe-fl- (unsafe-fl* #,o1 #,(car e1)) - (unsafe-fl* #,o2 #,(car e2)))))) + (unsafe-fl* #,o2 #,(car e2)))])) res))]))))) (pattern (#%plain-app op:*^ :unboxed-float-complex-opt-expr) #:when (subtypeof? this-syntax -FloatComplex) diff --git a/typed-racket-test/optimizer/known-bugs.rkt b/typed-racket-test/optimizer/known-bugs.rkt index 83794ed5..d85c35cb 100644 --- a/typed-racket-test/optimizer/known-bugs.rkt +++ b/typed-racket-test/optimizer/known-bugs.rkt @@ -56,7 +56,7 @@ (good-opt (- (* (/ 6 11) (/ 1.2345678f0 123456.7f0)) (make-rectangular 0.0 0.3))) (good-opt (/ 1.0 0.0+0.0i)) (good-opt (+ 0.0+0.0i (* 1 1 +inf.0))) - (bad-opt (* 1.0f-30 1.0f-30 1.0e60+1.0e60i)) + (good-opt (* 1.0f-30 1.0f-30 1.0e60+1.0e60i)) ;; Unary division has bad underflow (good-opt (/ (make-rectangular 1e+100 1e-300))) @@ -79,7 +79,7 @@ (good-opt (+ (exp 1.7976931348623151e+308) 0.0+0.0i)) ;; Multiplication of multiple args should keep exact semantics for exact args - (bad-opt (* (expt 10 500) (expt 10 -500) 1.0+1.0i)) + (good-opt (* (expt 10 500) (expt 10 -500) 1.0+1.0i)) ;; Addition of multiple args should keep exact semantics for exact args (good-opt (+ (expt 10 501) (expt -10 501) 1.0+1.0i)) diff --git a/typed-racket-test/optimizer/tests/float-complex-float.rkt b/typed-racket-test/optimizer/tests/float-complex-float.rkt index 3a8cd525..f3552947 100644 --- a/typed-racket-test/optimizer/tests/float-complex-float.rkt +++ b/typed-racket-test/optimizer/tests/float-complex-float.rkt @@ -15,6 +15,11 @@ TR opt: float-complex-float.rkt 12:0 (+ 1.5245886f+12 (max (exact-round 2) (exac TR opt: float-complex-float.rkt 12:17 (max (exact-round 2) (exact-round 5/4)) -- non float complex in complex ops TR opt: float-complex-float.rkt 12:3 1.5245886f+12 -- non float complex in complex ops TR opt: float-complex-float.rkt 12:57 (tanh (make-rectangular 1.4291365847030308e-64 -0.76987815f0)) -- unbox float-complex +TR opt: float-complex-float.rkt 13:0 (* (min 3/4) 0.9845773f0 (make-rectangular 3 0.0)) -- unboxed binary float complex +TR opt: float-complex-float.rkt 13:13 0.9845773f0 -- non float complex in complex ops +TR opt: float-complex-float.rkt 13:25 (make-rectangular 3 0.0) -- make-rectangular elimination +TR opt: float-complex-float.rkt 13:3 (min 3/4) -- non float complex in complex ops +TR opt: float-complex-float.rkt 13:3 (min 3/4) -- unary number TR opt: float-complex-float.rkt 4:0 (+ 1.0+2.0i 2.0 3.0+6.0i) -- unboxed binary float complex TR opt: float-complex-float.rkt 4:12 2.0 -- float in complex ops TR opt: float-complex-float.rkt 4:16 3.0+6.0i -- unboxed literal @@ -49,6 +54,7 @@ END +nan.0+0.0i -0.8414709848078965-4.5353337789114595e-57i 5.381428268223429e-17-0.9694319337396835i +2.2152990102767944+0.0i END #lang typed/scheme @@ -66,3 +72,4 @@ END (/ 2.3454025f0 (flmin (real->double-flonum 1.797693134862315e+308) (real->double-flonum -1.2848677f+32)) (make-rectangular +nan.0 0.0)) (+ (make-polar 4.8063810141303426e-57 -1.9082319f0) -0.8414709848078965) (+ 1.5245886f+12 (max (exact-round 2) (exact-round 5/4)) (tanh (make-rectangular 1.4291365847030308e-64 -0.76987815f0))) +(* (min 3/4) 0.9845773f0 (make-rectangular 3 0.0))