pub fn int64_hash(key_arg: u64) -> u64 {
let mut key = key_arg;
key = (!key).wrapping_add(key << 21); key = key ^ key >> 24;
key = key.wrapping_add(key << 3).wrapping_add(key << 8); key = key ^ key >> 14;
key = key.wrapping_add(key << 2).wrapping_add(key << 4); key = key ^ key >> 28;
key = key.wrapping_add(key << 31);
key
}
pub fn int64_hash_inverse(key_arg: u64) -> u64 {
let mut key = key_arg;
let mut tmp: u64 = key.wrapping_sub(key << 31);
key = key.wrapping_sub(tmp << 31);
tmp = key ^ key >> 28;
key ^= tmp >> 28;
key = key.wrapping_mul(14933078535860113213u64);
tmp = key ^ key >> 14;
tmp = key ^ tmp >> 14;
tmp = key ^ tmp >> 14;
key ^= tmp >> 14;
key = key.wrapping_mul(15244667743933553977u64);
tmp = key ^ key >> 24;
key ^= tmp >> 24;
tmp = !key;
tmp = !(key.wrapping_sub(tmp << 21));
tmp = !(key.wrapping_sub(tmp << 21));
key = !(key.wrapping_sub(tmp << 21));
key
}
pub fn int32_hash(tohash: u32) -> u32 {
let mut key = tohash;
key = key.wrapping_add(!(key << 15));
key = key ^ (key >> 10);
key = key.wrapping_add(key << 3);
key = key ^ (key >> 6);
key = key.wrapping_add(!(key << 11));
key = key ^ (key >> 16);
key
}
pub fn int32_hash_inverse(hash: u32) -> u32 {
let mut val = hash;
val = val ^ (val >> 16);
val = (!val).wrapping_mul(4290770943);
val = val ^ (val >> 6) ^ (val >> 12) ^ (val >> 18) ^ (val >> 24) ^ (val >> 30);
val = val.wrapping_mul(954437177);
val = val ^ (val >> 10) ^ (val >> 20) ^ (val >> 30);
val = (!val).wrapping_mul(3221192703);
val
}
#[cfg(test)]
mod tests {
use super::*;
use log::*;
use rand::rng;
use rand::RngCore;
#[allow(dead_code)]
fn log_init_test() {
let _ = env_logger::builder().is_test(true).try_init();
}
#[test]
fn test_inversible_hash_64() {
log_init_test();
let mut to_hash;
let mut hashed;
let mut i_hashed;
for i in 0..1000000 {
to_hash = rand::rng().next_u64();
hashed = int64_hash(to_hash);
i_hashed = int64_hash_inverse(hashed);
trace!("i hash unhash = {} {} {} ", i, to_hash, i_hashed);
assert!(to_hash == i_hashed);
}
}
#[test]
fn test_inversible_hash_32() {
log_init_test();
let mut to_hash;
let mut hashed;
let mut i_hashed;
for i in 0..1000000 {
to_hash = rng().next_u32();
hashed = int32_hash(to_hash);
i_hashed = int32_hash_inverse(hashed);
trace!("i hash unhash = {} {} {} ", i, to_hash, i_hashed);
assert!(to_hash == i_hashed);
}
} }