summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/src/umath/ufunc_object.c13
-rw-r--r--numpy/core/tests/test_ufunc.py15
2 files changed, 22 insertions, 6 deletions
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index c57199c79..19876d641 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -2697,9 +2697,13 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
}
}
- /* Any output core dimensions shape should be ignored */
+ /*
+ * Any output core dimensions shape should be ignored, so we add
+ * it as a Reduce dimension (which can be broadcast with the rest).
+ * These will be removed before the actual iteration for gufuncs.
+ */
for (idim = broadcast_ndim; idim < iter_ndim; ++idim) {
- op_axes_arrays[i][idim] = -1;
+ op_axes_arrays[i][idim] = NPY_ITER_REDUCTION_AXIS(-1);
}
/* Except for when it belongs to this output */
@@ -2771,7 +2775,7 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
*/
_ufunc_setup_flags(ufunc, NPY_ITER_COPY | NPY_UFUNC_DEFAULT_INPUT_FLAGS,
NPY_ITER_UPDATEIFCOPY |
- NPY_ITER_READWRITE |
+ NPY_ITER_WRITEONLY |
NPY_UFUNC_DEFAULT_OUTPUT_FLAGS,
op_flags);
/* For the generalized ufunc, we get the loop right away too */
@@ -2820,7 +2824,6 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
iter_flags = ufunc->iter_flags |
NPY_ITER_MULTI_INDEX |
NPY_ITER_REFS_OK |
- NPY_ITER_REDUCE_OK |
NPY_ITER_ZEROSIZE_OK |
NPY_ITER_COPY_IF_OVERLAP;
@@ -3646,7 +3649,7 @@ PyUFunc_Reduce(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
result = PyUFunc_ReduceWrapper(arr, out, wheremask, dtype, dtype,
NPY_UNSAFE_CASTING,
axis_flags, reorderable,
- keepdims, 0,
+ keepdims,
initial,
reduce_loop,
ufunc, buffersize, ufunc_name, errormask);
diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py
index abdaeeb93..e47365293 100644
--- a/numpy/core/tests/test_ufunc.py
+++ b/numpy/core/tests/test_ufunc.py
@@ -610,7 +610,17 @@ class TestUfunc:
warnings.simplefilter("always")
u += v
assert_equal(len(w), 1)
- assert_(x[0,0] != u[0, 0])
+ assert_(x[0, 0] != u[0, 0])
+
+ # Output reduction should not be allowed.
+ # See gh-15139
+ a = np.arange(6).reshape(3, 2)
+ b = np.ones(2)
+ out = np.empty(())
+ assert_raises(ValueError, umt.inner1d, a, b, out)
+ out2 = np.empty(3)
+ c = umt.inner1d(a, b, out2)
+ assert_(c is out2)
def test_type_cast(self):
msg = "type cast"
@@ -942,7 +952,10 @@ class TestUfunc:
assert_array_equal(result, np.vstack((np.zeros(3), a[2], -a[1])))
assert_raises(ValueError, umt.cross1d, np.eye(4), np.eye(4))
assert_raises(ValueError, umt.cross1d, a, np.arange(4.))
+ # Wrong output core dimension.
assert_raises(ValueError, umt.cross1d, a, np.arange(3.), np.zeros((3, 4)))
+ # Wrong output broadcast dimension (see gh-15139).
+ assert_raises(ValueError, umt.cross1d, a, np.arange(3.), np.zeros(3))
def test_can_ignore_signature(self):
# Comparing the effects of ? in signature: