summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Taylor <jtaylor.debian@googlemail.com>2014-11-26 21:51:05 +0100
committerCharles Harris <charlesr.harris@gmail.com>2015-01-21 19:06:24 -0700
commite0ef28b22a04d1d470e381f1b0cee56aec4349ed (patch)
tree369c14c41429f99c26b4006864991e205c89d722
parentc9075faa59f823033dca449edce002a0a569a9a5 (diff)
downloadnumpy-e0ef28b22a04d1d470e381f1b0cee56aec4349ed.tar.gz
BUG: fix string arrays not being aligned
If itemsize is a power of two use that as the required alignment up to the maximum provided by the platform. Power of two sizes may be accessed via larger moves than bytes. Non-power of two sizes are accessed bytewise and can thus always be considered aligned. Closes gh-5293
-rw-r--r--numpy/core/src/multiarray/common.c11
-rw-r--r--numpy/core/tests/test_multiarray.py11
2 files changed, 21 insertions, 1 deletions
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c
index 7015b3961..a8490f0e8 100644
--- a/numpy/core/src/multiarray/common.c
+++ b/numpy/core/src/multiarray/common.c
@@ -684,7 +684,16 @@ _IsAligned(PyArrayObject *ap)
/* alignment 1 types should have a efficient alignment for copy loops */
if (PyArray_ISFLEXIBLE(ap) || PyArray_ISSTRING(ap)) {
- alignment = NPY_MAX_COPY_ALIGNMENT;
+ npy_intp itemsize = PyArray_ITEMSIZE(ap);
+ /* power of two sizes may be loaded in larger moves */
+ if (((itemsize & (itemsize - 1)) == 0)) {
+ alignment = itemsize > NPY_MAX_COPY_ALIGNMENT ?
+ NPY_MAX_COPY_ALIGNMENT : itemsize;
+ }
+ else {
+ /* if not power of two it will be accessed bytewise */
+ alignment = 1;
+ }
}
if (alignment == 1) {
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index d472a9569..a9762978b 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -68,6 +68,17 @@ class TestFlags(TestCase):
assert_equal(self.a.flags.aligned, True)
assert_equal(self.a.flags.updateifcopy, False)
+ def test_string_align(self):
+ a = np.zeros(4, dtype=np.dtype('|S4'))
+ assert_(a.flags.aligned)
+ # not power of two are accessed bytewise and thus considered aligned
+ a = np.zeros(5, dtype=np.dtype('|S4'))
+ assert_(a.flags.aligned)
+
+ def test_void_align(self):
+ a = np.zeros(4, dtype=np.dtype([("a", "i4"), ("b", "i4")]))
+ assert_(a.flags.aligned)
+
class TestHash(TestCase):
# see #3793
def test_int(self):