summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2016-09-11 13:37:48 -0500
committerGitHub <noreply@github.com>2016-09-11 13:37:48 -0500
commit5925f8bb18bf40c97d0432e3216b8e12c8d5cf01 (patch)
treedf658aebdad8464c4a95b78b1596151ba8be10a7
parent5382c561700f2e48a5c855b55a9914c7c7bbc0fa (diff)
parent1cd78568f7ccb1aaba84a3ca6741f527c972ca4c (diff)
downloadnumpy-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.c2
-rw-r--r--numpy/core/tests/test_nditer.py16
-rw-r--r--numpy/core/tests/test_ufunc.py21
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()