diff options
author | Aria Shrimpton <me@aria.rip> | 2024-01-25 11:31:26 +0000 |
---|---|---|
committer | Aria Shrimpton <me@aria.rip> | 2024-01-25 11:31:26 +0000 |
commit | ce624ba5e537933744ac443891c6cf12d37abdee (patch) | |
tree | a6762b49e1d7aaa1d646047bd65df24b304d1c5e /src/crates/library | |
parent | 33e243e7fc96ad6ac9bf412a1384fd0bbcd02dc0 (diff) |
add mapping trait & hashmap to library + benchmarker
Diffstat (limited to 'src/crates/library')
-rw-r--r-- | src/crates/library/src/eager_sorted_vector.rs | 8 | ||||
-rw-r--r-- | src/crates/library/src/eager_unique_vector.rs | 8 | ||||
-rw-r--r-- | src/crates/library/src/hashmap.rs | 41 | ||||
-rw-r--r-- | src/crates/library/src/hashset.rs | 4 | ||||
-rw-r--r-- | src/crates/library/src/lazy_sorted_vector.rs | 16 | ||||
-rw-r--r-- | src/crates/library/src/lazy_unique_vector.rs | 18 | ||||
-rw-r--r-- | src/crates/library/src/lib.rs | 1 | ||||
-rw-r--r-- | src/crates/library/src/list.rs | 4 | ||||
-rw-r--r-- | src/crates/library/src/profiler.rs | 92 | ||||
-rw-r--r-- | src/crates/library/src/traits.rs | 29 | ||||
-rw-r--r-- | src/crates/library/src/treeset.rs | 4 | ||||
-rw-r--r-- | src/crates/library/src/vector.rs | 4 |
12 files changed, 167 insertions, 62 deletions
diff --git a/src/crates/library/src/eager_sorted_vector.rs b/src/crates/library/src/eager_sorted_vector.rs index 9be45d0..bf67105 100644 --- a/src/crates/library/src/eager_sorted_vector.rs +++ b/src/crates/library/src/eager_sorted_vector.rs @@ -23,7 +23,7 @@ impl<T: Ord> EagerSortedVec<T> { EagerSortedVec { v: Vec::new() } } - pub fn len(&mut self) -> usize { + pub fn len(&self) -> usize { self.v.len() } @@ -31,7 +31,7 @@ impl<T: Ord> EagerSortedVec<T> { self.v.binary_search(x).is_ok() } - pub fn is_empty(&mut self) -> bool { + pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -81,7 +81,7 @@ impl<T: Ord> Container<T> for EagerSortedVec<T> { (define (pre-len xs) (equal? xs (sort xs <))) (define (post-len xs r) (equal? r (op-len xs))) *ENDLIBSPEC*/ - fn len(&mut self) -> usize { + fn len(&self) -> usize { EagerSortedVec::len(self) } @@ -108,7 +108,7 @@ impl<T: Ord> Container<T> for EagerSortedVec<T> { (define (pre-is-empty xs) (equal? xs (sort xs <))) (define (post-is-empty xs r) (equal? r (op-is-empty xs))) *ENDLIBSPEC*/ - fn is_empty(&mut self) -> bool { + fn is_empty(&self) -> bool { EagerSortedVec::is_empty(self) } diff --git a/src/crates/library/src/eager_unique_vector.rs b/src/crates/library/src/eager_unique_vector.rs index b5e0284..632762b 100644 --- a/src/crates/library/src/eager_unique_vector.rs +++ b/src/crates/library/src/eager_unique_vector.rs @@ -28,7 +28,7 @@ impl<T: PartialEq> EagerUniqueVec<T> { EagerUniqueVec { v: Vec::new() } } - pub fn len(&mut self) -> usize { + pub fn len(&self) -> usize { self.v.len() } @@ -36,7 +36,7 @@ impl<T: PartialEq> EagerUniqueVec<T> { self.v.contains(x) } - pub fn is_empty(&mut self) -> bool { + pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -88,7 +88,7 @@ impl<T: Ord + PartialEq> Container<T> for EagerUniqueVec<T> { (define (pre-len xs) (equal? xs (remove-duplicates xs))) (define (post-len xs r) (equal? r (op-len xs))) *ENDLIBSPEC*/ - fn len(&mut self) -> usize { + fn len(&self) -> usize { EagerUniqueVec::len(self) } @@ -115,7 +115,7 @@ impl<T: Ord + PartialEq> Container<T> for EagerUniqueVec<T> { (define (pre-is-empty xs) (equal? xs (remove-duplicates xs))) (define (post-is-empty xs r) (equal? r (op-is-empty xs))) *ENDLIBSPEC*/ - fn is_empty(&mut self) -> bool { + fn is_empty(&self) -> bool { EagerUniqueVec::is_empty(self) } diff --git a/src/crates/library/src/hashmap.rs b/src/crates/library/src/hashmap.rs new file mode 100644 index 0000000..ace6453 --- /dev/null +++ b/src/crates/library/src/hashmap.rs @@ -0,0 +1,41 @@ +/*LIBSPEC-NAME* +rust-hashmap-spec std::collections::HashMap +*ENDLIBSPEC-NAME*/ + +use crate::traits::Mapping; +pub use std::collections::HashMap; +use std::hash::Hash; + +/*IMPL* +Mapping +*ENDIMPL*/ +impl<K: Ord + Hash, V> Mapping<K, V> for HashMap<K, V> { + fn len(&self) -> usize { + HashMap::len(self) + } + + fn contains(&mut self, x: &K) -> bool { + HashMap::contains_key(self, x) + } + + fn insert(&mut self, key: K, val: V) -> Option<V> { + HashMap::insert(self, key, val) + } + + fn get(&mut self, key: &K) -> Option<&V> { + HashMap::get(self, key) + } + + fn remove(&mut self, key: &K) -> Option<V> { + HashMap::remove(self, key) + } + + fn clear(&mut self) { + HashMap::clear(self) + } +} + +#[cfg(test)] +mod tests { + // TODO +} diff --git a/src/crates/library/src/hashset.rs b/src/crates/library/src/hashset.rs index d7d8915..f8f637c 100644 --- a/src/crates/library/src/hashset.rs +++ b/src/crates/library/src/hashset.rs @@ -18,7 +18,7 @@ impl<T: Ord + Hash> Container<T> for HashSet<T> { (define (pre-len xs) (equal? xs (remove-duplicates (sort xs <)))) (define (post-len xs r) (equal? r (op-len xs))) *ENDLIBSPEC*/ - fn len(&mut self) -> usize { + fn len(&self) -> usize { HashSet::len(self) } @@ -45,7 +45,7 @@ impl<T: Ord + Hash> Container<T> for HashSet<T> { (define (pre-is-empty xs) (equal? xs (remove-duplicates (sort xs <)))) (define (post-is-empty xs r) (equal? r (op-is-empty xs))) *ENDLIBSPEC*/ - fn is_empty(&mut self) -> bool { + fn is_empty(&self) -> bool { HashSet::is_empty(self) } diff --git a/src/crates/library/src/lazy_sorted_vector.rs b/src/crates/library/src/lazy_sorted_vector.rs index 5ead065..17cb7f6 100644 --- a/src/crates/library/src/lazy_sorted_vector.rs +++ b/src/crates/library/src/lazy_sorted_vector.rs @@ -27,11 +27,7 @@ impl<T: Ord> LazySortedVec<T> { } } - pub fn len(&mut self) -> usize { - if self.modified { - self.v.sort(); - self.modified = false; - } + pub fn len(&self) -> usize { self.v.len() } @@ -43,11 +39,7 @@ impl<T: Ord> LazySortedVec<T> { self.v.binary_search(x).is_ok() } - pub fn is_empty(&mut self) -> bool { - if self.modified { - self.v.sort(); - self.modified = false; - } + pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -117,7 +109,7 @@ impl<T: Ord> Container<T> for LazySortedVec<T> { (define (pre-len xs) (equal? xs (sort xs <))) (define (post-len xs r) (equal? r (op-len xs))) *ENDLIBSPEC*/ - fn len(&mut self) -> usize { + fn len(&self) -> usize { LazySortedVec::len(self) } @@ -144,7 +136,7 @@ impl<T: Ord> Container<T> for LazySortedVec<T> { (define (pre-is-empty xs) (equal? xs (sort xs <))) (define (post-is-empty xs r) (equal? r (op-is-empty xs))) *ENDLIBSPEC*/ - fn is_empty(&mut self) -> bool { + fn is_empty(&self) -> bool { LazySortedVec::is_empty(self) } diff --git a/src/crates/library/src/lazy_unique_vector.rs b/src/crates/library/src/lazy_unique_vector.rs index 9b5e60c..e9c24dc 100644 --- a/src/crates/library/src/lazy_unique_vector.rs +++ b/src/crates/library/src/lazy_unique_vector.rs @@ -28,12 +28,7 @@ impl<T: Ord> LazyUniqueVec<T> { LazyUniqueVec { v, modified: false } } - pub fn len(&mut self) -> usize { - if self.modified { - self.v.sort(); - self.v.dedup(); - self.modified = false; - } + pub fn len(&self) -> usize { self.v.len() } @@ -46,12 +41,7 @@ impl<T: Ord> LazyUniqueVec<T> { self.v.binary_search(x).is_ok() } - pub fn is_empty(&mut self) -> bool { - if self.modified { - self.v.sort(); - self.v.dedup(); - self.modified = false; - } + pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -127,7 +117,7 @@ impl<T: Ord> Container<T> for LazyUniqueVec<T> { (define (pre-len xs) (equal? xs (remove-duplicates (sort xs <)))) (define (post-len xs r) (equal? r (op-len xs))) *ENDLIBSPEC*/ - fn len(&mut self) -> usize { + fn len(&self) -> usize { LazyUniqueVec::len(self) } @@ -154,7 +144,7 @@ impl<T: Ord> Container<T> for LazyUniqueVec<T> { (define (pre-is-empty xs) (equal? xs (remove-duplicates (sort xs <)))) (define (post-is-empty xs r) (equal? r (op-is-empty xs))) *ENDLIBSPEC*/ - fn is_empty(&mut self) -> bool { + fn is_empty(&self) -> bool { LazyUniqueVec::is_empty(self) } diff --git a/src/crates/library/src/lib.rs b/src/crates/library/src/lib.rs index 1c39482..db5aac7 100644 --- a/src/crates/library/src/lib.rs +++ b/src/crates/library/src/lib.rs @@ -12,6 +12,7 @@ mod eager_unique_vector; mod lazy_sorted_vector; mod lazy_unique_vector; +mod hashmap; mod hashset; mod list; mod treeset; diff --git a/src/crates/library/src/list.rs b/src/crates/library/src/list.rs index 191b112..4ee045c 100644 --- a/src/crates/library/src/list.rs +++ b/src/crates/library/src/list.rs @@ -19,7 +19,7 @@ impl<T: Ord> Container<T> for LinkedList<T> { (define (pre-len xs) #t) (define (post-len xs r) (equal? r (op-len xs))) *ENDLIBSPEC*/ - fn len(&mut self) -> usize { + fn len(&self) -> usize { LinkedList::len(self) } @@ -46,7 +46,7 @@ impl<T: Ord> Container<T> for LinkedList<T> { (define (pre-is-empty xs) #t) (define (post-is-empty xs r) (equal? r (op-is-empty xs))) *ENDLIBSPEC*/ - fn is_empty(&mut self) -> bool { + fn is_empty(&self) -> bool { LinkedList::is_empty(self) } diff --git a/src/crates/library/src/profiler.rs b/src/crates/library/src/profiler.rs index 952d0a0..ba8c357 100644 --- a/src/crates/library/src/profiler.rs +++ b/src/crates/library/src/profiler.rs @@ -2,12 +2,13 @@ use std::{ env::var, fs::{create_dir, metadata, File}, io::Write, + marker::PhantomData, time::SystemTime, }; -use crate::traits::{Container, Indexable, Stack}; +use crate::traits::{Container, Indexable, Mapping, Stack}; -pub struct ProfilerWrapper<const ID: usize, T> { +pub struct ProfilerWrapper<const ID: usize, T, E> { inner: T, sum_ns: usize, n_contains: usize, @@ -19,9 +20,11 @@ pub struct ProfilerWrapper<const ID: usize, T> { n_nth: usize, n_push: usize, n_pop: usize, + n_get: usize, + _d: PhantomData<E>, } -impl<const ID: usize, T: Default> Default for ProfilerWrapper<ID, T> { +impl<const ID: usize, T: Default, E> Default for ProfilerWrapper<ID, T, E> { fn default() -> Self { Self { inner: T::default(), @@ -35,79 +38,131 @@ impl<const ID: usize, T: Default> Default for ProfilerWrapper<ID, T> { n_nth: 0, n_push: 0, n_pop: 0, + n_get: 0, + _d: Default::default(), } } } -impl<const ID: usize, T: Container<E>, E> Container<E> for ProfilerWrapper<ID, T> { - fn len(&mut self) -> usize { +impl<const ID: usize, T: Container<E>, E> ProfilerWrapper<ID, T, E> { + fn add_n(&mut self) { + self.sum_ns += self.inner.len(); + } +} + +impl<const ID: usize, T: Mapping<K, V>, K, V> ProfilerWrapper<ID, T, (K, V)> { + fn add_n_map(&mut self) { + self.sum_ns += self.inner.len(); + } +} + +impl<const ID: usize, T: Container<E>, E> Container<E> for ProfilerWrapper<ID, T, E> { + fn len(&self) -> usize { self.inner.len() } fn contains(&mut self, x: &E) -> bool { - self.sum_ns += self.inner.len(); + self.add_n(); self.n_contains += 1; self.inner.contains(x) } - fn is_empty(&mut self) -> bool { + fn is_empty(&self) -> bool { self.inner.is_empty() } fn insert(&mut self, elt: E) { - self.sum_ns += self.inner.len(); + self.add_n(); self.n_insert += 1; self.inner.insert(elt) } fn clear(&mut self) { - self.sum_ns += self.inner.len(); + self.add_n(); self.n_clear += 1; self.inner.clear() } fn remove(&mut self, elt: E) -> Option<E> { - self.sum_ns += self.inner.len(); + self.add_n(); self.n_remove += 1; self.inner.remove(elt) } } -impl<const ID: usize, T: Indexable<E> + Container<E>, E> Indexable<E> for ProfilerWrapper<ID, T> { +impl<const ID: usize, T: Indexable<E> + Container<E>, E> Indexable<E> + for ProfilerWrapper<ID, T, E> +{ fn first(&mut self) -> Option<&E> { - self.sum_ns += self.inner.len(); + self.add_n(); self.n_first += 1; self.inner.first() } fn last(&mut self) -> Option<&E> { - self.sum_ns += self.inner.len(); + self.add_n(); self.n_last += 1; self.inner.last() } fn nth(&mut self, n: usize) -> Option<&E> { - self.sum_ns += self.inner.len(); + self.add_n(); self.n_nth += 1; self.inner.nth(n) } } -impl<const ID: usize, T: Stack<E> + Container<E>, E> Stack<E> for ProfilerWrapper<ID, T> { +impl<const ID: usize, T: Stack<E> + Container<E>, E> Stack<E> for ProfilerWrapper<ID, T, E> { fn push(&mut self, elt: E) { - self.sum_ns += self.inner.len(); + self.add_n(); self.n_push += 1; self.inner.push(elt) } fn pop(&mut self) -> Option<E> { - self.sum_ns += self.inner.len(); + self.add_n(); self.n_pop += 1; self.inner.pop() } } -impl<const ID: usize, T> Drop for ProfilerWrapper<ID, T> { +impl<const ID: usize, T: Mapping<K, V>, K, V> Mapping<K, V> for ProfilerWrapper<ID, T, (K, V)> { + fn len(&self) -> usize { + self.inner.len() + } + + fn contains(&mut self, x: &K) -> bool { + self.add_n_map(); + self.n_contains += 1; + self.inner.contains(x) + } + + fn insert(&mut self, key: K, val: V) -> Option<V> { + self.add_n_map(); + self.n_insert += 1; + self.inner.insert(key, val) + } + + fn get(&mut self, key: &K) -> Option<&V> { + self.add_n_map(); + self.n_get += 1; + self.inner.get(key) + } + + fn remove(&mut self, key: &K) -> Option<V> { + self.add_n_map(); + self.n_remove += 1; + self.inner.remove(key) + } + + fn clear(&mut self) { + self.add_n_map(); + self.n_clear += 1; + self.inner.clear() + } +} + +impl<const ID: usize, T, E> Drop for ProfilerWrapper<ID, T, E> { fn drop(&mut self) { let base_dir = var("PROFILER_OUT_DIR").expect("ProfilerWrapper used without environment variable"); @@ -130,5 +185,6 @@ impl<const ID: usize, T> Drop for ProfilerWrapper<ID, T> { writeln!(f, "{}", self.n_nth).unwrap(); writeln!(f, "{}", self.n_push).unwrap(); writeln!(f, "{}", self.n_pop).unwrap(); + writeln!(f, "{}", self.n_get).unwrap(); } } diff --git a/src/crates/library/src/traits.rs b/src/crates/library/src/traits.rs index a29f7e0..bf4616a 100644 --- a/src/crates/library/src/traits.rs +++ b/src/crates/library/src/traits.rs @@ -1,10 +1,10 @@ //! Common traits for primrose container types pub trait Container<T>: Default { /// Get the current number of elements - fn len(&mut self) -> usize; + fn len(&self) -> usize; /// Check if the container is empty - fn is_empty(&mut self) -> bool; + fn is_empty(&self) -> bool; /// Check if the specified item is in the container fn contains(&mut self, x: &T) -> bool; @@ -29,3 +29,28 @@ pub trait Indexable<T> { fn last(&mut self) -> Option<&T>; fn nth(&mut self, n: usize) -> Option<&T>; } + +pub trait Mapping<K, V>: Default { + /// Get the current number of elements + fn len(&self) -> usize; + + /// Check if the container is empty + fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Check if the specified item is in the container + fn contains(&mut self, x: &K) -> bool; + + /// Insert the given item + fn insert(&mut self, key: K, val: V) -> Option<V>; + + /// Get the value for the given key + fn get(&mut self, key: &K) -> Option<&V>; + + /// Remove the first occurence of the given item + fn remove(&mut self, key: &K) -> Option<V>; + + /// Remove all elements from the container + fn clear(&mut self); +} diff --git a/src/crates/library/src/treeset.rs b/src/crates/library/src/treeset.rs index 4e2b213..f4f6923 100644 --- a/src/crates/library/src/treeset.rs +++ b/src/crates/library/src/treeset.rs @@ -17,7 +17,7 @@ impl<T: Ord> Container<T> for BTreeSet<T> { (define (pre-len xs) (equal? xs (remove-duplicates (sort xs <)))) (define (post-len xs r) (equal? r (op-len xs))) *ENDLIBSPEC*/ - fn len(&mut self) -> usize { + fn len(&self) -> usize { BTreeSet::len(self) } @@ -44,7 +44,7 @@ impl<T: Ord> Container<T> for BTreeSet<T> { (define (pre-is-empty xs) (equal? xs (remove-duplicates (sort xs <)))) (define (post-is-empty xs r) (equal? r (op-is-empty xs))) *ENDLIBSPEC*/ - fn is_empty(&mut self) -> bool { + fn is_empty(&self) -> bool { BTreeSet::is_empty(self) } diff --git a/src/crates/library/src/vector.rs b/src/crates/library/src/vector.rs index 38293c8..496f4f0 100644 --- a/src/crates/library/src/vector.rs +++ b/src/crates/library/src/vector.rs @@ -17,7 +17,7 @@ impl<T: PartialEq> Container<T> for Vec<T> { (define (pre-len xs) #t) (define (post-len xs r) (equal? r (op-len xs))) *ENDLIBSPEC*/ - fn len(&mut self) -> usize { + fn len(&self) -> usize { Vec::len(self) } @@ -44,7 +44,7 @@ impl<T: PartialEq> Container<T> for Vec<T> { (define (pre-is-empty xs) #t) (define (post-is-empty xs r) (equal? r (op-is-empty xs))) *ENDLIBSPEC*/ - fn is_empty(&mut self) -> bool { + fn is_empty(&self) -> bool { Vec::is_empty(self) } |