use crate::kernel::ExprId;
use std::collections::{HashMap, HashSet};
use std::hash::{BuildHasherDefault, Hasher};
#[derive(Default, Clone, Copy)]
pub(crate) struct IdHasher(u64);
const SEED: u64 = 0x9E37_79B9_7F4A_7C15;
impl Hasher for IdHasher {
#[inline]
fn write(&mut self, bytes: &[u8]) {
for &b in bytes {
self.write_u64(u64::from(b));
}
}
#[inline]
fn write_u32(&mut self, n: u32) {
self.write_u64(u64::from(n));
}
#[inline]
fn write_u64(&mut self, n: u64) {
self.0 = (self.0.rotate_left(5) ^ n).wrapping_mul(SEED);
}
#[inline]
fn finish(&self) -> u64 {
self.0
}
}
pub(crate) type IdBuildHasher = BuildHasherDefault<IdHasher>;
pub(crate) type IdMap<V> = HashMap<ExprId, V, IdBuildHasher>;
pub(crate) type IdSet = HashSet<ExprId, IdBuildHasher>;
#[cfg(test)]
mod tests {
use super::*;
use crate::kernel::{Domain, ExprPool};
#[test]
fn behaves_like_a_map() {
let pool = ExprPool::new();
let ids: Vec<ExprId> = (0..1000).map(|i| pool.integer(i)).collect();
let mut m: IdMap<usize> = IdMap::default();
for (i, &id) in ids.iter().enumerate() {
m.insert(id, i);
}
let x = pool.symbol("x", Domain::Real);
assert_eq!(m.len(), 1000);
assert!(!m.contains_key(&x));
for (i, &id) in ids.iter().enumerate() {
assert_eq!(m[&id], i);
}
}
}