use std::collections::VecDeque;
pub fn rolling_min_deque(data: &[f64], window: usize) -> Vec<f64> {
let n = data.len();
if window == 0 || window > n {
return vec![f64::NAN; n];
}
let mut result = vec![f64::NAN; n];
let mut deque: VecDeque<(usize, f64)> = VecDeque::with_capacity(window);
for i in 0..n {
while let Some(&(idx, _)) = deque.front() {
if idx <= i.saturating_sub(window) {
deque.pop_front();
} else {
break;
}
}
while let Some(&(_, val)) = deque.back() {
if val >= data[i] {
deque.pop_back();
} else {
break;
}
}
deque.push_back((i, data[i]));
if i >= window - 1 {
result[i] = deque.front().unwrap().1;
}
}
result
}
pub fn rolling_max_deque(data: &[f64], window: usize) -> Vec<f64> {
let n = data.len();
if window == 0 || window > n {
return vec![f64::NAN; n];
}
let mut result = vec![f64::NAN; n];
let mut deque: VecDeque<(usize, f64)> = VecDeque::with_capacity(window);
for i in 0..n {
while let Some(&(idx, _)) = deque.front() {
if idx <= i.saturating_sub(window) {
deque.pop_front();
} else {
break;
}
}
while let Some(&(_, val)) = deque.back() {
if val <= data[i] {
deque.pop_back();
} else {
break;
}
}
deque.push_back((i, data[i]));
if i >= window - 1 {
result[i] = deque.front().unwrap().1;
}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_rolling_min_max_deque() {
let data = vec![5.0, 3.0, 7.0, 2.0, 9.0, 1.0, 8.0];
let mins = rolling_min_deque(&data, 3);
let maxs = rolling_max_deque(&data, 3);
assert_eq!(mins[2], 3.0); assert_eq!(mins[3], 2.0); assert_eq!(mins[4], 2.0); assert_eq!(mins[5], 1.0);
assert_eq!(maxs[2], 7.0); assert_eq!(maxs[3], 7.0); assert_eq!(maxs[4], 9.0); assert_eq!(maxs[5], 9.0); }
}