summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/reference/c-api/types-and-structures.rst6
-rw-r--r--numpy/core/src/multiarray/array_method.c125
-rw-r--r--numpy/core/src/multiarray/array_method.h11
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.c117
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.h7
5 files changed, 137 insertions, 129 deletions
diff --git a/doc/source/reference/c-api/types-and-structures.rst b/doc/source/reference/c-api/types-and-structures.rst
index ab82fda87..75a97c20e 100644
--- a/doc/source/reference/c-api/types-and-structures.rst
+++ b/doc/source/reference/c-api/types-and-structures.rst
@@ -811,7 +811,7 @@ PyUFunc_Type and PyUFuncObject
char *core_signature;
PyUFunc_TypeResolutionFunc *type_resolver;
PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector;
- PyUFunc_MaskedInnerLoopSelectionFunc *masked_inner_loop_selector;
+ void *reserved2;
npy_uint32 *op_flags;
npy_uint32 *iter_flags;
/* new in API version 0x0000000D */
@@ -965,10 +965,6 @@ PyUFunc_Type and PyUFuncObject
For a possible future loop selector with a different signature.
- .. c:member:: PyUFunc_MaskedInnerLoopSelectionFunc *masked_inner_loop_selector
-
- Function which returns a masked inner loop for the ufunc
-
.. c:member:: npy_uint32 op_flags
Override the default operand flags for each ufunc operand.
diff --git a/numpy/core/src/multiarray/array_method.c b/numpy/core/src/multiarray/array_method.c
index ab992a3ae..cc841ee64 100644
--- a/numpy/core/src/multiarray/array_method.c
+++ b/numpy/core/src/multiarray/array_method.c
@@ -756,6 +756,131 @@ boundarraymethod__simple_strided_call(
}
+/*
+ * TODO: Currently still based on the old ufunc system and not ArrayMethod!
+ * This requires fixing the ufunc code first.
+ *
+ * Support for masked inner-strided loops. Masked inner-strided loops are
+ * only used in the ufunc machinery. So this special cases them.
+ * In the future it probably makes sense to create an::
+ *
+ * Arraymethod->get_masked_strided_loop()
+ *
+ * Function which this can wrap instead.
+ */
+typedef struct {
+ NpyAuxData base;
+ PyUFuncGenericFunction unmasked_stridedloop;
+ void *innerloopdata;
+ int nargs;
+ char *dataptrs[];
+} _masked_stridedloop_data;
+
+
+static void
+_masked_stridedloop_data_free(NpyAuxData *auxdata)
+{
+ _masked_stridedloop_data *data = (_masked_stridedloop_data *)auxdata;
+ PyMem_Free(data);
+}
+
+
+/*
+ * This function wraps a regular unmasked strided-loop as a
+ * masked strided-loop, only calling the function for elements
+ * where the mask is True.
+ */
+static void
+unmasked_ufunc_loop_as_masked(
+ char **data, const npy_intp *dimensions,
+ const npy_intp *strides, void *_auxdata)
+{
+ _masked_stridedloop_data *auxdata = (_masked_stridedloop_data *)_auxdata;
+ int nargs = auxdata->nargs;
+ PyUFuncGenericFunction strided_loop = auxdata->unmasked_stridedloop;
+ void *innerloopdata = auxdata->innerloopdata;
+
+ char **dataptrs = auxdata->dataptrs;
+ memcpy(dataptrs, data, nargs * sizeof(char *));
+ char *mask = data[nargs];
+ npy_intp mask_stride = strides[nargs];
+
+ npy_intp N = dimensions[0];
+ /* Process the data as runs of unmasked values */
+ do {
+ ssize_t subloopsize;
+
+ /* Skip masked values */
+ mask = npy_memchr(mask, 0, mask_stride, N, &subloopsize, 1);
+ for (int i = 0; i < nargs; i++) {
+ dataptrs[i] += subloopsize * strides[i];
+ }
+ N -= subloopsize;
+
+ /* Process unmasked values */
+ mask = npy_memchr(mask, 0, mask_stride, N, &subloopsize, 0);
+ strided_loop(dataptrs, &subloopsize, strides, innerloopdata);
+ for (int i = 0; i < nargs; i++) {
+ dataptrs[i] += subloopsize * strides[i];
+ }
+ N -= subloopsize;
+ } while (N > 0);
+}
+
+
+/*
+ * TODO: This function will be the masked equivalent to `get_loop`.
+ * This function wraps a legacy inner loop so it becomes masked.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+NPY_NO_EXPORT int
+PyUFunc_DefaultMaskedInnerLoopSelector(PyUFuncObject *ufunc,
+ PyArray_Descr **dtypes,
+ PyUFuncGenericFunction *out_innerloop,
+ NpyAuxData **out_innerloopdata,
+ int *out_needs_api)
+{
+ int retcode;
+ _masked_stridedloop_data *data;
+ int nargs = ufunc->nin + ufunc->nout;
+
+ if (ufunc->legacy_inner_loop_selector == NULL) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "the ufunc default masked inner loop selector doesn't "
+ "yet support wrapping the new inner loop selector, it "
+ "still only wraps the legacy inner loop selector");
+ return -1;
+ }
+
+ /* Add working memory for the data pointers, to modify them in-place */
+ data = PyMem_Malloc(sizeof(_masked_stridedloop_data) +
+ sizeof(char *) * nargs);
+ if (data == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ data->base.free = _masked_stridedloop_data_free;
+ data->base.clone = NULL; /* not currently used */
+ data->unmasked_stridedloop = NULL;
+ data->nargs = nargs;
+
+ /* Get the unmasked ufunc inner loop */
+ retcode = ufunc->legacy_inner_loop_selector(ufunc, dtypes,
+ &data->unmasked_stridedloop, &data->innerloopdata,
+ out_needs_api);
+ if (retcode < 0) {
+ PyArray_free(data);
+ return retcode;
+ }
+
+ /* Return the loop function + aux data */
+ *out_innerloop = &unmasked_ufunc_loop_as_masked;
+ *out_innerloopdata = (NpyAuxData *)data;
+ return 0;
+}
+
+
PyMethodDef boundarraymethod_methods[] = {
{"_resolve_descriptors", (PyCFunction)boundarraymethod__resolve_descripors,
METH_O, "Resolve the given dtypes."},
diff --git a/numpy/core/src/multiarray/array_method.h b/numpy/core/src/multiarray/array_method.h
index 88167a6bb..c2122a2da 100644
--- a/numpy/core/src/multiarray/array_method.h
+++ b/numpy/core/src/multiarray/array_method.h
@@ -158,6 +158,17 @@ npy_default_get_strided_loop(
PyArrayMethod_StridedLoop **out_loop, NpyAuxData **out_transferdata,
NPY_ARRAYMETHOD_FLAGS *flags);
+/*
+ * TODO: This function will not rely on the current ufunc code after the
+ * ufunc refactor.
+ */
+#include "numpy/ufuncobject.h"
+NPY_NO_EXPORT int
+PyUFunc_DefaultMaskedInnerLoopSelector(PyUFuncObject *ufunc,
+ PyArray_Descr **dtypes,
+ PyUFuncGenericFunction *out_innerloop,
+ NpyAuxData **out_innerloopdata,
+ int *out_needs_api);
/*
* TODO: This function is the internal version, and its error paths may
diff --git a/numpy/core/src/umath/ufunc_type_resolution.c b/numpy/core/src/umath/ufunc_type_resolution.c
index e09ce3233..468327b8c 100644
--- a/numpy/core/src/umath/ufunc_type_resolution.c
+++ b/numpy/core/src/umath/ufunc_type_resolution.c
@@ -1496,123 +1496,6 @@ PyUFunc_DefaultLegacyInnerLoopSelector(PyUFuncObject *ufunc,
}
-/*
- * Support for masked inner-strided loops. These are currently ONLY used
- * for normal ufuncs, and only a generic loop getter exists.
- * It may make sense to generalize this in the future or allow specialization.
- * Until then, the inner-loop signature is flexible.
- */
-typedef struct {
- NpyAuxData base;
- PyUFuncGenericFunction unmasked_stridedloop;
- void *innerloopdata;
- int nargs;
- char *dataptrs[];
-} _masked_stridedloop_data;
-
-
-static void
-_masked_stridedloop_data_free(NpyAuxData *auxdata)
-{
- _masked_stridedloop_data *data = (_masked_stridedloop_data *)auxdata;
- PyMem_Free(data);
-}
-
-
-/*
- * This function wraps a regular unmasked ufunc inner loop as a
- * masked ufunc inner loop, only calling the function for
- * elements where the mask is True.
- */
-static void
-unmasked_ufunc_loop_as_masked(
- char **data, const npy_intp *dimensions,
- const npy_intp *strides, void *_auxdata)
-{
- _masked_stridedloop_data *auxdata = (_masked_stridedloop_data *)_auxdata;
- int nargs = auxdata->nargs;
- PyUFuncGenericFunction strided_loop = auxdata->unmasked_stridedloop;
- void *innerloopdata = auxdata->innerloopdata;
-
- char **dataptrs = auxdata->dataptrs;
- memcpy(dataptrs, data, nargs * sizeof(char *));
- char *mask = data[nargs];
- npy_intp mask_stride = strides[nargs];
-
- npy_intp N = dimensions[0];
- /* Process the data as runs of unmasked values */
- do {
- ssize_t subloopsize;
-
- /* Skip masked values */
- mask = npy_memchr(mask, 0, mask_stride, N, &subloopsize, 1);
- for (int i = 0; i < nargs; i++) {
- dataptrs[i] += subloopsize * strides[i];
- }
- N -= subloopsize;
-
- /* Process unmasked values */
- mask = npy_memchr(mask, 0, mask_stride, N, &subloopsize, 0);
- strided_loop(dataptrs, &subloopsize, strides, innerloopdata);
- for (int i = 0; i < nargs; i++) {
- dataptrs[i] += subloopsize * strides[i];
- }
- N -= subloopsize;
- } while (N > 0);
-}
-
-
-/*
- * This function wraps a legacy inner loop so it becomes masked.
- *
- * Returns 0 on success, -1 on error.
- */
-NPY_NO_EXPORT int
-PyUFunc_DefaultMaskedInnerLoopSelector(PyUFuncObject *ufunc,
- PyArray_Descr **dtypes,
- PyUFuncGenericFunction *out_innerloop,
- NpyAuxData **out_innerloopdata,
- int *out_needs_api)
-{
- int retcode;
- _masked_stridedloop_data *data;
- int nargs = ufunc->nin + ufunc->nout;
-
- if (ufunc->legacy_inner_loop_selector == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "the ufunc default masked inner loop selector doesn't "
- "yet support wrapping the new inner loop selector, it "
- "still only wraps the legacy inner loop selector");
- return -1;
- }
-
- /* Add working memory for the data pointers, to modify them in-place */
- data = PyMem_Malloc(sizeof(_masked_stridedloop_data) +
- sizeof(char *) * nargs);
- if (data == NULL) {
- PyErr_NoMemory();
- return -1;
- }
- data->base.free = _masked_stridedloop_data_free;
- data->base.clone = NULL; /* not currently used */
- data->unmasked_stridedloop = NULL;
- data->nargs = nargs;
-
- /* Get the unmasked ufunc inner loop */
- retcode = ufunc->legacy_inner_loop_selector(ufunc, dtypes,
- &data->unmasked_stridedloop, &data->innerloopdata,
- out_needs_api);
- if (retcode < 0) {
- PyArray_free(data);
- return retcode;
- }
-
- /* Return the loop function + aux data */
- *out_innerloop = &unmasked_ufunc_loop_as_masked;
- *out_innerloopdata = (NpyAuxData *)data;
- return 0;
-}
-
static int
ufunc_loop_matches(PyUFuncObject *self,
PyArrayObject **op,
diff --git a/numpy/core/src/umath/ufunc_type_resolution.h b/numpy/core/src/umath/ufunc_type_resolution.h
index fdad19b3d..cd0ff4a0d 100644
--- a/numpy/core/src/umath/ufunc_type_resolution.h
+++ b/numpy/core/src/umath/ufunc_type_resolution.h
@@ -135,11 +135,4 @@ PyUFunc_DefaultLegacyInnerLoopSelector(PyUFuncObject *ufunc,
void **out_innerloopdata,
int *out_needs_api);
-NPY_NO_EXPORT int
-PyUFunc_DefaultMaskedInnerLoopSelector(PyUFuncObject *ufunc,
- PyArray_Descr **dtypes,
- PyUFuncGenericFunction *out_innerloop,
- NpyAuxData **out_innerloopdata,
- int *out_needs_api);
-
#endif