summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorMark Wiebe <mwwiebe@gmail.com>2011-08-07 07:26:53 -0700
committerCharles Harris <charlesr.harris@gmail.com>2011-08-27 07:26:53 -0600
commitc57efbc5ab9cd4ea6bc3b8d54f16b295a5d448bc (patch)
treed8423e039fbee7c94744f59b7164fa6407af1241 /numpy
parentb769df7101b5e764ed5965067f35906a6d461380 (diff)
downloadnumpy-c57efbc5ab9cd4ea6bc3b8d54f16b295a5d448bc.tar.gz
ENH: missingdata: Implement wheremasked scalar assignment with overwritena=True
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/SConscript1
-rw-r--r--numpy/core/setup.py1
-rw-r--r--numpy/core/src/multiarray/array_assign.c289
-rw-r--r--numpy/core/src/multiarray/array_assign.h32
-rw-r--r--numpy/core/src/multiarray/array_assign_scalar.c434
-rw-r--r--numpy/core/src/multiarray/convert.c2
-rw-r--r--numpy/core/src/multiarray/ctors.c16
-rw-r--r--numpy/core/src/multiarray/descriptor.c3
-rw-r--r--numpy/core/src/multiarray/dtype_transfer.c136
-rw-r--r--numpy/core/src/multiarray/item_selection.c2
-rw-r--r--numpy/core/src/multiarray/lowlevel_strided_loops.c.src12
-rw-r--r--numpy/core/src/multiarray/mapping.c6
-rw-r--r--numpy/core/src/multiarray/na_mask.c40
-rw-r--r--numpy/core/src/multiarray/na_mask.h11
-rw-r--r--numpy/core/src/multiarray/nditer_api.c8
-rw-r--r--numpy/core/src/multiarray/nditer_constr.c8
-rw-r--r--numpy/core/src/multiarray/nditer_impl.h4
-rw-r--r--numpy/core/src/private/lowlevel_strided_loops.h49
18 files changed, 649 insertions, 405 deletions
diff --git a/numpy/core/SConscript b/numpy/core/SConscript
index 60fde8e30..56b3a04f3 100644
--- a/numpy/core/SConscript
+++ b/numpy/core/SConscript
@@ -444,6 +444,7 @@ if ENABLE_SEPARATE_COMPILATION:
pjoin('src', 'multiarray', 'hashdescr.c'),
pjoin('src', 'multiarray', 'arrayobject.c'),
pjoin('src', 'multiarray', 'array_assign.c'),
+ pjoin('src', 'multiarray', 'array_assign_scalar.c'),
pjoin('src', 'multiarray', 'datetime.c'),
pjoin('src', 'multiarray', 'datetime_strings.c'),
pjoin('src', 'multiarray', 'datetime_busday.c'),
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index c721cf219..c08fd1601 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -752,6 +752,7 @@ def configuration(parent_package='',top_path=None):
join('src', 'multiarray', 'arrayobject.c'),
join('src', 'multiarray', 'arraytypes.c.src'),
join('src', 'multiarray', 'array_assign.c'),
+ join('src', 'multiarray', 'array_assign_scalar.c'),
join('src', 'multiarray', 'buffer.c'),
join('src', 'multiarray', 'calculation.c'),
join('src', 'multiarray', 'common.c'),
diff --git a/numpy/core/src/multiarray/array_assign.c b/numpy/core/src/multiarray/array_assign.c
index e13f00333..4ac41ecdf 100644
--- a/numpy/core/src/multiarray/array_assign.c
+++ b/numpy/core/src/multiarray/array_assign.c
@@ -1,5 +1,6 @@
/*
- * This file implements several array assignment routines.
+ * This file implements some helper functions for the array assignment
+ * routines. The actual assignment routines are in array_assign_*.c
*
* Written by Mark Wiebe (mwwiebe@gmail.com)
* Copyright (c) 2011 by Enthought, Inc.
@@ -17,22 +18,10 @@
#include "npy_config.h"
#include "numpy/npy_3kcompat.h"
-#include "convert_datatype.h"
-#include "methods.h"
-#include "shape.h"
-#include "lowlevel_strided_loops.h"
#include "array_assign.h"
-/*
- * Broadcasts strides to match the given dimensions. Can be used,
- * for instance, to set up a raw iteration.
- *
- * 'strides_name' is used to produce an error message if the strides
- * cannot be broadcast.
- *
- * Returns 0 on success, -1 on failure.
- */
-static int
+/* See array_assign.h for parameter documentation */
+NPY_NO_EXPORT int
broadcast_strides(int ndim, npy_intp *shape,
int strides_ndim, npy_intp *strides_shape, npy_intp *strides,
char *strides_name,
@@ -87,12 +76,9 @@ broadcast_error: {
}
}
-/*
- * Checks whether a data pointer + set of strides refers to a raw
- * array which is fully aligned data.
- */
-static int
-strides_are_aligned(int ndim, char *data, npy_intp *strides, int alignment)
+/* See array_assign.h for parameter documentation */
+NPY_NO_EXPORT int
+raw_array_is_aligned(int ndim, char *data, npy_intp *strides, int alignment)
{
if (alignment > 1) {
npy_intp align_check = (npy_intp)data;
@@ -109,264 +95,3 @@ strides_are_aligned(int ndim, char *data, npy_intp *strides, int alignment)
}
}
-/*
- * Assigns the scalar value to every element of the destination raw array.
- *
- * Returns 0 on success, -1 on failure.
- */
-static int
-raw_array_assign_scalar(int ndim, npy_intp *shape,
- PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
- PyArray_Descr *src_dtype, char *src_data)
-{
- int idim;
- npy_intp shape_it[NPY_MAXDIMS], dst_strides_it[NPY_MAXDIMS];
- npy_intp coord[NPY_MAXDIMS];
- NPY_BEGIN_THREADS_DEF;
-
- PyArray_StridedTransferFn *stransfer = NULL;
- NpyAuxData *transferdata = NULL;
- int aligned, needs_api = 0;
- npy_intp src_itemsize = src_dtype->elsize;
-
- /* Check alignment */
- aligned = strides_are_aligned(ndim, dst_data, dst_strides,
- dst_dtype->alignment);
- if (((npy_intp)src_data & (src_dtype->alignment - 1)) != 0) {
- aligned = 0;
- }
-
- /* Use raw iteration with no heap allocation */
- if (PyArray_PrepareOneRawArrayIter(
- ndim, shape,
- dst_data, dst_strides,
- &ndim, shape_it,
- &dst_data, dst_strides_it) < 0) {
- return -1;
- }
-
- /* Get the function to do the casting */
- if (PyArray_GetDTypeTransferFunction(aligned,
- 0, dst_strides_it[0],
- src_dtype, dst_dtype,
- 0,
- &stransfer, &transferdata,
- &needs_api) != NPY_SUCCEED) {
- return -1;
- }
-
- if (!needs_api) {
- NPY_BEGIN_THREADS;
- }
-
- NPY_RAW_ITER_START(idim, ndim, coord, shape_it) {
- /* Process the innermost dimension */
- stransfer(dst_data, dst_strides_it[0], src_data, 0,
- shape_it[0], src_itemsize, transferdata);
- } NPY_RAW_ITER_ONE_NEXT(idim, ndim, coord,
- shape_it, dst_data, dst_strides_it);
-
- if (!needs_api) {
- NPY_END_THREADS;
- }
-
- NPY_AUXDATA_FREE(transferdata);
-
- return (needs_api && PyErr_Occurred()) ? -1 : 0;
-}
-
-/*
- * Assigns the scalar value to every element of the destination raw array
- * where the 'wheremask' value is True.
- *
- * Returns 0 on success, -1 on failure.
- */
-static int
-raw_array_wheremasked_assign_scalar(int ndim, npy_intp *shape,
- PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
- PyArray_Descr *src_dtype, char *src_data,
- PyArray_Descr *wheremask_dtype, char *wheremask_data,
- npy_intp *wheremask_strides)
-{
- int idim;
- npy_intp shape_it[NPY_MAXDIMS], dst_strides_it[NPY_MAXDIMS];
- npy_intp wheremask_strides_it[NPY_MAXDIMS];
- npy_intp coord[NPY_MAXDIMS];
- NPY_BEGIN_THREADS_DEF;
-
- PyArray_MaskedStridedTransferFn *stransfer = NULL;
- NpyAuxData *transferdata = NULL;
- int aligned, needs_api = 0;
- npy_intp src_itemsize = src_dtype->elsize;
-
- /* Check alignment */
- aligned = strides_are_aligned(ndim, dst_data, dst_strides,
- dst_dtype->alignment);
- if (((npy_intp)src_data & (src_dtype->alignment - 1)) != 0) {
- aligned = 0;
- }
-
- /* Use raw iteration with no heap allocation */
- if (PyArray_PrepareTwoRawArrayIter(
- ndim, shape,
- dst_data, dst_strides,
- wheremask_data, wheremask_strides,
- &ndim, shape_it,
- &dst_data, dst_strides_it,
- &wheremask_data, wheremask_strides_it) < 0) {
- return -1;
- }
-
- /* Get the function to do the casting */
- if (PyArray_GetMaskedDTypeTransferFunction(aligned,
- 0, dst_strides_it[0], wheremask_strides_it[0],
- src_dtype, dst_dtype, wheremask_dtype,
- 0,
- &stransfer, &transferdata,
- &needs_api) != NPY_SUCCEED) {
- return -1;
- }
-
- if (!needs_api) {
- NPY_BEGIN_THREADS;
- }
-
- NPY_RAW_ITER_START(idim, ndim, coord, shape_it) {
- /* Process the innermost dimension */
- stransfer(dst_data, dst_strides_it[0], src_data, 0,
- (npy_mask *)wheremask_data, wheremask_strides_it[0],
- shape_it[0], src_itemsize, transferdata);
- } NPY_RAW_ITER_TWO_NEXT(idim, ndim, coord, shape_it,
- dst_data, dst_strides_it,
- wheremask_data, wheremask_strides_it);
-
- if (!needs_api) {
- NPY_END_THREADS;
- }
-
- NPY_AUXDATA_FREE(transferdata);
-
- return (needs_api && PyErr_Occurred()) ? -1 : 0;
-}
-
-/* See array_assign.h for documentation */
-NPY_NO_EXPORT int
-array_assign_scalar(PyArrayObject *dst,
- PyArray_Descr *src_dtype, char *src_data,
- PyArrayObject *wheremask,
- NPY_CASTING casting, npy_bool overwritena)
-{
- int allocated_src_data = 0, dst_has_maskna = PyArray_HASMASKNA(dst);
- npy_longlong scalarbuffer[4];
-
- /* Check the casting rule */
- if (!can_cast_scalar_to(src_dtype, src_data,
- PyArray_DESCR(dst), casting)) {
- PyObject *errmsg;
- errmsg = PyUString_FromString("Cannot cast scalar from ");
- PyUString_ConcatAndDel(&errmsg,
- PyObject_Repr((PyObject *)src_dtype));
- PyUString_ConcatAndDel(&errmsg,
- PyUString_FromString(" to "));
- PyUString_ConcatAndDel(&errmsg,
- PyObject_Repr((PyObject *)PyArray_DESCR(dst)));
- PyUString_ConcatAndDel(&errmsg,
- PyUString_FromFormat(" according to the rule %s",
- npy_casting_to_string(casting)));
- PyErr_SetObject(PyExc_TypeError, errmsg);
- return -1;
- }
-
- /*
- * Make a copy of the src data if it's a different dtype than 'dst'
- * or isn't aligned, and the destination we're copying to has
- * more than one element.
- */
- if ((!PyArray_EquivTypes(PyArray_DESCR(dst), src_dtype) ||
- ((npy_intp)src_data & (src_dtype->alignment - 1)) != 0) &&
- PyArray_SIZE(dst) > 1) {
- char *tmp_src_data;
-
- /*
- * Use a static buffer to store the aligned/cast version,
- * or allocate some memory if more space is needed.
- */
- if (sizeof(scalarbuffer) >= PyArray_DESCR(dst)->elsize) {
- tmp_src_data = (char *)&scalarbuffer[0];
- }
- else {
- tmp_src_data = PyArray_malloc(PyArray_DESCR(dst)->elsize);
- allocated_src_data = 1;
- }
- if (PyArray_CastRawArrays(1, src_data, tmp_src_data, 0, 0,
- src_dtype, PyArray_DESCR(dst), 0) != NPY_SUCCEED) {
- goto fail;
- }
-
- /* Replace src_data/src_dtype */
- src_data = tmp_src_data;
- src_dtype = PyArray_DESCR(dst);
- }
-
- if (wheremask == NULL) {
- /* A straightforward value assignment */
- if (overwritena || !dst_has_maskna) {
- /* If assigning to an array with an NA mask, set to all exposed */
- if (dst_has_maskna) {
- if (PyArray_AssignMaskNA(dst, 1) < 0) {
- goto fail;
- }
- }
-
- /* Do the assignment with raw array iteration */
- if (raw_array_assign_scalar(PyArray_NDIM(dst), PyArray_DIMS(dst),
- PyArray_DESCR(dst), PyArray_DATA(dst), PyArray_STRIDES(dst),
- src_dtype, src_data) < 0) {
- goto fail;
- }
- }
- /* A value assignment without overwriting NA values */
- else {
- }
- }
- else {
- /* A straightforward where-masked assignment */
- if (overwritena || !dst_has_maskna) {
- npy_intp wheremask_strides[NPY_MAXDIMS];
-
- /* Broadcast the wheremask to 'dst' for raw iteration */
- if (broadcast_strides(PyArray_NDIM(dst), PyArray_DIMS(dst),
- PyArray_NDIM(wheremask), PyArray_DIMS(wheremask),
- PyArray_STRIDES(wheremask), "where mask",
- wheremask_strides) < 0) {
- goto fail;
- }
-
- /* Do the masked assignment with raw array iteration */
- if (raw_array_wheremasked_assign_scalar(
- PyArray_NDIM(dst), PyArray_DIMS(dst),
- PyArray_DESCR(dst), PyArray_DATA(dst), PyArray_STRIDES(dst),
- src_dtype, src_data,
- PyArray_DESCR(wheremask), PyArray_DATA(wheremask),
- wheremask_strides) < 0) {
- goto fail;
- }
- }
- /* A masked value assignment without overwriting NA values */
- else {
- }
- }
-
- if (allocated_src_data) {
- PyArray_free(src_data);
- }
-
- return 0;
-
-fail:
- if (allocated_src_data) {
- PyArray_free(src_data);
- }
-
- return -1;
-}
diff --git a/numpy/core/src/multiarray/array_assign.h b/numpy/core/src/multiarray/array_assign.h
index 68263c157..ddbcf6dae 100644
--- a/numpy/core/src/multiarray/array_assign.h
+++ b/numpy/core/src/multiarray/array_assign.h
@@ -68,4 +68,36 @@ array_assign_flat(PyArrayObject *dst, NPY_ORDER dst_order,
PyArrayObject *wheremask,
NPY_CASTING casting, npy_bool overwritena);
+
+
+
+/*
+ * Internal detail of how much to buffer during array assignments which
+ * need it. This is for more complex NA masking operations where masks
+ * need to be inverted or combined together.
+ */
+#define NPY_ARRAY_ASSIGN_BUFFERSIZE 8192
+
+/*
+ * Broadcasts strides to match the given dimensions. Can be used,
+ * for instance, to set up a raw iteration.
+ *
+ * 'strides_name' is used to produce an error message if the strides
+ * cannot be broadcast.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+NPY_NO_EXPORT int
+broadcast_strides(int ndim, npy_intp *shape,
+ int strides_ndim, npy_intp *strides_shape, npy_intp *strides,
+ char *strides_name,
+ npy_intp *out_strides);
+
+/*
+ * Checks whether a data pointer + set of strides refers to a raw
+ * array which is fully aligned data.
+ */
+NPY_NO_EXPORT int
+raw_array_is_aligned(int ndim, char *data, npy_intp *strides, int alignment);
+
#endif
diff --git a/numpy/core/src/multiarray/array_assign_scalar.c b/numpy/core/src/multiarray/array_assign_scalar.c
new file mode 100644
index 000000000..502d8c733
--- /dev/null
+++ b/numpy/core/src/multiarray/array_assign_scalar.c
@@ -0,0 +1,434 @@
+/*
+ * This file implements assignment from a scalar to an ndarray.
+ *
+ * Written by Mark Wiebe (mwwiebe@gmail.com)
+ * Copyright (c) 2011 by Enthought, Inc.
+ *
+ * See LICENSE.txt for the license.
+ */
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
+#define NPY_NO_DEPRECATED_API
+#define _MULTIARRAYMODULE
+#include <numpy/ndarraytypes.h>
+
+#include "npy_config.h"
+#include "numpy/npy_3kcompat.h"
+
+#include "convert_datatype.h"
+#include "methods.h"
+#include "shape.h"
+#include "lowlevel_strided_loops.h"
+#include "na_mask.h"
+
+#include "array_assign.h"
+
+/*
+ * Assigns the scalar value to every element of the destination raw array.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int
+raw_array_assign_scalar(int ndim, npy_intp *shape,
+ PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
+ PyArray_Descr *src_dtype, char *src_data)
+{
+ int idim;
+ npy_intp shape_it[NPY_MAXDIMS], dst_strides_it[NPY_MAXDIMS];
+ npy_intp coord[NPY_MAXDIMS];
+ NPY_BEGIN_THREADS_DEF;
+
+ PyArray_StridedUnaryOp *stransfer = NULL;
+ NpyAuxData *transferdata = NULL;
+ int aligned, needs_api = 0;
+ npy_intp src_itemsize = src_dtype->elsize;
+
+ /* Check alignment */
+ aligned = raw_array_is_aligned(ndim, dst_data, dst_strides,
+ dst_dtype->alignment);
+ if (((npy_intp)src_data & (src_dtype->alignment - 1)) != 0) {
+ aligned = 0;
+ }
+
+ /* Use raw iteration with no heap allocation */
+ if (PyArray_PrepareOneRawArrayIter(
+ ndim, shape,
+ dst_data, dst_strides,
+ &ndim, shape_it,
+ &dst_data, dst_strides_it) < 0) {
+ return -1;
+ }
+
+ /* Get the function to do the casting */
+ if (PyArray_GetDTypeTransferFunction(aligned,
+ 0, dst_strides_it[0],
+ src_dtype, dst_dtype,
+ 0,
+ &stransfer, &transferdata,
+ &needs_api) != NPY_SUCCEED) {
+ return -1;
+ }
+
+ if (!needs_api) {
+ NPY_BEGIN_THREADS;
+ }
+
+ NPY_RAW_ITER_START(idim, ndim, coord, shape_it) {
+ /* Process the innermost dimension */
+ stransfer(dst_data, dst_strides_it[0], src_data, 0,
+ shape_it[0], src_itemsize, transferdata);
+ } NPY_RAW_ITER_ONE_NEXT(idim, ndim, coord,
+ shape_it, dst_data, dst_strides_it);
+
+ if (!needs_api) {
+ NPY_END_THREADS;
+ }
+
+ NPY_AUXDATA_FREE(transferdata);
+
+ return (needs_api && PyErr_Occurred()) ? -1 : 0;
+}
+
+/*
+ * Assigns the scalar value to every element of the destination raw array
+ * where the 'wheremask' value is True.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int
+raw_array_wheremasked_assign_scalar(int ndim, npy_intp *shape,
+ PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
+ PyArray_Descr *src_dtype, char *src_data,
+ PyArray_Descr *wheremask_dtype, char *wheremask_data,
+ npy_intp *wheremask_strides)
+{
+ int idim;
+ npy_intp shape_it[NPY_MAXDIMS], dst_strides_it[NPY_MAXDIMS];
+ npy_intp wheremask_strides_it[NPY_MAXDIMS];
+ npy_intp coord[NPY_MAXDIMS];
+ NPY_BEGIN_THREADS_DEF;
+
+ PyArray_MaskedStridedUnaryOp *stransfer = NULL;
+ NpyAuxData *transferdata = NULL;
+ int aligned, needs_api = 0;
+ npy_intp src_itemsize = src_dtype->elsize;
+
+ /* Check alignment */
+ aligned = raw_array_is_aligned(ndim, dst_data, dst_strides,
+ dst_dtype->alignment);
+ if (((npy_intp)src_data & (src_dtype->alignment - 1)) != 0) {
+ aligned = 0;
+ }
+
+ /* Use raw iteration with no heap allocation */
+ if (PyArray_PrepareTwoRawArrayIter(
+ ndim, shape,
+ dst_data, dst_strides,
+ wheremask_data, wheremask_strides,
+ &ndim, shape_it,
+ &dst_data, dst_strides_it,
+ &wheremask_data, wheremask_strides_it) < 0) {
+ return -1;
+ }
+
+ /* Get the function to do the casting */
+ if (PyArray_GetMaskedDTypeTransferFunction(aligned,
+ 0, dst_strides_it[0], wheremask_strides_it[0],
+ src_dtype, dst_dtype, wheremask_dtype,
+ 0,
+ &stransfer, &transferdata,
+ &needs_api) != NPY_SUCCEED) {
+ return -1;
+ }
+
+ if (!needs_api) {
+ NPY_BEGIN_THREADS;
+ }
+
+ NPY_RAW_ITER_START(idim, ndim, coord, shape_it) {
+ /* Process the innermost dimension */
+ stransfer(dst_data, dst_strides_it[0], src_data, 0,
+ (npy_mask *)wheremask_data, wheremask_strides_it[0],
+ shape_it[0], src_itemsize, transferdata);
+ } NPY_RAW_ITER_TWO_NEXT(idim, ndim, coord, shape_it,
+ dst_data, dst_strides_it,
+ wheremask_data, wheremask_strides_it);
+
+ if (!needs_api) {
+ NPY_END_THREADS;
+ }
+
+ NPY_AUXDATA_FREE(transferdata);
+
+ return (needs_api && PyErr_Occurred()) ? -1 : 0;
+}
+
+/*
+ * Assigns the scalar value to every element of the destination raw array
+ * except for those which are masked as NA.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int
+raw_array_assign_scalar_dont_overwritena(int ndim, npy_intp *shape,
+ PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
+ PyArray_Descr *src_dtype, char *src_data,
+ PyArray_Descr *maskna_dtype, char *maskna_data,
+ npy_intp *maskna_strides)
+{
+ int idim;
+ npy_intp shape_it[NPY_MAXDIMS], dst_strides_it[NPY_MAXDIMS];
+ npy_intp maskna_strides_it[NPY_MAXDIMS];
+ npy_intp coord[NPY_MAXDIMS];
+ NPY_BEGIN_THREADS_DEF;
+
+ PyArray_MaskedStridedUnaryOp *stransfer = NULL;
+ NpyAuxData *transferdata = NULL;
+ int aligned, needs_api = 0;
+ npy_intp src_itemsize = src_dtype->elsize;
+
+ PyArray_StridedUnaryOp *maskinv_stransfer = NULL;
+ NpyAuxData *maskinv_transferdata = NULL;
+
+ char *maskna_buffer;
+ npy_intp maskna_itemsize;
+
+ /* Check alignment */
+ aligned = raw_array_is_aligned(ndim, dst_data, dst_strides,
+ dst_dtype->alignment);
+ if (((npy_intp)src_data & (src_dtype->alignment - 1)) != 0) {
+ aligned = 0;
+ }
+
+ /* Use raw iteration with no heap allocation */
+ if (PyArray_PrepareTwoRawArrayIter(
+ ndim, shape,
+ dst_data, dst_strides,
+ maskna_data, maskna_strides,
+ &ndim, shape_it,
+ &dst_data, dst_strides_it,
+ &maskna_data, maskna_strides_it) < 0) {
+ return -1;
+ }
+
+ /* Allocate a buffer for inverting the mask */
+ maskna_itemsize = maskna_dtype->elsize;
+ maskna_buffer = PyArray_malloc(NPY_ARRAY_ASSIGN_BUFFERSIZE *
+ maskna_itemsize);
+ if (maskna_buffer == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ /* Get the function to do the casting */
+ if (PyArray_GetMaskedDTypeTransferFunction(aligned,
+ 0, dst_strides_it[0], maskna_itemsize,
+ src_dtype, dst_dtype, maskna_dtype,
+ 0,
+ &stransfer, &transferdata,
+ &needs_api) != NPY_SUCCEED) {
+ PyArray_free(maskna_buffer);
+ return -1;
+ }
+
+ /* Get the function to invert the mask */
+ if (PyArray_GetMaskInversionFunction(
+ maskna_strides_it[0], maskna_dtype,
+ &maskinv_stransfer, &maskinv_transferdata) < 0) {
+ PyArray_free(maskna_buffer);
+ NPY_AUXDATA_FREE(transferdata);
+ return -1;
+ }
+
+ if (!needs_api) {
+ NPY_BEGIN_THREADS;
+ }
+
+ NPY_RAW_ITER_START(idim, ndim, coord, shape_it) {
+ npy_intp buffered_count, count;
+ /* Process the innermost dimension a buffer size at a time */
+ count = shape_it[0];
+ do {
+ buffered_count = shape_it[0] > NPY_ARRAY_ASSIGN_BUFFERSIZE
+ ? count
+ : NPY_ARRAY_ASSIGN_BUFFERSIZE;
+ /* TODO: invert the mask into the buffer here */
+ stransfer(dst_data, dst_strides_it[0], src_data, 0,
+ (npy_mask *)maskna_buffer, maskna_itemsize,
+ buffered_count, src_itemsize, transferdata);
+ count -= buffered_count;
+ } while (count > 0);
+ } NPY_RAW_ITER_TWO_NEXT(idim, ndim, coord, shape_it,
+ dst_data, dst_strides_it,
+ maskna_data, maskna_strides_it);
+
+ if (!needs_api) {
+ NPY_END_THREADS;
+ }
+
+ NPY_AUXDATA_FREE(transferdata);
+ NPY_AUXDATA_FREE(maskinv_transferdata);
+
+ return (needs_api && PyErr_Occurred()) ? -1 : 0;
+}
+
+
+/* See array_assign.h for documentation */
+NPY_NO_EXPORT int
+array_assign_scalar(PyArrayObject *dst,
+ PyArray_Descr *src_dtype, char *src_data,
+ PyArrayObject *wheremask,
+ NPY_CASTING casting, npy_bool overwritena)
+{
+ int allocated_src_data = 0, dst_has_maskna = PyArray_HASMASKNA(dst);
+ npy_longlong scalarbuffer[4];
+
+ /* Check the casting rule */
+ if (!can_cast_scalar_to(src_dtype, src_data,
+ PyArray_DESCR(dst), casting)) {
+ PyObject *errmsg;
+ errmsg = PyUString_FromString("Cannot cast scalar from ");
+ PyUString_ConcatAndDel(&errmsg,
+ PyObject_Repr((PyObject *)src_dtype));
+ PyUString_ConcatAndDel(&errmsg,
+ PyUString_FromString(" to "));
+ PyUString_ConcatAndDel(&errmsg,
+ PyObject_Repr((PyObject *)PyArray_DESCR(dst)));
+ PyUString_ConcatAndDel(&errmsg,
+ PyUString_FromFormat(" according to the rule %s",
+ npy_casting_to_string(casting)));
+ PyErr_SetObject(PyExc_TypeError, errmsg);
+ return -1;
+ }
+
+ /*
+ * Make a copy of the src data if it's a different dtype than 'dst'
+ * or isn't aligned, and the destination we're copying to has
+ * more than one element.
+ */
+ if ((!PyArray_EquivTypes(PyArray_DESCR(dst), src_dtype) ||
+ ((npy_intp)src_data & (src_dtype->alignment - 1)) != 0) &&
+ PyArray_SIZE(dst) > 1) {
+ char *tmp_src_data;
+
+ /*
+ * Use a static buffer to store the aligned/cast version,
+ * or allocate some memory if more space is needed.
+ */
+ if (sizeof(scalarbuffer) >= PyArray_DESCR(dst)->elsize) {
+ tmp_src_data = (char *)&scalarbuffer[0];
+ }
+ else {
+ tmp_src_data = PyArray_malloc(PyArray_DESCR(dst)->elsize);
+ allocated_src_data = 1;
+ }
+ if (PyArray_CastRawArrays(1, src_data, tmp_src_data, 0, 0,
+ src_dtype, PyArray_DESCR(dst), 0) != NPY_SUCCEED) {
+ goto fail;
+ }
+
+ /* Replace src_data/src_dtype */
+ src_data = tmp_src_data;
+ src_dtype = PyArray_DESCR(dst);
+ }
+
+ if (wheremask == NULL) {
+ /* A straightforward value assignment */
+ if (overwritena || !dst_has_maskna) {
+ /* If assigning to an array with an NA mask, set to all exposed */
+ if (dst_has_maskna) {
+ if (PyArray_AssignMaskNA(dst, 1) < 0) {
+ goto fail;
+ }
+ }
+
+ /* Do the assignment with raw array iteration */
+ if (raw_array_assign_scalar(PyArray_NDIM(dst), PyArray_DIMS(dst),
+ PyArray_DESCR(dst), PyArray_DATA(dst), PyArray_STRIDES(dst),
+ src_dtype, src_data) < 0) {
+ goto fail;
+ }
+ }
+ /* A value assignment without overwriting NA values */
+ else {
+ if (raw_array_assign_scalar_dont_overwritena(
+ PyArray_NDIM(dst), PyArray_DIMS(dst),
+ PyArray_DESCR(dst), PyArray_DATA(dst), PyArray_STRIDES(dst),
+ src_dtype, src_data,
+ PyArray_MASKNA_DTYPE(dst), PyArray_MASKNA_DATA(dst),
+ PyArray_MASKNA_STRIDES(dst)) < 0) {
+ goto fail;
+ }
+ }
+ }
+ else {
+ if (PyArray_ContainsNA(wheremask)) {
+ if (!dst_has_maskna) {
+ PyErr_SetString(PyExc_ValueError,
+ "Cannot assign NA value to an array which "
+ "does not support NAs");
+ goto fail;
+ }
+ else {
+ /* TODO: add support for this */
+ PyErr_SetString(PyExc_ValueError,
+ "A where mask with NA values is not supported "
+ "yet");
+ goto fail;
+ }
+ }
+
+ /* A straightforward where-masked assignment */
+ if (overwritena || !dst_has_maskna) {
+ npy_intp wheremask_strides[NPY_MAXDIMS];
+
+ /* If assigning to an array with an NA mask, set to all exposed */
+ if (dst_has_maskna) {
+ /*
+ * TODO: If the where mask has NA values, this part
+ * changes too.
+ */
+ if (PyArray_AssignMaskNA(dst, 1) < 0) {
+ goto fail;
+ }
+ }
+
+ /* Broadcast the wheremask to 'dst' for raw iteration */
+ if (broadcast_strides(PyArray_NDIM(dst), PyArray_DIMS(dst),
+ PyArray_NDIM(wheremask), PyArray_DIMS(wheremask),
+ PyArray_STRIDES(wheremask), "where mask",
+ wheremask_strides) < 0) {
+ goto fail;
+ }
+
+ /* Do the masked assignment with raw array iteration */
+ if (raw_array_wheremasked_assign_scalar(
+ PyArray_NDIM(dst), PyArray_DIMS(dst),
+ PyArray_DESCR(dst), PyArray_DATA(dst), PyArray_STRIDES(dst),
+ src_dtype, src_data,
+ PyArray_DESCR(wheremask), PyArray_DATA(wheremask),
+ wheremask_strides) < 0) {
+ goto fail;
+ }
+ }
+ /* A masked value assignment without overwriting NA values */
+ else {
+ /* TODO: This function is next */
+ }
+ }
+
+ if (allocated_src_data) {
+ PyArray_free(src_data);
+ }
+
+ return 0;
+
+fail:
+ if (allocated_src_data) {
+ PyArray_free(src_data);
+ }
+
+ return -1;
+}
diff --git a/numpy/core/src/multiarray/convert.c b/numpy/core/src/multiarray/convert.c
index 4a5ab207c..593c9f91f 100644
--- a/numpy/core/src/multiarray/convert.c
+++ b/numpy/core/src/multiarray/convert.c
@@ -377,7 +377,7 @@ PyArray_FillWithScalar(PyArrayObject *arr, PyObject *obj)
NPY_NO_EXPORT int
PyArray_FillWithZero(PyArrayObject *a)
{
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
PyArray_Descr *dtype = PyArray_DESCR(a);
NpyIter *iter;
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c
index 19d8513bb..452c52731 100644
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -2821,10 +2821,10 @@ PyArray_EnsureAnyArray(PyObject *op)
NPY_NO_EXPORT int
PyArray_CopyAsFlat(PyArrayObject *dst, PyArrayObject *src, NPY_ORDER order)
{
- PyArray_StridedTransferFn *stransfer = NULL;
- PyArray_MaskedStridedTransferFn *maskedstransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
+ PyArray_MaskedStridedUnaryOp *maskedstransfer = NULL;
NpyAuxData *transferdata = NULL;
- PyArray_StridedTransferFn *maskna_stransfer = NULL;
+ PyArray_StridedUnaryOp *maskna_stransfer = NULL;
NpyAuxData *maskna_transferdata = NULL;
NpyIter *dst_iter, *src_iter;
@@ -3169,7 +3169,7 @@ PyArray_CopyInto(PyArrayObject *dst, PyArrayObject *src)
/* Special case for simple strides and no NA mask */
if (!dst_has_maskna && PyArray_NDIM(dst) >= PyArray_NDIM(src) &&
PyArray_TRIVIALLY_ITERABLE_PAIR(dst, src)) {
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
char *dst_data, *src_data;
npy_intp count, dst_stride, src_stride, src_itemsize;
@@ -3221,7 +3221,7 @@ PyArray_CopyInto(PyArrayObject *dst, PyArrayObject *src)
}
/* Copying unmasked into unmasked */
else if (!dst_has_maskna) {
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
PyArrayObject *op[2];
npy_uint32 op_flags[2];
@@ -3332,7 +3332,7 @@ PyArray_CopyInto(PyArrayObject *dst, PyArrayObject *src)
}
/* Copying non NA-masked into NA-masked */
else if (!src_has_maskna) {
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
PyArrayObject *op[2];
npy_uint32 op_flags[2];
@@ -3462,7 +3462,7 @@ PyArray_CopyInto(PyArrayObject *dst, PyArrayObject *src)
}
/* Copying NA-masked into NA-masked */
else {
- PyArray_MaskedStridedTransferFn *stransfer = NULL;
+ PyArray_MaskedStridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
PyArrayObject *op[2];
npy_uint32 op_flags[2];
@@ -3612,7 +3612,7 @@ NPY_NO_EXPORT int
PyArray_MaskedCopyInto(PyArrayObject *dst, PyArrayObject *src,
PyArrayObject *mask, NPY_CASTING casting)
{
- PyArray_MaskedStridedTransferFn *stransfer = NULL;
+ PyArray_MaskedStridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
NPY_BEGIN_THREADS_DEF;
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index 4f832bd12..d5e937a67 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -714,13 +714,12 @@ validate_object_field_overlap(PyArray_Descr *dtype)
PyObject *names, *fields, *key, *tup, *title;
Py_ssize_t i, j, names_size;
PyArray_Descr *fld_dtype, *fld2_dtype;
- int fld_offset, fld2_offset, align;
+ int fld_offset, fld2_offset;
/* Get some properties from the dtype */
names = dtype->names;
names_size = PyTuple_GET_SIZE(names);
fields = dtype->fields;
- align = PyDataType_FLAGCHK(dtype, NPY_ALIGNED_STRUCT);
for (i = 0; i < names_size; ++i) {
key = PyTuple_GET_ITEM(names, i);
diff --git a/numpy/core/src/multiarray/dtype_transfer.c b/numpy/core/src/multiarray/dtype_transfer.c
index a4fe27842..650042902 100644
--- a/numpy/core/src/multiarray/dtype_transfer.c
+++ b/numpy/core/src/multiarray/dtype_transfer.c
@@ -57,7 +57,7 @@ static int
get_decsrcref_transfer_function(int aligned,
npy_intp src_stride,
PyArray_Descr *src_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api);
@@ -70,7 +70,7 @@ static int
get_setdstzero_transfer_function(int aligned,
npy_intp dst_stride,
PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api);
@@ -81,7 +81,7 @@ get_setdstzero_transfer_function(int aligned,
*/
NPY_NO_EXPORT int
get_bool_setdstone_transfer_function(npy_intp dst_stride,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *NPY_UNUSED(out_needs_api));
@@ -213,7 +213,7 @@ NPY_NO_EXPORT int
PyArray_GetStridedZeroPadCopyFn(int aligned,
npy_intp src_stride, npy_intp dst_stride,
npy_intp src_itemsize, npy_intp dst_itemsize,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata)
{
if (src_itemsize == dst_itemsize) {
@@ -250,7 +250,7 @@ PyArray_GetStridedZeroPadCopyFn(int aligned,
/* Wraps a transfer function + data in alignment code */
typedef struct {
NpyAuxData base;
- PyArray_StridedTransferFn *wrapped,
+ PyArray_StridedUnaryOp *wrapped,
*tobuffer, *frombuffer;
NpyAuxData *wrappeddata, *todata, *fromdata;
npy_intp src_itemsize, dst_itemsize;
@@ -325,7 +325,7 @@ _strided_to_strided_contig_align_wrap(char *dst, npy_intp dst_stride,
NpyAuxData *data)
{
_align_wrap_data *d = (_align_wrap_data *)data;
- PyArray_StridedTransferFn *wrapped = d->wrapped,
+ PyArray_StridedUnaryOp *wrapped = d->wrapped,
*tobuffer = d->tobuffer,
*frombuffer = d->frombuffer;
npy_intp inner_src_itemsize = d->src_itemsize,
@@ -369,7 +369,7 @@ _strided_to_strided_contig_align_wrap_init_dest(char *dst, npy_intp dst_stride,
NpyAuxData *data)
{
_align_wrap_data *d = (_align_wrap_data *)data;
- PyArray_StridedTransferFn *wrapped = d->wrapped,
+ PyArray_StridedUnaryOp *wrapped = d->wrapped,
*tobuffer = d->tobuffer,
*frombuffer = d->frombuffer;
npy_intp inner_src_itemsize = d->src_itemsize,
@@ -426,11 +426,11 @@ _strided_to_strided_contig_align_wrap_init_dest(char *dst, npy_intp dst_stride,
NPY_NO_EXPORT int
wrap_aligned_contig_transfer_function(
npy_intp src_itemsize, npy_intp dst_itemsize,
- PyArray_StridedTransferFn *tobuffer, NpyAuxData *todata,
- PyArray_StridedTransferFn *frombuffer, NpyAuxData *fromdata,
- PyArray_StridedTransferFn *wrapped, NpyAuxData *wrappeddata,
+ PyArray_StridedUnaryOp *tobuffer, NpyAuxData *todata,
+ PyArray_StridedUnaryOp *frombuffer, NpyAuxData *fromdata,
+ PyArray_StridedUnaryOp *wrapped, NpyAuxData *wrappeddata,
int init_dest,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata)
{
_align_wrap_data *data;
@@ -524,7 +524,7 @@ wrap_copy_swap_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *dtype,
int should_swap,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata)
{
_wrap_copy_swap_data *data;
@@ -655,7 +655,7 @@ static int
get_nbo_cast_numeric_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
int src_type_num, int dst_type_num,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata)
{
/* Emit a warning if complex imaginary is being cast away */
@@ -943,7 +943,7 @@ static int
get_nbo_cast_datetime_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata)
{
PyArray_DatetimeMetaData *src_meta, *dst_meta;
@@ -1019,7 +1019,7 @@ static int
get_nbo_datetime_to_string_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata)
{
PyArray_DatetimeMetaData *src_meta;
@@ -1064,12 +1064,12 @@ static int
get_datetime_to_unicode_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
NpyAuxData *castdata = NULL, *todata = NULL, *fromdata = NULL;
- PyArray_StridedTransferFn *caststransfer, *tobuffer, *frombuffer;
+ PyArray_StridedUnaryOp *caststransfer, *tobuffer, *frombuffer;
PyArray_Descr *str_dtype;
/* Get an ASCII string data type, adapted to match the UNICODE one */
@@ -1134,7 +1134,7 @@ static int
get_nbo_string_to_datetime_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata)
{
PyArray_DatetimeMetaData *dst_meta;
@@ -1186,12 +1186,12 @@ static int
get_unicode_to_datetime_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
NpyAuxData *castdata = NULL, *todata = NULL, *fromdata = NULL;
- PyArray_StridedTransferFn *caststransfer, *tobuffer, *frombuffer;
+ PyArray_StridedUnaryOp *caststransfer, *tobuffer, *frombuffer;
PyArray_Descr *str_dtype;
/* Get an ASCII string data type, adapted to match the UNICODE one */
@@ -1258,7 +1258,7 @@ get_nbo_cast_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api,
int *out_needs_wrap)
@@ -1465,11 +1465,11 @@ get_cast_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
- PyArray_StridedTransferFn *caststransfer;
+ PyArray_StridedUnaryOp *caststransfer;
NpyAuxData *castdata, *todata = NULL, *fromdata = NULL;
int needs_wrap = 0;
npy_intp src_itemsize = src_dtype->elsize,
@@ -1506,7 +1506,7 @@ get_cast_transfer_function(int aligned,
}
/* Otherwise, we have to copy and/or swap to aligned temporaries */
else {
- PyArray_StridedTransferFn *tobuffer, *frombuffer;
+ PyArray_StridedUnaryOp *tobuffer, *frombuffer;
/* Get the copy/swap operation from src */
PyArray_GetDTypeCopySwapFn(aligned,
@@ -1553,11 +1553,11 @@ get_cast_transfer_function(int aligned,
/* Copies 1 element to N contiguous elements */
typedef struct {
NpyAuxData base;
- PyArray_StridedTransferFn *stransfer;
+ PyArray_StridedUnaryOp *stransfer;
NpyAuxData *data;
npy_intp N, dst_itemsize;
/* If this is non-NULL the source type has references needing a decref */
- PyArray_StridedTransferFn *stransfer_finish_src;
+ PyArray_StridedUnaryOp *stransfer_finish_src;
NpyAuxData *data_finish_src;
} _one_to_n_data;
@@ -1608,7 +1608,7 @@ _strided_to_strided_one_to_n(char *dst, npy_intp dst_stride,
NpyAuxData *data)
{
_one_to_n_data *d = (_one_to_n_data *)data;
- PyArray_StridedTransferFn *subtransfer = d->stransfer;
+ PyArray_StridedUnaryOp *subtransfer = d->stransfer;
NpyAuxData *subdata = d->data;
npy_intp subN = d->N, dst_itemsize = d->dst_itemsize;
@@ -1631,7 +1631,7 @@ _strided_to_strided_one_to_n_with_finish(char *dst, npy_intp dst_stride,
NpyAuxData *data)
{
_one_to_n_data *d = (_one_to_n_data *)data;
- PyArray_StridedTransferFn *subtransfer = d->stransfer,
+ PyArray_StridedUnaryOp *subtransfer = d->stransfer,
*stransfer_finish_src = d->stransfer_finish_src;
NpyAuxData *subdata = d->data, *data_finish_src = data_finish_src;
npy_intp subN = d->N, dst_itemsize = d->dst_itemsize;
@@ -1662,13 +1662,13 @@ _strided_to_strided_one_to_n_with_finish(char *dst, npy_intp dst_stride,
*/
static int
wrap_transfer_function_one_to_n(
- PyArray_StridedTransferFn *stransfer_inner,
+ PyArray_StridedUnaryOp *stransfer_inner,
NpyAuxData *data_inner,
- PyArray_StridedTransferFn *stransfer_finish_src,
+ PyArray_StridedUnaryOp *stransfer_finish_src,
NpyAuxData *data_finish_src,
npy_intp dst_itemsize,
npy_intp N,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata)
{
_one_to_n_data *data;
@@ -1706,11 +1706,11 @@ get_one_to_n_transfer_function(int aligned,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
npy_intp N,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
- PyArray_StridedTransferFn *stransfer, *stransfer_finish_src = NULL;
+ PyArray_StridedUnaryOp *stransfer, *stransfer_finish_src = NULL;
NpyAuxData *data, *data_finish_src = NULL;
/*
@@ -1759,7 +1759,7 @@ get_one_to_n_transfer_function(int aligned,
/* Copies N contiguous elements to N contiguous elements */
typedef struct {
NpyAuxData base;
- PyArray_StridedTransferFn *stransfer;
+ PyArray_StridedUnaryOp *stransfer;
NpyAuxData *data;
npy_intp N, src_itemsize, dst_itemsize;
} _n_to_n_data;
@@ -1802,7 +1802,7 @@ _strided_to_strided_n_to_n(char *dst, npy_intp dst_stride,
NpyAuxData *data)
{
_n_to_n_data *d = (_n_to_n_data *)data;
- PyArray_StridedTransferFn *subtransfer = d->stransfer;
+ PyArray_StridedUnaryOp *subtransfer = d->stransfer;
NpyAuxData *subdata = d->data;
npy_intp subN = d->N, src_subitemsize = d->src_itemsize,
dst_subitemsize = d->dst_itemsize;
@@ -1826,7 +1826,7 @@ _contig_to_contig_n_to_n(char *dst, npy_intp NPY_UNUSED(dst_stride),
NpyAuxData *data)
{
_n_to_n_data *d = (_n_to_n_data *)data;
- PyArray_StridedTransferFn *subtransfer = d->stransfer;
+ PyArray_StridedUnaryOp *subtransfer = d->stransfer;
NpyAuxData *subdata = d->data;
npy_intp subN = d->N, src_subitemsize = d->src_itemsize,
dst_subitemsize = d->dst_itemsize;
@@ -1843,12 +1843,12 @@ _contig_to_contig_n_to_n(char *dst, npy_intp NPY_UNUSED(dst_stride),
*/
static int
wrap_transfer_function_n_to_n(
- PyArray_StridedTransferFn *stransfer_inner,
+ PyArray_StridedUnaryOp *stransfer_inner,
NpyAuxData *data_inner,
npy_intp src_stride, npy_intp dst_stride,
npy_intp src_itemsize, npy_intp dst_itemsize,
npy_intp N,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata)
{
_n_to_n_data *data;
@@ -1889,11 +1889,11 @@ get_n_to_n_transfer_function(int aligned,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
npy_intp N,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
- PyArray_StridedTransferFn *stransfer;
+ PyArray_StridedUnaryOp *stransfer;
NpyAuxData *data;
/*
@@ -1931,12 +1931,12 @@ typedef struct {
/* Copies element with subarray broadcasting */
typedef struct {
NpyAuxData base;
- PyArray_StridedTransferFn *stransfer;
+ PyArray_StridedUnaryOp *stransfer;
NpyAuxData *data;
npy_intp src_N, dst_N, src_itemsize, dst_itemsize;
- PyArray_StridedTransferFn *stransfer_decsrcref;
+ PyArray_StridedUnaryOp *stransfer_decsrcref;
NpyAuxData *data_decsrcref;
- PyArray_StridedTransferFn *stransfer_decdstref;
+ PyArray_StridedUnaryOp *stransfer_decdstref;
NpyAuxData *data_decdstref;
/* This gets a run-length encoded representation of the transfer */
npy_intp run_count;
@@ -2004,7 +2004,7 @@ _strided_to_strided_subarray_broadcast(char *dst, npy_intp dst_stride,
NpyAuxData *data)
{
_subarray_broadcast_data *d = (_subarray_broadcast_data *)data;
- PyArray_StridedTransferFn *subtransfer = d->stransfer;
+ PyArray_StridedUnaryOp *subtransfer = d->stransfer;
NpyAuxData *subdata = d->data;
npy_intp run, run_count = d->run_count,
src_subitemsize = d->src_itemsize,
@@ -2045,11 +2045,11 @@ _strided_to_strided_subarray_broadcast_withrefs(char *dst, npy_intp dst_stride,
NpyAuxData *data)
{
_subarray_broadcast_data *d = (_subarray_broadcast_data *)data;
- PyArray_StridedTransferFn *subtransfer = d->stransfer;
+ PyArray_StridedUnaryOp *subtransfer = d->stransfer;
NpyAuxData *subdata = d->data;
- PyArray_StridedTransferFn *stransfer_decsrcref = d->stransfer_decsrcref;
+ PyArray_StridedUnaryOp *stransfer_decsrcref = d->stransfer_decsrcref;
NpyAuxData *data_decsrcref = d->data_decsrcref;
- PyArray_StridedTransferFn *stransfer_decdstref = d->stransfer_decdstref;
+ PyArray_StridedUnaryOp *stransfer_decdstref = d->stransfer_decdstref;
NpyAuxData *data_decdstref = d->data_decdstref;
npy_intp run, run_count = d->run_count,
src_subitemsize = d->src_itemsize,
@@ -2102,7 +2102,7 @@ get_subarray_broadcast_transfer_function(int aligned,
npy_intp src_size, npy_intp dst_size,
PyArray_Dims src_shape, PyArray_Dims dst_shape,
int move_references,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
@@ -2289,7 +2289,7 @@ get_subarray_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
@@ -2386,7 +2386,7 @@ get_subarray_transfer_function(int aligned,
/**************************** COPY FIELDS *******************************/
typedef struct {
npy_intp src_offset, dst_offset, src_itemsize;
- PyArray_StridedTransferFn *stransfer;
+ PyArray_StridedUnaryOp *stransfer;
NpyAuxData *data;
} _single_field_transfer;
@@ -2497,7 +2497,7 @@ get_fields_transfer_function(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
@@ -2869,7 +2869,7 @@ static int
get_decsrcref_fields_transfer_function(int aligned,
npy_intp src_stride,
PyArray_Descr *src_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
@@ -2940,7 +2940,7 @@ static int
get_setdestzero_fields_transfer_function(int aligned,
npy_intp dst_stride,
PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
@@ -3005,11 +3005,11 @@ get_setdestzero_fields_transfer_function(int aligned,
typedef struct {
NpyAuxData base;
/* The transfer function being wrapped */
- PyArray_StridedTransferFn *stransfer;
+ PyArray_StridedUnaryOp *stransfer;
NpyAuxData *transferdata;
/* The src decref function if necessary */
- PyArray_StridedTransferFn *decsrcref_stransfer;
+ PyArray_StridedUnaryOp *decsrcref_stransfer;
NpyAuxData *decsrcref_transferdata;
} _masked_wrapper_transfer_data;
@@ -3067,7 +3067,7 @@ void _strided_masked_wrapper_decsrcref_transfer_function(
_masked_wrapper_transfer_data *d =
(_masked_wrapper_transfer_data *)transferdata;
npy_intp subloopsize;
- PyArray_StridedTransferFn *unmasked_stransfer, *decsrcref_stransfer;
+ PyArray_StridedUnaryOp *unmasked_stransfer, *decsrcref_stransfer;
NpyAuxData *unmasked_transferdata, *decsrcref_transferdata;
unmasked_stransfer = d->stransfer;
@@ -3112,7 +3112,7 @@ void _strided_masked_wrapper_transfer_function(
_masked_wrapper_transfer_data *d =
(_masked_wrapper_transfer_data *)transferdata;
npy_intp subloopsize;
- PyArray_StridedTransferFn *unmasked_stransfer;
+ PyArray_StridedUnaryOp *unmasked_stransfer;
NpyAuxData *unmasked_transferdata;
unmasked_stransfer = d->stransfer;
@@ -3177,7 +3177,7 @@ _null_to_contig_set_bool_one(char *dst,
/* Only for the bool type, sets the destination to 1 */
NPY_NO_EXPORT int
get_bool_setdstone_transfer_function(npy_intp dst_stride,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *NPY_UNUSED(out_needs_api))
{
@@ -3274,7 +3274,7 @@ NPY_NO_EXPORT int
get_setdstzero_transfer_function(int aligned,
npy_intp dst_stride,
PyArray_Descr *dst_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
@@ -3314,7 +3314,7 @@ get_setdstzero_transfer_function(int aligned,
else if (PyDataType_HASSUBARRAY(dst_dtype)) {
PyArray_Dims dst_shape = {NULL, -1};
npy_intp dst_size = 1;
- PyArray_StridedTransferFn *contig_stransfer;
+ PyArray_StridedUnaryOp *contig_stransfer;
NpyAuxData *contig_data;
if (out_needs_api) {
@@ -3401,7 +3401,7 @@ NPY_NO_EXPORT int
get_decsrcref_transfer_function(int aligned,
npy_intp src_stride,
PyArray_Descr *src_dtype,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
@@ -3427,7 +3427,7 @@ get_decsrcref_transfer_function(int aligned,
else if (PyDataType_HASSUBARRAY(src_dtype)) {
PyArray_Dims src_shape = {NULL, -1};
npy_intp src_size = 1;
- PyArray_StridedTransferFn *stransfer;
+ PyArray_StridedUnaryOp *stransfer;
NpyAuxData *data;
if (out_needs_api) {
@@ -3483,7 +3483,7 @@ NPY_NO_EXPORT int
PyArray_GetDTypeCopySwapFn(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *dtype,
- PyArray_StridedTransferFn **outstransfer,
+ PyArray_StridedUnaryOp **outstransfer,
NpyAuxData **outtransferdata)
{
npy_intp itemsize = dtype->elsize;
@@ -3529,7 +3529,7 @@ PyArray_GetDTypeTransferFunction(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
@@ -3755,11 +3755,11 @@ PyArray_GetMaskedDTypeTransferFunction(int aligned,
PyArray_Descr *dst_dtype,
PyArray_Descr *mask_dtype,
int move_references,
- PyArray_MaskedStridedTransferFn **out_stransfer,
+ PyArray_MaskedStridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api)
{
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
_masked_wrapper_transfer_data *data;
@@ -3831,7 +3831,7 @@ PyArray_CastRawArrays(npy_intp count,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references)
{
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
int aligned = 1, needs_api = 0;
@@ -4110,7 +4110,7 @@ PyArray_CastRawNDimArrays(int ndim, npy_intp *shape,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references)
{
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
int idim;
npy_intp src_align, dst_align;
diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c
index 8e861d460..8a38f4531 100644
--- a/numpy/core/src/multiarray/item_selection.c
+++ b/numpy/core/src/multiarray/item_selection.c
@@ -138,7 +138,7 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
if (use_maskna) {
char *dst_maskna = NULL, *src_maskna = NULL;
npy_intp itemsize = PyArray_DESCR(obj)->elsize;
- PyArray_MaskedStridedTransferFn *maskedstransfer = NULL;
+ PyArray_MaskedStridedUnaryOp *maskedstransfer = NULL;
NpyAuxData *transferdata = NULL;
int needs_api = 0;
diff --git a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src
index 4476e0a35..82cf49ea2 100644
--- a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src
+++ b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src
@@ -311,7 +311,7 @@ _contig_to_contig(char *dst, npy_intp NPY_UNUSED(dst_stride),
}
-NPY_NO_EXPORT PyArray_StridedTransferFn *
+NPY_NO_EXPORT PyArray_StridedUnaryOp *
PyArray_GetStridedCopyFn(int aligned, npy_intp src_stride,
npy_intp dst_stride, npy_intp itemsize)
{
@@ -466,7 +466,7 @@ PyArray_GetStridedCopyFn(int aligned, npy_intp src_stride,
* #not_pair = 1, 0#
*/
-NPY_NO_EXPORT PyArray_StridedTransferFn *
+NPY_NO_EXPORT PyArray_StridedUnaryOp *
@function@(int aligned, npy_intp src_stride,
npy_intp dst_stride, npy_intp itemsize)
{
@@ -848,7 +848,7 @@ static void
/**end repeat**/
-NPY_NO_EXPORT PyArray_StridedTransferFn *
+NPY_NO_EXPORT PyArray_StridedUnaryOp *
PyArray_GetStridedNumericCastFn(int aligned, npy_intp src_stride,
npy_intp dst_stride,
int src_type_num, int dst_type_num)
@@ -929,7 +929,7 @@ PyArray_TransferNDimToStrided(npy_intp ndim,
npy_intp *coords, npy_intp coords_inc,
npy_intp *shape, npy_intp shape_inc,
npy_intp count, npy_intp src_itemsize,
- PyArray_StridedTransferFn *stransfer,
+ PyArray_StridedUnaryOp *stransfer,
NpyAuxData *data)
{
npy_intp i, M, N, coord0, shape0, src_stride0, coord1, shape1, src_stride1;
@@ -1048,7 +1048,7 @@ PyArray_TransferStridedToNDim(npy_intp ndim,
npy_intp *coords, npy_intp coords_inc,
npy_intp *shape, npy_intp shape_inc,
npy_intp count, npy_intp src_itemsize,
- PyArray_StridedTransferFn *stransfer,
+ PyArray_StridedUnaryOp *stransfer,
NpyAuxData *data)
{
npy_intp i, M, N, coord0, shape0, dst_stride0, coord1, shape1, dst_stride1;
@@ -1168,7 +1168,7 @@ PyArray_TransferMaskedStridedToNDim(npy_intp ndim,
npy_intp *coords, npy_intp coords_inc,
npy_intp *shape, npy_intp shape_inc,
npy_intp count, npy_intp src_itemsize,
- PyArray_MaskedStridedTransferFn *stransfer,
+ PyArray_MaskedStridedUnaryOp *stransfer,
NpyAuxData *data)
{
npy_intp i, M, N, coord0, shape0, dst_stride0, coord1, shape1, dst_stride1;
diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c
index 30f00576b..4d37da61c 100644
--- a/numpy/core/src/multiarray/mapping.c
+++ b/numpy/core/src/multiarray/mapping.c
@@ -762,7 +762,7 @@ array_boolean_subscript(PyArrayObject *self,
PyArrayObject *op[2] = {self, bmask};
npy_uint32 flags, op_flags[2];
npy_intp fixed_strides[3];
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
NpyIter_IterNextFunc *iternext;
@@ -1068,7 +1068,7 @@ array_ass_boolean_subscript(PyArrayObject *self,
/* Regular inner loop */
if (!self_has_maskna) {
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
npy_intp self_stride = innerstrides[0];
npy_intp bmask_stride = innerstrides[1];
@@ -1119,7 +1119,7 @@ array_ass_boolean_subscript(PyArrayObject *self,
}
/* NA masked inner loop */
else {
- PyArray_MaskedStridedTransferFn *stransfer = NULL;
+ PyArray_MaskedStridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
npy_intp i;
npy_intp self_stride = innerstrides[0];
diff --git a/numpy/core/src/multiarray/na_mask.c b/numpy/core/src/multiarray/na_mask.c
index 286fe5c1b..d6c8d1463 100644
--- a/numpy/core/src/multiarray/na_mask.c
+++ b/numpy/core/src/multiarray/na_mask.c
@@ -577,3 +577,43 @@ printf("\n");
return 0;
}
+
+static void
+_strided_bool_mask_inversion(char *dst, npy_intp dst_stride,
+ char *src, npy_intp src_stride,
+ npy_intp N, npy_intp NPY_UNUSED(src_itemsize),
+ NpyAuxData *NPY_UNUSED(data))
+{
+ while (N > 0) {
+ *dst = !(*src);
+ dst += dst_stride;
+ src += src_stride;
+ --N;
+ }
+}
+
+NPY_NO_EXPORT int
+PyArray_GetMaskInversionFunction(npy_intp mask_stride,
+ PyArray_Descr *mask_dtype,
+ PyArray_StridedUnaryOp **out_stransfer,
+ NpyAuxData **out_transferdata)
+{
+ /* Will use the transferdata with the field version */
+ if (PyDataType_HASFIELDS(mask_dtype)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "field-based masks are not supported yet");
+ return -1;
+ }
+
+ if (mask_dtype->type_num != NPY_BOOL && mask_dtype->type_num != NPY_MASK) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "unsupported data type for mask");
+ return -1;
+ }
+
+ /* TODO: Specialize for contiguous data */
+
+ *out_stransfer = &_strided_bool_mask_inversion;
+ *out_transferdata = NULL;
+ return 0;
+}
diff --git a/numpy/core/src/multiarray/na_mask.h b/numpy/core/src/multiarray/na_mask.h
index 22944b781..d0538cda3 100644
--- a/numpy/core/src/multiarray/na_mask.h
+++ b/numpy/core/src/multiarray/na_mask.h
@@ -1,6 +1,8 @@
#ifndef _NPY_PRIVATE__NA_MASK_H_
#define _NPY_PRIVATE__NA_MASK_H_
+#include "lowlevel_strided_loops.h"
+
/*
* Assigns the given NA value to all the elements in the array.
*
@@ -26,4 +28,13 @@ PyArray_AssignMaskNA(PyArrayObject *arr, npy_mask maskvalue);
NPY_NO_EXPORT PyObject *
PyArray_IsNA(PyObject *obj);
+/*
+ * Gets a strided unary operation which inverts mask values.
+ */
+NPY_NO_EXPORT int
+PyArray_GetMaskInversionFunction(npy_intp mask_stride,
+ PyArray_Descr *mask_dtype,
+ PyArray_StridedUnaryOp **out_stransfer,
+ NpyAuxData **out_transferdata);
+
#endif
diff --git a/numpy/core/src/multiarray/nditer_api.c b/numpy/core/src/multiarray/nditer_api.c
index b3402129f..0c925d8b9 100644
--- a/numpy/core/src/multiarray/nditer_api.c
+++ b/numpy/core/src/multiarray/nditer_api.c
@@ -1838,7 +1838,7 @@ npyiter_copy_from_buffers(NpyIter *iter)
npy_intp reduce_outerdim = 0;
npy_intp *reduce_outerstrides = NULL;
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
npy_intp axisdata_incr = NIT_AXISDATA_SIZEOF(itflags, ndim, nop) /
@@ -1962,7 +1962,7 @@ npyiter_copy_from_buffers(NpyIter *iter)
dst_coords, axisdata_incr,
dst_shape, axisdata_incr,
op_transfersize, dtypes[iop]->elsize,
- (PyArray_MaskedStridedTransferFn *)stransfer,
+ (PyArray_MaskedStridedUnaryOp *)stransfer,
transferdata);
}
/* WRITEMASKED operand */
@@ -1989,7 +1989,7 @@ npyiter_copy_from_buffers(NpyIter *iter)
dst_coords, axisdata_incr,
dst_shape, axisdata_incr,
op_transfersize, dtypes[iop]->elsize,
- (PyArray_MaskedStridedTransferFn *)stransfer,
+ (PyArray_MaskedStridedUnaryOp *)stransfer,
transferdata);
}
/* Regular operand */
@@ -2064,7 +2064,7 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs)
npy_intp *reduce_outerstrides = NULL;
char **reduce_outerptrs = NULL;
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
/*
diff --git a/numpy/core/src/multiarray/nditer_constr.c b/numpy/core/src/multiarray/nditer_constr.c
index 9f7b7948d..a7f3ab30e 100644
--- a/numpy/core/src/multiarray/nditer_constr.c
+++ b/numpy/core/src/multiarray/nditer_constr.c
@@ -3355,13 +3355,13 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
PyArrayObject **op = NIT_OPERANDS(iter);
PyArray_Descr **op_dtype = NIT_DTYPES(iter);
npy_intp *strides = NAD_STRIDES(axisdata), op_stride;
- PyArray_StridedTransferFn **readtransferfn = NBF_READTRANSFERFN(bufferdata),
+ PyArray_StridedUnaryOp **readtransferfn = NBF_READTRANSFERFN(bufferdata),
**writetransferfn = NBF_WRITETRANSFERFN(bufferdata);
NpyAuxData **readtransferdata = NBF_READTRANSFERDATA(bufferdata),
**writetransferdata = NBF_WRITETRANSFERDATA(bufferdata);
npy_int8 *maskna_indices = NIT_MASKNA_INDICES(iter);
- PyArray_StridedTransferFn *stransfer = NULL;
+ PyArray_StridedUnaryOp *stransfer = NULL;
NpyAuxData *transferdata = NULL;
int needs_api = 0;
@@ -3433,7 +3433,7 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
op_orig_dtype,
mask_dtype,
move_references,
- (PyArray_MaskedStridedTransferFn **)&stransfer,
+ (PyArray_MaskedStridedUnaryOp **)&stransfer,
&transferdata,
&needs_api) != NPY_SUCCEED) {
goto fail;
@@ -3460,7 +3460,7 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
op_orig_dtype,
mask_dtype,
move_references,
- (PyArray_MaskedStridedTransferFn **)&stransfer,
+ (PyArray_MaskedStridedUnaryOp **)&stransfer,
&transferdata,
&needs_api) != NPY_SUCCEED) {
goto fail;
diff --git a/numpy/core/src/multiarray/nditer_impl.h b/numpy/core/src/multiarray/nditer_impl.h
index 753b8188f..de361470d 100644
--- a/numpy/core/src/multiarray/nditer_impl.h
+++ b/numpy/core/src/multiarray/nditer_impl.h
@@ -251,11 +251,11 @@ struct NpyIter_BD {
(&(bufferdata)->bd_flexdata + 2*(nop)))
#define NBF_REDUCE_OUTERPTRS(bufferdata) ((char **) \
(&(bufferdata)->bd_flexdata + 3*(nop)))
-#define NBF_READTRANSFERFN(bufferdata) ((PyArray_StridedTransferFn **) \
+#define NBF_READTRANSFERFN(bufferdata) ((PyArray_StridedUnaryOp **) \
(&(bufferdata)->bd_flexdata + 4*(nop)))
#define NBF_READTRANSFERDATA(bufferdata) ((NpyAuxData **) \
(&(bufferdata)->bd_flexdata + 5*(nop)))
-#define NBF_WRITETRANSFERFN(bufferdata) ((PyArray_StridedTransferFn **) \
+#define NBF_WRITETRANSFERFN(bufferdata) ((PyArray_StridedUnaryOp **) \
(&(bufferdata)->bd_flexdata + 6*(nop)))
#define NBF_WRITETRANSFERDATA(bufferdata) ((NpyAuxData **) \
(&(bufferdata)->bd_flexdata + 7*(nop)))
diff --git a/numpy/core/src/private/lowlevel_strided_loops.h b/numpy/core/src/private/lowlevel_strided_loops.h
index a4ba0526d..f25019015 100644
--- a/numpy/core/src/private/lowlevel_strided_loops.h
+++ b/numpy/core/src/private/lowlevel_strided_loops.h
@@ -8,12 +8,13 @@
*/
/*
- * This function pointer is for functions that transfer an arbitrarily strided
- * input to a an arbitrarily strided output. It may be a fully general
- * function, or a specialized function when the strides or item size
- * have special values.
+ * This function pointer is for unary operations that input an
+ * arbitrarily strided one-dimensional array segment and output
+ * an arbitrarily strided array segment of the same size.
+ * It may be a fully general function, or a specialized function
+ * when the strides or item size have particular known values.
*
- * Examples of transfer functions are a straight copy, a byte-swap,
+ * Examples of unary operations are a straight copy, a byte-swap,
* and a casting operation,
*
* The 'transferdata' parameter is slightly special, following a
@@ -21,20 +22,20 @@
* Use NPY_AUXDATA_CLONE and NPY_AUXDATA_FREE to deal with this data.
*
*/
-typedef void (PyArray_StridedTransferFn)(char *dst, npy_intp dst_stride,
+typedef void (PyArray_StridedUnaryOp)(char *dst, npy_intp dst_stride,
char *src, npy_intp src_stride,
npy_intp N, npy_intp src_itemsize,
NpyAuxData *transferdata);
/*
* This is for pointers to functions which behave exactly as
- * for PyArray_StridedTransferFn, but with an additional mask controlling
- * which values are transferred.
+ * for PyArray_StridedUnaryOp, but with an additional mask controlling
+ * which values are transformed.
*
- * In particular, the 'i'-th element is transfered if and only if
- * NpyMask_IsExposed(mask[i*mask_stride]).
+ * In particular, the 'i'-th element is operated on if and only if
+ * NpyMaskValue_IsExposed(mask[i*mask_stride]).
*/
-typedef void (PyArray_MaskedStridedTransferFn)(char *dst, npy_intp dst_stride,
+typedef void (PyArray_MaskedStridedUnaryOp)(char *dst, npy_intp dst_stride,
char *src, npy_intp src_stride,
npy_mask *mask, npy_intp mask_stride,
npy_intp N, npy_intp src_itemsize,
@@ -57,7 +58,7 @@ typedef void (PyArray_MaskedStridedTransferFn)(char *dst, npy_intp dst_stride,
* Should be the item size if it will always be the same, 0 otherwise.
*
*/
-NPY_NO_EXPORT PyArray_StridedTransferFn *
+NPY_NO_EXPORT PyArray_StridedUnaryOp *
PyArray_GetStridedCopyFn(int aligned,
npy_intp src_stride, npy_intp dst_stride,
npy_intp itemsize);
@@ -72,7 +73,7 @@ PyArray_GetStridedCopyFn(int aligned,
*
* Parameters are as for PyArray_GetStridedCopyFn.
*/
-NPY_NO_EXPORT PyArray_StridedTransferFn *
+NPY_NO_EXPORT PyArray_StridedUnaryOp *
PyArray_GetStridedCopySwapFn(int aligned,
npy_intp src_stride, npy_intp dst_stride,
npy_intp itemsize);
@@ -87,7 +88,7 @@ PyArray_GetStridedCopySwapFn(int aligned,
*
* Parameters are as for PyArray_GetStridedCopyFn.
*/
-NPY_NO_EXPORT PyArray_StridedTransferFn *
+NPY_NO_EXPORT PyArray_StridedUnaryOp *
PyArray_GetStridedCopySwapPairFn(int aligned,
npy_intp src_stride, npy_intp dst_stride,
npy_intp itemsize);
@@ -106,7 +107,7 @@ NPY_NO_EXPORT int
PyArray_GetStridedZeroPadCopyFn(int aligned,
npy_intp src_stride, npy_intp dst_stride,
npy_intp src_itemsize, npy_intp dst_itemsize,
- PyArray_StridedTransferFn **outstransfer,
+ PyArray_StridedUnaryOp **outstransfer,
NpyAuxData **outtransferdata);
/*
@@ -115,7 +116,7 @@ PyArray_GetStridedZeroPadCopyFn(int aligned,
* to dst_type_num. If a conversion is unsupported, returns NULL
* without setting a Python exception.
*/
-NPY_NO_EXPORT PyArray_StridedTransferFn *
+NPY_NO_EXPORT PyArray_StridedUnaryOp *
PyArray_GetStridedNumericCastFn(int aligned,
npy_intp src_stride, npy_intp dst_stride,
int src_type_num, int dst_type_num);
@@ -130,14 +131,14 @@ NPY_NO_EXPORT int
PyArray_GetDTypeCopySwapFn(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *dtype,
- PyArray_StridedTransferFn **outstransfer,
+ PyArray_StridedUnaryOp **outstransfer,
NpyAuxData **outtransferdata);
/*
* If it's possible, gives back a transfer function which casts and/or
* byte swaps data with the dtype 'src_dtype' into data with the dtype
* 'dst_dtype'. If the outtransferdata is populated with a non-NULL value,
- * it must be deallocated with the ``PyArray_FreeStridedTransferData``
+ * it must be deallocated with the NPY_AUXDATA_FREE
* function when the transfer function is no longer required.
*
* aligned:
@@ -165,7 +166,7 @@ PyArray_GetDTypeCopySwapFn(int aligned,
* out_transferdata:
* The auxiliary data for the transfer function is placed here.
* When finished with the transfer function, the caller must call
- * ``PyArray_FreeStridedTransferData`` on this data.
+ * NPY_AUXDATA_FREE on this data.
* out_needs_api:
* If this is non-NULL, and the transfer function produced needs
* to call into the (Python) API, this gets set to 1. This
@@ -183,7 +184,7 @@ PyArray_GetDTypeTransferFunction(int aligned,
npy_intp src_stride, npy_intp dst_stride,
PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
int move_references,
- PyArray_StridedTransferFn **out_stransfer,
+ PyArray_StridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api);
@@ -211,7 +212,7 @@ PyArray_GetMaskedDTypeTransferFunction(int aligned,
PyArray_Descr *dst_dtype,
PyArray_Descr *mask_dtype,
int move_references,
- PyArray_MaskedStridedTransferFn **out_stransfer,
+ PyArray_MaskedStridedUnaryOp **out_stransfer,
NpyAuxData **out_transferdata,
int *out_needs_api);
@@ -292,7 +293,7 @@ PyArray_TransferNDimToStrided(npy_intp ndim,
npy_intp *coords, npy_intp coords_inc,
npy_intp *shape, npy_intp shape_inc,
npy_intp count, npy_intp src_itemsize,
- PyArray_StridedTransferFn *stransfer,
+ PyArray_StridedUnaryOp *stransfer,
NpyAuxData *transferdata);
NPY_NO_EXPORT npy_intp
@@ -302,7 +303,7 @@ PyArray_TransferStridedToNDim(npy_intp ndim,
npy_intp *coords, npy_intp coords_inc,
npy_intp *shape, npy_intp shape_inc,
npy_intp count, npy_intp src_itemsize,
- PyArray_StridedTransferFn *stransfer,
+ PyArray_StridedUnaryOp *stransfer,
NpyAuxData *transferdata);
NPY_NO_EXPORT npy_intp
@@ -313,7 +314,7 @@ PyArray_TransferMaskedStridedToNDim(npy_intp ndim,
npy_intp *coords, npy_intp coords_inc,
npy_intp *shape, npy_intp shape_inc,
npy_intp count, npy_intp src_itemsize,
- PyArray_MaskedStridedTransferFn *stransfer,
+ PyArray_MaskedStridedUnaryOp *stransfer,
NpyAuxData *data);
/*