[pypy-commit] pypy default: (taavi) Merged numpy-ufuncs2, adds a ton of more ufuncs to numpypy.

alex_gaynor noreply at buildbot.pypy.org
Fri Mar 16 21:58:41 CET 2012


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: 
Changeset: r53733:9bca9727b9a9
Date: 2012-03-16 15:57 -0500
http://bitbucket.org/pypy/pypy/changeset/9bca9727b9a9/

Log:	(taavi) Merged numpy-ufuncs2, adds a ton of more ufuncs to numpypy.

diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -67,6 +67,7 @@
         ("arccos", "arccos"),
         ("arcsin", "arcsin"),
         ("arctan", "arctan"),
+        ("arctan2", "arctan2"),
         ("arccosh", "arccosh"),
         ("arcsinh", "arcsinh"),
         ("arctanh", "arctanh"),
@@ -77,7 +78,10 @@
         ("true_divide", "true_divide"),
         ("equal", "equal"),
         ("exp", "exp"),
+        ("exp2", "exp2"),
+        ("expm1", "expm1"),
         ("fabs", "fabs"),
+        ("fmod", "fmod"),
         ("floor", "floor"),
         ("ceil", "ceil"),
         ("greater", "greater"),
@@ -92,8 +96,10 @@
         ("radians", "radians"),
         ("degrees", "degrees"),
         ("deg2rad", "radians"),
+        ("rad2deg", "degrees"),
         ("reciprocal", "reciprocal"),
         ("sign", "sign"),
+        ("signbit", "signbit"),
         ("sin", "sin"),
         ("sinh", "sinh"),
         ("subtract", "subtract"),
@@ -106,6 +112,9 @@
         ('bitwise_not', 'invert'),
         ('isnan', 'isnan'),
         ('isinf', 'isinf'),
+        ('isneginf', 'isneginf'),
+        ('isposinf', 'isposinf'),
+        ('isfinite', 'isfinite'),
         ('logical_and', 'logical_and'),
         ('logical_xor', 'logical_xor'),
         ('logical_not', 'logical_not'),
@@ -116,6 +125,8 @@
         ('log1p', 'log1p'),
         ('power', 'power'),
         ('floor_divide', 'floor_divide'),
+        ('logaddexp', 'logaddexp'),
+        ('logaddexp2', 'logaddexp2'),
     ]:
         interpleveldefs[exposed] = "interp_ufuncs.get(space).%s" % impl
 
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -404,6 +404,9 @@
             ("greater_equal", "ge", 2, {"comparison_func": True}),
             ("isnan", "isnan", 1, {"bool_result": True}),
             ("isinf", "isinf", 1, {"bool_result": True}),
+            ("isneginf", "isneginf", 1, {"bool_result": True}),
+            ("isposinf", "isposinf", 1, {"bool_result": True}),
+            ("isfinite", "isfinite", 1, {"bool_result": True}),
 
             ('logical_and', 'logical_and', 2, {'comparison_func': True,
                                                'identity': 1}),
@@ -421,12 +424,16 @@
             ("negative", "neg", 1),
             ("absolute", "abs", 1),
             ("sign", "sign", 1, {"promote_bools": True}),
+            ("signbit", "signbit", 1, {"bool_result": True}),
             ("reciprocal", "reciprocal", 1),
 
             ("fabs", "fabs", 1, {"promote_to_float": True}),
+            ("fmod", "fmod", 2, {"promote_to_float": True}),
             ("floor", "floor", 1, {"promote_to_float": True}),
             ("ceil", "ceil", 1, {"promote_to_float": True}),
             ("exp", "exp", 1, {"promote_to_float": True}),
+            ("exp2", "exp2", 1, {"promote_to_float": True}),
+            ("expm1", "expm1", 1, {"promote_to_float": True}),
 
             ('sqrt', 'sqrt', 1, {'promote_to_float': True}),
 
@@ -436,6 +443,7 @@
             ("arcsin", "arcsin", 1, {"promote_to_float": True}),
             ("arccos", "arccos", 1, {"promote_to_float": True}),
             ("arctan", "arctan", 1, {"promote_to_float": True}),
+            ("arctan2", "arctan2", 2, {"promote_to_float": True}),
             ("sinh", "sinh", 1, {"promote_to_float": True}),
             ("cosh", "cosh", 1, {"promote_to_float": True}),
             ("tanh", "tanh", 1, {"promote_to_float": True}),
