# [pypy-commit] pypy numpy-ufuncs2: Fixing power (int and float)

Tue Mar 13 09:23:23 CET 2012

```Author: Taavi Burns <taavi.burns at gmail.com>
Branch: numpy-ufuncs2
Changeset: r53440:581e835ab9ef
Date: 2012-03-13 01:20 -0700
http://bitbucket.org/pypy/pypy/changeset/581e835ab9ef/

Log:	Fixing power (int and float)

diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -577,7 +577,7 @@
assert log1p(float('inf')) == float('inf')
assert (log1p([0, 1e-50, math.e - 1]) == [0, 1e-50, 1]).all()

-    def test_power(self):
+    def test_power_float(self):
import math
from _numpypy import power, array
a = array([1., 2., 3.])
@@ -591,6 +591,44 @@
for i in range(len(a)):
assert c[i] == a[i] ** b[i]

+        assert power(2, float('inf')) == float('inf')
+        assert power(float('inf'), float('inf')) == float('inf')
+        assert power(12345.0, 12345.0) == float('inf')
+        assert power(-12345.0, 12345.0) == float('-inf')
+        assert power(-12345.0, 12346.0) == float('inf')
+        assert math.isnan(power(-1, 1.1))
+        assert math.isnan(power(-1, -1.1))
+        assert power(-2.0, -1) == -0.5
+        assert power(-2.0, -2) == 0.25
+        assert power(12345.0, -12345.0) == 0
+        assert power(float('-inf'), 2) == float('inf')
+        assert power(float('-inf'), 2.5) == float('inf')
+        assert power(float('-inf'), 3) == float('-inf')
+
+    def test_power_int(self):
+        import math
+        from _numpypy import power, array
+        a = array([1, 2, 3])
+        b = power(a, 3)
+        for i in range(len(a)):
+            assert b[i] == a[i] ** 3
+
+        a = array([1, 2, 3])
+        b = array([1, 2, 3])
+        c = power(a, b)
+        for i in range(len(a)):
+            assert c[i] == a[i] ** b[i]
+
+        # assert power(12345, 12345) == -9223372036854775808
+        # assert power(-12345, 12345) == -9223372036854775808
+        # assert power(-12345, 12346) == -9223372036854775808
+        assert power(2, 0) == 1
+        assert power(2, -1) == 0
+        assert power(2, -2) == 0
+        assert power(-2, -1) == 0
+        assert power(-2, -2) == 0
+        assert power(12345, -12345) == 0
+
def test_floordiv(self):
from _numpypy import floor_divide, array
a = array([1., 2., 3., 4., 5., 6., 6.01])
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -293,6 +293,8 @@

@simple_binary_op
def pow(self, v1, v2):
+        if v2 < 0:
+            return 0
res = 1
while v2 > 0:
if v2 & 1:
@@ -440,7 +442,15 @@

@simple_binary_op
def pow(self, v1, v2):
-        return math.pow(v1, v2)
+        try:
+            return math.pow(v1, v2)
+        except ValueError:
+            return rfloat.NAN
+        except OverflowError:
+            if math.modf(v2)[0] == 0 and math.modf(v2 / 2)[0] != 0:
+                # Odd integer powers result in the same sign as the base
+                return rfloat.copysign(rfloat.INFINITY, v1)
+            return rfloat.INFINITY

@simple_binary_op
def copysign(self, v1, v2):
```