shape_runtime/simd_rolling/
minmax.rs1use std::collections::VecDeque;
4
5pub fn rolling_min_deque(data: &[f64], window: usize) -> Vec<f64> {
14 let n = data.len();
15
16 if window == 0 || window > n {
17 return vec![f64::NAN; n];
18 }
19
20 let mut result = vec![f64::NAN; n];
21 let mut deque: VecDeque<(usize, f64)> = VecDeque::with_capacity(window);
23
24 for i in 0..n {
25 while let Some(&(idx, _)) = deque.front() {
27 if idx <= i.saturating_sub(window) {
28 deque.pop_front();
29 } else {
30 break;
31 }
32 }
33
34 while let Some(&(_, val)) = deque.back() {
36 if val >= data[i] {
37 deque.pop_back();
38 } else {
39 break;
40 }
41 }
42
43 deque.push_back((i, data[i]));
44
45 if i >= window - 1 {
46 result[i] = deque.front().unwrap().1;
47 }
48 }
49
50 result
51}
52
53pub fn rolling_max_deque(data: &[f64], window: usize) -> Vec<f64> {
59 let n = data.len();
60
61 if window == 0 || window > n {
62 return vec![f64::NAN; n];
63 }
64
65 let mut result = vec![f64::NAN; n];
66 let mut deque: VecDeque<(usize, f64)> = VecDeque::with_capacity(window);
68
69 for i in 0..n {
70 while let Some(&(idx, _)) = deque.front() {
72 if idx <= i.saturating_sub(window) {
73 deque.pop_front();
74 } else {
75 break;
76 }
77 }
78
79 while let Some(&(_, val)) = deque.back() {
81 if val <= data[i] {
82 deque.pop_back();
83 } else {
84 break;
85 }
86 }
87
88 deque.push_back((i, data[i]));
89
90 if i >= window - 1 {
91 result[i] = deque.front().unwrap().1;
92 }
93 }
94
95 result
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_rolling_min_max_deque() {
104 let data = vec![5.0, 3.0, 7.0, 2.0, 9.0, 1.0, 8.0];
105
106 let mins = rolling_min_deque(&data, 3);
107 let maxs = rolling_max_deque(&data, 3);
108
109 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); }
119}