[pypy-commit] pypy numpypy-out: add more ufunc tests, try an implementation

mattip noreply at buildbot.pypy.org
Tue Feb 14 22:13:33 CET 2012


Author: mattip
Branch: numpypy-out
Changeset: r52477:08b7ccd7985e
Date: 2012-02-14 22:46 +0200
http://bitbucket.org/pypy/pypy/changeset/08b7ccd7985e/

Log:	add more ufunc tests, try an implementation

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
@@ -35,6 +35,7 @@
         kwds_w.pop('casting', None)
         w_subok = kwds_w.pop('subok', None)
         w_out = kwds_w.pop('out', space.w_None)
+        # Setup a default value for out
         if space.is_w(w_out, space.w_None):
             out = None
         else:
@@ -46,13 +47,17 @@
             raise OperationError(space.w_ValueError,
                 space.wrap("invalid number of arguments")
             )
-        elif len(args_w) > self.argcount:
+        elif (len(args_w) > self.argcount and out is not None) or \
+             (len(args_w) > self.argcount + 1):
             raise OperationError(space.w_TypeError,
                 space.wrap("invalid number of arguments")
             )
-        elif out is not None:
+        # Override the default out value, if it has been provided in w_wargs
+        if len(args_w) > self.argcount:
+            out = args_w[-1]
+        else:
             args_w = args_w[:] + [out]
-        if args_w[-1] and not isinstance(args_w[-1], BaseArray):
+        if out is not None and not isinstance(out, BaseArray):
             raise OperationError(space.w_TypeError, space.wrap(
                                             'output must be an array'))
         return self.call(space, args_w)
@@ -223,23 +228,34 @@
 
     def call(self, space, args_w):
         from pypy.module.micronumpy.interp_numarray import (Call1,
-            convert_to_array, Scalar)
+            convert_to_array, Scalar, shape_agreement)
 
-        [w_obj, w_out] = args_w
+        if len(args_w)<2:
+            [w_obj] = args_w
+            out = None
+        else:
+            [w_obj, out] = args_w
         w_obj = convert_to_array(space, w_obj)
         calc_dtype = find_unaryop_result_dtype(space,
                                   w_obj.find_dtype(),
                                   promote_to_float=self.promote_to_float,
                                   promote_bools=self.promote_bools)
-        if self.bool_result:
+        if out:
+            ret_shape = shape_agreement(space, w_obj.shape, out.shape)
+            assert(ret_shape is not None)
+            res_dtype = out.find_dtype()
+        elif self.bool_result:
             res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
         else:
             res_dtype = calc_dtype
         if isinstance(w_obj, Scalar):
-            return space.wrap(self.func(calc_dtype, w_obj.value.convert_to(calc_dtype)))
+            arr = self.func(calc_dtype, w_obj.value.convert_to(calc_dtype))
+            if isinstance(out,Scalar):
+                out.value=arr
+            return space.wrap(out)
 
         w_res = Call1(self.func, self.name, w_obj.shape, calc_dtype, res_dtype,
-                      w_obj)
+                      w_obj, out)
         w_obj.add_invalidates(w_res)
         return w_res
 
@@ -259,11 +275,14 @@
     def call(self, space, args_w):
         from pypy.module.micronumpy.interp_numarray import (Call2,
             convert_to_array, Scalar, shape_agreement, BaseArray)
-
-        [w_lhs, w_rhs, w_out] = args_w
+        if len(args_w)>2:
+            [w_lhs, w_rhs, w_out] = args_w
+        else:
+            [w_lhs, w_rhs] = args_w
+            w_out = None
         w_lhs = convert_to_array(space, w_lhs)
         w_rhs = convert_to_array(space, w_rhs)
