use crate::ambassador_impl_Index;
use crate::traits::Backend;
use ambassador::{Delegate, delegatable_trait};
use impl_tools::autoimpl;
use mem_dbg::{MemDbg, MemSize};
use std::ops::Deref;
use std::ops::Index;
use crate::traits::ambassador_impl_Backend;
use crate::traits::bit_vec_ops::{BitLength, ambassador_impl_BitLength};
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
#[delegatable_trait]
pub trait BitCount: BitLength {
fn count_ones(&self) -> usize;
#[inline(always)]
fn count_zeros(&self) -> usize {
self.len() - self.count_ones()
}
}
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
#[delegatable_trait]
pub trait NumBits: BitLength {
fn num_ones(&self) -> usize;
#[inline(always)]
fn num_zeros(&self) -> usize {
self.len() - self.num_ones()
}
}
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
#[delegatable_trait]
pub trait Rank: BitLength + NumBits + RankUnchecked {
#[inline(always)]
fn rank(&self, pos: usize) -> usize {
if pos >= self.len() {
self.num_ones()
} else {
unsafe { self.rank_unchecked(pos) }
}
}
}
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
#[delegatable_trait]
pub trait RankUnchecked {
unsafe fn rank_unchecked(&self, pos: usize) -> usize;
fn prefetch(&self, _pos: usize) {
}
}
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
#[delegatable_trait]
pub trait RankZero: Rank {
fn rank_zero(&self, pos: usize) -> usize {
pos - self.rank(pos)
}
unsafe fn rank_zero_unchecked(&self, pos: usize) -> usize {
pos - unsafe { self.rank_unchecked(pos) }
}
}
#[delegatable_trait]
pub trait RankHinted {
unsafe fn rank_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
pos: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize;
}
impl<T: RankHinted + ?Sized> RankHinted for &T {
#[inline(always)]
unsafe fn rank_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
pos: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize {
unsafe { (**self).rank_hinted::<WORDS_PER_SUBBLOCK>(pos, hint_pos, hint_rank) }
}
}
impl<T: RankHinted + ?Sized> RankHinted for &mut T {
#[inline(always)]
unsafe fn rank_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
pos: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize {
unsafe { (**self).rank_hinted::<WORDS_PER_SUBBLOCK>(pos, hint_pos, hint_rank) }
}
}
impl<T: RankHinted + ?Sized> RankHinted for Box<T> {
#[inline(always)]
unsafe fn rank_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
pos: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize {
unsafe { (**self).rank_hinted::<WORDS_PER_SUBBLOCK>(pos, hint_pos, hint_rank) }
}
}
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
#[delegatable_trait]
pub trait SelectUnchecked {
unsafe fn select_unchecked(&self, rank: usize) -> usize;
}
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
#[delegatable_trait]
pub trait Select: SelectUnchecked + NumBits {
fn select(&self, rank: usize) -> Option<usize> {
if rank >= self.num_ones() {
None
} else {
Some(unsafe { self.select_unchecked(rank) })
}
}
}
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
#[delegatable_trait]
pub trait SelectZeroUnchecked {
unsafe fn select_zero_unchecked(&self, rank: usize) -> usize;
}
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
#[delegatable_trait]
pub trait SelectZero: SelectZeroUnchecked + NumBits {
fn select_zero(&self, rank: usize) -> Option<usize> {
if rank >= self.num_zeros() {
None
} else {
Some(unsafe { self.select_zero_unchecked(rank) })
}
}
}
#[delegatable_trait]
pub trait SelectHinted {
unsafe fn select_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
rank: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize;
}
impl<T: SelectHinted + ?Sized> SelectHinted for &T {
#[inline(always)]
unsafe fn select_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
rank: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize {
unsafe { (**self).select_hinted::<WORDS_PER_SUBBLOCK>(rank, hint_pos, hint_rank) }
}
}
impl<T: SelectHinted + ?Sized> SelectHinted for &mut T {
#[inline(always)]
unsafe fn select_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
rank: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize {
unsafe { (**self).select_hinted::<WORDS_PER_SUBBLOCK>(rank, hint_pos, hint_rank) }
}
}
impl<T: SelectHinted + ?Sized> SelectHinted for Box<T> {
#[inline(always)]
unsafe fn select_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
rank: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize {
unsafe { (**self).select_hinted::<WORDS_PER_SUBBLOCK>(rank, hint_pos, hint_rank) }
}
}
#[delegatable_trait]
pub trait SelectZeroHinted {
unsafe fn select_zero_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
rank: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize;
}
impl<T: SelectZeroHinted + ?Sized> SelectZeroHinted for &T {
#[inline(always)]
unsafe fn select_zero_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
rank: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize {
unsafe { (**self).select_zero_hinted::<WORDS_PER_SUBBLOCK>(rank, hint_pos, hint_rank) }
}
}
impl<T: SelectZeroHinted + ?Sized> SelectZeroHinted for &mut T {
#[inline(always)]
unsafe fn select_zero_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
rank: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize {
unsafe { (**self).select_zero_hinted::<WORDS_PER_SUBBLOCK>(rank, hint_pos, hint_rank) }
}
}
impl<T: SelectZeroHinted + ?Sized> SelectZeroHinted for Box<T> {
#[inline(always)]
unsafe fn select_zero_hinted<const WORDS_PER_SUBBLOCK: usize>(
&self,
rank: usize,
hint_pos: usize,
hint_rank: usize,
) -> usize {
unsafe { (**self).select_zero_hinted::<WORDS_PER_SUBBLOCK>(rank, hint_pos, hint_rank) }
}
}
#[derive(Debug, Clone, MemSize, MemDbg, Delegate)]
#[cfg_attr(feature = "epserde", derive(epserde::Epserde))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[delegate(Index<usize>, target = "bits")]
#[delegate(crate::traits::Backend, target = "bits")]
#[delegate(crate::traits::bit_vec_ops::BitLength, target = "bits")]
#[delegate(crate::traits::rank_sel::Rank, target = "bits")]
#[delegate(crate::traits::rank_sel::RankHinted, target = "bits")]
#[delegate(crate::traits::rank_sel::RankUnchecked, target = "bits")]
#[delegate(crate::traits::rank_sel::RankZero, target = "bits")]
#[delegate(crate::traits::rank_sel::Select, target = "bits")]
#[delegate(crate::traits::rank_sel::SelectHinted, target = "bits")]
#[delegate(crate::traits::rank_sel::SelectUnchecked, target = "bits")]
#[delegate(crate::traits::rank_sel::SelectZero, target = "bits")]
#[delegate(crate::traits::rank_sel::SelectZeroHinted, target = "bits")]
#[delegate(crate::traits::rank_sel::SelectZeroUnchecked, target = "bits")]
pub struct AddNumBits<B> {
bits: B,
number_of_ones: usize,
}
impl<B> AddNumBits<B> {
pub fn into_inner(self) -> B {
self.bits
}
#[inline(always)]
#[must_use]
pub const unsafe fn from_raw_parts(bits: B, number_of_ones: usize) -> Self {
Self {
bits,
number_of_ones,
}
}
#[inline(always)]
pub fn into_raw_parts(self) -> (B, usize) {
(self.bits, self.number_of_ones)
}
}
impl<B: BitLength> AddNumBits<B> {
#[inline(always)]
pub fn len(&self) -> usize {
BitLength::len(self)
}
}
impl<B: BitLength> NumBits for AddNumBits<B> {
#[inline(always)]
fn num_ones(&self) -> usize {
self.number_of_ones
}
}
impl<B: BitLength> BitCount for AddNumBits<B> {
#[inline(always)]
fn count_ones(&self) -> usize {
self.number_of_ones
}
}
impl<B> Deref for AddNumBits<B> {
type Target = B;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.bits
}
}
impl<B: BitCount> From<B> for AddNumBits<B> {
fn from(bits: B) -> Self {
let number_of_ones = bits.count_ones();
AddNumBits {
bits,
number_of_ones,
}
}
}
impl<B: Backend + AsRef<[<B as Backend>::Word]>> AsRef<[<B as Backend>::Word]> for AddNumBits<B> {
#[inline(always)]
fn as_ref(&self) -> &[<B as Backend>::Word] {
self.bits.as_ref()
}
}