pub trait Rank {
fn rank(&self, index: usize) -> Option<usize>;
fn rank0(&self, index: usize) -> Option<usize> {
self.rank(index).map(|rank| index - rank)
}
}
pub trait Select {
fn select(&self, rank: usize) -> Option<usize>;
fn select0(&self, rank0: usize) -> Option<usize>;
}
pub trait RankSupport<T> {
unsafe fn rank(&self, data: &T, index: usize) -> Option<usize>;
unsafe fn rank0(&self, data: &T, index: usize) -> Option<usize> {
self.rank(data, index).map(|rank| index - rank)
}
}
pub trait SelectSupport<T> {
unsafe fn select(&self, data: &T, rank: usize) -> Option<usize>;
unsafe fn select0(&self, data: &T, rank0: usize) -> Option<usize>;
}
#[derive(Debug)]
pub struct RankStructure<T, R>
where
R: RankSupport<T>,
{
data: T,
rank_support: R,
}
impl<T, R> RankStructure<T, R>
where
R: RankSupport<T>,
{
pub unsafe fn new(data: T, rank_support: R) -> Self {
Self { data, rank_support }
}
pub fn data(&self) -> &T {
&self.data
}
pub fn rank_support(&self) -> &R {
&self.rank_support
}
}
impl<T, R> Rank for RankStructure<T, R>
where
R: RankSupport<T>,
{
fn rank(&self, index: usize) -> Option<usize> {
unsafe { self.rank_support.rank(&self.data, index) }
}
}
impl<T, R> Select for RankStructure<T, R>
where
R: SelectSupport<T> + RankSupport<T>,
{
fn select(&self, rank: usize) -> Option<usize> {
unsafe { self.rank_support.select(&self.data, rank) }
}
fn select0(&self, rank0: usize) -> Option<usize> {
unsafe { self.rank_support.select0(&self.data, rank0) }
}
}
impl<T, R> Access for RankStructure<T, R>
where
T: Access,
R: RankSupport<T>,
{
fn access(&self, index: usize) -> Option<bool> {
self.data.access(index)
}
}
impl<T, R> HeapSize for RankStructure<T, R>
where
T: HeapSize,
R: HeapSize + RankSupport<T>,
{
fn heap_size_in_bits(&self) -> usize {
self.data.heap_size_in_bits() + self.rank_support.heap_size_in_bits()
}
}
#[derive(Debug)]
pub struct SelectStructure<T, S>
where
S: SelectSupport<T>,
{
data: T,
select_support: S,
}
impl<T, S> SelectStructure<T, S>
where
S: SelectSupport<T>,
{
pub unsafe fn new(data: T, select_support: S) -> Self {
Self {
data,
select_support,
}
}
pub fn data(&self) -> &T {
&self.data
}
pub fn select_support(&self) -> &S {
&self.select_support
}
}
impl<T, S> Select for SelectStructure<T, S>
where
S: SelectSupport<T>,
{
fn select(&self, rank: usize) -> Option<usize> {
unsafe { self.select_support.select(&self.data, rank) }
}
fn select0(&self, rank: usize) -> Option<usize> {
unsafe { self.select_support.select0(&self.data, rank) }
}
}
impl<T, S> Rank for SelectStructure<T, S>
where
S: SelectSupport<T> + RankSupport<T>,
{
fn rank(&self, index: usize) -> Option<usize> {
unsafe { self.select_support.rank(&self.data, index) }
}
}
impl<T, S> Access for SelectStructure<T, S>
where
T: Access,
S: SelectSupport<T>,
{
fn access(&self, index: usize) -> Option<bool> {
self.data.access(index)
}
}
impl<T, S> HeapSize for SelectStructure<T, S>
where
T: HeapSize,
S: HeapSize + SelectSupport<T>,
{
fn heap_size_in_bits(&self) -> usize {
self.data.heap_size_in_bits() + self.select_support.heap_size_in_bits()
}
}
#[derive(Debug)]
pub struct RankSelectStructure<T, R, S>
where
R: RankSupport<T>,
S: SelectSupport<T>,
{
data: T,
rank_support: R,
select_support: S,
}
impl<T, R, S> RankSelectStructure<T, R, S>
where
R: RankSupport<T>,
S: SelectSupport<T>,
{
pub unsafe fn new(data: T, rank_support: R, select_support: S) -> Self {
Self {
data,
rank_support,
select_support,
}
}
pub fn data(&self) -> &T {
&self.data
}
pub fn rank_support(&self) -> &R {
&self.rank_support
}
pub fn select_support(&self) -> &S {
&self.select_support
}
}
impl<T, R, S> Rank for RankSelectStructure<T, R, S>
where
R: RankSupport<T>,
S: SelectSupport<T>,
{
fn rank(&self, index: usize) -> Option<usize> {
unsafe { self.rank_support.rank(&self.data, index) }
}
}
impl<T, R, S> Select for RankSelectStructure<T, R, S>
where
R: RankSupport<T>,
S: SelectSupport<T>,
{
fn select(&self, rank: usize) -> Option<usize> {
unsafe { self.select_support.select(&self.data, rank) }
}
fn select0(&self, rank0: usize) -> Option<usize> {
unsafe { self.select_support.select0(&self.data, rank0) }
}
}
impl<T, R, S> Access for RankSelectStructure<T, R, S>
where
T: Access,
S: SelectSupport<T>,
R: RankSupport<T>,
{
fn access(&self, index: usize) -> Option<bool> {
self.data.access(index)
}
}
impl<T, R, S> HeapSize for RankSelectStructure<T, R, S>
where
T: HeapSize,
S: HeapSize + SelectSupport<T>,
R: HeapSize + RankSupport<T>,
{
fn heap_size_in_bits(&self) -> usize {
self.data.heap_size_in_bits()
+ self.rank_support.heap_size_in_bits()
+ self.select_support.heap_size_in_bits()
}
}
impl<T, R, S, B> Build<RankStructure<T, R>, RankSelectStructure<T, R, S>> for B
where
R: RankSupport<T>,
B: Build<T, SelectStructure<T, S>>,
S: SelectSupport<T>,
{
fn build(&self, data: RankStructure<T, R>) -> RankSelectStructure<T, R, S> {
let rank_support = data.rank_support;
let data = data.data;
let select_structure = self.build(data);
let select_support = select_structure.select_support;
let data = select_structure.data;
unsafe { RankSelectStructure::new(data, rank_support, select_support) }
}
}
impl<T, R, S, B> Build<SelectStructure<T, S>, RankSelectStructure<T, R, S>> for B
where
R: RankSupport<T>,
B: Build<T, RankStructure<T, R>>,
S: SelectSupport<T>,
{
fn build(&self, data: SelectStructure<T, S>) -> RankSelectStructure<T, R, S> {
let select_support = data.select_support;
let data = data.data;
let rank_structure = self.build(data);
let rank_support = rank_structure.rank_support;
let data = rank_structure.data;
unsafe { RankSelectStructure::new(data, rank_support, select_support) }
}
}
pub trait Build<T, O> {
fn build(&self, data: T) -> O;
}
pub mod sparse_sampling_rank;
pub use sparse_sampling_rank::SparseSamplingRank;
pub mod dense_sampling_rank;
pub use dense_sampling_rank::DenseSamplingRank;
use crate::profiling::HeapSize;
use super::Access;
#[cfg(test)]
pub(crate) mod tests_utils;