1#![allow(unused_must_use)]
2
3use crate::bit_vec::*;
4use serde::{Deserialize, Serialize};
5use serde_json;
6use std::borrow::{Borrow, Cow};
7use std::fs::File;
8use std::io::prelude::*;
9
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11pub struct RankSupport<'bv> {
12 pub(crate) bv: Cow<'bv, BitVec>,
13 pub(crate) rs: Vec<BitVec>,
14 pub(crate) rb: Vec<Vec<BitVec>>,
15 pub(crate) rp: Vec<Vec<BitVec>>,
16}
17
18impl<'bv> RankSupport<'bv> {
19 fn compute_rs(bv: &BitVec) -> Vec<BitVec> {
20 let log2n = (bv.size as f64).log2();
21 let super_block_size = BitVecSize((log2n * log2n / 2.0).ceil() as usize);
22 let super_block_space = BitVecSize(((bv.size + 1) as f64).log2().ceil() as usize);
24 let vec_size = (bv.size as f64 / (super_block_size.to_usize() as f64)).ceil() as usize;
25 let mut super_blocks: Vec<u64> = Vec::with_capacity(vec_size);
26 for _ in 0..vec_size {
27 super_blocks.push(0);
28 }
29 let mut count = 0;
31 for i in 0..(vec_size - 1) {
32 for j in 0..super_block_size.to_usize() {
33 count += bv.get_u8(i * super_block_size.to_usize() + j) as u64;
34 }
35 super_blocks[i + 1] = count;
36 }
38 super_blocks
40 .iter()
41 .map(|x| BitVec::from_u64(x.clone(), super_block_space.to_usize()))
42 .collect()
43 }
44 fn compute_rb(bv: &BitVec, rs: &Vec<BitVec>) -> Vec<Vec<BitVec>> {
45 let log2n = (bv.size as f64).log2();
46 let super_block_size = BitVecSize((log2n * log2n / 2.0).ceil() as usize);
47 let block_size = BitVecSize((log2n / 2.0).ceil() as usize);
48 let block_space = BitVecSize(((super_block_size.to_usize()) as f64).log2().ceil() as usize);
50 let vec_size = rs.len();
51 let sub_vec_size = log2n.ceil() as usize;
52 let mut blocks: Vec<Vec<u64>> = Vec::with_capacity(vec_size);
53 for i in 0..vec_size {
54 blocks.push(Vec::with_capacity(sub_vec_size));
55 for _ in 0..sub_vec_size {
56 blocks[i].push(0);
57 }
58 }
59 for i in 0..vec_size {
60 let mut count = 0;
61 for j in 0..(sub_vec_size - 1) {
62 for k in 0..block_size.to_usize() {
63 count += bv
64 .get_u8(i * super_block_size.to_usize() + j * block_size.to_usize() + k)
65 as u64;
66 }
67 blocks[i][j + 1] = count;
68 }
69 }
70 blocks
72 .into_iter()
73 .map(|v| {
74 v.into_iter()
75 .map(|x| BitVec::from_u64(x.clone(), block_space.to_usize()))
76 .collect()
77 })
78 .collect()
79 }
80 fn compute_rp(bv: &BitVec) -> Vec<Vec<BitVec>> {
81 let log2n = (bv.size as f64).log2();
82 let super_block_size = (log2n * log2n / 2.0).ceil() as usize;
83 let block_size = (log2n / 2.0).ceil() as usize;
84 let block_space = (super_block_size as f64).log2().ceil() as usize;
85 let lookup_table_size = 2_usize.pow(block_size as u32);
86 let mut lookup_table: Vec<Vec<u64>> = Vec::with_capacity(lookup_table_size);
87 for _ in 0..lookup_table_size {
88 lookup_table.push(Vec::with_capacity(block_size));
89 }
90 for i in 0..lookup_table_size {
91 for j in 0..block_size {
92 let temp_bv = BitVec::from_u64(i as u64, block_size);
94 let rank = RankSupport::dummy_rankn(&temp_bv, j);
95 lookup_table[i].push(rank);
96 }
97 }
98 lookup_table
100 .into_iter()
101 .map(|v| {
102 v.into_iter()
103 .map(|x| BitVec::from_u64(x, block_space))
104 .collect()
105 })
106 .collect()
107 }
108 pub(in crate) fn compute_index(&mut self) {
109 self.rs = RankSupport::compute_rs(self.bv.borrow());
110 self.rb = RankSupport::compute_rb(self.bv.borrow(), &self.rs);
111 self.rp = RankSupport::compute_rp(self.bv.borrow());
112 }
113 pub(in crate) fn new_with_index_computation(bit_vec: Cow<'bv, BitVec>) -> RankSupport {
114 let bv = bit_vec;
115 let rs = RankSupport::compute_rs(bv.borrow());
116 let rb = RankSupport::compute_rb(bv.borrow(), &rs);
117 let rp = RankSupport::compute_rp(bv.borrow());
118 RankSupport { bv, rs, rb, rp }
119 }
120 pub fn set(&mut self, i: usize) {
121 self.bv.to_mut().set(i);
122 }
123}
124
125impl<'bv> RankSupport<'bv> {
126 pub fn new(bit_vec: &BitVec) -> RankSupport {
127 RankSupport::new_with_index_computation(Cow::Borrowed(bit_vec))
128 }
129 pub fn dummy_rankn(bv: &BitVec, i: usize) -> u64 {
130 let mut rank = 0;
131 for ind in 0..=i {
132 rank += bv.get(ind) as u64;
133 }
134 rank
135 }
136 pub fn rank1(&self, i: u64) -> u64 {
137 let log2n = (self.bv.size as f64).log2();
138 let super_block_size = (log2n * log2n / 2.0).ceil() as usize;
139 let block_size = (log2n / 2.0).ceil() as usize;
140 let super_block_index = (i as usize / super_block_size) as usize;
143 let i = i as usize % super_block_size;
144 let block_index = (i / block_size) as usize;
145 let lookup_rank_index = i % block_size;
146 let value_from_super_block = self.rs[super_block_index].to_u64();
147 let value_from_block = self.rb[super_block_index][block_index].to_u64();
148 let left = super_block_index * super_block_size + block_index * block_size;
149 let right = left + block_size;
150 let lookup_row_index = self.bv.extract(left, right).to_u64() as usize;
151 let value_from_lookup = self.rp[lookup_row_index][lookup_rank_index].to_u64();
152 value_from_super_block + value_from_block + value_from_lookup
160 }
161 pub fn overhead(&self) -> usize {
162 std::mem::size_of_val(&*self.rs)
163 + std::mem::size_of_val(&*self.rb)
164 + std::mem::size_of_val(&*self.rp)
165 }
166 pub fn save(&self, file_name: &str) -> std::io::Result<()> {
167 let serialized = serde_json::to_string(&self)?;
168 let mut file = File::create(file_name)?;
169 file.write_all(serialized.as_bytes())?;
170 Ok(())
171 }
172 pub fn load(file_name: String) -> std::io::Result<RankSupport<'bv>> {
173 let mut file = File::open(file_name)?;
174 let mut contents = String::new();
175 file.read_to_string(&mut contents)?;
176 let deserialized: RankSupport = serde_json::from_str(&contents)?;
177 Ok(deserialized)
178 }
179}
180
181#[cfg(test)]
182mod rank1_tests {
183 use crate::bit_vec::BitVec;
184 use crate::rank_support::RankSupport;
185 #[test]
186 fn small_tests() {
187 for i in 1..=128 {
188 let size = i * 8;
189 let b = BitVec::new_with_random(size);
190 let mut r = RankSupport::new(&b);
191 r.compute_index();
192 for j in 0..b.size {
193 let dummy_res = RankSupport::dummy_rankn(&b, j);
194 let smart_res = r.rank1(j as u64);
195 assert_eq!(
196 dummy_res, smart_res,
197 "<============= Case [size: {}, point: {}] Starts ==============>\n \
198 BV = {}\n\
199 Rank = {}\n\
200 Dummy Rank = {}\n\
201 <============= Case [size: {}, point: {}] Ends ==============>\n",
202 size, j, b, smart_res, dummy_res, size, j
203 );
204 }
205 }
206 }
207 #[test]
208 fn small_tests_two() {
209 for i in 1..=128 {
210 let size = i * 8;
211 let b = BitVec::new_with_random(size);
212 let r = RankSupport::new(&b);
213 for j in 0..b.size {
214 let dummy_res = RankSupport::dummy_rankn(&b, j);
215 let smart_res = r.rank1(j as u64);
216 assert_eq!(
217 dummy_res, smart_res,
218 "<============= Case [size: {}, point: {}] Starts ==============>\n \
219 BV = {}\n\
220 Rank = {}\n\
221 Dummy Rank = {}\n\
222 <============= Case [size: {}, point: {}] Ends ==============>\n",
223 size, j, b, smart_res, dummy_res, size, j
224 );
225 }
226 }
227 }
228 #[test]
229 fn medium_tests() {
230 for i in 128..=160 {
231 let size = i * 128;
232 let b = BitVec::new_with_random(size);
233 let mut r = RankSupport::new(&b);
234 r.compute_index();
235 for j in (0..b.size).step_by(80) {
236 let dummy_res = RankSupport::dummy_rankn(&b, j);
238 let smart_res = r.rank1(j as u64);
239 assert_eq!(
240 dummy_res, smart_res,
241 "<============= Case [size: {}, point: {}] Starts ==============>\n \
242 BV = {}\n\
243 Rank = {}\n\
244 Dummy Rank = {}\n\
245 <============= Case [size: {}, point: {}] Ends ==============>\n",
246 size, j, b, smart_res, dummy_res, size, j
247 );
248 }
249 }
250 }
251 #[test]
252 fn large_tests() {
253 for i in 256..=280 {
254 let size = i * 128;
255 let b = BitVec::new_with_random(size);
256 let mut r = RankSupport::new(&b);
257 r.compute_index();
258 for j in (0..b.size).step_by(250) {
259 let dummy_res = RankSupport::dummy_rankn(&b, j);
261 let smart_res = r.rank1(j as u64);
262 assert_eq!(
263 dummy_res, smart_res,
264 "<============= Case [size: {}, point: {}] Starts ==============>\n \
265 BV = {}\n\
266 Rank = {}\n\
267 Dummy Rank = {}\n\
268 <============= Case [size: {}, point: {}] Ends ==============>\n",
269 size, j, b, smart_res, dummy_res, size, j
270 );
271 }
272 }
273 }
274 #[test]
275 fn very_large_tests() {
276 {
277 let size = 40960;
278 let b = BitVec::new_with_random(size);
279 let mut r = RankSupport::new(&b);
280 r.compute_index();
281 for j in (0..b.size).step_by(250) {
282 let dummy_res = RankSupport::dummy_rankn(&b, j);
283 let smart_res = r.rank1(j as u64);
284 assert_eq!(
285 dummy_res, smart_res,
286 "<============= Case [size: {}, point: {}] Starts ==============>\n \
287 BV = {}\n\
288 Rank = {}\n\
289 Dummy Rank = {}\n\
290 <============= Case [size: {}, point: {}] Ends ==============>\n",
291 size, j, b, smart_res, dummy_res, size, j
292 );
293 }
294 }
295 {
296 let size = 51200;
297 let b = BitVec::new_with_random(size);
298 let mut r = RankSupport::new(&b);
299 r.compute_index();
300 for j in (0..b.size).step_by(250) {
301 let dummy_res = RankSupport::dummy_rankn(&b, j);
302 let smart_res = r.rank1(j as u64);
303 assert_eq!(
304 dummy_res, smart_res,
305 "<============= Case [size: {}, point: {}] Starts ==============>\n \
306 BV = {}\n\
307 Rank = {}\n\
308 Dummy Rank = {}\n\
309 <============= Case [size: {}, point: {}] Ends ==============>\n",
310 size, j, b, smart_res, dummy_res, size, j
311 );
312 }
313 }
314 {
315 let size = 61440;
316 let b = BitVec::new_with_random(size);
317 let mut r = RankSupport::new(&b);
318 r.compute_index();
319 for j in (0..b.size).step_by(250) {
320 let dummy_res = RankSupport::dummy_rankn(&b, j);
321 let smart_res = r.rank1(j as u64);
322 assert_eq!(
323 dummy_res, smart_res,
324 "<============= Case [size: {}, point: {}] Starts ==============>\n \
325 BV = {}\n\
326 Rank = {}\n\
327 Dummy Rank = {}\n\
328 <============= Case [size: {}, point: {}] Ends ==============>\n",
329 size, j, b, smart_res, dummy_res, size, j
330 );
331 }
332 }
333 }
334}
335
336#[cfg(test)]
337mod save_load_tests {
338 use crate::bit_vec::BitVec;
339 use crate::rank_support::RankSupport;
340 #[test]
341 fn simple_test() {
342 {
343 let size = 128;
344 let b = BitVec::new_with_random(size);
345 let mut r = RankSupport::new(&b);
346 r.compute_index();
347 r.save("example.txt");
348 let r2 = RankSupport::load("example.txt".to_owned()).unwrap();
349 for j in 0..b.size {
350 let dummy_res = RankSupport::dummy_rankn(&b, j);
351 let smart_res = r2.rank1(j as u64);
352 assert_eq!(
353 dummy_res, smart_res,
354 "<============= Case [size: {}, point: {}] Starts ==============>\n \
355 BV = {}\n\
356 Rank = {}\n\
357 Dummy Rank = {}\n\
358 <============= Case [size: {}, point: {}] Ends ==============>\n",
359 size, j, b, smart_res, dummy_res, size, j
360 );
361 }
362 }
363 }
364 #[test]
365 fn fail_test_file_not_found() {
366 {
367 let size = 128;
368 let b = BitVec::new_with_random(size);
369 let mut r = RankSupport::new(&b);
370 r.compute_index();
371 r.save("example.txt");
372 let res = RankSupport::load("example2.txt".to_owned());
373 assert!(res.is_err());
374 }
375 }
376 #[test]
377 fn new_with_load_test() {
378 {
379 let size = 128;
380 let b = BitVec::new_with_random(size);
381 let b = b.clone();
382 let r = RankSupport::new(&b);
383 r.save("example1.txt");
384 let r2 = RankSupport::load("example1.txt".to_owned()).unwrap();
385 for j in 0..b.size {
386 let dummy_res = RankSupport::dummy_rankn(&b, j);
387 let smart_res = r2.rank1(j as u64);
388 assert_eq!(
389 dummy_res, smart_res,
390 "<============= Case [size: {}, point: {}] Starts ==============>\n \
391 BV = {}\n\
392 Rank = {}\n\
393 Dummy Rank = {}\n\
394 <============= Case [size: {}, point: {}] Ends ==============>\n",
395 size, j, b, smart_res, dummy_res, size, j
396 );
397 }
398 }
399 }
400}
401
402#[cfg(test)]
403mod benchmark_overhead {
404 use crate::{BitVec, RankSupport};
405 #[test]
406 pub fn benchmark() {
407 let mut overheads = vec![];
408 for i in 1..=84 {
409 let size = i * i * 8;
410 let b = BitVec::new_with_random(size);
411 let r = RankSupport::new(&b);
412 let overhead = r.overhead();
413 overheads.push((size, overhead));
414 }
415 println!("Overheads: {:?}", overheads);
416 }
417}