[pypy-svn] pypy default: Remove hack in pow() that worked only when not translated,

amauryfa commits-noreply at bitbucket.org
Tue Jan 25 18:01:06 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r41320:6d41ac77bc10
Date: 2011-01-25 17:15 +0100
http://bitbucket.org/pypy/pypy/changeset/6d41ac77bc10/

Log:	Remove hack in pow() that worked only when not translated, and don't
	rely on math.pow() to return the correct result with
	(-1)**(big_number)

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
@@ -410,6 +410,37 @@
             "pow() 3rd argument not allowed unless all arguments are integers"))
     x = w_float1.floatval
     y = w_float2.floatval
+
+    if x == 0.0:
+        if y < 0.0:
+            if isinf(y):
+                return space.wrap(INFINITY)
+            raise OperationError(space.w_ZeroDivisionError,
+                                 space.wrap("0.0 cannot be raised to "
+                                            "a negative power"))
+
+    negate_result = False
+    # special case: "(-1.0) ** bignum" should not raise ValueError,
+    # unlike "math.pow(-1.0, bignum)".  See http://mail.python.org/
+    # -           pipermail/python-bugs-list/2003-March/016795.html
+    if x < 0.0:
+        if math.floor(y) != y:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("negative number cannot be "
+                                            "raised to a fractional power"))
+        # y is an exact integer, albeit perhaps a very large one.
+        # Replace x by its absolute value and remember to negate the
+        # pow result if y is odd.
+        x = -x
+        negate_result = math.fmod(abs(y), 2.0) == 1.0
+
+    if x == 1.0:
+        # (-1) ** large_integer also ends up here
+        if negate_result:
+            return W_FloatObject(-1.0)
+        else:
+            return W_FloatObject(1.0)
+
     try:
         # We delegate to our implementation of math.pow() the error detection.
         z = math.pow(x,y)
@@ -417,33 +448,10 @@
         raise FailedToImplementArgs(space.w_OverflowError,
                                     space.wrap("float power"))
     except ValueError:
-        # special case: "(-1.0) ** bignum" should not raise ValueError,
-        # unlike "math.pow(-1.0, bignum)".  See http://mail.python.org/
-        # -           pipermail/python-bugs-list/2003-March/016795.html
-        if x < 0.0:
-            if math.floor(y) != y:
-                raise OperationError(space.w_ValueError,
-                                     space.wrap("negative number cannot be "
-                                                "raised to a fractional power"))
-            if x == -1.0:
-                if math.floor(y * 0.5) * 2.0 == y:
-                     return space.wrap(1.0)
-                else:
-                     return space.wrap( -1.0)
-        elif x == 0.0:
-            if y < 0.0:
-                if isinf(y):
-                    return space.wrap(INFINITY)
-                raise OperationError(space.w_ZeroDivisionError,
-                                     space.wrap("0.0 cannot be raised to "
-                                                "a negative power"))
         raise OperationError(space.w_ValueError,
                              space.wrap("float power"))
-    # Should the result be negated?
-    if (not we_are_translated() and sys.version_info < (2, 7) and
-        z == 0.0 and x < 0.0 and
-        not isinf(x) and not isinf(y) and
-        math.fmod(abs(y), 2.0) == 1.0):
+
+    if negate_result:
         z = -z
     return W_FloatObject(z)
 

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
@@ -209,6 +209,7 @@
         res = pw(-2.0, -2001.0)
         assert res == -0.0
         assert math.copysign(1., res) == -1.
+        assert pw(-1.0, -1e15) == 1.0
 
     def test_float_cmp(self):
         assert 12.5 == 12.5


More information about the Pypy-commit mailing list