use crate::{BitVectorMut, QVector, RSNarrow, RankBin};
use mem_dbg::{MemDbg, MemSize};
use serde::{Deserialize, Serialize};
#[derive(Clone, Default, Eq, PartialEq, Serialize, Deserialize, MemSize, MemDbg, Debug)]
pub struct PrefetchSupport {
samples: Vec<RSNarrow>,
sample_rate_shift: usize, }
impl PrefetchSupport {
pub fn new(qv: &QVector, sample_rate_shift: usize) -> Self {
let mut bvs = [
BitVectorMut::default(),
BitVectorMut::default(),
BitVectorMut::default(),
BitVectorMut::default(),
];
let mut counters = [0; 4];
let mut bits = [false; 4];
let sample_rate = 1 << sample_rate_shift;
for (i, symbol) in qv.iter().enumerate() {
let symbol = symbol as usize;
counters[symbol] += 1;
if counters[symbol] % sample_rate == 0 {
bits[symbol] = true;
}
if i % sample_rate == 0 || i == qv.len() - 1 {
for i in 0..4 {
bvs[i].push(bits[i]);
}
bits = [false, false, false, false];
}
}
Self {
samples: bvs
.into_iter()
.map(|bvm| RSNarrow::new(bvm.into()))
.collect(),
sample_rate_shift,
}
}
#[inline]
pub unsafe fn approx_rank_unchecked(&self, symbol: u8, i: usize) -> usize {
let block_id = i >> self.sample_rate_shift;
let sample_rate = 1 << self.sample_rate_shift;
self.samples
.get_unchecked(symbol as usize)
.rank1(block_id + 1)
.unwrap()
* sample_rate
}
}