1extern crate alloc;
2use alloc::vec;
3use alloc::vec::Vec;
4
5pub struct Front<T: Copy + Default> {
7 zero: T,
8 dx: i32,
9 dy: i32,
10 dz: i32,
11 mask: i32,
12 index: i32,
13 buffer: Vec<T>,
14}
15
16impl<T: Copy + Default> Front<T> {
17 pub fn new(nx: i32, ny: i32, zero: T) -> Self {
19 let dx = 1;
20 let dy = nx + 1;
21 let dz = dy * (ny + 1);
22 let mask = compute_mask(dx + dy + dz);
23 Self {
24 zero,
25 dx,
26 dy,
27 dz,
28 mask,
29 index: 0,
30 buffer: vec![T::default(); (mask + 1) as usize],
31 }
32 }
33
34 #[inline]
36 pub fn get(&self, x: i32, y: i32, z: i32) -> T {
37 let idx = (self.index - self.dx * x - self.dy * y - self.dz * z) & self.mask;
38 self.buffer[idx as usize]
39 }
40
41 #[inline]
43 pub fn push(&mut self, value: T) {
44 self.buffer[(self.index & self.mask) as usize] = value;
45 self.index += 1;
46 }
47
48 pub fn push_n(&mut self, value: T, count: i32) {
50 for _ in 0..count {
51 self.buffer[(self.index & self.mask) as usize] = value;
52 self.index += 1;
53 }
54 }
55
56 pub fn advance(&mut self, x: i32, y: i32, z: i32) {
58 self.push_n(self.zero, self.dx * x + self.dy * y + self.dz * z);
59 }
60}
61
62fn compute_mask(mut n: i32) -> i32 {
64 n -= 1;
65 n |= n >> 1;
66 n |= n >> 2;
67 n |= n >> 4;
68 n |= n >> 8;
69 n |= n >> 16;
70 n
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn init_to_zero() {
79 let f = Front::<u32>::new(4, 4, 0);
80 assert_eq!(f.get(0, 0, 0), 0);
81 assert_eq!(f.get(1, 0, 0), 0);
82 assert_eq!(f.get(0, 1, 0), 0);
83 assert_eq!(f.get(0, 0, 1), 0);
84 }
85
86 #[test]
87 fn push_and_retrieve() {
88 let mut f = Front::<u32>::new(4, 4, 0);
89 f.push(42);
90 assert_eq!(f.get(1, 0, 0), 42);
93 }
94
95 #[test]
96 fn advance_fills_zeros() {
97 let mut f = Front::<u32>::new(4, 4, 0);
98 f.push(99);
99 f.advance(1, 0, 0); assert_eq!(f.get(1, 0, 0), 0);
101 assert_eq!(f.get(2, 0, 0), 99);
103 }
104
105 #[test]
106 fn circular_buffer_wraps() {
107 let mut f = Front::<u32>::new(2, 2, 0);
108 let buf_size = (f.mask + 1) as u32;
109 for i in 0..buf_size * 2 {
111 f.push(i);
112 }
113 let last = buf_size * 2 - 1;
115 assert_eq!(f.get(1, 0, 0), last);
116 }
117}