summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/release/upcoming_changes/14942.compatibility.rst11
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src55
-rw-r--r--numpy/core/src/multiarray/item_selection.c83
-rw-r--r--numpy/core/tests/test_item_selection.py5
4 files changed, 76 insertions, 78 deletions
diff --git a/doc/release/upcoming_changes/14942.compatibility.rst b/doc/release/upcoming_changes/14942.compatibility.rst
index 41a2457e2..1f0159c2f 100644
--- a/doc/release/upcoming_changes/14942.compatibility.rst
+++ b/doc/release/upcoming_changes/14942.compatibility.rst
@@ -1,5 +1,6 @@
-Fasttake slot is deprecated and now NULL'ed
--------------------------------------------
-The fasttake slot for all dtypes is now never used internally
-and always set to NULL. No downstream project should be using
-this, so no compatibility issue is expected.
+Fasttake and fastputmask slots are deprecated and NULL'ed
+---------------------------------------------------------
+The fasttake and fastputmask slots are now never used internally.
+They will always set to NULL for builtin dtypes.
+No downstream project should be using these, so no compatibility
+issue are expected.
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src
index 0f52df486..70c8baa8f 100644
--- a/numpy/core/src/multiarray/arraytypes.c.src
+++ b/numpy/core/src/multiarray/arraytypes.c.src
@@ -3923,59 +3923,6 @@ static void
/*
*****************************************************************************
- ** FASTPUTMASK **
- *****************************************************************************
- */
-
-
-/**begin repeat
- *
- * #name = BOOL,
- * BYTE, UBYTE, SHORT, USHORT, INT, UINT,
- * LONG, ULONG, LONGLONG, ULONGLONG,
- * HALF, FLOAT, DOUBLE, LONGDOUBLE,
- * CFLOAT, CDOUBLE, CLONGDOUBLE,
- * DATETIME, TIMEDELTA#
- * #type = npy_bool, npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
- * npy_long, npy_ulong, npy_longlong, npy_ulonglong,
- * npy_half, npy_float, npy_double, npy_longdouble,
- * npy_cfloat, npy_cdouble, npy_clongdouble,
- * npy_datetime, npy_timedelta#
-*/
-static void
-@name@_fastputmask(@type@ *in, npy_bool *mask, npy_intp ni, @type@ *vals,
- npy_intp nv)
-{
- npy_intp i, j;
-
- if (nv == 1) {
- @type@ s_val = *vals;
- for (i = 0; i < ni; i++) {
- if (mask[i]) {
- in[i] = s_val;
- }
- }
- }
- else {
- for (i = 0, j = 0; i < ni; i++, j++) {
- if (j >= nv) {
- j = 0;
- }
- if (mask[i]) {
- in[i] = vals[j];
- }
- }
- }
- return;
-}
-/**end repeat**/
-
-#define OBJECT_fastputmask NULL
-
-
-
-/*
- *****************************************************************************
** small correlate **
*****************************************************************************
*/
@@ -4332,7 +4279,7 @@ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = {
NULL,
NULL,
(PyArray_FastClipFunc*)NULL,
- (PyArray_FastPutmaskFunc*)@from@_fastputmask,
+ (PyArray_FastPutmaskFunc*)NULL,
(PyArray_FastTakeFunc*)NULL,
(PyArray_ArgFunc*)@from@_argmin
};
diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c
index 000ff6ef9..fd0450834 100644
--- a/numpy/core/src/multiarray/item_selection.c
+++ b/numpy/core/src/multiarray/item_selection.c
@@ -490,16 +490,78 @@ PyArray_PutTo(PyArrayObject *self, PyObject* values0, PyObject *indices0,
return NULL;
}
+
+static NPY_GCC_OPT_3 NPY_INLINE void
+npy_fastputmask_impl(
+ char *dest, char *src, const npy_bool *mask_data,
+ npy_intp ni, npy_intp nv, npy_intp chunk)
+{
+ if (nv == 1) {
+ for (npy_intp i = 0; i < ni; i++) {
+ if (mask_data[i]) {
+ memmove(dest, src, chunk);
+ }
+ dest += chunk;
+ }
+ }
+ else {
+ char *tmp_src = src;
+ for (npy_intp i = 0, j = 0; i < ni; i++, j++) {
+ if (NPY_UNLIKELY(j >= nv)) {
+ j = 0;
+ tmp_src = src;
+ }
+ if (mask_data[i]) {
+ memmove(dest, tmp_src, chunk);
+ }
+ dest += chunk;
+ tmp_src += chunk;
+ }
+ }
+}
+
+
+/*
+ * Helper function instantiating npy_fastput_impl in different branches
+ * to allow the compiler to optimize each to the specific itemsize.
+ */
+static NPY_GCC_OPT_3 void
+npy_fastputmask(
+ char *dest, char *src, npy_bool *mask_data,
+ npy_intp ni, npy_intp nv, npy_intp chunk)
+{
+ if (chunk == 1) {
+ return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+ }
+ if (chunk == 2) {
+ return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+ }
+ if (chunk == 4) {
+ return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+ }
+ if (chunk == 8) {
+ return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+ }
+ if (chunk == 16) {
+ return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+ }
+ if (chunk == 32) {
+ return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+ }
+
+ return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+}
+
+
/*NUMPY_API
* Put values into an array according to a mask.
*/
NPY_NO_EXPORT PyObject *
PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
{
- PyArray_FastPutmaskFunc *func;
PyArrayObject *mask, *values;
PyArray_Descr *dtype;
- npy_intp i, j, chunk, ni, nv;
+ npy_intp chunk, ni, nv;
char *src, *dest;
npy_bool *mask_data;
int copied = 0;
@@ -564,7 +626,7 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
dest = PyArray_DATA(self);
if (PyDataType_REFCHK(PyArray_DESCR(self))) {
- for (i = 0, j = 0; i < ni; i++, j++) {
+ for (npy_intp i = 0, j = 0; i < ni; i++, j++) {
if (j >= nv) {
j = 0;
}
@@ -581,20 +643,7 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
else {
NPY_BEGIN_THREADS_DEF;
NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(self));
- func = PyArray_DESCR(self)->f->fastputmask;
- if (func == NULL) {
- for (i = 0, j = 0; i < ni; i++, j++) {
- if (j >= nv) {
- j = 0;
- }
- if (mask_data[i]) {
- memmove(dest + i*chunk, src + j*chunk, chunk);
- }
- }
- }
- else {
- func(dest, mask_data, ni, src, nv);
- }
+ npy_fastputmask(dest, src, mask_data, ni, nv, chunk);
NPY_END_THREADS;
}
diff --git a/numpy/core/tests/test_item_selection.py b/numpy/core/tests/test_item_selection.py
index cadd0d513..3c35245a3 100644
--- a/numpy/core/tests/test_item_selection.py
+++ b/numpy/core/tests/test_item_selection.py
@@ -20,8 +20,9 @@ class TestTake:
'clip': {-1: 0, 4: 1}}
# Currently all types but object, use the same function generation.
# So it should not be necessary to test all. However test also a non
- # refcounted struct on top of object.
- types = int, object, np.dtype([('', 'i', 2)])
+ # refcounted struct on top of object, which has a size that hits the
+ # default (non-specialized) path.
+ types = int, object, np.dtype([('', 'i2', 3)])
for t in types:
# ta works, even if the array may be odd if buffer interface is used
ta = np.array(a if np.issubdtype(t, np.number) else a_str, dtype=t)