diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2014-03-26 16:41:39 -0600 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2014-03-26 16:41:39 -0600 |
commit | 09530882e439591adb94aab006ac99141b83f8ef (patch) | |
tree | 386293d693a9d9cf4ea8d64d3eada032b957624b | |
parent | 73959002924a43893f16c7ed6e138519bbb24424 (diff) | |
parent | c4376726bfa8335e38d8fee6cc5e376af82a24de (diff) | |
download | numpy-09530882e439591adb94aab006ac99141b83f8ef.tar.gz |
Merge pull request #4544 from juliantaylor/unaligned-index
BUG: fix unaligned access of new indexing
-rw-r--r-- | numpy/core/src/multiarray/common.c | 14 | ||||
-rw-r--r-- | numpy/core/src/multiarray/lowlevel_strided_loops.c.src | 11 | ||||
-rw-r--r-- | numpy/core/tests/test_indexing.py | 22 |
3 files changed, 39 insertions, 8 deletions
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c index 0e8a21394..1729d50e2 100644 --- a/numpy/core/src/multiarray/common.c +++ b/numpy/core/src/multiarray/common.c @@ -650,14 +650,12 @@ _IsAligned(PyArrayObject *ap) { unsigned int i; npy_uintp aligned; - const unsigned int alignment = PyArray_DESCR(ap)->alignment; - - /* The special casing for STRING and VOID types was removed - * in accordance with http://projects.scipy.org/numpy/ticket/1227 - * It used to be that IsAligned always returned True for these - * types, which is indeed the case when they are created using - * PyArray_DescrConverter(), but not necessarily when using - * PyArray_DescrAlignConverter(). */ + npy_uintp alignment = PyArray_DESCR(ap)->alignment; + + /* alignment 1 types should have a efficient alignment for copy loops */ + if (PyArray_ISFLEXIBLE(ap) || PyArray_ISSTRING(ap)) { + alignment = 16; + } if (alignment == 1) { return 1; diff --git a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src index e3d0c4b88..02920014b 100644 --- a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src +++ b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src @@ -1429,6 +1429,7 @@ mapiter_trivial_@name@(PyArrayObject *self, PyArrayObject *ind, default: #endif while (itersize--) { + assert(npy_is_aligned(ind_ptr, _ALIGN(npy_intp))); indval = *((npy_intp*)ind_ptr); #if @isget@ if (check_and_adjust_index(&indval, fancy_dim, 1, _save) < 0 ) { @@ -1443,6 +1444,8 @@ mapiter_trivial_@name@(PyArrayObject *self, PyArrayObject *ind, #if @isget@ #if @elsize@ + assert(npy_is_aligned(result_ptr, _ALIGN(@copytype@))); + assert(npy_is_aligned(self_ptr, _ALIGN(@copytype@))); *(@copytype@ *)result_ptr = *(@copytype@ *)self_ptr; #else copyswap(result_ptr, self_ptr, 0, self); @@ -1450,6 +1453,8 @@ mapiter_trivial_@name@(PyArrayObject *self, PyArrayObject *ind, #else /* !@isget@ */ #if @elsize@ + assert(npy_is_aligned(result_ptr, _ALIGN(@copytype@))); + assert(npy_is_aligned(self_ptr, _ALIGN(@copytype@))); *(@copytype@ *)self_ptr = *(@copytype@ *)result_ptr; #else copyswap(self_ptr, result_ptr, 0, self); @@ -1567,6 +1572,8 @@ mapiter_@name@(PyArrayMapIterObject *mit) while (count--) { self_ptr = baseoffset; for (i=0; i < @numiter@; i++) { + assert(npy_is_aligned(outer_ptrs[i], + _ALIGN(npy_intp))); indval = *((npy_intp*)outer_ptrs[i]); #if @isget@ && @one_iter@ @@ -1587,12 +1594,16 @@ mapiter_@name@(PyArrayMapIterObject *mit) #if @isget@ #if @elsize@ + assert(npy_is_aligned(outer_ptrs[i], _ALIGN(@copytype@))); + assert(npy_is_aligned(self_ptr, _ALIGN(@copytype@))); *(@copytype@ *)(outer_ptrs[i]) = *(@copytype@ *)self_ptr; #else copyswap(outer_ptrs[i], self_ptr, 0, array); #endif #else /* !@isget@ */ #if @elsize@ + assert(npy_is_aligned(outer_ptrs[i], _ALIGN(@copytype@))); + assert(npy_is_aligned(self_ptr, _ALIGN(@copytype@))); *(@copytype@ *)self_ptr = *(@copytype@ *)(outer_ptrs[i]); #else copyswap(self_ptr, outer_ptrs[i], 0, array); diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py index 736210722..f09940af7 100644 --- a/numpy/core/tests/test_indexing.py +++ b/numpy/core/tests/test_indexing.py @@ -336,6 +336,28 @@ class TestIndexing(TestCase): assert_equal(sys.getrefcount(np.dtype(np.intp)), refcount) + def test_unaligned(self): + v = (np.zeros(64, dtype=np.int8) + ord('a'))[1:-7] + d = v.view(np.dtype("S8")) + # unaligned source + x = (np.zeros(16, dtype=np.int8) + ord('a'))[1:-7] + x = x.view(np.dtype("S8")) + x[...] = np.array("b" * 8, dtype="S") + b = np.arange(d.size) + #trivial + assert_equal(d[b], d) + d[b] = x + # nontrivial + # unaligned index array + b = np.zeros(d.size + 1).view(np.int8)[1:-(np.intp(0).itemsize - 1)] + b = b.view(np.intp)[:d.size] + b[...] = np.arange(d.size) + assert_equal(d[b.astype(np.int16)], d) + d[b.astype(np.int16)] = x + # boolean + d[b % 2 == 0] + d[b % 2 == 0] = x[::2] + class TestFieldIndexing(TestCase): def test_scalar_return_type(self): |