Skip to main content

SliceBuilder

Struct SliceBuilder 

Source
pub struct SliceBuilder<'a> { /* private fields */ }
Expand description

Builder for tensor slicing (RFC-008 §10). This is the canonical API.

Create via Tensor::slice; finish with .build().

§Examples

use matten::Tensor;

let t = Tensor::new(vec![1.0,2.0,3.0,4.0,5.0,6.0], &[2, 3]);

// First row: index axis 0, keep all of axis 1
let row = t.slice().index(0).all().build().unwrap();
assert_eq!(row.shape(), &[3]);
assert_eq!(row.as_slice(), &[1.0, 2.0, 3.0]);

// First two rows, all columns
let top = t.slice().range(0..2).all().build().unwrap();
assert_eq!(top.shape(), &[2, 3]);

Implementations§

Source§

impl<'a> SliceBuilder<'a>

Source

pub fn all(self) -> Self

Selects all elements along the next axis.

Examples found in repository?
examples/54_pairwise_distance.rs (line 40)
34fn main() {
35    let points = Tensor::new(vec![0.0, 0.0, 3.0, 4.0, 6.0, 0.0], &[3, 2]);
36
37    let dists = pairwise_euclidean(&points);
38    println!("pairwise distances:");
39    for i in 0..3 {
40        let row = dists.slice().index(i).all().build().unwrap();
41        println!("  row {i}: {:?}", row.as_slice());
42    }
43
44    // (0,0)→(3,4) = 5, (3,4)→(6,0) = 5, (0,0)→(6,0) = 6
45    assert!((dists.get(&[0, 1]).unwrap() - 5.0).abs() < 1e-9);
46    assert!((dists.get(&[1, 2]).unwrap() - 5.0).abs() < 1e-9);
47    assert!((dists.get(&[0, 2]).unwrap() - 6.0).abs() < 1e-9);
48    println!("Pairwise distances: OK");
49}
More examples
Hide additional examples
examples/08_slicing_builder.rs (line 14)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let t = Tensor::new((1..=12).map(|x| x as f64).collect(), &[3, 4]);
11    println!("tensor   {t:?}");
12
13    // First row (index 0, axis removed from output shape)
14    let row0 = t.slice().index(0).all().build()?;
15    println!("row 0    {row0:?}"); // shape [4]
16
17    // First two rows, all columns
18    let top2 = t.slice().range(0..2).all().build()?;
19    println!("top 2    {top2:?}"); // shape [2,4]
20
21    // All rows, columns 1..3
22    let cols = t.slice().all().range(1..3).build()?;
23    println!("cols 1:3 {cols:?}"); // shape [3,2]
24
25    // Single element -> scalar
26    let elem = t.slice().index(1).index(2).build()?;
27    assert!(elem.is_scalar());
28    println!("t[1,2]   {elem:?}");
29
30    Ok(())
31}
examples/09_slice_str.rs (line 25)
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11    let t = Tensor::new((1..=12).map(|x| x as f64).collect(), &[3, 4]);
12
13    println!("\"0, :\"    = {:?}", t.slice_str("0, :")?);
14    println!("\"0:2, :\" = {:?}", t.slice_str("0:2, :")?);
15    println!("\":, 1:3\" = {:?}", t.slice_str(":, 1:3")?);
16
17    // Whitespace is ignored
18    let a = t.slice_str("0:2, :")?;
19    let b = t.slice_str(" 0:2 , : ")?;
20    assert_eq!(a, b);
21    println!("whitespace-insensitive: OK");
22
23    // builder and slice_str agree
24    let from_str = t.slice_str("0:2, :")?;
25    let from_builder = t.slice().range(0..2).all().build()?;
26    assert_eq!(from_str, from_builder);
27    println!("builder == slice_str: OK");
28
29    // Malformed specs never panic
30    println!("bad spec: {:?}", t.slice_str("0::")); // Err
31
32    Ok(())
33}
examples/52_minmax_scaling.rs (line 26)
7fn main() {
8    let data = Tensor::new(
9        vec![1.0, 10.0, 100.0, 2.0, 20.0, 200.0, 3.0, 30.0, 300.0],
10        &[3, 3],
11    );
12
13    // Column min and max using axis reductions
14    let col_min = data.min_axis(0);
15    let col_max = data.max_axis(0);
16    let range = &col_max - &col_min;
17
18    // Broadcast: (data - min) / (max - min)
19    let scaled = &(&data - &col_min) / &range;
20
21    println!("col_min  = {:?}", col_min.as_slice());
22    println!("col_max  = {:?}", col_max.as_slice());
23    println!("scaled shape = {:?}", scaled.shape());
24
25    // First row should be all 0.0, last row all 1.0
26    let row0 = scaled.slice().index(0).all().build().unwrap();
27    let row2 = scaled.slice().index(2).all().build().unwrap();
28    assert!(row0.as_slice().iter().all(|&v| (v - 0.0).abs() < 1e-10));
29    assert!(row2.as_slice().iter().all(|&v| (v - 1.0).abs() < 1e-10));
30    println!("Min-max scaling: OK");
31}
examples/12_boundary_error_handling.rs (line 45)
10fn main() {
11    // ── shape/data mismatch ──────────────────────────────────────────────
12    match Tensor::try_new(vec![1.0, 2.0], &[3]) {
13        Err(MattenError::Shape { operation, message }) => {
14            println!("[Shape]  {operation}: {message}")
15        }
16        other => println!("{other:?}"),
17    }
18
19    // ── malformed JSON ───────────────────────────────────────────────────
20    match Tensor::from_json(r#"[[1.0,"text"]]"#) {
21        Err(MattenError::Parse { format, message }) => println!("[Parse/{format}]  {message}"),
22        other => println!("{other:?}"),
23    }
24
25    // ── ragged JSON array ────────────────────────────────────────────────
26    match Tensor::from_json("[[1.0,2.0],[3.0]]") {
27        Err(MattenError::Parse { format, message }) => println!("[Parse/{format}]  {message}"),
28        other => println!("{other:?}"),
29    }
30
31    // ── non-numeric CSV field ────────────────────────────────────────────
32    match Tensor::load_csv("examples/data/malformed_numeric.csv") {
33        Err(MattenError::Parse { format, message }) => println!("[Parse/{format}]  {message}"),
34        other => println!("{other:?}"),
35    }
36
37    // ── missing file ─────────────────────────────────────────────────────
38    match Tensor::load_json("/no/such/file.json") {
39        Err(MattenError::Io { path, source }) => println!("[Io]  {}: {source}", path.display()),
40        other => println!("{other:?}"),
41    }
42
43    // ── slice out of range ───────────────────────────────────────────────
44    let t = Tensor::new(vec![1.0, 2.0, 3.0, 4.0], &[2, 2]);
45    match t.slice().index(5).all().build() {
46        Err(MattenError::Slice { message, .. }) => println!("[Slice]  {message}"),
47        other => println!("{other:?}"),
48    }
49
50    println!("All boundary errors handled gracefully — no panics.");
51}
Source

pub fn index(self, index: usize) -> Self

Selects a single element along the next axis. That axis is removed from the output shape.

Examples found in repository?
examples/54_pairwise_distance.rs (line 40)
34fn main() {
35    let points = Tensor::new(vec![0.0, 0.0, 3.0, 4.0, 6.0, 0.0], &[3, 2]);
36
37    let dists = pairwise_euclidean(&points);
38    println!("pairwise distances:");
39    for i in 0..3 {
40        let row = dists.slice().index(i).all().build().unwrap();
41        println!("  row {i}: {:?}", row.as_slice());
42    }
43
44    // (0,0)→(3,4) = 5, (3,4)→(6,0) = 5, (0,0)→(6,0) = 6
45    assert!((dists.get(&[0, 1]).unwrap() - 5.0).abs() < 1e-9);
46    assert!((dists.get(&[1, 2]).unwrap() - 5.0).abs() < 1e-9);
47    assert!((dists.get(&[0, 2]).unwrap() - 6.0).abs() < 1e-9);
48    println!("Pairwise distances: OK");
49}
More examples
Hide additional examples
examples/08_slicing_builder.rs (line 14)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let t = Tensor::new((1..=12).map(|x| x as f64).collect(), &[3, 4]);
11    println!("tensor   {t:?}");
12
13    // First row (index 0, axis removed from output shape)
14    let row0 = t.slice().index(0).all().build()?;
15    println!("row 0    {row0:?}"); // shape [4]
16
17    // First two rows, all columns
18    let top2 = t.slice().range(0..2).all().build()?;
19    println!("top 2    {top2:?}"); // shape [2,4]
20
21    // All rows, columns 1..3
22    let cols = t.slice().all().range(1..3).build()?;
23    println!("cols 1:3 {cols:?}"); // shape [3,2]
24
25    // Single element -> scalar
26    let elem = t.slice().index(1).index(2).build()?;
27    assert!(elem.is_scalar());
28    println!("t[1,2]   {elem:?}");
29
30    Ok(())
31}
examples/52_minmax_scaling.rs (line 26)
7fn main() {
8    let data = Tensor::new(
9        vec![1.0, 10.0, 100.0, 2.0, 20.0, 200.0, 3.0, 30.0, 300.0],
10        &[3, 3],
11    );
12
13    // Column min and max using axis reductions
14    let col_min = data.min_axis(0);
15    let col_max = data.max_axis(0);
16    let range = &col_max - &col_min;
17
18    // Broadcast: (data - min) / (max - min)
19    let scaled = &(&data - &col_min) / &range;
20
21    println!("col_min  = {:?}", col_min.as_slice());
22    println!("col_max  = {:?}", col_max.as_slice());
23    println!("scaled shape = {:?}", scaled.shape());
24
25    // First row should be all 0.0, last row all 1.0
26    let row0 = scaled.slice().index(0).all().build().unwrap();
27    let row2 = scaled.slice().index(2).all().build().unwrap();
28    assert!(row0.as_slice().iter().all(|&v| (v - 0.0).abs() < 1e-10));
29    assert!(row2.as_slice().iter().all(|&v| (v - 1.0).abs() < 1e-10));
30    println!("Min-max scaling: OK");
31}
examples/12_boundary_error_handling.rs (line 45)
10fn main() {
11    // ── shape/data mismatch ──────────────────────────────────────────────
12    match Tensor::try_new(vec![1.0, 2.0], &[3]) {
13        Err(MattenError::Shape { operation, message }) => {
14            println!("[Shape]  {operation}: {message}")
15        }
16        other => println!("{other:?}"),
17    }
18
19    // ── malformed JSON ───────────────────────────────────────────────────
20    match Tensor::from_json(r#"[[1.0,"text"]]"#) {
21        Err(MattenError::Parse { format, message }) => println!("[Parse/{format}]  {message}"),
22        other => println!("{other:?}"),
23    }
24
25    // ── ragged JSON array ────────────────────────────────────────────────
26    match Tensor::from_json("[[1.0,2.0],[3.0]]") {
27        Err(MattenError::Parse { format, message }) => println!("[Parse/{format}]  {message}"),
28        other => println!("{other:?}"),
29    }
30
31    // ── non-numeric CSV field ────────────────────────────────────────────
32    match Tensor::load_csv("examples/data/malformed_numeric.csv") {
33        Err(MattenError::Parse { format, message }) => println!("[Parse/{format}]  {message}"),
34        other => println!("{other:?}"),
35    }
36
37    // ── missing file ─────────────────────────────────────────────────────
38    match Tensor::load_json("/no/such/file.json") {
39        Err(MattenError::Io { path, source }) => println!("[Io]  {}: {source}", path.display()),
40        other => println!("{other:?}"),
41    }
42
43    // ── slice out of range ───────────────────────────────────────────────
44    let t = Tensor::new(vec![1.0, 2.0, 3.0, 4.0], &[2, 2]);
45    match t.slice().index(5).all().build() {
46        Err(MattenError::Slice { message, .. }) => println!("[Slice]  {message}"),
47        other => println!("{other:?}"),
48    }
49
50    println!("All boundary errors handled gracefully — no panics.");
51}
Source

