diff options
author | Sebastian Berg <sebastian@sipsolutions.net> | 2017-03-26 14:17:25 +0200 |
---|---|---|
committer | Sebastian Berg <sebastian@sipsolutions.net> | 2017-04-29 18:22:02 +0200 |
commit | bfb41d6a93b92b6a0aa92075d6163690bb6ed71c (patch) | |
tree | b495b264f8f2171654e44d51a337b5fbc32243bb | |
parent | ef2cfe12c49ab377cfbf2f54993699b92229b907 (diff) | |
download | numpy-bfb41d6a93b92b6a0aa92075d6163690bb6ed71c.tar.gz |
ENH: Allow removal of 0-sized axes from nditer and empty gufunc calls
The caller should take of not using pointers given in such a case
-rw-r--r-- | doc/release/1.13.0-notes.rst | 18 | ||||
-rw-r--r-- | numpy/core/src/multiarray/nditer_api.c | 6 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_object.c | 37 |
3 files changed, 18 insertions, 43 deletions
diff --git a/doc/release/1.13.0-notes.rst b/doc/release/1.13.0-notes.rst index bf4f1c815..f802b4c12 100644 --- a/doc/release/1.13.0-notes.rst +++ b/doc/release/1.13.0-notes.rst @@ -99,6 +99,24 @@ now issue a DeprecationWarning - ``.__getitem__(slice(start, end))`` should be used instead. +C API +----- + +GUfuncs on empty arrays and NpyIter axis removal +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is now allowed to remove a zero-sized axis from NpyIter. Which may mean +that code removing axes from NpyIter has to add an additional check when +accessing the removed dimensions later on. + +The largest followup change is that gufuncs are now allowed to have zero-sized +inner dimensions. This means that a gufunc now has to anticipate an empty inner +dimension, while this was never possible and an error raised instead. + +For most gufuncs no change should be necessary. However, it is now possible +for gufuncs with a signature such as ``(..., N, M) -> (..., M)`` to return +a valid result if ``N=0`` without further wrapping code. + + New Features ============ diff --git a/numpy/core/src/multiarray/nditer_api.c b/numpy/core/src/multiarray/nditer_api.c index da3c85ae0..f2bc23715 100644 --- a/numpy/core/src/multiarray/nditer_api.c +++ b/numpy/core/src/multiarray/nditer_api.c @@ -106,12 +106,6 @@ NpyIter_RemoveAxis(NpyIter *iter, int axis) return NPY_FAIL; } - if (NAD_SHAPE(axisdata_del) == 0) { - PyErr_SetString(PyExc_ValueError, - "cannot remove a zero-sized axis from an iterator"); - return NPY_FAIL; - } - /* Adjust the permutation */ for (idim = 0; idim < ndim-1; ++idim) { npy_int8 p = (idim < xdim) ? perm[idim] : perm[idim+1]; diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index caa36bd2d..52c2a6454 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -3269,14 +3269,6 @@ PyUFunc_Accumulate(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out, op[0] = NpyIter_GetOperandArray(iter)[0]; op[1] = NpyIter_GetOperandArray(iter)[1]; - if (PyArray_SIZE(op[0]) == 0) { - if (out == NULL) { - out = op[0]; - Py_INCREF(out); - } - goto finish; - } - if (NpyIter_RemoveAxis(iter, axis) != NPY_SUCCEED) { goto fail; } @@ -3623,35 +3615,6 @@ PyUFunc_Reduceat(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *ind, need_outer_iterator = 1; } - /* Special case when the index array's size is zero */ - if (ind_size == 0) { - if (out == NULL) { - npy_intp out_shape[NPY_MAXDIMS]; - memcpy(out_shape, PyArray_SHAPE(arr), - PyArray_NDIM(arr) * NPY_SIZEOF_INTP); - out_shape[axis] = 0; - Py_INCREF(op_dtypes[0]); - op[0] = out = (PyArrayObject *)PyArray_NewFromDescr( - &PyArray_Type, op_dtypes[0], - PyArray_NDIM(arr), out_shape, NULL, NULL, - 0, NULL); - if (out == NULL) { - goto fail; - } - } - else { - /* Allow any zero-sized output array in this case */ - if (PyArray_SIZE(out) != 0) { - PyErr_SetString(PyExc_ValueError, - "output operand shape for reduceat is " - "incompatible with index array of shape (0,)"); - goto fail; - } - } - - goto finish; - } - if (need_outer_iterator) { npy_uint32 flags = NPY_ITER_ZEROSIZE_OK| NPY_ITER_REFS_OK| |