bvrs/
rank_support.rs

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> /* Data Structure Construction */ {
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        // println!("SuperBlockSize: {:?}", super_block_size);
23        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        // println!("Before {:?}", super_blocks);
30        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            // println!("At {}: {:?}", i, super_blocks);
37        }
38        // println!("SuperBlocks {:?}", super_blocks);
39        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        // println!("Blocksize: {:?}", block_size);
49        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        // println!("Blocks: {:?}", blocks);
71        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                // println!("Round (i: {}) (j: {})", i, j);
93                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        // println!("Lookup: {:?}", lookup_table);
99        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> /* Public API */ {
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        // println!("SuperBlockSize: {}", super_block_size);
141        // println!("BlockSize: {}", block_size);
142        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        // println!("Lookup:");
153        // print!("(left: {})\t", left);
154        // print!("(right: {})\t", right);
155        // print!("(extracted: {})\t", self.bv.extract(left, right));
156        // print!("(row: {})\t", lookup_row_index);
157        // println!("(rank: {})", lookup_rank_index);
158
159        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                // println!("Test {} {}", i, j);
237                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                // println!("Test {} {}", i, j);
260                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}