haar_lib/ds/
cumulative_sum_2d.rs1pub use crate::algebra::traits::Group;
4use std::ops::{Index, Range};
5
6#[derive(Debug, Clone, PartialEq, Eq, Default, Hash)]
8pub struct CumulativeSum2D<G: Group> {
9 group: G,
10 data: Vec<Vec<G::Element>>,
11}
12
13#[derive(Debug, Clone, PartialEq, Eq, Default, Hash)]
15pub struct CumulativeSum2DBuilder<G: Group> {
16 group: G,
17 data: Vec<Vec<G::Element>>,
18 n: usize,
19 m: usize,
20}
21
22impl<G: Group> CumulativeSum2D<G>
23where
24 G::Element: Copy,
25{
26 pub fn fold_2d(
28 &self,
29 Range { start: l, end: r }: Range<usize>,
30 Range { start: d, end: u }: Range<usize>,
31 ) -> G::Element {
32 let g = &self.group;
33 let a = g.inv(self.data[l][u]);
34 let b = g.inv(self.data[r][d]);
35 let c = self.data[l][d];
36 let d = self.data[r][u];
37
38 g.fold_m([a, b, c, d])
39 }
40}
41
42impl<G: Group> Index<(usize, usize)> for CumulativeSum2D<G> {
43 type Output = G::Element;
44
45 fn index(&self, (i, j): (usize, usize)) -> &Self::Output {
46 &self.data[i][j]
47 }
48}
49
50impl<G: Group> CumulativeSum2DBuilder<G>
51where
52 G::Element: Copy,
53{
54 pub fn new(group: G, n: usize, m: usize) -> Self {
56 Self {
57 data: vec![vec![group.id(); m + 1]; n + 1],
58 group,
59 n,
60 m,
61 }
62 }
63
64 pub fn assign(&mut self, i: usize, j: usize, value: G::Element) {
66 self.data[i + 1][j + 1] = value;
67 }
68
69 pub fn update(&mut self, i: usize, j: usize, value: G::Element) {
71 self.data[i + 1][j + 1] = self.group.op(self.data[i + 1][j + 1], value);
72 }
73
74 pub fn build(self) -> CumulativeSum2D<G> {
76 let mut data = self.data;
77 let group = self.group;
78
79 for i in 1..=self.n {
80 for j in 0..=self.m {
81 data[i][j] = group.op(data[i][j], data[i - 1][j]);
82 }
83 }
84 for data in data.iter_mut().take(self.n + 1) {
85 for j in 1..=self.m {
86 data[j] = group.op(data[j], data[j - 1]);
87 }
88 }
89
90 CumulativeSum2D { group, data }
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97 use crate::algebra::sum::*;
98 use my_testtools::*;
99 use rand::Rng;
100
101 #[test]
102 fn test() {
103 let mut rng = rand::thread_rng();
104
105 let n = 20;
106 let m = 30;
107
108 let g = Sum::<i32>::new();
109 let mut csb = CumulativeSum2DBuilder::new(g, n, m);
110
111 let mut other = vec![vec![g.id(); m]; n];
112
113 for _ in 0..1000 {
114 let i = rng.gen_range(0..n);
115 let j = rng.gen_range(0..m);
116 let x = rng.gen_range(-1000..=1000);
117
118 csb.update(i, j, x);
119 g.op_assign_r(&mut other[i][j], x);
120 }
121
122 let cs = csb.build();
123
124 for _ in 0..100 {
125 let lr = rand_range(&mut rng, 0..n);
126 let du = rand_range(&mut rng, 0..m);
127
128 let ans = other[lr.clone()]
129 .iter()
130 .map(|v| v[du.clone()].iter().cloned().fold_m(&g))
131 .fold_m(&g);
132
133 assert_eq!(cs.fold_2d(lr, du), ans);
134 }
135 }
136}