diff options
-rw-r--r-- | doc/release/upcoming_changes/14942.compatibility.rst | 11 | ||||
-rw-r--r-- | numpy/core/src/multiarray/arraytypes.c.src | 55 | ||||
-rw-r--r-- | numpy/core/src/multiarray/item_selection.c | 83 | ||||
-rw-r--r-- | numpy/core/tests/test_item_selection.py | 5 |
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) |