Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix segfaulting issue with reduce iterator #382

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 4 additions & 42 deletions bottleneck/include/iterators.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,6 @@ static inline void init_iter_all(iter *it, PyArrayObject *a, int ravel, int anyo
it->nits = 1;
it->a_ravel = NULL;

/* The fix for relaxed strides checking in numpy and the fix for
* issue #183 has left this if..else tree in need of a refactor from the
* the ground up */
if (ndim == 1) {
it->ndim_m2 = -1;
it->length = shape[0];
Expand All @@ -98,47 +95,12 @@ static inline void init_iter_all(iter *it, PyArrayObject *a, int ravel, int anyo
it->ndim_m2 = -1;
it->length = 1;
it->astride = 0;
} else if (C_CONTIGUOUS(a) && !F_CONTIGUOUS(a)) {
/* The &&! in the next two else ifs is to deal with relaxed
* stride checking introduced in numpy 1.12.0; see gh #161 */
} else if (C_CONTIGUOUS(a) || (anyorder && F_CONTIGUOUS(a))) {
/* If continguous then we just need the itemsize */
it->ndim_m2 = -1;
it->axis = ndim - 1;
// it->axis does not matter
it->length = PyArray_SIZE(a);
it->astride = 0;
for (i = ndim - 1; i > -1; i--) {
/* protect against length zero strides such as in
* np.ones((2, 2))[..., np.newaxis] */
if (strides[i] == 0) {
continue;
}
it->astride = strides[i];
break;
}
} else if (F_CONTIGUOUS(a) && !C_CONTIGUOUS(a)) {
if (anyorder || !ravel) {
it->ndim_m2 = -1;
it->length = PyArray_SIZE(a);
it->astride = 0;
for (i = 0; i < ndim; i++) {
/* protect against length zero strides such as in
* np.ones((2, 2), order='F')[np.newaxis, ...] */
if (strides[i] == 0) {
continue;
}
it->astride = strides[i];
break;
}
} else {
it->ndim_m2 = -1;
if (anyorder) {
a = (PyArrayObject *)PyArray_Ravel(a, NPY_ANYORDER);
} else {
a = (PyArrayObject *)PyArray_Ravel(a, NPY_CORDER);
}
it->a_ravel = a;
it->length = PyArray_DIM(a, 0);
it->astride = PyArray_STRIDE(a, 0);
}
it->astride = item_size;
} else if (ravel) {
it->ndim_m2 = -1;
if (anyorder) {
Expand Down
28 changes: 28 additions & 0 deletions bottleneck/tests/reduce_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,31 @@ def test_ddof_nans(func, dtype):
for axis in [None, 0, 1, -1]:
result = func(array, axis=axis, ddof=3)
assert np.isnan(result)


@pytest.mark.parametrize("dtype", DTYPES)
@pytest.mark.parametrize(
("func", "expected"),
[(bn.nansum, 1000),
(bn.nanmean, 1),
(bn.nanmax, 1)],
ids=lambda x: x.__name__ if not isinstance(x, int) else x
)
def test_reduce_with_unordered_strides_ccontig(func, expected, dtype) -> None:
array = np.ones((1, 500, 2), dtype=dtype).transpose((1,2,0))
result = func(array)
assert result == expected

@pytest.mark.parametrize("dtype", DTYPES)
@pytest.mark.parametrize(
("func", "expected"),
[(bn.nansum, 1000),
(bn.nanmean, 1),
(bn.nanmax, 1)],
ids=lambda x: x.__name__ if not isinstance(x, int) else x
)
def test_reduce_with_unordered_strides_fcontig(func, expected, dtype) -> None:
array = np.ones((1, 500, 2), dtype=dtype).transpose((0,2,1))
result = func(array)
assert result == expected