Skip to content

fix: partition panics on lanes with a negative stride - #1625

Open
b84330808 wants to merge 1 commit into
rust-ndarray:masterfrom
b84330808:fix-partition-negative-stride
Open

b84330808 wants to merge 1 commit into
rust-ndarray:masterfrom
b84330808:fix-partition-negative-stride

Conversation

@b84330808

Copy link
Copy Markdown

partition panics when the lanes along axis have a negative stride:

use ndarray::prelude::*;

let mut a = array![[7, 1, 5, 3], [2, 6, 0, 4]];
a.invert_axis(Axis(1));
a.partition(1, Axis(1)); // panics

let b = array![3, 1, 4, 1, 5, 9, 2, 6];
b.slice(s![..;-1]).partition(3, Axis(0)); // panics too
called `Option::unwrap()` on a `None` value

partition copies the array with to_owned(), which keeps the negative stride, and then takes the slice fast path if the first lane is_contiguous(). A lane with stride -1 counts as contiguous, but as_slice_mut() only returns a slice for standard layout, so the unwrap() in the fast path fails.

This checks as_slice_mut().is_some() instead, which is exactly what the fast path needs. Lanes with a negative stride now go through the existing copy path, which already handles any stride.

Added test_partition_negative_stride covering an inverted axis and a reversed view; it panics without the change. cargo test -p ndarray -F approx,serde,rayon, cargo clippy -F approx,serde,rayon and cargo +nightly fmt --all --check pass locally.

I used Claude Code to write this change.

`partition` picks the slice fast path when the first lane is contiguous,
then calls `as_slice_mut().unwrap()` on each lane. A lane along an
inverted axis (e.g. after `invert_axis` or `s![..;-1]`) is contiguous but
has stride -1, so `as_slice_mut()` returns `None` and the unwrap panics.

Check `as_slice_mut().is_some()` instead, so such lanes go through the
copying path that already handles arbitrary strides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@by-ae by-ae left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Checked this out at c4aba74 and ran the partition tests in the lib (cargo test -p ndarray --lib test_partition): all 8 pass, including the new test_partition_negative_stride.

I also ran a randomized probe outside the test suite: 3000 random 1-3D i32 arrays (C and F order), with each axis randomly inverted or sliced with step -2 or 2, partitioning along a random axis at a random kth. For every lane it checked that the result is a permutation of the input lane, that p[kth] equals the kth element of the sorted lane, and that everything before or after it is <= or >= respectively. On master the same probe panics at the as_slice_mut().unwrap() inside the fast path (impl_methods.rs:3324). On this branch all 3000 cases pass.

Checking only the first lane is fine, since every lane along axis has the same stride, so if as_slice_mut() works for the first lane it works for all of them.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants