aboutsummaryrefslogtreecommitdiff
path: root/src/crates
diff options
context:
space:
mode:
authorAria Shrimpton <me@aria.rip>2024-01-25 11:31:26 +0000
committerAria Shrimpton <me@aria.rip>2024-01-25 11:31:26 +0000
commitce624ba5e537933744ac443891c6cf12d37abdee (patch)
treea6762b49e1d7aaa1d646047bd65df24b304d1c5e /src/crates
parent33e243e7fc96ad6ac9bf412a1384fd0bbcd02dc0 (diff)
add mapping trait & hashmap to library + benchmarker
Diffstat (limited to 'src/crates')
-rw-r--r--src/crates/benchmarker/Cargo.toml4
-rw-r--r--src/crates/benchmarker/benches/hashmap.rs7
-rw-r--r--src/crates/benchmarker/src/lib.rs2
-rw-r--r--src/crates/benchmarker/src/mapping.rs141
-rw-r--r--src/crates/library/src/eager_sorted_vector.rs8
-rw-r--r--src/crates/library/src/eager_unique_vector.rs8
-rw-r--r--src/crates/library/src/hashmap.rs41
-rw-r--r--src/crates/library/src/hashset.rs4
-rw-r--r--src/crates/library/src/lazy_sorted_vector.rs16
-rw-r--r--src/crates/library/src/lazy_unique_vector.rs18
-rw-r--r--src/crates/library/src/lib.rs1
-rw-r--r--src/crates/library/src/list.rs4
-rw-r--r--src/crates/library/src/profiler.rs92
-rw-r--r--src/crates/library/src/traits.rs29
-rw-r--r--src/crates/library/src/treeset.rs4
-rw-r--r--src/crates/library/src/vector.rs4
16 files changed, 321 insertions, 62 deletions
diff --git a/src/crates/benchmarker/Cargo.toml b/src/crates/benchmarker/Cargo.toml
index 3fffe5e..875ed26 100644
--- a/src/crates/benchmarker/Cargo.toml
+++ b/src/crates/benchmarker/Cargo.toml
@@ -17,3 +17,7 @@ harness = false
[[bench]]
name = "linked_list"
harness = false
+
+[[bench]]
+name = "hashmap"
+harness = false
diff --git a/src/crates/benchmarker/benches/hashmap.rs b/src/crates/benchmarker/benches/hashmap.rs
new file mode 100644
index 0000000..dbd498a
--- /dev/null
+++ b/src/crates/benchmarker/benches/hashmap.rs
@@ -0,0 +1,7 @@
+fn main() {
+ let ns = [
+ 64, 128, 256, 512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 16384, 24576, 32768,
+ 40960, 49152, 57344, 65536,
+ ];
+ candelabra_benchmarker::benchmark_mapping::<std::collections::HashMap<usize, usize>, _, _>(&ns);
+}
diff --git a/src/crates/benchmarker/src/lib.rs b/src/crates/benchmarker/src/lib.rs
index 3018f56..f449527 100644
--- a/src/crates/benchmarker/src/lib.rs
+++ b/src/crates/benchmarker/src/lib.rs
@@ -1,5 +1,6 @@
mod container;
mod indexable;
+mod mapping;
mod stack;
use std::{
@@ -9,6 +10,7 @@ use std::{
pub use container::*;
pub use indexable::*;
+pub use mapping::*;
pub use stack::*;
const WARM_UP_TIME: Duration = Duration::from_millis(500);
diff --git a/src/crates/benchmarker/src/mapping.rs b/src/crates/benchmarker/src/mapping.rs
new file mode 100644
index 0000000..b567b30
--- /dev/null
+++ b/src/crates/benchmarker/src/mapping.rs
@@ -0,0 +1,141 @@
+use primrose_library::traits::Mapping;
+use rand::{
+ distributions::{Distribution, Standard},
+ random, thread_rng, Rng,
+};
+
+use crate::{benchmark_op, print_result};
+
+pub fn benchmark_mapping<T, K, V>(ns: &[usize])
+where
+ T: Mapping<K, V> + Default + Clone,
+ K: Copy,
+ V: Copy,
+ Standard: Distribution<K> + Distribution<V>,
+{
+ for n in ns {
+ scenario_populate::<T, K, V>(*n);
+ scenario_contains::<T, K, V>(*n);
+ scenario_remove::<T, K, V>(*n);
+ scenario_clear::<T, K, V>(*n);
+ }
+}
+
+fn scenario_populate<T, K, V>(n: usize)
+where
+ T: Mapping<K, V> + Default + Clone,
+ K: Copy,
+ V: Copy,
+ Standard: Distribution<K> + Distribution<V>,
+{
+ let mut results = benchmark_op(
+ || {
+ (
+ T::default(),
+ (0..n)
+ .map(|_| (random(), random()))
+ .collect::<Vec<(K, V)>>(),
+ )
+ },
+ |(c, xs)| {
+ for (k, v) in xs {
+ c.insert(*k, *v);
+ }
+ },
+ );
+
+ // Since we've repeated n times in each run
+ results.min_nanos /= n as f64;
+ results.avg_nanos /= n as f64;
+ results.max_nanos /= n as f64;
+
+ print_result("insert", n, results);
+}
+
+fn scenario_contains<T, K, V>(n: usize)
+where
+ T: Mapping<K, V> + Default + Clone,
+ K: Copy,
+ V: Copy,
+ Standard: Distribution<K> + Distribution<V>,
+{
+ let results = benchmark_op(
+ || {
+ let mut rng = thread_rng();
+ let mut c = T::default();
+
+ // decide where the element that we will search for will be
+ let pivot = rng.gen_range(0..n);
+
+ // insert the element at pivot, and keep track of what it is
+ for _ in 0..pivot {
+ c.insert(random(), random());
+ }
+ let chosen = rng.gen();
+ c.insert(chosen, random());
+ for _ in pivot..n {
+ c.insert(random(), random());
+ }
+
+ (c, chosen)
+ },
+ |(c, chosen)| c.contains(chosen),
+ );
+
+ print_result("contains", n, results);
+}
+
+fn scenario_remove<T, K, V>(n: usize)
+where
+ T: Mapping<K, V> + Default + Clone,
+ K: Copy,
+ V: Copy,
+ Standard: Distribution<K> + Distribution<V>,
+{
+ let results = benchmark_op(
+ || {
+ let mut rng = thread_rng();
+ let mut c = T::default();
+
+ // decide where the element that we will search for will be
+ let pivot = rng.gen_range(0..n);
+
+ // insert the element at pivot, and keep track of what it is
+ for _ in 0..pivot {
+ c.insert(random(), random());
+ }
+ let chosen = rng.gen();
+ c.insert(chosen, random());
+ for _ in pivot..n {
+ c.insert(random(), random());
+ }
+
+ (c, chosen)
+ },
+ |(c, chosen)| c.remove(chosen),
+ );
+
+ print_result("remove", n, results);
+}
+
+fn scenario_clear<T, K, V>(n: usize)
+where
+ T: Mapping<K, V> + Default + Clone,
+ K: Copy,
+ V: Copy,
+ Standard: Distribution<K> + Distribution<V>,
+{
+ let results = benchmark_op(
+ || {
+ let mut c = T::default();
+
+ for _ in 0..n {
+ c.insert(random(), random());
+ }
+ c
+ },
+ |c| c.clear(),
+ );
+
+ print_result("clear", n, results);
+}
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)
}