Skip to content

Commit f5f1d34

Browse files
committed
refinements
1 parent 20da893 commit f5f1d34

2 files changed

Lines changed: 22 additions & 3 deletions

File tree

src/methods.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,14 +1466,20 @@ map_object(PyObject *Py_UNUSED(m), PyObject *args, PyObject *kwargs)
14661466
int has_big_int = 0;
14671467
int needs_object = 0;
14681468

1469-
for (npy_intp i = 0; i < n; i++) {
1469+
// 1D: hoist the base pointer and element stride and walk a running pointer, rather
1470+
// than recomputing PyArray_GETPTR1 each iteration. For a contiguous array the stride
1471+
// is the itemsize (direct indexing into the flat buffer); a strided slice still works.
1472+
char *p = (char*)PyArray_DATA(array);
1473+
npy_intp stride = PyArray_STRIDES(array)[0];
1474+
1475+
for (npy_intp i = 0; i < n; i++, p += stride) {
14701476
PyObject *elem;
14711477
if (is_object) {
1472-
elem = *(PyObject**)PyArray_GETPTR1(array, i);
1478+
elem = *(PyObject**)p;
14731479
Py_INCREF(elem);
14741480
}
14751481
else {
1476-
elem = PyArray_ToScalar(PyArray_GETPTR1(array, i), array);
1482+
elem = PyArray_ToScalar(p, array);
14771483
if (elem == NULL) {
14781484
goto fail;
14791485
}

test/test_map_object.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,19 @@ def test_map_object_empty(self) -> None:
119119
post = self._check(np.array([], dtype=np.float64), lambda x: str(x))
120120
self.assertEqual(len(post), 0)
121121

122+
def test_map_object_strided_non_contiguous(self) -> None:
123+
# a strided slice (non-contiguous) must be walked correctly by the running pointer
124+
base = np.array([1.0, 99.0, 2.0, 99.0, 3.0])
125+
strided = base[::2]
126+
self.assertFalse(strided.flags['C_CONTIGUOUS'])
127+
post = self._check(strided, lambda x: str(x))
128+
self.assertEqual(post.tolist(), ['1.0', '2.0', '3.0'])
129+
130+
def test_map_object_strided_object(self) -> None:
131+
arr = np.array(['a', 'X', 'bb', 'X', 'ccc'], dtype=object)[::2]
132+
post = self._check(arr, lambda x: len(x))
133+
self.assertEqual(post.tolist(), [1, 2, 3])
134+
122135
def test_map_object_propagates_exception(self) -> None:
123136
def bad(x):
124137
raise ValueError('boom')

0 commit comments

Comments
 (0)