Skip to content

Commit

Permalink
Swap from fxhash to ahash. Closes #1.
Browse files Browse the repository at this point in the history
  • Loading branch information
willcrichton committed Nov 3, 2023
1 parent 913fbf5 commit 0e431be
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 12 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ default = ["bitvec"]
[dependencies]
bitvec = { version = "1.0.1", optional = true }
take_mut = { version = "0.2.2", optional = true }
fxhash = "0.2.1"
index_vec = "0.1.3"
splitmut = "0.2.1"
roaring = { version = "0.10.2", optional = true }
roaring = { version = "0.10.2", optional = true }
ahash = "0.8.6"
4 changes: 2 additions & 2 deletions src/domain.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use fxhash::FxHashMap as HashMap;
use ahash::AHashMap;
use index_vec::{Idx, IndexVec};
use std::fmt;

Expand All @@ -9,7 +9,7 @@ use crate::IndexedValue;
/// Contains a reverse-mapping from `T` to `T::Index` for efficient lookups of indices.
pub struct IndexedDomain<T: IndexedValue> {
domain: IndexVec<T::Index, T>,
reverse_map: HashMap<T, T::Index>,
reverse_map: AHashMap<T, T::Index>,
}

impl<T: IndexedValue> IndexedDomain<T> {
Expand Down
82 changes: 77 additions & 5 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ use std::{
ops::{Index, IndexMut},
};

use fxhash::FxHashMap;
use ahash::AHashMap;
use index_vec::{Idx, IndexVec};

use crate::{
pointer::{ArcFamily, PointerFamily, RcFamily, RefFamily},
IndexedDomain, IndexedValue, ToIndex,
FromIndexicalIterator, IndexedDomain, IndexedValue, ToIndex,
};

/// A mapping from indexed keys to values, implemented sparsely with a hash map.
///
/// This is more memory-efficient than the [`DenseIndexMap`] with a small
/// number of keys.
pub struct SparseIndexMap<'a, K: IndexedValue + 'a, V, P: PointerFamily<'a>> {
map: FxHashMap<K::Index, V>,
map: AHashMap<K::Index, V>,
domain: P::Pointer<IndexedDomain<K>>,
}

Expand All @@ -39,7 +39,7 @@ where
/// Constructs an empty map within the given domain.
pub fn new(domain: &P::Pointer<IndexedDomain<K>>) -> Self {
SparseIndexMap {
map: FxHashMap::default(),
map: AHashMap::default(),
domain: domain.clone(),
}
}
Expand Down Expand Up @@ -97,6 +97,18 @@ where
let idx = key.to_index(&self.domain);
self.map.entry(idx)
}

/// Returns the number of entries in the map.
#[inline]
pub fn len(&self) -> usize {
self.map.len()
}

/// Returns true if the map has no elements.
#[inline]
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
}

impl<'a, K, V, P> Index<K::Index> for SparseIndexMap<'a, K, V, P>
Expand All @@ -121,6 +133,40 @@ where
}
}

impl<'a, K, V, P, M, U> FromIndexicalIterator<'a, K, P, M, (U, V)> for SparseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
U: ToIndex<K, M>,
{
fn from_indexical_iter(
iter: impl Iterator<Item = (U, V)>,
domain: &P::Pointer<IndexedDomain<K>>,
) -> Self {
let map = iter
.map(|(u, v)| (u.to_index(domain), v))
.collect::<AHashMap<_, _>>();
SparseIndexMap {
map,
domain: domain.clone(),
}
}
}

impl<'a, 'b, K, V, P> IntoIterator for &'b SparseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a + 'b,
V: 'b,
P: PointerFamily<'a>,
{
type Item = (&'b K::Index, &'b V);
type IntoIter = hash_map::Iter<'b, K::Index, V>;

fn into_iter(self) -> Self::IntoIter {
self.map.iter()
}
}

/// A mapping from indexed keys to values, implemented densely with a vector.
///
/// This is more time-efficient than the [`SparseIndexMap`] for lookup,
Expand All @@ -147,8 +193,13 @@ where
/// Constructs a new map with an initial element of `mk_elem(i)` for each `i` in `domain`.
#[inline]
pub fn new(domain: &P::Pointer<IndexedDomain<K>>, mk_elem: impl FnMut(K::Index) -> V) -> Self {
Self::from_vec(domain, IndexVec::from_iter(domain.indices().map(mk_elem)))
}

#[inline]
fn from_vec(domain: &P::Pointer<IndexedDomain<K>>, map: IndexVec<K::Index, V>) -> Self {
DenseIndexMap {
map: IndexVec::from_iter(domain.indices().map(mk_elem)),
map,
domain: domain.clone(),
}
}
Expand Down Expand Up @@ -224,3 +275,24 @@ where
self.get_mut(index).unwrap()
}
}

impl<'a, K, V, P, M, U> FromIndexicalIterator<'a, K, P, M, (U, V)> for DenseIndexMap<'a, K, V, P>
where
K: IndexedValue + 'a,
P: PointerFamily<'a>,
U: ToIndex<K, M>,
{
fn from_indexical_iter(
iter: impl Iterator<Item = (U, V)>,
domain: &P::Pointer<IndexedDomain<K>>,
) -> Self {
let mut map = iter
.map(|(u, v)| (u.to_index(domain), v))
.collect::<AHashMap<_, _>>();
let vec = domain
.indices()
.map(|i| map.remove(&i).unwrap_or_else(|| panic!("Cannot use FromIndexicalIterator for a DenseIndexMap with a sparse key set")))
.collect::<IndexVec<_, _>>();
DenseIndexMap::from_vec(domain, vec)
}
}
6 changes: 3 additions & 3 deletions src/matrix.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use fxhash::FxHashMap;
use ahash::AHashMap;
use splitmut::SplitMut;
use std::{fmt, hash::Hash};

Expand All @@ -12,7 +12,7 @@ use crate::{
/// "Sparse" means "hash map from rows to bit-sets of columns". Subsequently, only column types `C` must be indexed,
/// while row types `R` only need be hashable.
pub struct IndexMatrix<'a, R, C: IndexedValue + 'a, S: BitSet, P: PointerFamily<'a>> {
pub(crate) matrix: FxHashMap<R, IndexSet<'a, C, S, P>>,
pub(crate) matrix: AHashMap<R, IndexSet<'a, C, S, P>>,
empty_set: IndexSet<'a, C, S, P>,
col_domain: P::Pointer<IndexedDomain<C>>,
}
Expand All @@ -27,7 +27,7 @@ where
/// Creates an empty matrix.
pub fn new(col_domain: &P::Pointer<IndexedDomain<C>>) -> Self {
IndexMatrix {
matrix: FxHashMap::default(),
matrix: AHashMap::default(),
empty_set: IndexSet::new(col_domain),
col_domain: col_domain.clone(),
}
Expand Down

0 comments on commit 0e431be

Please sign in to comment.