pub fn windowed_view(ts: &[f64], window_size: usize, window_step: usize) -> Vec<Vec<f64>> {
assert!(window_size > 0, "window_size must be positive");
assert!(window_step > 0, "window_step must be positive");
assert!(
window_size <= ts.len(),
"window_size ({window_size}) must not exceed time series length ({})",
ts.len()
);
(0..=ts.len() - window_size)
.step_by(window_step)
.map(|i| ts[i..i + window_size].to_vec())
.collect()
}
pub fn windowed_view_refs(ts: &[f64], window_size: usize, window_step: usize) -> Vec<&[f64]> {
assert!(window_size > 0, "window_size must be positive");
assert!(window_step > 0, "window_step must be positive");
assert!(
window_size <= ts.len(),
"window_size ({window_size}) must not exceed time series length ({})",
ts.len()
);
(0..=ts.len() - window_size)
.step_by(window_step)
.map(|i| &ts[i..i + window_size])
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic() {
let ts = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let windows = windowed_view(&ts, 3, 1);
assert_eq!(
windows,
vec![
vec![1.0, 2.0, 3.0],
vec![2.0, 3.0, 4.0],
vec![3.0, 4.0, 5.0],
]
);
}
#[test]
fn test_step_2() {
let ts = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let windows = windowed_view(&ts, 3, 2);
assert_eq!(windows, vec![vec![1.0, 2.0, 3.0], vec![3.0, 4.0, 5.0],]);
}
#[test]
fn test_full_window() {
let ts = vec![1.0, 2.0, 3.0];
let windows = windowed_view(&ts, 3, 1);
assert_eq!(windows, vec![vec![1.0, 2.0, 3.0]]);
}
#[test]
fn test_refs() {
let ts = vec![1.0, 2.0, 3.0, 4.0];
let refs = windowed_view_refs(&ts, 2, 1);
assert_eq!(refs.len(), 3);
assert_eq!(refs[0], &[1.0, 2.0]);
assert_eq!(refs[2], &[3.0, 4.0]);
}
#[test]
#[should_panic(expected = "window_size must be positive")]
fn test_zero_window() {
windowed_view(&[1.0], 0, 1);
}
#[test]
#[should_panic(expected = "window_size")]
fn test_window_too_large() {
windowed_view(&[1.0, 2.0], 3, 1);
}
}