Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SecondaryMap for HashSet #62

Merged
merged 2 commits into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 118 additions & 14 deletions src/secondary.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
//! TODO
//! Trait definition for secondary maps from keys to values with default elements.

use std::iter::FusedIterator;
use std::collections::HashSet;
use std::{hash::Hash, iter::FusedIterator};

use bitvec::{
slice::{BitSlice, IterOnes},
vec::BitVec,
};

/// A map from keys to values that does not manage it's indices.
/// A map from keys to values with default elements.
///
/// Querying a key that has not been set returns a default value.
pub trait SecondaryMap<K, V> {
Expand All @@ -31,9 +32,6 @@ pub trait SecondaryMap<K, V> {
/// Increases the capacity of the secondary map to `capacity`.
fn ensure_capacity(&mut self, capacity: usize);

/// Resizes the secondary map to `new_len`.
fn resize(&mut self, new_len: usize);

/// Returns the maximum index the secondary map can contain without allocating.
fn capacity(&self) -> usize;

Expand Down Expand Up @@ -62,10 +60,26 @@ pub trait SecondaryMap<K, V> {
///
/// [`PortGraph::set_num_ports`]: crate::portgraph::PortGraph::set_num_ports
/// [`PortGraph::compact_nodes`]: crate::portgraph::PortGraph::compact_nodes
fn rekey(&mut self, old: K, new: Option<K>);
#[inline]
fn rekey(&mut self, old: K, new: Option<K>) {
let val = self.take(old);
if let Some(key) = new {
self.set(key, val);
}
}

/// Swaps the values of two keys.
fn swap(&mut self, key0: K, key1: K);
#[inline]
fn swap(&mut self, key0: K, key1: K)
where
K: Clone,
V: Clone,
{
let val0 = self.get(key0.clone()).clone();
let val1 = self.get(key1.clone()).clone();
self.set(key0, val1);
self.set(key1, val0);
}

/// Returns an iterator over the non-default entries of the secondary map.
fn iter<'a>(&'a self) -> Self::Iter<'a>
Expand Down Expand Up @@ -100,11 +114,6 @@ where
BitVec::reserve(self, capacity.saturating_sub(self.capacity()));
}

#[inline]
fn resize(&mut self, new_len: usize) {
BitVec::resize(self, new_len, false)
}

#[inline]
fn capacity(&self) -> usize {
BitVec::capacity(self)
Expand Down Expand Up @@ -228,4 +237,99 @@ where

impl<'a, K> FusedIterator for BitVecIter<'a, K> where K: TryFrom<usize> {}

// TODO: Implementations for HashSet, BTreeSet, HashMap, BTreeMap.
impl<K> SecondaryMap<K, bool> for HashSet<K>
where
K: Hash + Eq + Clone,
{
type Iter<'a> = HashSetIter<'a, K> where Self: 'a, K: 'a;

#[inline]
fn new() -> Self {
HashSet::new()
}

#[inline]
fn with_capacity(capacity: usize) -> Self {
HashSet::with_capacity(capacity)
}

#[inline]
fn default_value(&self) -> bool {
false
}

#[inline]
fn ensure_capacity(&mut self, capacity: usize) {
HashSet::reserve(self, capacity.saturating_sub(self.capacity()));
}

#[inline]
fn capacity(&self) -> usize {
HashSet::capacity(self)
}

#[inline]
fn get(&self, key: K) -> &bool {
if HashSet::contains(self, &key) {
&true
} else {
&false
}
Comment on lines +273 to +277
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if HashSet::contains(self, &key) {
&true
} else {
&false
}
&HashSet::contains(self, &key)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Annoyingly we cannot do that, because the return value of HashSet::contains(self, &key) is a local variable, where true and false can be statically defined :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is quite funny

}

#[inline]
fn set(&mut self, key: K, val: bool) {
match val {
true => HashSet::insert(self, key),
false => HashSet::remove(self, &key),
};
}

#[inline]
fn take(&mut self, key: K) -> bool {
HashSet::take(self, &key).is_some()
}

#[inline]
fn iter<'a>(&'a self) -> Self::Iter<'a>
where
K: 'a,
{
HashSetIter {
iter: HashSet::iter(self),
}
}
}

/// Iterator over non-default entries of a bit vector secondary map.
#[derive(Debug, Clone)]
pub struct HashSetIter<'a, K> {
iter: std::collections::hash_set::Iter<'a, K>,
}

impl<'a, K> Iterator for HashSetIter<'a, K>
where
K: Clone,
{
type Item = (K, &'a bool);

#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|k| (k.clone(), &true))
}

#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.iter.nth(n).map(|k| (k.clone(), &true))
}

#[inline]
fn count(self) -> usize {
self.iter.count()
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
10 changes: 0 additions & 10 deletions src/unmanaged.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
//! ```

use std::{
cmp::Ordering,
iter::{Enumerate, FusedIterator},
marker::PhantomData,
mem::{self, MaybeUninit},
Expand Down Expand Up @@ -340,15 +339,6 @@ where
UnmanagedDenseMap::ensure_capacity(self, capacity)
}

#[inline]
fn resize(&mut self, new_len: usize) {
match self.data.len().cmp(&new_len) {
Ordering::Less => self.ensure_capacity(new_len),
Ordering::Greater => self.shrink_to(new_len),
_ => {}
}
}

#[inline]
fn capacity(&self) -> usize {
UnmanagedDenseMap::capacity(self)
Expand Down