summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--azure-pipelines.yml27
-rw-r--r--doc/source/reference/c-api/types-and-structures.rst6
-rw-r--r--doc_requirements.txt2
-rw-r--r--environment.yml2
-rw-r--r--numpy/core/fromnumeric.py16
-rw-r--r--numpy/core/setup.py6
-rw-r--r--numpy/core/src/_simd/_simd_vector.inc2
-rw-r--r--numpy/core/src/common/npy_hashtable.c220
-rw-r--r--numpy/core/src/common/npy_hashtable.h32
-rw-r--r--numpy/core/src/multiarray/_multiarray_tests.c.src92
-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/multiarray/convert_datatype.c11
-rw-r--r--numpy/core/src/multiarray/datetime_busdaycal.c4
-rw-r--r--numpy/core/src/multiarray/descriptor.c35
-rw-r--r--numpy/core/src/multiarray/descriptor.h6
-rw-r--r--numpy/core/src/multiarray/dtype_transfer.c4
-rw-r--r--numpy/core/src/multiarray/flagsobject.c87
-rw-r--r--numpy/core/src/multiarray/getset.c66
-rw-r--r--numpy/core/src/multiarray/item_selection.c4
-rw-r--r--numpy/core/src/multiarray/iterators.c12
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c20
-rw-r--r--numpy/core/src/multiarray/nditer_pywrap.c71
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src42
-rw-r--r--numpy/core/src/umath/ufunc_object.c68
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.c117
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.h7
-rw-r--r--numpy/core/tests/test_casting_unittests.py17
-rw-r--r--numpy/core/tests/test_hashtable.py30
-rw-r--r--numpy/lib/arraysetops.py4
-rw-r--r--numpy/lib/format.py2
-rw-r--r--numpy/lib/tests/test_arraysetops.py11
-rw-r--r--numpy/lib/utils.py2
-rwxr-xr-xnumpy/linalg/lapack_lite/make_lite.py4
-rw-r--r--test_requirements.txt4
35 files changed, 835 insertions, 334 deletions
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 14a59e880..fa527f565 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -305,4 +305,31 @@ stages:
failTaskOnFailedTests: true
testRunTitle: 'Publish test results for gcc 4.8'
+ - job: Linux_conda
+ pool:
+ vmImage: 'ubuntu-20.04'
+ steps:
+ - script: |
+ # create and activate conda environment
+ conda env create -f environment.yml
+ displayName: 'Create conda environment.'
+ - script: |
+ # >>> conda initialize >>>
+ # !! Contents within this block are 'conda init' !!
+ # see https://github.com/conda/conda/issues/7980
+ __conda_setup="$('conda' 'shell.bash' 'hook' 2> /dev/null)"
+ eval "$__conda_setup"
+ unset __conda_setup
+ # <<< conda initialize <<<
+ conda activate numpy-dev
+ # Run native baseline Build / Tests
+ python runtests.py --show-build-log --cpu-baseline=native --cpu-dispatch=none \
+ --debug-info --mode=full -- -rsx --junitxml=junit/test-results.xml
+ displayName: 'Run native baseline Build / Tests in conda.'
+ - task: PublishTestResults@2
+ condition: succeededOrFailed()
+ inputs:
+ testResultsFiles: '**/test-*.xml'
+ failTaskOnFailedTests: true
+ testRunTitle: 'Publish test results for conda installation'
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/doc_requirements.txt b/doc_requirements.txt
index 0ca72781a..ec6459277 100644
--- a/doc_requirements.txt
+++ b/doc_requirements.txt
@@ -1,4 +1,4 @@
-sphinx==4.0.1
+sphinx==4.0.3
numpydoc==1.1.0
ipython
scipy
diff --git a/environment.yml b/environment.yml
index 607aeb231..40670b5df 100644
--- a/environment.yml
+++ b/environment.yml
@@ -18,7 +18,7 @@ dependencies:
- pytest-xdist
- hypothesis
# For type annotations
- - mypy=0.812
+ - mypy=0.902
- typing_extensions
# For building docs
- sphinx=4.0.1
diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py
index 820d6831f..ee93da901 100644
--- a/numpy/core/fromnumeric.py
+++ b/numpy/core/fromnumeric.py
@@ -1183,11 +1183,11 @@ def argmax(a, axis=None, out=None):
>>> x = np.array([[4,2,3], [1,0,3]])
>>> index_array = np.argmax(x, axis=-1)
- >>> # Same as np.max(x, axis=-1, keepdims=True)
+ >>> # Same as np.amax(x, axis=-1, keepdims=True)
>>> np.take_along_axis(x, np.expand_dims(index_array, axis=-1), axis=-1)
array([[4],
[3]])
- >>> # Same as np.max(x, axis=-1)
+ >>> # Same as np.amax(x, axis=-1)
>>> np.take_along_axis(x, np.expand_dims(index_array, axis=-1), axis=-1).squeeze(axis=-1)
array([4, 3])
@@ -1264,11 +1264,11 @@ def argmin(a, axis=None, out=None):
>>> x = np.array([[4,2,3], [1,0,3]])
>>> index_array = np.argmin(x, axis=-1)
- >>> # Same as np.min(x, axis=-1, keepdims=True)
+ >>> # Same as np.amin(x, axis=-1, keepdims=True)
>>> np.take_along_axis(x, np.expand_dims(index_array, axis=-1), axis=-1)
array([[2],
[0]])
- >>> # Same as np.max(x, axis=-1)
+ >>> # Same as np.amax(x, axis=-1)
>>> np.take_along_axis(x, np.expand_dims(index_array, axis=-1), axis=-1).squeeze(axis=-1)
array([2, 0])
@@ -2740,14 +2740,14 @@ def amax(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue,
You can use an initial value to compute the maximum of an empty slice, or
to initialize it to a different value:
- >>> np.max([[-50], [10]], axis=-1, initial=0)
+ >>> np.amax([[-50], [10]], axis=-1, initial=0)
array([ 0, 10])
Notice that the initial value is used as one of the elements for which the
maximum is determined, unlike for the default argument Python's max
function, which is only used for empty iterables.
- >>> np.max([5], initial=6)
+ >>> np.amax([5], initial=6)
6
>>> max([5], default=6)
5
@@ -2863,7 +2863,7 @@ def amin(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue,
>>> np.nanmin(b)
0.0
- >>> np.min([[-50], [10]], axis=-1, initial=0)
+ >>> np.amin([[-50], [10]], axis=-1, initial=0)
array([-50, 0])
Notice that the initial value is used as one of the elements for which the
@@ -2872,7 +2872,7 @@ def amin(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue,
Notice that this isn't the same as Python's ``default`` argument.
- >>> np.min([6], initial=5)
+ >>> np.amin([6], initial=5)
5
>>> min([6], default=5)
6
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index b03e9f990..2061eb510 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -701,9 +701,11 @@ def configuration(parent_package='',top_path=None):
config.add_extension('_multiarray_tests',
sources=[join('src', 'multiarray', '_multiarray_tests.c.src'),
join('src', 'common', 'mem_overlap.c'),
- join('src', 'common', 'npy_argparse.c')],
+ join('src', 'common', 'npy_argparse.c'),
+ join('src', 'common', 'npy_hashtable.c')],
depends=[join('src', 'common', 'mem_overlap.h'),
join('src', 'common', 'npy_argparse.h'),
+ join('src', 'common', 'npy_hashtable.h'),
join('src', 'common', 'npy_extint128.h')],
libraries=['npymath'])
@@ -723,6 +725,7 @@ def configuration(parent_package='',top_path=None):
join('src', 'common', 'npy_ctypes.h'),
join('src', 'common', 'npy_extint128.h'),
join('src', 'common', 'npy_import.h'),
+ join('src', 'common', 'npy_hashtable.h'),
join('src', 'common', 'npy_longdouble.h'),
join('src', 'common', 'templ_common.h.src'),
join('src', 'common', 'ucsnarrow.h'),
@@ -737,6 +740,7 @@ def configuration(parent_package='',top_path=None):
join('src', 'common', 'array_assign.c'),
join('src', 'common', 'mem_overlap.c'),
join('src', 'common', 'npy_argparse.c'),
+ join('src', 'common', 'npy_hashtable.c'),
join('src', 'common', 'npy_longdouble.c'),
join('src', 'common', 'templ_common.h.src'),
join('src', 'common', 'ucsnarrow.c'),
diff --git a/numpy/core/src/_simd/_simd_vector.inc b/numpy/core/src/_simd/_simd_vector.inc
index d4b6310fd..3d0c15375 100644
--- a/numpy/core/src/_simd/_simd_vector.inc
+++ b/numpy/core/src/_simd/_simd_vector.inc
@@ -33,7 +33,7 @@ static PySequenceMethods simd__vector_as_sequence = {
};
static PyObject *
-simd__vector_name(PySIMDVectorObject *self)
+simd__vector_name(PySIMDVectorObject *self, void *NPY_UNUSED(ignored))
{
return PyUnicode_FromString(simd_data_getinfo(self->dtype)->pyname);
}
diff --git a/numpy/core/src/common/npy_hashtable.c b/numpy/core/src/common/npy_hashtable.c
new file mode 100644
index 000000000..af9e2df43
--- /dev/null
+++ b/numpy/core/src/common/npy_hashtable.c
@@ -0,0 +1,220 @@
+/*
+ * This functionality is designed specifically for the ufunc machinery to
+ * dispatch based on multiple DTypes. Since this is designed to be used
+ * as purely a cache, it currently does no reference counting.
+ * Even though this is a cache, there is currently no maximum size. It may
+ * make sense to limit the size, or count collisions: If too many collisions
+ * occur, we could grow the cache, otherwise, just replace an old item that
+ * was presumably not used for a long time.
+ *
+ * If a different part of NumPy requires a custom hashtable, the code should
+ * be reused with care since specializing it more for the ufunc dispatching
+ * case is likely desired.
+ */
+
+#include "templ_common.h"
+#include "npy_hashtable.h"
+
+
+
+#if SIZEOF_PY_UHASH_T > 4
+#define _NpyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
+#define _NpyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
+#define _NpyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
+#define _NpyHASH_XXROTATE(x) ((x << 31) | (x >> 33)) /* Rotate left 31 bits */
+#else
+#define _NpyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
+#define _NpyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
+#define _NpyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
+#define _NpyHASH_XXROTATE(x) ((x << 13) | (x >> 19)) /* Rotate left 13 bits */
+#endif
+
+/*
+ * This hashing function is basically the Python tuple hash with the type
+ * identity hash inlined. The tuple hash itself is a reduced version of xxHash.
+ *
+ * Users cannot control pointers, so we do not have to worry about DoS attacks?
+ */
+static NPY_INLINE Py_hash_t
+identity_list_hash(PyObject *const *v, int len)
+{
+ Py_uhash_t acc = _NpyHASH_XXPRIME_5;
+ for (int i = 0; i < len; i++) {
+ /*
+ * Lane is the single item hash, which for us is the rotated pointer.
+ * Identical to the python type hash (pointers end with 0s normally).
+ */
+ size_t y = (size_t)v[i];
+ Py_uhash_t lane = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4));
+ acc += lane * _NpyHASH_XXPRIME_2;
+ acc = _NpyHASH_XXROTATE(acc);
+ acc *= _NpyHASH_XXPRIME_1;
+ }
+ return acc;
+}
+#undef _NpyHASH_XXPRIME_1
+#undef _NpyHASH_XXPRIME_2
+#undef _NpyHASH_XXPRIME_5
+#undef _NpyHASH_XXROTATE
+
+
+static NPY_INLINE PyObject **
+find_item(PyArrayIdentityHash const *tb, PyObject *const *key)
+{
+ Py_hash_t hash = identity_list_hash(key, tb->key_len);
+ npy_uintp perturb = (npy_uintp)hash;
+ npy_intp bucket;
+ npy_intp mask = tb->size - 1 ;
+ PyObject **item;
+
+ bucket = (npy_intp)hash & mask;
+ while (1) {
+ item = &(tb->buckets[bucket * (tb->key_len + 1)]);
+
+ if (item[0] == NULL) {
+ /* The item is not in the cache; return the empty bucket */
+ return item;
+ }
+ if (memcmp(item+1, key, tb->key_len * sizeof(PyObject *)) == 0) {
+ /* This is a match, so return the item/bucket */
+ return item;
+ }
+ /* Hash collision, perturb like Python (must happen rarely!) */
+ perturb >>= 5; /* Python uses the macro PERTURB_SHIFT == 5 */
+ bucket = mask & (bucket * 5 + perturb + 1);
+ }
+}
+
+
+NPY_NO_EXPORT PyArrayIdentityHash *
+PyArrayIdentityHash_New(int key_len)
+{
+ PyArrayIdentityHash *res = PyMem_Malloc(sizeof(PyArrayIdentityHash));
+ if (res == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ assert(key_len > 0);
+ res->key_len = key_len;
+ res->size = 4; /* Start with a size of 4 */
+ res->nelem = 0;
+
+ res->buckets = PyMem_Calloc(4 * (key_len + 1), sizeof(PyObject *));
+ if (res->buckets == NULL) {
+ PyErr_NoMemory();
+ PyMem_Free(res);
+ return NULL;
+ }
+ return res;
+}
+
+
+NPY_NO_EXPORT void
+PyArrayIdentityHash_Dealloc(PyArrayIdentityHash *tb)
+{
+ PyMem_Free(tb->buckets);
+ PyMem_Free(tb);
+}
+
+
+static int
+_resize_if_necessary(PyArrayIdentityHash *tb)
+{
+ npy_intp new_size, prev_size = tb->size;
+ PyObject **old_table = tb->buckets;
+ assert(prev_size > 0);
+
+ if ((tb->nelem + 1) * 2 > prev_size) {
+ /* Double in size */
+ new_size = prev_size * 2;
+ }
+ else {
+ new_size = prev_size;
+ while ((tb->nelem + 8) * 2 < new_size / 2) {
+ /*
+ * Should possibly be improved. However, we assume that we
+ * almost never shrink. Still if we do, do not shrink as much
+ * as possible to avoid growing right away.
+ */
+ new_size /= 2;
+ }
+ assert(new_size >= 4);
+ }
+ if (new_size == prev_size) {
+ return 0;
+ }
+
+ npy_intp alloc_size;
+ if (npy_mul_with_overflow_intp(&alloc_size, new_size, tb->key_len + 1)) {
+ return -1;
+ }
+ tb->buckets = PyMem_Calloc(alloc_size, sizeof(PyObject *));
+ if (tb->buckets == NULL) {
+ tb->buckets = old_table;
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ tb->size = new_size;
+ for (npy_intp i = 0; i < prev_size; i++) {
+ PyObject **item = &old_table[i * (tb->key_len + 1)];
+ if (item[0] != NULL) {
+ tb->nelem -= 1; /* Decrement, setitem will increment again */
+ PyArrayIdentityHash_SetItem(tb, item+1, item[0], 1);
+ }
+ }
+ PyMem_Free(old_table);
+ return 0;
+}
+
+
+/**
+ * Add an item to the identity cache. The storage location must not change
+ * unless the cache is cleared.
+ *
+ * @param tb The mapping.
+ * @param key The key, must be a C-array of pointers of the length
+ * corresponding to the mapping.
+ * @param value Normally a Python object, no reference counting is done.
+ * use NULL to clear an item. If the item does not exist, no
+ * action is performed for NULL.
+ * @param replace If 1, allow replacements.
+ * @returns 0 on success, -1 with a MemoryError or RuntimeError (if an item
+ * is added which is already in the cache). The caller should avoid
+ * the RuntimeError.
+ */
+NPY_NO_EXPORT int
+PyArrayIdentityHash_SetItem(PyArrayIdentityHash *tb,
+ PyObject *const *key, PyObject *value, int replace)
+{
+ if (value != NULL && _resize_if_necessary(tb) < 0) {
+ /* Shrink, only if a new value is added. */
+ return -1;
+ }
+
+ PyObject **tb_item = find_item(tb, key);
+ if (value != NULL) {
+ if (tb_item[0] != NULL && !replace) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Identity cache already includes the item.");
+ return -1;
+ }
+ tb_item[0] = value;
+ memcpy(tb_item+1, key, tb->key_len * sizeof(PyObject *));
+ tb->nelem += 1;
+ }
+ else {
+ /* Clear the bucket -- just the value should be enough though. */
+ memset(tb_item, 0, (tb->key_len + 1) * sizeof(PyObject *));
+ }
+
+ return 0;
+}
+
+
+NPY_NO_EXPORT PyObject *
+PyArrayIdentityHash_GetItem(PyArrayIdentityHash const *tb, PyObject *const *key)
+{
+ return find_item(tb, key)[0];
+}
diff --git a/numpy/core/src/common/npy_hashtable.h b/numpy/core/src/common/npy_hashtable.h
new file mode 100644
index 000000000..5f11d2c1d
--- /dev/null
+++ b/numpy/core/src/common/npy_hashtable.h
@@ -0,0 +1,32 @@
+#ifndef _NPY_NPY_HASHTABLE_H
+#define _NPY_NPY_HASHTABLE_H
+
+#include <Python.h>
+
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+#include "numpy/ndarraytypes.h"
+
+
+typedef struct {
+ int key_len; /* number of identities used */
+ /* Buckets stores: val1, key1[0], key1[1], ..., val2, key2[0], ... */
+ PyObject **buckets;
+ npy_intp size; /* current size */
+ npy_intp nelem; /* number of elements */
+} PyArrayIdentityHash;
+
+
+NPY_NO_EXPORT int
+PyArrayIdentityHash_SetItem(PyArrayIdentityHash *tb,
+ PyObject *const *key, PyObject *value, int replace);
+
+NPY_NO_EXPORT PyObject *
+PyArrayIdentityHash_GetItem(PyArrayIdentityHash const *tb, PyObject *const *key);
+
+NPY_NO_EXPORT PyArrayIdentityHash *
+PyArrayIdentityHash_New(int key_len);
+
+NPY_NO_EXPORT void
+PyArrayIdentityHash_Dealloc(PyArrayIdentityHash *tb);
+
+#endif /* _NPY_NPY_HASHTABLE_H */
diff --git a/numpy/core/src/multiarray/_multiarray_tests.c.src b/numpy/core/src/multiarray/_multiarray_tests.c.src
index 79140bdb7..4b9a4f9dd 100644
--- a/numpy/core/src/multiarray/_multiarray_tests.c.src
+++ b/numpy/core/src/multiarray/_multiarray_tests.c.src
@@ -1,4 +1,6 @@
/* -*-c-*- */
+#define PY_SSIZE_T_CLEAN
+
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#include <Python.h>
#define _NPY_NO_DEPRECATIONS /* for NPY_CHAR */
@@ -11,6 +13,7 @@
#include "mem_overlap.h"
#include "npy_extint128.h"
#include "array_method.h"
+#include "npy_hashtable.h"
#if defined(MS_WIN32) || defined(__CYGWIN__)
#define EXPORT(x) __declspec(dllexport) x
@@ -1116,6 +1119,92 @@ get_all_cast_information(PyObject *NPY_UNUSED(mod), PyObject *NPY_UNUSED(args))
/*
+ * Helper to test the identity cache, takes a list of values and adds
+ * all to the cache except the last key/value pair. The last value is
+ * ignored, instead the last key is looked up.
+ * None is returned, if the key is not found.
+ * If `replace` is True, duplicate entries are ignored when adding to the
+ * hashtable.
+ */
+static PyObject *
+identityhash_tester(PyObject *NPY_UNUSED(mod),
+ PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames)
+{
+ NPY_PREPARE_ARGPARSER;
+
+ int key_len;
+ int replace;
+ PyObject *replace_obj = Py_False;
+ PyObject *sequence;
+ PyObject *result = NULL;
+
+ if (npy_parse_arguments("identityhash_tester", args, len_args, kwnames,
+ "key_len", &PyArray_PythonPyIntFromInt, &key_len,
+ "sequence", NULL, &sequence,
+ "|replace", NULL, &replace_obj,
+ NULL, NULL, NULL) < 0) {
+ return NULL;
+ }
+ replace = PyObject_IsTrue(replace_obj);
+ if (error_converting(replace)) {
+ return NULL;
+ }
+
+ if (key_len < 1 || key_len >= NPY_MAXARGS) {
+ PyErr_SetString(PyExc_ValueError, "must have 1 to max-args keys.");
+ return NULL;
+ }
+ PyArrayIdentityHash *tb = PyArrayIdentityHash_New(key_len);
+ if (tb == NULL) {
+ return NULL;
+ }
+
+ /* Replace the sequence with a guaranteed fast-sequence */
+ sequence = PySequence_Fast(sequence, "converting sequence.");
+ if (sequence == NULL) {
+ goto finish;
+ }
+
+ Py_ssize_t length = PySequence_Fast_GET_SIZE(sequence);
+ for (Py_ssize_t i = 0; i < length; i++) {
+ PyObject *key_val = PySequence_Fast_GET_ITEM(sequence, i);
+ if (!PyTuple_CheckExact(key_val) || PyTuple_GET_SIZE(key_val) != 2) {
+ PyErr_SetString(PyExc_TypeError, "bad key-value pair.");
+ goto finish;
+ }
+ PyObject *key = PyTuple_GET_ITEM(key_val, 0);
+ PyObject *value = PyTuple_GET_ITEM(key_val, 1);
+ if (!PyTuple_CheckExact(key) || PyTuple_GET_SIZE(key) != key_len) {
+ PyErr_SetString(PyExc_TypeError, "bad key tuple.");
+ goto finish;
+ }
+
+ PyObject *keys[NPY_MAXARGS];
+ for (int j = 0; j < key_len; j++) {
+ keys[j] = PyTuple_GET_ITEM(key, j);
+ }
+ if (i != length - 1) {
+ if (PyArrayIdentityHash_SetItem(tb, keys, value, replace) < 0) {
+ goto finish;
+ }
+ }
+ else {
+ result = PyArrayIdentityHash_GetItem(tb, keys);
+ if (result == NULL) {
+ result = Py_None;
+ }
+ Py_INCREF(result);
+ }
+ }
+
+ finish:
+ Py_DECREF(sequence);
+ PyArrayIdentityHash_Dealloc(tb);
+ return result;
+}
+
+
+/*
* Test C-api level item getting.
*/
static PyObject *
@@ -2345,6 +2434,9 @@ static PyMethodDef Multiarray_TestsMethods[] = {
"Return a list with info on all available casts. Some of the info"
"may differ for an actual cast if it uses value-based casting "
"(flexible types)."},
+ {"identityhash_tester",
+ (PyCFunction)identityhash_tester,
+ METH_KEYWORDS | METH_FASTCALL, NULL},
{"array_indexing",
array_indexing,
METH_VARARGS, NULL},
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/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c
index cd0e21098..067c356ca 100644
--- a/numpy/core/src/multiarray/convert_datatype.c
+++ b/numpy/core/src/multiarray/convert_datatype.c
@@ -391,7 +391,16 @@ _get_cast_safety_from_castingimpl(PyArrayMethodObject *castingimpl,
finish:
Py_DECREF(out_descrs[0]);
Py_DECREF(out_descrs[1]);
- /* NPY_NO_CASTING has to be used for (NPY_EQUIV_CASTING|_NPY_CAST_IS_VIEW) */
+ /*
+ * Check for less harmful non-standard returns. The following two returns
+ * should never happen. They would be roughly equivalent, but less precise,
+ * versions of `(NPY_NO_CASTING|_NPY_CAST_IS_VIEW)`.
+ * 1. No-casting must imply cast-is-view.
+ * 2. Equivalent-casting + cast-is-view is (currently) the definition
+ * of a "no" cast (there may be reasons to relax this).
+ * Note that e.g. `(NPY_UNSAFE_CASTING|_NPY_CAST_IS_VIEW)` is valid.
+ */
+ assert(casting != NPY_NO_CASTING);
assert(casting != (NPY_EQUIV_CASTING|_NPY_CAST_IS_VIEW));
return casting;
}
diff --git a/numpy/core/src/multiarray/datetime_busdaycal.c b/numpy/core/src/multiarray/datetime_busdaycal.c
index d48141d4c..e3e729d3c 100644
--- a/numpy/core/src/multiarray/datetime_busdaycal.c
+++ b/numpy/core/src/multiarray/datetime_busdaycal.c
@@ -434,7 +434,7 @@ busdaycalendar_dealloc(NpyBusDayCalendar *self)
}
static PyObject *
-busdaycalendar_weekmask_get(NpyBusDayCalendar *self)
+busdaycalendar_weekmask_get(NpyBusDayCalendar *self, void *NPY_UNUSED(ignored))
{
PyArrayObject *ret;
npy_intp size = 7;
@@ -452,7 +452,7 @@ busdaycalendar_weekmask_get(NpyBusDayCalendar *self)
}
static PyObject *
-busdaycalendar_holidays_get(NpyBusDayCalendar *self)
+busdaycalendar_holidays_get(NpyBusDayCalendar *self, void *NPY_UNUSED(ignored))
{
PyArrayObject *ret;
PyArray_Descr *date_dtype;
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index b8b477e5d..58aa608c3 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -1895,7 +1895,7 @@ static PyMemberDef arraydescr_members[] = {
};
static PyObject *
-arraydescr_subdescr_get(PyArray_Descr *self)
+arraydescr_subdescr_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
if (!PyDataType_HASSUBARRAY(self)) {
Py_RETURN_NONE;
@@ -1905,7 +1905,7 @@ arraydescr_subdescr_get(PyArray_Descr *self)
}
NPY_NO_EXPORT PyObject *
-arraydescr_protocol_typestr_get(PyArray_Descr *self)
+arraydescr_protocol_typestr_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
char basic_ = self->kind;
char endian = self->byteorder;
@@ -1951,7 +1951,7 @@ arraydescr_protocol_typestr_get(PyArray_Descr *self)
}
static PyObject *
-arraydescr_name_get(PyArray_Descr *self)
+arraydescr_name_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
/* let python handle this */
PyObject *_numpy_dtype;
@@ -1966,7 +1966,7 @@ arraydescr_name_get(PyArray_Descr *self)
}
static PyObject *
-arraydescr_base_get(PyArray_Descr *self)
+arraydescr_base_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
if (!PyDataType_HASSUBARRAY(self)) {
Py_INCREF(self);
@@ -1977,7 +1977,7 @@ arraydescr_base_get(PyArray_Descr *self)
}
static PyObject *
-arraydescr_shape_get(PyArray_Descr *self)
+arraydescr_shape_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
if (!PyDataType_HASSUBARRAY(self)) {
return PyTuple_New(0);
@@ -1988,7 +1988,7 @@ arraydescr_shape_get(PyArray_Descr *self)
}
static PyObject *
-arraydescr_ndim_get(PyArray_Descr *self)
+arraydescr_ndim_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
Py_ssize_t ndim;
@@ -2006,7 +2006,7 @@ arraydescr_ndim_get(PyArray_Descr *self)
NPY_NO_EXPORT PyObject *
-arraydescr_protocol_descr_get(PyArray_Descr *self)
+arraydescr_protocol_descr_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
PyObject *dobj, *res;
PyObject *_numpy_internal;
@@ -2018,7 +2018,7 @@ arraydescr_protocol_descr_get(PyArray_Descr *self)
return NULL;
}
PyTuple_SET_ITEM(dobj, 0, PyUnicode_FromString(""));
- PyTuple_SET_ITEM(dobj, 1, arraydescr_protocol_typestr_get(self));
+ PyTuple_SET_ITEM(dobj, 1, arraydescr_protocol_typestr_get(self, NULL));
res = PyList_New(1);
if (res == NULL) {
Py_DECREF(dobj);
@@ -2043,7 +2043,7 @@ arraydescr_protocol_descr_get(PyArray_Descr *self)
* return 0 if neither (i.e. it's a copy of one)
*/
static PyObject *
-arraydescr_isbuiltin_get(PyArray_Descr *self)
+arraydescr_isbuiltin_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
long val;
val = 0;
@@ -2090,7 +2090,7 @@ _arraydescr_isnative(PyArray_Descr *self)
* fields are defined
*/
static PyObject *
-arraydescr_isnative_get(PyArray_Descr *self)
+arraydescr_isnative_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
PyObject *ret;
int retval;
@@ -2104,7 +2104,7 @@ arraydescr_isnative_get(PyArray_Descr *self)
}
static PyObject *
-arraydescr_isalignedstruct_get(PyArray_Descr *self)
+arraydescr_isalignedstruct_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
PyObject *ret;
ret = (self->flags&NPY_ALIGNED_STRUCT) ? Py_True : Py_False;
@@ -2113,7 +2113,7 @@ arraydescr_isalignedstruct_get(PyArray_Descr *self)
}
static PyObject *
-arraydescr_fields_get(PyArray_Descr *self)
+arraydescr_fields_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
if (!PyDataType_HASFIELDS(self)) {
Py_RETURN_NONE;
@@ -2122,7 +2122,7 @@ arraydescr_fields_get(PyArray_Descr *self)
}
static PyObject *
-arraydescr_metadata_get(PyArray_Descr *self)
+arraydescr_metadata_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
if (self->metadata == NULL) {
Py_RETURN_NONE;
@@ -2131,7 +2131,7 @@ arraydescr_metadata_get(PyArray_Descr *self)
}
static PyObject *
-arraydescr_hasobject_get(PyArray_Descr *self)
+arraydescr_hasobject_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
if (PyDataType_FLAGCHK(self, NPY_ITEM_HASOBJECT)) {
Py_RETURN_TRUE;
@@ -2142,7 +2142,7 @@ arraydescr_hasobject_get(PyArray_Descr *self)
}
static PyObject *
-arraydescr_names_get(PyArray_Descr *self)
+arraydescr_names_get(PyArray_Descr *self, void *NPY_UNUSED(ignored))
{
if (!PyDataType_HASFIELDS(self)) {
Py_RETURN_NONE;
@@ -2152,7 +2152,8 @@ arraydescr_names_get(PyArray_Descr *self)
}
static int
-arraydescr_names_set(PyArray_Descr *self, PyObject *val)
+arraydescr_names_set(
+ PyArray_Descr *self, PyObject *val, void *NPY_UNUSED(ignored))
{
int N = 0;
int i;
@@ -2536,7 +2537,7 @@ arraydescr_reduce(PyArray_Descr *self, PyObject *NPY_UNUSED(args))
}
PyTuple_SET_ITEM(state, 1, PyUnicode_FromFormat("%c", endian));
- PyTuple_SET_ITEM(state, 2, arraydescr_subdescr_get(self));
+ PyTuple_SET_ITEM(state, 2, arraydescr_subdescr_get(self, NULL));
if (PyDataType_HASFIELDS(self)) {
Py_INCREF(self->names);
Py_INCREF(self->fields);
diff --git a/numpy/core/src/multiarray/descriptor.h b/numpy/core/src/multiarray/descriptor.h
index fc9e0895b..e1316acbd 100644
--- a/numpy/core/src/multiarray/descriptor.h
+++ b/numpy/core/src/multiarray/descriptor.h
@@ -1,8 +1,10 @@
#ifndef _NPY_ARRAYDESCR_H_
#define _NPY_ARRAYDESCR_H_
-NPY_NO_EXPORT PyObject *arraydescr_protocol_typestr_get(PyArray_Descr *);
-NPY_NO_EXPORT PyObject *arraydescr_protocol_descr_get(PyArray_Descr *self);
+NPY_NO_EXPORT PyObject *arraydescr_protocol_typestr_get(
+ PyArray_Descr *, void *);
+NPY_NO_EXPORT PyObject *arraydescr_protocol_descr_get(
+ PyArray_Descr *self, void *);
NPY_NO_EXPORT PyObject *
array_set_typeDict(PyObject *NPY_UNUSED(ignored), PyObject *args);
diff --git a/numpy/core/src/multiarray/dtype_transfer.c b/numpy/core/src/multiarray/dtype_transfer.c
index aa8cc84ff..50db627ea 100644
--- a/numpy/core/src/multiarray/dtype_transfer.c
+++ b/numpy/core/src/multiarray/dtype_transfer.c
@@ -322,11 +322,11 @@ strided_to_strided_object_to_any(
while (N > 0) {
memcpy(&src_ref, src, sizeof(src_ref));
- if (PyArray_Pack(data->descr, dst, src_ref) < 0) {
+ if (PyArray_Pack(data->descr, dst, src_ref ? src_ref : Py_None) < 0) {
return -1;
}
- if (data->move_references) {
+ if (data->move_references && src_ref != NULL) {
Py_DECREF(src_ref);
memset(src, 0, sizeof(src_ref));
}
diff --git a/numpy/core/src/multiarray/flagsobject.c b/numpy/core/src/multiarray/flagsobject.c
index 9b7d8deae..c45d2ae96 100644
--- a/numpy/core/src/multiarray/flagsobject.c
+++ b/numpy/core/src/multiarray/flagsobject.c
@@ -200,7 +200,8 @@ arrayflags_dealloc(PyArrayFlagsObject *self)
#define _define_get(UPPER, lower) \
static PyObject * \
- arrayflags_ ## lower ## _get(PyArrayFlagsObject *self) \
+ arrayflags_ ## lower ## _get( \
+ PyArrayFlagsObject *self, void *NPY_UNUSED(ignored)) \
{ \
return PyBool_FromLong((self->flags & (UPPER)) == (UPPER)); \
}
@@ -211,7 +212,8 @@ static char *msg = "future versions will not create a writeable "
#define _define_get_warn(UPPER, lower) \
static PyObject * \
- arrayflags_ ## lower ## _get(PyArrayFlagsObject *self) \
+ arrayflags_ ## lower ## _get( \
+ PyArrayFlagsObject *self, void *NPY_UNUSED(ignored)) \
{ \
if (self->flags & NPY_ARRAY_WARN_ON_WRITE) { \
if (PyErr_Warn(PyExc_FutureWarning, msg) < 0) {\
@@ -236,7 +238,7 @@ _define_get_warn(NPY_ARRAY_ALIGNED|
NPY_ARRAY_C_CONTIGUOUS, carray)
static PyObject *
-arrayflags_updateifcopy_get(PyArrayFlagsObject *self)
+arrayflags_updateifcopy_get(PyArrayFlagsObject *self, void *NPY_UNUSED(ignored))
{
PyObject *item;
/* 2017-Nov-10 1.14 */
@@ -255,7 +257,7 @@ arrayflags_updateifcopy_get(PyArrayFlagsObject *self)
static PyObject *
-arrayflags_forc_get(PyArrayFlagsObject *self)
+arrayflags_forc_get(PyArrayFlagsObject *self, void *NPY_UNUSED(ignored))
{
PyObject *item;
@@ -271,7 +273,7 @@ arrayflags_forc_get(PyArrayFlagsObject *self)
}
static PyObject *
-arrayflags_fnc_get(PyArrayFlagsObject *self)
+arrayflags_fnc_get(PyArrayFlagsObject *self, void *NPY_UNUSED(ignored))
{
PyObject *item;
@@ -287,7 +289,7 @@ arrayflags_fnc_get(PyArrayFlagsObject *self)
}
static PyObject *
-arrayflags_farray_get(PyArrayFlagsObject *self)
+arrayflags_farray_get(PyArrayFlagsObject *self, void *NPY_UNUSED(ignored))
{
PyObject *item;
@@ -305,14 +307,15 @@ arrayflags_farray_get(PyArrayFlagsObject *self)
}
static PyObject *
-arrayflags_num_get(PyArrayFlagsObject *self)
+arrayflags_num_get(PyArrayFlagsObject *self, void *NPY_UNUSED(ignored))
{
return PyLong_FromLong(self->flags);
}
/* relies on setflags order being write, align, uic */
static int
-arrayflags_updateifcopy_set(PyArrayFlagsObject *self, PyObject *obj)
+arrayflags_updateifcopy_set(
+ PyArrayFlagsObject *self, PyObject *obj, void *NPY_UNUSED(ignored))
{
PyObject *res;
@@ -341,7 +344,8 @@ arrayflags_updateifcopy_set(PyArrayFlagsObject *self, PyObject *obj)
/* relies on setflags order being write, align, uic */
static int
-arrayflags_writebackifcopy_set(PyArrayFlagsObject *self, PyObject *obj)
+arrayflags_writebackifcopy_set(
+ PyArrayFlagsObject *self, PyObject *obj, void *NPY_UNUSED(ignored))
{
PyObject *res;
@@ -365,7 +369,8 @@ arrayflags_writebackifcopy_set(PyArrayFlagsObject *self, PyObject *obj)
}
static int
-arrayflags_aligned_set(PyArrayFlagsObject *self, PyObject *obj)
+arrayflags_aligned_set(
+ PyArrayFlagsObject *self, PyObject *obj, void *NPY_UNUSED(ignored))
{
PyObject *res;
@@ -390,7 +395,8 @@ arrayflags_aligned_set(PyArrayFlagsObject *self, PyObject *obj)
}
static int
-arrayflags_writeable_set(PyArrayFlagsObject *self, PyObject *obj)
+arrayflags_writeable_set(
+ PyArrayFlagsObject *self, PyObject *obj, void *NPY_UNUSED(ignored))
{
PyObject *res;
@@ -415,7 +421,8 @@ arrayflags_writeable_set(PyArrayFlagsObject *self, PyObject *obj)
}
static int
-arrayflags_warn_on_write_set(PyArrayFlagsObject *self, PyObject *obj)
+arrayflags_warn_on_write_set(
+ PyArrayFlagsObject *self, PyObject *obj, void *NPY_UNUSED(ignored))
{
/*
* This code should go away in a future release, so do not mangle the
@@ -554,89 +561,89 @@ arrayflags_getitem(PyArrayFlagsObject *self, PyObject *ind)
case 1:
switch(key[0]) {
case 'C':
- return arrayflags_contiguous_get(self);
+ return arrayflags_contiguous_get(self, NULL);
case 'F':
- return arrayflags_fortran_get(self);
+ return arrayflags_fortran_get(self, NULL);
case 'W':
- return arrayflags_writeable_get(self);
+ return arrayflags_writeable_get(self, NULL);
case 'B':
- return arrayflags_behaved_get(self);
+ return arrayflags_behaved_get(self, NULL);
case 'O':
- return arrayflags_owndata_get(self);
+ return arrayflags_owndata_get(self, NULL);
case 'A':
- return arrayflags_aligned_get(self);
+ return arrayflags_aligned_get(self, NULL);
case 'X':
- return arrayflags_writebackifcopy_get(self);
+ return arrayflags_writebackifcopy_get(self, NULL);
case 'U':
- return arrayflags_updateifcopy_get(self);
+ return arrayflags_updateifcopy_get(self, NULL);
default:
goto fail;
}
break;
case 2:
if (strncmp(key, "CA", n) == 0) {
- return arrayflags_carray_get(self);
+ return arrayflags_carray_get(self, NULL);
}
if (strncmp(key, "FA", n) == 0) {
- return arrayflags_farray_get(self);
+ return arrayflags_farray_get(self, NULL);
}
break;
case 3:
if (strncmp(key, "FNC", n) == 0) {
- return arrayflags_fnc_get(self);
+ return arrayflags_fnc_get(self, NULL);
}
break;
case 4:
if (strncmp(key, "FORC", n) == 0) {
- return arrayflags_forc_get(self);
+ return arrayflags_forc_get(self, NULL);
}
break;
case 6:
if (strncmp(key, "CARRAY", n) == 0) {
- return arrayflags_carray_get(self);
+ return arrayflags_carray_get(self, NULL);
}
if (strncmp(key, "FARRAY", n) == 0) {
- return arrayflags_farray_get(self);
+ return arrayflags_farray_get(self, NULL);
}
break;
case 7:
if (strncmp(key,"FORTRAN",n) == 0) {
- return arrayflags_fortran_get(self);
+ return arrayflags_fortran_get(self, NULL);
}
if (strncmp(key,"BEHAVED",n) == 0) {
- return arrayflags_behaved_get(self);
+ return arrayflags_behaved_get(self, NULL);
}
if (strncmp(key,"OWNDATA",n) == 0) {
- return arrayflags_owndata_get(self);
+ return arrayflags_owndata_get(self, NULL);
}
if (strncmp(key,"ALIGNED",n) == 0) {
- return arrayflags_aligned_get(self);
+ return arrayflags_aligned_get(self, NULL);
}
break;
case 9:
if (strncmp(key,"WRITEABLE",n) == 0) {
- return arrayflags_writeable_get(self);
+ return arrayflags_writeable_get(self, NULL);
}
break;
case 10:
if (strncmp(key,"CONTIGUOUS",n) == 0) {
- return arrayflags_contiguous_get(self);
+ return arrayflags_contiguous_get(self, NULL);
}
break;
case 12:
if (strncmp(key, "UPDATEIFCOPY", n) == 0) {
- return arrayflags_updateifcopy_get(self);
+ return arrayflags_updateifcopy_get(self, NULL);
}
if (strncmp(key, "C_CONTIGUOUS", n) == 0) {
- return arrayflags_contiguous_get(self);
+ return arrayflags_contiguous_get(self, NULL);
}
if (strncmp(key, "F_CONTIGUOUS", n) == 0) {
- return arrayflags_fortran_get(self);
+ return arrayflags_fortran_get(self, NULL);
}
break;
case 15:
if (strncmp(key, "WRITEBACKIFCOPY", n) == 0) {
- return arrayflags_writebackifcopy_get(self);
+ return arrayflags_writebackifcopy_get(self, NULL);
}
break;
}
@@ -671,19 +678,19 @@ arrayflags_setitem(PyArrayFlagsObject *self, PyObject *ind, PyObject *item)
}
if (((n==9) && (strncmp(key, "WRITEABLE", n) == 0)) ||
((n==1) && (strncmp(key, "W", n) == 0))) {
- return arrayflags_writeable_set(self, item);
+ return arrayflags_writeable_set(self, item, NULL);
}
else if (((n==7) && (strncmp(key, "ALIGNED", n) == 0)) ||
((n==1) && (strncmp(key, "A", n) == 0))) {
- return arrayflags_aligned_set(self, item);
+ return arrayflags_aligned_set(self, item, NULL);
}
else if (((n==12) && (strncmp(key, "UPDATEIFCOPY", n) == 0)) ||
((n==1) && (strncmp(key, "U", n) == 0))) {
- return arrayflags_updateifcopy_set(self, item);
+ return arrayflags_updateifcopy_set(self, item, NULL);
}
else if (((n==15) && (strncmp(key, "WRITEBACKIFCOPY", n) == 0)) ||
((n==1) && (strncmp(key, "X", n) == 0))) {
- return arrayflags_writebackifcopy_set(self, item);
+ return arrayflags_writebackifcopy_set(self, item, NULL);
}
fail:
diff --git a/numpy/core/src/multiarray/getset.c b/numpy/core/src/multiarray/getset.c
index bccbb7b0c..de2a8c14e 100644
--- a/numpy/core/src/multiarray/getset.c
+++ b/numpy/core/src/multiarray/getset.c
@@ -26,26 +26,26 @@
/******************* array attribute get and set routines ******************/
static PyObject *
-array_ndim_get(PyArrayObject *self)
+array_ndim_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
return PyLong_FromLong(PyArray_NDIM(self));
}
static PyObject *
-array_flags_get(PyArrayObject *self)
+array_flags_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
return PyArray_NewFlagsObject((PyObject *)self);
}
static PyObject *
-array_shape_get(PyArrayObject *self)
+array_shape_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
return PyArray_IntTupleFromIntp(PyArray_NDIM(self), PyArray_DIMS(self));
}
static int
-array_shape_set(PyArrayObject *self, PyObject *val)
+array_shape_set(PyArrayObject *self, PyObject *val, void* NPY_UNUSED(ignored))
{
int nd;
PyArrayObject *ret;
@@ -103,13 +103,13 @@ array_shape_set(PyArrayObject *self, PyObject *val)
static PyObject *
-array_strides_get(PyArrayObject *self)
+array_strides_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
return PyArray_IntTupleFromIntp(PyArray_NDIM(self), PyArray_STRIDES(self));
}
static int
-array_strides_set(PyArrayObject *self, PyObject *obj)
+array_strides_set(PyArrayObject *self, PyObject *obj, void *NPY_UNUSED(ignored))
{
PyArray_Dims newstrides = {NULL, -1};
PyArrayObject *new;
@@ -182,7 +182,7 @@ array_strides_set(PyArrayObject *self, PyObject *obj)
static PyObject *
-array_priority_get(PyArrayObject *NPY_UNUSED(self))
+array_priority_get(PyArrayObject *NPY_UNUSED(self), void *NPY_UNUSED(ignored))
{
return PyFloat_FromDouble(NPY_PRIORITY);
}
@@ -190,11 +190,11 @@ array_priority_get(PyArrayObject *NPY_UNUSED(self))
static PyObject *
array_typestr_get(PyArrayObject *self)
{
- return arraydescr_protocol_typestr_get(PyArray_DESCR(self));
+ return arraydescr_protocol_typestr_get(PyArray_DESCR(self), NULL);
}
static PyObject *
-array_descr_get(PyArrayObject *self)
+array_descr_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
Py_INCREF(PyArray_DESCR(self));
return (PyObject *)PyArray_DESCR(self);
@@ -206,7 +206,7 @@ array_protocol_descr_get(PyArrayObject *self)
PyObject *res;
PyObject *dobj;
- res = arraydescr_protocol_descr_get(PyArray_DESCR(self));
+ res = arraydescr_protocol_descr_get(PyArray_DESCR(self), NULL);
if (res) {
return res;
}
@@ -240,7 +240,7 @@ array_protocol_strides_get(PyArrayObject *self)
static PyObject *
-array_dataptr_get(PyArrayObject *self)
+array_dataptr_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
return Py_BuildValue("NO",
PyLong_FromVoidPtr(PyArray_DATA(self)),
@@ -250,7 +250,7 @@ array_dataptr_get(PyArrayObject *self)
}
static PyObject *
-array_ctypes_get(PyArrayObject *self)
+array_ctypes_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
PyObject *_numpy_internal;
PyObject *ret;
@@ -265,7 +265,7 @@ array_ctypes_get(PyArrayObject *self)
}
static PyObject *
-array_interface_get(PyArrayObject *self)
+array_interface_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
PyObject *dict;
PyObject *obj;
@@ -278,7 +278,7 @@ array_interface_get(PyArrayObject *self)
int ret;
/* dataptr */
- obj = array_dataptr_get(self);
+ obj = array_dataptr_get(self, NULL);
ret = PyDict_SetItemString(dict, "data", obj);
Py_DECREF(obj);
if (ret < 0) {
@@ -302,7 +302,7 @@ array_interface_get(PyArrayObject *self)
return NULL;
}
- obj = arraydescr_protocol_typestr_get(PyArray_DESCR(self));
+ obj = arraydescr_protocol_typestr_get(PyArray_DESCR(self), NULL);
ret = PyDict_SetItemString(dict, "typestr", obj);
Py_DECREF(obj);
if (ret < 0) {
@@ -310,7 +310,7 @@ array_interface_get(PyArrayObject *self)
return NULL;
}
- obj = array_shape_get(self);
+ obj = array_shape_get(self, NULL);
ret = PyDict_SetItemString(dict, "shape", obj);
Py_DECREF(obj);
if (ret < 0) {
@@ -330,13 +330,13 @@ array_interface_get(PyArrayObject *self)
}
static PyObject *
-array_data_get(PyArrayObject *self)
+array_data_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
return PyMemoryView_FromObject((PyObject *)self);
}
static int
-array_data_set(PyArrayObject *self, PyObject *op)
+array_data_set(PyArrayObject *self, PyObject *op, void *NPY_UNUSED(ignored))
{
void *buf;
Py_ssize_t buf_len;
@@ -411,19 +411,19 @@ array_data_set(PyArrayObject *self, PyObject *op)
static PyObject *
-array_itemsize_get(PyArrayObject *self)
+array_itemsize_get(PyArrayObject *self, void* NPY_UNUSED(ignored))
{
return PyLong_FromLong((long) PyArray_DESCR(self)->elsize);
}
static PyObject *
-array_size_get(PyArrayObject *self)
+array_size_get(PyArrayObject *self, void* NPY_UNUSED(ignored))
{
return PyArray_PyIntFromIntp(PyArray_SIZE(self));
}
static PyObject *
-array_nbytes_get(PyArrayObject *self)
+array_nbytes_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
return PyArray_PyIntFromIntp(PyArray_NBYTES(self));
}
@@ -438,7 +438,7 @@ array_nbytes_get(PyArrayObject *self)
* will be adjusted in that case as well.
*/
static int
-array_descr_set(PyArrayObject *self, PyObject *arg)
+array_descr_set(PyArrayObject *self, PyObject *arg, void *NPY_UNUSED(ignored))
{
PyArray_Descr *newtype = NULL;
@@ -598,7 +598,7 @@ array_descr_set(PyArrayObject *self, PyObject *arg)
}
static PyObject *
-array_struct_get(PyArrayObject *self)
+array_struct_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
PyArrayInterface *inter;
@@ -641,7 +641,7 @@ array_struct_get(PyArrayObject *self)
}
inter->data = PyArray_DATA(self);
if (PyDataType_HASFIELDS(PyArray_DESCR(self))) {
- inter->descr = arraydescr_protocol_descr_get(PyArray_DESCR(self));
+ inter->descr = arraydescr_protocol_descr_get(PyArray_DESCR(self), NULL);
if (inter->descr == NULL) {
PyErr_Clear();
}
@@ -664,7 +664,7 @@ array_struct_get(PyArrayObject *self)
}
static PyObject *
-array_base_get(PyArrayObject *self)
+array_base_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
if (PyArray_BASE(self) == NULL) {
Py_RETURN_NONE;
@@ -734,7 +734,7 @@ _get_part(PyArrayObject *self, int imag)
*/
static PyObject *
-array_real_get(PyArrayObject *self)
+array_real_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
PyArrayObject *ret;
@@ -750,7 +750,7 @@ array_real_get(PyArrayObject *self)
static int
-array_real_set(PyArrayObject *self, PyObject *val)
+array_real_set(PyArrayObject *self, PyObject *val, void *NPY_UNUSED(ignored))
{
PyArrayObject *ret;
PyArrayObject *new;
@@ -788,7 +788,7 @@ array_real_set(PyArrayObject *self, PyObject *val)
*/
static PyObject *
-array_imag_get(PyArrayObject *self)
+array_imag_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
PyArrayObject *ret;
@@ -816,7 +816,7 @@ array_imag_get(PyArrayObject *self)
}
static int
-array_imag_set(PyArrayObject *self, PyObject *val)
+array_imag_set(PyArrayObject *self, PyObject *val, void *NPY_UNUSED(ignored))
{
if (val == NULL) {
PyErr_SetString(PyExc_AttributeError,
@@ -850,13 +850,13 @@ array_imag_set(PyArrayObject *self, PyObject *val)
}
static PyObject *
-array_flat_get(PyArrayObject *self)
+array_flat_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
return PyArray_IterNew((PyObject *)self);
}
static int
-array_flat_set(PyArrayObject *self, PyObject *val)
+array_flat_set(PyArrayObject *self, PyObject *val, void *NPY_UNUSED(ignored))
{
PyArrayObject *arr = NULL;
int retval = -1;
@@ -928,7 +928,7 @@ array_flat_set(PyArrayObject *self, PyObject *val)
}
static PyObject *
-array_transpose_get(PyArrayObject *self)
+array_transpose_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
{
return PyArray_Transpose(self, NULL);
}
@@ -937,7 +937,7 @@ array_transpose_get(PyArrayObject *self)
--- default sub-class behavior
*/
static PyObject *
-array_finalize_get(PyArrayObject *NPY_UNUSED(self))
+array_finalize_get(PyArrayObject *NPY_UNUSED(self), void *NPY_UNUSED(ignored))
{
Py_RETURN_NONE;
}
diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c
index fb354ce54..2b8ea9e79 100644
--- a/numpy/core/src/multiarray/item_selection.c
+++ b/numpy/core/src/multiarray/item_selection.c
@@ -2131,7 +2131,7 @@ count_nonzero_bytes_384(const npy_uint64 * w)
#if NPY_SIMD
/* Count the zero bytes between `*d` and `end`, updating `*d` to point to where to keep counting from. */
-static NPY_INLINE NPY_GCC_OPT_3 npyv_u8
+NPY_FINLINE NPY_GCC_OPT_3 npyv_u8
count_zero_bytes_u8(const npy_uint8 **d, const npy_uint8 *end, npy_uint8 max_count)
{
const npyv_u8 vone = npyv_setall_u8(1);
@@ -2150,7 +2150,7 @@ count_zero_bytes_u8(const npy_uint8 **d, const npy_uint8 *end, npy_uint8 max_cou
return vsum8;
}
-static NPY_INLINE NPY_GCC_OPT_3 npyv_u16x2
+NPY_FINLINE NPY_GCC_OPT_3 npyv_u16x2
count_zero_bytes_u16(const npy_uint8 **d, const npy_uint8 *end, npy_uint16 max_count)
{
npyv_u16x2 vsum16;
diff --git a/numpy/core/src/multiarray/iterators.c b/numpy/core/src/multiarray/iterators.c
index 576ea89b3..f724837ce 100644
--- a/numpy/core/src/multiarray/iterators.c
+++ b/numpy/core/src/multiarray/iterators.c
@@ -1067,13 +1067,13 @@ static PyMemberDef iter_members[] = {
};
static PyObject *
-iter_index_get(PyArrayIterObject *self)
+iter_index_get(PyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
return PyArray_PyIntFromIntp(self->index);
}
static PyObject *
-iter_coords_get(PyArrayIterObject *self)
+iter_coords_get(PyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
int nd;
nd = PyArray_NDIM(self->ao);
@@ -1413,25 +1413,25 @@ arraymultiter_dealloc(PyArrayMultiIterObject *multi)
}
static PyObject *
-arraymultiter_size_get(PyArrayMultiIterObject *self)
+arraymultiter_size_get(PyArrayMultiIterObject *self, void *NPY_UNUSED(ignored))
{
return PyArray_PyIntFromIntp(self->size);
}
static PyObject *
-arraymultiter_index_get(PyArrayMultiIterObject *self)
+arraymultiter_index_get(PyArrayMultiIterObject *self, void *NPY_UNUSED(ignored))
{
return PyArray_PyIntFromIntp(self->index);
}
static PyObject *
-arraymultiter_shape_get(PyArrayMultiIterObject *self)
+arraymultiter_shape_get(PyArrayMultiIterObject *self, void *NPY_UNUSED(ignored))
{
return PyArray_IntTupleFromIntp(self->nd, self->dimensions);
}
static PyObject *
-arraymultiter_iters_get(PyArrayMultiIterObject *self)
+arraymultiter_iters_get(PyArrayMultiIterObject *self, void *NPY_UNUSED(ignored))
{
PyObject *res;
int i, n;
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index b8ab52340..5fde890de 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -4702,15 +4702,6 @@ PyMODINIT_FUNC PyInit__multiarray_umath(void) {
goto err;
}
- /* Load the ufunc operators into the array module's namespace */
- if (InitOperators(d) < 0) {
- goto err;
- }
-
- if (set_matmul_flags(d) < 0) {
- goto err;
- }
-
PyArrayDTypeMeta_Type.tp_base = &PyType_Type;
if (PyType_Ready(&PyArrayDTypeMeta_Type) < 0) {
goto err;
@@ -4724,6 +4715,7 @@ PyMODINIT_FUNC PyInit__multiarray_umath(void) {
initialize_casting_tables();
initialize_numeric_types();
+
if (initscalarmath(m) < 0) {
goto err;
}
@@ -4734,6 +4726,7 @@ PyMODINIT_FUNC PyInit__multiarray_umath(void) {
if (setup_scalartypes(d) < 0) {
goto err;
}
+
PyArrayIter_Type.tp_iter = PyObject_SelfIter;
NpyIter_Type.tp_iter = PyObject_SelfIter;
PyArrayMultiIter_Type.tp_iter = PyObject_SelfIter;
@@ -4898,6 +4891,15 @@ PyMODINIT_FUNC PyInit__multiarray_umath(void) {
goto err;
}
+ /* Load the ufunc operators into the array module's namespace */
+ if (InitOperators(d) < 0) {
+ goto err;
+ }
+
+ if (set_matmul_flags(d) < 0) {
+ goto err;
+ }
+
if (initumath(m) != 0) {
goto err;
}
diff --git a/numpy/core/src/multiarray/nditer_pywrap.c b/numpy/core/src/multiarray/nditer_pywrap.c
index 7698ae43d..db6c4eb07 100644
--- a/numpy/core/src/multiarray/nditer_pywrap.c
+++ b/numpy/core/src/multiarray/nditer_pywrap.c
@@ -1384,7 +1384,8 @@ npyiter_debug_print(NewNpyArrayIterObject *self)
NPY_NO_EXPORT PyObject *
npyiter_seq_item(NewNpyArrayIterObject *self, Py_ssize_t i);
-static PyObject *npyiter_value_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_value_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
PyObject *ret;
@@ -1420,7 +1421,8 @@ static PyObject *npyiter_value_get(NewNpyArrayIterObject *self)
return ret;
}
-static PyObject *npyiter_operands_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_operands_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
PyObject *ret;
@@ -1449,7 +1451,8 @@ static PyObject *npyiter_operands_get(NewNpyArrayIterObject *self)
return ret;
}
-static PyObject *npyiter_itviews_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_itviews_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
PyObject *ret;
@@ -1508,10 +1511,11 @@ npyiter_next(NewNpyArrayIterObject *self)
}
self->started = 1;
- return npyiter_value_get(self);
+ return npyiter_value_get(self, NULL);
};
-static PyObject *npyiter_shape_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_shape_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
npy_intp ndim, shape[NPY_MAXDIMS];
@@ -1529,7 +1533,8 @@ static PyObject *npyiter_shape_get(NewNpyArrayIterObject *self)
return NULL;
}
-static PyObject *npyiter_multi_index_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_multi_index_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
npy_intp ndim, multi_index[NPY_MAXDIMS];
@@ -1565,7 +1570,8 @@ static PyObject *npyiter_multi_index_get(NewNpyArrayIterObject *self)
}
static int
-npyiter_multi_index_set(NewNpyArrayIterObject *self, PyObject *value)
+npyiter_multi_index_set(
+ NewNpyArrayIterObject *self, PyObject *value, void *NPY_UNUSED(ignored))
{
npy_intp idim, ndim, multi_index[NPY_MAXDIMS];
@@ -1620,7 +1626,8 @@ npyiter_multi_index_set(NewNpyArrayIterObject *self, PyObject *value)
}
}
-static PyObject *npyiter_index_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_index_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
if (self->iter == NULL || self->finished) {
PyErr_SetString(PyExc_ValueError,
@@ -1639,7 +1646,9 @@ static PyObject *npyiter_index_get(NewNpyArrayIterObject *self)
}
}
-static int npyiter_index_set(NewNpyArrayIterObject *self, PyObject *value)
+static int
+npyiter_index_set(
+ NewNpyArrayIterObject *self, PyObject *value, void *NPY_UNUSED(ignored))
{
if (value == NULL) {
PyErr_SetString(PyExc_AttributeError,
@@ -1678,7 +1687,8 @@ static int npyiter_index_set(NewNpyArrayIterObject *self, PyObject *value)
}
}
-static PyObject *npyiter_iterindex_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_iterindex_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
if (self->iter == NULL || self->finished) {
PyErr_SetString(PyExc_ValueError,
@@ -1689,7 +1699,9 @@ static PyObject *npyiter_iterindex_get(NewNpyArrayIterObject *self)
return PyLong_FromLong(NpyIter_GetIterIndex(self->iter));
}
-static int npyiter_iterindex_set(NewNpyArrayIterObject *self, PyObject *value)
+static int
+npyiter_iterindex_set(
+ NewNpyArrayIterObject *self, PyObject *value, void *NPY_UNUSED(ignored))
{
npy_intp iterindex;
@@ -1722,7 +1734,8 @@ static int npyiter_iterindex_set(NewNpyArrayIterObject *self, PyObject *value)
return 0;
}
-static PyObject *npyiter_iterrange_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_iterrange_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
npy_intp istart = 0, iend = 0;
PyObject *ret;
@@ -1746,7 +1759,9 @@ static PyObject *npyiter_iterrange_get(NewNpyArrayIterObject *self)
return ret;
}
-static int npyiter_iterrange_set(NewNpyArrayIterObject *self, PyObject *value)
+static int
+npyiter_iterrange_set(
+ NewNpyArrayIterObject *self, PyObject *value, void *NPY_UNUSED(ignored))
{
npy_intp istart = 0, iend = 0;
@@ -1788,7 +1803,9 @@ static int npyiter_iterrange_set(NewNpyArrayIterObject *self, PyObject *value)
return 0;
}
-static PyObject *npyiter_has_delayed_bufalloc_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_has_delayed_bufalloc_get(
+ NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
if (self->iter == NULL) {
PyErr_SetString(PyExc_ValueError,
@@ -1804,7 +1821,9 @@ static PyObject *npyiter_has_delayed_bufalloc_get(NewNpyArrayIterObject *self)
}
}
-static PyObject *npyiter_iterationneedsapi_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_iterationneedsapi_get(
+ NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
if (self->iter == NULL) {
PyErr_SetString(PyExc_ValueError,
@@ -1820,7 +1839,9 @@ static PyObject *npyiter_iterationneedsapi_get(NewNpyArrayIterObject *self)
}
}
-static PyObject *npyiter_has_multi_index_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_has_multi_index_get(
+ NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
if (self->iter == NULL) {
PyErr_SetString(PyExc_ValueError,
@@ -1836,7 +1857,8 @@ static PyObject *npyiter_has_multi_index_get(NewNpyArrayIterObject *self)
}
}
-static PyObject *npyiter_has_index_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_has_index_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
if (self->iter == NULL) {
PyErr_SetString(PyExc_ValueError,
@@ -1852,7 +1874,8 @@ static PyObject *npyiter_has_index_get(NewNpyArrayIterObject *self)
}
}
-static PyObject *npyiter_dtypes_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_dtypes_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
PyObject *ret;
@@ -1881,7 +1904,8 @@ static PyObject *npyiter_dtypes_get(NewNpyArrayIterObject *self)
return ret;
}
-static PyObject *npyiter_ndim_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_ndim_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
if (self->iter == NULL) {
PyErr_SetString(PyExc_ValueError,
@@ -1892,7 +1916,8 @@ static PyObject *npyiter_ndim_get(NewNpyArrayIterObject *self)
return PyLong_FromLong(NpyIter_GetNDim(self->iter));
}
-static PyObject *npyiter_nop_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_nop_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
if (self->iter == NULL) {
PyErr_SetString(PyExc_ValueError,
@@ -1903,7 +1928,8 @@ static PyObject *npyiter_nop_get(NewNpyArrayIterObject *self)
return PyLong_FromLong(NpyIter_GetNOp(self->iter));
}
-static PyObject *npyiter_itersize_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_itersize_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
if (self->iter == NULL) {
PyErr_SetString(PyExc_ValueError,
@@ -1914,7 +1940,8 @@ static PyObject *npyiter_itersize_get(NewNpyArrayIterObject *self)
return PyLong_FromLong(NpyIter_GetIterSize(self->iter));
}
-static PyObject *npyiter_finished_get(NewNpyArrayIterObject *self)
+static PyObject *
+npyiter_finished_get(NewNpyArrayIterObject *self, void *NPY_UNUSED(ignored))
{
if (self->iter == NULL || !self->finished) {
Py_RETURN_FALSE;
diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src
index 9930f7791..40f736125 100644
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -1054,19 +1054,19 @@ gentype_richcompare(PyObject *self, PyObject *other, int cmp_op)
}
static PyObject *
-gentype_ndim_get(PyObject *NPY_UNUSED(self))
+gentype_ndim_get(PyObject *NPY_UNUSED(self), void *NPY_UNUSED(ignored))
{
return PyLong_FromLong(0);
}
static PyObject *
-gentype_flags_get(PyObject *NPY_UNUSED(self))
+gentype_flags_get(PyObject *NPY_UNUSED(self), void *NPY_UNUSED(ignored))
{
return PyArray_NewFlagsObject(NULL);
}
static PyObject *
-voidtype_flags_get(PyVoidScalarObject *self)
+voidtype_flags_get(PyVoidScalarObject *self, void *NPY_UNUSED(ignored))
{
PyObject *flagobj;
flagobj = PyArrayFlags_Type.tp_alloc(&PyArrayFlags_Type, 0);
@@ -1079,7 +1079,7 @@ voidtype_flags_get(PyVoidScalarObject *self)
}
static PyObject *
-voidtype_dtypedescr_get(PyVoidScalarObject *self)
+voidtype_dtypedescr_get(PyVoidScalarObject *self, void *NPY_UNUSED(ignored))
{
Py_INCREF(self->descr);
return (PyObject *)self->descr;
@@ -1087,7 +1087,7 @@ voidtype_dtypedescr_get(PyVoidScalarObject *self)
static PyObject *
-inttype_numerator_get(PyObject *self)
+inttype_numerator_get(PyObject *self, void *NPY_UNUSED(ignored))
{
Py_INCREF(self);
return self;
@@ -1095,21 +1095,21 @@ inttype_numerator_get(PyObject *self)
static PyObject *
-inttype_denominator_get(PyObject *self)
+inttype_denominator_get(PyObject *self, void *NPY_UNUSED(ignored))
{
return PyLong_FromLong(1);
}
static PyObject *
-gentype_data_get(PyObject *self)
+gentype_data_get(PyObject *self, void *NPY_UNUSED(ignored))
{
return PyMemoryView_FromObject(self);
}
static PyObject *
-gentype_itemsize_get(PyObject *self)
+gentype_itemsize_get(PyObject *self, void *NPY_UNUSED(ignored))
{
PyArray_Descr *typecode;
PyObject *ret;
@@ -1123,7 +1123,7 @@ gentype_itemsize_get(PyObject *self)
}
static PyObject *
-gentype_size_get(PyObject *NPY_UNUSED(self))
+gentype_size_get(PyObject *NPY_UNUSED(self), void *NPY_UNUSED(ignored))
{
return PyLong_FromLong(1);
}
@@ -1132,7 +1132,7 @@ static PyObject *
gentype_sizeof(PyObject *self)
{
Py_ssize_t nbytes;
- PyObject * isz = gentype_itemsize_get(self);
+ PyObject * isz = gentype_itemsize_get(self, NULL);
if (isz == NULL) {
return NULL;
}
@@ -1161,7 +1161,7 @@ gentype_struct_free(PyObject *ptr)
}
static PyObject *
-gentype_struct_get(PyObject *self)
+gentype_struct_get(PyObject *self, void *NPY_UNUSED(ignored))
{
PyArrayObject *arr;
PyArrayInterface *inter;
@@ -1187,20 +1187,20 @@ gentype_struct_get(PyObject *self)
}
static PyObject *
-gentype_priority_get(PyObject *NPY_UNUSED(self))
+gentype_priority_get(PyObject *NPY_UNUSED(self), void *NPY_UNUSED(ignored))
{
return PyFloat_FromDouble(NPY_SCALAR_PRIORITY);
}
static PyObject *
-gentype_shape_get(PyObject *NPY_UNUSED(self))
+gentype_shape_get(PyObject *NPY_UNUSED(self), void *NPY_UNUSED(ignored))
{
return PyTuple_New(0);
}
static PyObject *
-gentype_interface_get(PyObject *self)
+gentype_interface_get(PyObject *self, void *NPY_UNUSED(ignored))
{
PyArrayObject *arr;
PyObject *inter;
@@ -1220,20 +1220,20 @@ gentype_interface_get(PyObject *self)
static PyObject *
-gentype_typedescr_get(PyObject *self)
+gentype_typedescr_get(PyObject *self, void *NPY_UNUSED(ignored))
{
return (PyObject *)PyArray_DescrFromScalar(self);
}
static PyObject *
-gentype_base_get(PyObject *NPY_UNUSED(self))
+gentype_base_get(PyObject *NPY_UNUSED(self), void *NPY_UNUSED(ignored))
{
Py_RETURN_NONE;
}
static PyObject *
-voidtype_base_get(PyVoidScalarObject *self)
+voidtype_base_get(PyVoidScalarObject *self, void *NPY_UNUSED(ignored))
{
if (self->base == NULL) {
Py_RETURN_NONE;
@@ -1264,7 +1264,7 @@ _realdescr_fromcomplexscalar(PyObject *self, int *typenum)
}
static PyObject *
-gentype_real_get(PyObject *self)
+gentype_real_get(PyObject *self, void *NPY_UNUSED(ignored))
{
PyArray_Descr *typecode;
PyObject *ret;
@@ -1291,7 +1291,7 @@ gentype_real_get(PyObject *self)
}
static PyObject *
-gentype_imag_get(PyObject *self)
+gentype_imag_get(PyObject *self, void *NPY_UNUSED(ignored))
{
PyArray_Descr *typecode=NULL;
PyObject *ret;
@@ -1331,7 +1331,7 @@ gentype_imag_get(PyObject *self)
}
static PyObject *
-gentype_flat_get(PyObject *self)
+gentype_flat_get(PyObject *self, void *NPY_UNUSED(ignored))
{
PyObject *ret, *arr;
@@ -1346,7 +1346,7 @@ gentype_flat_get(PyObject *self)
static PyObject *
-gentype_transpose_get(PyObject *self)
+gentype_transpose_get(PyObject *self, void *NPY_UNUSED(ignored))
{
Py_INCREF(self);
return self;
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 27d21121f..60a315f6e 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -49,6 +49,7 @@
#include "common.h"
#include "dtypemeta.h"
#include "numpyos.h"
+#include "convert_datatype.h"
/********** PRINTF DEBUG TRACING **************/
#define NPY_UF_DBG_TRACING 0
@@ -991,33 +992,44 @@ fail:
*/
static int
check_for_trivial_loop(PyUFuncObject *ufunc,
- PyArrayObject **op,
- PyArray_Descr **dtype,
- npy_intp buffersize)
+ PyArrayObject **op, PyArray_Descr **dtypes,
+ npy_intp buffersize)
{
- npy_intp i, nin = ufunc->nin, nop = nin + ufunc->nout;
+ int i, nin = ufunc->nin, nop = nin + ufunc->nout;
for (i = 0; i < nop; ++i) {
/*
* If the dtype doesn't match, or the array isn't aligned,
* indicate that the trivial loop can't be done.
*/
- if (op[i] != NULL &&
- (!PyArray_ISALIGNED(op[i]) ||
- !PyArray_EquivTypes(dtype[i], PyArray_DESCR(op[i]))
- )) {
+ if (op[i] == NULL) {
+ continue;
+ }
+ int must_copy = !PyArray_ISALIGNED(op[i]);
+
+ if (dtypes[i] != PyArray_DESCR(op[i])) {
+ NPY_CASTING safety = PyArray_GetCastSafety(
+ PyArray_DESCR(op[i]), dtypes[i], NULL);
+ if (safety < 0) {
+ /* A proper error during a cast check should be rare */
+ return -1;
+ }
+ if (!(safety & _NPY_CAST_IS_VIEW)) {
+ must_copy = 1;
+ }
+ }
+ if (must_copy) {
/*
* If op[j] is a scalar or small one dimensional
* array input, make a copy to keep the opportunity
- * for a trivial loop.
+ * for a trivial loop. Outputs are not copied here.
*/
- if (i < nin && (PyArray_NDIM(op[i]) == 0 ||
- (PyArray_NDIM(op[i]) == 1 &&
- PyArray_DIM(op[i],0) <= buffersize))) {
+ if (i < nin && (PyArray_NDIM(op[i]) == 0
+ || (PyArray_NDIM(op[i]) == 1
+ && PyArray_DIM(op[i], 0) <= buffersize))) {
PyArrayObject *tmp;
- Py_INCREF(dtype[i]);
- tmp = (PyArrayObject *)
- PyArray_CastToType(op[i], dtype[i], 0);
+ Py_INCREF(dtypes[i]);
+ tmp = (PyArrayObject *)PyArray_CastToType(op[i], dtypes[i], 0);
if (tmp == NULL) {
return -1;
}
@@ -2476,8 +2488,6 @@ PyUFunc_GenericFunctionInternal(PyUFuncObject *ufunc,
/* These parameters come from extobj= or from a TLS global */
int buffersize = 0, errormask = 0;
- int trivial_loop_ok = 0;
-
NPY_UF_DBG_PRINT1("\nEvaluating ufunc %s\n", ufunc_name);
/* Get the buffersize and errormask */
@@ -2532,16 +2542,16 @@ PyUFunc_GenericFunctionInternal(PyUFuncObject *ufunc,
* Since it requires dtypes, it can only be called after
* ufunc->type_resolver
*/
- trivial_loop_ok = check_for_trivial_loop(ufunc,
+ int trivial_ok = check_for_trivial_loop(ufunc,
op, operation_descrs, buffersize);
- if (trivial_loop_ok < 0) {
+ if (trivial_ok < 0) {
return -1;
}
/* check_for_trivial_loop on half-floats can overflow */
npy_clear_floatstatus_barrier((char*)&ufunc);
- retval = execute_legacy_ufunc_loop(ufunc, trivial_loop_ok,
+ retval = execute_legacy_ufunc_loop(ufunc, trivial_ok,
op, operation_descrs, order,
buffersize, output_array_prepare,
full_args, op_flags);
@@ -6000,7 +6010,7 @@ _typecharfromnum(int num) {
static PyObject *
-ufunc_get_doc(PyUFuncObject *ufunc)
+ufunc_get_doc(PyUFuncObject *ufunc, void *NPY_UNUSED(ignored))
{
static PyObject *_sig_formatter;
PyObject *doc;
@@ -6032,31 +6042,31 @@ ufunc_get_doc(PyUFuncObject *ufunc)
static PyObject *
-ufunc_get_nin(PyUFuncObject *ufunc)
+ufunc_get_nin(PyUFuncObject *ufunc, void *NPY_UNUSED(ignored))
{
return PyLong_FromLong(ufunc->nin);
}
static PyObject *
-ufunc_get_nout(PyUFuncObject *ufunc)
+ufunc_get_nout(PyUFuncObject *ufunc, void *NPY_UNUSED(ignored))
{
return PyLong_FromLong(ufunc->nout);
}
static PyObject *
-ufunc_get_nargs(PyUFuncObject *ufunc)
+ufunc_get_nargs(PyUFuncObject *ufunc, void *NPY_UNUSED(ignored))
{
return PyLong_FromLong(ufunc->nargs);
}
static PyObject *
-ufunc_get_ntypes(PyUFuncObject *ufunc)
+ufunc_get_ntypes(PyUFuncObject *ufunc, void *NPY_UNUSED(ignored))
{
return PyLong_FromLong(ufunc->ntypes);
}
static PyObject *
-ufunc_get_types(PyUFuncObject *ufunc)
+ufunc_get_types(PyUFuncObject *ufunc, void *NPY_UNUSED(ignored))
{
/* return a list with types grouped input->output */
PyObject *list;
@@ -6090,20 +6100,20 @@ ufunc_get_types(PyUFuncObject *ufunc)
}
static PyObject *
-ufunc_get_name(PyUFuncObject *ufunc)
+ufunc_get_name(PyUFuncObject *ufunc, void *NPY_UNUSED(ignored))
{
return PyUnicode_FromString(ufunc->name);
}
static PyObject *
-ufunc_get_identity(PyUFuncObject *ufunc)
+ufunc_get_identity(PyUFuncObject *ufunc, void *NPY_UNUSED(ignored))
{
npy_bool reorderable;
return _get_identity(ufunc, &reorderable);
}
static PyObject *
-ufunc_get_signature(PyUFuncObject *ufunc)
+ufunc_get_signature(PyUFuncObject *ufunc, void *NPY_UNUSED(ignored))
{
if (!ufunc->core_enabled) {
Py_RETURN_NONE;
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
diff --git a/numpy/core/tests/test_casting_unittests.py b/numpy/core/tests/test_casting_unittests.py
index 1c465fea1..8398b3cad 100644
--- a/numpy/core/tests/test_casting_unittests.py
+++ b/numpy/core/tests/test_casting_unittests.py
@@ -657,3 +657,20 @@ class TestCasting:
expected = casting == "unsafe"
assert np.can_cast("V4", dtype, casting=casting) == expected
assert np.can_cast(dtype, "V4", casting=casting) == expected
+
+ @pytest.mark.parametrize("dtype", np.typecodes["All"])
+ def test_object_casts_NULL_None_equivalence(self, dtype):
+ # None to <other> casts may succeed or fail, but a NULL'ed array must
+ # behave the same as one filled with None's.
+ arr_normal = np.array([None] * 5)
+ arr_NULLs = np.empty_like([None] * 5)
+ # If the check fails (maybe it should) the test would lose its purpose:
+ assert arr_NULLs.tobytes() == b"\x00" * arr_NULLs.nbytes
+
+ try:
+ expected = arr_normal.astype(dtype)
+ except TypeError:
+ with pytest.raises(TypeError):
+ arr_NULLs.astype(dtype)
+ else:
+ assert_array_equal(expected, arr_NULLs.astype(dtype))
diff --git a/numpy/core/tests/test_hashtable.py b/numpy/core/tests/test_hashtable.py
new file mode 100644
index 000000000..bace4c051
--- /dev/null
+++ b/numpy/core/tests/test_hashtable.py
@@ -0,0 +1,30 @@
+import pytest
+
+import random
+from numpy.core._multiarray_tests import identityhash_tester
+
+
+@pytest.mark.parametrize("key_length", [1, 3, 6])
+@pytest.mark.parametrize("length", [1, 16, 2000])
+def test_identity_hashtable(key_length, length):
+ # use a 30 object pool for everything (duplicates will happen)
+ pool = [object() for i in range(20)]
+ keys_vals = []
+ for i in range(length):
+ keys = tuple(random.choices(pool, k=key_length))
+ keys_vals.append((keys, random.choice(pool)))
+
+ dictionary = dict(keys_vals)
+
+ # add a random item at the end:
+ keys_vals.append(random.choice(keys_vals))
+ # the expected one could be different with duplicates:
+ expected = dictionary[keys_vals[-1][0]]
+
+ res = identityhash_tester(key_length, keys_vals, replace=True)
+ assert res is expected
+
+ # check that ensuring one duplicate definitely raises:
+ keys_vals.insert(0, keys_vals[-2])
+ with pytest.raises(RuntimeError):
+ identityhash_tester(key_length, keys_vals)
diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py
index 7600e17be..bd56b6975 100644
--- a/numpy/lib/arraysetops.py
+++ b/numpy/lib/arraysetops.py
@@ -339,7 +339,9 @@ def _unique1d(ar, return_index=False, return_inverse=False,
aux_firstnan = np.searchsorted(np.isnan(aux), True, side='left')
else:
aux_firstnan = np.searchsorted(aux, aux[-1], side='left')
- mask[1:aux_firstnan] = (aux[1:aux_firstnan] != aux[:aux_firstnan - 1])
+ if aux_firstnan > 0:
+ mask[1:aux_firstnan] = (
+ aux[1:aux_firstnan] != aux[:aux_firstnan - 1])
mask[aux_firstnan] = True
mask[aux_firstnan + 1:] = False
else:
diff --git a/numpy/lib/format.py b/numpy/lib/format.py
index ead6a0420..9b8f90dbd 100644
--- a/numpy/lib/format.py
+++ b/numpy/lib/format.py
@@ -44,7 +44,7 @@ Capabilities
read most ``.npy`` files that they have been given without much
documentation.
-- Allows memory-mapping of the data. See `open_memmep`.
+- Allows memory-mapping of the data. See `open_memmap`.
- Can be read from a filelike stream object instead of an actual file.
diff --git a/numpy/lib/tests/test_arraysetops.py b/numpy/lib/tests/test_arraysetops.py
index d62da9efb..13385cd24 100644
--- a/numpy/lib/tests/test_arraysetops.py
+++ b/numpy/lib/tests/test_arraysetops.py
@@ -610,6 +610,17 @@ class TestUnique:
assert_equal(np.unique(a, return_inverse=True), (ua, ua_inv))
assert_equal(np.unique(a, return_counts=True), (ua, ua_cnt))
+ # test for gh-19300
+ all_nans = [np.nan] * 4
+ ua = [np.nan]
+ ua_idx = [0]
+ ua_inv = [0, 0, 0, 0]
+ ua_cnt = [4]
+ assert_equal(np.unique(all_nans), ua)
+ assert_equal(np.unique(all_nans, return_index=True), (ua, ua_idx))
+ assert_equal(np.unique(all_nans, return_inverse=True), (ua, ua_inv))
+ assert_equal(np.unique(all_nans, return_counts=True), (ua, ua_cnt))
+
def test_unique_axis_errors(self):
assert_raises(TypeError, self._run_axis_tests, object)
assert_raises(TypeError, self._run_axis_tests,
diff --git a/numpy/lib/utils.py b/numpy/lib/utils.py
index 12a7cacdc..b1a916d4a 100644
--- a/numpy/lib/utils.py
+++ b/numpy/lib/utils.py
@@ -904,7 +904,7 @@ def _lookfor_generate_cache(module, import_modules, regenerate):
sys.stdout = old_stdout
sys.stderr = old_stderr
# Catch SystemExit, too
- except BaseException:
+ except (Exception, SystemExit):
continue
for n, v in _getmembers(item):
diff --git a/numpy/linalg/lapack_lite/make_lite.py b/numpy/linalg/lapack_lite/make_lite.py
index b145f6c4f..09ffaf840 100755
--- a/numpy/linalg/lapack_lite/make_lite.py
+++ b/numpy/linalg/lapack_lite/make_lite.py
@@ -275,8 +275,8 @@ def scrubF2CSource(c_file):
def ensure_executable(name):
try:
which(name)
- except:
- raise SystemExit(name + ' not found')
+ except Exception as ex:
+ raise SystemExit(name + ' not found') from ex
def create_name_header(output_dir):
routine_re = re.compile(r'^ (subroutine|.* function)\s+(\w+)\(.*$',
diff --git a/test_requirements.txt b/test_requirements.txt
index 35a78aff1..bc30ed4bc 100644
--- a/test_requirements.txt
+++ b/test_requirements.txt
@@ -1,7 +1,7 @@
cython==0.29.23
wheel<0.36.3
setuptools<49.2.0
-hypothesis==6.14.0
+hypothesis==6.14.1
pytest==6.2.4
pytz==2021.1
pytest-cov==2.12.1
@@ -11,5 +11,5 @@ cffi
# For testing types. Notes on the restrictions:
# - Mypy relies on C API features not present in PyPy
# - There is no point in installing typing_extensions without mypy
-mypy==0.902; platform_python_implementation != "PyPy"
+mypy==0.910; platform_python_implementation != "PyPy"
typing_extensions==3.10.0.0; platform_python_implementation != "PyPy"