use crate::prelude::*;
use anyhow::Result;
use common_traits::SelectInWord;
use epserde::*;
use mem_dbg::*;
#[derive(Epserde, Debug, Clone, MemDbg, MemSize)]
pub struct SelectFixed1<
B: SelectHinted = CountBitVec,
O: BitFieldSlice<usize> = Vec<usize>,
const LOG2_ONES_PER_INVENTORY: usize = 8,
> {
bits: B,
inventory: O,
_marker: core::marker::PhantomData<[(); LOG2_ONES_PER_INVENTORY]>,
}
impl<B: SelectHinted + AsRef<[usize]>, const LOG2_ONES_PER_INVENTORY: usize>
SelectFixed1<B, Vec<usize>, LOG2_ONES_PER_INVENTORY>
{
pub fn new(bitvec: B, number_of_ones: usize) -> Self {
let mut res = SelectFixed1 {
inventory: vec![
0;
(number_of_ones + (1 << LOG2_ONES_PER_INVENTORY) - 1)
>> LOG2_ONES_PER_INVENTORY
],
bits: bitvec,
_marker: core::marker::PhantomData,
};
res.build_ones();
res
}
}
impl<
B: SelectHinted + AsRef<[usize]>,
O: BitFieldSlice<usize> + BitFieldSliceMut<usize>,
const LOG2_ONES_PER_INVENTORY: usize,
> SelectFixed1<B, O, LOG2_ONES_PER_INVENTORY>
{
fn build_ones(&mut self) {
let mut number_of_ones = 0;
let mut next_quantum = 0;
let mut ones_index = 0;
for (i, word) in self.bits.as_ref().iter().copied().enumerate() {
let ones_in_word = word.count_ones() as u64;
while number_of_ones + ones_in_word > next_quantum {
let in_word_index = word.select_in_word((next_quantum - number_of_ones) as usize);
let index = (i * usize::BITS as usize) + in_word_index;
self.inventory.set(ones_index, index);
next_quantum += 1 << LOG2_ONES_PER_INVENTORY;
ones_index += 1;
}
number_of_ones += ones_in_word;
}
}
}
impl<B: SelectHinted + BitCount, O: BitFieldSlice<usize>, const LOG2_ONES_PER_INVENTORY: usize>
Select for SelectFixed1<B, O, LOG2_ONES_PER_INVENTORY>
{
#[inline(always)]
unsafe fn select_unchecked(&self, rank: usize) -> usize {
let index = rank >> LOG2_ONES_PER_INVENTORY;
let pos = self.inventory.get_unchecked(index);
let rank_at_pos = index << LOG2_ONES_PER_INVENTORY;
self.bits.select_hinted_unchecked(rank, pos, rank_at_pos)
}
}
impl<B: SelectHinted, T, const LOG2_ONES_PER_INVENTORY: usize> ConvertTo<B>
for SelectFixed1<B, T, LOG2_ONES_PER_INVENTORY>
where
T: AsRef<[usize]>,
{
#[inline(always)]
fn convert_to(self) -> Result<B> {
Ok(self.bits)
}
}
impl<B: SelectHinted + BitCount + AsRef<[usize]>, const LOG2_ONES_PER_INVENTORY: usize>
ConvertTo<SelectFixed1<B, Vec<usize>, LOG2_ONES_PER_INVENTORY>> for B
{
#[inline(always)]
fn convert_to(self) -> Result<SelectFixed1<B, Vec<usize>, LOG2_ONES_PER_INVENTORY>> {
let count = self.count();
Ok(SelectFixed1::new(self, count))
}
}
impl<
B: SelectHinted + BitLength,
O: BitFieldSlice<usize>,
const LOG2_ONES_PER_INVENTORY: usize,
> BitLength for SelectFixed1<B, O, LOG2_ONES_PER_INVENTORY>
{
#[inline(always)]
fn len(&self) -> usize {
self.bits.len()
}
}
impl<B: SelectHinted + BitCount, O: BitFieldSlice<usize>, const LOG2_ONES_PER_INVENTORY: usize>
BitCount for SelectFixed1<B, O, LOG2_ONES_PER_INVENTORY>
{
#[inline(always)]
fn count(&self) -> usize {
self.bits.count()
}
}
impl<
B: SelectHinted + SelectZero,
O: BitFieldSlice<usize>,
const LOG2_ONES_PER_INVENTORY: usize,
> SelectZero for SelectFixed1<B, O, LOG2_ONES_PER_INVENTORY>
{
#[inline(always)]
fn select_zero(&self, rank: usize) -> Option<usize> {
self.bits.select_zero(rank)
}
#[inline(always)]
unsafe fn select_zero_unchecked(&self, rank: usize) -> usize {
self.bits.select_zero_unchecked(rank)
}
}
impl<
B: SelectHinted + SelectZeroHinted,
O: BitFieldSlice<usize>,
const LOG2_ONES_PER_INVENTORY: usize,
> SelectZeroHinted for SelectFixed1<B, O, LOG2_ONES_PER_INVENTORY>
{
#[inline(always)]
unsafe fn select_zero_hinted_unchecked(
&self,
rank: usize,
pos: usize,
rank_at_pos: usize,
) -> usize {
self.bits
.select_zero_hinted_unchecked(rank, pos, rank_at_pos)
}
#[inline(always)]
fn select_zero_hinted(&self, rank: usize, pos: usize, rank_at_pos: usize) -> Option<usize> {
self.bits.select_zero_hinted(rank, pos, rank_at_pos)
}
}
impl<B: SelectHinted + Rank, O: BitFieldSlice<usize>, const LOG2_ONES_PER_INVENTORY: usize> Rank
for SelectFixed1<B, O, LOG2_ONES_PER_INVENTORY>
{
fn rank(&self, pos: usize) -> usize {
self.bits.rank(pos)
}
unsafe fn rank_unchecked(&self, pos: usize) -> usize {
self.bits.rank_unchecked(pos)
}
}
impl<B: SelectHinted + RankZero, O: BitFieldSlice<usize>, const LOG2_ONES_PER_INVENTORY: usize>
RankZero for SelectFixed1<B, O, LOG2_ONES_PER_INVENTORY>
{
fn rank_zero(&self, pos: usize) -> usize {
self.bits.rank_zero(pos)
}
unsafe fn rank_zero_unchecked(&self, pos: usize) -> usize {
self.bits.rank_zero_unchecked(pos)
}
}
impl<
B: SelectHinted + AsRef<[usize]>,
O: BitFieldSlice<usize>,
const LOG2_ONES_PER_INVENTORY: usize,
> AsRef<[usize]> for SelectFixed1<B, O, LOG2_ONES_PER_INVENTORY>
{
fn as_ref(&self) -> &[usize] {
self.bits.as_ref()
}
}