sliding_window_aggregation/
lib.rs1pub struct SWAg<T, F> {
5 back: Vec<T>,
6 back_agg: Vec<T>,
7 front: Vec<T>,
8 front_agg: Vec<T>,
9 f: F,
10}
11
12impl<T: Copy, F: Fn(T, T) -> T> SWAg<T, F> {
13 pub fn new(f: F) -> Self {
14 SWAg {
15 back: Vec::new(),
16 back_agg: Vec::new(),
17 front: Vec::new(),
18 front_agg: Vec::new(),
19 f: f,
20 }
21 }
22 pub fn fold_all(&self) -> Option<T> {
23 match (self.back_agg.last(), self.front_agg.last()) {
24 (None, None) => None,
25 (None, x) => x.cloned(),
26 (x, None) => x.cloned(),
27 (Some(&x), Some(&y)) => Some((self.f)(x, y)),
28 }
29 }
30 pub fn push_back(&mut self, x: T) {
31 let last = self.front_agg.last().cloned();
32 self.front.push(x);
33 self.front_agg.push(match last {
34 None => x,
35 Some(y) => (self.f)(y, x),
36 });
37 }
38 pub fn pop_front(&mut self) -> Option<T> {
39 match self.back.pop() {
40 Some(x) => return Some(x),
41 None => (),
42 };
43 std::mem::swap(&mut self.front, &mut self.back);
44 self.back.reverse();
45 let returned = self.back.pop();
46 let len = self.back.len();
47 self.back_agg = Vec::with_capacity(self.back.len());
48 if len > 0 {
49 self.back_agg.push(self.back[0]);
50 let mut cur = self.back[0];
51 for i in 1..len {
52 cur = (self.f)(self.back[i], cur);
53 self.back_agg.push(cur);
54 }
55 }
56 self.front = Vec::new();
57 self.front_agg = Vec::new();
58 returned
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65 #[test]
66 fn fold_all_works() {
67 let mut swag = SWAg::<i32, _>::new(|x, y| x + y);
68 swag.push_back(3);
69 swag.push_back(4);
70 swag.push_back(1);
71 assert_eq!(swag.fold_all(), Some(8));
72 }
73 #[test]
74 fn fold_all_not_commutative_works() {
75 let mut swag = SWAg::<(i32, i32), _>::new(|(x, b), (y, c)| (c * x + y, b * c));
76 swag.push_back((3, 10));
77 swag.push_back((4, 10));
78 swag.push_back((1, 10));
79 assert_eq!(swag.fold_all(), Some((341, 1000)));
80 }
81 #[test]
82 fn fold_all_with_pop_front_works() {
83 let mut swag = SWAg::<(i32, i32), _>::new(|(x, b), (y, c)| (c * x + y, b * c));
84 swag.push_back((3, 10));
85 swag.push_back((4, 10));
86 swag.push_back((5, 10));
87 swag.push_back((6, 10));
88 assert_eq!(swag.pop_front(), Some((3, 10))); swag.push_back((1, 10)); assert_eq!(swag.fold_all(), Some((4561, 10000)));
91 }
92}