use std::fmt::{Debug, Formatter};
use crate::array::Array;
use crate::representation::{RepresentationTrait, REPRESENTATION_SMALL};
const SMALL_MASK: usize = 0x0000_0000_7fff_ffff;
#[derive(PartialEq)]
pub(crate) struct Small<const P: usize, const W: usize>(usize);
impl<const P: usize, const W: usize> Small<P, W> {
#[inline]
pub(crate) fn insert(&mut self, h: u32) -> bool {
let h1 = self.h1();
if h1 == 0 {
self.0 |= (h as usize) << 2;
return true;
} else if h1 == h {
return true;
}
let h2 = self.h2();
if h2 == 0 {
self.0 |= (h as usize) << 33;
return true;
} else if h2 == h {
return true;
}
false
}
#[inline]
fn h1(&self) -> u32 {
((self.0 >> 2) & SMALL_MASK) as u32
}
#[inline]
fn h2(&self) -> u32 {
((self.0 >> 33) & SMALL_MASK) as u32
}
#[inline]
pub(crate) fn items(&self) -> [u32; 2] {
[self.h1(), self.h2()]
}
}
impl<const P: usize, const W: usize> RepresentationTrait for Small<P, W> {
fn insert_encoded_hash(&mut self, h: u32) -> usize {
if self.insert(h) {
self.to_data()
} else {
let items = self.items();
let arr = Array::<P, W>::from_vec(vec![items[0], items[1], h, 0], 3);
arr.to_data()
}
}
#[inline]
fn estimate(&self) -> usize {
match (self.h1(), self.h2()) {
(0, 0) => 0,
(_, 0) => 1,
(_, _) => 2,
}
}
fn size_of(&self) -> usize {
std::mem::size_of::<Self>()
}
#[inline]
unsafe fn drop(&mut self) {}
#[inline]
fn to_data(&self) -> usize {
self.0 | REPRESENTATION_SMALL
}
}
impl<const P: usize, const W: usize> Debug for Small<P, W> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.to_string())
}
}
impl<const P: usize, const W: usize> From<usize> for Small<P, W> {
fn from(data: usize) -> Self {
Self(data)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn small_size() {
assert_eq!(std::mem::size_of::<Small<0, 0>>(), 8);
}
}