diff options
-rw-r--r-- | Lib/test/test_float.py | 30 | ||||
-rw-r--r-- | Misc/NEWS | 4 | ||||
-rw-r--r-- | Objects/floatobject.c | 18 |
3 files changed, 14 insertions, 38 deletions
diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 6d90637..b4897c9 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -12,6 +12,16 @@ import re INF = float("inf") NAN = float("nan") +have_getformat = hasattr(float, "__getformat__") +requires_getformat = unittest.skipUnless(have_getformat, + "requires __getformat__") +requires_setformat = unittest.skipUnless(hasattr(float, "__setformat__"), + "requires __setformat__") +# decorator for skipping tests on non-IEEE 754 platforms +requires_IEEE_754 = unittest.skipUnless(have_getformat and + float.__getformat__("double").startswith("IEEE"), + "test requires IEEE 754 doubles") + #locate file with float format test values test_dir = os.path.dirname(__file__) or os.curdir format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt') @@ -231,26 +241,6 @@ class GeneralFloatCases(unittest.TestCase): self.assertTrue(d == d, "{%r : None} not equal to itself" % f) - @requires_IEEE_754 - def test_float_mod(self): - # Check behaviour of % operator for IEEE 754 special cases. - # In particular, check signs of zeros. - mod = operator.mod - - self.assertEqualAndEqualSign(mod(-1.0, 1.0), 0.0) - self.assertEqualAndEqualSign(mod(-1e-100, 1.0), 1.0) - self.assertEqualAndEqualSign(mod(-0.0, 1.0), 0.0) - self.assertEqualAndEqualSign(mod(0.0, 1.0), 0.0) - self.assertEqualAndEqualSign(mod(1e-100, 1.0), 1e-100) - self.assertEqualAndEqualSign(mod(1.0, 1.0), 0.0) - - self.assertEqualAndEqualSign(mod(-1.0, -1.0), -0.0) - self.assertEqualAndEqualSign(mod(-1e-100, -1.0), -1e-100) - self.assertEqualAndEqualSign(mod(-0.0, -1.0), -0.0) - self.assertEqualAndEqualSign(mod(0.0, -1.0), -0.0) - self.assertEqualAndEqualSign(mod(1e-100, -1.0), -1.0) - self.assertEqualAndEqualSign(mod(1.0, -1.0), -0.0) - class FormatFunctionsTestCase(unittest.TestCase): @@ -10,10 +10,6 @@ What's New in Python 3.1.4? Core and Builtins ----------------- -- Issue #10596: Fix float.__mod__ to have the same behaviour as - float.__divmod__ with respect to signed zeros. -4.0 % 4.0 should be - 0.0, not -0.0. - Library ------- diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 6a2af74..865c960 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -600,20 +600,10 @@ float_rem(PyObject *v, PyObject *w) #endif PyFPE_START_PROTECT("modulo", return 0) mod = fmod(vx, wx); - if (mod) { - /* ensure the remainder has the same sign as the denominator */ - if ((wx < 0) != (mod < 0)) { - mod += wx; - } - } - else { - /* the remainder is zero, and in the presence of signed zeroes - fmod returns different results across platforms; ensure - it has the same sign as the denominator; we'd like to do - "mod = wx * 0.0", but that may get optimized away */ - mod *= mod; /* hide "mod = +0" from optimizer */ - if (wx < 0.0) - mod = -mod; + /* note: checking mod*wx < 0 is incorrect -- underflows to + 0 if wx < sqrt(smallest nonzero double) */ + if (mod && ((wx < 0) != (mod < 0))) { + mod += wx; } PyFPE_END_PROTECT(mod) return PyFloat_FromDouble(mod); |