-        if space.is_w(w_out, space.w_None) or not w_out:
+        if space.is_w(w_out, space.w_None) or w_out is None:
             out = None
             calc_dtype = find_binop_result_dtype(space,
                 w_lhs.find_dtype(), w_rhs.find_dtype(),
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -902,35 +902,6 @@
         assert (array([[1,2],[3,4]]).prod(0) == [3, 8]).all()
         assert (array([[1,2],[3,4]]).prod(1) == [2, 12]).all()
 
-    def test_reduce_out(self):
-        from numpypy import arange, zeros, array
-        a = arange(15).reshape(5, 3)
-        b = arange(12).reshape(4,3)
-        c = a.sum(0, out=b[1])
-        assert (c == [30, 35, 40]).all()
-        assert (c == b[1]).all()
-        raises(ValueError, 'a.prod(0, out=arange(10))')
-        a=arange(12).reshape(3,2,2)
-        raises(ValueError, 'a.sum(0, out=arange(12).reshape(3,2,2))')
-        raises(ValueError, 'a.sum(0, out=arange(3))')
-        c = array([-1, 0, 1]).sum(out=zeros([], dtype=bool))
-        #You could argue that this should product False, but
-        # that would require an itermediate result. Cpython numpy
-        # gives True.
-        assert c == True
-        a = array([[-1, 0, 1], [1, 0, -1]])
-        c = a.sum(0, out=zeros((3,), dtype=bool))
-        assert (c == [True, False, True]).all()
-        c = a.sum(1, out=zeros((2,), dtype=bool))
-        assert (c == [True, True]).all()
-
-    def test_reduce_intermediary(self):
-        from numpypy import arange, array
-        a = arange(15).reshape(5, 3)
-        b = array(range(3), dtype=bool)
-        c = a.prod(0, out=b)
-        assert(b == [False,  True,  True]).all()
-
     def test_identity(self):
         from _numpypy import identity, array
         from _numpypy import int32, float64, dtype
diff --git a/pypy/module/micronumpy/test/test_outarg.py b/pypy/module/micronumpy/test/test_outarg.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_outarg.py
@@ -0,0 +1,48 @@
+import py
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+class AppTestOutArg(BaseNumpyAppTest):
+    def test_reduce_out(self):
+        from numpypy import arange, zeros, array
+        a = arange(15).reshape(5, 3)
+        b = arange(12).reshape(4,3)
+        c = a.sum(0, out=b[1])
+        assert (c == [30, 35, 40]).all()
+        assert (c == b[1]).all()
+        raises(ValueError, 'a.prod(0, out=arange(10))')
+        a=arange(12).reshape(3,2,2)
+        raises(ValueError, 'a.sum(0, out=arange(12).reshape(3,2,2))')
+        raises(ValueError, 'a.sum(0, out=arange(3))')
+        c = array([-1, 0, 1]).sum(out=zeros([], dtype=bool))
+        #You could argue that this should product False, but
+        # that would require an itermediate result. Cpython numpy
+        # gives True.
+        assert c == True
+        a = array([[-1, 0, 1], [1, 0, -1]])
+        c = a.sum(0, out=zeros((3,), dtype=bool))
+        assert (c == [True, False, True]).all()
+        c = a.sum(1, out=zeros((2,), dtype=bool))
+        assert (c == [True, True]).all()
+
+    def test_reduce_intermediary(self):
+        from numpypy import arange, array
+        a = arange(15).reshape(5, 3)
+        b = array(range(3), dtype=bool)
+        c = a.prod(0, out=b)
+        assert(b == [False,  True,  True]).all()
+
+    def test_ufunc_out(self):
+        from _numpypy import array, negative, zeros
+        a = array([[1, 2], [3, 4]])
+        c = zeros((2,2,2))
+        b = negative(a + a, out=c[1])
+        assert (b == [[-2, -4], [-6, -8]]).all()
+        assert (c[:, :, 1] == [[0, 0], [-4, -8]]).all()
+
+    def test_ufunc_cast(self):
+        from _numpypy import array, negative
+        cast_error = raises(TypeError, negative, array(16,dtype=float),
+                                                 out=array(0, dtype=int))
+        assert str(cast_error.value) == \
+            "Cannot cast ufunc negative output from dtype('float64') to dtype('int64') with casting rule 'same_kind'"
+        


More information about the pypy-commit mailing list