diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2016-09-11 13:37:48 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-11 13:37:48 -0500 |
commit | 5925f8bb18bf40c97d0432e3216b8e12c8d5cf01 (patch) | |
tree | df658aebdad8464c4a95b78b1596151ba8be10a7 | |
parent | 5382c561700f2e48a5c855b55a9914c7c7bbc0fa (diff) | |
parent | 1cd78568f7ccb1aaba84a3ca6741f527c972ca4c (diff) | |
download | numpy-5925f8bb18bf40c97d0432e3216b8e12c8d5cf01.tar.gz |
Merge pull request #8044 from charris/backport-8042
Backport 8042, BUG: core: fix bug in NpyIter buffering with discontinuous arrays
-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 c00360bfb..45aef0b58 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 ed0197991..d39f1fe2d 100644 --- a/numpy/core/tests/test_nditer.py +++ b/numpy/core/tests/test_nditer.py @@ -2367,6 +2367,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 ab8cecff0..1b734e412 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -1238,6 +1238,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() |