macro_rules! s {
() => { ... };
($idx:literal) => { ... };
($idx1:literal, $idx2:literal $(,)?) => { ... };
($idx1:literal, $idx2:literal, $idx3:literal $(,)?) => { ... };
($idx1:literal, $idx2:literal, $idx3:literal, $idx4:literal $(,)?) => { ... };
($start:literal .. $end:literal ; $step:literal) => { ... };
($start:literal .. ; $step:literal) => { ... };
(.. $end:literal ; $step:literal) => { ... };
(.. ; $step:literal) => { ... };
($start:literal .. $end:literal) => { ... };
($start:literal ..) => { ... };
(.. $end:literal) => { ... };
(..) => { ... };
($start:literal ..= $end:literal) => { ... };
($start:literal ..= $end:literal ; $step:literal) => { ... };
(..= $end:literal) => { ... };
(..= $end:literal ; $step:literal) => { ... };
(.. ; $step:literal, $start2:literal .. $end2:literal $(,)?) => { ... };
($start1:literal .. ; $step:literal, $start2:literal .. $end2:literal $(,)?) => { ... };
($start1:literal .. $end1:literal ; $step:literal, $start2:literal .. $end2:literal $(,)?) => { ... };
($start1:literal .., $start2:literal .. $end2:literal $(,)?) => { ... };
($start1:literal .., .. $end2:literal $(,)?) => { ... };
($idx:literal, $start:literal .. $(,)?) => { ... };
($idx:literal, .. $end:literal $(,)?) => { ... };
($start1:literal .. $end1:literal, $start2:literal .. $end2:literal $(,)?) => { ... };
($idx:literal, $start:literal .. $end:literal $(,)?) => { ... };
($start:literal .. $end:literal, $idx:literal $(,)?) => { ... };
($idx:literal, .. $(,)?) => { ... };
(.., $idx:literal $(,)?) => { ... };
(.., .. $(,)?) => { ... };
($expr:expr) => { ... };
($expr1:expr, $expr2:expr $(,)?) => { ... };
($expr1:expr, $expr2:expr, $expr3:expr $(,)?) => { ... };
($expr1:expr, $expr2:expr, $expr3:expr, $expr4:expr $(,)?) => { ... };
(None) => { ... };
(None, $expr:expr $(,)?) => { ... };
($expr:expr, None $(,)?) => { ... };
(None, $idx:literal $(,)?) => { ... };
($idx:literal, None $(,)?) => { ... };
(None, .. $(,)?) => { ... };
(.., None $(,)?) => { ... };
($($expr:expr),+ $(,)?) => { ... };
}Expand description
Creates slice specifications for tensor slicing operations.
The s! macro provides a convenient syntax for creating SliceSpecs that can be
used with tensor slicing operations. It supports a wide variety of slicing patterns
including individual indices, ranges, stepped ranges, inclusive ranges, and new axis
insertion for dimension expansion.
§Syntax Patterns
§Basic Indexing
s!()- Empty slice specifications!(0)- Single index at position 0s!(0, 1)- Multiple indices for multi-dimensional tensors
§Range Slicing
s!(1..4)- Range from 1 to 4 (exclusive)s!(1..=4)- Inclusive range from 1 to 4s!(1..)- Range from 1 to ends!(..4)- Range from start to 4s!(..)- Full range (all elements)
§Stepped Ranges
s!(0..10; 2)- Range with step size 2s!(..;3)- Full range with step size 3s!(1..=10;2)- Inclusive range with step
§Multi-dimensional Slicing
s!(0, 1..3)- Index in first dimension, range in seconds!(1..3, 2..5)- Ranges in multiple dimensionss!(.., 0)- Full range in first dimensions, index in last
§New Axis Insertion
s!(None)- Insert new axiss!(None, 0)- Insert new axis, then indexs!(0, None)- Index, then insert new axis
§Parameters
The macro accepts various input patterns:
- Literal integers: Direct indexing (e.g.,
0,1,-1) - Range expressions: Various range types with optional steps
- None: For new axis insertion
- General expressions: Any expression that implements
Into<SliceElem>
§Returns
Returns a SliceSpecs containing the slice elements that can be used
with tensor slicing methods like Tensor::slice and TensorView::slice.
§Examples
§Basic Indexing
use slsl::{s, Tensor};
let tensor = Tensor::zeros::<f32>([4, 5])?;
// Single index - selects row 1
let row = tensor.slice(s!(1));
assert_eq!(row.shape().as_slice(), &[5]);
// Two indices - selects element at (1, 2)
let element = tensor.slice(s!(1, 2));
assert_eq!(element.shape().as_slice(), &[]);§Range Slicing
use slsl::{s, Tensor};
let tensor = Tensor::zeros::<f32>([6, 8])?;
// Range slice - rows 1 to 4 (exclusive)
let rows = tensor.slice(s!(1..4));
assert_eq!(rows.shape().as_slice(), &[3]); // Takes only the first dimension slice
// For 2D slicing, need to specify both dimensions
let rows_2d = tensor.slice(s!(1..4, ..));
assert_eq!(rows_2d.shape().as_slice(), &[3, 8]);
// Inclusive range
let rows_inc = tensor.slice(s!(1..=4));
assert_eq!(rows_inc.shape().as_slice(), &[4]);
// From start to index 3
let start = tensor.slice(s!(..3));
assert_eq!(start.shape().as_slice(), &[3]);§Stepped Ranges
use slsl::{s, Tensor};
let tensor = Tensor::zeros::<f32>([12])?;
// Every second element from 0 to 8
let stepped = tensor.slice(s!(0..8; 2));
assert_eq!(stepped.shape().as_slice(), &[4]);
// Every third element from start to end
let full_stepped = tensor.slice(s!(..;3));
assert_eq!(full_stepped.shape().as_slice(), &[4]); // [0, 3, 6, 9]§Multi-dimensional Slicing
use slsl::{s, Tensor};
let tensor = Tensor::zeros::<f32>([4, 6, 8])?;
// Mixed index and range - selects element 1 from first dim, range from second dim
let mixed = tensor.slice(s!(1, 2..5));
assert_eq!(mixed.shape().as_slice(), &[3]); // Results in 1D tensor
// Multiple ranges - keeps specified ranges from first two dimensions
let ranges = tensor.slice(s!(1..3, 2..4));
assert_eq!(ranges.shape().as_slice(), &[2, 2]); // Results in 2D tensor
// Full range in first dimension, index in second
let partial = tensor.slice(s!(.., 3));
assert_eq!(partial.shape().as_slice(), &[4]); // Results in 1D tensor§New Axis Insertion
use slsl::{s, Tensor};
let tensor = Tensor::zeros::<f32>([4, 5])?;
// Insert new axis at the beginning
let expanded = tensor.slice(s!(None, .., ..));
assert_eq!(expanded.shape().as_slice(), &[1, 4, 5]);
// Insert new axis in the middle
let middle = tensor.slice(s!(.., None, ..));
assert_eq!(middle.shape().as_slice(), &[4, 1, 5]);§Advanced Patterns
use slsl::{s, Tensor};
let tensor = Tensor::zeros::<f32>([8, 10])?;
// Complex multi-dimensional slicing
let complex = tensor.slice(s!(1..6; 2, 2..8));
assert_eq!(complex.shape().as_slice(), &[3, 6]); // Every 2nd row from 1-6, cols 2-8
// Negative indexing (from end)
let from_end = tensor.slice(s!(-2, ..));
assert_eq!(from_end.shape().as_slice(), &[10]); // Second-to-last row§Performance Notes
- The macro generates efficient slice specifications at compile time
- Multiple literal patterns are optimized for common use cases
- Complex expressions are handled through the general case conversion
- Range operations with step=1 have optimized implementations
§See Also
SliceElem- Individual slice element typesSliceSpecs- Collection of slice elementsTensor::slice- Apply slice to owned tensorTensorView::slice- Apply slice to tensor view