haar_lib/ds/
cumulative_sum_1d.rs1pub use crate::algebra::traits::Group;
4use std::ops::{Index, Range};
5
6#[derive(Debug, Clone, PartialEq, Eq, Default, Hash)]
8pub struct CumulativeSum1D<G: Group> {
9 group: G,
10 data: Vec<G::Element>,
11}
12
13#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
15pub struct CumulativeSum1DBuilder<G: Group> {
16 group: G,
17 data: Vec<G::Element>,
18}
19
20impl<G: Group> CumulativeSum1D<G>
21where
22 G::Element: Copy,
23{
24 pub fn fold(&self, Range { start: l, end: r }: Range<usize>) -> G::Element {
26 self.group.op(self.data[r], self.group.inv(self.data[l]))
27 }
28}
29
30impl<G: Group> Index<usize> for CumulativeSum1D<G> {
31 type Output = G::Element;
32
33 fn index(&self, i: usize) -> &Self::Output {
34 &self.data[i]
35 }
36}
37
38impl<G: Group> CumulativeSum1DBuilder<G>
39where
40 G::Element: Copy,
41{
42 pub fn new(group: G, n: usize) -> Self {
44 Self {
45 data: vec![group.id(); n + 1],
46 group,
47 }
48 }
49
50 pub fn assign(&mut self, i: usize, value: G::Element) {
52 self.data[i + 1] = value;
53 }
54
55 pub fn update(&mut self, i: usize, value: G::Element) {
57 self.data[i + 1] = self.group.op(self.data[i + 1], value);
58 }
59
60 pub fn build(self) -> CumulativeSum1D<G> {
62 let group = self.group;
63 let data = self
64 .data
65 .iter()
66 .scan(group.id(), |st, &x| {
67 *st = group.op(*st, x);
68 Some(*st)
69 })
70 .collect::<Vec<_>>();
71
72 CumulativeSum1D { group, data }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use crate::algebra::sum::*;
80 use my_testtools::*;
81 use rand::Rng;
82
83 #[test]
84 fn test() {
85 let mut rng = rand::thread_rng();
86
87 let n = 20;
88 let g = Sum::<i32>::new();
89 let mut csb = CumulativeSum1DBuilder::new(g, n);
90
91 let mut other = vec![g.id(); n];
92
93 for _ in 0..1000 {
94 let i = rng.gen_range(0..n);
95 let x = rng.gen_range(-1000..=1000);
96
97 csb.update(i, x);
98 g.op_assign_r(&mut other[i], x);
99 }
100
101 let cs = csb.build();
102
103 for _ in 0..100 {
104 let range = rand_range(&mut rng, 0..n);
105 let ans = other[range.clone()].iter().cloned().fold_m(&g);
106 assert_eq!(cs.fold(range), ans);
107 }
108 }
109}