From 975a94623b1c84979ef9bfe620745299f420315a Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Tue, 4 Jan 2022 14:53:23 -0800 Subject: BUG: Relax dtype identity check in reductions In some cases, e.g. ensure-native-byte-order will return not the default, but a copy of the descriptor. This (and maybe metadata) makes it somewhat annoying to ensure exact identity between descriptors for reduce "operands" as returned by the resolve-descirptors method of the ArrayMethod. To avoid this problem, we check for no-casting (which implies viewable with `offset == 0`) rather than strict identity. Unfortunately, this means that descriptor resolution must be slightly more careful, but in general this should all be perfectly well defined. Closes gh-20699 --- numpy/core/src/umath/ufunc_object.c | 8 ++++++-- numpy/core/tests/test_ufunc.py | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index 52b354353..83e18a363 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -2764,9 +2764,13 @@ reducelike_promote_and_resolve(PyUFuncObject *ufunc, * The first operand and output should be the same array, so they should * be identical. The second argument can be different for reductions, * but is checked to be identical for accumulate and reduceat. + * Ideally, the type-resolver ensures that all are identical, but we do + * not enforce this here strictly. Otherwise correct handling of + * byte-order changes (or metadata) requires a lot of care; see gh-20699. */ - if (out_descrs[0] != out_descrs[2] || ( - enforce_uniform_args && out_descrs[0] != out_descrs[1])) { + if (!PyArray_EquivTypes(out_descrs[0], out_descrs[2]) || ( + enforce_uniform_args && !PyArray_EquivTypes( + out_descrs[0], out_descrs[1]))) { PyErr_Format(PyExc_TypeError, "the resolved dtypes are not compatible with %s.%s. " "Resolved (%R, %R, %R)", diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index 76e4cdcfd..9a9d46da0 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -2148,6 +2148,17 @@ class TestUfunc: # It would be safe, but not equiv casting: ufunc(a, c, out=out, casting="equiv") + def test_reducelike_byteorder_resolution(self): + # See gh-20699, byte-order changes need some extra care in the type + # resolution to make the following succeed: + arr_be = np.arange(10, dtype=">i8") + arr_le = np.arange(10, dtype="