use crate::bit_vectors::{rank_select::tests_utils::test_rank_select_access_for, BitVec};
use super::*;
const WORD_SIZE: usize = std::mem::size_of::<usize>() * 8;
#[test]
fn new() {
const TEST_DATA: [usize; 10] = [
0b1000, 0b0010, 0b0000, 0b0110, 0b0000, 0b1010, 0b0000, 0b1011, 0b0100, 0b0001,
];
let bv = BitVec::from(TEST_DATA);
let rs = DenseSamplingRank::new(&bv, 4);
assert_eq!(rs.superblocks.len(), 4);
assert_eq!(rs.superblock_size, 4 * WORD_SIZE);
assert_eq!(rs.k, 4);
assert_eq!(rs.superblocks(), &[0, 4, 9, 11]);
let blocks = rs.blocks().iter().collect::<Vec<_>>();
assert_eq!(&blocks, &[0, 1, 2, 2, 0, 0, 2, 2, 0, 1, 2]);
}
#[test]
fn new_when_fully_sampled() {
const TEST_DATA: [usize; 8] = [
0b1000, 0b0010, 0b0000, 0b0110, 0b0000, 0b1010, 0b0000, 0b1011,
];
let bv = BitVec::from(TEST_DATA);
let rs = DenseSamplingRank::new(&bv, 4);
assert_eq!(rs.superblocks.len(), 3);
assert_eq!(rs.superblock_size, 4 * WORD_SIZE);
assert_eq!(rs.k, 4);
assert_eq!(rs.superblocks(), &[0, 4, 9]);
let blocks = rs.blocks().iter().collect::<Vec<_>>();
assert_eq!(&blocks, &[0, 1, 2, 2, 0, 0, 2, 2, 0]);
}
macro_rules! test_constant_time_for_k{
($( $k: expr ),*) => {
$(
paste::paste!{
mod [<when_k_is_ $k>]{
use super::*;
#[test]
fn new_when_len_is_multiple_of_superblock_size() {
const DESIRED_NUM_SUPERBLOCKS: usize = 6;
const BV_SIZE: usize = $k * DESIRED_NUM_SUPERBLOCKS * WORD_SIZE;
let bv = BitVec::from_value(true, BV_SIZE);
let rs = DenseSamplingRank::new(&bv, $k);
assert_eq!(rs.superblocks.len(), DESIRED_NUM_SUPERBLOCKS + 1);
assert_eq!(rs.superblock_size, $k * WORD_SIZE);
assert_eq!(rs.k, $k);
let mut acc = 0;
for superblock in rs.superblocks().iter().skip(1) {
acc += WORD_SIZE * $k;
assert_eq!(*superblock, acc);
}
assert_eq!(acc, BV_SIZE);
}
#[test]
fn new_when_len_not_multiple_of_superblock_size() {
const DESIRED_NUM_SUPERBLOCKS: usize = 6;
const BV_SIZE: usize = $k * DESIRED_NUM_SUPERBLOCKS * WORD_SIZE + WORD_SIZE / 2;
let bv = BitVec::from_value(true, BV_SIZE);
let rs = DenseSamplingRank::new(&bv, $k);
assert_eq!(rs.superblocks.len(), DESIRED_NUM_SUPERBLOCKS + 1 + 1);
assert_eq!(rs.superblock_size, $k * WORD_SIZE);
assert_eq!(rs.k, $k);
let mut acc = 0;
for superblock in rs.superblocks().iter().skip(1).take(DESIRED_NUM_SUPERBLOCKS) {
acc += WORD_SIZE * $k;
assert_eq!(*superblock, acc);
}
assert_eq!(rs.superblocks().last().copied(), Some(BV_SIZE));
assert_eq!(acc, BV_SIZE - WORD_SIZE / 2);
}
#[test]
fn heap_size_in_bits() {
let bv = BitVec::from_value(true, WORD_SIZE * 420 * $k);
let rs = DenseSamplingRank::new(&bv, $k);
let superblocks_overhead = (bv.len()/WORD_SIZE/$k + 1 )* WORD_SIZE;
let mut blocks_overhead = (WORD_SIZE * ($k-1)).bits_required() as usize * (bv.len() / WORD_SIZE + 1);
let leftover_bits = blocks_overhead % WORD_SIZE;
if leftover_bits !=0 {
blocks_overhead += WORD_SIZE - leftover_bits;
}
assert_eq!(
rs.heap_size_in_bits(),
superblocks_overhead + blocks_overhead
);
}
test_rank_select_access_for!(DenseSamplingRank, $k);
}
}
)*
}
}
test_constant_time_for_k!(1, 2, 4, 5, 8, 16, 20, 32);