diff options
-rw-r--r-- | Lib/test/test_float.py | 21 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Python/compile.c | 15 |
3 files changed, 38 insertions, 1 deletions
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index fb47db8eb0..2f0d7840c8 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -99,6 +99,27 @@ class IEEEFormatTestCase(unittest.TestCase): ('<f', LE_FLOAT_NAN)]: struct.unpack(fmt, data) + if float.__getformat__("double").startswith("IEEE"): + def test_negative_zero(self): + import math + def pos_pos(): + return 0.0, math.atan2(0.0, -1) + def pos_neg(): + return 0.0, math.atan2(-0.0, -1) + def neg_pos(): + return -0.0, math.atan2(0.0, -1) + def neg_neg(): + return -0.0, math.atan2(-0.0, -1) + self.assertEquals(pos_pos(), neg_pos()) + self.assertEquals(pos_neg(), neg_neg()) + + if float.__getformat__("double").startswith("IEEE"): + def test_underflow_sign(self): + import math + # check that -1e-1000 gives -0.0, not 0.0 + self.assertEquals(math.atan2(-1e-1000, -1), math.atan2(-0.0, -1)) + self.assertEquals(math.atan2(float('-1e-1000'), -1), + math.atan2(-0.0, -1)) def test_main(): test_support.run_unittest( @@ -12,6 +12,9 @@ What's New in Python 2.5.2c1? Core and builtins ----------------- +- Issue #1678380: distinction between 0.0 and -0.0 was lost during constant + folding optimization. This was a regression from Python 2.4. + - Issue #1882: when compiling code from a string, encoding cookies in the second line of code were not always recognized correctly. diff --git a/Python/compile.c b/Python/compile.c index ce19aa9df4..0e824caabd 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1567,7 +1567,20 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) Py_ssize_t arg; /* necessary to make sure types aren't coerced (e.g., int and long) */ - t = PyTuple_Pack(2, o, o->ob_type); + /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ + if (PyFloat_Check(o)) { + double d = PyFloat_AS_DOUBLE(o); + unsigned char* p = (unsigned char*) &d; + /* all we need is to make the tuple different in either the 0.0 + * or -0.0 case from all others, just to avoid the "coercion". + */ + if (*p==0 && p[sizeof(double)-1]==0) + t = PyTuple_Pack(3, o, o->ob_type, Py_None); + else + t = PyTuple_Pack(2, o, o->ob_type); + } else { + t = PyTuple_Pack(2, o, o->ob_type); + } if (t == NULL) return -1; |