[pypy-commit] pypy ufuncapi: backed out changeset ca3b82260c3a, signatures are still relevant

mattip noreply at buildbot.pypy.org
Wed Aug 13 00:01:12 CEST 2014


Author: mattip <matti.picus at gmail.com>
Branch: ufuncapi
Changeset: r72770:86f97db12e19
Date: 2014-08-09 21:53 +0300
http://bitbucket.org/pypy/pypy/changeset/86f97db12e19/

Log:	backed out changeset ca3b82260c3a, signatures are still relevant

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
@@ -139,7 +139,7 @@
             out_flat = out_array.flat
             for i in range(in_array.size):
                 out_flat[i] = in_flat[i] * 2
-        def double_times2(in_array, out_array):
+        def double_times2(space, __args__):
             assert in_array.dtype == float
             in_flat = in_array.flat
             out_flat = out_array.flat
@@ -147,6 +147,7 @@
                 out_flat[i] = in_flat[i] * 2
         from numpy import frompyfunc, dtype, arange
         ufunc = frompyfunc([int_times2, double_times2], 1, 1, 
+                            signature='()->()',
                             dtypes=[dtype(int), dtype(int),
                             dtype(float), dtype(float)
                             ]
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
@@ -482,20 +482,22 @@
 
 class W_UfuncGeneric(W_Ufunc):
     '''
-    Handle a number of python functions, each with a dtypes.
-    The dtypes can specify the input, output args for the function. 
-    When called, the actual function used will be resolved by examining
-    the input arg's dtypes.
+    Handle a number of python functions, each with a signature and dtypes.
+    The signature can specify how to create the inner loop, i.e.
+    (i,j),(j,k)->(i,k) for a dot-like matrix multiplication, and the dtypes
+    can specify the input, output args for the function. When called, the actual
+    function used will be resolved by examining the input arg's dtypes.
 
     If dtypes == 'match', only one argument is provided and the output dtypes
     will match the input dtype (not cpython numpy compatible)
     '''
     _immutable_fields_ = ["funcs", "dtypes", "data"]
 
-    def __init__(self, space, funcs, name, identity, nin, nout, dtypes, match_dtypes=False):
-        # XXX make sure funcs, dtypes, nin, nout are consistent
+    def __init__(self, space, funcs, name, identity, nin, nout, dtypes, signature, match_dtypes=False):
+        # XXX make sure funcs, signature, dtypes, nin, nout are consistent
 
-        # These don't matter, we use the dtypes for determining output dtype
+        # These don't matter, we use the signature and dtypes for determining
+        # output dtype
         promote_to_largest = promote_to_float = promote_bools = False
         allow_bool = allow_complex = True
         int_only = complex_to_float = False
@@ -512,6 +514,7 @@
             raise oefmt(space.w_ValueError,
                 "generic ufunc with %d functions, %d arguments, but %d dtypes",
                 len(funcs), self.nargs, len(dtypes))
+        self.signature = signature
 
     def reduce(self, space, w_obj, w_axis, keepdims=False, out=None, dtype=None,
                cumulative=False):
@@ -542,30 +545,27 @@
         new_shape = inargs[0].get_shape()
         assert isinstance(outargs[0], W_NDimArray)
         res_dtype = outargs[0].get_dtype()
-        if not self.match_dtypes:
+        # XXX handle inner-loop indexing
+        sign_parts = self.signature.split('->')
+        if len(sign_parts) == 2 and sign_parts[0].strip() == '()' \
+                                and sign_parts[1].strip() == '()':
+                                        
+            arglist = space.newlist(inargs + outargs)
             func = self.funcs[index]
             space.call_function(func, *(inargs + outargs))
             if len(outargs) < 2:
                 return outargs[0]
             return outargs
-        # XXX TODO handle more complicated signatures,
-        #          for now, assume (i) -> (i)
         if len(outargs) < 2:
             return loop.call_many_to_one(space, new_shape, self.funcs[index],
                                          res_dtype, inargs, outargs[0])
         return loop.call_many_to_many(space, new_shape, self.funcs[index],
                                      res_dtype, inargs, outargs)
 
-    def type_resolver(self, space, inargs, outargs):
+    def type_resolver(self, space, index, outargs):
         # Find a match for the inargs.dtype in self.dtypes, like
         # linear_search_type_resolver in numy ufunc_type_resolutions.c
-        for i in range(0, len(self.dtypes), self.nargs):
-            if inargs[0].get_dtype() == self.dtypes[i]:
-                break
-        else:
-            raise oefmt(space.w_TypeError,
-                         'input dtype %r did not match any known dtypes', inargs[0].get_dtype())
-        return i / self.nargs
+        return 0
 
     def alloc_outargs(self, space, index, inargs, outargs):
         # Any None outarg should be allocated here
@@ -911,12 +911,12 @@
 def get(space):
     return space.fromcache(UfuncState)
 
- at unwrap_spec(nin=int, nout=int, w_identity=WrappedDefault(None),
+ at unwrap_spec(nin=int, nout=int, signature=str, w_identity=WrappedDefault(None),
              name=str, doc=str)
-def frompyfunc(space, w_func, nin, nout, w_dtypes=None,
+def frompyfunc(space, w_func, nin, nout, w_dtypes=None, signature='',
      w_identity=None, name='', doc=''):
     ''' frompyfunc(func, nin, nout) #cpython numpy compatible
-        frompyfunc(func, nin, nout, dtypes=None, 
+        frompyfunc(func, nin, nout, dtypes=None, signature='',
                    identity=None, name='', doc='')
 
     Takes an arbitrary Python function and returns a ufunc.
@@ -934,6 +934,9 @@
         The number of arrays returned by `func`.
     dtypes: None or [dtype, ...] of the input, output args for each function,
                or 'match' to force output to exactly match input dtype
+    signature*: str, default=''
+         The mapping of input args to output args, defining the
+         inner-loop indexing
     identity*: None (default) or int
          For reduce-type ufuncs, the default value
     name: str, default=''
@@ -948,7 +951,7 @@
 
     Notes
     -----
-    If the signature and dtypes are both missing, the returned ufunc always
+    If the signature and out_dtype are both missing, the returned ufunc always
     returns PyObject arrays (cpython numpy compatability).
 
     Examples
@@ -976,7 +979,7 @@
             raise oefmt(space.w_TypeError, 'func must be callable')
         func = [w_func]
     match_dtypes = False    
-    if space.is_none(w_dtypes):
+    if space.is_none(w_dtypes) and not signature:
         raise oefmt(space.w_NotImplementedError,
              'object dtype requested but not implemented')
     elif (space.isinstance_w(w_dtypes, space.w_tuple) or
@@ -988,7 +991,9 @@
             else:    
                 dtypes = [None]*len(_dtypes)
                 for i in range(len(dtypes)):
+                    print 'decoding',_dtypes[i]
                     dtypes[i] = descriptor.decode_w_dtype(space, _dtypes[i])
+                    print 'got',dtypes[i]
     else:
         raise oefmt(space.w_ValueError,
             'dtypes must be None or a list of dtypes')
@@ -999,7 +1004,7 @@
         identity = \
             descriptor.get_dtype_cache(space).w_longdtype.box(w_identity)
 
-    w_ret = W_UfuncGeneric(space, func, name, identity, nin, nout, dtypes,
+    w_ret = W_UfuncGeneric(space, func, name, identity, nin, nout, dtypes, signature,
                                 match_dtypes=match_dtypes)
     if doc:
         w_ret.w_doc = space.wrap(doc)


More information about the pypy-commit mailing list