1const SEED: u64 = 0xbdd8_9aa9_8270_4029;
2const MAGIC: [u64; 3] = [
3 0x2d35_8dcc_aa6c_78a5,
4 0x8bb8_4b93_962e_acc9,
5 0x4b33_a62e_d433_d4a3,
6];
7const MAGICSEED: u64 = SEED ^ mix(SEED ^ MAGIC[0], MAGIC[1]) ^ 16;
8
9#[inline(always)]
10const fn mum(a: u64, b: u64) -> (u64, u64) {
11 let r = a as u128 * b as u128;
12 let a1 = (r & 0x00000000_00000000_ffffffff_ffffffff) as u64;
13 let b1 = (r >> 64) as u64;
14 return (a1, b1);
15}
16
17#[inline(always)]
18const fn mix(a: u64, b: u64) -> u64 {
19 let (a1, b1) = mum(a, b);
20 return a1 ^ b1;
21}
22
23pub fn hash(key: u128) -> u64 {
24 let w3 = (key >> 96) as u32;
26 let w2 = ((key & 0x00000000_ffffffff_00000000_00000000) >> 64) as u32;
27 let w1 = ((key & 0x00000000_00000000_ffffffff_00000000) >> 32) as u32;
28 let w0 = (key & 0x00000000_00000000_00000000_ffffffff) as u32;
29 let mut a = (w0 as u64) << 32 | w3 as u64;
30 let mut b = (w1 as u64) << 32 | w2 as u64;
31 (a, b) = mum(a ^ MAGIC[1], b ^ MAGICSEED);
32 return mix(a ^ MAGIC[0] ^ 16, b ^ MAGIC[1]);
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38
39 #[test]
40 fn it_hashes_as_expected() {
41 assert_eq!( hash(0), 8755926293314635566);
42 assert_eq!( hash(1), 17996969877019643443);
43 assert_eq!( hash(0xff), 5200326291411116507);
44 assert_eq!( hash(0x1000), 3752997491443908878);
45 assert_eq!( hash(0x1000_0000), 1347028408682550078);
46 assert_eq!( hash(0x10000000_00000000), 3593052489046108800);
47 assert_eq!( hash(0x10000000_00000001), 7365235785575411947);
48 assert_eq!( hash(0x10000000_00000000_00000000), 5399386355486589714);
49 assert_eq!(hash(0x10000000_00000000_00000000_00000000), 13365378750111633005);
50 assert_eq!(hash(0xffffffff_ffffffff_ffffffff_ffffffff), 10466158564987642889);
51 }
52}