faex 0.1.2

A fast and efficient Compact Data Structures Library
Documentation
use crate::bit_vectors::rank_select::Rank;
use crate::bit_vectors::BitVec;
use crate::int_vectors::CompactIntVec;
use crate::profiling::HeapSize;
use crate::util::{ceil_div, BitsRequired};

use super::{SelectStructure, SelectSupport, SparseSamplingRank};
use crate::Build;
pub struct SparseSamplingSelect {
    s: usize,
    total_rank: usize,
    select_samples: CompactIntVec,
    sparse_sample_rank: SparseSamplingRank,
}

impl SparseSamplingSelect {
    pub fn new(data: &BitVec, s: usize, k: usize) -> Self {
        assert!(s > 0, "s must be greater than 0");
        assert!(k > 0, "k must be greater than 0");

        let n = data.len();

        let bits_required = n.bits_required() as usize;
        let mut select_samples = CompactIntVec::new(bits_required);

        let mut r = 0;
        for i in 0..n {
            if data.read(i) {
                if r % s == 0 {
                    select_samples.push(i);
                }
                r += 1;
            }
        }

        let spec = SparseSamplingRank::spec(k);
        let sparse_sample_rank = spec.build(data);

        select_samples.push(n);

        Self {
            s,
            total_rank: r,
            select_samples,
            sparse_sample_rank,
        }
    }

    pub fn s(&self) -> usize {
        self.s
    }
}

impl SelectSupport<BitVec> for SparseSamplingSelect {
    unsafe fn select(&self, data: &BitVec, rank: usize) -> Option<usize> {
        if rank == 0 {
            return Some(0);
        }

        if rank > self.total_rank {
            return None;
        }

        let p = (rank - 1) / self.s;
        let left = self.select_samples.get(p)? / self.sparse_sample_rank.superblock_size();
        let right = self.select_samples.get(p + 1)? / self.sparse_sample_rank.superblock_size();

        self.sparse_sample_rank
            .select_with_hints(data, rank, left, right)
    }

    unsafe fn select0(&self, data: &BitVec, rank0: usize) -> Option<usize> {
        todo!()
    }
}

pub struct SparseSamplingSelectSpec {
    s: usize,
    k: usize,
}

impl SparseSamplingSelectSpec {
    pub const fn new(s: usize, k: usize) -> Self {
        Self { s, k }
    }
}

impl SparseSamplingSelect {
    pub const fn spec(s: usize, k: usize) -> SparseSamplingSelectSpec {
        SparseSamplingSelectSpec::new(s, k)
    }
}

impl Build<BitVec, SelectStructure<BitVec, SparseSamplingSelect>> for SparseSamplingSelectSpec {
    fn build(&self, data: BitVec) -> SelectStructure<BitVec, SparseSamplingSelect> {
        let sparse_sampling_select = SparseSamplingSelect::new(&data, self.s, self.k);
        unsafe { SelectStructure::new(data, sparse_sampling_select) }
    }
}

impl Build<&BitVec, SparseSamplingSelect> for SparseSamplingSelectSpec {
    fn build(&self, data: &BitVec) -> SparseSamplingSelect {
        SparseSamplingSelect::new(data, self.s, self.k)
    }
}

impl HeapSize for SparseSamplingSelect {
    fn heap_size_in_bits(&self) -> usize {
        self.select_samples.heap_size_in_bits() + self.sparse_sample_rank.heap_size_in_bits()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::bit_vectors::rank_select::tests_utils::test_select_for;
    #[test]
    fn new() {
        use super::*;
        let bv = BitVec::from([0b10101010usize; 2]);
        let ss = SparseSamplingSelect::new(&bv, 4, 1);
        assert_eq!(ss.s(), 4);
        println!("{}", ss.select_samples);
        dbg!(unsafe { ss.select(&bv, 9) });
    }
    test_select_for!(SparseSamplingSelect, 4, 4);
}