diff options
-rw-r--r-- | numpy/core/src/umath/ufunc_object.c | 13 | ||||
-rw-r--r-- | numpy/core/tests/test_ufunc.py | 15 |
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: |