summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2014-03-26 16:41:39 -0600
committerCharles Harris <charlesr.harris@gmail.com>2014-03-26 16:41:39 -0600
commit09530882e439591adb94aab006ac99141b83f8ef (patch)
tree386293d693a9d9cf4ea8d64d3eada032b957624b
parent73959002924a43893f16c7ed6e138519bbb24424 (diff)
parentc4376726bfa8335e38d8fee6cc5e376af82a24de (diff)
downloadnumpy-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.c14
-rw-r--r--numpy/core/src/multiarray/lowlevel_strided_loops.c.src11
-rw-r--r--numpy/core/tests/test_indexing.py22
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):