Author: mattip <matti.pi...@gmail.com>
Branch: ufuncapi
Changeset: r73997:8b581c9fd1d1
Date: 2014-10-17 08:57 -0500
http://bitbucket.org/pypy/pypy/changeset/8b581c9fd1d1/

Log:    progress toward using nditer, discover missing functionality

diff --git a/pypy/module/cpyext/ndarrayobject.py 
b/pypy/module/cpyext/ndarrayobject.py
--- a/pypy/module/cpyext/ndarrayobject.py
+++ b/pypy/module/cpyext/ndarrayobject.py
@@ -278,5 +278,5 @@
     w_name = rffi.charp2str(name)
     w_identity = space.wrap(identity)
     ufunc_generic = ufuncs.frompyfunc(space, w_funcs, nin, nout, w_dtypes,
-                 w_signature, w_identity, w_name, w_doc)
+                 w_signature, w_identity, w_name, w_doc, stack_inputs=True)
     return ufunc_generic
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
@@ -170,8 +170,11 @@
         ufunc = frompyfunc([times_2], 1, 1,
                             signature='(m,m)->(m,m)',
                             dtypes=[dtype(int), dtype(int)],
+                            stack_inputs=True,
                           )
         ai = arange(18, dtype=int).reshape(2,3,3)
+        exc = raises(ValueError, ufunc, ai[:,:,0])
+        assert "mismatch in its core dimension 1" in exc.value.message
         ai2 = ufunc(ai)
         assert all(ai1 == ai * 2)
 
diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py
--- a/pypy/module/micronumpy/ufuncs.py
+++ b/pypy/module/micronumpy/ufuncs.py
@@ -9,6 +9,7 @@
 from pypy.module.micronumpy import boxes, descriptor, loop, constants as NPY
 from pypy.module.micronumpy.base import convert_to_array, W_NDimArray
 from pypy.module.micronumpy.ctors import numpify
