use ndarray::Array1;
const FNV_OFFSET: u64 = 0xcbf29ce484222325;
const FNV_PRIME: u64 = 0x100000001b3;
#[derive(Clone, Copy)]
pub(crate) struct Fnv1a {
hash: u64,
}
impl Fnv1a {
#[inline]
pub(crate) fn new() -> Self {
Self { hash: FNV_OFFSET }
}
#[inline]
pub(crate) fn mix_byte(&mut self, byte: u8) {
self.hash ^= byte as u64;
self.hash = self.hash.wrapping_mul(FNV_PRIME);
}
#[inline]
pub(crate) fn mix_f64(&mut self, x: f64) {
let bits = if x == 0.0 { 0u64 } else { x.to_bits() };
for b in bits.to_le_bytes() {
self.mix_byte(b);
}
}
#[inline]
pub(crate) fn mix_opt_beta(&mut self, marker: u8, beta: Option<&Array1<f64>>) {
self.mix_byte(marker);
match beta {
None => self.mix_byte(0xff),
Some(v) => {
let len = v.len() as u64;
for b in len.to_le_bytes() {
self.mix_byte(b);
}
for x in v.iter() {
self.mix_f64(*x);
}
}
}
}
#[inline]
pub(crate) fn finish_nonzero(self) -> u64 {
if self.hash == 0 { 1 } else { self.hash }
}
}