Skip to main content

rustymath_core/
hashing.rs

1//! The hash maps and sets rustymath uses. `Hashing` is foldhash's fast hasher with its fixed seed (`FixedState`), with `hash_one` marked `#[inline(always)]`. With one seed in every process, maps hash and iterate alike between runs, and instruction counts repeat. hashbrown 0.17 hashes every key through `BuildHasher::hash_one`, and core's default body for it has no inline hint, so incremental builds can call it out of line on every lookup.
2use std::hash::{BuildHasher, Hash, Hasher};
3
4#[derive(Clone, Default, Debug)]
5pub struct Hashing(foldhash::fast::FixedState);
6
7impl BuildHasher for Hashing {
8    type Hasher = foldhash::fast::FoldHasher<'static>;
9    #[inline(always)]
10    fn build_hasher(&self) -> Self::Hasher { self.0.build_hasher() }
11    #[inline(always)]
12    fn hash_one<T: Hash>(&self, x: T) -> u64 {
13        let mut h = self.build_hasher();
14        x.hash(&mut h);
15        h.finish()
16    }
17}
18
19pub type HashMap<K, V> = hashbrown::HashMap<K, V, Hashing>;
20pub type HashSet<K> = hashbrown::HashSet<K, Hashing>;
21
22/// `new` and `with_capacity` for `HashMap`, which hashbrown gives only for its default hasher.
23pub trait HashMapExt {
24    fn new() -> Self;
25    fn with_capacity(capacity: usize) -> Self;
26}
27impl<K, V> HashMapExt for HashMap<K, V> {
28    fn new() -> Self { Self::with_hasher(Hashing::default()) }
29    fn with_capacity(capacity: usize) -> Self { Self::with_capacity_and_hasher(capacity, Hashing::default()) }
30}
31
32/// `new` and `with_capacity` for `HashSet`, which hashbrown gives only for its default hasher.
33pub trait HashSetExt {
34    fn new() -> Self;
35    fn with_capacity(capacity: usize) -> Self;
36}
37impl<K> HashSetExt for HashSet<K> {
38    fn new() -> Self { Self::with_hasher(Hashing::default()) }
39    fn with_capacity(capacity: usize) -> Self { Self::with_capacity_and_hasher(capacity, Hashing::default()) }
40}