Skip to content

BUG: Fix buffered iterator stride after removing multi-index#31985

Open
snoopuppy582 wants to merge 1 commit into
numpy:mainfrom
snoopuppy582:fix/unravel-index-buffer-boundary
Open

BUG: Fix buffered iterator stride after removing multi-index#31985
snoopuppy582 wants to merge 1 commit into
numpy:mainfrom
snoopuppy582:fix/unravel-index-buffer-boundary

Conversation

@snoopuppy582

Copy link
Copy Markdown

PR summary

This PR fixes a critical bug where incorrect coordinates are returned after the iterator buffer boundary for large (N, 1) index arrays. As seen in real-world applications (e.g., MRI reconstruction in mckib2/pygrappa#107), this can silently produce incorrect results without raising any exceptions.

Root Cause:
The issue occurs because the transfer loop is fixed to a zero stride for a size-one inner axis, failing to reflect the updated runtime stride after remove_multi_index is applied.

Fix:
To resolve this, I modified numpy/_core/src/multiarray/nditer_constr.c to exclude mutable strides from the fixed-stride optimization.

Testing & Verification:

  • Added generic nditer regression tests in numpy/_core/tests/test_nditer.py.
  • Added public unravel_index regression tests in numpy/lib/tests/test_index_tricks.py.
  • I have manually run and confirmed that all core tests and linting pass successfully locally.

Closes #31980

First time committer introduction

Hi, I am snoopuppy582, a developer using NumPy. I investigated this issue because of its silent but critical impact on real-world calculations, and I hope this patch helps improve the stability of the library.

AI Disclosure

I used AI tools (OpenAI Codex / ChatGPT) strictly for review and verification purposes to ensure the quality of the fix.

I manually analyzed the root cause, wrote the C modifications and regression tests, and executed all local validations. I have fully reviewed and understood the entire diff. Also, this PR description, the commit messages, and all future communications are written entirely by me manually.

if ((itflags & NPY_ITFLAG_HASMULTIINDEX) &&
NAD_SHAPE(axisdata) == 1 && op_stride == 0) {
op_stride = NPY_MAX_INTP;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for a small contribution to the code review here -- I confirmed that both of the added regression tests fail locally on ARM Mac when I revert this source patch. The full testsuite is passing for me locally on this branch.

The patch does appear to be focused around a real world failure scenario, though it does seem a little obscure and hard to follow.

Probably a more active NumPy core dev should take a look--the patch is relatively small, but the team is getting pretty inundated at the moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: unravel_index returns incorrect coordinates for large (N, 1) index arrays across an iterator buffer boundary

2 participants