faex 0.1.2

A fast and efficient Compact Data Structures Library
Documentation
use super::*;
use crate::bit_vectors::{rank_select::tests_utils::test_rank_select_access_for, BitVec};
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 = SparseSamplingRank::new(&bv, 4);

    // +1 because of the starting block (0) and +1 because of the last block as not all blocks are
    // fully sampled
    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]);
}

#[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 = SparseSamplingRank::new(&bv, 4);

    // +1 because of the starting block (0) and +1 because of the last block as not all blocks are
    // fully sampled
    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]);
}

macro_rules! test_sparse_sampling_for_k{
    ($( $k: expr ),*) => {
        $(
            paste::paste!{
            mod [<when_k_is_ $k>]{
                use super::*;

                #[test]
                fn new_when_empty_bitvec(){
                    let bv = BitVec::new();
                    let rs = SparseSamplingRank::new(&bv, $k);

                    assert_eq!(rs.superblocks.len(), 1);
                    assert_eq!(rs.superblock_size, $k * WORD_SIZE);
                    assert_eq!(rs.k, $k);

                    assert_eq!(rs.superblocks(), &[0]);
                }

                #[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 = SparseSamplingRank::new(&bv, $k);

                    // + 1 block because of the starting block (0)
                    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 = SparseSamplingRank::new(&bv, $k);
                    // + 1 block because of the starting block (0), +1 because of the last block as not all blocks are fully sampled
                    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);
                    }
                    // The last superblock is not fully sampled, as BV_SIZE is not multiple of the superblock size
                    assert_eq!(rs.superblocks().last().copied(), Some(BV_SIZE));
                    // Do not count the non-multiple block since it has no superblock associated
                    assert_eq!(acc, BV_SIZE - WORD_SIZE / 2);
                }
                #[test]
                fn heap_size_in_bits() {
                    let bv = BitVec::from_value(true,WORD_SIZE * 16 * $k);
                    let rs = SparseSamplingRank::new(&bv, $k);
                    // size overhead for a bitvec with length n is n/64/k * 64 bits -> n/k bits, which is 1/k of the original size
                    assert_eq!(
                        rs.heap_size_in_bits(),
                        (bv.len() / WORD_SIZE / $k + 1) * WORD_SIZE
                    );
                }

                test_rank_select_access_for!(SparseSamplingRank, $k);
            }
         }
        )*
    }
}

test_sparse_sampling_for_k!(1, 2, 4, 5, 8, 16, 20, 32);