@@ -450,6 +458,8 @@
             ("log2", "log2", 1, {"promote_to_float": True}),
             ("log10", "log10", 1, {"promote_to_float": True}),
             ("log1p", "log1p", 1, {"promote_to_float": True}),
+            ("logaddexp", "logaddexp", 2, {"promote_to_float": True}),
+            ("logaddexp2", "logaddexp2", 2, {"promote_to_float": True}),
         ]:
             self.add_ufunc(space, *ufunc_def)
 
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
@@ -113,14 +113,37 @@
 
         assert (divide(array([-10]), array([2])) == array([-5])).all()
 
+    def test_true_divide(self):
+        from _numpypy import array, true_divide
+
+        a = array([0, 1, 2, 3, 4, 1, -1])
+        b = array([4, 4, 4, 4, 4, 0,  0])
+        c = true_divide(a, b)
+        assert (c == [0.0, 0.25, 0.5, 0.75, 1.0, float('inf'), float('-inf')]).all()
+
+        assert math.isnan(true_divide(0, 0))
+
     def test_fabs(self):
         from _numpypy import array, fabs
-        from math import fabs as math_fabs
+        from math import fabs as math_fabs, isnan
 
         a = array([-5.0, -0.0, 1.0])
         b = fabs(a)
         for i in range(3):
             assert b[i] == math_fabs(a[i])
+        assert fabs(float('inf')) == float('inf')
+        assert fabs(float('-inf')) == float('inf')
+        assert isnan(fabs(float('nan')))
+
+    def test_fmod(self):
+        from _numpypy import fmod
+        import math
+
+        assert fmod(-1e-100, 1e100) == -1e-100
+        assert fmod(3, float('inf')) == 3
+        assert (fmod([-3, -2, -1, 1, 2, 3], 2) == [-1,  0, -1,  1,  0,  1]).all()
+        for v in [float('inf'), float('-inf'), float('nan'), float('-nan')]:
+            assert math.isnan(fmod(v, 2))
 
     def test_minimum(self):
         from _numpypy import array, minimum
@@ -172,6 +195,15 @@
         assert a[0] == 1
         assert a[1] == 0
 
+    def test_signbit(self):
+        from _numpypy import signbit, copysign
+        import struct
+
+        assert (signbit([0, 0.0, 1, 1.0, float('inf'), float('nan')]) ==
+            [False, False, False, False, False, False]).all()
+        assert (signbit([-0, -0.0, -1, -1.0, float('-inf'), -float('nan'), float('-nan')]) ==
+            [False,  True,  True,  True,  True,  True, True]).all()
+
     def test_reciporocal(self):
         from _numpypy import array, reciprocal
 
@@ -231,13 +263,46 @@
         a = array([-5.0, -0.0, 0.0, 12345678.0, float("inf"),
                    -float('inf'), -12343424.0])
         b = exp(a)
-        for i in range(4):
+        for i in range(len(a)):
             try:
                 res = math.exp(a[i])
             except OverflowError:
                 res = float('inf')
             assert b[i] == res
 
+    def test_exp2(self):
+        import math
+        from _numpypy import array, exp2
+
+        a = array([-5.0, -0.0, 0.0, 2, 12345678.0, float("inf"),
+                   -float('inf'), -12343424.0])
+        b = exp2(a)
+        for i in range(len(a)):
+            try:
+                res = 2 ** a[i]
+            except OverflowError:
+                res = float('inf')
+            assert b[i] == res
+
+        assert exp2(3) == 8
+        assert math.isnan(exp2(float("nan")))
+
+    def test_expm1(self):
+        import math
+        from _numpypy import array, expm1
+
+        a = array([-5.0, -0.0, 0.0, 12345678.0, float("inf"),
+                   -float('inf'), -12343424.0])
+        b = expm1(a)
+        for i in range(4):
+            try:
+                res = math.exp(a[i]) - 1
+            except OverflowError:
+                res = float('inf')
+            assert b[i] == res
+
+        assert expm1(1e-50) == 1e-50
+
     def test_sin(self):
         import math
         from _numpypy import array, sin
@@ -310,6 +375,21 @@
         b = arctan(a)
         assert math.isnan(b[0])
 
