diff options
-rw-r--r-- | numpy/core/src/multiarray/nditer_api.c | 2 | ||||
-rw-r--r-- | numpy/core/tests/test_nditer.py | 16 | ||||
-rw-r--r-- | numpy/core/tests/test_ufunc.py | 21 |
3 files changed, 38 insertions, 1 deletions
diff --git a/numpy/core/src/multiarray/nditer_api.c b/numpy/core/src/multiarray/nditer_api.c index 21bbbaad4..da3c85ae0 100644 --- a/numpy/core/src/multiarray/nditer_api.c +++ b/numpy/core/src/multiarray/nditer_api.c @@ -2334,7 +2334,7 @@ npyiter_copy_to_buffers(NpyIter *iter, char **prev_dataptrs) } else { /* It's all in one stride in the reduce outer loop */ - if ((reduce_outerdim > 0) && + if ((reduce_outerdim == 1) && (transfersize/reduce_innersize <= NAD_SHAPE(reduce_outeraxisdata) - NAD_INDEX(reduce_outeraxisdata))) { diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py index 3b5aaa28d..51c3d6286 100644 --- a/numpy/core/tests/test_nditer.py +++ b/numpy/core/tests/test_nditer.py @@ -2374,6 +2374,22 @@ def test_iter_buffering_reduction(): it.reset() assert_equal(it[0], [1, 2, 1, 2]) + # Iterator inner loop should take argument contiguity into account + x = np.ones((7, 13, 8), np.int8)[4:6,1:11:6,1:5].transpose(1, 2, 0) + x[...] = np.arange(x.size).reshape(x.shape) + y_base = np.arange(4*4, dtype=np.int8).reshape(4, 4) + y_base_copy = y_base.copy() + y = y_base[::2,:,None] + + it = np.nditer([y, x], + ['buffered', 'external_loop', 'reduce_ok'], + [['readwrite'], ['readonly']]) + for a, b in it: + a.fill(2) + + assert_equal(y_base[1::2], y_base_copy[1::2]) + assert_equal(y_base[::2], 2) + def test_iter_buffering_reduction_reuse_reduce_loops(): # There was a bug triggering reuse of the reduce loop inappropriately, # which caused processing to happen in unnecessarily small chunks diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index 62fe3c04b..3fea68700 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -1257,6 +1257,27 @@ class TestUfunc(TestCase): for f in binary_funcs: assert_raises(TypeError, f, a, b) + def test_reduce_noncontig_output(self): + # Check that reduction deals with non-contiguous output arrays + # appropriately. + # + # gh-8036 + + x = np.arange(7*13*8, dtype=np.int16).reshape(7, 13, 8) + x = x[4:6,1:11:6,1:5].transpose(1, 2, 0) + y_base = np.arange(4*4, dtype=np.int16).reshape(4, 4) + y = y_base[::2,:] + + y_base_copy = y_base.copy() + + r0 = np.add.reduce(x, out=y.copy(), axis=2) + r1 = np.add.reduce(x, out=y, axis=2) + + # The results should match, and y_base shouldn't get clobbered + assert_equal(r0, r1) + assert_equal(y_base[1,:], y_base_copy[1,:]) + assert_equal(y_base[3,:], y_base_copy[3,:]) + if __name__ == "__main__": run_module_suite() |