Author: Amaury Forgeot d'Arc <amaur...@gmail.com> Branch: merge-2.7.2 Changeset: r51654:40000ebe74d7 Date: 2012-01-22 18:31 +0100 http://bitbucket.org/pypy/pypy/changeset/40000ebe74d7/
Log: Fix edge cases in float.__mod__ diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py --- a/pypy/objspace/std/floatobject.py +++ b/pypy/objspace/std/floatobject.py @@ -383,8 +383,16 @@ except ValueError: mod = rfloat.NAN else: - if (mod and ((y < 0.0) != (mod < 0.0))): - mod += y + if mod: + # ensure the remainder has the same sign as the denominator + if (y < 0.0) != (mod < 0.0): + mod += y + 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 = y * 0.0", but that may get optimized away + mod = copysign(0.0, y) return W_FloatObject(mod) diff --git a/pypy/objspace/std/test/test_floatobject.py b/pypy/objspace/std/test/test_floatobject.py --- a/pypy/objspace/std/test/test_floatobject.py +++ b/pypy/objspace/std/test/test_floatobject.py @@ -789,3 +789,26 @@ raises(ZeroDivisionError, lambda: inf % 0) raises(ZeroDivisionError, lambda: inf // 0) raises(ZeroDivisionError, divmod, inf, 0) + + def test_modulo_edgecases(self): + # Check behaviour of % operator for IEEE 754 special cases. + # In particular, check signs of zeros. + mod = float.__mod__ + import math + + def check(a, b): + assert (a, math.copysign(1.0, a)) == (b, math.copysign(1.0, b)) + + check(mod(-1.0, 1.0), 0.0) + check(mod(-1e-100, 1.0), 1.0) + check(mod(-0.0, 1.0), 0.0) + check(mod(0.0, 1.0), 0.0) + check(mod(1e-100, 1.0), 1e-100) + check(mod(1.0, 1.0), 0.0) + + check(mod(-1.0, -1.0), -0.0) + check(mod(-1e-100, -1.0), -1e-100) + check(mod(-0.0, -1.0), -0.0) + check(mod(0.0, -1.0), -0.0) + check(mod(1e-100, -1.0), -1.0) + check(mod(1.0, -1.0), -0.0) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit