#[derive(Debug, Default)]
pub struct SardineCan {
buckets: u64,
count: u8,
}
impl std::fmt::Display for SardineCan {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let res = format!("{:b}", self.buckets);
writeln!(f, "{}", res)
}
}
impl SardineCan {
pub fn add(&mut self, mut x: u8) {
x &= 0b0111_1111;
self.buckets <<= 8;
self.buckets |= x as u64;
self.count += 1;
}
pub fn parallel_tile_64(query: u8) -> u64 {
let multiplier: u64 = 0b10000000_10000000_10000000_10000000_10000000_10000000_100000001;
let tiled_x = query as u64 * multiplier;
let sentinel_mask: u64 =
0b10000000_10000000_10000000_10000000_10000000_10000000_1000000010000000;
tiled_x | sentinel_mask
}
pub fn parallel_rank(&self, x: u8) -> u8 {
Self::parallel_rank_helper(self.buckets, x)
}
fn parallel_rank_helper(packed_keys: u64, query: u8) -> u8 {
let mut difference = Self::parallel_tile_64(query) - packed_keys;
let sentinel_mask: u64 =
0b10000000_10000000_10000000_10000000_10000000_10000000_1000000010000000;
difference &= sentinel_mask;
difference.count_ones() as u8
}
pub fn parallel_count(difference: u64) -> u8 {
let stacker = 0b10000000_10000000_10000000_10000000_10000000_10000000_100000001u64;
let mut stacked = difference as u128 * stacker as u128;
stacked >>= 63;
stacked &= 0b111;
stacked as u8
}
}