use bitm::BitAccess;
use std::ops::{Index, IndexMut};
use crate::phast::MAX_VALUES;
use super::MAX_WINDOW_SIZE;
pub trait GenericUsedValue: Default + Send {
fn add(&mut self, value: usize);
fn remove(&mut self, value: usize);
}
pub struct CyclicSet<const SIZE_64: usize>([u64; SIZE_64]);
impl<const SIZE_64: usize> GenericUsedValue for CyclicSet<SIZE_64> {
#[inline] fn add(&mut self, value: usize) {
unsafe{ self.0.set_bit_unchecked(value & Self::MASK) }
}
#[inline] fn remove(&mut self, value: usize) {
unsafe{ self.0.clear_bit_unchecked(value & Self::MASK) }
}
}
impl<const SIZE_64: usize> CyclicSet<SIZE_64> {
const MASK: usize = SIZE_64*64 - 1;
const CHUNK_MASK: usize = SIZE_64 - 1;
#[inline]
pub(crate) fn contain(&self, value: usize) -> bool {
unsafe{ self.0.get_bit_unchecked(value & Self::MASK) }
}
#[inline]
pub(crate) fn get64(&self, first_value: usize) -> u64 {
let chunk_index = first_value / 64;
let bit_in_lo = first_value % 64;
let lo = unsafe{ *self.0.get_unchecked(chunk_index & Self::CHUNK_MASK) };
if bit_in_lo == 0 { return lo; }
let hi = unsafe{ *self.0.get_unchecked((chunk_index+1) & Self::CHUNK_MASK) };
(lo >> bit_in_lo) | (hi << (64-bit_in_lo))
}
}
impl<const SIZE_64: usize> Default for CyclicSet<SIZE_64> {
#[inline] fn default() -> Self {
Self(std::array::from_fn(|_| 0))
}
}
pub type UsedValueSet = CyclicSet<{MAX_VALUES/64}>; pub type UsedValueSetLarge = CyclicSet<{MAX_VALUES*2/64}>;
pub struct CyclicArray<T, const SIZE: usize = MAX_WINDOW_SIZE>(pub [T; SIZE]);
impl<T: Default, const SIZE: usize> Default for CyclicArray<T, SIZE> {
#[inline(always)]
fn default() -> Self {
Self(std::array::from_fn(|_| Default::default()))
}
}
impl<T, const SIZE: usize> Index<usize> for CyclicArray<T, SIZE> {
type Output = T;
#[inline(always)] fn index(&self, index: usize) -> &Self::Output {
unsafe { self.0.get_unchecked(index & (SIZE-1)) }
}
}
impl<T, const SIZE: usize> IndexMut<usize> for CyclicArray<T, SIZE> {
#[inline(always)] fn index_mut(&mut self, index: usize) -> &mut Self::Output {
unsafe { self.0.get_unchecked_mut(index & (SIZE-1)) }
}
}
impl<const SIZE_64: usize> GenericUsedValue for CyclicArray<u8, SIZE_64> {
#[inline] fn add(&mut self, value: usize) {
self[value] += 1;
}
#[inline] fn remove(&mut self, value: usize) {
self[value] = 0;
}
}
pub type UsedValueMultiSetU8 = CyclicArray<u8, MAX_VALUES>;