+from pypy.module.micronumpy.nditer import W_NDIter
 from pypy.module.micronumpy.strides import shape_agreement
 from pypy.module.micronumpy.support import _parse_signature
 from rpython.rlib.rawstorage import (raw_storage_setitem, free_raw_storage,
@@ -516,7 +517,7 @@
     '''
     _immutable_fields_ = ["funcs", "dtypes", "data", "match_dtypes"]
 
-    def __init__(self, space, funcs, name, identity, nin, nout, dtypes, 
signature, match_dtypes=False):
+    def __init__(self, space, funcs, name, identity, nin, nout, dtypes, 
signature, match_dtypes=False, stack_inputs=False):
         # XXX make sure funcs, signature, dtypes, nin, nout are consistent
 
         # These don't matter, we use the signature and dtypes for determining
@@ -540,6 +541,7 @@
         self.signature = signature
         #These will be filled in by _parse_signature
         self.core_enabled = True    # False for scalar ufunc, True for 
generalized ufunc
+        self.stack_inputs = stack_inputs
         self.core_num_dim_ix = 0 # number of distinct dimention names in 
signature
         self.core_num_dims = [0] * self.nargs  # number of core dimensions of 
each nargs
         self.core_offsets = [0] * self.nargs
@@ -620,13 +622,14 @@
             while(idim < num_dims):
                 core_dim_index = self.core_dim_ixs[dim_offset + idim]
                 op_dim_size = curarg.get_shape()[core_start_dim + idim]
-                if inner_dimensions[i + 1] == 1:
-                    inner_dimensions[i + 1] = op_dim_size
+                if inner_dimensions[core_dim_index + 1] == 1:
+                    inner_dimensions[core_dim_index + 1] = op_dim_size
                 elif op_dim_size != 1 and inner_dimensions[1 + core_dim_index] 
!= op_dim_size:
-                    oefmt(space.w_ValueError, "%s: Operand %d has a mismatch 
in "
-                        " its core dimension %d, with gufunc signature %s "
-                        "(size %d is different from %d)", self.name, i, idim,
-                    self.signature, op_dim_size, inner_dimensions[1 + 
core_dim_index])
+                    raise oefmt(space.w_ValueError, "%s: Operand %d has a "
+                        "mismatch in its core dimension %d, with gufunc "
+                        "signature %s (size %d is different from %d)",
+                         self.name, i, idim, self.signature, op_dim_size,
+                         inner_dimensions[1 + core_dim_index])
                 idim += 1
         for i in range(len(outargs)):
             curarg = outargs[i]
@@ -635,10 +638,10 @@
             num_dims = self.core_num_dims[i]
             core_start_dim = curarg.ndims() - num_dims
             if core_start_dim < 0:
-                oefmt(space.w_ValueError, "%s: Output operand %d does not"
-                    "have enough dimensions (has %d, gufunc with signature "
-                    "%s requires %d)", self.name, i, curarg.ndims(),
-                    self.signature, num_dims)
+                raise oefmt(space.w_ValueError, "%s: Output operand %d does "
+                    "not have enough dimensions (has %d, gufunc with "
+                    "signature %s requires %d)", self.name, i,
+                    curarg.ndims(), self.signature, num_dims)
             if core_start_dim >=0:
                 idim = 0
             else:
@@ -646,13 +649,14 @@
             while(idim < num_dims):
                 core_dim_index = self.core_dim_ixs[dim_offset + idim]
                 op_dim_size = curarg.get_shape()[core_start_dim + idim]
-                if inner_dimensions[i + 1] == 1:
-                    inner_dimensions[i + 1] = op_dim_size
+                if inner_dimensions[core_dim_index + 1] == 1:
+                    inner_dimensions[core_dim_index + 1] = op_dim_size
                 elif inner_dimensions[1 + core_dim_index] != op_dim_size:
-                    oefmt(space.w_ValueError, "%s: Operand %d has a mismatch 
in "
-                        " its core dimension %d, with gufunc signature %s "
-                        "(size %d is different from %d)", self.name, i, idim,
-                    self.signature, op_dim_size, inner_dimensions[1 + 
core_dim_index])
+                    raise oefmt(space.w_ValueError, "%s: Operand %d has a "
+                        "mismatch in its core dimension %d, with gufunc "
+                        "signature %s (size %d is different from %d)",
+                         self.name, i, idim, self.signature, op_dim_size,
+                         inner_dimensions[1 + core_dim_index])
                 idim += 1
         iter_shape = [-1] * (broadcast_ndim + (len(outargs) * iter_ndim))
         j = broadcast_ndim
@@ -693,12 +697,21 @@
         # the current op (signalling it can handle ndarray's).
 
         # TODO parse and handle subok
+        # TODO handle flags, op_flags
+        flags = ['external_loop']
+        op_flags = None
 
         # mimic NpyIter_AdvancedNew with a nditer
 
-        if isinstance(func, W_GenericUFuncCaller):
-            pass
-            # xxx rdo what needs to be done to inner-loop indexing
+        if self.stack_inputs:
+            inargs = inargs + outargs
+            it = W_NDIter(space, space.newlist(inargs + outargs),
+                            flags=flags, op_flags=op_flags,
+            for args in it:
+                space.call_args(func, Arguments.frompacked(space, args))
+            if len(outargs) > 1:
+                return outargs
+            return outargs[0]
         inargs0 = inargs[0]
         assert isinstance(inargs0, W_NDimArray)
         new_shape = inargs0.get_shape()
@@ -1104,12 +1117,12 @@
     return space.fromcache(UfuncState)
 
 @unwrap_spec(nin=int, nout=int, signature=str, w_identity=WrappedDefault(None),
-             name=str, doc=str)
+             name=str, doc=str, stack_inputs=bool)
 def frompyfunc(space, w_func, nin, nout, w_dtypes=None, signature='',
-     w_identity=None, name='', doc=''):
+     w_identity=None, name='', doc='', stack_inputs=False):
     ''' frompyfunc(func, nin, nout) #cpython numpy compatible
         frompyfunc(func, nin, nout, dtypes=None, signature='',
-                   identity=None, name='', doc='')
+                   identity=None, name='', doc='', stack_inputs=False)
 
     Takes an arbitrary Python function and returns a ufunc.
 
@@ -1133,6 +1146,10 @@
          For reduce-type ufuncs, the default value
     name: str, default=''
     doc: str, default=''
+    stack_inputs*: boolean, whether the function is of the form
+            out = func(*in)     False
+            or
+            func(*in_out)       True
 
     only one of out_dtype or signature may be specified
 
@@ -1143,8 +1160,9 @@
 
     Notes
     -----
-    If the signature and out_dtype are both missing, the returned ufunc always
-    returns PyObject arrays (cpython numpy compatability).
+    If the signature and out_dtype are both missing, the returned ufunc
+        always returns PyObject arrays (cpython numpy compatability).
+    Input arguments marked with a * are pypy-only extensions
 
     Examples
     --------
@@ -1201,8 +1219,9 @@
         # cpython compatability, func is of the form (i),(i)->(i)
         signature = ','.join(['(i)'] * nin) + '->' + ','.join(['(i)'] * nout)
 
-    w_ret = W_UfuncGeneric(space, func, name, identity, nin, nout, dtypes, 
signature,
-                                match_dtypes=match_dtypes)
+    w_ret = W_UfuncGeneric(space, func, name, identity, nin, nout, dtypes,
+                           signature, match_dtypes=match_dtypes,
+                           stack_inputs=stack_inputs)
     _parse_signature(space, w_ret, w_ret.signature)
     if doc:
         w_ret.w_doc = space.wrap(doc)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to