1#![forbid(unsafe_code)]
2
3pub const PRIME32_1: u32 = 0x9E37_79B1;
4pub const PRIME32_2: u32 = 0x85EB_CA77;
5pub const PRIME64_1: u64 = 0x9E37_79B1_85EB_CA87;
6
7#[inline]
8pub fn hash4(value: u32, hash_log: u32) -> u32 {
9 (value.wrapping_mul(PRIME32_1)) >> (32 - hash_log)
10}
11
12#[inline]
13pub fn hash5(value: u64, hash_log: u32) -> u32 {
14 ((value << 24).wrapping_mul(PRIME64_1) >> (64 - hash_log)) as u32
15}
16
17#[inline]
18pub fn hash6(value: u64, hash_log: u32) -> u32 {
19 ((value << 16).wrapping_mul(PRIME64_1) >> (64 - hash_log)) as u32
20}
21
22#[inline]
23pub fn hash7(value: u64, hash_log: u32) -> u32 {
24 ((value << 8).wrapping_mul(PRIME64_1) >> (64 - hash_log)) as u32
25}
26
27#[inline]
28pub fn hash8(value: u64, hash_log: u32) -> u32 {
29 (value.wrapping_mul(PRIME64_1) >> (64 - hash_log)) as u32
30}
31
32#[cfg(test)]
33mod tests {
34 use super::*;
35
36 #[test]
37 fn hash4_distributes() {
38 let mut buckets = [0u32; 256];
39 for i in 0..4096u32 {
40 let h = hash4(i, 8) as usize;
41 buckets[h] += 1;
42 }
43 let used = buckets.iter().filter(|&&c| c > 0).count();
44 assert!(used > 200, "hash4 only hit {used}/256 buckets");
45 }
46
47 #[test]
48 fn hash8_distributes() {
49 let mut buckets = [0u32; 256];
50 for i in 0..4096u64 {
51 let h = hash8(i, 8) as usize;
52 buckets[h] += 1;
53 }
54 let used = buckets.iter().filter(|&&c| c > 0).count();
55 assert!(used > 200, "hash8 only hit {used}/256 buckets");
56 }
57}