[pypy-svn] pypy default: Fix a crash in pow() with nonfinite values
amauryfa
commits-noreply at bitbucket.org
Fri Feb 4 01:40:39 CET 2011
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch:
Changeset: r41592:c5f9e9eb2e26
Date: 2011-02-04 01:38 +0100
http://bitbucket.org/pypy/pypy/changeset/c5f9e9eb2e26/
Log: Fix a crash in pow() with nonfinite values
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
@@ -412,6 +412,48 @@
x = w_float1.floatval
y = w_float2.floatval
+ # Sort out special cases here instead of relying on pow()
+ if y == 0.0:
+ # x**0 is 1, even 0**0
+ return W_FloatObject(1.0)
+ if isnan(x):
+ # nan**y = nan, unless y == 0
+ return W_FloatObject(x)
+ if isnan(y):
+ # x**nan = nan, unless x == 1; x**nan = x
+ if x == 1.0:
+ return W_FloatObject(1.0)
+ else:
+ return W_FloatObject(y)
+ if isinf(y):
+ # x**inf is: 0.0 if abs(x) < 1; 1.0 if abs(x) == 1; inf if
+ # abs(x) > 1 (including case where x infinite)
+ #
+ # x**-inf is: inf if abs(x) < 1; 1.0 if abs(x) == 1; 0.0 if
+ # abs(x) > 1 (including case where v infinite)
+ x = abs(x)
+ if x == 1.0:
+ return W_FloatObject(1.0)
+ elif (y > 0.0) == (x > 1.0):
+ return W_FloatObject(INFINITY)
+ else:
+ return W_FloatObject(0.0)
+ if isinf(x):
+ # (+-inf)**w is: inf for w positive, 0 for w negative; in oth
+ # cases, we need to add the appropriate sign if w is an odd
+ # integer.
+ y_is_odd = math.fmod(abs(y), 2.0) == 1.0
+ if y > 0.0:
+ if y_is_odd:
+ return W_FloatObject(x)
+ else:
+ return W_FloatObject(abs(x))
+ else:
+ if y_is_odd:
+ return W_FloatObject(copysign(0.0, x))
+ else:
+ return W_FloatObject(0.0)
+
if x == 0.0:
if y < 0.0:
if isinf(y):
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
@@ -204,6 +204,21 @@
assert pw(0.0, float("-inf")) == float("inf")
assert math.isnan(pw(-3, float("nan")))
assert math.isnan(pw(-3., float("nan")))
+ assert pw(-1.0, -float('inf')) == 1.0
+ assert pw(-1.0, float('inf')) == 1.0
+ assert pw(float('inf'), 0) == 1.0
+ assert pw(float('nan'), 0) == 1.0
+
+ assert math.isinf(pw(-0.5, float('-inf')))
+ assert math.isinf(pw(+0.5, float('-inf')))
+ assert pw(-1.5, float('-inf')) == 0.0
+ assert pw(+1.5, float('-inf')) == 0.0
+
+ assert str(pw(float('-inf'), -0.5)) == '0.0'
+ assert str(pw(float('-inf'), -2.0)) == '0.0'
+ assert str(pw(float('-inf'), -1.0)) == '-0.0'
+ assert str(pw(float('-inf'), 1.0)) == '-inf'
+ assert str(pw(float('-inf'), 2.0)) == 'inf'
def test_pow_neg_base(self):
import math
More information about the Pypy-commit
mailing list