logo
macro_rules! s {
    (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr;$s:expr) => { ... };
    (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr) => { ... };
    (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr;$s:expr ,) => { ... };
    (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr ,) => { ... };
    (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr;$s:expr, $($t:tt)*) => { ... };
    (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr, $($t:tt)*) => { ... };
    (@parse ::std::marker::PhantomData::<$crate::Ix0>, ::std::marker::PhantomData::<$crate::Ix0>, []) => { ... };
    (@parse $($t:tt)*) => { ... };
    (@convert $r:expr) => { ... };
    (@convert $r:expr, $s:expr) => { ... };
    ($($t:tt)*) => { ... };
}
Expand description

Slice argument constructor.

s![] takes a list of ranges/slices/indices/new-axes, separated by comma, with optional step sizes that are separated from the range by a semicolon. It is converted into a SliceInfo instance.

Each range/slice/index uses signed indices, where a negative value is counted from the end of the axis. Step sizes are also signed and may be negative, but must not be zero.

The syntax is s![ [ elem [, elem [ , … ] ] ] ], where elem is any of the following:

  • index: an index to use for taking a subview with respect to that axis. (The index is selected. The axis is removed except with .slice_collapse().)
  • range: a range with step size 1 to use for slicing that axis.
  • range ; step: a range with step size step to use for slicing that axis.
  • slice: a Slice instance to use for slicing that axis.
  • slice ; step: a range constructed from a Slice instance, multiplying the step size by step, to use for slicing that axis.
  • new-axis: a NewAxis instance that represents the creation of a new axis. (Except for .slice_collapse(), which panics on NewAxis elements.)

The number of elem, not including new-axis, must match the number of axes in the array. index, range, slice, step, and new-axis can be expressions. index must be of type isize, usize, or i32. range must be of type Range<I>, RangeTo<I>, RangeFrom<I>, or RangeFull where I is isize, usize, or i32. step must be a type that can be converted to isize with the as keyword.

For example, s![0..4;2, 6, 1..5, NewAxis] is a slice of the first axis for 0..4 with step size 2, a subview of the second axis at index 6, a slice of the third axis for 1..5 with default step size 1, and a new axis of length 1 at the end of the shape. The input array must have 3 dimensions. The resulting slice would have shape [2, 4, 1] for .slice(), .slice_mut(), and .slice_move(), while .slice_collapse() would panic. Without the NewAxis, i.e. s![0..4;2, 6, 1..5], .slice_collapse() would result in an array of shape [2, 1, 4].

See also Slicing.

Example

use ndarray::{s, Array2, ArrayView2};

fn laplacian(v: &ArrayView2<f32>) -> Array2<f32> {
    -4. * &v.slice(s![1..-1, 1..-1])
    + v.slice(s![ ..-2, 1..-1])
    + v.slice(s![1..-1,  ..-2])
    + v.slice(s![1..-1, 2..  ])
    + v.slice(s![2..  , 1..-1])
}

Negative step

The behavior of negative step arguments is most easily understood with slicing as a two-step process:

  1. First, perform a slice with range.

  2. If step is positive, start with the front of the slice; if step is negative, start with the back of the slice. Then, add step until reaching the other end of the slice (inclusive).

An equivalent way to think about step 2 is, “If step is negative, reverse the slice. Start at the front of the (possibly reversed) slice, and add step.abs() until reaching the back of the slice (inclusive).”

For example,

let arr = array![0, 1, 2, 3];
assert_eq!(arr.slice(s![1..3;-1]), array![2, 1]);
assert_eq!(arr.slice(s![1..;-2]), array![3, 1]);
assert_eq!(arr.slice(s![0..4;-2]), array![3, 1]);
assert_eq!(arr.slice(s![0..;-2]), array![3, 1]);
assert_eq!(arr.slice(s![..;-2]), array![3, 1]);