[pypy-commit] pypy default: fix float mod behavior to match cpython (issue 1873)
bdkearns
noreply at buildbot.pypy.org
Wed Sep 24 18:51:18 CEST 2014
Author: Brian Kearns <bdkearns at gmail.com>
Branch:
Changeset: r73681:42870fecc305
Date: 2014-09-24 09:50 -0700
http://bitbucket.org/pypy/pypy/changeset/42870fecc305/
Log: fix float mod behavior to match cpython (issue 1873)
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
@@ -15,6 +15,7 @@
from rpython.rlib.rbigint import rbigint
from rpython.rlib import rfloat
from rpython.tool.sourcetools import func_with_new_name
+from rpython.rtyper.lltypesystem.module.ll_math import math_fmod
from pypy.objspace.std.intobject import W_IntObject
@@ -360,21 +361,17 @@
y = w_float2.floatval
if y == 0.0:
raise FailedToImplementArgs(space.w_ZeroDivisionError, space.wrap("float modulo"))
- try:
- mod = math.fmod(x, y)
- except ValueError:
- mod = rfloat.NAN
+ mod = math_fmod(x, y)
+ if mod:
+ # ensure the remainder has the same sign as the denominator
+ if (y < 0.0) != (mod < 0.0):
+ mod += y
else:
- 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)
+ # 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)
@@ -383,10 +380,7 @@
y = w_float2.floatval
if y == 0.0:
raise FailedToImplementArgs(space.w_ZeroDivisionError, space.wrap("float modulo"))
- try:
- mod = math.fmod(x, y)
- except ValueError:
- return [W_FloatObject(rfloat.NAN), W_FloatObject(rfloat.NAN)]
+ mod = math_fmod(x, y)
# fmod is typically exact, so vx-mod is *mathematically* an
# exact multiple of wx. But this is fp arithmetic, and fp
# vx - mod is an approximation; the result is that div may
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
@@ -794,7 +794,7 @@
raises(ValueError, float.fromhex, "0P")
def test_division_edgecases(self):
- import math
+ import math, os
# inf
inf = float("inf")
@@ -803,6 +803,16 @@
x, y = divmod(inf, 3)
assert math.isnan(x)
assert math.isnan(y)
+ x, y = divmod(3, inf)
+ z = 3 % inf
+ if os.name == 'nt':
+ assert math.isnan(x)
+ assert math.isnan(y)
+ assert math.isnan(z)
+ else:
+ assert x == 0
+ assert y == 3
+ assert z == 3
# divide by 0
raises(ZeroDivisionError, lambda: inf % 0)
More information about the pypy-commit
mailing list