1#![no_std]
2
3#[cfg(test)]
4mod tests{
5 use super::murmur3_32;
6 #[test]
7 fn standard_murmur3_32() {
8 assert_eq!(murmur3_32(&[], 0), 0);
9 assert_eq!(murmur3_32(&[], 1), 0x514E28B7);
10 assert_eq!(murmur3_32(&[], 0xffffffff), 0x81F16F39);
11 assert_eq!(murmur3_32(&[0,0,0,0], 0), 0x2362F9DE);
12 assert_eq!(murmur3_32(&[0x21,0x43,0x65,0x87], 0x5082EDEE), 0x2362F9DE);
13 assert_eq!(murmur3_32(&[0x21,0x43,0x65], 0), 0x7E4A8634);
14 assert_eq!(murmur3_32(&[0x21,0x43], 0), 0xA0F7B07A);
15 assert_eq!(murmur3_32(&[0x21], 0), 0x72661CF4);
16 }
17}
18
19pub const fn murmur3_32(data: &[u8], seed: u32) -> u32 {
21 let slice_size: usize = data.len();
22
23 let c1: u32 = 0xcc9e2d51;
24 let c2: u32 = 0x1b873593;
25 let r2 = 13;
26 let m = 5;
27 let n: u32 = 0xe6546b64;
28
29 let mut hash = seed;
30
31 let mut i = 0;
32 let iterator = slice_size/4;
33 while i < iterator {
34 let data = [data[i*4], data[i*4+1], data[i*4+2], data[i*4+3]];
35 let mut k = u32::from_le_bytes(data);
36 k = k.wrapping_mul(c1);
37 k = k.rotate_left(15);
38 k = k.wrapping_mul(c2);
39
40 hash = hash ^ k;
41 hash = hash << r2;
42 hash = hash.wrapping_mul(m).wrapping_add(n);
43
44 i+=1;
45 }
46 match slice_size%4 {
47 0 => (),
48 1 => {
49 let data = [data[i*4], 0, 0, 0];
50 let k = mix_bytes_32(data);
51 hash = hash ^ k;
52 },
53 2 => {
54 let data = [data[i*4], data[i*4+1], 0, 0];
55 let k = mix_bytes_32(data);
56 hash = hash ^ k;
57 },
58 3 => {
59 let data = [data[i*4], data[i*4+1], data[i*4+2], 0];
60 let k = mix_bytes_32(data);
61 hash = hash ^ k;
62
63 }
64 _ => unsafe{core::hint::unreachable_unchecked()}
65 }
66
67 hash = hash ^ slice_size as u32;
68 hash = hash ^ (hash.wrapping_shr(16));
69 hash = hash.wrapping_mul(0x85ebca6b);
70 hash = hash ^ (hash.wrapping_shr(13));
71 hash = hash.wrapping_mul(0xc2b2ae35);
72 hash = hash ^ (hash.wrapping_shr(16));
73
74
75 hash
76}
77
78const fn mix_bytes_32(data: [u8; 4]) -> u32 {
79 let r1 = 15;
80 let c1: u32 = 0xcc9e2d51;
81 let c2: u32 = 0x1b873593;
82 let mut k = u32::from_le_bytes(data);
83 k = k.wrapping_mul(c1);
84 k = k.rotate_left(r1);
85 k = k.wrapping_mul(c2);
86 return k
87}