s

Macro s 

Source
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 specification
  • s!(0) - Single index at position 0
  • s!(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 4
  • s!(1..) - Range from 1 to end
  • s!(..4) - Range from start to 4
  • s!(..) - Full range (all elements)

§Stepped Ranges

  • s!(0..10; 2) - Range with step size 2
  • s!(..;3) - Full range with step size 3
  • s!(1..=10;2) - Inclusive range with step

§Multi-dimensional Slicing

  • s!(0, 1..3) - Index in first dimension, range in second
  • s!(1..3, 2..5) - Ranges in multiple dimensions
  • s!(.., 0) - Full range in first dimensions, index in last

§New Axis Insertion

  • s!(None) - Insert new axis
  • s!(None, 0) - Insert new axis, then index
  • s!(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