#[inline]
pub(crate) fn murmurhash3_x64_128(data: &[u8], seed: u32) -> (u64, u64) {
const C1: u64 = 0x87c3_7b91_1142_53d5;
const C2: u64 = 0x4cf5_ad43_2745_937f;
let len = data.len();
let nblocks = len / 16;
let mut h1 = u64::from(seed);
let mut h2 = u64::from(seed);
for i in 0..nblocks {
let off = i * 16;
let mut k1 = read_u64_le(data, off);
let mut k2 = read_u64_le(data, off + 8);
k1 = k1.wrapping_mul(C1);
k1 = k1.rotate_left(31);
k1 = k1.wrapping_mul(C2);
h1 ^= k1;
h1 = h1.rotate_left(27);
h1 = h1.wrapping_add(h2);
h1 = h1.wrapping_mul(5).wrapping_add(0x52dc_e729);
k2 = k2.wrapping_mul(C2);
k2 = k2.rotate_left(33);
k2 = k2.wrapping_mul(C1);
h2 ^= k2;
h2 = h2.rotate_left(31);
h2 = h2.wrapping_add(h1);
h2 = h2.wrapping_mul(5).wrapping_add(0x3849_5ab5);
}
let tail = &data[nblocks * 16..];
let n = tail.len(); let mut k1 = 0u64;
let mut k2 = 0u64;
if n >= 9 {
if n >= 15 {
k2 ^= u64::from(tail[14]) << 48;
}
if n >= 14 {
k2 ^= u64::from(tail[13]) << 40;
}
if n >= 13 {
k2 ^= u64::from(tail[12]) << 32;
}
if n >= 12 {
k2 ^= u64::from(tail[11]) << 24;
}
if n >= 11 {
k2 ^= u64::from(tail[10]) << 16;
}
if n >= 10 {
k2 ^= u64::from(tail[9]) << 8;
}
k2 ^= u64::from(tail[8]);
k2 = k2.wrapping_mul(C2);
k2 = k2.rotate_left(33);
k2 = k2.wrapping_mul(C1);
h2 ^= k2;
}
if n >= 1 {
if n >= 8 {
k1 ^= u64::from(tail[7]) << 56;
}
if n >= 7 {
k1 ^= u64::from(tail[6]) << 48;
}
if n >= 6 {
k1 ^= u64::from(tail[5]) << 40;
}
if n >= 5 {
k1 ^= u64::from(tail[4]) << 32;
}
if n >= 4 {
k1 ^= u64::from(tail[3]) << 24;
}
if n >= 3 {
k1 ^= u64::from(tail[2]) << 16;
}
if n >= 2 {
k1 ^= u64::from(tail[1]) << 8;
}
k1 ^= u64::from(tail[0]);
k1 = k1.wrapping_mul(C1);
k1 = k1.rotate_left(31);
k1 = k1.wrapping_mul(C2);
h1 ^= k1;
}
h1 ^= len as u64;
h2 ^= len as u64;
h1 = h1.wrapping_add(h2);
h2 = h2.wrapping_add(h1);
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 = h1.wrapping_add(h2);
h2 = h2.wrapping_add(h1);
(h1, h2)
}
#[inline]
pub(crate) fn murmur3_128_as_long_put_long_int(key: i64, index: i32) -> i64 {
let mut buf = [0u8; 12];
buf[..8].copy_from_slice(&key.to_le_bytes());
buf[8..].copy_from_slice(&index.to_le_bytes());
let (h1, _h2) = murmurhash3_x64_128(&buf, 0);
h1 as i64
}
#[inline]
fn read_u64_le(data: &[u8], off: usize) -> u64 {
u64::from_le_bytes(data[off..off + 8].try_into().unwrap())
}
#[inline]
fn fmix64(mut k: u64) -> u64 {
k ^= k >> 33;
k = k.wrapping_mul(0xff51_afd7_ed55_8ccd);
k ^= k >> 33;
k = k.wrapping_mul(0xc4ce_b9fe_1a85_ec53);
k ^= k >> 33;
k
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn guava_put_long_int_as_long_vectors() {
assert_eq!(murmur3_128_as_long_put_long_int(1, 0), 8673688779682957586);
assert_eq!(murmur3_128_as_long_put_long_int(42, 7), 1969424773395075097);
assert_eq!(
murmur3_128_as_long_put_long_int(100, 1),
-8854681018154386345
);
assert_eq!(murmur3_128_as_long_put_long_int(-1, 0), 7097917686268154775);
assert_eq!(murmur3_128_as_long_put_long_int(0, 0), -6568239567428591645);
assert_eq!(
murmur3_128_as_long_put_long_int(85429583872, 0),
-5867849384608515022
);
assert_eq!(
murmur3_128_as_long_put_long_int(8769479697893324776, 0),
-6296241382218419536
);
}
}