Created
June 2, 2020 21:36
-
-
Save stevenlr/72bdfbed388e4134f64332c57ec181e6 to your computer and use it in GitHub Desktop.
const fn murmur3 x64 128
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(const_fn)] | |
#![feature(const_loop)] | |
#![feature(const_if_match)] | |
const fn fmix64(mut k: u64) -> u64 { | |
k ^= k >> 33; | |
k = k.overflowing_mul(0xff51afd7ed558ccd).0; | |
k ^= k >> 33; | |
k = k.overflowing_mul(0xc4ceb9fe1a85ec53).0; | |
k ^= k >> 33; | |
return k; | |
} | |
const fn bytes_to_u64(s: &[u8], offset: usize) -> u64 { | |
((s[offset + 0] as u64) << 0) | |
| ((s[offset + 1] as u64) << 8) | |
| ((s[offset + 2] as u64) << 16) | |
| ((s[offset + 3] as u64) << 24) | |
| ((s[offset + 4] as u64) << 32) | |
| ((s[offset + 5] as u64) << 40) | |
| ((s[offset + 6] as u64) << 48) | |
| ((s[offset + 7] as u64) << 56) | |
} | |
const fn bytes_to_u64_tail(s: &[u8], offset: usize) -> u64 { | |
let mut left = s.len() - offset; | |
if left > 8 { | |
left = 8; | |
} | |
let mut i = 0; | |
let mut acc = 0u64; | |
while i < left { | |
acc |= (s[offset + i] as u64) << (i * 8); | |
i += 1; | |
} | |
return acc; | |
} | |
const fn murmur3_x64_128(s: &str) -> u128 { | |
let data = s.as_bytes(); | |
let nblocks = data.len() / 16; | |
let mut i = 0; | |
let mut h1: u64 = 0; | |
let mut h2: u64 = 0; | |
const C1: u64 = 0x87c37b91114253d5; | |
const C2: u64 = 0x4cf5ad432745937f; | |
// body | |
while i < nblocks { | |
let k1 = bytes_to_u64(data, i * 16 + 0); | |
let k2 = bytes_to_u64(data, i * 16 + 8); | |
h1 ^= k1 | |
.overflowing_mul(C1) | |
.0 | |
.rotate_left(31) | |
.overflowing_mul(C2) | |
.0; | |
h1 = h1 | |
.rotate_left(27) | |
.overflowing_add(h2) | |
.0 | |
.overflowing_mul(5) | |
.0 | |
.overflowing_add(0x52dce729) | |
.0; | |
h2 ^= k2 | |
.overflowing_mul(C2) | |
.0 | |
.rotate_left(33) | |
.overflowing_mul(C1) | |
.0; | |
h2 = h2 | |
.rotate_left(31) | |
.overflowing_add(h1) | |
.0 | |
.overflowing_mul(5) | |
.0 | |
.overflowing_add(0x38495ab5) | |
.0; | |
i += 1; | |
} | |
// tail | |
let left = data.len() - nblocks * 16; | |
if left > 8 { | |
let k2 = bytes_to_u64_tail(data, nblocks * 16 + 8); | |
h2 ^= k2 | |
.overflowing_mul(C2) | |
.0 | |
.rotate_left(33) | |
.overflowing_mul(C1) | |
.0; | |
} | |
if left > 0 { | |
let k1 = bytes_to_u64_tail(data, nblocks * 16); | |
h1 ^= k1 | |
.overflowing_mul(C1) | |
.0 | |
.rotate_left(31) | |
.overflowing_mul(C2) | |
.0; | |
} | |
h1 ^= s.len() as u64; | |
h2 ^= s.len() as u64; | |
h1 = h1.overflowing_add(h2).0; | |
h2 = h2.overflowing_add(h1).0; | |
h1 = fmix64(h1); | |
h2 = fmix64(h2); | |
h1 = h1.overflowing_add(h2).0; | |
h2 = h2.overflowing_add(h1).0; | |
return ((h1 as u128) << 64) | (h2 as u128); | |
} | |
const MY_ID_1: u128 = murmur3_x64_128("Hello, world"); | |
const MY_ID_2: u128 = murmur3_x64_128("hello, world"); | |
const MY_ID_3: u128 = murmur3_x64_128("Hello, world"); | |
fn main() { | |
assert_eq!(MY_ID_1, MY_ID_3); | |
assert!(MY_ID_1 != MY_ID_2); | |
println!("{:x} {:x} {:x}", MY_ID_1, MY_ID_2, MY_ID_3) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment