[pypy-commit] pypy default: Support -NAN, which is actually different from NAN. We can tell

arigo noreply at buildbot.pypy.org
Tue Mar 13 20:33:41 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r53470:80452a4f1906
Date: 2012-03-13 12:33 -0700
http://bitbucket.org/pypy/pypy/changeset/80452a4f1906/

Log:	Support -NAN, which is actually different from NAN. We can tell the
	difference starting from Python 2.6 with math.copysign().

diff --git a/pypy/module/math/test/test_direct.py b/pypy/module/math/test/test_direct.py
--- a/pypy/module/math/test/test_direct.py
+++ b/pypy/module/math/test/test_direct.py
@@ -55,6 +55,12 @@
         ('frexp', (-1.25,), lambda x: x == (-0.625, 1)),
         ('modf',  (4.25,), lambda x: x == (0.25, 4.0)),
         ('modf',  (-4.25,), lambda x: x == (-0.25, -4.0)),
+        ('copysign', (1.5, 0.0), 1.5),
+        ('copysign', (1.5, -0.0), -1.5),
+        ('copysign', (1.5, INFINITY), 1.5),
+        ('copysign', (1.5, -INFINITY), -1.5),
+        ('copysign', (1.5, NAN), 1.5),
+        ('copysign', (1.75, -NAN), -1.75),      # special case for -NAN here
         ]
 
     OVFCASES = [
diff --git a/pypy/rlib/rfloat.py b/pypy/rlib/rfloat.py
--- a/pypy/rlib/rfloat.py
+++ b/pypy/rlib/rfloat.py
@@ -295,7 +295,7 @@
     return z
 
 INFINITY = 1e200 * 1e200
-NAN = INFINITY / INFINITY
+NAN = abs(INFINITY / INFINITY)    # bah, INF/INF gives us -NAN?
 
 try:
     # Try to get math functions added in 2.6.
diff --git a/pypy/translator/c/primitive.py b/pypy/translator/c/primitive.py
--- a/pypy/translator/c/primitive.py
+++ b/pypy/translator/c/primitive.py
@@ -89,6 +89,12 @@
     else:
         return '%dLL' % value
 
+def is_positive_nan(value):
+    # bah.  we don't have math.copysign() if we're running Python 2.5
+    import struct
+    c = struct.pack("!d", value)[0]
+    return {'\x7f': True, '\xff': False}[c]
+
 def name_float(value, db):
     if isinf(value):
         if value > 0:
@@ -96,7 +102,10 @@
         else:
             return '(-Py_HUGE_VAL)'
     elif isnan(value):
-        return '(Py_HUGE_VAL/Py_HUGE_VAL)'
+        if is_positive_nan(value):
+            return '(Py_HUGE_VAL/Py_HUGE_VAL)'
+        else:
+            return '(-(Py_HUGE_VAL/Py_HUGE_VAL))'
     else:
         x = repr(value)
         assert not x.startswith('n')
@@ -112,7 +121,10 @@
             return '((float)-Py_HUGE_VAL)'
     elif isnan(value):
         # XXX are these expressions ok?
-        return '((float)(Py_HUGE_VAL/Py_HUGE_VAL))'
+        if is_positive_nan(value):
+            return '((float)(Py_HUGE_VAL/Py_HUGE_VAL))'
+        else:
+            return '(-(float)(Py_HUGE_VAL/Py_HUGE_VAL))'
     else:
         return repr(value) + 'f'
 


More information about the pypy-commit mailing list