From 23fe13b4d58313c1b988a948a219661486545d54 Mon Sep 17 00:00:00 2001 From: Nikodemus Siivola Date: Mon, 5 Mar 2007 16:58:26 +0000 Subject: [PATCH] 1.0.3.31: fix new = and /= transformations for NaNs * (= nan nan) is false, and (/= nan nan) is true, as pointed out by CSR. * More tests. --- src/compiler/srctran.lisp | 25 ++++++++++++++-------- tests/float.pure.lisp | 52 +++++++++++++++++++++++++++++++++------------ version.lisp-expr | 2 +- 3 files changed, 55 insertions(+), 24 deletions(-) diff --git a/src/compiler/srctran.lisp b/src/compiler/srctran.lisp index 30c0c61..c49fe94 100644 --- a/src/compiler/srctran.lisp +++ b/src/compiler/srctran.lisp @@ -3410,14 +3410,15 @@ (give-up-ir1-transform "The operands might not be the same type."))))) -(labels ((maybe-float-lvar-p (lvar) - (neq *empty-type* (type-intersection (specifier-type 'float) - (lvar-type lvar)))) - (maybe-invert (op inverted x y) - ;; Don't invert if either argument can be a float (NaNs) - (if (or (maybe-float-lvar-p x) (maybe-float-lvar-p y)) - `(or (,op x y) (= x y)) - `(if (,inverted x y) nil t)))) +(defun maybe-float-lvar-p (lvar) + (neq *empty-type* (type-intersection (specifier-type 'float) + (lvar-type lvar)))) + +(flet ((maybe-invert (op inverted x y) + ;; Don't invert if either argument can be a float (NaNs) + (if (or (maybe-float-lvar-p x) (maybe-float-lvar-p y)) + `(or (,op x y) (= x y)) + `(if (,inverted x y) nil t)))) (deftransform >= ((x y) (number number) *) "invert or open code" (maybe-invert '> '< x y)) @@ -3432,7 +3433,13 @@ (macrolet ((def (name inverse reflexive-p surely-true surely-false) `(deftransform ,name ((x y)) "optimize using intervals" - (if (same-leaf-ref-p x y) + (if (and (same-leaf-ref-p x y) + ;; For non-reflexive functions we don't need + ;; to worry about NaNs: (non-ref-op NaN NaN) => false, + ;; but with reflexive ones we don't know... + ,@(when reflexive-p + '((and (not (maybe-float-lvar-p x)) + (not (maybe-float-lvar-p y)))))) ,reflexive-p (let ((ix (or (type-approximate-interval (lvar-type x)) (give-up-ir1-transform))) diff --git a/tests/float.pure.lisp b/tests/float.pure.lisp index 5685131..1367747 100644 --- a/tests/float.pure.lisp +++ b/tests/float.pure.lisp @@ -162,17 +162,41 @@ (macrolet ((test (form) (let ((nform (subst '(/ 0.0 0.0) 'nan form))) `(progn - (assert (not (eval ',nform))) - (assert (not (funcall (lambda () ,nform)))))))) - ;; Source transforms for >= and <= used to be too eager about - ;; inverting the test, causing NaN issues. - (test (>= nan 1.0)) - (test (>= 1.0 nan)) - (test (>= 1.0 nan 0.0)) - (test (>= 1.0 0.0 nan)) - (test (>= nan 1.0 0.0)) - (test (<= nan 1.0)) - (test (<= 1.0 nan)) - (test (<= 1.0 nan 2.0)) - (test (<= 1.0 2.0 nan)) - (test (<= nan 1.0 2.0))))) + (assert (eval ',nform)) + (assert (eval `(let ((nan (/ 0.0 0.0))) + ,',form))) + (assert (funcall + (compile nil `(lambda () ,',nform)))) + (assert (funcall + (compile nil `(lambda (nan) ,',form)) + (/ 0.0 0.0))))))) + (test (/= nan nan)) + (test (/= nan nan nan)) + (test (/= 1.0 nan 2.0 nan)) + (test (/= nan 1.0 2.0 nan)) + (test (not (= nan 1.0))) + (test (not (= nan nan))) + (test (not (= nan nan nan))) + (test (not (= 1.0 nan))) + (test (not (= nan 1.0))) + (test (not (= 1.0 1.0 nan))) + (test (not (= 1.0 nan 1.0))) + (test (not (= nan 1.0 1.0))) + (test (not (>= nan nan))) + (test (not (>= nan 1.0))) + (test (not (>= 1.0 nan))) + (test (not (>= 1.0 nan 0.0))) + (test (not (>= 1.0 0.0 nan))) + (test (not (>= nan 1.0 0.0))) + (test (not (<= nan nan))) + (test (not (<= nan 1.0))) + (test (not (<= 1.0 nan))) + (test (not (<= 1.0 nan 2.0))) + (test (not (<= 1.0 2.0 nan))) + (test (not (<= nan 1.0 2.0))) + (test (not (< nan nan))) + (test (not (< -1.0 nan))) + (test (not (< nan 1.0))) + (test (not (> nan nan))) + (test (not (> -1.0 nan))) + (test (not (> nan 1.0)))))) diff --git a/version.lisp-expr b/version.lisp-expr index 6d0880f..35e3fa3 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"1.0.3.30" +"1.0.3.31" -- 1.7.10.4