+    def test_arctan2(self):
+        import math
+        from _numpypy import array, arctan2
+
+        # From the numpy documentation
+        assert (
+            arctan2(
+                [0.,  0.,           1.,          -1., float('inf'),  float('inf')],
+                [0., -0., float('inf'), float('inf'), float('inf'), float('-inf')]) ==
+            [0.,  math.pi,  0., -0.,  math.pi/4, 3*math.pi/4]).all()
+
+        a = array([float('nan')])
+        b = arctan2(a, 0)
+        assert math.isnan(b[0])
+
     def test_sinh(self):
         import math
         from _numpypy import array, sinh
@@ -415,6 +495,19 @@
         for i in range(len(a)):
             assert b[i] == math.degrees(a[i])
 
+    def test_rad2deg(self):
+        import math
+        from _numpypy import rad2deg, array
+        a = array([
+            -181, -180, -179,
+            181, 180, 179,
+            359, 360, 361,
+            400, -1, 0, 1,
+            float('inf'), float('-inf')])
+        b = rad2deg(a)
+        for i in range(len(a)):
+            assert b[i] == math.degrees(a[i])
+
     def test_reduce_errors(self):
         from _numpypy import sin, add
 
@@ -510,6 +603,26 @@
         assert (isinf(array([0.2, float('inf'), float('nan')])) == [False, True, False]).all()
         assert isinf(array([0.2])).dtype.kind == 'b'
 
+    def test_isposinf_isneginf(self):
+        from _numpypy import isneginf, isposinf
+        assert isposinf(float('inf'))
+        assert not isposinf(float('-inf'))
+        assert not isposinf(float('nan'))
+        assert not isposinf(0)
+        assert not isposinf(0.0)
+        assert isneginf(float('-inf'))
+        assert not isneginf(float('inf'))
+        assert not isneginf(float('nan'))
+        assert not isneginf(0)
+        assert not isneginf(0.0)
+
+    def test_isfinite(self):
+        from _numpypy import isfinite
+        assert (isfinite([0, 0.0, 1e50, -1e-50]) ==
+            [True, True, True, True]).all()
+        assert (isfinite([float('-inf'), float('inf'), float('-nan'), float('nan')]) ==
+            [False, False, False, False]).all()
+
     def test_logical_ops(self):
         from _numpypy import logical_and, logical_or, logical_xor, logical_not
 
@@ -544,7 +657,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.])
@@ -558,9 +671,94 @@
         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])
         b = floor_divide(a, 2.5)
         for i in range(len(a)):
             assert b[i] == a[i] // 2.5
+
+    def test_logaddexp(self):
+        import math
+        from _numpypy import logaddexp
+
+        # From the numpy documentation
+        prob1 = math.log(1e-50)
+        prob2 = math.log(2.5e-50)
+        prob12 = logaddexp(prob1, prob2)
+        assert math.fabs(-113.87649168120691 - prob12) < 0.000000000001
+
+        assert logaddexp(0, 0) == math.log(2)
+        assert logaddexp(float('-inf'), 0) == 0
+        assert logaddexp(12345678, 12345678) == float('inf')
+
+        assert math.isnan(logaddexp(float('nan'), 1))
+        assert math.isnan(logaddexp(1, float('nan')))
+        assert math.isnan(logaddexp(float('nan'), float('inf')))
+        assert math.isnan(logaddexp(float('inf'), float('nan')))
+        assert logaddexp(float('-inf'), float('-inf')) == float('-inf')
+        assert logaddexp(float('-inf'), float('inf')) == float('inf')
+        assert logaddexp(float('inf'), float('-inf')) == float('inf')
+        assert logaddexp(float('inf'), float('inf')) == float('inf')
+
+    def test_logaddexp2(self):
+        import math
+        from _numpypy import logaddexp2
+        log2 = math.log(2)
+
+        # From the numpy documentation
+        prob1 = math.log(1e-50) / log2
+        prob2 = math.log(2.5e-50) / log2
+        prob12 = logaddexp2(prob1, prob2)
+        assert math.fabs(-164.28904982231052 - prob12) < 0.000000000001
+
+        assert logaddexp2(0, 0) == 1
+        assert logaddexp2(float('-inf'), 0) == 0
+        assert logaddexp2(12345678, 12345678) == float('inf')
+
+        assert math.isnan(logaddexp2(float('nan'), 1))
+        assert math.isnan(logaddexp2(1, float('nan')))
+        assert math.isnan(logaddexp2(float('nan'), float('inf')))
+        assert math.isnan(logaddexp2(float('inf'), float('nan')))
+        assert logaddexp2(float('-inf'), float('-inf')) == float('-inf')
+        assert logaddexp2(float('-inf'), float('inf')) == float('inf')
+        assert logaddexp2(float('inf'), float('-inf')) == float('inf')
+        assert logaddexp2(float('inf'), float('inf')) == float('inf')
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
@@ -155,6 +155,14 @@
     def isinf(self, v):
         return False
 
