@@ -355,6 +355,49 @@ Notes:
355355 [(ref ,maybe-src ,x) (and (not (prelex-assigned x)) x)]
356356 [else #f ])))
357357
358+ (define (real-expr->flonum-expr x r )
359+ ; Transform 0 into 0.0 as usual
360+ ; Assume (predicate-implies r real-pred)
361+ (cond
362+ [(and (Lsrc? r)
363+ (nanopass-case (Lsrc Expr) r
364+ [(quote ,d ) d]
365+ [else #f ])) =>
366+ (lambda (d ) (make-1seq 'value x `(quote ,(real->flonum d) )))]
367+ [(predicate-implies? r flonum-pred)
368+ x]
369+ [else
370+ (let ([->flonum-name (if (predicate-implies? r fixnum-pred)
371+ 'fixnum->flonum
372+ 'real->flonum )])
373+ `(call ,(make-preinfo-call) ,(lookup-primref 3 ->flonum-name) ,x))]))
374+
375+ (define (real-expr->flonum-expr/- x r )
376+ ; Transform 0 into -0.0 instead of 0.0
377+ ; Assume (predicate-implies r real-pred)
378+ (cond
379+ [(and (Lsrc? r)
380+ (nanopass-case (Lsrc Expr) r
381+ [(quote ,d ) d]
382+ [else #f ])) =>
383+ (lambda (d ) (make-1seq 'value x `(quote ,(if (eqv? d 0) -0.0 (real->flonum d)) )))]
384+ [(predicate-implies? r flonum-pred)
385+ x]
386+ [else
387+ (let ([->flonum-name (if (predicate-implies? r fixnum-pred)
388+ 'fixnum->flonum
389+ 'real->flonum )])
390+ (cond
391+ [(predicate-disjoint? r `(quote 0 ))
392+ `(call ,(make-preinfo-call) ,(lookup-primref 3 ->flonum-name) ,x)]
393+ [else
394+ (build-let 'value (list x) (list r)
395+ (lambda (x* )
396+ (let ([x (car x*)])
397+ `(if (call ,(make-preinfo-call) ,(lookup-primref 3 'eqv? ) ,x (quote 0 ))
398+ (quote -0.0 )
399+ (call ,(make-preinfo-call) ,(lookup-primref 3 ->flonum-name) ,x)))))]))]))
400+
358401 (define (filter/head+rest pred? l )
359402 ; (filter/head+rest odd? '(1 3 2 5 4 6))
360403 ; ==> (values '(1 3) '(2 5 4 6))
@@ -1135,6 +1178,73 @@ Notes:
11351178 (and (eq? ctxt 'test )
11361179 (pred-env-add/ref ntypes val (rtd->record-predicate rtd #t ) plxc))
11371180 #f )]))])
1181+
1182+ (let ()
1183+ (define (predicate-implies-real? r ) (predicate-implies? r real-pred))
1184+ (define (predicate-implies-fixnum? r ) (predicate-implies? r fixnum-pred))
1185+ (define (predicate-implies-integer? r ) (predicate-implies? r integer-pred))
1186+ (define (predicate-implies-flonum? r ) (predicate-implies? r flonum-pred))
1187+ (define (predicate-implies-exact? r ) (predicate-implies? r exact-pred))
1188+ (define (predicate-implies-inexact? r ) (predicate-implies? r inexact-pred))
1189+
1190+ (define (predicate-close/plus r* )
1191+ (cond
1192+ [(andmap predicate-implies-exact? r*)
1193+ (if (andmap predicate-implies-real? r*)
1194+ (if (andmap predicate-implies-integer? r*)
1195+ exact-integer-pred
1196+ exact-real-pred)
1197+ exact-pred)]
1198+ [(ormap predicate-implies-inexact? r*)
1199+ (if (andmap predicate-implies-real? r*)
1200+ flonum-pred
1201+ inexact-pred)]
1202+ [else
1203+ (if (andmap predicate-implies-real? r*)
1204+ real-pred
1205+ number-pred)]))
1206+
1207+ (define-specialize 2 +
1208+ [() (values `(quote 0 ) `(quote 0 ) ntypes #f #f )]
1209+ [(x) (values `(call ,preinfo ,pr ,x)
1210+ (predicate-intersect (get-type x) number-pred) ntypes #f #f )]
1211+ [x* ; x* has at least 2 arguments
1212+ (let* ([r* (get-type x*)]
1213+ [ret (predicate-close/plus
1214+ (map (lambda (r ) (predicate-intersect r number-pred)) r*))]
1215+ [ir (and (andmap predicate-implies-real? r*)
1216+ (cond
1217+ [(andmap predicate-implies-fixnum? r*)
1218+ `(call ,preinfo ,(lookup-primref 3 '$fxx+ ) ,x* ...)]
1219+ [(cond
1220+ [(enable-arithmetic-left-associative)
1221+ ; if they can't be reordered, check that at least
1222+ ; one of the first two is a flonum
1223+ (or (predicate-implies-flonum? (car r*))
1224+ (predicate-implies-flonum? (cadr r*)))]
1225+ [else
1226+ ; otherwise, checkt that all or all but one are flonums,
1227+ ; in case they are reordered
1228+ (let-values ([(head* rest*)
1229+ (filter/head+rest predicate-implies-flonum? r*)])
1230+ (or (null? rest*)
1231+ (andmap predicate-implies-flonum? (cdr rest*))))])
1232+ (cond
1233+ [(ormap (lambda (r ) (and (predicate-disjoint? r `(quote -0.0 ))
1234+ (predicate-disjoint? r `(quote 0 ))))
1235+ r*)
1236+ ; If one argument is neither 0 or -0.0 it's possible
1237+ ; to replace 0 with 0.0 instead of -0.0
1238+ ; because the rounding mode is never FE_DOWNWARD
1239+ `(call ,preinfo ,(lookup-primref 3 'fl+ )
1240+ ,(map real-expr->flonum-expr x* r*) ...)]
1241+ [else
1242+ `(call ,preinfo ,(lookup-primref 3 'fl+ )
1243+ ,(map real-expr->flonum-expr/- x* r*) ...)])]
1244+ [else
1245+ #f ]))])
1246+ (values (or ir `(call ,preinfo ,pr ,x* ...)) ret ntypes #f #f ))])
1247+ )
11381248
11391249 (define-specialize 2 (add1 sub1 1+ 1- -1+)
11401250 [(n) (let ([r (get-type n)])
0 commit comments