1use super::encode::Bits;
2
3#[derive(Debug)]
10pub struct CompressionQueue<const N: usize> {
11 zigzag: [usize; 16],
12 bitcount: [usize; 16],
13 front: usize,
14 len: usize,
15}
16
17impl<const N: usize> CompressionQueue<N> {
18 pub const fn new() -> Self {
22 assert!(N <= 16);
23 CompressionQueue {
24 zigzag: [0; 16],
25 bitcount: [0; 16],
26 front: 0,
27 len: 0,
28 }
29 }
30
31 pub const fn len(&self) -> usize {
35 self.len
36 }
37
38 pub fn is_full(&self) -> bool {
43 self.len >= N
44 }
45
46 pub fn is_empty(&self) -> bool {
51 self.len == 0
52 }
53
54 pub fn push<T: Bits + Sized>(&mut self, value: T) {
59 let index = (self.front + self.len) % 16;
60 unsafe { self.write(index, value) };
61 if self.len < 16 {
62 self.len += 1;
63 } else {
64 self.front = (self.front + 1) % 16;
65 }
66 }
67
68 pub fn pop(&mut self) -> Option<usize> {
73 if self.is_empty() {
74 return None;
75 }
76
77 let value = unsafe { self.value_at(self.front) };
78 self.front = (self.front + 1) % 16;
79 self.len -= 1;
80 Some(value)
81 }
82
83 #[inline(always)]
89 pub fn pop_n<const M: usize>(&mut self) -> [usize; M] {
90 let mut values: [usize; M] = [0; M];
91 for i in 0..M {
92 let index = (self.front + i) % 16;
93 unsafe {
94 *values.get_unchecked_mut(i) = self.value_at(index);
95 }
96 }
97 self.front = (self.front + M) % 16;
98 self.len -= M;
99 values
100 }
101
102 #[inline(always)]
108 pub fn peak_bitcounts<const M: usize>(&mut self) -> [usize; M] {
109 let mut values: [usize; M] = [0; M];
110 for i in 0..M {
111 let index = (self.front + i) % 16;
112 unsafe {
113 *values.get_unchecked_mut(i) = self.count_at(index);
114 }
115 }
116 values
117 }
118
119 unsafe fn value_at(&self, index: usize) -> usize {
127 *self.zigzag.get_unchecked(index)
128 }
129
130 unsafe fn count_at(&self, index: usize) -> usize {
138 *self.bitcount.get_unchecked(index)
139 }
140
141 unsafe fn write<T: Bits + Sized>(&mut self, index: usize, t: T) {
151 let (zbits, zcount) = t.zigzag_bits();
152 *self.zigzag.get_unchecked_mut(index) = zbits;
153 *self.bitcount.get_unchecked_mut(index) = zcount;
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160
161 #[test]
162 fn can_init() {
163 let queue: CompressionQueue<10> = CompressionQueue::new();
164 assert_eq!(queue.len(), 0);
165 assert_eq!(queue.is_full(), false);
166 assert_eq!(queue.is_empty(), true);
167 }
168
169 #[test]
170 fn is_empty_or_full() {
171 let mut queue: CompressionQueue<4> = CompressionQueue::new();
172 assert_eq!(queue.len(), 0);
173 assert_eq!(queue.is_empty(), true);
174 assert_eq!(queue.is_full(), false);
175
176 for i in 0..4 {
178 queue.push(i as i8);
179 assert_eq!(queue.len(), i + 1);
180 assert_eq!(queue.is_empty(), false);
181 assert_eq!(queue.is_full(), i == 3);
182 }
183
184 for i in 0..4 {
186 assert_eq!(queue.pop(), Some((i as i8).zigzag()));
187 assert_eq!(queue.len(), 3 - i);
188 assert_eq!(queue.is_empty(), (i == 3));
189 assert_eq!(queue.is_full(), false);
190 }
191 }
192
193 #[test]
194 fn can_overwrite() {
195 let mut queue: CompressionQueue<4> = CompressionQueue::new();
196
197 for i in 0..4 {
199 queue.push(i as i8);
200 assert_eq!(queue.len(), i + 1);
201 assert_eq!(queue.is_empty(), false);
202 assert_eq!(queue.is_full(), i == 3);
203 }
204
205 for i in 4..8 {
207 queue.push(i as i8);
208 assert_eq!(queue.len(), i + 1);
209 assert_eq!(queue.is_empty(), false);
210 assert_eq!(queue.is_full(), true);
211 }
212
213 for i in 8..20 {
215 queue.push(i as i8);
216 assert_eq!(queue.len(), (i + 1).min(16));
217 assert_eq!(queue.is_empty(), false);
218 assert_eq!(queue.is_full(), true);
219 }
220
221 for j in 0..4 {
223 assert_eq!(queue.pop(), Some(((j + 4) as i8).zigzag()));
224 assert_eq!(queue.len(), 15 - j);
225 assert_eq!(queue.is_empty(), false);
226 assert_eq!(queue.is_full(), true);
227 }
228
229 queue.pop_n::<8>();
231 assert_eq!(queue.len(), 4);
232 assert_eq!(queue.is_empty(), false);
233 assert_eq!(queue.is_full(), true);
234
235 for j in 0..4 {
237 assert_eq!(queue.pop(), Some(((j + 16) as i8).zigzag()));
238 assert_eq!(queue.len(), 3 - j);
239 assert_eq!(queue.is_empty(), (j == 3));
240 assert_eq!(queue.is_full(), false);
241 }
242 }
243
244 #[test]
245 fn fuzz() {
246 use alloc::collections::VecDeque;
247 use rand::Rng;
248
249 let mut rng = rand::thread_rng();
250 let mut std_queue: VecDeque<usize> = VecDeque::new();
251 let mut queue: CompressionQueue<10> = CompressionQueue::new();
252 for _ in 0..10000 {
253 let value = rng.gen::<i32>();
254 let zig_zag_value = value.zigzag();
255 if rng.gen::<bool>() {
256 std_queue.push_back(zig_zag_value as usize);
257 if queue.len() == 16 {
258 assert_eq!(std_queue.pop_front(), queue.pop());
259 }
260 queue.push(value);
261 } else {
262 assert_eq!(std_queue.pop_front(), queue.pop());
263 }
264 assert_eq!(std_queue.len(), queue.len());
265
266 for _ in 0..queue.len() {
267 assert_eq!(std_queue.pop_front(), queue.pop());
268 }
269 }
270 }
271}