Author: mattip <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit