# Commits

committed 40000eb

Fix edge cases in float.__mod__

# pypy/objspace/std/floatobject.py

`     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)`
` `

# pypy/objspace/std/test/test_floatobject.py

`         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)`