8000 BUG: fix string arrays not being aligned · numpy/numpy@3351dbf · GitHub
[go: up one dir, main page]

Skip to content

Commit 3351dbf

Browse files
committed
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
1 parent 31b94e8 commit 3351dbf

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

numpy/core/src/multiarray/common.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,16 @@ _IsAligned(PyArrayObject *ap)
684684

685685
/* alignment 1 types should have a efficient alignment for copy loops */
686686
if (PyArray_ISFLEXIBLE(ap) || PyArray_ISSTRING(ap)) {
687-
alignment = NPY_MAX_COPY_ALIGNMENT;
687+
npy_intp itemsize = PyArray_ITEMSIZE(ap);
688+
/* power of two sizes may be loaded in larger moves */
689+
if (((itemsize & (itemsize - 1)) == 0)) {
690+
alignment = itemsize > NPY_MAX_COPY_ALIGNMENT ?
691+
NPY_MAX_COPY_ALIGNMENT : itemsize;
692+
}
693+
else {
694+
/* if not power of two it will be accessed bytewise */
695+
alignment = 1;
696+
}
688697
}
689698

690699
if (alignment == 1) {

numpy/core/tests/test_multiarray.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ def test_otherflags(self):
6868
assert_equal(self.a.flags.aligned, True)
6969
assert_equal(self.a.flags.updateifcopy, False)
7070

71+
def test_string_align(self):
72+
a = np.zeros(4, dtype=np.dtype('|S4'))
73+
assert_(a.flags.aligned)
74+
# not power of two are accessed bytewise and thus considered aligned
75+
a = np.zeros(5, dtype=np.dtype('|S4'))
76+
assert_(a.flags.aligned)
77+
78+
def test_void_align(self):
79+
a = np.zeros(4, dtype=np.dtype([("a", "i4"), ("b", "i4")]))
80+
assert_(a.flags.aligned)
81+
7182
class TestHash(TestCase):
7283
# see #3793
7384
def test_int(self):

0 commit comments

Comments
 (0)
0