Skip to content

Instantly share code, notes, and snippets.

@stevenlr
Created June 2, 2020 21:36
Show Gist options
  • Save stevenlr/72bdfbed388e4134f64332c57ec181e6 to your computer and use it in GitHub Desktop.
Save stevenlr/72bdfbed388e4134f64332c57ec181e6 to your computer and use it in GitHub Desktop.
const fn murmur3 x64 128
#![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