pub fn range<R: IntoSliceRange>(self, range: R) -> Self

Selects a range of elements along the next axis.

Accepts Range, RangeFrom, RangeTo, RangeFull, or RangeInclusive.

Examples found in repository?
examples/56_rolling_windows_basic.rs (line 9)
7fn rolling_sum(t: &Tensor, window: usize) -> Vec<f64> {
8    (0..=(t.len() - window))
9        .map(|i| t.slice().range(i..i + window).build().unwrap().sum())
10        .collect()
11}
12
13fn rolling_max(t: &Tensor, window: usize) -> Vec<f64> {
14    (0..=(t.len() - window))
15        .map(|i| t.slice().range(i..i + window).build().unwrap().max())
16        .collect()
17}
More examples
Hide additional examples
examples/55_moving_average.rs (line 15)
7fn main() {
8    let series = Tensor::from_vec(vec![1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0]);
9    let window = 3usize;
10    let n = series.len();
11
12    // Compute moving averages for windows [0..3], [1..4], ...
13    let mut avgs = Vec::new();
14    for start in 0..=(n - window) {
15        let w = series.slice().range(start..start + window).build().unwrap();
16        avgs.push(w.mean());
17    }
18
19    println!("series = {:?}", series.as_slice());
20    println!("3-pt moving avg = {:?}", avgs);
21    assert_eq!(avgs.len(), n - window + 1);
22    assert!((avgs[0] - 3.0).abs() < 1e-10); // mean(1,3,5) = 3
23    assert!((avgs[1] - 5.0).abs() < 1e-10); // mean(3,5,7) = 5
24    println!("Moving average: OK");
25}
examples/08_slicing_builder.rs (line 18)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let t = Tensor::new((1..=12).map(|x| x as f64).collect(), &[3, 4]);
11    println!("tensor   {t:?}");
12
13    // First row (index 0, axis removed from output shape)
14    let row0 = t.slice().index(0).all().build()?;
15    println!("row 0    {row0:?}"); // shape [4]
16
17    // First two rows, all columns
18    let top2 = t.slice().range(0..2).all().build()?;
19    println!("top 2    {top2:?}"); // shape [2,4]
20
21    // All rows, columns 1..3
22    let cols = t.slice().all().range(1..3).build()?;
23    println!("cols 1:3 {cols:?}"); // shape [3,2]
24
25    // Single element -> scalar
26    let elem = t.slice().index(1).index(2).build()?;
27    assert!(elem.is_scalar());
28    println!("t[1,2]   {elem:?}");
29
30    Ok(())
31}
examples/09_slice_str.rs (line 25)
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11    let t = Tensor::new((1..=12).map(|x| x as f64).collect(), &[3, 4]);
12
13    println!("\"0, :\"    = {:?}", t.slice_str("0, :")?);
14    println!("\"0:2, :\" = {:?}", t.slice_str("0:2, :")?);
15    println!("\":, 1:3\" = {:?}", t.slice_str(":, 1:3")?);
16
17    // Whitespace is ignored
18    let a = t.slice_str("0:2, :")?;
19    let b = t.slice_str(" 0:2 , : ")?;
20    assert_eq!(a, b);
21    println!("whitespace-insensitive: OK");
22
23    // builder and slice_str agree
24    let from_str = t.slice_str("0:2, :")?;
25    let from_builder = t.slice().range(0..2).all().build()?;
26    assert_eq!(from_str, from_builder);
27    println!("builder == slice_str: OK");
28
29    // Malformed specs never panic
30    println!("bad spec: {:?}", t.slice_str("0::")); // Err
31
32    Ok(())
33}
Source

pub fn build(self) -> Result<Tensor, MattenError>

Materialises the slice as an owned Tensor.

§Errors

Returns MattenError::Slice on rank mismatch or out-of-bounds specs.

Examples found in repository?
examples/56_rolling_windows_basic.rs (line 9)
7fn rolling_sum(t: &Tensor, window: usize) -> Vec<f64> {
8    (0..=(t.len() - window))
9        .map(|i| t.slice().range(i..i + window).build().unwrap().sum())
10        .collect()
11}
12
13fn rolling_max(t: &Tensor, window: usize) -> Vec<f64> {
14    (0..=(t.len() - window))
15        .map(|i| t.slice().range(i..i + window).build().unwrap().max())
16        .collect()
17}
More examples
Hide additional examples
examples/54_pairwise_distance.rs (line 40)
34fn main() {
35    let points = Tensor::new(vec![0.0, 0.0, 3.0, 4.0, 6.0, 0.0], &[3, 2]);
36
37    let dists = pairwise_euclidean(&points);
38    println!("pairwise distances:");
39    for i in 0..3 {
40        let row = dists.slice().index(i).all().build().unwrap();
41        println!("  row {i}: {:?}", row.as_slice());
42    }
43
44    // (0,0)→(3,4) = 5, (3,4)→(6,0) = 5, (0,0)→(6,0) = 6
45    assert!((dists.get(&[0, 1]).unwrap() - 5.0).abs() < 1e-9);
46    assert!((dists.get(&[1, 2]).unwrap() - 5.0).abs() < 1e-9);
47    assert!((dists.get(&[0, 2]).unwrap() - 6.0).abs() < 1e-9);
48    println!("Pairwise distances: OK");
49}
examples/55_moving_average.rs (line 15)
7fn main() {
8    let series = Tensor::from_vec(vec![1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0]);
9    let window = 3usize;
10    let n = series.len();
11
12    // Compute moving averages for windows [0..3], [1..4], ...
13    let mut avgs = Vec::new();
14    for start in 0..=(n - window) {
15        let w = series.slice().range(start..start + window).build().unwrap();
16        avgs.push(w.mean());
17    }
18
19    println!("series = {:?}", series.as_slice());
20    println!("3-pt moving avg = {:?}", avgs);
21    assert_eq!(avgs.len(), n - window + 1);
22    assert!((avgs[0] - 3.0).abs() < 1e-10); // mean(1,3,5) = 3
23    assert!((avgs[1] - 5.0).abs() < 1e-10); // mean(3,5,7) = 5
24    println!("Moving average: OK");
25}
examples/08_slicing_builder.rs (line 14)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let t = Tensor::new((1..=12).map(|x| x as f64).collect(), &[3, 4]);
11    println!("tensor   {t:?}");
12
13    // First row (index 0, axis removed from output shape)
14    let row0 = t.slice().index(0).all().build()?;
15    println!("row 0    {row0:?}"); // shape [4]
16
17    // First two rows, all columns
18    let top2 = t.slice().range(0..2).all().build()?;
19    println!("top 2    {top2:?}"); // shape [2,4]
20
21    // All rows, columns 1..3
22    let cols = t.slice().all().range(1..3).build()?;
23    println!("cols 1:3 {cols:?}"); // shape [3,2]
24
25    // Single element -> scalar
26    let elem = t.slice().index(1).index(2).build()?;
27    assert!(elem.is_scalar());
28    println!("t[1,2]   {elem:?}");
29
30    Ok(())
31}
examples/09_slice_str.rs (line 25)
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11    let t = Tensor::new((1..=12).map(|x| x as f64).collect(), &[3, 4]);
12
13    println!("\"0, :\"    = {:?}", t.slice_str("0, :")?);
14    println!("\"0:2, :\" = {:?}", t.slice_str("0:2, :")?);
15    println!("\":, 1:3\" = {:?}", t.slice_str(":, 1:3")?);
16
17    // Whitespace is ignored
18    let a = t.slice_str("0:2, :")?;
19    let b = t.slice_str(" 0:2 , : ")?;
20    assert_eq!(a, b);
21    println!("whitespace-insensitive: OK");
22
23    // builder and slice_str agree
24    let from_str = t.slice_str("0:2, :")?;
25    let from_builder = t.slice().range(0..2).all().build()?;
26    assert_eq!(from_str, from_builder);
27    println!("builder == slice_str: OK");
28
29    // Malformed specs never panic
30    println!("bad spec: {:?}", t.slice_str("0::")); // Err
31
32    Ok(())
33}
examples/52_minmax_scaling.rs (line 26)
7fn main() {
8    let data = Tensor::new(
9        vec![1.0, 10.0, 100.0, 2.0, 20.0, 200.0, 3.0, 30.0, 300.0],
10        &[3, 3],
11    );
12
13    // Column min and max using axis reductions
14    let col_min = data.min_axis(0);
15    let col_max = data.max_axis(0);
16    let range = &col_max - &col_min;
17
18    // Broadcast: (data - min) / (max - min)
19    let scaled = &(&data - &col_min) / &range;
20
21    println!("col_min  = {:?}", col_min.as_slice());
22    println!("col_max  = {:?}", col_max.as_slice());
23    println!("scaled shape = {:?}", scaled.shape());
24
25    // First row should be all 0.0, last row all 1.0
26    let row0 = scaled.slice().index(0).all().build().unwrap();
27    let row2 = scaled.slice().index(2).all().build().unwrap();
28    assert!(row0.as_slice().iter().all(|&v| (v - 0.0).abs() < 1e-10));
29    assert!(row2.as_slice().iter().all(|&v| (v - 1.0).abs() < 1e-10));
30    println!("Min-max scaling: OK");
31}

Auto Trait Implementations§

§

impl<'a> Freeze for SliceBuilder<'a>

§

impl<'a> RefUnwindSafe for SliceBuilder<'a>

§

impl<'a> Send for SliceBuilder<'a>

§

impl<'a> Sync for SliceBuilder<'a>

§

impl<'a> Unpin for SliceBuilder<'a>

§

impl<'a> UnsafeUnpin for SliceBuilder<'a>

§

impl<'a> UnwindSafe for SliceBuilder<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.