use crate::NumHash;
use num_modular::ModularCoreOps;
use num_traits::Float;
use core::hash::{Hash, Hasher};
const P64: u64 = 0xFFFFFFFFFFFFFFC5; const M61: i64 = 0x1FFFFFFFFFFFFFFF; const HASH_INF: i64 = i64::MAX;
impl NumHash for i64 {
#[inline]
fn num_hash<H: Hasher>(&self, state: &mut H) {
(self % M61).hash(state)
}
}
impl NumHash for u64 {
#[inline]
fn num_hash<H: Hasher>(&self, state: &mut H) {
((self % M61 as u64) as i64).hash(state)
}
}
macro_rules! impl_hash_for_small_sint {
($($signed:ty)*) => ($(
impl NumHash for $signed {
#[inline]
fn num_hash<H: Hasher>(&self, state: &mut H) {
(&(*self as i64)).num_hash(state)
}
}
)*);
}
impl_hash_for_small_sint! { i8 i16 i32 isize }
macro_rules! impl_hash_for_small_uint {
($($unsigned:ty)*) => ($(
impl NumHash for $unsigned {
#[inline]
fn num_hash<H: Hasher>(&self, state: &mut H) {
(&(*self as u64)).num_hash(state)
}
}
)*);
}
impl_hash_for_small_uint! { u8 u16 u32 usize }
impl NumHash for u128 {
#[inline]
fn num_hash<H: Hasher>(&self, state: &mut H) {
((self % M61 as u128) as i64).hash(state)
}
}
impl NumHash for i128 {
#[inline]
fn num_hash<H: Hasher>(&self, state: &mut H) {
((self % M61 as i128) as i64).hash(state)
}
}
macro_rules! impl_hash_for_float {
($($float:ty)*) => ($(
impl NumHash for $float {
fn num_hash<H: Hasher>(&self, state: &mut H) {
if self.is_nan() {
0i64.num_hash(state) } else if self.is_infinite() {
if self.is_sign_positive() {
HASH_INF.num_hash(state)
} else {
(-HASH_INF).num_hash(state)
}
} else {
let (mantissa, exp, sign) = self.integer_decode();
let exp = if exp > 0 { (exp as u64) % 61 } else { ModularCoreOps::<u64>::negm(&(-exp as u64), &61) };
let v = mantissa.mulm(1u64 << ((exp as u64) % 61), &(M61 as u64));
(v as i64 * sign as i64).hash(state);
}
}
}
)*);
}
impl_hash_for_float! { f32 f64 }