+    @raw_unary_op
+    def isneginf(self, v):
+        return False
+
+    @raw_unary_op
+    def isposinf(self, v):
+        return False
+
     @raw_binary_op
     def eq(self, v1, v2):
         return v1 == v2
@@ -293,6 +301,8 @@
 
     @simple_binary_op
     def pow(self, v1, v2):
+        if v2 < 0:
+            return 0
         res = 1
         while v2 > 0:
             if v2 & 1:
@@ -440,7 +450,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):
@@ -452,10 +470,21 @@
             return 0.0
         return rfloat.copysign(1.0, v)
 
+    @raw_unary_op
+    def signbit(self, v):
+        return rfloat.copysign(1.0, v) < 0.0
+
     @simple_unary_op
     def fabs(self, v):
         return math.fabs(v)
 
+    @simple_binary_op
+    def fmod(self, v1, v2):
+        try:
+            return math.fmod(v1, v2)
+        except ValueError:
+            return rfloat.NAN
+
     @simple_unary_op
     def reciprocal(self, v):
         if v == 0.0:
@@ -478,6 +507,20 @@
             return rfloat.INFINITY
 
     @simple_unary_op
+    def exp2(self, v):
+        try:
+            return math.pow(2, v)
+        except OverflowError:
+            return rfloat.INFINITY
+
+    @simple_unary_op
+    def expm1(self, v):
+        try:
+            return rfloat.expm1(v)
+        except OverflowError:
+            return rfloat.INFINITY
+
+    @simple_unary_op
     def sin(self, v):
         return math.sin(v)
 
@@ -505,6 +548,10 @@
     def arctan(self, v):
         return math.atan(v)
 
+    @simple_binary_op
+    def arctan2(self, v1, v2):
+        return math.atan2(v1, v2)
+
     @simple_unary_op
     def sinh(self, v):
         return math.sinh(v)
@@ -550,6 +597,18 @@
     def isinf(self, v):
         return rfloat.isinf(v)
 
+    @raw_unary_op
+    def isneginf(self, v):
+        return rfloat.isinf(v) and v < 0
+
+    @raw_unary_op
+    def isposinf(self, v):
+        return rfloat.isinf(v) and v > 0
+
+    @raw_unary_op
+    def isfinite(self, v):
+        return not (rfloat.isinf(v) or rfloat.isnan(v))
+
     @simple_unary_op
     def radians(self, v):
         return v * degToRad
@@ -601,6 +660,48 @@
         except ValueError:
             return rfloat.NAN
 
+    @simple_binary_op
+    def logaddexp(self, v1, v2):
+        try:
+            v1e = math.exp(v1)
+        except OverflowError:
+            v1e = rfloat.INFINITY
+        try:
+            v2e = math.exp(v2)
+        except OverflowError:
+            v2e = rfloat.INFINITY
+
+        v12e = v1e + v2e
+        try:
+            return math.log(v12e)
+        except ValueError:
+            if v12e == 0.0:
+                # CPython raises ValueError here, so we have to check
+                # the value to find the correct numpy return value
+                return -rfloat.INFINITY
+            return rfloat.NAN
+
+    @simple_binary_op
+    def logaddexp2(self, v1, v2):
+        try:
+            v1e = math.pow(2, v1)
+        except OverflowError:
+            v1e = rfloat.INFINITY
+        try:
+            v2e = math.pow(2, v2)
+        except OverflowError:
+            v2e = rfloat.INFINITY
+
+        v12e = v1e + v2e
+        try:
+            return math.log(v12e) / log2
+        except ValueError:
+            if v12e == 0.0:
+                # CPython raises ValueError here, so we have to check
+                # the value to find the correct numpy return value
+                return -rfloat.INFINITY
+            return rfloat.NAN
+
 
 class Float32(BaseType, Float):
     T = rffi.FLOAT


More information about the pypy-commit mailing list