[pypy-commit] pypy default: merge numpy-unify-methods which checks that there exists an implementation or an exception for all single-arg ufuncs on all base numpypy dtypes, and implements the missing ones

mattip noreply at buildbot.pypy.org
Mon Feb 25 23:12:20 CET 2013


Author: Matti Picus <matti.picus at gmail.com>
Branch: 
Changeset: r61800:f5a6f7eb7622
Date: 2013-02-25 23:20 +0200
http://bitbucket.org/pypy/pypy/changeset/f5a6f7eb7622/

Log:	merge numpy-unify-methods which checks that there exists an
	implementation or an exception for all single-arg ufuncs on all base
	numpypy dtypes, and implements the missing ones

diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -39,6 +39,7 @@
 .. branch: task-decorator
 .. branch: fix-e4fa0b2
 .. branch: win32-fixes
+.. branch: numpy-unify-methods
 .. branch: fix-version-tool
 .. branch: popen2-removal
 
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
@@ -258,6 +258,9 @@
         if w_obj.get_dtype().is_flexible_type():
             raise OperationError(space.w_TypeError, 
                       space.wrap('Not implemented for this type'))
+        if self.int_only and not w_obj.get_dtype().is_int_type():
+            raise OperationError(space.w_TypeError, space.wrap(
+                "ufunc %s not supported for the input type" % self.name))
         calc_dtype = find_unaryop_result_dtype(space,
                                   w_obj.get_dtype(),
                                   promote_to_float=self.promote_to_float,
@@ -337,6 +340,9 @@
             promote_bools=self.promote_bools,
             allow_complex=self.allow_complex,
             )
+        if self.int_only and not calc_dtype.is_int_type():
+            raise OperationError(space.w_TypeError, space.wrap(
+                "ufunc '%s' not supported for the input types" % self.name))
         if space.is_none(w_out):
             out = None
         elif not isinstance(w_out, W_NDimArray):
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
@@ -82,6 +82,52 @@
         for i in range(3):
             assert min_c_b[i] == min(b[i], c)
 
+    def test_scalar(self):
+        # tests that by calling all available ufuncs on scalars, none will
+        # raise uncaught interp-level exceptions, (and crash the test)
+        # and those that are uncallable can be accounted for.
+        # test on the four base-class dtypes: int, bool, float, complex
+        # We need this test since they have no common base class.
+        import numpypy as np
+        def find_uncallable_ufuncs(v):
+            uncallable = []
+            for s in dir(np):
+                u = getattr(np, s)
+                if isinstance(u, np.ufunc) and u.nin < 2:
+                    try:
+                        u(a)
+                    except TypeError:
+                        #assert e.message.startswith('ufunc')
+                        uncallable.append(s)
+                elif isinstance(u, np.ufunc) and u.nin ==2:
+                    try:
+                        u(a, a)
+                    except TypeError:
+                        #assert e.message.startswith('ufunc')
+                        uncallable.append(s)
+            return uncallable
+        a = np.array(0,'int64')
+        uncallable = find_uncallable_ufuncs(a) 
+        assert len(uncallable) == 0
+        a = np.array(True,'bool')
+        uncallable = find_uncallable_ufuncs(a) 
+        assert len(uncallable) == 0 or uncallable == ['sign'] # numpy 1.7.0
+        a = np.array(1.0,'float')
+        uncallable = find_uncallable_ufuncs(a) 
+        assert len(uncallable) == 2 and set(uncallable) == set(['bitwise_not', 'invert']) 
+        a = np.array(1.0,'complex')
+        uncallable = find_uncallable_ufuncs(a) 
+        assert len(uncallable) == 13
+        assert set(uncallable) == \
+            set(['bitwise_not', 'ceil', 'deg2rad', 'degrees', 'fabs', 'floor',
+                'rad2deg', 'invert', 'isneginf', 'isposinf', 'radians',  'signbit',
+                'trunc'])
+
+    def test_int_only(self):
+        from numpypy import bitwise_and, array
+        a = array(1.0)
+        raises(TypeError, bitwise_and, a, a)
+
     def test_negative(self):
         from numpypy import array, negative
 
@@ -249,13 +295,16 @@
         assert (a == ref).all()
 
     def test_signbit(self):
-        from numpypy import signbit
+        from numpypy import signbit, add
 
         assert (signbit([0, 0.0, 1, 1.0, float('inf')]) ==
             [False, False, False, False, False]).all()
         assert (signbit([-0, -0.0, -1, -1.0, float('-inf')]) ==
             [False,  True,  True,  True,  True]).all()
 
+        a = add.identity
+        assert signbit(a) == False
+
         skip('sign of nan is non-determinant')
         assert (signbit([float('nan'), float('-nan'), -float('nan')]) ==
             [False, True, True]).all()    
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
@@ -7,6 +7,7 @@
 from pypy.objspace.std.floatobject import float2string
 from pypy.objspace.std.complexobject import str_format
 from rpython.rlib import rfloat, clibffi, rcomplex
+from rpython.rlib.rarithmetic import maxint
 from rpython.rlib.rawstorage import (alloc_raw_storage, raw_storage_setitem,
                                   raw_storage_getitem)
 from rpython.rlib.objectmodel import specialize
@@ -375,6 +376,20 @@
     def invert(self, v):
         return ~v
 
+    @raw_unary_op
+    def isfinite(self, v):
+        return True
+
+    @raw_unary_op
+    def signbit(self, v):
+        return False
+
+    @simple_unary_op
+    def reciprocal(self, v):
+        if v:
+            return 1
+        return 0
+
 NonNativeBool = Bool
 
 class Integer(Primitive):
@@ -479,6 +494,17 @@
     def invert(self, v):
         return ~v
 
+    @simple_unary_op
+    def reciprocal(self, v):
+        if v == 0:
+            # XXX good place to warn
+            return -maxint
+        return 1 / v
+
+    @raw_unary_op
+    def signbit(self, v):
+        return v < 0
+
 class NonNativeInteger(NonNativePrimitive, Integer):
     _mixin_ = True
 


More information about the pypy-commit mailing list