use std::mem::{ManuallyDrop, MaybeUninit};
use std::ops::ControlFlow;
use crate::{assume, level_indices};
use crate::bit_block::BitBlock;
use crate::config::Config;
use crate::iter::{BlockIter, IndexIter};
pub trait BitSetBase {
type Conf: Config;
const TRUSTED_HIERARCHY: bool;
}
pub trait LevelMasks: BitSetBase{
fn level0_mask(&self) -> <Self::Conf as Config>::Level0BitBlock;
unsafe fn level1_mask(&self, level0_index: usize)
-> <Self::Conf as Config>::Level1BitBlock;
unsafe fn data_mask(&self, level0_index: usize, level1_index: usize)
-> <Self::Conf as Config>::DataBitBlock;
}
pub trait LevelMasksIterExt: LevelMasks{
type IterState;
type Level1BlockData: Default;
fn make_iter_state(&self) -> Self::IterState;
unsafe fn drop_iter_state(&self, state: &mut ManuallyDrop<Self::IterState>);
unsafe fn init_level1_block_data(
&self,
state: &mut Self::IterState,
level1_block_data: &mut MaybeUninit<Self::Level1BlockData>,
level0_index: usize
) -> (<Self::Conf as Config>::Level1BitBlock, bool);
unsafe fn data_mask_from_block_data(
level1_block_data: &Self::Level1BlockData, level1_index: usize
) -> <Self::Conf as Config>::DataBitBlock;
}
impl<'a, T: LevelMasks> BitSetBase for &'a T {
type Conf = T::Conf;
const TRUSTED_HIERARCHY: bool = T::TRUSTED_HIERARCHY;
}
impl<'a, T: LevelMasks> LevelMasks for &'a T {
#[inline]
fn level0_mask(&self) -> <Self::Conf as Config>::Level0BitBlock {
<T as LevelMasks>::level0_mask(self)
}
#[inline]
unsafe fn level1_mask(&self, level0_index: usize)
-> <Self::Conf as Config>::Level1BitBlock
{
<T as LevelMasks>::level1_mask(self, level0_index)
}
#[inline]
unsafe fn data_mask(&self, level0_index: usize, level1_index: usize)
-> <Self::Conf as Config>::DataBitBlock
{
<T as LevelMasks>::data_mask(self, level0_index, level1_index)
}
}
impl<'a, T: LevelMasksIterExt> LevelMasksIterExt for &'a T {
type Level1BlockData = T::Level1BlockData;
type IterState = T::IterState;
#[inline]
fn make_iter_state(&self) -> Self::IterState {
<T as LevelMasksIterExt>::make_iter_state(self)
}
#[inline]
unsafe fn drop_iter_state(&self, cache: &mut ManuallyDrop<Self::IterState>) {
<T as LevelMasksIterExt>::drop_iter_state(self, cache)
}
#[inline]
unsafe fn init_level1_block_data(
&self,
state: &mut Self::IterState,
level1_blocks: &mut MaybeUninit<Self::Level1BlockData>,
level0_index: usize
) -> (<Self::Conf as Config>::Level1BitBlock, bool) {
<T as LevelMasksIterExt>::init_level1_block_data(
self, state, level1_blocks, level0_index
)
}
#[inline]
unsafe fn data_mask_from_block_data(
level1_blocks: &Self::Level1BlockData, level1_index: usize
) -> <Self::Conf as Config>::DataBitBlock {
<T as LevelMasksIterExt>::data_mask_from_block_data(
level1_blocks, level1_index
)
}
}
pub unsafe trait BitSetInterface
: BitSetBase
+ LevelMasksIterExt
+ IntoIterator<IntoIter = IndexIter<Self>>
+ Sized
{
#[inline]
fn block_iter(&self) -> BlockIter<&'_ Self> {
BlockIter::new(self)
}
#[inline]
fn iter(&self) -> IndexIter<&'_ Self> {
IndexIter::new(self)
}
#[inline]
fn into_block_iter(self) -> BlockIter<Self> {
BlockIter::new(self)
}
#[inline]
fn contains(&self, index: usize) -> bool {
bitset_contains(self, index)
}
#[inline]
fn is_empty(&self) -> bool {
bitset_is_empty(self)
}
}
#[inline]
pub(crate) fn bitset_contains<S: LevelMasks>(bitset: S, index: usize) -> bool {
let (level0_index, level1_index, data_index) =
level_indices::<S::Conf>(index);
unsafe{
let data_block = bitset.data_mask(level0_index, level1_index);
data_block.get_bit_unchecked(data_index)
}
}
pub(crate) fn bitset_is_empty<S: LevelMasksIterExt>(bitset: S) -> bool {
if S::TRUSTED_HIERARCHY{
return bitset.level0_mask().is_zero();
}
use ControlFlow::*;
BlockIter::new(bitset).traverse(|block|{
if !block.is_empty(){
Break(())
} else {
Continue(())
}
}).is_continue()
}
pub(crate) fn bitsets_eq<L, R>(left: L, right: R) -> bool
where
L: LevelMasksIterExt,
R: LevelMasksIterExt<Conf = L::Conf>,
{
let left_level0_mask = left.level0_mask();
let right_level0_mask = right.level0_mask();
let is_trusted_hierarchy = L::TRUSTED_HIERARCHY & R::TRUSTED_HIERARCHY;
let level0_mask =
if is_trusted_hierarchy{
if left_level0_mask != right_level0_mask {
return false;
}
left_level0_mask
} else {
left_level0_mask | right_level0_mask
};
let mut left_cache_data = left.make_iter_state();
let mut right_cache_data = right.make_iter_state();
let mut left_level1_blocks = MaybeUninit::new(Default::default());
let mut right_level1_blocks = MaybeUninit::new(Default::default());
use ControlFlow::*;
let is_eq = level0_mask.traverse_bits(|level0_index|{
let (left_level1_mask, left_valid) = unsafe {
left_level1_blocks.assume_init_drop();
left.init_level1_block_data(&mut left_cache_data, &mut left_level1_blocks, level0_index)
};
let (right_level1_mask, right_valid) = unsafe {
right_level1_blocks.assume_init_drop();
right.init_level1_block_data(&mut right_cache_data, &mut right_level1_blocks, level0_index)
};
if is_trusted_hierarchy {
unsafe{
assume!(left_valid);
assume!(right_valid);
}
if left_level1_mask != right_level1_mask {
return Break(());
}
}
if is_trusted_hierarchy || (left_valid & right_valid) {
let level1_mask =
if is_trusted_hierarchy {
left_level1_mask
} else{
left_level1_mask | right_level1_mask
};
level1_mask.traverse_bits(|level1_index|{
let left_data = unsafe {
L::data_mask_from_block_data(left_level1_blocks.assume_init_ref(), level1_index)
};
let right_data = unsafe {
R::data_mask_from_block_data(right_level1_blocks.assume_init_ref(), level1_index)
};
if left_data == right_data{
Continue(())
} else {
Break(())
}
})
} else if left_valid {
if L::TRUSTED_HIERARCHY{
return if left_level1_mask.is_zero() {
Continue(())
} else {
Break(())
}
}
left_level1_mask.traverse_bits(|level1_index|{
let left_data = unsafe{
L::data_mask_from_block_data(left_level1_blocks.assume_init_ref(), level1_index)
};
if left_data.is_zero() {
Continue(())
} else {
Break(())
}
})
} else if right_valid {
if R::TRUSTED_HIERARCHY{
return if right_level1_mask.is_zero() {
Continue(())
} else {
Break(())
}
}
right_level1_mask.traverse_bits(|level1_index|{
let right_data = unsafe{
R::data_mask_from_block_data(right_level1_blocks.assume_init_ref(), level1_index)
};
if right_data.is_zero() {
Continue(())
} else {
Break(())
}
})
} else {
Continue(())
}
}).is_continue();
unsafe {
left_level1_blocks.assume_init_drop();
right_level1_blocks.assume_init_drop();
}
is_eq
}