Skip to content

Instantly share code, notes, and snippets.

@sstadick
Created January 21, 2025 22:23
Show Gist options
  • Select an option

  • Save sstadick/8c0631cbd8049480bddb7fc8b0436ec7 to your computer and use it in GitHub Desktop.

Select an option

Save sstadick/8c0631cbd8049480bddb7fc8b0436ec7 to your computer and use it in GitHub Desktop.
SplitMix64 Hasher for Rust u64
use std::hash::{BuildHasher, Hasher};
#[derive(Clone, Copy, Default)]
pub struct SplitMix64Hasher(u64);
impl Hasher for SplitMix64Hasher {
#[inline]
fn finish(&self) -> u64 {
self.0
}
fn write(&mut self, _bytes: &[u8]) {
panic!("This hasher only takes u64");
}
#[inline]
fn write_u64(&mut self, x: u64) {
// Mix the seed (stored in self.0) with input
let mut h = x;
h ^= h >> 30;
h = h.wrapping_mul(0xbf58476d1ce4e5b9);
h ^= h >> 27;
h = h.wrapping_mul(0x94d049bb133111eb);
h ^= h >> 31;
self.0 = h;
}
}
#[derive(Default)]
pub struct SplitMix64Builder;
impl BuildHasher for SplitMix64Builder {
type Hasher = SplitMix64Hasher;
fn build_hasher(&self) -> Self::Hasher {
Self::Hasher::default()
}
}
#[cfg(test)]
mod test {
use std::collections::HashMap;
use super::*;
use rstest::rstest;
#[rstest]
fn test_simple() {
let mut map: HashMap<u64, u32, SplitMix64Builder> = HashMap::with_hasher(SplitMix64Builder);
for i in 0..10000 {
map.insert(i, i as u32);
}
for i in 0..10000 {
assert_eq!(map.get(&(i as u64)), Some(&(i as u32)));
}
}
#[rstest]
#[should_panic]
fn test_non_u64() {
let mut map: HashMap<u32, u32, SplitMix64Builder> = HashMap::with_hasher(SplitMix64Builder);
for i in 0..10000 {
map.insert(i, i as u32);
}
for i in 0..10000 {
assert_eq!(map.get(&(i as u32)), Some(&(i as u32)));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment