From 112c8a966fbdb52ff2a535dc8e6df3a8b3cb8fb2 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Thu, 30 Oct 2014 21:25:08 -0400 Subject: refactor libcollections as part of collection reform * Moves multi-collection files into their own directory, and splits them into seperate files * Changes exports so that each collection has its own module * Adds underscores to public modules and filenames to match standard naming conventions (that is, treemap::{TreeMap, TreeSet} => tree_map::TreeMap, tree_set::TreeSet) * Renames PriorityQueue to BinaryHeap * Renames SmallIntMap to VecMap * Miscellanious fallout fixes [breaking-change] --- src/doc/reference.md | 16 +- src/libcollections/binary_heap.rs | 698 ++++++ src/libcollections/bit.rs | 2764 ++++++++++++++++++++++ src/libcollections/bitv.rs | 2761 ---------------------- src/libcollections/btree/map.rs | 2 +- src/libcollections/btree/mod.rs | 25 +- src/libcollections/btree/set.rs | 2 +- src/libcollections/enum_set.rs | 2 +- src/libcollections/lib.rs | 66 +- src/libcollections/priority_queue.rs | 698 ------ src/libcollections/ring_buf.rs | 1152 +++++++++ src/libcollections/ringbuf.rs | 1152 --------- src/libcollections/smallintmap.rs | 1052 --------- src/libcollections/str.rs | 2 +- src/libcollections/tree/map.rs | 1918 +++++++++++++++ src/libcollections/tree/mod.rs | 36 + src/libcollections/tree/set.rs | 950 ++++++++ src/libcollections/treemap.rs | 2867 ----------------------- src/libcollections/trie.rs | 1899 --------------- src/libcollections/trie/map.rs | 1460 ++++++++++++ src/libcollections/trie/mod.rs | 20 + src/libcollections/trie/set.rs | 457 ++++ src/libcollections/vec_map.rs | 1052 +++++++++ src/librustc/driver/config.rs | 2 +- src/librustc/lint/builtin.rs | 2 +- src/librustc/metadata/creader.rs | 2 +- src/librustc/metadata/csearch.rs | 2 +- src/librustc/metadata/decoder.rs | 2 +- src/librustc/metadata/loader.rs | 2 +- src/librustc/middle/const_eval.rs | 2 +- src/librustc/middle/resolve.rs | 2 +- src/librustc/middle/traits/select.rs | 2 +- src/librustc/middle/ty.rs | 2 +- src/librustc/middle/typeck/check/_match.rs | 2 +- src/librustc/middle/typeck/check/mod.rs | 2 +- src/librustc/middle/typeck/check/regionck.rs | 2 +- src/librustc/middle/typeck/check/regionmanip.rs | 2 +- src/librustc/middle/typeck/infer/skolemize.rs | 10 +- src/librustdoc/html/render.rs | 2 +- src/librustdoc/lib.rs | 2 +- src/librustrt/local_data.rs | 2 +- src/libstd/collections/hash/bench.rs | 130 + src/libstd/collections/hash/map.rs | 2133 +++++++++++++++++ src/libstd/collections/hash/mod.rs | 16 + src/libstd/collections/hash/set.rs | 834 +++++++ src/libstd/collections/hash/table.rs | 907 +++++++ src/libstd/collections/hashmap/bench.rs | 130 - src/libstd/collections/hashmap/map.rs | 2133 ----------------- src/libstd/collections/hashmap/mod.rs | 33 - src/libstd/collections/hashmap/set.rs | 834 ------- src/libstd/collections/hashmap/table.rs | 907 ------- src/libstd/collections/mod.rs | 41 +- src/libsyntax/ext/mtwt.rs | 2 +- src/libtest/stats.rs | 8 +- src/test/bench/core-set.rs | 2 +- src/test/bench/std-smallintmap.rs | 8 +- src/test/run-fail/hashmap-capacity-overflow.rs | 2 +- src/test/run-pass/auto-encode.rs | 2 +- src/test/run-pass/while-let.rs | 6 +- 59 files changed, 14657 insertions(+), 14566 deletions(-) create mode 100644 src/libcollections/binary_heap.rs create mode 100644 src/libcollections/bit.rs delete mode 100644 src/libcollections/bitv.rs delete mode 100644 src/libcollections/priority_queue.rs create mode 100644 src/libcollections/ring_buf.rs delete mode 100644 src/libcollections/ringbuf.rs delete mode 100644 src/libcollections/smallintmap.rs create mode 100644 src/libcollections/tree/map.rs create mode 100644 src/libcollections/tree/mod.rs create mode 100644 src/libcollections/tree/set.rs delete mode 100644 src/libcollections/treemap.rs delete mode 100644 src/libcollections/trie.rs create mode 100644 src/libcollections/trie/map.rs create mode 100644 src/libcollections/trie/mod.rs create mode 100644 src/libcollections/trie/set.rs create mode 100644 src/libcollections/vec_map.rs create mode 100644 src/libstd/collections/hash/bench.rs create mode 100644 src/libstd/collections/hash/map.rs create mode 100644 src/libstd/collections/hash/mod.rs create mode 100644 src/libstd/collections/hash/set.rs create mode 100644 src/libstd/collections/hash/table.rs delete mode 100644 src/libstd/collections/hashmap/bench.rs delete mode 100644 src/libstd/collections/hashmap/map.rs delete mode 100644 src/libstd/collections/hashmap/mod.rs delete mode 100644 src/libstd/collections/hashmap/set.rs delete mode 100644 src/libstd/collections/hashmap/table.rs (limited to 'src') diff --git a/src/doc/reference.md b/src/doc/reference.md index 084309e9978..704311b37d9 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -944,10 +944,10 @@ An example of `use` declarations: ``` use std::iter::range_step; use std::option::{Some, None}; -use std::collections::hashmap::{mod, HashMap}; +use std::collections::hash_map::{mod, HashMap}; -# fn foo(_: T){} -# fn bar(map: HashMap, set: hashmap::HashSet){} +fn foo(_: T){} +fn bar(map1: HashMap, map2: hash_map::HashMap){} fn main() { // Equivalent to 'std::iter::range_step(0u, 10u, 2u);' @@ -957,10 +957,10 @@ fn main() { // std::option::None]);' foo(vec![Some(1.0f64), None]); - // Both `hash` and `HashMap` are in scope. - let map = HashMap::new(); - let set = hashmap::HashSet::new(); - bar(map, set); + // Both `hash_map` and `HashMap` are in scope. + let map1 = HashMap::new(); + let map2 = hash_map::HashMap::new(); + bar(map1, map2); } ``` @@ -4096,7 +4096,7 @@ cause transitions between the states. The lifecycle states of a task are: * running * blocked -* panicked +* panicked * dead A task begins its lifecycle — once it has been spawned — in the diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs new file mode 100644 index 00000000000..8481111ae91 --- /dev/null +++ b/src/libcollections/binary_heap.rs @@ -0,0 +1,698 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A priority queue implemented with a binary heap. +//! +//! Insertions have `O(log n)` time complexity and checking or popping the largest element is +//! `O(1)`. Converting a vector to a priority queue can be done in-place, and has `O(n)` +//! complexity. A priority queue can also be converted to a sorted vector in-place, allowing it to +//! be used for an `O(n log n)` in-place heapsort. +//! +//! # Example +//! +//! This is a larger example which implements [Dijkstra's algorithm][dijkstra] +//! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph]. +//! It showcases how to use the `BinaryHeap` with custom types. +//! +//! [dijkstra]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm +//! [sssp]: http://en.wikipedia.org/wiki/Shortest_path_problem +//! [dir_graph]: http://en.wikipedia.org/wiki/Directed_graph +//! +//! ``` +//! use std::collections::BinaryHeap; +//! use std::uint; +//! +//! #[deriving(Eq, PartialEq)] +//! struct State { +//! cost: uint, +//! position: uint +//! } +//! +//! // The priority queue depends on `Ord`. +//! // Explicitly implement the trait so the queue becomes a min-heap +//! // instead of a max-heap. +//! impl Ord for State { +//! fn cmp(&self, other: &State) -> Ordering { +//! // Notice that the we flip the ordering here +//! other.cost.cmp(&self.cost) +//! } +//! } +//! +//! // `PartialOrd` needs to be implemented as well. +//! impl PartialOrd for State { +//! fn partial_cmp(&self, other: &State) -> Option { +//! Some(self.cmp(other)) +//! } +//! } +//! +//! // Each node is represented as an `uint`, for a shorter implementation. +//! struct Edge { +//! node: uint, +//! cost: uint +//! } +//! +//! // Dijkstra's shortest path algorithm. +//! +//! // Start at `start` and use `dist` to track the current shortest distance +//! // to each node. This implementation isn't memory efficient as it may leave duplicate +//! // nodes in the queue. It also uses `uint::MAX` as a sentinel value, +//! // for a simpler implementation. +//! fn shortest_path(adj_list: &Vec>, start: uint, goal: uint) -> uint { +//! // dist[node] = current shortest distance from `start` to `node` +//! let mut dist = Vec::from_elem(adj_list.len(), uint::MAX); +//! +//! let mut pq = BinaryHeap::new(); +//! +//! // We're at `start`, with a zero cost +//! dist[start] = 0u; +//! pq.push(State { cost: 0u, position: start }); +//! +//! // Examine the frontier with lower cost nodes first (min-heap) +//! loop { +//! let State { cost, position } = match pq.pop() { +//! None => break, // empty +//! Some(s) => s +//! }; +//! +//! // Alternatively we could have continued to find all shortest paths +//! if position == goal { return cost } +//! +//! // Important as we may have already found a better way +//! if cost > dist[position] { continue } +//! +//! // For each node we can reach, see if we can find a way with +//! // a lower cost going through this node +//! for edge in adj_list[position].iter() { +//! let next = State { cost: cost + edge.cost, position: edge.node }; +//! +//! // If so, add it to the frontier and continue +//! if next.cost < dist[next.position] { +//! pq.push(next); +//! // Relaxation, we have now found a better way +//! dist[next.position] = next.cost; +//! } +//! } +//! } +//! +//! // Goal not reachable +//! uint::MAX +//! } +//! +//! fn main() { +//! // This is the directed graph we're going to use. +//! // The node numbers correspond to the different states, +//! // and the edge weights symbolises the cost of moving +//! // from one node to another. +//! // Note that the edges are one-way. +//! // +//! // 7 +//! // +-----------------+ +//! // | | +//! // v 1 2 | +//! // 0 -----> 1 -----> 3 ---> 4 +//! // | ^ ^ ^ +//! // | | 1 | | +//! // | | | 3 | 1 +//! // +------> 2 -------+ | +//! // 10 | | +//! // +---------------+ +//! // +//! // The graph is represented as an adjacency list where each index, +//! // corresponding to a node value, has a list of outgoing edges. +//! // Chosen for it's efficiency. +//! let graph = vec![ +//! // Node 0 +//! vec![Edge { node: 2, cost: 10 }, +//! Edge { node: 1, cost: 1 }], +//! // Node 1 +//! vec![Edge { node: 3, cost: 2 }], +//! // Node 2 +//! vec![Edge { node: 1, cost: 1 }, +//! Edge { node: 3, cost: 3 }, +//! Edge { node: 4, cost: 1 }], +//! // Node 3 +//! vec![Edge { node: 0, cost: 7 }, +//! Edge { node: 4, cost: 2 }], +//! // Node 4 +//! vec![]]; +//! +//! assert_eq!(shortest_path(&graph, 0, 1), 1); +//! assert_eq!(shortest_path(&graph, 0, 3), 3); +//! assert_eq!(shortest_path(&graph, 3, 0), 7); +//! assert_eq!(shortest_path(&graph, 0, 4), 5); +//! assert_eq!(shortest_path(&graph, 4, 0), uint::MAX); +//! } +//! ``` + +#![allow(missing_docs)] + +use core::prelude::*; + +use core::default::Default; +use core::mem::{zeroed, replace, swap}; +use core::ptr; + +use slice; +use vec::Vec; + +/// A priority queue implemented with a binary heap. +/// +/// This will be a max-heap. +#[deriving(Clone)] +pub struct BinaryHeap { + data: Vec, +} + +impl Default for BinaryHeap { + #[inline] + fn default() -> BinaryHeap { BinaryHeap::new() } +} + +impl BinaryHeap { + /// Creates an empty `BinaryHeap` as a max-heap. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let pq: BinaryHeap = BinaryHeap::new(); + /// ``` + pub fn new() -> BinaryHeap { BinaryHeap{data: vec!(),} } + + /// Creates an empty `BinaryHeap` with a specific capacity. + /// This preallocates enough memory for `capacity` elements, + /// so that the `BinaryHeap` does not have to be reallocated + /// until it contains at least that many values. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let pq: BinaryHeap = BinaryHeap::with_capacity(10u); + /// ``` + pub fn with_capacity(capacity: uint) -> BinaryHeap { + BinaryHeap { data: Vec::with_capacity(capacity) } + } + + /// Creates a `BinaryHeap` from a vector. This is sometimes called + /// `heapifying` the vector. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let pq = BinaryHeap::from_vec(vec![9i, 1, 2, 7, 3, 2]); + /// ``` + pub fn from_vec(xs: Vec) -> BinaryHeap { + let mut q = BinaryHeap{data: xs,}; + let mut n = q.len() / 2; + while n > 0 { + n -= 1; + q.siftdown(n) + } + q + } + + /// An iterator visiting all values in underlying vector, in + /// arbitrary order. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let pq = BinaryHeap::from_vec(vec![1i, 2, 3, 4]); + /// + /// // Print 1, 2, 3, 4 in arbitrary order + /// for x in pq.iter() { + /// println!("{}", x); + /// } + /// ``` + pub fn iter<'a>(&'a self) -> Items<'a, T> { + Items { iter: self.data.iter() } + } + + /// Returns the greatest item in a queue, or `None` if it is empty. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut pq = BinaryHeap::new(); + /// assert_eq!(pq.top(), None); + /// + /// pq.push(1i); + /// pq.push(5i); + /// pq.push(2i); + /// assert_eq!(pq.top(), Some(&5i)); + /// + /// ``` + pub fn top<'a>(&'a self) -> Option<&'a T> { + if self.is_empty() { None } else { Some(&self.data[0]) } + } + + /// Returns the number of elements the queue can hold without reallocating. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let pq: BinaryHeap = BinaryHeap::with_capacity(100u); + /// assert!(pq.capacity() >= 100u); + /// ``` + pub fn capacity(&self) -> uint { self.data.capacity() } + + /// Reserves capacity for exactly `n` elements in the `BinaryHeap`. + /// Do nothing if the capacity is already sufficient. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut pq: BinaryHeap = BinaryHeap::new(); + /// pq.reserve_exact(100u); + /// assert!(pq.capacity() == 100u); + /// ``` + pub fn reserve_exact(&mut self, n: uint) { self.data.reserve_exact(n) } + + /// Reserves capacity for at least `n` elements in the `BinaryHeap`. + /// Do nothing if the capacity is already sufficient. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut pq: BinaryHeap = BinaryHeap::new(); + /// pq.reserve(100u); + /// assert!(pq.capacity() >= 100u); + /// ``` + pub fn reserve(&mut self, n: uint) { + self.data.reserve(n) + } + + /// Removes the greatest item from a queue and returns it, or `None` if it + /// is empty. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut pq = BinaryHeap::from_vec(vec![1i, 3]); + /// + /// assert_eq!(pq.pop(), Some(3i)); + /// assert_eq!(pq.pop(), Some(1i)); + /// assert_eq!(pq.pop(), None); + /// ``` + pub fn pop(&mut self) -> Option { + match self.data.pop() { + None => { None } + Some(mut item) => { + if !self.is_empty() { + swap(&mut item, &mut self.data[0]); + self.siftdown(0); + } + Some(item) + } + } + } + + /// Pushes an item onto the queue. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut pq = BinaryHeap::new(); + /// pq.push(3i); + /// pq.push(5i); + /// pq.push(1i); + /// + /// assert_eq!(pq.len(), 3); + /// assert_eq!(pq.top(), Some(&5i)); + /// ``` + pub fn push(&mut self, item: T) { + self.data.push(item); + let new_len = self.len() - 1; + self.siftup(0, new_len); + } + + /// Pushes an item onto a queue then pops the greatest item off the queue in + /// an optimized fashion. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut pq = BinaryHeap::new(); + /// pq.push(1i); + /// pq.push(5i); + /// + /// assert_eq!(pq.push_pop(3i), 5); + /// assert_eq!(pq.push_pop(9i), 9); + /// assert_eq!(pq.len(), 2); + /// assert_eq!(pq.top(), Some(&3i)); + /// ``` + pub fn push_pop(&mut self, mut item: T) -> T { + if !self.is_empty() && *self.top().unwrap() > item { + swap(&mut item, &mut self.data[0]); + self.siftdown(0); + } + item + } + + /// Pops the greatest item off a queue then pushes an item onto the queue in + /// an optimized fashion. The push is done regardless of whether the queue + /// was empty. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut pq = BinaryHeap::new(); + /// + /// assert_eq!(pq.replace(1i), None); + /// assert_eq!(pq.replace(3i), Some(1i)); + /// assert_eq!(pq.len(), 1); + /// assert_eq!(pq.top(), Some(&3i)); + /// ``` + pub fn replace(&mut self, mut item: T) -> Option { + if !self.is_empty() { + swap(&mut item, &mut self.data[0]); + self.siftdown(0); + Some(item) + } else { + self.push(item); + None + } + } + + /// Consumes the `BinaryHeap` and returns the underlying vector + /// in arbitrary order. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let pq = BinaryHeap::from_vec(vec![1i, 2, 3, 4, 5, 6, 7]); + /// let vec = pq.into_vec(); + /// + /// // Will print in some order + /// for x in vec.iter() { + /// println!("{}", x); + /// } + /// ``` + pub fn into_vec(self) -> Vec { let BinaryHeap{data: v} = self; v } + + /// Consumes the `BinaryHeap` and returns a vector in sorted + /// (ascending) order. + /// + /// # Example + /// + /// ``` + /// use std::collections::BinaryHeap; + /// + /// let mut pq = BinaryHeap::from_vec(vec![1i, 2, 4, 5, 7]); + /// pq.push(6); + /// pq.push(3); + /// + /// let vec = pq.into_sorted_vec(); + /// assert_eq!(vec, vec![1i, 2, 3, 4, 5, 6, 7]); + /// ``` + pub fn into_sorted_vec(self) -> Vec { + let mut q = self; + let mut end = q.len(); + while end > 1 { + end -= 1; + q.data.as_mut_slice().swap(0, end); + q.siftdown_range(0, end) + } + q.into_vec() + } + + // The implementations of siftup and siftdown use unsafe blocks in + // order to move an element out of the vector (leaving behind a + // zeroed element), shift along the others and move it back into the + // vector over the junk element. This reduces the constant factor + // compared to using swaps, which involves twice as many moves. + fn siftup(&mut self, start: uint, mut pos: uint) { + unsafe { + let new = replace(&mut self.data[pos], zeroed()); + + while pos > start { + let parent = (pos - 1) >> 1; + if new > self.data[parent] { + let x = replace(&mut self.data[parent], zeroed()); + ptr::write(&mut self.data[pos], x); + pos = parent; + continue + } + break + } + ptr::write(&mut self.data[pos], new); + } + } + + fn siftdown_range(&mut self, mut pos: uint, end: uint) { + unsafe { + let start = pos; + let new = replace(&mut self.data[pos], zeroed()); + + let mut child = 2 * pos + 1; + while child < end { + let right = child + 1; + if right < end && !(self.data[child] > self.data[right]) { + child = right; + } + let x = replace(&mut self.data[child], zeroed()); + ptr::write(&mut self.data[pos], x); + pos = child; + child = 2 * pos + 1; + } + + ptr::write(&mut self.data[pos], new); + self.siftup(start, pos); + } + } + + fn siftdown(&mut self, pos: uint) { + let len = self.len(); + self.siftdown_range(pos, len); + } + + /// Returns the length of the queue. + pub fn len(&self) -> uint { self.data.len() } + + /// Returns true if the queue contains no elements + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Drops all items from the queue. + pub fn clear(&mut self) { self.data.truncate(0) } +} + +/// `BinaryHeap` iterator. +pub struct Items <'a, T:'a> { + iter: slice::Items<'a, T>, +} + +impl<'a, T> Iterator<&'a T> for Items<'a, T> { + #[inline] + fn next(&mut self) -> Option<(&'a T)> { self.iter.next() } + + #[inline] + fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } +} + +impl FromIterator for BinaryHeap { + fn from_iter>(mut iter: Iter) -> BinaryHeap { + let vec: Vec = iter.collect(); + BinaryHeap::from_vec(vec) + } +} + +impl Extendable for BinaryHeap { + fn extend>(&mut self, mut iter: Iter) { + let (lower, _) = iter.size_hint(); + + let len = self.capacity(); + self.reserve(len + lower); + + for elem in iter { + self.push(elem); + } + } +} + +#[cfg(test)] +mod tests { + use std::prelude::*; + + use super::BinaryHeap; + use vec::Vec; + + #[test] + fn test_iterator() { + let data = vec!(5i, 9, 3); + let iterout = [9i, 5, 3]; + let pq = BinaryHeap::from_vec(data); + let mut i = 0; + for el in pq.iter() { + assert_eq!(*el, iterout[i]); + i += 1; + } + } + + #[test] + fn test_top_and_pop() { + let data = vec!(2u, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1); + let mut sorted = data.clone(); + sorted.sort(); + let mut heap = BinaryHeap::from_vec(data); + while !heap.is_empty() { + assert_eq!(heap.top().unwrap(), sorted.last().unwrap()); + assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); + } + } + + #[test] + fn test_push() { + let mut heap = BinaryHeap::from_vec(vec!(2i, 4, 9)); + assert_eq!(heap.len(), 3); + assert!(*heap.top().unwrap() == 9); + heap.push(11); + assert_eq!(heap.len(), 4); + assert!(*heap.top().unwrap() == 11); + heap.push(5); + assert_eq!(heap.len(), 5); + assert!(*heap.top().unwrap() == 11); + heap.push(27); + assert_eq!(heap.len(), 6); + assert!(*heap.top().unwrap() == 27); + heap.push(3); + assert_eq!(heap.len(), 7); + assert!(*heap.top().unwrap() == 27); + heap.push(103); + assert_eq!(heap.len(), 8); + assert!(*heap.top().unwrap() == 103); + } + + #[test] + fn test_push_unique() { + let mut heap = BinaryHeap::from_vec(vec!(box 2i, box 4, box 9)); + assert_eq!(heap.len(), 3); + assert!(*heap.top().unwrap() == box 9); + heap.push(box 11); + assert_eq!(heap.len(), 4); + assert!(*heap.top().unwrap() == box 11); + heap.push(box 5); + assert_eq!(heap.len(), 5); + assert!(*heap.top().unwrap() == box 11); + heap.push(box 27); + assert_eq!(heap.len(), 6); + assert!(*heap.top().unwrap() == box 27); + heap.push(box 3); + assert_eq!(heap.len(), 7); + assert!(*heap.top().unwrap() == box 27); + heap.push(box 103); + assert_eq!(heap.len(), 8); + assert!(*heap.top().unwrap() == box 103); + } + + #[test] + fn test_push_pop() { + let mut heap = BinaryHeap::from_vec(vec!(5i, 5, 2, 1, 3)); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(6), 6); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(0), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(4), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(1), 4); + assert_eq!(heap.len(), 5); + } + + #[test] + fn test_replace() { + let mut heap = BinaryHeap::from_vec(vec!(5i, 5, 2, 1, 3)); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(6).unwrap(), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(0).unwrap(), 6); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(4).unwrap(), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(1).unwrap(), 4); + assert_eq!(heap.len(), 5); + } + + fn check_to_vec(mut data: Vec) { + let heap = BinaryHeap::from_vec(data.clone()); + let mut v = heap.clone().into_vec(); + v.sort(); + data.sort(); + + assert_eq!(v.as_slice(), data.as_slice()); + assert_eq!(heap.into_sorted_vec().as_slice(), data.as_slice()); + } + + #[test] + fn test_to_vec() { + check_to_vec(vec!()); + check_to_vec(vec!(5i)); + check_to_vec(vec!(3i, 2)); + check_to_vec(vec!(2i, 3)); + check_to_vec(vec!(5i, 1, 2)); + check_to_vec(vec!(1i, 100, 2, 3)); + check_to_vec(vec!(1i, 3, 5, 7, 9, 2, 4, 6, 8, 0)); + check_to_vec(vec!(2i, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1)); + check_to_vec(vec!(9i, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0)); + check_to_vec(vec!(0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); + check_to_vec(vec!(10i, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + check_to_vec(vec!(0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2)); + check_to_vec(vec!(5i, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1)); + } + + #[test] + fn test_empty_pop() { + let mut heap: BinaryHeap = BinaryHeap::new(); + assert!(heap.pop().is_none()); + } + + #[test] + fn test_empty_top() { + let empty: BinaryHeap = BinaryHeap::new(); + assert!(empty.top().is_none()); + } + + #[test] + fn test_empty_replace() { + let mut heap: BinaryHeap = BinaryHeap::new(); + heap.replace(5).is_none(); + } + + #[test] + fn test_from_iter() { + let xs = vec!(9u, 8, 7, 6, 5, 4, 3, 2, 1); + + let mut q: BinaryHeap = xs.as_slice().iter().rev().map(|&x| x).collect(); + + for &x in xs.iter() { + assert_eq!(q.pop().unwrap(), x); + } + } +} diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs new file mode 100644 index 00000000000..b7085c96aed --- /dev/null +++ b/src/libcollections/bit.rs @@ -0,0 +1,2764 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// FIXME(Gankro): Bitv and BitvSet are very tightly coupled. Ideally (for maintenance), +// they should be in separate files/modules, with BitvSet only using Bitv's public API. + +//! Collections implemented with bit vectors. +//! +//! # Example +//! +//! This is a simple example of the [Sieve of Eratosthenes][sieve] +//! which calculates prime numbers up to a given limit. +//! +//! [sieve]: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes +//! +//! ``` +//! use std::collections::{BitvSet, Bitv}; +//! use std::iter; +//! +//! let max_prime = 10000; +//! +//! // Store the primes as a BitvSet +//! let primes = { +//! // Assume all numbers are prime to begin, and then we +//! // cross off non-primes progressively +//! let mut bv = Bitv::with_capacity(max_prime, true); +//! +//! // Neither 0 nor 1 are prime +//! bv.set(0, false); +//! bv.set(1, false); +//! +//! for i in iter::range_inclusive(2, (max_prime as f64).sqrt() as uint) { +//! // if i is a prime +//! if bv[i] { +//! // Mark all multiples of i as non-prime (any multiples below i * i +//! // will have been marked as non-prime previously) +//! for j in iter::range_step(i * i, max_prime, i) { bv.set(j, false) } +//! } +//! } +//! BitvSet::from_bitv(bv) +//! }; +//! +//! // Simple primality tests below our max bound +//! let print_primes = 20; +//! print!("The primes below {} are: ", print_primes); +//! for x in range(0, print_primes) { +//! if primes.contains(&x) { +//! print!("{} ", x); +//! } +//! } +//! println!(""); +//! +//! // We can manipulate the internal Bitv +//! let num_primes = primes.get_ref().iter().filter(|x| *x).count(); +//! println!("There are {} primes below {}", num_primes, max_prime); +//! ``` + +use core::prelude::*; + +use core::cmp; +use core::default::Default; +use core::fmt; +use core::iter::{Chain, Enumerate, Repeat, Skip, Take}; +use core::iter; +use core::slice; +use core::u32; +use std::hash; + +use vec::Vec; + +type MatchWords<'a> = Chain, Skip>>>>; +// Take two BitV's, and return iterators of their words, where the shorter one +// has been padded with 0's +fn match_words <'a,'b>(a: &'a Bitv, b: &'b Bitv) -> (MatchWords<'a>, MatchWords<'b>) { + let a_len = a.storage.len(); + let b_len = b.storage.len(); + + // have to uselessly pretend to pad the longer one for type matching + if a_len < b_len { + (a.mask_words(0).chain(Repeat::new(0u32).enumerate().take(b_len).skip(a_len)), + b.mask_words(0).chain(Repeat::new(0u32).enumerate().take(0).skip(0))) + } else { + (a.mask_words(0).chain(Repeat::new(0u32).enumerate().take(0).skip(0)), + b.mask_words(0).chain(Repeat::new(0u32).enumerate().take(a_len).skip(b_len))) + } +} + +static TRUE: bool = true; +static FALSE: bool = false; + +/// The bitvector type. +/// +/// # Example +/// +/// ```rust +/// use collections::Bitv; +/// +/// let mut bv = Bitv::with_capacity(10, false); +/// +/// // insert all primes less than 10 +/// bv.set(2, true); +/// bv.set(3, true); +/// bv.set(5, true); +/// bv.set(7, true); +/// println!("{}", bv.to_string()); +/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count()); +/// +/// // flip all values in bitvector, producing non-primes less than 10 +/// bv.negate(); +/// println!("{}", bv.to_string()); +/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count()); +/// +/// // reset bitvector to empty +/// bv.clear(); +/// println!("{}", bv.to_string()); +/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count()); +/// ``` +pub struct Bitv { + /// Internal representation of the bit vector + storage: Vec, + /// The number of valid bits in the internal representation + nbits: uint +} + +impl Index for Bitv { + #[inline] + fn index<'a>(&'a self, i: &uint) -> &'a bool { + if self.get(*i) { + &TRUE + } else { + &FALSE + } + } +} + +struct MaskWords<'a> { + iter: slice::Items<'a, u32>, + next_word: Option<&'a u32>, + last_word_mask: u32, + offset: uint +} + +impl<'a> Iterator<(uint, u32)> for MaskWords<'a> { + /// Returns (offset, word) + #[inline] + fn next<'a>(&'a mut self) -> Option<(uint, u32)> { + let ret = self.next_word; + match ret { + Some(&w) => { + self.next_word = self.iter.next(); + self.offset += 1; + // The last word may need to be masked + if self.next_word.is_none() { + Some((self.offset - 1, w & self.last_word_mask)) + } else { + Some((self.offset - 1, w)) + } + }, + None => None + } + } +} + +impl Bitv { + #[inline] + fn process(&mut self, other: &Bitv, op: |u32, u32| -> u32) -> bool { + let len = other.storage.len(); + assert_eq!(self.storage.len(), len); + let mut changed = false; + // Notice: `a` is *not* masked here, which is fine as long as + // `op` is a bitwise operation, since any bits that should've + // been masked were fine to change anyway. `b` is masked to + // make sure its unmasked bits do not cause damage. + for (a, (_, b)) in self.storage.iter_mut() + .zip(other.mask_words(0)) { + let w = op(*a, b); + if *a != w { + changed = true; + *a = w; + } + } + changed + } + + #[inline] + fn mask_words<'a>(&'a self, mut start: uint) -> MaskWords<'a> { + if start > self.storage.len() { + start = self.storage.len(); + } + let mut iter = self.storage[start..].iter(); + MaskWords { + next_word: iter.next(), + iter: iter, + last_word_mask: { + let rem = self.nbits % u32::BITS; + if rem > 0 { + (1 << rem) - 1 + } else { !0 } + }, + offset: start + } + } + + /// Creates an empty `Bitv`. + /// + /// # Example + /// + /// ``` + /// use std::collections::Bitv; + /// let mut bv = Bitv::new(); + /// ``` + pub fn new() -> Bitv { + Bitv { storage: Vec::new(), nbits: 0 } + } + + /// Creates a `Bitv` that holds `nbits` elements, setting each element + /// to `init`. + /// + /// # Example + /// + /// ``` + /// use std::collections::Bitv; + /// + /// let mut bv = Bitv::with_capacity(10u, false); + /// assert_eq!(bv.len(), 10u); + /// for x in bv.iter() { + /// assert_eq!(x, false); + /// } + /// ``` + pub fn with_capacity(nbits: uint, init: bool) -> Bitv { + let mut bitv = Bitv { + storage: Vec::from_elem((nbits + u32::BITS - 1) / u32::BITS, + if init { !0u32 } else { 0u32 }), + nbits: nbits + }; + + // Zero out any unused bits in the highest word if necessary + let used_bits = bitv.nbits % u32::BITS; + if init && used_bits != 0 { + let largest_used_word = (bitv.nbits + u32::BITS - 1) / u32::BITS - 1; + bitv.storage[largest_used_word] &= (1 << used_bits) - 1; + } + + bitv + } + + /// Retrieves the value at index `i`. + /// + /// # Failure + /// + /// Fails if `i` is out of bounds. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let bv = bitv::from_bytes([0b01100000]); + /// assert_eq!(bv.get(0), false); + /// assert_eq!(bv.get(1), true); + /// + /// // Can also use array indexing + /// assert_eq!(bv[1], true); + /// ``` + #[inline] + pub fn get(&self, i: uint) -> bool { + assert!(i < self.nbits); + let w = i / u32::BITS; + let b = i % u32::BITS; + let x = self.storage[w] & (1 << b); + x != 0 + } + + /// Sets the value of a bit at a index `i`. + /// + /// # Failure + /// + /// Fails if `i` is out of bounds. + /// + /// # Example + /// + /// ``` + /// use std::collections::Bitv; + /// + /// let mut bv = Bitv::with_capacity(5, false); + /// bv.set(3, true); + /// assert_eq!(bv[3], true); + /// ``` + #[inline] + pub fn set(&mut self, i: uint, x: bool) { + assert!(i < self.nbits); + let w = i / u32::BITS; + let b = i % u32::BITS; + let flag = 1 << b; + let val = if x { self.storage[w] | flag } + else { self.storage[w] & !flag }; + self.storage[w] = val; + } + + /// Sets all bits to 1. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let before = 0b01100000; + /// let after = 0b11111111; + /// + /// let mut bv = bitv::from_bytes([before]); + /// bv.set_all(); + /// assert_eq!(bv, bitv::from_bytes([after])); + /// ``` + #[inline] + pub fn set_all(&mut self) { + for w in self.storage.iter_mut() { *w = !0u32; } + } + + /// Flips all bits. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let before = 0b01100000; + /// let after = 0b10011111; + /// + /// let mut bv = bitv::from_bytes([before]); + /// bv.negate(); + /// assert_eq!(bv, bitv::from_bytes([after])); + /// ``` + #[inline] + pub fn negate(&mut self) { + for w in self.storage.iter_mut() { *w = !*w; } + } + + /// Calculates the union of two bitvectors. This acts like the bitwise `or` + /// function. + /// + /// Sets `self` to the union of `self` and `other`. Both bitvectors must be + /// the same length. Returns `true` if `self` changed. + /// + /// # Failure + /// + /// Fails if the bitvectors are of different lengths. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let a = 0b01100100; + /// let b = 0b01011010; + /// let res = 0b01111110; + /// + /// let mut a = bitv::from_bytes([a]); + /// let b = bitv::from_bytes([b]); + /// + /// assert!(a.union(&b)); + /// assert_eq!(a, bitv::from_bytes([res])); + /// ``` + #[inline] + pub fn union(&mut self, other: &Bitv) -> bool { + self.process(other, |w1, w2| w1 | w2) + } + + /// Calculates the intersection of two bitvectors. This acts like the + /// bitwise `and` function. + /// + /// Sets `self` to the intersection of `self` and `other`. Both bitvectors + /// must be the same length. Returns `true` if `self` changed. + /// + /// # Failure + /// + /// Fails if the bitvectors are of different lengths. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let a = 0b01100100; + /// let b = 0b01011010; + /// let res = 0b01000000; + /// + /// let mut a = bitv::from_bytes([a]); + /// let b = bitv::from_bytes([b]); + /// + /// assert!(a.intersect(&b)); + /// assert_eq!(a, bitv::from_bytes([res])); + /// ``` + #[inline] + pub fn intersect(&mut self, other: &Bitv) -> bool { + self.process(other, |w1, w2| w1 & w2) + } + + /// Calculates the difference between two bitvectors. + /// + /// Sets each element of `self` to the value of that element minus the + /// element of `other` at the same index. Both bitvectors must be the same + /// length. Returns `true` if `self` changed. + /// + /// # Failure + /// + /// Fails if the bitvectors are of different length. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let a = 0b01100100; + /// let b = 0b01011010; + /// let a_b = 0b00100100; // a - b + /// let b_a = 0b00011010; // b - a + /// + /// let mut bva = bitv::from_bytes([a]); + /// let bvb = bitv::from_bytes([b]); + /// + /// assert!(bva.difference(&bvb)); + /// assert_eq!(bva, bitv::from_bytes([a_b])); + /// + /// let bva = bitv::from_bytes([a]); + /// let mut bvb = bitv::from_bytes([b]); + /// + /// assert!(bvb.difference(&bva)); + /// assert_eq!(bvb, bitv::from_bytes([b_a])); + /// ``` + #[inline] + pub fn difference(&mut self, other: &Bitv) -> bool { + self.process(other, |w1, w2| w1 & !w2) + } + + /// Returns `true` if all bits are 1. + /// + /// # Example + /// + /// ``` + /// use std::collections::Bitv; + /// + /// let mut bv = Bitv::with_capacity(5, true); + /// assert_eq!(bv.all(), true); + /// + /// bv.set(1, false); + /// assert_eq!(bv.all(), false); + /// ``` + #[inline] + pub fn all(&self) -> bool { + let mut last_word = !0u32; + // Check that every word but the last is all-ones... + self.mask_words(0).all(|(_, elem)| + { let tmp = last_word; last_word = elem; tmp == !0u32 }) && + // ...and that the last word is ones as far as it needs to be + (last_word == ((1 << self.nbits % u32::BITS) - 1) || last_word == !0u32) + } + + /// Returns an iterator over the elements of the vector in order. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let bv = bitv::from_bytes([0b01110100, 0b10010010]); + /// assert_eq!(bv.iter().filter(|x| *x).count(), 7); + /// ``` + #[inline] + pub fn iter<'a>(&'a self) -> Bits<'a> { + Bits {bitv: self, next_idx: 0, end_idx: self.nbits} + } + + /// Returns `true` if all bits are 0. + /// + /// # Example + /// + /// ``` + /// use std::collections::Bitv; + /// + /// let mut bv = Bitv::with_capacity(10, false); + /// assert_eq!(bv.none(), true); + /// + /// bv.set(3, true); + /// assert_eq!(bv.none(), false); + /// ``` + pub fn none(&self) -> bool { + self.mask_words(0).all(|(_, w)| w == 0) + } + + /// Returns `true` if any bit is 1. + /// + /// # Example + /// + /// ``` + /// use std::collections::Bitv; + /// + /// let mut bv = Bitv::with_capacity(10, false); + /// assert_eq!(bv.any(), false); + /// + /// bv.set(3, true); + /// assert_eq!(bv.any(), true); + /// ``` + #[inline] + pub fn any(&self) -> bool { + !self.none() + } + + /// Organises the bits into bytes, such that the first bit in the + /// `Bitv` becomes the high-order bit of the first byte. If the + /// size of the `Bitv` is not a multiple of eight then trailing bits + /// will be filled-in with `false`. + /// + /// # Example + /// + /// ``` + /// use std::collections::Bitv; + /// + /// let mut bv = Bitv::with_capacity(3, true); + /// bv.set(1, false); + /// + /// assert_eq!(bv.to_bytes(), vec!(0b10100000)); + /// + /// let mut bv = Bitv::with_capacity(9, false); + /// bv.set(2, true); + /// bv.set(8, true); + /// + /// assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000)); + /// ``` + pub fn to_bytes(&self) -> Vec { + fn bit (bitv: &Bitv, byte: uint, bit: uint) -> u8 { + let offset = byte * 8 + bit; + if offset >= bitv.nbits { + 0 + } else { + bitv.get(offset) as u8 << (7 - bit) + } + } + + let len = self.nbits/8 + + if self.nbits % 8 == 0 { 0 } else { 1 }; + Vec::from_fn(len, |i| + bit(self, i, 0) | + bit(self, i, 1) | + bit(self, i, 2) | + bit(self, i, 3) | + bit(self, i, 4) | + bit(self, i, 5) | + bit(self, i, 6) | + bit(self, i, 7) + ) + } + + /// Transforms `self` into a `Vec` by turning each bit into a `bool`. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let bv = bitv::from_bytes([0b10100000]); + /// assert_eq!(bv.to_bools(), vec!(true, false, true, false, + /// false, false, false, false)); + /// ``` + pub fn to_bools(&self) -> Vec { + Vec::from_fn(self.nbits, |i| self.get(i)) + } + + /// Compares a `Bitv` to a slice of `bool`s. + /// Both the `Bitv` and slice must have the same length. + /// + /// # Failure + /// + /// Fails if the the `Bitv` and slice are of different length. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let bv = bitv::from_bytes([0b10100000]); + /// + /// assert!(bv.eq_vec([true, false, true, false, + /// false, false, false, false])); + /// ``` + pub fn eq_vec(&self, v: &[bool]) -> bool { + assert_eq!(self.nbits, v.len()); + let mut i = 0; + while i < self.nbits { + if self.get(i) != v[i] { return false; } + i = i + 1; + } + true + } + + /// Shortens a `Bitv`, dropping excess elements. + /// + /// If `len` is greater than the vector's current length, this has no + /// effect. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let mut bv = bitv::from_bytes([0b01001011]); + /// bv.truncate(2); + /// assert!(bv.eq_vec([false, true])); + /// ``` + pub fn truncate(&mut self, len: uint) { + if len < self.len() { + self.nbits = len; + let word_len = (len + u32::BITS - 1) / u32::BITS; + self.storage.truncate(word_len); + if len % u32::BITS > 0 { + let mask = (1 << len % u32::BITS) - 1; + self.storage[word_len - 1] &= mask; + } + } + } + + /// Grows the vector to be able to store `size` bits without resizing. + /// + /// # Example + /// + /// ``` + /// use std::collections::Bitv; + /// + /// let mut bv = Bitv::with_capacity(3, false); + /// bv.reserve(10); + /// assert_eq!(bv.len(), 3); + /// assert!(bv.capacity() >= 10); + /// ``` + pub fn reserve(&mut self, size: uint) { + let old_size = self.storage.len(); + let new_size = (size + u32::BITS - 1) / u32::BITS; + if old_size < new_size { + self.storage.grow(new_size - old_size, 0); + } + } + + /// Returns the capacity in bits for this bit vector. Inserting any + /// element less than this amount will not trigger a resizing. + /// + /// # Example + /// + /// ``` + /// use std::collections::Bitv; + /// + /// let mut bv = Bitv::new(); + /// bv.reserve(10); + /// assert!(bv.capacity() >= 10); + /// ``` + #[inline] + pub fn capacity(&self) -> uint { + self.storage.len() * u32::BITS + } + + /// Grows the `Bitv` in-place, adding `n` copies of `value` to the `Bitv`. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let mut bv = bitv::from_bytes([0b01001011]); + /// bv.grow(2, true); + /// assert_eq!(bv.len(), 10); + /// assert_eq!(bv.to_bytes(), vec!(0b01001011, 0b11000000)); + /// ``` + pub fn grow(&mut self, n: uint, value: bool) { + let new_nbits = self.nbits + n; + let new_nwords = (new_nbits + u32::BITS - 1) / u32::BITS; + let full_value = if value { !0 } else { 0 }; + // Correct the old tail word + let old_last_word = (self.nbits + u32::BITS - 1) / u32::BITS - 1; + if self.nbits % u32::BITS > 0 { + let overhang = self.nbits % u32::BITS; // # of already-used bits + let mask = !((1 << overhang) - 1); // e.g. 5 unused bits => 111110....0 + if value { + self.storage[old_last_word] |= mask; + } else { + self.storage[old_last_word] &= !mask; + } + } + // Fill in words after the old tail word + let stop_idx = cmp::min(self.storage.len(), new_nwords); + for idx in range(old_last_word + 1, stop_idx) { + self.storage[idx] = full_value; + } + // Allocate new words, if needed + if new_nwords > self.storage.len() { + let to_add = new_nwords - self.storage.len(); + self.storage.grow(to_add, full_value); + + // Zero out and unused bits in the new tail word + if value { + let tail_word = new_nwords - 1; + let used_bits = new_nbits % u32::BITS; + self.storage[tail_word] &= (1 << used_bits) - 1; + } + } + // Adjust internal bit count + self.nbits = new_nbits; + } + + /// Shortens by one element and returns the removed element. + /// + /// # Failure + /// + /// Assert if empty. + /// + /// # Example + /// + /// ``` + /// use std::collections::bitv; + /// + /// let mut bv = bitv::from_bytes([0b01001001]); + /// assert_eq!(bv.pop(), true); + /// assert_eq!(bv.pop(), false); + /// assert_eq!(bv.len(), 6); + /// assert_eq!(bv.to_bytes(), vec!(0b01001000)); + /// ``` + pub fn pop(&mut self) -> bool { + let ret = self.get(self.nbits - 1); + // If we are unusing a whole word, make sure it is zeroed out + if self.nbits % u32::BITS == 1 { + self.storage[self.nbits / u32::BITS] = 0; + } + self.nbits -= 1; + ret + } + + /// Pushes a `bool` onto the end. + /// + /// # Example + /// + /// ``` + /// use std::collections::Bitv; + /// + /// let mut bv = Bitv::new(); + /// bv.push(true); + /// bv.push(false); + /// assert!(bv.eq_vec([true, false])); + /// ``` + pub fn push(&mut self, elem: bool) { + let insert_pos = self.nbits; + self.nbits += 1; + if self.storage.len() * u32::BITS < self.nbits { + self.storage.push(0); + } + self.set(insert_pos, elem); + } + + /// Return the total number of bits in this vector + #[inline] + pub fn len(&self) -> uint { self.nbits } + + /// Returns true if there are no bits in this vector + #[inline] + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Clears all bits in this vector. + #[inline] + pub fn clear(&mut self) { + for w in self.storage.iter_mut() { *w = 0u32; } + } +} + +/// Transforms a byte-vector into a `Bitv`. Each byte becomes eight bits, +/// with the most significant bits of each byte coming first. Each +/// bit becomes `true` if equal to 1 or `false` if equal to 0. +/// +/// # Example +/// +/// ``` +/// use std::collections::bitv; +/// +/// let bv = bitv::from_bytes([0b10100000, 0b00010010]); +/// assert!(bv.eq_vec([true, false, true, false, +/// false, false, false, false, +/// false, false, false, true, +/// false, false, true, false])); +/// ``` +pub fn from_bytes(bytes: &[u8]) -> Bitv { + from_fn(bytes.len() * 8, |i| { + let b = bytes[i / 8] as u32; + let offset = i % 8; + b >> (7 - offset) & 1 == 1 + }) +} + +/// Creates a `Bitv` of the specified length where the value at each +/// index is `f(index)`. +/// +/// # Example +/// +/// ``` +/// use std::collections::bitv::from_fn; +/// +/// let bv = from_fn(5, |i| { i % 2 == 0 }); +/// assert!(bv.eq_vec([true, false, true, false, true])); +/// ``` +pub fn from_fn(len: uint, f: |index: uint| -> bool) -> Bitv { + let mut bitv = Bitv::with_capacity(len, false); + for i in range(0u, len) { + bitv.set(i, f(i)); + } + bitv +} + +impl Default for Bitv { + #[inline] + fn default() -> Bitv { Bitv::new() } +} + +impl FromIterator for Bitv { + fn from_iter>(iterator: I) -> Bitv { + let mut ret = Bitv::new(); + ret.extend(iterator); + ret + } +} + +impl Extendable for Bitv { + #[inline] + fn extend>(&mut self, mut iterator: I) { + let (min, _) = iterator.size_hint(); + let nbits = self.nbits; + self.reserve(nbits + min); + for element in iterator { + self.push(element) + } + } +} + +impl Clone for Bitv { + #[inline] + fn clone(&self) -> Bitv { + Bitv { storage: self.storage.clone(), nbits: self.nbits } + } + + #[inline] + fn clone_from(&mut self, source: &Bitv) { + self.nbits = source.nbits; + self.storage.reserve(source.storage.len()); + for (i, w) in self.storage.iter_mut().enumerate() { *w = source.storage[i]; } + } +} + +impl PartialOrd for Bitv { + #[inline] + fn partial_cmp(&self, other: &Bitv) -> Option { + iter::order::partial_cmp(self.iter(), other.iter()) + } +} + +impl Ord for Bitv { + #[inline] + fn cmp(&self, other: &Bitv) -> Ordering { + iter::order::cmp(self.iter(), other.iter()) + } +} + +impl fmt::Show for Bitv { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + for bit in self.iter() { + try!(write!(fmt, "{}", if bit { 1u } else { 0u })); + } + Ok(()) + } +} + +impl hash::Hash for Bitv { + fn hash(&self, state: &mut S) { + self.nbits.hash(state); + for (_, elem) in self.mask_words(0) { + elem.hash(state); + } + } +} + +impl cmp::PartialEq for Bitv { + #[inline] + fn eq(&self, other: &Bitv) -> bool { + if self.nbits != other.nbits { + return false; + } + self.mask_words(0).zip(other.mask_words(0)).all(|((_, w1), (_, w2))| w1 == w2) + } +} + +impl cmp::Eq for Bitv {} + +/// An iterator for `Bitv`. +pub struct Bits<'a> { + bitv: &'a Bitv, + next_idx: uint, + end_idx: uint, +} + +impl<'a> Iterator for Bits<'a> { + #[inline] + fn next(&mut self) -> Option { + if self.next_idx != self.end_idx { + let idx = self.next_idx; + self.next_idx += 1; + Some(self.bitv.get(idx)) + } else { + None + } + } + + fn size_hint(&self) -> (uint, Option) { + let rem = self.end_idx - self.next_idx; + (rem, Some(rem)) + } +} + +impl<'a> DoubleEndedIterator for Bits<'a> { + #[inline] + fn next_back(&mut self) -> Option { + if self.next_idx != self.end_idx { + self.end_idx -= 1; + Some(self.bitv.get(self.end_idx)) + } else { + None + } + } +} + +impl<'a> ExactSize for Bits<'a> {} + +impl<'a> RandomAccessIterator for Bits<'a> { + #[inline] + fn indexable(&self) -> uint { + self.end_idx - self.next_idx + } + + #[inline] + fn idx(&mut self, index: uint) -> Option { + if index >= self.indexable() { + None + } else { + Some(self.bitv.get(index)) + } + } +} + +/// An implementation of a set using a bit vector as an underlying +/// representation for holding unsigned numerical elements. +/// +/// It should also be noted that the amount of storage necessary for holding a +/// set of objects is proportional to the maximum of the objects when viewed +/// as a `uint`. +/// +/// # Example +/// +/// ``` +/// use std::collections::{BitvSet, Bitv}; +/// use std::collections::bitv; +/// +/// // It's a regular set +/// let mut s = BitvSet::new(); +/// s.insert(0); +/// s.insert(3); +/// s.insert(7); +/// +/// s.remove(&7); +/// +/// if !s.contains(&7) { +/// println!("There is no 7"); +/// } +/// +/// // Can initialize from a `Bitv` +/// let other = BitvSet::from_bitv(bitv::from_bytes([0b11010000])); +/// +/// s.union_with(&other); +/// +/// // Print 0, 1, 3 in some order +/// for x in s.iter() { +/// println!("{}", x); +/// } +/// +/// // Can convert back to a `Bitv` +/// let bv: Bitv = s.into_bitv(); +/// assert!(bv.get(3)); +/// ``` +#[deriving(Clone)] +pub struct BitvSet(Bitv); + +impl Default for BitvSet { + #[inline] + fn default() -> BitvSet { BitvSet::new() } +} + +impl FromIterator for BitvSet { + fn from_iter>(iterator: I) -> BitvSet { + let mut ret = BitvSet::new(); + ret.extend(iterator); + ret + } +} + +impl Extendable for BitvSet { + #[inline] + fn extend>(&mut self, iterator: I) { + let &BitvSet(ref mut self_bitv) = self; + self_bitv.extend(iterator); + } +} + +impl PartialOrd for BitvSet { + #[inline] + fn partial_cmp(&self, other: &BitvSet) -> Option { + let (a_iter, b_iter) = match_words(self.get_ref(), other.get_ref()); + iter::order::partial_cmp(a_iter, b_iter) + } +} + +impl Ord for BitvSet { + #[inline] + fn cmp(&self, other: &BitvSet) -> Ordering { + let (a_iter, b_iter) = match_words(self.get_ref(), other.get_ref()); + iter::order::cmp(a_iter, b_iter) + } +} + +impl cmp::PartialEq for BitvSet { + #[inline] + fn eq(&self, other: &BitvSet) -> bool { + let (a_iter, b_iter) = match_words(self.get_ref(), other.get_ref()); + iter::order::eq(a_iter, b_iter) + } +} + +impl cmp::Eq for BitvSet {} + +impl BitvSet { + /// Creates a new bit vector set with initially no contents. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// let mut s = BitvSet::new(); + /// ``` + #[inline] + pub fn new() -> BitvSet { + BitvSet(Bitv::new()) + } + + /// Creates a new bit vector set with initially no contents, able to + /// hold `nbits` elements without resizing. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// let mut s = BitvSet::with_capacity(100); + /// assert!(s.capacity() >= 100); + /// ``` + #[inline] + pub fn with_capacity(nbits: uint) -> BitvSet { + let bitv = Bitv::with_capacity(nbits, false); + BitvSet::from_bitv(bitv) + } + + /// Creates a new bit vector set from the given bit vector. + /// + /// # Example + /// + /// ``` + /// use std::collections::{bitv, BitvSet}; + /// + /// let bv = bitv::from_bytes([0b01100000]); + /// let s = BitvSet::from_bitv(bv); + /// + /// // Print 1, 2 in arbitrary order + /// for x in s.iter() { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn from_bitv(mut bitv: Bitv) -> BitvSet { + // Mark every bit as valid + bitv.nbits = bitv.capacity(); + BitvSet(bitv) + } + + /// Returns the capacity in bits for this bit vector. Inserting any + /// element less than this amount will not trigger a resizing. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// + /// let mut s = BitvSet::with_capacity(100); + /// assert!(s.capacity() >= 100); + /// ``` + #[inline] + pub fn capacity(&self) -> uint { + let &BitvSet(ref bitv) = self; + bitv.capacity() + } + + /// Grows the underlying vector to be able to store `size` bits. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// + /// let mut s = BitvSet::new(); + /// s.reserve(10); + /// assert!(s.capacity() >= 10); + /// ``` + pub fn reserve(&mut self, size: uint) { + let &BitvSet(ref mut bitv) = self; + bitv.reserve(size); + if bitv.nbits < size { + bitv.nbits = bitv.capacity(); + } + } + + /// Consumes this set to return the underlying bit vector. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// + /// let mut s = BitvSet::new(); + /// s.insert(0); + /// s.insert(3); + /// + /// let bv = s.into_bitv(); + /// assert!(bv.get(0)); + /// assert!(bv.get(3)); + /// ``` + #[inline] + pub fn into_bitv(self) -> Bitv { + let BitvSet(bitv) = self; + bitv + } + + /// Returns a reference to the underlying bit vector. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// + /// let mut s = BitvSet::new(); + /// s.insert(0); + /// + /// let bv = s.get_ref(); + /// assert_eq!(bv[0], true); + /// ``` + #[inline] + pub fn get_ref<'a>(&'a self) -> &'a Bitv { + let &BitvSet(ref bitv) = self; + bitv + } + + #[inline] + fn other_op(&mut self, other: &BitvSet, f: |u32, u32| -> u32) { + // Expand the vector if necessary + self.reserve(other.capacity()); + + // Unwrap Bitvs + let &BitvSet(ref mut self_bitv) = self; + let &BitvSet(ref other_bitv) = other; + + // virtually pad other with 0's for equal lengths + let mut other_words = { + let (_, result) = match_words(self_bitv, other_bitv); + result + }; + + // Apply values found in other + for (i, w) in other_words { + let old = self_bitv.storage[i]; + let new = f(old, w); + self_bitv.storage[i] = new; + } + } + + /// Truncates the underlying vector to the least length required. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// + /// let mut s = BitvSet::new(); + /// s.insert(32183231); + /// s.remove(&32183231); + /// + /// // Internal storage will probably be bigger than necessary + /// println!("old capacity: {}", s.capacity()); + /// + /// // Now should be smaller + /// s.shrink_to_fit(); + /// println!("new capacity: {}", s.capacity()); + /// ``` + #[inline] + pub fn shrink_to_fit(&mut self) { + let &BitvSet(ref mut bitv) = self; + // Obtain original length + let old_len = bitv.storage.len(); + // Obtain coarse trailing zero length + let n = bitv.storage.iter().rev().take_while(|&&n| n == 0).count(); + // Truncate + let trunc_len = cmp::max(old_len - n, 1); + bitv.storage.truncate(trunc_len); + bitv.nbits = trunc_len * u32::BITS; + } + + /// Iterator over each u32 stored in the `BitvSet`. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// use std::collections::bitv; + /// + /// let s = BitvSet::from_bitv(bitv::from_bytes([0b01001010])); + /// + /// // Print 1, 4, 6 in arbitrary order + /// for x in s.iter() { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn iter<'a>(&'a self) -> BitPositions<'a> { + BitPositions {set: self, next_idx: 0u} + } + + /// Iterator over each u32 stored in `self` union `other`. + /// See [union_with](#method.union_with) for an efficient in-place version. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// use std::collections::bitv; + /// + /// let a = BitvSet::from_bitv(bitv::from_bytes([0b01101000])); + /// let b = BitvSet::from_bitv(bitv::from_bytes([0b10100000])); + /// + /// // Print 0, 1, 2, 4 in arbitrary order + /// for x in a.union(&b) { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn union<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> { + TwoBitPositions { + set: self, + other: other, + merge: |w1, w2| w1 | w2, + current_word: 0u32, + next_idx: 0u + } + } + + /// Iterator over each uint stored in `self` intersect `other`. + /// See [intersect_with](#method.intersect_with) for an efficient in-place version. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// use std::collections::bitv; + /// + /// let a = BitvSet::from_bitv(bitv::from_bytes([0b01101000])); + /// let b = BitvSet::from_bitv(bitv::from_bytes([0b10100000])); + /// + /// // Print 2 + /// for x in a.intersection(&b) { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn intersection<'a>(&'a self, other: &'a BitvSet) -> Take> { + let min = cmp::min(self.capacity(), other.capacity()); + TwoBitPositions { + set: self, + other: other, + merge: |w1, w2| w1 & w2, + current_word: 0u32, + next_idx: 0 + }.take(min) + } + + /// Iterator over each uint stored in the `self` setminus `other`. + /// See [difference_with](#method.difference_with) for an efficient in-place version. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// use std::collections::bitv; + /// + /// let a = BitvSet::from_bitv(bitv::from_bytes([0b01101000])); + /// let b = BitvSet::from_bitv(bitv::from_bytes([0b10100000])); + /// + /// // Print 1, 4 in arbitrary order + /// for x in a.difference(&b) { + /// println!("{}", x); + /// } + /// + /// // Note that difference is not symmetric, + /// // and `b - a` means something else. + /// // This prints 0 + /// for x in b.difference(&a) { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn difference<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> { + TwoBitPositions { + set: self, + other: other, + merge: |w1, w2| w1 & !w2, + current_word: 0u32, + next_idx: 0 + } + } + + /// Iterator over each u32 stored in the symmetric difference of `self` and `other`. + /// See [symmetric_difference_with](#method.symmetric_difference_with) for + /// an efficient in-place version. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// use std::collections::bitv; + /// + /// let a = BitvSet::from_bitv(bitv::from_bytes([0b01101000])); + /// let b = BitvSet::from_bitv(bitv::from_bytes([0b10100000])); + /// + /// // Print 0, 1, 4 in arbitrary order + /// for x in a.symmetric_difference(&b) { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn symmetric_difference<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> { + TwoBitPositions { + set: self, + other: other, + merge: |w1, w2| w1 ^ w2, + current_word: 0u32, + next_idx: 0 + } + } + + /// Unions in-place with the specified other bit vector. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// use std::collections::bitv; + /// + /// let a = 0b01101000; + /// let b = 0b10100000; + /// let res = 0b11101000; + /// + /// let mut a = BitvSet::from_bitv(bitv::from_bytes([a])); + /// let b = BitvSet::from_bitv(bitv::from_bytes([b])); + /// let res = BitvSet::from_bitv(bitv::from_bytes([res])); + /// + /// a.union_with(&b); + /// assert_eq!(a, res); + /// ``` + #[inline] + pub fn union_with(&mut self, other: &BitvSet) { + self.other_op(other, |w1, w2| w1 | w2); + } + + /// Intersects in-place with the specified other bit vector. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// use std::collections::bitv; + /// + /// let a = 0b01101000; + /// let b = 0b10100000; + /// let res = 0b00100000; + /// + /// let mut a = BitvSet::from_bitv(bitv::from_bytes([a])); + /// let b = BitvSet::from_bitv(bitv::from_bytes([b])); + /// let res = BitvSet::from_bitv(bitv::from_bytes([res])); + /// + /// a.intersect_with(&b); + /// assert_eq!(a, res); + /// ``` + #[inline] + pub fn intersect_with(&mut self, other: &BitvSet) { + self.other_op(other, |w1, w2| w1 & w2); + } + + /// Makes this bit vector the difference with the specified other bit vector + /// in-place. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// use std::collections::bitv; + /// + /// let a = 0b01101000; + /// let b = 0b10100000; + /// let a_b = 0b01001000; // a - b + /// let b_a = 0b10000000; // b - a + /// + /// let mut bva = BitvSet::from_bitv(bitv::from_bytes([a])); + /// let bvb = BitvSet::from_bitv(bitv::from_bytes([b])); + /// let bva_b = BitvSet::from_bitv(bitv::from_bytes([a_b])); + /// let bvb_a = BitvSet::from_bitv(bitv::from_bytes([b_a])); + /// + /// bva.difference_with(&bvb); + /// assert_eq!(bva, bva_b); + /// + /// let bva = BitvSet::from_bitv(bitv::from_bytes([a])); + /// let mut bvb = BitvSet::from_bitv(bitv::from_bytes([b])); + /// + /// bvb.difference_with(&bva); + /// assert_eq!(bvb, bvb_a); + /// ``` + #[inline] + pub fn difference_with(&mut self, other: &BitvSet) { + self.other_op(other, |w1, w2| w1 & !w2); + } + + /// Makes this bit vector the symmetric difference with the specified other + /// bit vector in-place. + /// + /// # Example + /// + /// ``` + /// use std::collections::BitvSet; + /// use std::collections::bitv; + /// + /// let a = 0b01101000; + /// let b = 0b10100000; + /// let res = 0b11001000; + /// + /// let mut a = BitvSet::from_bitv(bitv::from_bytes([a])); + /// let b = BitvSet::from_bitv(bitv::from_bytes([b])); + /// let res = BitvSet::from_bitv(bitv::from_bytes([res])); + /// + /// a.symmetric_difference_with(&b); + /// assert_eq!(a, res); + /// ``` + #[inline] + pub fn symmetric_difference_with(&mut self, other: &BitvSet) { + self.other_op(other, |w1, w2| w1 ^ w2); + } + + /// Return the number of set bits in this set. + #[inline] + pub fn len(&self) -> uint { + let &BitvSet(ref bitv) = self; + bitv.storage.iter().fold(0, |acc, &n| acc + n.count_ones()) + } + + /// Returns whether there are no bits set in this set + #[inline] + pub fn is_empty(&self) -> bool { + let &BitvSet(ref bitv) = self; + bitv.storage.iter().all(|&n| n == 0) + } + + /// Clears all bits in this set + #[inline] + pub fn clear(&mut self) { + let &BitvSet(ref mut bitv) = self; + bitv.clear(); + } + + /// Returns `true` if this set contains the specified integer. + #[inline] + pub fn contains(&self, value: &uint) -> bool { + let &BitvSet(ref bitv) = self; + *value < bitv.nbits && bitv.get(*value) + } + + /// Returns `true` if the set has no elements in common with `other`. + /// This is equivalent to checking for an empty intersection. + #[inline] + pub fn is_disjoint(&self, other: &BitvSet) -> bool { + self.intersection(other).next().is_none() + } + + /// Returns `true` if the set is a subset of another. + #[inline] + pub fn is_subset(&self, other: &BitvSet) -> bool { + let &BitvSet(ref self_bitv) = self; + let &BitvSet(ref other_bitv) = other; + + // Check that `self` intersect `other` is self + self_bitv.mask_words(0).zip(other_bitv.mask_words(0)) + .all(|((_, w1), (_, w2))| w1 & w2 == w1) && + // Check that `self` setminus `other` is empty + self_bitv.mask_words(other_bitv.storage.len()).all(|(_, w)| w == 0) + } + + /// Returns `true` if the set is a superset of another. + #[inline] + pub fn is_superset(&self, other: &BitvSet) -> bool { + other.is_subset(self) + } + + /// Adds a value to the set. Returns `true` if the value was not already + /// present in the set. + pub fn insert(&mut self, value: uint) -> bool { + if self.contains(&value) { + return false; + } + + // Ensure we have enough space to hold the new element + if value >= self.capacity() { + let new_cap = cmp::max(value + 1, self.capacity() * 2); + self.reserve(new_cap); + } + + let &BitvSet(ref mut bitv) = self; + bitv.set(value, true); + return true; + } + + /// Removes a value from the set. Returns `true` if the value was + /// present in the set. + pub fn remove(&mut self, value: &uint) -> bool { + if !self.contains(value) { + return false; + } + let &BitvSet(ref mut bitv) = self; + bitv.set(*value, false); + return true; + } +} + +impl fmt::Show for BitvSet { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + try!(write!(fmt, "{{")); + let mut first = true; + for n in self.iter() { + if !first { + try!(write!(fmt, ", ")); + } + try!(write!(fmt, "{}", n)); + first = false; + } + write!(fmt, "}}") + } +} + +impl hash::Hash for BitvSet { + fn hash(&self, state: &mut S) { + for pos in self.iter() { + pos.hash(state); + } + } +} + +/// An iterator for `BitvSet`. +pub struct BitPositions<'a> { + set: &'a BitvSet, + next_idx: uint +} + +/// An iterator combining two `BitvSet` iterators. +pub struct TwoBitPositions<'a> { + set: &'a BitvSet, + other: &'a BitvSet, + merge: |u32, u32|: 'a -> u32, + current_word: u32, + next_idx: uint +} + +impl<'a> Iterator for BitPositions<'a> { + fn next(&mut self) -> Option { + while self.next_idx < self.set.capacity() { + let idx = self.next_idx; + self.next_idx += 1; + + if self.set.contains(&idx) { + return Some(idx); + } + } + + return None; + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + (0, Some(self.set.capacity() - self.next_idx)) + } +} + +impl<'a> Iterator for TwoBitPositions<'a> { + fn next(&mut self) -> Option { + while self.next_idx < self.set.capacity() || + self.next_idx < self.other.capacity() { + let bit_idx = self.next_idx % u32::BITS; + if bit_idx == 0 { + let &BitvSet(ref s_bitv) = self.set; + let &BitvSet(ref o_bitv) = self.other; + // Merging the two words is a bit of an awkward dance since + // one Bitv might be longer than the other + let word_idx = self.next_idx / u32::BITS; + let w1 = if word_idx < s_bitv.storage.len() { + s_bitv.storage[word_idx] + } else { 0 }; + let w2 = if word_idx < o_bitv.storage.len() { + o_bitv.storage[word_idx] + } else { 0 }; + self.current_word = (self.merge)(w1, w2); + } + + self.next_idx += 1; + if self.current_word & (1 << bit_idx) != 0 { + return Some(self.next_idx - 1); + } + } + return None; + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let cap = cmp::max(self.set.capacity(), self.other.capacity()); + (0, Some(cap - self.next_idx)) + } +} + +#[cfg(test)] +mod tests { + use std::prelude::*; + use std::iter::range_step; + use std::u32; + use std::rand; + use std::rand::Rng; + use test::Bencher; + + use super::{Bitv, BitvSet, from_fn, from_bytes}; + use bitv; + use vec::Vec; + + static BENCH_BITS : uint = 1 << 14; + + #[test] + fn test_to_str() { + let zerolen = Bitv::new(); + assert_eq!(zerolen.to_string().as_slice(), ""); + + let eightbits = Bitv::with_capacity(8u, false); + assert_eq!(eightbits.to_string().as_slice(), "00000000") + } + + #[test] + fn test_0_elements() { + let act = Bitv::new(); + let exp = Vec::from_elem(0u, false); + assert!(act.eq_vec(exp.as_slice())); + } + + #[test] + fn test_1_element() { + let mut act = Bitv::with_capacity(1u, false); + assert!(act.eq_vec([false])); + act = Bitv::with_capacity(1u, true); + assert!(act.eq_vec([true])); + } + + #[test] + fn test_2_elements() { + let mut b = bitv::Bitv::with_capacity(2, false); + b.set(0, true); + b.set(1, false); + assert_eq!(b.to_string().as_slice(), "10"); + } + + #[test] + fn test_10_elements() { + let mut act; + // all 0 + + act = Bitv::with_capacity(10u, false); + assert!((act.eq_vec( + [false, false, false, false, false, false, false, false, false, false]))); + // all 1 + + act = Bitv::with_capacity(10u, true); + assert!((act.eq_vec([true, true, true, true, true, true, true, true, true, true]))); + // mixed + + act = Bitv::with_capacity(10u, false); + act.set(0u, true); + act.set(1u, true); + act.set(2u, true); + act.set(3u, true); + act.set(4u, true); + assert!((act.eq_vec([true, true, true, true, true, false, false, false, false, false]))); + // mixed + + act = Bitv::with_capacity(10u, false); + act.set(5u, true); + act.set(6u, true); + act.set(7u, true); + act.set(8u, true); + act.set(9u, true); + assert!((act.eq_vec([false, false, false, false, false, true, true, true, true, true]))); + // mixed + + act = Bitv::with_capacity(10u, false); + act.set(0u, true); + act.set(3u, true); + act.set(6u, true); + act.set(9u, true); + assert!((act.eq_vec([true, false, false, true, false, false, true, false, false, true]))); + } + + #[test] + fn test_31_elements() { + let mut act; + // all 0 + + act = Bitv::with_capacity(31u, false); + assert!(act.eq_vec( + [false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false])); + // all 1 + + act = Bitv::with_capacity(31u, true); + assert!(act.eq_vec( + [true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true])); + // mixed + + act = Bitv::with_capacity(31u, false); + act.set(0u, true); + act.set(1u, true); + act.set(2u, true); + act.set(3u, true); + act.set(4u, true); + act.set(5u, true); + act.set(6u, true); + act.set(7u, true); + assert!(act.eq_vec( + [true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false])); + // mixed + + act = Bitv::with_capacity(31u, false); + act.set(16u, true); + act.set(17u, true); + act.set(18u, true); + act.set(19u, true); + act.set(20u, true); + act.set(21u, true); + act.set(22u, true); + act.set(23u, true); + assert!(act.eq_vec( + [false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false])); + // mixed + + act = Bitv::with_capacity(31u, false); + act.set(24u, true); + act.set(25u, true); + act.set(26u, true); + act.set(27u, true); + act.set(28u, true); + act.set(29u, true); + act.set(30u, true); + assert!(act.eq_vec( + [false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, + false, true, true, true, true, true, true, true])); + // mixed + + act = Bitv::with_capacity(31u, false); + act.set(3u, true); + act.set(17u, true); + act.set(30u, true); + assert!(act.eq_vec( + [false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true])); + } + + #[test] + fn test_32_elements() { + let mut act; + // all 0 + + act = Bitv::with_capacity(32u, false); + assert!(act.eq_vec( + [false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false])); + // all 1 + + act = Bitv::with_capacity(32u, true); + assert!(act.eq_vec( + [true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true])); + // mixed + + act = Bitv::with_capacity(32u, false); + act.set(0u, true); + act.set(1u, true); + act.set(2u, true); + act.set(3u, true); + act.set(4u, true); + act.set(5u, true); + act.set(6u, true); + act.set(7u, true); + assert!(act.eq_vec( + [true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false])); + // mixed + + act = Bitv::with_capacity(32u, false); + act.set(16u, true); + act.set(17u, true); + act.set(18u, true); + act.set(19u, true); + act.set(20u, true); + act.set(21u, true); + act.set(22u, true); + act.set(23u, true); + assert!(act.eq_vec( + [false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false])); + // mixed + + act = Bitv::with_capacity(32u, false); + act.set(24u, true); + act.set(25u, true); + act.set(26u, true); + act.set(27u, true); + act.set(28u, true); + act.set(29u, true); + act.set(30u, true); + act.set(31u, true); + assert!(act.eq_vec( + [false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, + false, true, true, true, true, true, true, true, true])); + // mixed + + act = Bitv::with_capacity(32u, false); + act.set(3u, true); + act.set(17u, true); + act.set(30u, true); + act.set(31u, true); + assert!(act.eq_vec( + [false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true, true])); + } + + #[test] + fn test_33_elements() { + let mut act; + // all 0 + + act = Bitv::with_capacity(33u, false); + assert!(act.eq_vec( + [false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false])); + // all 1 + + act = Bitv::with_capacity(33u, true); + assert!(act.eq_vec( + [true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true, true, true, true, true, true, true, true, true, + true, true, true, true, true, true])); + // mixed + + act = Bitv::with_capacity(33u, false); + act.set(0u, true); + act.set(1u, true); + act.set(2u, true); + act.set(3u, true); + act.set(4u, true); + act.set(5u, true); + act.set(6u, true); + act.set(7u, true); + assert!(act.eq_vec( + [true, true, true, true, true, true, true, true, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false])); + // mixed + + act = Bitv::with_capacity(33u, false); + act.set(16u, true); + act.set(17u, true); + act.set(18u, true); + act.set(19u, true); + act.set(20u, true); + act.set(21u, true); + act.set(22u, true); + act.set(23u, true); + assert!(act.eq_vec( + [false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, true, true, true, true, true, true, true, + false, false, false, false, false, false, false, false, false])); + // mixed + + act = Bitv::with_capacity(33u, false); + act.set(24u, true); + act.set(25u, true); + act.set(26u, true); + act.set(27u, true); + act.set(28u, true); + act.set(29u, true); + act.set(30u, true); + act.set(31u, true); + assert!(act.eq_vec( + [false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, + false, true, true, true, true, true, true, true, true, false])); + // mixed + + act = Bitv::with_capacity(33u, false); + act.set(3u, true); + act.set(17u, true); + act.set(30u, true); + act.set(31u, true); + act.set(32u, true); + assert!(act.eq_vec( + [false, false, false, true, false, false, false, false, false, false, false, false, + false, false, false, false, false, true, false, false, false, false, false, false, + false, false, false, false, false, false, true, true, true])); + } + + #[test] + fn test_equal_differing_sizes() { + let v0 = Bitv::with_capacity(10u, false); + let v1 = Bitv::with_capacity(11u, false); + assert!(v0 != v1); + } + + #[test] + fn test_equal_greatly_differing_sizes() { + let v0 = Bitv::with_capacity(10u, false); + let v1 = Bitv::with_capacity(110u, false); + assert!(v0 != v1); + } + + #[test] + fn test_equal_sneaky_small() { + let mut a = bitv::Bitv::with_capacity(1, false); + a.set(0, true); + + let mut b = bitv::Bitv::with_capacity(1, true); + b.set(0, true); + + assert_eq!(a, b); + } + + #[test] + fn test_equal_sneaky_big() { + let mut a = bitv::Bitv::with_capacity(100, false); + for i in range(0u, 100) { + a.set(i, true); + } + + let mut b = bitv::Bitv::with_capacity(100, true); + for i in range(0u, 100) { + b.set(i, true); + } + + assert_eq!(a, b); + } + + #[test] + fn test_from_bytes() { + let bitv = from_bytes([0b10110110, 0b00000000, 0b11111111]); + let str = format!("{}{}{}", "10110110", "00000000", "11111111"); + assert_eq!(bitv.to_string().as_slice(), str.as_slice()); + } + + #[test] + fn test_to_bytes() { + let mut bv = Bitv::with_capacity(3, true); + bv.set(1, false); + assert_eq!(bv.to_bytes(), vec!(0b10100000)); + + let mut bv = Bitv::with_capacity(9, false); + bv.set(2, true); + bv.set(8, true); + assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000)); + } + + #[test] + fn test_from_bools() { + let bools = vec![true, false, true, true]; + let bitv: Bitv = bools.iter().map(|n| *n).collect(); + assert_eq!(bitv.to_string().as_slice(), "1011"); + } + + #[test] + fn test_bitv_set_from_bools() { + let bools = vec![true, false, true, true]; + let a: BitvSet = bools.iter().map(|n| *n).collect(); + let mut b = BitvSet::new(); + b.insert(0); + b.insert(2); + b.insert(3); + assert_eq!(a, b); + } + + #[test] + fn test_to_bools() { + let bools = vec!(false, false, true, false, false, true, true, false); + assert_eq!(from_bytes([0b00100110]).iter().collect::>(), bools); + } + + #[test] + fn test_bitv_iterator() { + let bools = vec![true, false, true, true]; + let bitv: Bitv = bools.iter().map(|n| *n).collect(); + + assert_eq!(bitv.iter().collect::>(), bools) + + let long = Vec::from_fn(10000, |i| i % 2 == 0); + let bitv: Bitv = long.iter().map(|n| *n).collect(); + assert_eq!(bitv.iter().collect::>(), long) + } + + #[test] + fn test_bitv_set_iterator() { + let bools = [true, false, true, true]; + let bitv: BitvSet = bools.iter().map(|n| *n).collect(); + + let idxs: Vec = bitv.iter().collect(); + assert_eq!(idxs, vec!(0, 2, 3)); + + let long: BitvSet = range(0u, 10000).map(|n| n % 2 == 0).collect(); + let real = range_step(0, 10000, 2).collect::>(); + + let idxs: Vec = long.iter().collect(); + assert_eq!(idxs, real); + } + + #[test] + fn test_bitv_set_frombitv_init() { + let bools = [true, false]; + let lengths = [10, 64, 100]; + for &b in bools.iter() { + for &l in lengths.iter() { + let bitset = BitvSet::from_bitv(Bitv::with_capacity(l, b)); + assert_eq!(bitset.contains(&1u), b) + assert_eq!(bitset.contains(&(l-1u)), b) + assert!(!bitset.contains(&l)) + } + } + } + + #[test] + fn test_small_difference() { + let mut b1 = Bitv::with_capacity(3, false); + let mut b2 = Bitv::with_capacity(3, false); + b1.set(0, true); + b1.set(1, true); + b2.set(1, true); + b2.set(2, true); + assert!(b1.difference(&b2)); + assert!(b1.get(0)); + assert!(!b1.get(1)); + assert!(!b1.get(2)); + } + + #[test] + fn test_big_difference() { + let mut b1 = Bitv::with_capacity(100, false); + let mut b2 = Bitv::with_capacity(100, false); + b1.set(0, true); + b1.set(40, true); + b2.set(40, true); + b2.set(80, true); + assert!(b1.difference(&b2)); + assert!(b1.get(0)); + assert!(!b1.get(40)); + assert!(!b1.get(80)); + } + + #[test] + fn test_small_clear() { + let mut b = Bitv::with_capacity(14, true); + b.clear(); + assert!(b.none()); + } + + #[test] + fn test_big_clear() { + let mut b = Bitv::with_capacity(140, true); + b.clear(); + assert!(b.none()); + } + + #[test] + fn test_bitv_masking() { + let b = Bitv::with_capacity(140, true); + let mut bs = BitvSet::from_bitv(b); + assert!(bs.contains(&139)); + assert!(!bs.contains(&140)); + assert!(bs.insert(150)); + assert!(!bs.contains(&140)); + assert!(!bs.contains(&149)); + assert!(bs.contains(&150)); + assert!(!bs.contains(&151)); + } + + #[test] + fn test_bitv_set_basic() { + // calculate nbits with u32::BITS granularity + fn calc_nbits(bits: uint) -> uint { + u32::BITS * ((bits + u32::BITS - 1) / u32::BITS) + } + + let mut b = BitvSet::new(); + assert_eq!(b.capacity(), calc_nbits(0)); + assert!(b.insert(3)); + assert_eq!(b.capacity(), calc_nbits(3)); + assert!(!b.insert(3)); + assert!(b.contains(&3)); + assert!(b.insert(4)); + assert!(!b.insert(4)); + assert!(b.contains(&3)); + assert!(b.insert(400)); + assert_eq!(b.capacity(), calc_nbits(400)); + assert!(!b.insert(400)); + assert!(b.contains(&400)); + assert_eq!(b.len(), 3); + } + + #[test] + fn test_bitv_set_intersection() { + let mut a = BitvSet::new(); + let mut b = BitvSet::new(); + + assert!(a.insert(11)); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(77)); + assert!(a.insert(103)); + assert!(a.insert(5)); + + assert!(b.insert(2)); + assert!(b.insert(11)); + assert!(b.insert(77)); + assert!(b.insert(5)); + assert!(b.insert(3)); + + let expected = [3, 5, 11, 77]; + let actual = a.intersection(&b).collect::>(); + assert_eq!(actual.as_slice(), expected.as_slice()); + } + + #[test] + fn test_bitv_set_difference() { + let mut a = BitvSet::new(); + let mut b = BitvSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(200)); + assert!(a.insert(500)); + + assert!(b.insert(3)); + assert!(b.insert(200)); + + let expected = [1, 5, 500]; + let actual = a.difference(&b).collect::>(); + assert_eq!(actual.as_slice(), expected.as_slice()); + } + + #[test] + fn test_bitv_set_symmetric_difference() { + let mut a = BitvSet::new(); + let mut b = BitvSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + + assert!(b.insert(3)); + assert!(b.insert(9)); + assert!(b.insert(14)); + assert!(b.insert(220)); + + let expected = [1, 5, 11, 14, 220]; + let actual = a.symmetric_difference(&b).collect::>(); + assert_eq!(actual.as_slice(), expected.as_slice()); + } + + #[test] + fn test_bitv_set_union() { + let mut a = BitvSet::new(); + let mut b = BitvSet::new(); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + assert!(a.insert(160)); + assert!(a.insert(19)); + assert!(a.insert(24)); + assert!(a.insert(200)); + + assert!(b.insert(1)); + assert!(b.insert(5)); + assert!(b.insert(9)); + assert!(b.insert(13)); + assert!(b.insert(19)); + + let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160, 200]; + let actual = a.union(&b).collect::>(); + assert_eq!(actual.as_slice(), expected.as_slice()); + } + + #[test] + fn test_bitv_set_subset() { + let mut set1 = BitvSet::new(); + let mut set2 = BitvSet::new(); + + assert!(set1.is_subset(&set2)); // {} {} + set2.insert(100); + assert!(set1.is_subset(&set2)); // {} { 1 } + set2.insert(200); + assert!(set1.is_subset(&set2)); // {} { 1, 2 } + set1.insert(200); + assert!(set1.is_subset(&set2)); // { 2 } { 1, 2 } + set1.insert(300); + assert!(!set1.is_subset(&set2)); // { 2, 3 } { 1, 2 } + set2.insert(300); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3 } + set2.insert(400); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3, 4 } + set2.remove(&100); + assert!(set1.is_subset(&set2)); // { 2, 3 } { 2, 3, 4 } + set2.remove(&300); + assert!(!set1.is_subset(&set2)); // { 2, 3 } { 2, 4 } + set1.remove(&300); + assert!(set1.is_subset(&set2)); // { 2 } { 2, 4 } + } + + #[test] + fn test_bitv_set_is_disjoint() { + let a = BitvSet::from_bitv(from_bytes([0b10100010])); + let b = BitvSet::from_bitv(from_bytes([0b01000000])); + let c = BitvSet::new(); + let d = BitvSet::from_bitv(from_bytes([0b00110000])); + + assert!(!a.is_disjoint(&d)); + assert!(!d.is_disjoint(&a)); + + assert!(a.is_disjoint(&b)) + assert!(a.is_disjoint(&c)) + assert!(b.is_disjoint(&a)) + assert!(b.is_disjoint(&c)) + assert!(c.is_disjoint(&a)) + assert!(c.is_disjoint(&b)) + } + + #[test] + fn test_bitv_set_union_with() { + //a should grow to include larger elements + let mut a = BitvSet::new(); + a.insert(0); + let mut b = BitvSet::new(); + b.insert(5); + let expected = BitvSet::from_bitv(from_bytes([0b10000100])); + a.union_with(&b); + assert_eq!(a, expected); + + // Standard + let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); + let mut b = BitvSet::from_bitv(from_bytes([0b01100010])); + let c = a.clone(); + a.union_with(&b); + b.union_with(&c); + assert_eq!(a.len(), 4); + assert_eq!(b.len(), 4); + } + + #[test] + fn test_bitv_set_intersect_with() { + // Explicitly 0'ed bits + let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); + let mut b = BitvSet::from_bitv(from_bytes([0b00000000])); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert!(a.is_empty()); + assert!(b.is_empty()); + + // Uninitialized bits should behave like 0's + let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); + let mut b = BitvSet::new(); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert!(a.is_empty()); + assert!(b.is_empty()); + + // Standard + let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); + let mut b = BitvSet::from_bitv(from_bytes([0b01100010])); + let c = a.clone(); + a.intersect_with(&b); + b.intersect_with(&c); + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); + } + + #[test] + fn test_bitv_set_difference_with() { + // Explicitly 0'ed bits + let mut a = BitvSet::from_bitv(from_bytes([0b00000000])); + let b = BitvSet::from_bitv(from_bytes([0b10100010])); + a.difference_with(&b); + assert!(a.is_empty()); + + // Uninitialized bits should behave like 0's + let mut a = BitvSet::new(); + let b = BitvSet::from_bitv(from_bytes([0b11111111])); + a.difference_with(&b); + assert!(a.is_empty()); + + // Standard + let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); + let mut b = BitvSet::from_bitv(from_bytes([0b01100010])); + let c = a.clone(); + a.difference_with(&b); + b.difference_with(&c); + assert_eq!(a.len(), 1); + assert_eq!(b.len(), 1); + } + + #[test] + fn test_bitv_set_symmetric_difference_with() { + //a should grow to include larger elements + let mut a = BitvSet::new(); + a.insert(0); + a.insert(1); + let mut b = BitvSet::new(); + b.insert(1); + b.insert(5); + let expected = BitvSet::from_bitv(from_bytes([0b10000100])); + a.symmetric_difference_with(&b); + assert_eq!(a, expected); + + let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); + let b = BitvSet::new(); + let c = a.clone(); + a.symmetric_difference_with(&b); + assert_eq!(a, c); + + // Standard + let mut a = BitvSet::from_bitv(from_bytes([0b11100010])); + let mut b = BitvSet::from_bitv(from_bytes([0b01101010])); + let c = a.clone(); + a.symmetric_difference_with(&b); + b.symmetric_difference_with(&c); + assert_eq!(a.len(), 2); + assert_eq!(b.len(), 2); + } + + #[test] + fn test_bitv_set_eq() { + let a = BitvSet::from_bitv(from_bytes([0b10100010])); + let b = BitvSet::from_bitv(from_bytes([0b00000000])); + let c = BitvSet::new(); + + assert!(a == a); + assert!(a != b); + assert!(a != c); + assert!(b == b); + assert!(b == c); + assert!(c == c); + } + + #[test] + fn test_bitv_set_cmp() { + let a = BitvSet::from_bitv(from_bytes([0b10100010])); + let b = BitvSet::from_bitv(from_bytes([0b00000000])); + let c = BitvSet::new(); + + assert_eq!(a.cmp(&b), Greater); + assert_eq!(a.cmp(&c), Greater); + assert_eq!(b.cmp(&a), Less); + assert_eq!(b.cmp(&c), Equal); + assert_eq!(c.cmp(&a), Less); + assert_eq!(c.cmp(&b), Equal); + } + + #[test] + fn test_bitv_remove() { + let mut a = BitvSet::new(); + + assert!(a.insert(1)); + assert!(a.remove(&1)); + + assert!(a.insert(100)); + assert!(a.remove(&100)); + + assert!(a.insert(1000)); + assert!(a.remove(&1000)); + a.shrink_to_fit(); + assert_eq!(a.capacity(), u32::BITS); + } + + #[test] + fn test_bitv_lt() { + let mut a = Bitv::with_capacity(5u, false); + let mut b = Bitv::with_capacity(5u, false); + + assert!(!(a < b) && !(b < a)); + b.set(2, true); + assert!(a < b); + a.set(3, true); + assert!(a < b); + a.set(2, true); + assert!(!(a < b) && b < a); + b.set(0, true); + assert!(a < b); + } + + #[test] + fn test_ord() { + let mut a = Bitv::with_capacity(5u, false); + let mut b = Bitv::with_capacity(5u, false); + + assert!(a <= b && a >= b); + a.set(1, true); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + b.set(1, true); + b.set(2, true); + assert!(b > a && b >= a); + assert!(a < b && a <= b); + } + + #[test] + fn test_bitv_clone() { + let mut a = BitvSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(100)); + assert!(a.insert(1000)); + + let mut b = a.clone(); + + assert!(a == b); + + assert!(b.remove(&1)); + assert!(a.contains(&1)); + + assert!(a.remove(&1000)); + assert!(b.contains(&1000)); + } + + #[test] + fn test_small_bitv_tests() { + let v = from_bytes([0]); + assert!(!v.all()); + assert!(!v.any()); + assert!(v.none()); + + let v = from_bytes([0b00010100]); + assert!(!v.all()); + assert!(v.any()); + assert!(!v.none()); + + let v = from_bytes([0xFF]); + assert!(v.all()); + assert!(v.any()); + assert!(!v.none()); + } + + #[test] + fn test_big_bitv_tests() { + let v = from_bytes([ // 88 bits + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0]); + assert!(!v.all()); + assert!(!v.any()); + assert!(v.none()); + + let v = from_bytes([ // 88 bits + 0, 0, 0b00010100, 0, + 0, 0, 0, 0b00110100, + 0, 0, 0]); + assert!(!v.all()); + assert!(v.any()); + assert!(!v.none()); + + let v = from_bytes([ // 88 bits + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF]); + assert!(v.all()); + assert!(v.any()); + assert!(!v.none()); + } + + #[test] + fn test_bitv_push_pop() { + let mut s = Bitv::with_capacity(5 * u32::BITS - 2, false); + assert_eq!(s.len(), 5 * u32::BITS - 2); + assert_eq!(s.get(5 * u32::BITS - 3), false); + s.push(true); + s.push(true); + assert_eq!(s.get(5 * u32::BITS - 2), true); + assert_eq!(s.get(5 * u32::BITS - 1), true); + // Here the internal vector will need to be extended + s.push(false); + assert_eq!(s.get(5 * u32::BITS), false); + s.push(false); + assert_eq!(s.get(5 * u32::BITS + 1), false); + assert_eq!(s.len(), 5 * u32::BITS + 2); + // Pop it all off + assert_eq!(s.pop(), false); + assert_eq!(s.pop(), false); + assert_eq!(s.pop(), true); + assert_eq!(s.pop(), true); + assert_eq!(s.len(), 5 * u32::BITS - 2); + } + + #[test] + fn test_bitv_truncate() { + let mut s = Bitv::with_capacity(5 * u32::BITS, true); + + assert_eq!(s, Bitv::with_capacity(5 * u32::BITS, true)); + assert_eq!(s.len(), 5 * u32::BITS); + s.truncate(4 * u32::BITS); + assert_eq!(s, Bitv::with_capacity(4 * u32::BITS, true)); + assert_eq!(s.len(), 4 * u32::BITS); + // Truncating to a size > s.len() should be a noop + s.truncate(5 * u32::BITS); + assert_eq!(s, Bitv::with_capacity(4 * u32::BITS, true)); + assert_eq!(s.len(), 4 * u32::BITS); + s.truncate(3 * u32::BITS - 10); + assert_eq!(s, Bitv::with_capacity(3 * u32::BITS - 10, true)); + assert_eq!(s.len(), 3 * u32::BITS - 10); + s.truncate(0); + assert_eq!(s, Bitv::with_capacity(0, true)); + assert_eq!(s.len(), 0); + } + + #[test] + fn test_bitv_reserve() { + let mut s = Bitv::with_capacity(5 * u32::BITS, true); + // Check capacity + assert_eq!(s.capacity(), 5 * u32::BITS); + s.reserve(2 * u32::BITS); + assert_eq!(s.capacity(), 5 * u32::BITS); + s.reserve(7 * u32::BITS); + assert_eq!(s.capacity(), 7 * u32::BITS); + s.reserve(7 * u32::BITS); + assert_eq!(s.capacity(), 7 * u32::BITS); + s.reserve(7 * u32::BITS + 1); + assert_eq!(s.capacity(), 8 * u32::BITS); + // Check that length hasn't changed + assert_eq!(s.len(), 5 * u32::BITS); + s.push(true); + s.push(false); + s.push(true); + assert_eq!(s.get(5 * u32::BITS - 1), true); + assert_eq!(s.get(5 * u32::BITS - 0), true); + assert_eq!(s.get(5 * u32::BITS + 1), false); + assert_eq!(s.get(5 * u32::BITS + 2), true); + } + + #[test] + fn test_bitv_grow() { + let mut bitv = from_bytes([0b10110110, 0b00000000, 0b10101010]); + bitv.grow(32, true); + assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF])); + bitv.grow(64, false); + assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])); + bitv.grow(16, true); + assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF])); + } + + #[test] + fn test_bitv_extend() { + let mut bitv = from_bytes([0b10110110, 0b00000000, 0b11111111]); + let ext = from_bytes([0b01001001, 0b10010010, 0b10111101]); + bitv.extend(ext.iter()); + assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b11111111, + 0b01001001, 0b10010010, 0b10111101])); + } + + #[test] + fn test_bitv_set_show() { + let mut s = BitvSet::new(); + s.insert(1); + s.insert(10); + s.insert(50); + s.insert(2); + assert_eq!("{1, 2, 10, 50}".to_string(), s.to_string()); + } + + fn rng() -> rand::IsaacRng { + let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + rand::SeedableRng::from_seed(seed) + } + + #[bench] + fn bench_uint_small(b: &mut Bencher) { + let mut r = rng(); + let mut bitv = 0 as uint; + b.iter(|| { + for _ in range(0u, 100) { + bitv |= 1 << ((r.next_u32() as uint) % u32::BITS); + } + &bitv + }) + } + + #[bench] + fn bench_bitv_set_big_fixed(b: &mut Bencher) { + let mut r = rng(); + let mut bitv = Bitv::with_capacity(BENCH_BITS, false); + b.iter(|| { + for _ in range(0u, 100) { + bitv.set((r.next_u32() as uint) % BENCH_BITS, true); + } + &bitv + }) + } + + #[bench] + fn bench_bitv_set_big_variable(b: &mut Bencher) { + let mut r = rng(); + let mut bitv = Bitv::with_capacity(BENCH_BITS, false); + b.iter(|| { + for _ in range(0u, 100) { + bitv.set((r.next_u32() as uint) % BENCH_BITS, r.gen()); + } + &bitv + }) + } + + #[bench] + fn bench_bitv_set_small(b: &mut Bencher) { + let mut r = rng(); + let mut bitv = Bitv::with_capacity(u32::BITS, false); + b.iter(|| { + for _ in range(0u, 100) { + bitv.set((r.next_u32() as uint) % u32::BITS, true); + } + &bitv + }) + } + + #[bench] + fn bench_bitvset_small(b: &mut Bencher) { + let mut r = rng(); + let mut bitv = BitvSet::new(); + b.iter(|| { + for _ in range(0u, 100) { + bitv.insert((r.next_u32() as uint) % u32::BITS); + } + &bitv + }) + } + + #[bench] + fn bench_bitvset_big(b: &mut Bencher) { + let mut r = rng(); + let mut bitv = BitvSet::new(); + b.iter(|| { + for _ in range(0u, 100) { + bitv.insert((r.next_u32() as uint) % BENCH_BITS); + } + &bitv + }) + } + + #[bench] + fn bench_bitv_big_union(b: &mut Bencher) { + let mut b1 = Bitv::with_capacity(BENCH_BITS, false); + let b2 = Bitv::with_capacity(BENCH_BITS, false); + b.iter(|| { + b1.union(&b2) + }) + } + + #[bench] + fn bench_bitv_small_iter(b: &mut Bencher) { + let bitv = Bitv::with_capacity(u32::BITS, false); + b.iter(|| { + let mut sum = 0u; + for _ in range(0u, 10) { + for pres in bitv.iter() { + sum += pres as uint; + } + } + sum + }) + } + + #[bench] + fn bench_bitv_big_iter(b: &mut Bencher) { + let bitv = Bitv::with_capacity(BENCH_BITS, false); + b.iter(|| { + let mut sum = 0u; + for pres in bitv.iter() { + sum += pres as uint; + } + sum + }) + } + + #[bench] + fn bench_bitvset_iter(b: &mut Bencher) { + let bitv = BitvSet::from_bitv(from_fn(BENCH_BITS, + |idx| {idx % 3 == 0})); + b.iter(|| { + let mut sum = 0u; + for idx in bitv.iter() { + sum += idx as uint; + } + sum + }) + } +} diff --git a/src/libcollections/bitv.rs b/src/libcollections/bitv.rs deleted file mode 100644 index 26e0c73724c..00000000000 --- a/src/libcollections/bitv.rs +++ /dev/null @@ -1,2761 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Collections implemented with bit vectors. -//! -//! # Example -//! -//! This is a simple example of the [Sieve of Eratosthenes][sieve] -//! which calculates prime numbers up to a given limit. -//! -//! [sieve]: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes -//! -//! ``` -//! use std::collections::{BitvSet, Bitv}; -//! use std::iter; -//! -//! let max_prime = 10000; -//! -//! // Store the primes as a BitvSet -//! let primes = { -//! // Assume all numbers are prime to begin, and then we -//! // cross off non-primes progressively -//! let mut bv = Bitv::with_capacity(max_prime, true); -//! -//! // Neither 0 nor 1 are prime -//! bv.set(0, false); -//! bv.set(1, false); -//! -//! for i in iter::range_inclusive(2, (max_prime as f64).sqrt() as uint) { -//! // if i is a prime -//! if bv[i] { -//! // Mark all multiples of i as non-prime (any multiples below i * i -//! // will have been marked as non-prime previously) -//! for j in iter::range_step(i * i, max_prime, i) { bv.set(j, false) } -//! } -//! } -//! BitvSet::from_bitv(bv) -//! }; -//! -//! // Simple primality tests below our max bound -//! let print_primes = 20; -//! print!("The primes below {} are: ", print_primes); -//! for x in range(0, print_primes) { -//! if primes.contains(&x) { -//! print!("{} ", x); -//! } -//! } -//! println!(""); -//! -//! // We can manipulate the internal Bitv -//! let num_primes = primes.get_ref().iter().filter(|x| *x).count(); -//! println!("There are {} primes below {}", num_primes, max_prime); -//! ``` - -use core::prelude::*; - -use core::cmp; -use core::default::Default; -use core::fmt; -use core::iter::{Chain, Enumerate, Repeat, Skip, Take}; -use core::iter; -use core::slice; -use core::u32; -use std::hash; - -use vec::Vec; - -type MatchWords<'a> = Chain, Skip>>>>; -// Take two BitV's, and return iterators of their words, where the shorter one -// has been padded with 0's -fn match_words <'a,'b>(a: &'a Bitv, b: &'b Bitv) -> (MatchWords<'a>, MatchWords<'b>) { - let a_len = a.storage.len(); - let b_len = b.storage.len(); - - // have to uselessly pretend to pad the longer one for type matching - if a_len < b_len { - (a.mask_words(0).chain(Repeat::new(0u32).enumerate().take(b_len).skip(a_len)), - b.mask_words(0).chain(Repeat::new(0u32).enumerate().take(0).skip(0))) - } else { - (a.mask_words(0).chain(Repeat::new(0u32).enumerate().take(0).skip(0)), - b.mask_words(0).chain(Repeat::new(0u32).enumerate().take(a_len).skip(b_len))) - } -} - -static TRUE: bool = true; -static FALSE: bool = false; - -/// The bitvector type. -/// -/// # Example -/// -/// ```rust -/// use collections::Bitv; -/// -/// let mut bv = Bitv::with_capacity(10, false); -/// -/// // insert all primes less than 10 -/// bv.set(2, true); -/// bv.set(3, true); -/// bv.set(5, true); -/// bv.set(7, true); -/// println!("{}", bv.to_string()); -/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count()); -/// -/// // flip all values in bitvector, producing non-primes less than 10 -/// bv.negate(); -/// println!("{}", bv.to_string()); -/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count()); -/// -/// // reset bitvector to empty -/// bv.clear(); -/// println!("{}", bv.to_string()); -/// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count()); -/// ``` -pub struct Bitv { - /// Internal representation of the bit vector - storage: Vec, - /// The number of valid bits in the internal representation - nbits: uint -} - -impl Index for Bitv { - #[inline] - fn index<'a>(&'a self, i: &uint) -> &'a bool { - if self.get(*i) { - &TRUE - } else { - &FALSE - } - } -} - -struct MaskWords<'a> { - iter: slice::Items<'a, u32>, - next_word: Option<&'a u32>, - last_word_mask: u32, - offset: uint -} - -impl<'a> Iterator<(uint, u32)> for MaskWords<'a> { - /// Returns (offset, word) - #[inline] - fn next<'a>(&'a mut self) -> Option<(uint, u32)> { - let ret = self.next_word; - match ret { - Some(&w) => { - self.next_word = self.iter.next(); - self.offset += 1; - // The last word may need to be masked - if self.next_word.is_none() { - Some((self.offset - 1, w & self.last_word_mask)) - } else { - Some((self.offset - 1, w)) - } - }, - None => None - } - } -} - -impl Bitv { - #[inline] - fn process(&mut self, other: &Bitv, op: |u32, u32| -> u32) -> bool { - let len = other.storage.len(); - assert_eq!(self.storage.len(), len); - let mut changed = false; - // Notice: `a` is *not* masked here, which is fine as long as - // `op` is a bitwise operation, since any bits that should've - // been masked were fine to change anyway. `b` is masked to - // make sure its unmasked bits do not cause damage. - for (a, (_, b)) in self.storage.iter_mut() - .zip(other.mask_words(0)) { - let w = op(*a, b); - if *a != w { - changed = true; - *a = w; - } - } - changed - } - - #[inline] - fn mask_words<'a>(&'a self, mut start: uint) -> MaskWords<'a> { - if start > self.storage.len() { - start = self.storage.len(); - } - let mut iter = self.storage[start..].iter(); - MaskWords { - next_word: iter.next(), - iter: iter, - last_word_mask: { - let rem = self.nbits % u32::BITS; - if rem > 0 { - (1 << rem) - 1 - } else { !0 } - }, - offset: start - } - } - - /// Creates an empty `Bitv`. - /// - /// # Example - /// - /// ``` - /// use std::collections::Bitv; - /// let mut bv = Bitv::new(); - /// ``` - pub fn new() -> Bitv { - Bitv { storage: Vec::new(), nbits: 0 } - } - - /// Creates a `Bitv` that holds `nbits` elements, setting each element - /// to `init`. - /// - /// # Example - /// - /// ``` - /// use std::collections::Bitv; - /// - /// let mut bv = Bitv::with_capacity(10u, false); - /// assert_eq!(bv.len(), 10u); - /// for x in bv.iter() { - /// assert_eq!(x, false); - /// } - /// ``` - pub fn with_capacity(nbits: uint, init: bool) -> Bitv { - let mut bitv = Bitv { - storage: Vec::from_elem((nbits + u32::BITS - 1) / u32::BITS, - if init { !0u32 } else { 0u32 }), - nbits: nbits - }; - - // Zero out any unused bits in the highest word if necessary - let used_bits = bitv.nbits % u32::BITS; - if init && used_bits != 0 { - let largest_used_word = (bitv.nbits + u32::BITS - 1) / u32::BITS - 1; - bitv.storage[largest_used_word] &= (1 << used_bits) - 1; - } - - bitv - } - - /// Retrieves the value at index `i`. - /// - /// # Failure - /// - /// Fails if `i` is out of bounds. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let bv = bitv::from_bytes([0b01100000]); - /// assert_eq!(bv.get(0), false); - /// assert_eq!(bv.get(1), true); - /// - /// // Can also use array indexing - /// assert_eq!(bv[1], true); - /// ``` - #[inline] - pub fn get(&self, i: uint) -> bool { - assert!(i < self.nbits); - let w = i / u32::BITS; - let b = i % u32::BITS; - let x = self.storage[w] & (1 << b); - x != 0 - } - - /// Sets the value of a bit at a index `i`. - /// - /// # Failure - /// - /// Fails if `i` is out of bounds. - /// - /// # Example - /// - /// ``` - /// use std::collections::Bitv; - /// - /// let mut bv = Bitv::with_capacity(5, false); - /// bv.set(3, true); - /// assert_eq!(bv[3], true); - /// ``` - #[inline] - pub fn set(&mut self, i: uint, x: bool) { - assert!(i < self.nbits); - let w = i / u32::BITS; - let b = i % u32::BITS; - let flag = 1 << b; - let val = if x { self.storage[w] | flag } - else { self.storage[w] & !flag }; - self.storage[w] = val; - } - - /// Sets all bits to 1. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let before = 0b01100000; - /// let after = 0b11111111; - /// - /// let mut bv = bitv::from_bytes([before]); - /// bv.set_all(); - /// assert_eq!(bv, bitv::from_bytes([after])); - /// ``` - #[inline] - pub fn set_all(&mut self) { - for w in self.storage.iter_mut() { *w = !0u32; } - } - - /// Flips all bits. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let before = 0b01100000; - /// let after = 0b10011111; - /// - /// let mut bv = bitv::from_bytes([before]); - /// bv.negate(); - /// assert_eq!(bv, bitv::from_bytes([after])); - /// ``` - #[inline] - pub fn negate(&mut self) { - for w in self.storage.iter_mut() { *w = !*w; } - } - - /// Calculates the union of two bitvectors. This acts like the bitwise `or` - /// function. - /// - /// Sets `self` to the union of `self` and `other`. Both bitvectors must be - /// the same length. Returns `true` if `self` changed. - /// - /// # Failure - /// - /// Fails if the bitvectors are of different lengths. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let a = 0b01100100; - /// let b = 0b01011010; - /// let res = 0b01111110; - /// - /// let mut a = bitv::from_bytes([a]); - /// let b = bitv::from_bytes([b]); - /// - /// assert!(a.union(&b)); - /// assert_eq!(a, bitv::from_bytes([res])); - /// ``` - #[inline] - pub fn union(&mut self, other: &Bitv) -> bool { - self.process(other, |w1, w2| w1 | w2) - } - - /// Calculates the intersection of two bitvectors. This acts like the - /// bitwise `and` function. - /// - /// Sets `self` to the intersection of `self` and `other`. Both bitvectors - /// must be the same length. Returns `true` if `self` changed. - /// - /// # Failure - /// - /// Fails if the bitvectors are of different lengths. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let a = 0b01100100; - /// let b = 0b01011010; - /// let res = 0b01000000; - /// - /// let mut a = bitv::from_bytes([a]); - /// let b = bitv::from_bytes([b]); - /// - /// assert!(a.intersect(&b)); - /// assert_eq!(a, bitv::from_bytes([res])); - /// ``` - #[inline] - pub fn intersect(&mut self, other: &Bitv) -> bool { - self.process(other, |w1, w2| w1 & w2) - } - - /// Calculates the difference between two bitvectors. - /// - /// Sets each element of `self` to the value of that element minus the - /// element of `other` at the same index. Both bitvectors must be the same - /// length. Returns `true` if `self` changed. - /// - /// # Failure - /// - /// Fails if the bitvectors are of different length. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let a = 0b01100100; - /// let b = 0b01011010; - /// let a_b = 0b00100100; // a - b - /// let b_a = 0b00011010; // b - a - /// - /// let mut bva = bitv::from_bytes([a]); - /// let bvb = bitv::from_bytes([b]); - /// - /// assert!(bva.difference(&bvb)); - /// assert_eq!(bva, bitv::from_bytes([a_b])); - /// - /// let bva = bitv::from_bytes([a]); - /// let mut bvb = bitv::from_bytes([b]); - /// - /// assert!(bvb.difference(&bva)); - /// assert_eq!(bvb, bitv::from_bytes([b_a])); - /// ``` - #[inline] - pub fn difference(&mut self, other: &Bitv) -> bool { - self.process(other, |w1, w2| w1 & !w2) - } - - /// Returns `true` if all bits are 1. - /// - /// # Example - /// - /// ``` - /// use std::collections::Bitv; - /// - /// let mut bv = Bitv::with_capacity(5, true); - /// assert_eq!(bv.all(), true); - /// - /// bv.set(1, false); - /// assert_eq!(bv.all(), false); - /// ``` - #[inline] - pub fn all(&self) -> bool { - let mut last_word = !0u32; - // Check that every word but the last is all-ones... - self.mask_words(0).all(|(_, elem)| - { let tmp = last_word; last_word = elem; tmp == !0u32 }) && - // ...and that the last word is ones as far as it needs to be - (last_word == ((1 << self.nbits % u32::BITS) - 1) || last_word == !0u32) - } - - /// Returns an iterator over the elements of the vector in order. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let bv = bitv::from_bytes([0b01110100, 0b10010010]); - /// assert_eq!(bv.iter().filter(|x| *x).count(), 7); - /// ``` - #[inline] - pub fn iter<'a>(&'a self) -> Bits<'a> { - Bits {bitv: self, next_idx: 0, end_idx: self.nbits} - } - - /// Returns `true` if all bits are 0. - /// - /// # Example - /// - /// ``` - /// use std::collections::Bitv; - /// - /// let mut bv = Bitv::with_capacity(10, false); - /// assert_eq!(bv.none(), true); - /// - /// bv.set(3, true); - /// assert_eq!(bv.none(), false); - /// ``` - pub fn none(&self) -> bool { - self.mask_words(0).all(|(_, w)| w == 0) - } - - /// Returns `true` if any bit is 1. - /// - /// # Example - /// - /// ``` - /// use std::collections::Bitv; - /// - /// let mut bv = Bitv::with_capacity(10, false); - /// assert_eq!(bv.any(), false); - /// - /// bv.set(3, true); - /// assert_eq!(bv.any(), true); - /// ``` - #[inline] - pub fn any(&self) -> bool { - !self.none() - } - - /// Organises the bits into bytes, such that the first bit in the - /// `Bitv` becomes the high-order bit of the first byte. If the - /// size of the `Bitv` is not a multiple of eight then trailing bits - /// will be filled-in with `false`. - /// - /// # Example - /// - /// ``` - /// use std::collections::Bitv; - /// - /// let mut bv = Bitv::with_capacity(3, true); - /// bv.set(1, false); - /// - /// assert_eq!(bv.to_bytes(), vec!(0b10100000)); - /// - /// let mut bv = Bitv::with_capacity(9, false); - /// bv.set(2, true); - /// bv.set(8, true); - /// - /// assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000)); - /// ``` - pub fn to_bytes(&self) -> Vec { - fn bit (bitv: &Bitv, byte: uint, bit: uint) -> u8 { - let offset = byte * 8 + bit; - if offset >= bitv.nbits { - 0 - } else { - bitv.get(offset) as u8 << (7 - bit) - } - } - - let len = self.nbits/8 + - if self.nbits % 8 == 0 { 0 } else { 1 }; - Vec::from_fn(len, |i| - bit(self, i, 0) | - bit(self, i, 1) | - bit(self, i, 2) | - bit(self, i, 3) | - bit(self, i, 4) | - bit(self, i, 5) | - bit(self, i, 6) | - bit(self, i, 7) - ) - } - - /// Transforms `self` into a `Vec` by turning each bit into a `bool`. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let bv = bitv::from_bytes([0b10100000]); - /// assert_eq!(bv.to_bools(), vec!(true, false, true, false, - /// false, false, false, false)); - /// ``` - pub fn to_bools(&self) -> Vec { - Vec::from_fn(self.nbits, |i| self.get(i)) - } - - /// Compares a `Bitv` to a slice of `bool`s. - /// Both the `Bitv` and slice must have the same length. - /// - /// # Failure - /// - /// Fails if the the `Bitv` and slice are of different length. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let bv = bitv::from_bytes([0b10100000]); - /// - /// assert!(bv.eq_vec([true, false, true, false, - /// false, false, false, false])); - /// ``` - pub fn eq_vec(&self, v: &[bool]) -> bool { - assert_eq!(self.nbits, v.len()); - let mut i = 0; - while i < self.nbits { - if self.get(i) != v[i] { return false; } - i = i + 1; - } - true - } - - /// Shortens a `Bitv`, dropping excess elements. - /// - /// If `len` is greater than the vector's current length, this has no - /// effect. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let mut bv = bitv::from_bytes([0b01001011]); - /// bv.truncate(2); - /// assert!(bv.eq_vec([false, true])); - /// ``` - pub fn truncate(&mut self, len: uint) { - if len < self.len() { - self.nbits = len; - let word_len = (len + u32::BITS - 1) / u32::BITS; - self.storage.truncate(word_len); - if len % u32::BITS > 0 { - let mask = (1 << len % u32::BITS) - 1; - self.storage[word_len - 1] &= mask; - } - } - } - - /// Grows the vector to be able to store `size` bits without resizing. - /// - /// # Example - /// - /// ``` - /// use std::collections::Bitv; - /// - /// let mut bv = Bitv::with_capacity(3, false); - /// bv.reserve(10); - /// assert_eq!(bv.len(), 3); - /// assert!(bv.capacity() >= 10); - /// ``` - pub fn reserve(&mut self, size: uint) { - let old_size = self.storage.len(); - let new_size = (size + u32::BITS - 1) / u32::BITS; - if old_size < new_size { - self.storage.grow(new_size - old_size, 0); - } - } - - /// Returns the capacity in bits for this bit vector. Inserting any - /// element less than this amount will not trigger a resizing. - /// - /// # Example - /// - /// ``` - /// use std::collections::Bitv; - /// - /// let mut bv = Bitv::new(); - /// bv.reserve(10); - /// assert!(bv.capacity() >= 10); - /// ``` - #[inline] - pub fn capacity(&self) -> uint { - self.storage.len() * u32::BITS - } - - /// Grows the `Bitv` in-place, adding `n` copies of `value` to the `Bitv`. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let mut bv = bitv::from_bytes([0b01001011]); - /// bv.grow(2, true); - /// assert_eq!(bv.len(), 10); - /// assert_eq!(bv.to_bytes(), vec!(0b01001011, 0b11000000)); - /// ``` - pub fn grow(&mut self, n: uint, value: bool) { - let new_nbits = self.nbits + n; - let new_nwords = (new_nbits + u32::BITS - 1) / u32::BITS; - let full_value = if value { !0 } else { 0 }; - // Correct the old tail word - let old_last_word = (self.nbits + u32::BITS - 1) / u32::BITS - 1; - if self.nbits % u32::BITS > 0 { - let overhang = self.nbits % u32::BITS; // # of already-used bits - let mask = !((1 << overhang) - 1); // e.g. 5 unused bits => 111110....0 - if value { - self.storage[old_last_word] |= mask; - } else { - self.storage[old_last_word] &= !mask; - } - } - // Fill in words after the old tail word - let stop_idx = cmp::min(self.storage.len(), new_nwords); - for idx in range(old_last_word + 1, stop_idx) { - self.storage[idx] = full_value; - } - // Allocate new words, if needed - if new_nwords > self.storage.len() { - let to_add = new_nwords - self.storage.len(); - self.storage.grow(to_add, full_value); - - // Zero out and unused bits in the new tail word - if value { - let tail_word = new_nwords - 1; - let used_bits = new_nbits % u32::BITS; - self.storage[tail_word] &= (1 << used_bits) - 1; - } - } - // Adjust internal bit count - self.nbits = new_nbits; - } - - /// Shortens by one element and returns the removed element. - /// - /// # Failure - /// - /// Assert if empty. - /// - /// # Example - /// - /// ``` - /// use std::collections::bitv; - /// - /// let mut bv = bitv::from_bytes([0b01001001]); - /// assert_eq!(bv.pop(), true); - /// assert_eq!(bv.pop(), false); - /// assert_eq!(bv.len(), 6); - /// assert_eq!(bv.to_bytes(), vec!(0b01001000)); - /// ``` - pub fn pop(&mut self) -> bool { - let ret = self.get(self.nbits - 1); - // If we are unusing a whole word, make sure it is zeroed out - if self.nbits % u32::BITS == 1 { - self.storage[self.nbits / u32::BITS] = 0; - } - self.nbits -= 1; - ret - } - - /// Pushes a `bool` onto the end. - /// - /// # Example - /// - /// ``` - /// use std::collections::Bitv; - /// - /// let mut bv = Bitv::new(); - /// bv.push(true); - /// bv.push(false); - /// assert!(bv.eq_vec([true, false])); - /// ``` - pub fn push(&mut self, elem: bool) { - let insert_pos = self.nbits; - self.nbits += 1; - if self.storage.len() * u32::BITS < self.nbits { - self.storage.push(0); - } - self.set(insert_pos, elem); - } - - /// Return the total number of bits in this vector - #[inline] - pub fn len(&self) -> uint { self.nbits } - - /// Returns true if there are no bits in this vector - #[inline] - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears all bits in this vector. - #[inline] - pub fn clear(&mut self) { - for w in self.storage.iter_mut() { *w = 0u32; } - } -} - -/// Transforms a byte-vector into a `Bitv`. Each byte becomes eight bits, -/// with the most significant bits of each byte coming first. Each -/// bit becomes `true` if equal to 1 or `false` if equal to 0. -/// -/// # Example -/// -/// ``` -/// use std::collections::bitv; -/// -/// let bv = bitv::from_bytes([0b10100000, 0b00010010]); -/// assert!(bv.eq_vec([true, false, true, false, -/// false, false, false, false, -/// false, false, false, true, -/// false, false, true, false])); -/// ``` -pub fn from_bytes(bytes: &[u8]) -> Bitv { - from_fn(bytes.len() * 8, |i| { - let b = bytes[i / 8] as u32; - let offset = i % 8; - b >> (7 - offset) & 1 == 1 - }) -} - -/// Creates a `Bitv` of the specified length where the value at each -/// index is `f(index)`. -/// -/// # Example -/// -/// ``` -/// use std::collections::bitv::from_fn; -/// -/// let bv = from_fn(5, |i| { i % 2 == 0 }); -/// assert!(bv.eq_vec([true, false, true, false, true])); -/// ``` -pub fn from_fn(len: uint, f: |index: uint| -> bool) -> Bitv { - let mut bitv = Bitv::with_capacity(len, false); - for i in range(0u, len) { - bitv.set(i, f(i)); - } - bitv -} - -impl Default for Bitv { - #[inline] - fn default() -> Bitv { Bitv::new() } -} - -impl FromIterator for Bitv { - fn from_iter>(iterator: I) -> Bitv { - let mut ret = Bitv::new(); - ret.extend(iterator); - ret - } -} - -impl Extendable for Bitv { - #[inline] - fn extend>(&mut self, mut iterator: I) { - let (min, _) = iterator.size_hint(); - let nbits = self.nbits; - self.reserve(nbits + min); - for element in iterator { - self.push(element) - } - } -} - -impl Clone for Bitv { - #[inline] - fn clone(&self) -> Bitv { - Bitv { storage: self.storage.clone(), nbits: self.nbits } - } - - #[inline] - fn clone_from(&mut self, source: &Bitv) { - self.nbits = source.nbits; - self.storage.reserve(source.storage.len()); - for (i, w) in self.storage.iter_mut().enumerate() { *w = source.storage[i]; } - } -} - -impl PartialOrd for Bitv { - #[inline] - fn partial_cmp(&self, other: &Bitv) -> Option { - iter::order::partial_cmp(self.iter(), other.iter()) - } -} - -impl Ord for Bitv { - #[inline] - fn cmp(&self, other: &Bitv) -> Ordering { - iter::order::cmp(self.iter(), other.iter()) - } -} - -impl fmt::Show for Bitv { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - for bit in self.iter() { - try!(write!(fmt, "{}", if bit { 1u } else { 0u })); - } - Ok(()) - } -} - -impl hash::Hash for Bitv { - fn hash(&self, state: &mut S) { - self.nbits.hash(state); - for (_, elem) in self.mask_words(0) { - elem.hash(state); - } - } -} - -impl cmp::PartialEq for Bitv { - #[inline] - fn eq(&self, other: &Bitv) -> bool { - if self.nbits != other.nbits { - return false; - } - self.mask_words(0).zip(other.mask_words(0)).all(|((_, w1), (_, w2))| w1 == w2) - } -} - -impl cmp::Eq for Bitv {} - -/// An iterator for `Bitv`. -pub struct Bits<'a> { - bitv: &'a Bitv, - next_idx: uint, - end_idx: uint, -} - -impl<'a> Iterator for Bits<'a> { - #[inline] - fn next(&mut self) -> Option { - if self.next_idx != self.end_idx { - let idx = self.next_idx; - self.next_idx += 1; - Some(self.bitv.get(idx)) - } else { - None - } - } - - fn size_hint(&self) -> (uint, Option) { - let rem = self.end_idx - self.next_idx; - (rem, Some(rem)) - } -} - -impl<'a> DoubleEndedIterator for Bits<'a> { - #[inline] - fn next_back(&mut self) -> Option { - if self.next_idx != self.end_idx { - self.end_idx -= 1; - Some(self.bitv.get(self.end_idx)) - } else { - None - } - } -} - -impl<'a> ExactSize for Bits<'a> {} - -impl<'a> RandomAccessIterator for Bits<'a> { - #[inline] - fn indexable(&self) -> uint { - self.end_idx - self.next_idx - } - - #[inline] - fn idx(&mut self, index: uint) -> Option { - if index >= self.indexable() { - None - } else { - Some(self.bitv.get(index)) - } - } -} - -/// An implementation of a set using a bit vector as an underlying -/// representation for holding unsigned numerical elements. -/// -/// It should also be noted that the amount of storage necessary for holding a -/// set of objects is proportional to the maximum of the objects when viewed -/// as a `uint`. -/// -/// # Example -/// -/// ``` -/// use std::collections::{BitvSet, Bitv}; -/// use std::collections::bitv; -/// -/// // It's a regular set -/// let mut s = BitvSet::new(); -/// s.insert(0); -/// s.insert(3); -/// s.insert(7); -/// -/// s.remove(&7); -/// -/// if !s.contains(&7) { -/// println!("There is no 7"); -/// } -/// -/// // Can initialize from a `Bitv` -/// let other = BitvSet::from_bitv(bitv::from_bytes([0b11010000])); -/// -/// s.union_with(&other); -/// -/// // Print 0, 1, 3 in some order -/// for x in s.iter() { -/// println!("{}", x); -/// } -/// -/// // Can convert back to a `Bitv` -/// let bv: Bitv = s.into_bitv(); -/// assert!(bv.get(3)); -/// ``` -#[deriving(Clone)] -pub struct BitvSet(Bitv); - -impl Default for BitvSet { - #[inline] - fn default() -> BitvSet { BitvSet::new() } -} - -impl FromIterator for BitvSet { - fn from_iter>(iterator: I) -> BitvSet { - let mut ret = BitvSet::new(); - ret.extend(iterator); - ret - } -} - -impl Extendable for BitvSet { - #[inline] - fn extend>(&mut self, iterator: I) { - let &BitvSet(ref mut self_bitv) = self; - self_bitv.extend(iterator); - } -} - -impl PartialOrd for BitvSet { - #[inline] - fn partial_cmp(&self, other: &BitvSet) -> Option { - let (a_iter, b_iter) = match_words(self.get_ref(), other.get_ref()); - iter::order::partial_cmp(a_iter, b_iter) - } -} - -impl Ord for BitvSet { - #[inline] - fn cmp(&self, other: &BitvSet) -> Ordering { - let (a_iter, b_iter) = match_words(self.get_ref(), other.get_ref()); - iter::order::cmp(a_iter, b_iter) - } -} - -impl cmp::PartialEq for BitvSet { - #[inline] - fn eq(&self, other: &BitvSet) -> bool { - let (a_iter, b_iter) = match_words(self.get_ref(), other.get_ref()); - iter::order::eq(a_iter, b_iter) - } -} - -impl cmp::Eq for BitvSet {} - -impl BitvSet { - /// Creates a new bit vector set with initially no contents. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// let mut s = BitvSet::new(); - /// ``` - #[inline] - pub fn new() -> BitvSet { - BitvSet(Bitv::new()) - } - - /// Creates a new bit vector set with initially no contents, able to - /// hold `nbits` elements without resizing. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// let mut s = BitvSet::with_capacity(100); - /// assert!(s.capacity() >= 100); - /// ``` - #[inline] - pub fn with_capacity(nbits: uint) -> BitvSet { - let bitv = Bitv::with_capacity(nbits, false); - BitvSet::from_bitv(bitv) - } - - /// Creates a new bit vector set from the given bit vector. - /// - /// # Example - /// - /// ``` - /// use std::collections::{bitv, BitvSet}; - /// - /// let bv = bitv::from_bytes([0b01100000]); - /// let s = BitvSet::from_bitv(bv); - /// - /// // Print 1, 2 in arbitrary order - /// for x in s.iter() { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn from_bitv(mut bitv: Bitv) -> BitvSet { - // Mark every bit as valid - bitv.nbits = bitv.capacity(); - BitvSet(bitv) - } - - /// Returns the capacity in bits for this bit vector. Inserting any - /// element less than this amount will not trigger a resizing. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// - /// let mut s = BitvSet::with_capacity(100); - /// assert!(s.capacity() >= 100); - /// ``` - #[inline] - pub fn capacity(&self) -> uint { - let &BitvSet(ref bitv) = self; - bitv.capacity() - } - - /// Grows the underlying vector to be able to store `size` bits. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// - /// let mut s = BitvSet::new(); - /// s.reserve(10); - /// assert!(s.capacity() >= 10); - /// ``` - pub fn reserve(&mut self, size: uint) { - let &BitvSet(ref mut bitv) = self; - bitv.reserve(size); - if bitv.nbits < size { - bitv.nbits = bitv.capacity(); - } - } - - /// Consumes this set to return the underlying bit vector. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// - /// let mut s = BitvSet::new(); - /// s.insert(0); - /// s.insert(3); - /// - /// let bv = s.into_bitv(); - /// assert!(bv.get(0)); - /// assert!(bv.get(3)); - /// ``` - #[inline] - pub fn into_bitv(self) -> Bitv { - let BitvSet(bitv) = self; - bitv - } - - /// Returns a reference to the underlying bit vector. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// - /// let mut s = BitvSet::new(); - /// s.insert(0); - /// - /// let bv = s.get_ref(); - /// assert_eq!(bv[0], true); - /// ``` - #[inline] - pub fn get_ref<'a>(&'a self) -> &'a Bitv { - let &BitvSet(ref bitv) = self; - bitv - } - - #[inline] - fn other_op(&mut self, other: &BitvSet, f: |u32, u32| -> u32) { - // Expand the vector if necessary - self.reserve(other.capacity()); - - // Unwrap Bitvs - let &BitvSet(ref mut self_bitv) = self; - let &BitvSet(ref other_bitv) = other; - - // virtually pad other with 0's for equal lengths - let mut other_words = { - let (_, result) = match_words(self_bitv, other_bitv); - result - }; - - // Apply values found in other - for (i, w) in other_words { - let old = self_bitv.storage[i]; - let new = f(old, w); - self_bitv.storage[i] = new; - } - } - - /// Truncates the underlying vector to the least length required. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// - /// let mut s = BitvSet::new(); - /// s.insert(32183231); - /// s.remove(&32183231); - /// - /// // Internal storage will probably be bigger than necessary - /// println!("old capacity: {}", s.capacity()); - /// - /// // Now should be smaller - /// s.shrink_to_fit(); - /// println!("new capacity: {}", s.capacity()); - /// ``` - #[inline] - pub fn shrink_to_fit(&mut self) { - let &BitvSet(ref mut bitv) = self; - // Obtain original length - let old_len = bitv.storage.len(); - // Obtain coarse trailing zero length - let n = bitv.storage.iter().rev().take_while(|&&n| n == 0).count(); - // Truncate - let trunc_len = cmp::max(old_len - n, 1); - bitv.storage.truncate(trunc_len); - bitv.nbits = trunc_len * u32::BITS; - } - - /// Iterator over each u32 stored in the `BitvSet`. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; - /// - /// let s = BitvSet::from_bitv(bitv::from_bytes([0b01001010])); - /// - /// // Print 1, 4, 6 in arbitrary order - /// for x in s.iter() { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn iter<'a>(&'a self) -> BitPositions<'a> { - BitPositions {set: self, next_idx: 0u} - } - - /// Iterator over each u32 stored in `self` union `other`. - /// See [union_with](#method.union_with) for an efficient in-place version. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; - /// - /// let a = BitvSet::from_bitv(bitv::from_bytes([0b01101000])); - /// let b = BitvSet::from_bitv(bitv::from_bytes([0b10100000])); - /// - /// // Print 0, 1, 2, 4 in arbitrary order - /// for x in a.union(&b) { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn union<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> { - TwoBitPositions { - set: self, - other: other, - merge: |w1, w2| w1 | w2, - current_word: 0u32, - next_idx: 0u - } - } - - /// Iterator over each uint stored in `self` intersect `other`. - /// See [intersect_with](#method.intersect_with) for an efficient in-place version. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; - /// - /// let a = BitvSet::from_bitv(bitv::from_bytes([0b01101000])); - /// let b = BitvSet::from_bitv(bitv::from_bytes([0b10100000])); - /// - /// // Print 2 - /// for x in a.intersection(&b) { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn intersection<'a>(&'a self, other: &'a BitvSet) -> Take> { - let min = cmp::min(self.capacity(), other.capacity()); - TwoBitPositions { - set: self, - other: other, - merge: |w1, w2| w1 & w2, - current_word: 0u32, - next_idx: 0 - }.take(min) - } - - /// Iterator over each uint stored in the `self` setminus `other`. - /// See [difference_with](#method.difference_with) for an efficient in-place version. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; - /// - /// let a = BitvSet::from_bitv(bitv::from_bytes([0b01101000])); - /// let b = BitvSet::from_bitv(bitv::from_bytes([0b10100000])); - /// - /// // Print 1, 4 in arbitrary order - /// for x in a.difference(&b) { - /// println!("{}", x); - /// } - /// - /// // Note that difference is not symmetric, - /// // and `b - a` means something else. - /// // This prints 0 - /// for x in b.difference(&a) { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn difference<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> { - TwoBitPositions { - set: self, - other: other, - merge: |w1, w2| w1 & !w2, - current_word: 0u32, - next_idx: 0 - } - } - - /// Iterator over each u32 stored in the symmetric difference of `self` and `other`. - /// See [symmetric_difference_with](#method.symmetric_difference_with) for - /// an efficient in-place version. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; - /// - /// let a = BitvSet::from_bitv(bitv::from_bytes([0b01101000])); - /// let b = BitvSet::from_bitv(bitv::from_bytes([0b10100000])); - /// - /// // Print 0, 1, 4 in arbitrary order - /// for x in a.symmetric_difference(&b) { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn symmetric_difference<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> { - TwoBitPositions { - set: self, - other: other, - merge: |w1, w2| w1 ^ w2, - current_word: 0u32, - next_idx: 0 - } - } - - /// Unions in-place with the specified other bit vector. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; - /// - /// let a = 0b01101000; - /// let b = 0b10100000; - /// let res = 0b11101000; - /// - /// let mut a = BitvSet::from_bitv(bitv::from_bytes([a])); - /// let b = BitvSet::from_bitv(bitv::from_bytes([b])); - /// let res = BitvSet::from_bitv(bitv::from_bytes([res])); - /// - /// a.union_with(&b); - /// assert_eq!(a, res); - /// ``` - #[inline] - pub fn union_with(&mut self, other: &BitvSet) { - self.other_op(other, |w1, w2| w1 | w2); - } - - /// Intersects in-place with the specified other bit vector. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; - /// - /// let a = 0b01101000; - /// let b = 0b10100000; - /// let res = 0b00100000; - /// - /// let mut a = BitvSet::from_bitv(bitv::from_bytes([a])); - /// let b = BitvSet::from_bitv(bitv::from_bytes([b])); - /// let res = BitvSet::from_bitv(bitv::from_bytes([res])); - /// - /// a.intersect_with(&b); - /// assert_eq!(a, res); - /// ``` - #[inline] - pub fn intersect_with(&mut self, other: &BitvSet) { - self.other_op(other, |w1, w2| w1 & w2); - } - - /// Makes this bit vector the difference with the specified other bit vector - /// in-place. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; - /// - /// let a = 0b01101000; - /// let b = 0b10100000; - /// let a_b = 0b01001000; // a - b - /// let b_a = 0b10000000; // b - a - /// - /// let mut bva = BitvSet::from_bitv(bitv::from_bytes([a])); - /// let bvb = BitvSet::from_bitv(bitv::from_bytes([b])); - /// let bva_b = BitvSet::from_bitv(bitv::from_bytes([a_b])); - /// let bvb_a = BitvSet::from_bitv(bitv::from_bytes([b_a])); - /// - /// bva.difference_with(&bvb); - /// assert_eq!(bva, bva_b); - /// - /// let bva = BitvSet::from_bitv(bitv::from_bytes([a])); - /// let mut bvb = BitvSet::from_bitv(bitv::from_bytes([b])); - /// - /// bvb.difference_with(&bva); - /// assert_eq!(bvb, bvb_a); - /// ``` - #[inline] - pub fn difference_with(&mut self, other: &BitvSet) { - self.other_op(other, |w1, w2| w1 & !w2); - } - - /// Makes this bit vector the symmetric difference with the specified other - /// bit vector in-place. - /// - /// # Example - /// - /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; - /// - /// let a = 0b01101000; - /// let b = 0b10100000; - /// let res = 0b11001000; - /// - /// let mut a = BitvSet::from_bitv(bitv::from_bytes([a])); - /// let b = BitvSet::from_bitv(bitv::from_bytes([b])); - /// let res = BitvSet::from_bitv(bitv::from_bytes([res])); - /// - /// a.symmetric_difference_with(&b); - /// assert_eq!(a, res); - /// ``` - #[inline] - pub fn symmetric_difference_with(&mut self, other: &BitvSet) { - self.other_op(other, |w1, w2| w1 ^ w2); - } - - /// Return the number of set bits in this set. - #[inline] - pub fn len(&self) -> uint { - let &BitvSet(ref bitv) = self; - bitv.storage.iter().fold(0, |acc, &n| acc + n.count_ones()) - } - - /// Returns whether there are no bits set in this set - #[inline] - pub fn is_empty(&self) -> bool { - let &BitvSet(ref bitv) = self; - bitv.storage.iter().all(|&n| n == 0) - } - - /// Clears all bits in this set - #[inline] - pub fn clear(&mut self) { - let &BitvSet(ref mut bitv) = self; - bitv.clear(); - } - - /// Returns `true` if this set contains the specified integer. - #[inline] - pub fn contains(&self, value: &uint) -> bool { - let &BitvSet(ref bitv) = self; - *value < bitv.nbits && bitv.get(*value) - } - - /// Returns `true` if the set has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - #[inline] - pub fn is_disjoint(&self, other: &BitvSet) -> bool { - self.intersection(other).next().is_none() - } - - /// Returns `true` if the set is a subset of another. - #[inline] - pub fn is_subset(&self, other: &BitvSet) -> bool { - let &BitvSet(ref self_bitv) = self; - let &BitvSet(ref other_bitv) = other; - - // Check that `self` intersect `other` is self - self_bitv.mask_words(0).zip(other_bitv.mask_words(0)) - .all(|((_, w1), (_, w2))| w1 & w2 == w1) && - // Check that `self` setminus `other` is empty - self_bitv.mask_words(other_bitv.storage.len()).all(|(_, w)| w == 0) - } - - /// Returns `true` if the set is a superset of another. - #[inline] - pub fn is_superset(&self, other: &BitvSet) -> bool { - other.is_subset(self) - } - - /// Adds a value to the set. Returns `true` if the value was not already - /// present in the set. - pub fn insert(&mut self, value: uint) -> bool { - if self.contains(&value) { - return false; - } - - // Ensure we have enough space to hold the new element - if value >= self.capacity() { - let new_cap = cmp::max(value + 1, self.capacity() * 2); - self.reserve(new_cap); - } - - let &BitvSet(ref mut bitv) = self; - bitv.set(value, true); - return true; - } - - /// Removes a value from the set. Returns `true` if the value was - /// present in the set. - pub fn remove(&mut self, value: &uint) -> bool { - if !self.contains(value) { - return false; - } - let &BitvSet(ref mut bitv) = self; - bitv.set(*value, false); - return true; - } -} - -impl fmt::Show for BitvSet { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - try!(write!(fmt, "{{")); - let mut first = true; - for n in self.iter() { - if !first { - try!(write!(fmt, ", ")); - } - try!(write!(fmt, "{}", n)); - first = false; - } - write!(fmt, "}}") - } -} - -impl hash::Hash for BitvSet { - fn hash(&self, state: &mut S) { - for pos in self.iter() { - pos.hash(state); - } - } -} - -/// An iterator for `BitvSet`. -pub struct BitPositions<'a> { - set: &'a BitvSet, - next_idx: uint -} - -/// An iterator combining two `BitvSet` iterators. -pub struct TwoBitPositions<'a> { - set: &'a BitvSet, - other: &'a BitvSet, - merge: |u32, u32|: 'a -> u32, - current_word: u32, - next_idx: uint -} - -impl<'a> Iterator for BitPositions<'a> { - fn next(&mut self) -> Option { - while self.next_idx < self.set.capacity() { - let idx = self.next_idx; - self.next_idx += 1; - - if self.set.contains(&idx) { - return Some(idx); - } - } - - return None; - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - (0, Some(self.set.capacity() - self.next_idx)) - } -} - -impl<'a> Iterator for TwoBitPositions<'a> { - fn next(&mut self) -> Option { - while self.next_idx < self.set.capacity() || - self.next_idx < self.other.capacity() { - let bit_idx = self.next_idx % u32::BITS; - if bit_idx == 0 { - let &BitvSet(ref s_bitv) = self.set; - let &BitvSet(ref o_bitv) = self.other; - // Merging the two words is a bit of an awkward dance since - // one Bitv might be longer than the other - let word_idx = self.next_idx / u32::BITS; - let w1 = if word_idx < s_bitv.storage.len() { - s_bitv.storage[word_idx] - } else { 0 }; - let w2 = if word_idx < o_bitv.storage.len() { - o_bitv.storage[word_idx] - } else { 0 }; - self.current_word = (self.merge)(w1, w2); - } - - self.next_idx += 1; - if self.current_word & (1 << bit_idx) != 0 { - return Some(self.next_idx - 1); - } - } - return None; - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let cap = cmp::max(self.set.capacity(), self.other.capacity()); - (0, Some(cap - self.next_idx)) - } -} - -#[cfg(test)] -mod tests { - use std::prelude::*; - use std::iter::range_step; - use std::u32; - use std::rand; - use std::rand::Rng; - use test::Bencher; - - use bitv::{Bitv, BitvSet, from_fn, from_bytes}; - use bitv; - use vec::Vec; - - static BENCH_BITS : uint = 1 << 14; - - #[test] - fn test_to_str() { - let zerolen = Bitv::new(); - assert_eq!(zerolen.to_string().as_slice(), ""); - - let eightbits = Bitv::with_capacity(8u, false); - assert_eq!(eightbits.to_string().as_slice(), "00000000") - } - - #[test] - fn test_0_elements() { - let act = Bitv::new(); - let exp = Vec::from_elem(0u, false); - assert!(act.eq_vec(exp.as_slice())); - } - - #[test] - fn test_1_element() { - let mut act = Bitv::with_capacity(1u, false); - assert!(act.eq_vec([false])); - act = Bitv::with_capacity(1u, true); - assert!(act.eq_vec([true])); - } - - #[test] - fn test_2_elements() { - let mut b = bitv::Bitv::with_capacity(2, false); - b.set(0, true); - b.set(1, false); - assert_eq!(b.to_string().as_slice(), "10"); - } - - #[test] - fn test_10_elements() { - let mut act; - // all 0 - - act = Bitv::with_capacity(10u, false); - assert!((act.eq_vec( - [false, false, false, false, false, false, false, false, false, false]))); - // all 1 - - act = Bitv::with_capacity(10u, true); - assert!((act.eq_vec([true, true, true, true, true, true, true, true, true, true]))); - // mixed - - act = Bitv::with_capacity(10u, false); - act.set(0u, true); - act.set(1u, true); - act.set(2u, true); - act.set(3u, true); - act.set(4u, true); - assert!((act.eq_vec([true, true, true, true, true, false, false, false, false, false]))); - // mixed - - act = Bitv::with_capacity(10u, false); - act.set(5u, true); - act.set(6u, true); - act.set(7u, true); - act.set(8u, true); - act.set(9u, true); - assert!((act.eq_vec([false, false, false, false, false, true, true, true, true, true]))); - // mixed - - act = Bitv::with_capacity(10u, false); - act.set(0u, true); - act.set(3u, true); - act.set(6u, true); - act.set(9u, true); - assert!((act.eq_vec([true, false, false, true, false, false, true, false, false, true]))); - } - - #[test] - fn test_31_elements() { - let mut act; - // all 0 - - act = Bitv::with_capacity(31u, false); - assert!(act.eq_vec( - [false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false])); - // all 1 - - act = Bitv::with_capacity(31u, true); - assert!(act.eq_vec( - [true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true])); - // mixed - - act = Bitv::with_capacity(31u, false); - act.set(0u, true); - act.set(1u, true); - act.set(2u, true); - act.set(3u, true); - act.set(4u, true); - act.set(5u, true); - act.set(6u, true); - act.set(7u, true); - assert!(act.eq_vec( - [true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false])); - // mixed - - act = Bitv::with_capacity(31u, false); - act.set(16u, true); - act.set(17u, true); - act.set(18u, true); - act.set(19u, true); - act.set(20u, true); - act.set(21u, true); - act.set(22u, true); - act.set(23u, true); - assert!(act.eq_vec( - [false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false])); - // mixed - - act = Bitv::with_capacity(31u, false); - act.set(24u, true); - act.set(25u, true); - act.set(26u, true); - act.set(27u, true); - act.set(28u, true); - act.set(29u, true); - act.set(30u, true); - assert!(act.eq_vec( - [false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, true, true, true, true, true, true, true])); - // mixed - - act = Bitv::with_capacity(31u, false); - act.set(3u, true); - act.set(17u, true); - act.set(30u, true); - assert!(act.eq_vec( - [false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true])); - } - - #[test] - fn test_32_elements() { - let mut act; - // all 0 - - act = Bitv::with_capacity(32u, false); - assert!(act.eq_vec( - [false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false])); - // all 1 - - act = Bitv::with_capacity(32u, true); - assert!(act.eq_vec( - [true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true])); - // mixed - - act = Bitv::with_capacity(32u, false); - act.set(0u, true); - act.set(1u, true); - act.set(2u, true); - act.set(3u, true); - act.set(4u, true); - act.set(5u, true); - act.set(6u, true); - act.set(7u, true); - assert!(act.eq_vec( - [true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false])); - // mixed - - act = Bitv::with_capacity(32u, false); - act.set(16u, true); - act.set(17u, true); - act.set(18u, true); - act.set(19u, true); - act.set(20u, true); - act.set(21u, true); - act.set(22u, true); - act.set(23u, true); - assert!(act.eq_vec( - [false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false, false])); - // mixed - - act = Bitv::with_capacity(32u, false); - act.set(24u, true); - act.set(25u, true); - act.set(26u, true); - act.set(27u, true); - act.set(28u, true); - act.set(29u, true); - act.set(30u, true); - act.set(31u, true); - assert!(act.eq_vec( - [false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, true, true, true, true, true, true, true, true])); - // mixed - - act = Bitv::with_capacity(32u, false); - act.set(3u, true); - act.set(17u, true); - act.set(30u, true); - act.set(31u, true); - assert!(act.eq_vec( - [false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true, true])); - } - - #[test] - fn test_33_elements() { - let mut act; - // all 0 - - act = Bitv::with_capacity(33u, false); - assert!(act.eq_vec( - [false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false])); - // all 1 - - act = Bitv::with_capacity(33u, true); - assert!(act.eq_vec( - [true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true, true, true, true, true, true, true, - true, true, true, true, true, true])); - // mixed - - act = Bitv::with_capacity(33u, false); - act.set(0u, true); - act.set(1u, true); - act.set(2u, true); - act.set(3u, true); - act.set(4u, true); - act.set(5u, true); - act.set(6u, true); - act.set(7u, true); - assert!(act.eq_vec( - [true, true, true, true, true, true, true, true, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false])); - // mixed - - act = Bitv::with_capacity(33u, false); - act.set(16u, true); - act.set(17u, true); - act.set(18u, true); - act.set(19u, true); - act.set(20u, true); - act.set(21u, true); - act.set(22u, true); - act.set(23u, true); - assert!(act.eq_vec( - [false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, true, true, true, true, true, true, true, - false, false, false, false, false, false, false, false, false])); - // mixed - - act = Bitv::with_capacity(33u, false); - act.set(24u, true); - act.set(25u, true); - act.set(26u, true); - act.set(27u, true); - act.set(28u, true); - act.set(29u, true); - act.set(30u, true); - act.set(31u, true); - assert!(act.eq_vec( - [false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, - false, true, true, true, true, true, true, true, true, false])); - // mixed - - act = Bitv::with_capacity(33u, false); - act.set(3u, true); - act.set(17u, true); - act.set(30u, true); - act.set(31u, true); - act.set(32u, true); - assert!(act.eq_vec( - [false, false, false, true, false, false, false, false, false, false, false, false, - false, false, false, false, false, true, false, false, false, false, false, false, - false, false, false, false, false, false, true, true, true])); - } - - #[test] - fn test_equal_differing_sizes() { - let v0 = Bitv::with_capacity(10u, false); - let v1 = Bitv::with_capacity(11u, false); - assert!(v0 != v1); - } - - #[test] - fn test_equal_greatly_differing_sizes() { - let v0 = Bitv::with_capacity(10u, false); - let v1 = Bitv::with_capacity(110u, false); - assert!(v0 != v1); - } - - #[test] - fn test_equal_sneaky_small() { - let mut a = bitv::Bitv::with_capacity(1, false); - a.set(0, true); - - let mut b = bitv::Bitv::with_capacity(1, true); - b.set(0, true); - - assert_eq!(a, b); - } - - #[test] - fn test_equal_sneaky_big() { - let mut a = bitv::Bitv::with_capacity(100, false); - for i in range(0u, 100) { - a.set(i, true); - } - - let mut b = bitv::Bitv::with_capacity(100, true); - for i in range(0u, 100) { - b.set(i, true); - } - - assert_eq!(a, b); - } - - #[test] - fn test_from_bytes() { - let bitv = from_bytes([0b10110110, 0b00000000, 0b11111111]); - let str = format!("{}{}{}", "10110110", "00000000", "11111111"); - assert_eq!(bitv.to_string().as_slice(), str.as_slice()); - } - - #[test] - fn test_to_bytes() { - let mut bv = Bitv::with_capacity(3, true); - bv.set(1, false); - assert_eq!(bv.to_bytes(), vec!(0b10100000)); - - let mut bv = Bitv::with_capacity(9, false); - bv.set(2, true); - bv.set(8, true); - assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000)); - } - - #[test] - fn test_from_bools() { - let bools = vec![true, false, true, true]; - let bitv: Bitv = bools.iter().map(|n| *n).collect(); - assert_eq!(bitv.to_string().as_slice(), "1011"); - } - - #[test] - fn test_bitv_set_from_bools() { - let bools = vec![true, false, true, true]; - let a: BitvSet = bools.iter().map(|n| *n).collect(); - let mut b = BitvSet::new(); - b.insert(0); - b.insert(2); - b.insert(3); - assert_eq!(a, b); - } - - #[test] - fn test_to_bools() { - let bools = vec!(false, false, true, false, false, true, true, false); - assert_eq!(from_bytes([0b00100110]).iter().collect::>(), bools); - } - - #[test] - fn test_bitv_iterator() { - let bools = vec![true, false, true, true]; - let bitv: Bitv = bools.iter().map(|n| *n).collect(); - - assert_eq!(bitv.iter().collect::>(), bools) - - let long = Vec::from_fn(10000, |i| i % 2 == 0); - let bitv: Bitv = long.iter().map(|n| *n).collect(); - assert_eq!(bitv.iter().collect::>(), long) - } - - #[test] - fn test_bitv_set_iterator() { - let bools = [true, false, true, true]; - let bitv: BitvSet = bools.iter().map(|n| *n).collect(); - - let idxs: Vec = bitv.iter().collect(); - assert_eq!(idxs, vec!(0, 2, 3)); - - let long: BitvSet = range(0u, 10000).map(|n| n % 2 == 0).collect(); - let real = range_step(0, 10000, 2).collect::>(); - - let idxs: Vec = long.iter().collect(); - assert_eq!(idxs, real); - } - - #[test] - fn test_bitv_set_frombitv_init() { - let bools = [true, false]; - let lengths = [10, 64, 100]; - for &b in bools.iter() { - for &l in lengths.iter() { - let bitset = BitvSet::from_bitv(Bitv::with_capacity(l, b)); - assert_eq!(bitset.contains(&1u), b) - assert_eq!(bitset.contains(&(l-1u)), b) - assert!(!bitset.contains(&l)) - } - } - } - - #[test] - fn test_small_difference() { - let mut b1 = Bitv::with_capacity(3, false); - let mut b2 = Bitv::with_capacity(3, false); - b1.set(0, true); - b1.set(1, true); - b2.set(1, true); - b2.set(2, true); - assert!(b1.difference(&b2)); - assert!(b1.get(0)); - assert!(!b1.get(1)); - assert!(!b1.get(2)); - } - - #[test] - fn test_big_difference() { - let mut b1 = Bitv::with_capacity(100, false); - let mut b2 = Bitv::with_capacity(100, false); - b1.set(0, true); - b1.set(40, true); - b2.set(40, true); - b2.set(80, true); - assert!(b1.difference(&b2)); - assert!(b1.get(0)); - assert!(!b1.get(40)); - assert!(!b1.get(80)); - } - - #[test] - fn test_small_clear() { - let mut b = Bitv::with_capacity(14, true); - b.clear(); - assert!(b.none()); - } - - #[test] - fn test_big_clear() { - let mut b = Bitv::with_capacity(140, true); - b.clear(); - assert!(b.none()); - } - - #[test] - fn test_bitv_masking() { - let b = Bitv::with_capacity(140, true); - let mut bs = BitvSet::from_bitv(b); - assert!(bs.contains(&139)); - assert!(!bs.contains(&140)); - assert!(bs.insert(150)); - assert!(!bs.contains(&140)); - assert!(!bs.contains(&149)); - assert!(bs.contains(&150)); - assert!(!bs.contains(&151)); - } - - #[test] - fn test_bitv_set_basic() { - // calculate nbits with u32::BITS granularity - fn calc_nbits(bits: uint) -> uint { - u32::BITS * ((bits + u32::BITS - 1) / u32::BITS) - } - - let mut b = BitvSet::new(); - assert_eq!(b.capacity(), calc_nbits(0)); - assert!(b.insert(3)); - assert_eq!(b.capacity(), calc_nbits(3)); - assert!(!b.insert(3)); - assert!(b.contains(&3)); - assert!(b.insert(4)); - assert!(!b.insert(4)); - assert!(b.contains(&3)); - assert!(b.insert(400)); - assert_eq!(b.capacity(), calc_nbits(400)); - assert!(!b.insert(400)); - assert!(b.contains(&400)); - assert_eq!(b.len(), 3); - } - - #[test] - fn test_bitv_set_intersection() { - let mut a = BitvSet::new(); - let mut b = BitvSet::new(); - - assert!(a.insert(11)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let expected = [3, 5, 11, 77]; - let actual = a.intersection(&b).collect::>(); - assert_eq!(actual.as_slice(), expected.as_slice()); - } - - #[test] - fn test_bitv_set_difference() { - let mut a = BitvSet::new(); - let mut b = BitvSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(200)); - assert!(a.insert(500)); - - assert!(b.insert(3)); - assert!(b.insert(200)); - - let expected = [1, 5, 500]; - let actual = a.difference(&b).collect::>(); - assert_eq!(actual.as_slice(), expected.as_slice()); - } - - #[test] - fn test_bitv_set_symmetric_difference() { - let mut a = BitvSet::new(); - let mut b = BitvSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(220)); - - let expected = [1, 5, 11, 14, 220]; - let actual = a.symmetric_difference(&b).collect::>(); - assert_eq!(actual.as_slice(), expected.as_slice()); - } - - #[test] - fn test_bitv_set_union() { - let mut a = BitvSet::new(); - let mut b = BitvSet::new(); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(160)); - assert!(a.insert(19)); - assert!(a.insert(24)); - assert!(a.insert(200)); - - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160, 200]; - let actual = a.union(&b).collect::>(); - assert_eq!(actual.as_slice(), expected.as_slice()); - } - - #[test] - fn test_bitv_set_subset() { - let mut set1 = BitvSet::new(); - let mut set2 = BitvSet::new(); - - assert!(set1.is_subset(&set2)); // {} {} - set2.insert(100); - assert!(set1.is_subset(&set2)); // {} { 1 } - set2.insert(200); - assert!(set1.is_subset(&set2)); // {} { 1, 2 } - set1.insert(200); - assert!(set1.is_subset(&set2)); // { 2 } { 1, 2 } - set1.insert(300); - assert!(!set1.is_subset(&set2)); // { 2, 3 } { 1, 2 } - set2.insert(300); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3 } - set2.insert(400); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 1, 2, 3, 4 } - set2.remove(&100); - assert!(set1.is_subset(&set2)); // { 2, 3 } { 2, 3, 4 } - set2.remove(&300); - assert!(!set1.is_subset(&set2)); // { 2, 3 } { 2, 4 } - set1.remove(&300); - assert!(set1.is_subset(&set2)); // { 2 } { 2, 4 } - } - - #[test] - fn test_bitv_set_is_disjoint() { - let a = BitvSet::from_bitv(from_bytes([0b10100010])); - let b = BitvSet::from_bitv(from_bytes([0b01000000])); - let c = BitvSet::new(); - let d = BitvSet::from_bitv(from_bytes([0b00110000])); - - assert!(!a.is_disjoint(&d)); - assert!(!d.is_disjoint(&a)); - - assert!(a.is_disjoint(&b)) - assert!(a.is_disjoint(&c)) - assert!(b.is_disjoint(&a)) - assert!(b.is_disjoint(&c)) - assert!(c.is_disjoint(&a)) - assert!(c.is_disjoint(&b)) - } - - #[test] - fn test_bitv_set_union_with() { - //a should grow to include larger elements - let mut a = BitvSet::new(); - a.insert(0); - let mut b = BitvSet::new(); - b.insert(5); - let expected = BitvSet::from_bitv(from_bytes([0b10000100])); - a.union_with(&b); - assert_eq!(a, expected); - - // Standard - let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); - let mut b = BitvSet::from_bitv(from_bytes([0b01100010])); - let c = a.clone(); - a.union_with(&b); - b.union_with(&c); - assert_eq!(a.len(), 4); - assert_eq!(b.len(), 4); - } - - #[test] - fn test_bitv_set_intersect_with() { - // Explicitly 0'ed bits - let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); - let mut b = BitvSet::from_bitv(from_bytes([0b00000000])); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert!(a.is_empty()); - assert!(b.is_empty()); - - // Uninitialized bits should behave like 0's - let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); - let mut b = BitvSet::new(); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert!(a.is_empty()); - assert!(b.is_empty()); - - // Standard - let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); - let mut b = BitvSet::from_bitv(from_bytes([0b01100010])); - let c = a.clone(); - a.intersect_with(&b); - b.intersect_with(&c); - assert_eq!(a.len(), 2); - assert_eq!(b.len(), 2); - } - - #[test] - fn test_bitv_set_difference_with() { - // Explicitly 0'ed bits - let mut a = BitvSet::from_bitv(from_bytes([0b00000000])); - let b = BitvSet::from_bitv(from_bytes([0b10100010])); - a.difference_with(&b); - assert!(a.is_empty()); - - // Uninitialized bits should behave like 0's - let mut a = BitvSet::new(); - let b = BitvSet::from_bitv(from_bytes([0b11111111])); - a.difference_with(&b); - assert!(a.is_empty()); - - // Standard - let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); - let mut b = BitvSet::from_bitv(from_bytes([0b01100010])); - let c = a.clone(); - a.difference_with(&b); - b.difference_with(&c); - assert_eq!(a.len(), 1); - assert_eq!(b.len(), 1); - } - - #[test] - fn test_bitv_set_symmetric_difference_with() { - //a should grow to include larger elements - let mut a = BitvSet::new(); - a.insert(0); - a.insert(1); - let mut b = BitvSet::new(); - b.insert(1); - b.insert(5); - let expected = BitvSet::from_bitv(from_bytes([0b10000100])); - a.symmetric_difference_with(&b); - assert_eq!(a, expected); - - let mut a = BitvSet::from_bitv(from_bytes([0b10100010])); - let b = BitvSet::new(); - let c = a.clone(); - a.symmetric_difference_with(&b); - assert_eq!(a, c); - - // Standard - let mut a = BitvSet::from_bitv(from_bytes([0b11100010])); - let mut b = BitvSet::from_bitv(from_bytes([0b01101010])); - let c = a.clone(); - a.symmetric_difference_with(&b); - b.symmetric_difference_with(&c); - assert_eq!(a.len(), 2); - assert_eq!(b.len(), 2); - } - - #[test] - fn test_bitv_set_eq() { - let a = BitvSet::from_bitv(from_bytes([0b10100010])); - let b = BitvSet::from_bitv(from_bytes([0b00000000])); - let c = BitvSet::new(); - - assert!(a == a); - assert!(a != b); - assert!(a != c); - assert!(b == b); - assert!(b == c); - assert!(c == c); - } - - #[test] - fn test_bitv_set_cmp() { - let a = BitvSet::from_bitv(from_bytes([0b10100010])); - let b = BitvSet::from_bitv(from_bytes([0b00000000])); - let c = BitvSet::new(); - - assert_eq!(a.cmp(&b), Greater); - assert_eq!(a.cmp(&c), Greater); - assert_eq!(b.cmp(&a), Less); - assert_eq!(b.cmp(&c), Equal); - assert_eq!(c.cmp(&a), Less); - assert_eq!(c.cmp(&b), Equal); - } - - #[test] - fn test_bitv_remove() { - let mut a = BitvSet::new(); - - assert!(a.insert(1)); - assert!(a.remove(&1)); - - assert!(a.insert(100)); - assert!(a.remove(&100)); - - assert!(a.insert(1000)); - assert!(a.remove(&1000)); - a.shrink_to_fit(); - assert_eq!(a.capacity(), u32::BITS); - } - - #[test] - fn test_bitv_lt() { - let mut a = Bitv::with_capacity(5u, false); - let mut b = Bitv::with_capacity(5u, false); - - assert!(!(a < b) && !(b < a)); - b.set(2, true); - assert!(a < b); - a.set(3, true); - assert!(a < b); - a.set(2, true); - assert!(!(a < b) && b < a); - b.set(0, true); - assert!(a < b); - } - - #[test] - fn test_ord() { - let mut a = Bitv::with_capacity(5u, false); - let mut b = Bitv::with_capacity(5u, false); - - assert!(a <= b && a >= b); - a.set(1, true); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - b.set(1, true); - b.set(2, true); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - #[test] - fn test_bitv_clone() { - let mut a = BitvSet::new(); - - assert!(a.insert(1)); - assert!(a.insert(100)); - assert!(a.insert(1000)); - - let mut b = a.clone(); - - assert!(a == b); - - assert!(b.remove(&1)); - assert!(a.contains(&1)); - - assert!(a.remove(&1000)); - assert!(b.contains(&1000)); - } - - #[test] - fn test_small_bitv_tests() { - let v = from_bytes([0]); - assert!(!v.all()); - assert!(!v.any()); - assert!(v.none()); - - let v = from_bytes([0b00010100]); - assert!(!v.all()); - assert!(v.any()); - assert!(!v.none()); - - let v = from_bytes([0xFF]); - assert!(v.all()); - assert!(v.any()); - assert!(!v.none()); - } - - #[test] - fn test_big_bitv_tests() { - let v = from_bytes([ // 88 bits - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0]); - assert!(!v.all()); - assert!(!v.any()); - assert!(v.none()); - - let v = from_bytes([ // 88 bits - 0, 0, 0b00010100, 0, - 0, 0, 0, 0b00110100, - 0, 0, 0]); - assert!(!v.all()); - assert!(v.any()); - assert!(!v.none()); - - let v = from_bytes([ // 88 bits - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF]); - assert!(v.all()); - assert!(v.any()); - assert!(!v.none()); - } - - #[test] - fn test_bitv_push_pop() { - let mut s = Bitv::with_capacity(5 * u32::BITS - 2, false); - assert_eq!(s.len(), 5 * u32::BITS - 2); - assert_eq!(s.get(5 * u32::BITS - 3), false); - s.push(true); - s.push(true); - assert_eq!(s.get(5 * u32::BITS - 2), true); - assert_eq!(s.get(5 * u32::BITS - 1), true); - // Here the internal vector will need to be extended - s.push(false); - assert_eq!(s.get(5 * u32::BITS), false); - s.push(false); - assert_eq!(s.get(5 * u32::BITS + 1), false); - assert_eq!(s.len(), 5 * u32::BITS + 2); - // Pop it all off - assert_eq!(s.pop(), false); - assert_eq!(s.pop(), false); - assert_eq!(s.pop(), true); - assert_eq!(s.pop(), true); - assert_eq!(s.len(), 5 * u32::BITS - 2); - } - - #[test] - fn test_bitv_truncate() { - let mut s = Bitv::with_capacity(5 * u32::BITS, true); - - assert_eq!(s, Bitv::with_capacity(5 * u32::BITS, true)); - assert_eq!(s.len(), 5 * u32::BITS); - s.truncate(4 * u32::BITS); - assert_eq!(s, Bitv::with_capacity(4 * u32::BITS, true)); - assert_eq!(s.len(), 4 * u32::BITS); - // Truncating to a size > s.len() should be a noop - s.truncate(5 * u32::BITS); - assert_eq!(s, Bitv::with_capacity(4 * u32::BITS, true)); - assert_eq!(s.len(), 4 * u32::BITS); - s.truncate(3 * u32::BITS - 10); - assert_eq!(s, Bitv::with_capacity(3 * u32::BITS - 10, true)); - assert_eq!(s.len(), 3 * u32::BITS - 10); - s.truncate(0); - assert_eq!(s, Bitv::with_capacity(0, true)); - assert_eq!(s.len(), 0); - } - - #[test] - fn test_bitv_reserve() { - let mut s = Bitv::with_capacity(5 * u32::BITS, true); - // Check capacity - assert_eq!(s.capacity(), 5 * u32::BITS); - s.reserve(2 * u32::BITS); - assert_eq!(s.capacity(), 5 * u32::BITS); - s.reserve(7 * u32::BITS); - assert_eq!(s.capacity(), 7 * u32::BITS); - s.reserve(7 * u32::BITS); - assert_eq!(s.capacity(), 7 * u32::BITS); - s.reserve(7 * u32::BITS + 1); - assert_eq!(s.capacity(), 8 * u32::BITS); - // Check that length hasn't changed - assert_eq!(s.len(), 5 * u32::BITS); - s.push(true); - s.push(false); - s.push(true); - assert_eq!(s.get(5 * u32::BITS - 1), true); - assert_eq!(s.get(5 * u32::BITS - 0), true); - assert_eq!(s.get(5 * u32::BITS + 1), false); - assert_eq!(s.get(5 * u32::BITS + 2), true); - } - - #[test] - fn test_bitv_grow() { - let mut bitv = from_bytes([0b10110110, 0b00000000, 0b10101010]); - bitv.grow(32, true); - assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF])); - bitv.grow(64, false); - assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0])); - bitv.grow(16, true); - assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b10101010, - 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF])); - } - - #[test] - fn test_bitv_extend() { - let mut bitv = from_bytes([0b10110110, 0b00000000, 0b11111111]); - let ext = from_bytes([0b01001001, 0b10010010, 0b10111101]); - bitv.extend(ext.iter()); - assert_eq!(bitv, from_bytes([0b10110110, 0b00000000, 0b11111111, - 0b01001001, 0b10010010, 0b10111101])); - } - - #[test] - fn test_bitv_set_show() { - let mut s = BitvSet::new(); - s.insert(1); - s.insert(10); - s.insert(50); - s.insert(2); - assert_eq!("{1, 2, 10, 50}".to_string(), s.to_string()); - } - - fn rng() -> rand::IsaacRng { - let seed: &[_] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; - rand::SeedableRng::from_seed(seed) - } - - #[bench] - fn bench_uint_small(b: &mut Bencher) { - let mut r = rng(); - let mut bitv = 0 as uint; - b.iter(|| { - for _ in range(0u, 100) { - bitv |= 1 << ((r.next_u32() as uint) % u32::BITS); - } - &bitv - }) - } - - #[bench] - fn bench_bitv_set_big_fixed(b: &mut Bencher) { - let mut r = rng(); - let mut bitv = Bitv::with_capacity(BENCH_BITS, false); - b.iter(|| { - for _ in range(0u, 100) { - bitv.set((r.next_u32() as uint) % BENCH_BITS, true); - } - &bitv - }) - } - - #[bench] - fn bench_bitv_set_big_variable(b: &mut Bencher) { - let mut r = rng(); - let mut bitv = Bitv::with_capacity(BENCH_BITS, false); - b.iter(|| { - for _ in range(0u, 100) { - bitv.set((r.next_u32() as uint) % BENCH_BITS, r.gen()); - } - &bitv - }) - } - - #[bench] - fn bench_bitv_set_small(b: &mut Bencher) { - let mut r = rng(); - let mut bitv = Bitv::with_capacity(u32::BITS, false); - b.iter(|| { - for _ in range(0u, 100) { - bitv.set((r.next_u32() as uint) % u32::BITS, true); - } - &bitv - }) - } - - #[bench] - fn bench_bitvset_small(b: &mut Bencher) { - let mut r = rng(); - let mut bitv = BitvSet::new(); - b.iter(|| { - for _ in range(0u, 100) { - bitv.insert((r.next_u32() as uint) % u32::BITS); - } - &bitv - }) - } - - #[bench] - fn bench_bitvset_big(b: &mut Bencher) { - let mut r = rng(); - let mut bitv = BitvSet::new(); - b.iter(|| { - for _ in range(0u, 100) { - bitv.insert((r.next_u32() as uint) % BENCH_BITS); - } - &bitv - }) - } - - #[bench] - fn bench_bitv_big_union(b: &mut Bencher) { - let mut b1 = Bitv::with_capacity(BENCH_BITS, false); - let b2 = Bitv::with_capacity(BENCH_BITS, false); - b.iter(|| { - b1.union(&b2) - }) - } - - #[bench] - fn bench_bitv_small_iter(b: &mut Bencher) { - let bitv = Bitv::with_capacity(u32::BITS, false); - b.iter(|| { - let mut sum = 0u; - for _ in range(0u, 10) { - for pres in bitv.iter() { - sum += pres as uint; - } - } - sum - }) - } - - #[bench] - fn bench_bitv_big_iter(b: &mut Bencher) { - let bitv = Bitv::with_capacity(BENCH_BITS, false); - b.iter(|| { - let mut sum = 0u; - for pres in bitv.iter() { - sum += pres as uint; - } - sum - }) - } - - #[bench] - fn bench_bitvset_iter(b: &mut Bencher) { - let bitv = BitvSet::from_bitv(from_fn(BENCH_BITS, - |idx| {idx % 3 == 0})); - b.iter(|| { - let mut sum = 0u; - for idx in bitv.iter() { - sum += idx as uint; - } - sum - }) - } -} diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 4570d49ba0a..e3dfabfa295 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -23,7 +23,7 @@ use core::default::Default; use core::{iter, fmt, mem}; use core::fmt::Show; -use ringbuf::RingBuf; +use ring_buf::RingBuf; /// A map based on a B-Tree. /// diff --git a/src/libcollections/btree/mod.rs b/src/libcollections/btree/mod.rs index 653de91c0ff..282128099da 100644 --- a/src/libcollections/btree/mod.rs +++ b/src/libcollections/btree/mod.rs @@ -8,27 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::map::BTreeMap; -pub use self::map::Entries; -pub use self::map::MutEntries; -pub use self::map::MoveEntries; -pub use self::map::Keys; -pub use self::map::Values; -pub use self::map::Entry; -pub use self::map::Occupied; -pub use self::map::Vacant; -pub use self::map::OccupiedEntry; -pub use self::map::VacantEntry; - -pub use self::set::BTreeSet; -pub use self::set::Items; -pub use self::set::MoveItems; -pub use self::set::DifferenceItems; -pub use self::set::UnionItems; -pub use self::set::SymDifferenceItems; -pub use self::set::IntersectionItems; - - mod node; -mod map; -mod set; +pub mod map; +pub mod set; diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index eac74098758..27752207b97 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -13,7 +13,7 @@ use core::prelude::*; -use super::{BTreeMap, Keys, MoveEntries}; +use btree_map::{BTreeMap, Keys, MoveEntries}; use std::hash::Hash; use core::default::Default; use core::{iter, fmt}; diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index b78c1897b06..bcae4fe68c9 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -155,7 +155,7 @@ mod test { use std::prelude::*; use std::mem; - use enum_set::{EnumSet, CLike}; + use super::{EnumSet, CLike}; #[deriving(PartialEq, Show)] #[repr(uint)] diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index e28bc766480..5ec8a85fb0f 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -37,34 +37,72 @@ extern crate alloc; #[cfg(test)] #[phase(plugin, link)] extern crate std; #[cfg(test)] #[phase(plugin, link)] extern crate log; -pub use bitv::{Bitv, BitvSet}; -pub use btree::{BTreeMap, BTreeSet}; + +pub use binary_heap::BinaryHeap; +pub use bitv::Bitv; +pub use bitv_set::BitvSet; +pub use btree_map::BTreeMap; +pub use btree_set::BTreeSet; pub use dlist::DList; pub use enum_set::EnumSet; -pub use priority_queue::PriorityQueue; -pub use ringbuf::RingBuf; -pub use smallintmap::SmallIntMap; +pub use ring_buf::RingBuf; pub use string::String; -pub use treemap::{TreeMap, TreeSet}; -pub use trie::{TrieMap, TrieSet}; +pub use tree_map::TreeMap; +pub use tree_set::TreeSet; +pub use trie_map::TrieMap; +pub use trie_set::TrieSet; pub use vec::Vec; +pub use vec_map::VecMap; mod macros; -pub mod bitv; -pub mod btree; +pub mod binary_heap; +mod bit; +mod btree; pub mod dlist; pub mod enum_set; -pub mod priority_queue; -pub mod ringbuf; -pub mod smallintmap; -pub mod treemap; -pub mod trie; +pub mod ring_buf; +mod tree; +mod trie; pub mod slice; pub mod str; pub mod string; pub mod vec; pub mod hash; +pub mod vec_map; + +pub mod bitv { + pub use bit::{Bitv, Bits, from_fn, from_bytes}; +} + +pub mod bitv_set { + pub use bit::{BitvSet, BitPositions, TwoBitPositions}; +} + +pub mod tree_map { + pub use tree::map::*; +} + +pub mod tree_set { + pub use tree::set::*; +} + +pub mod trie_map { + pub use trie::map::*; +} + +pub mod trie_set { + pub use trie::set::*; +} + +pub mod btree_map { + pub use btree::map::*; +} + +pub mod btree_set { + pub use btree::set::*; +} + #[cfg(test)] mod bench; diff --git a/src/libcollections/priority_queue.rs b/src/libcollections/priority_queue.rs deleted file mode 100644 index 885b5c99c45..00000000000 --- a/src/libcollections/priority_queue.rs +++ /dev/null @@ -1,698 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A priority queue implemented with a binary heap. -//! -//! Insertions have `O(log n)` time complexity and checking or popping the largest element is -//! `O(1)`. Converting a vector to a priority queue can be done in-place, and has `O(n)` -//! complexity. A priority queue can also be converted to a sorted vector in-place, allowing it to -//! be used for an `O(n log n)` in-place heapsort. -//! -//! # Example -//! -//! This is a larger example which implements [Dijkstra's algorithm][dijkstra] -//! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph]. -//! It showcases how to use the `PriorityQueue` with custom types. -//! -//! [dijkstra]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm -//! [sssp]: http://en.wikipedia.org/wiki/Shortest_path_problem -//! [dir_graph]: http://en.wikipedia.org/wiki/Directed_graph -//! -//! ``` -//! use std::collections::PriorityQueue; -//! use std::uint; -//! -//! #[deriving(Eq, PartialEq)] -//! struct State { -//! cost: uint, -//! position: uint -//! } -//! -//! // The priority queue depends on `Ord`. -//! // Explicitly implement the trait so the queue becomes a min-heap -//! // instead of a max-heap. -//! impl Ord for State { -//! fn cmp(&self, other: &State) -> Ordering { -//! // Notice that the we flip the ordering here -//! other.cost.cmp(&self.cost) -//! } -//! } -//! -//! // `PartialOrd` needs to be implemented as well. -//! impl PartialOrd for State { -//! fn partial_cmp(&self, other: &State) -> Option { -//! Some(self.cmp(other)) -//! } -//! } -//! -//! // Each node is represented as an `uint`, for a shorter implementation. -//! struct Edge { -//! node: uint, -//! cost: uint -//! } -//! -//! // Dijkstra's shortest path algorithm. -//! -//! // Start at `start` and use `dist` to track the current shortest distance -//! // to each node. This implementation isn't memory efficient as it may leave duplicate -//! // nodes in the queue. It also uses `uint::MAX` as a sentinel value, -//! // for a simpler implementation. -//! fn shortest_path(adj_list: &Vec>, start: uint, goal: uint) -> uint { -//! // dist[node] = current shortest distance from `start` to `node` -//! let mut dist = Vec::from_elem(adj_list.len(), uint::MAX); -//! -//! let mut pq = PriorityQueue::new(); -//! -//! // We're at `start`, with a zero cost -//! dist[start] = 0u; -//! pq.push(State { cost: 0u, position: start }); -//! -//! // Examine the frontier with lower cost nodes first (min-heap) -//! loop { -//! let State { cost, position } = match pq.pop() { -//! None => break, // empty -//! Some(s) => s -//! }; -//! -//! // Alternatively we could have continued to find all shortest paths -//! if position == goal { return cost } -//! -//! // Important as we may have already found a better way -//! if cost > dist[position] { continue } -//! -//! // For each node we can reach, see if we can find a way with -//! // a lower cost going through this node -//! for edge in adj_list[position].iter() { -//! let next = State { cost: cost + edge.cost, position: edge.node }; -//! -//! // If so, add it to the frontier and continue -//! if next.cost < dist[next.position] { -//! pq.push(next); -//! // Relaxation, we have now found a better way -//! dist[next.position] = next.cost; -//! } -//! } -//! } -//! -//! // Goal not reachable -//! uint::MAX -//! } -//! -//! fn main() { -//! // This is the directed graph we're going to use. -//! // The node numbers correspond to the different states, -//! // and the edge weights symbolises the cost of moving -//! // from one node to another. -//! // Note that the edges are one-way. -//! // -//! // 7 -//! // +-----------------+ -//! // | | -//! // v 1 2 | -//! // 0 -----> 1 -----> 3 ---> 4 -//! // | ^ ^ ^ -//! // | | 1 | | -//! // | | | 3 | 1 -//! // +------> 2 -------+ | -//! // 10 | | -//! // +---------------+ -//! // -//! // The graph is represented as an adjacency list where each index, -//! // corresponding to a node value, has a list of outgoing edges. -//! // Chosen for it's efficiency. -//! let graph = vec![ -//! // Node 0 -//! vec![Edge { node: 2, cost: 10 }, -//! Edge { node: 1, cost: 1 }], -//! // Node 1 -//! vec![Edge { node: 3, cost: 2 }], -//! // Node 2 -//! vec![Edge { node: 1, cost: 1 }, -//! Edge { node: 3, cost: 3 }, -//! Edge { node: 4, cost: 1 }], -//! // Node 3 -//! vec![Edge { node: 0, cost: 7 }, -//! Edge { node: 4, cost: 2 }], -//! // Node 4 -//! vec![]]; -//! -//! assert_eq!(shortest_path(&graph, 0, 1), 1); -//! assert_eq!(shortest_path(&graph, 0, 3), 3); -//! assert_eq!(shortest_path(&graph, 3, 0), 7); -//! assert_eq!(shortest_path(&graph, 0, 4), 5); -//! assert_eq!(shortest_path(&graph, 4, 0), uint::MAX); -//! } -//! ``` - -#![allow(missing_docs)] - -use core::prelude::*; - -use core::default::Default; -use core::mem::{zeroed, replace, swap}; -use core::ptr; - -use slice; -use vec::Vec; - -/// A priority queue implemented with a binary heap. -/// -/// This will be a max-heap. -#[deriving(Clone)] -pub struct PriorityQueue { - data: Vec, -} - -impl Default for PriorityQueue { - #[inline] - fn default() -> PriorityQueue { PriorityQueue::new() } -} - -impl PriorityQueue { - /// Creates an empty `PriorityQueue` as a max-heap. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// let pq: PriorityQueue = PriorityQueue::new(); - /// ``` - pub fn new() -> PriorityQueue { PriorityQueue{data: vec!(),} } - - /// Creates an empty `PriorityQueue` with a specific capacity. - /// This preallocates enough memory for `capacity` elements, - /// so that the `PriorityQueue` does not have to be reallocated - /// until it contains at least that many values. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// let pq: PriorityQueue = PriorityQueue::with_capacity(10u); - /// ``` - pub fn with_capacity(capacity: uint) -> PriorityQueue { - PriorityQueue { data: Vec::with_capacity(capacity) } - } - - /// Creates a `PriorityQueue` from a vector. This is sometimes called - /// `heapifying` the vector. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// let pq = PriorityQueue::from_vec(vec![9i, 1, 2, 7, 3, 2]); - /// ``` - pub fn from_vec(xs: Vec) -> PriorityQueue { - let mut q = PriorityQueue{data: xs,}; - let mut n = q.len() / 2; - while n > 0 { - n -= 1; - q.siftdown(n) - } - q - } - - /// An iterator visiting all values in underlying vector, in - /// arbitrary order. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// let pq = PriorityQueue::from_vec(vec![1i, 2, 3, 4]); - /// - /// // Print 1, 2, 3, 4 in arbitrary order - /// for x in pq.iter() { - /// println!("{}", x); - /// } - /// ``` - pub fn iter<'a>(&'a self) -> Items<'a, T> { - Items { iter: self.data.iter() } - } - - /// Returns the greatest item in a queue, or `None` if it is empty. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// - /// let mut pq = PriorityQueue::new(); - /// assert_eq!(pq.top(), None); - /// - /// pq.push(1i); - /// pq.push(5i); - /// pq.push(2i); - /// assert_eq!(pq.top(), Some(&5i)); - /// - /// ``` - pub fn top<'a>(&'a self) -> Option<&'a T> { - if self.is_empty() { None } else { Some(&self.data[0]) } - } - - /// Returns the number of elements the queue can hold without reallocating. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// - /// let pq: PriorityQueue = PriorityQueue::with_capacity(100u); - /// assert!(pq.capacity() >= 100u); - /// ``` - pub fn capacity(&self) -> uint { self.data.capacity() } - - /// Reserves capacity for exactly `n` elements in the `PriorityQueue`. - /// Do nothing if the capacity is already sufficient. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// - /// let mut pq: PriorityQueue = PriorityQueue::new(); - /// pq.reserve_exact(100u); - /// assert!(pq.capacity() == 100u); - /// ``` - pub fn reserve_exact(&mut self, n: uint) { self.data.reserve_exact(n) } - - /// Reserves capacity for at least `n` elements in the `PriorityQueue`. - /// Do nothing if the capacity is already sufficient. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// - /// let mut pq: PriorityQueue = PriorityQueue::new(); - /// pq.reserve(100u); - /// assert!(pq.capacity() >= 100u); - /// ``` - pub fn reserve(&mut self, n: uint) { - self.data.reserve(n) - } - - /// Removes the greatest item from a queue and returns it, or `None` if it - /// is empty. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// - /// let mut pq = PriorityQueue::from_vec(vec![1i, 3]); - /// - /// assert_eq!(pq.pop(), Some(3i)); - /// assert_eq!(pq.pop(), Some(1i)); - /// assert_eq!(pq.pop(), None); - /// ``` - pub fn pop(&mut self) -> Option { - match self.data.pop() { - None => { None } - Some(mut item) => { - if !self.is_empty() { - swap(&mut item, &mut self.data[0]); - self.siftdown(0); - } - Some(item) - } - } - } - - /// Pushes an item onto the queue. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// - /// let mut pq = PriorityQueue::new(); - /// pq.push(3i); - /// pq.push(5i); - /// pq.push(1i); - /// - /// assert_eq!(pq.len(), 3); - /// assert_eq!(pq.top(), Some(&5i)); - /// ``` - pub fn push(&mut self, item: T) { - self.data.push(item); - let new_len = self.len() - 1; - self.siftup(0, new_len); - } - - /// Pushes an item onto a queue then pops the greatest item off the queue in - /// an optimized fashion. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// - /// let mut pq = PriorityQueue::new(); - /// pq.push(1i); - /// pq.push(5i); - /// - /// assert_eq!(pq.push_pop(3i), 5); - /// assert_eq!(pq.push_pop(9i), 9); - /// assert_eq!(pq.len(), 2); - /// assert_eq!(pq.top(), Some(&3i)); - /// ``` - pub fn push_pop(&mut self, mut item: T) -> T { - if !self.is_empty() && *self.top().unwrap() > item { - swap(&mut item, &mut self.data[0]); - self.siftdown(0); - } - item - } - - /// Pops the greatest item off a queue then pushes an item onto the queue in - /// an optimized fashion. The push is done regardless of whether the queue - /// was empty. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// - /// let mut pq = PriorityQueue::new(); - /// - /// assert_eq!(pq.replace(1i), None); - /// assert_eq!(pq.replace(3i), Some(1i)); - /// assert_eq!(pq.len(), 1); - /// assert_eq!(pq.top(), Some(&3i)); - /// ``` - pub fn replace(&mut self, mut item: T) -> Option { - if !self.is_empty() { - swap(&mut item, &mut self.data[0]); - self.siftdown(0); - Some(item) - } else { - self.push(item); - None - } - } - - /// Consumes the `PriorityQueue` and returns the underlying vector - /// in arbitrary order. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// - /// let pq = PriorityQueue::from_vec(vec![1i, 2, 3, 4, 5, 6, 7]); - /// let vec = pq.into_vec(); - /// - /// // Will print in some order - /// for x in vec.iter() { - /// println!("{}", x); - /// } - /// ``` - pub fn into_vec(self) -> Vec { let PriorityQueue{data: v} = self; v } - - /// Consumes the `PriorityQueue` and returns a vector in sorted - /// (ascending) order. - /// - /// # Example - /// - /// ``` - /// use std::collections::PriorityQueue; - /// - /// let mut pq = PriorityQueue::from_vec(vec![1i, 2, 4, 5, 7]); - /// pq.push(6); - /// pq.push(3); - /// - /// let vec = pq.into_sorted_vec(); - /// assert_eq!(vec, vec![1i, 2, 3, 4, 5, 6, 7]); - /// ``` - pub fn into_sorted_vec(self) -> Vec { - let mut q = self; - let mut end = q.len(); - while end > 1 { - end -= 1; - q.data.as_mut_slice().swap(0, end); - q.siftdown_range(0, end) - } - q.into_vec() - } - - // The implementations of siftup and siftdown use unsafe blocks in - // order to move an element out of the vector (leaving behind a - // zeroed element), shift along the others and move it back into the - // vector over the junk element. This reduces the constant factor - // compared to using swaps, which involves twice as many moves. - fn siftup(&mut self, start: uint, mut pos: uint) { - unsafe { - let new = replace(&mut self.data[pos], zeroed()); - - while pos > start { - let parent = (pos - 1) >> 1; - if new > self.data[parent] { - let x = replace(&mut self.data[parent], zeroed()); - ptr::write(&mut self.data[pos], x); - pos = parent; - continue - } - break - } - ptr::write(&mut self.data[pos], new); - } - } - - fn siftdown_range(&mut self, mut pos: uint, end: uint) { - unsafe { - let start = pos; - let new = replace(&mut self.data[pos], zeroed()); - - let mut child = 2 * pos + 1; - while child < end { - let right = child + 1; - if right < end && !(self.data[child] > self.data[right]) { - child = right; - } - let x = replace(&mut self.data[child], zeroed()); - ptr::write(&mut self.data[pos], x); - pos = child; - child = 2 * pos + 1; - } - - ptr::write(&mut self.data[pos], new); - self.siftup(start, pos); - } - } - - fn siftdown(&mut self, pos: uint) { - let len = self.len(); - self.siftdown_range(pos, len); - } - - /// Returns the length of the queue. - pub fn len(&self) -> uint { self.data.len() } - - /// Returns true if the queue contains no elements - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Drops all items from the queue. - pub fn clear(&mut self) { self.data.truncate(0) } -} - -/// `PriorityQueue` iterator. -pub struct Items <'a, T:'a> { - iter: slice::Items<'a, T>, -} - -impl<'a, T> Iterator<&'a T> for Items<'a, T> { - #[inline] - fn next(&mut self) -> Option<(&'a T)> { self.iter.next() } - - #[inline] - fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } -} - -impl FromIterator for PriorityQueue { - fn from_iter>(mut iter: Iter) -> PriorityQueue { - let vec: Vec = iter.collect(); - PriorityQueue::from_vec(vec) - } -} - -impl Extendable for PriorityQueue { - fn extend>(&mut self, mut iter: Iter) { - let (lower, _) = iter.size_hint(); - - let len = self.capacity(); - self.reserve(len + lower); - - for elem in iter { - self.push(elem); - } - } -} - -#[cfg(test)] -mod tests { - use std::prelude::*; - - use priority_queue::PriorityQueue; - use vec::Vec; - - #[test] - fn test_iterator() { - let data = vec!(5i, 9, 3); - let iterout = [9i, 5, 3]; - let pq = PriorityQueue::from_vec(data); - let mut i = 0; - for el in pq.iter() { - assert_eq!(*el, iterout[i]); - i += 1; - } - } - - #[test] - fn test_top_and_pop() { - let data = vec!(2u, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1); - let mut sorted = data.clone(); - sorted.sort(); - let mut heap = PriorityQueue::from_vec(data); - while !heap.is_empty() { - assert_eq!(heap.top().unwrap(), sorted.last().unwrap()); - assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); - } - } - - #[test] - fn test_push() { - let mut heap = PriorityQueue::from_vec(vec!(2i, 4, 9)); - assert_eq!(heap.len(), 3); - assert!(*heap.top().unwrap() == 9); - heap.push(11); - assert_eq!(heap.len(), 4); - assert!(*heap.top().unwrap() == 11); - heap.push(5); - assert_eq!(heap.len(), 5); - assert!(*heap.top().unwrap() == 11); - heap.push(27); - assert_eq!(heap.len(), 6); - assert!(*heap.top().unwrap() == 27); - heap.push(3); - assert_eq!(heap.len(), 7); - assert!(*heap.top().unwrap() == 27); - heap.push(103); - assert_eq!(heap.len(), 8); - assert!(*heap.top().unwrap() == 103); - } - - #[test] - fn test_push_unique() { - let mut heap = PriorityQueue::from_vec(vec!(box 2i, box 4, box 9)); - assert_eq!(heap.len(), 3); - assert!(*heap.top().unwrap() == box 9); - heap.push(box 11); - assert_eq!(heap.len(), 4); - assert!(*heap.top().unwrap() == box 11); - heap.push(box 5); - assert_eq!(heap.len(), 5); - assert!(*heap.top().unwrap() == box 11); - heap.push(box 27); - assert_eq!(heap.len(), 6); - assert!(*heap.top().unwrap() == box 27); - heap.push(box 3); - assert_eq!(heap.len(), 7); - assert!(*heap.top().unwrap() == box 27); - heap.push(box 103); - assert_eq!(heap.len(), 8); - assert!(*heap.top().unwrap() == box 103); - } - - #[test] - fn test_push_pop() { - let mut heap = PriorityQueue::from_vec(vec!(5i, 5, 2, 1, 3)); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(6), 6); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(0), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(4), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.push_pop(1), 4); - assert_eq!(heap.len(), 5); - } - - #[test] - fn test_replace() { - let mut heap = PriorityQueue::from_vec(vec!(5i, 5, 2, 1, 3)); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(6).unwrap(), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(0).unwrap(), 6); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(4).unwrap(), 5); - assert_eq!(heap.len(), 5); - assert_eq!(heap.replace(1).unwrap(), 4); - assert_eq!(heap.len(), 5); - } - - fn check_to_vec(mut data: Vec) { - let heap = PriorityQueue::from_vec(data.clone()); - let mut v = heap.clone().into_vec(); - v.sort(); - data.sort(); - - assert_eq!(v.as_slice(), data.as_slice()); - assert_eq!(heap.into_sorted_vec().as_slice(), data.as_slice()); - } - - #[test] - fn test_to_vec() { - check_to_vec(vec!()); - check_to_vec(vec!(5i)); - check_to_vec(vec!(3i, 2)); - check_to_vec(vec!(2i, 3)); - check_to_vec(vec!(5i, 1, 2)); - check_to_vec(vec!(1i, 100, 2, 3)); - check_to_vec(vec!(1i, 3, 5, 7, 9, 2, 4, 6, 8, 0)); - check_to_vec(vec!(2i, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1)); - check_to_vec(vec!(9i, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0)); - check_to_vec(vec!(0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); - check_to_vec(vec!(10i, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); - check_to_vec(vec!(0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2)); - check_to_vec(vec!(5i, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1)); - } - - #[test] - fn test_empty_pop() { - let mut heap: PriorityQueue = PriorityQueue::new(); - assert!(heap.pop().is_none()); - } - - #[test] - fn test_empty_top() { - let empty: PriorityQueue = PriorityQueue::new(); - assert!(empty.top().is_none()); - } - - #[test] - fn test_empty_replace() { - let mut heap: PriorityQueue = PriorityQueue::new(); - heap.replace(5).is_none(); - } - - #[test] - fn test_from_iter() { - let xs = vec!(9u, 8, 7, 6, 5, 4, 3, 2, 1); - - let mut q: PriorityQueue = xs.as_slice().iter().rev().map(|&x| x).collect(); - - for &x in xs.iter() { - assert_eq!(q.pop().unwrap(), x); - } - } -} diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs new file mode 100644 index 00000000000..3c4c3fce61d --- /dev/null +++ b/src/libcollections/ring_buf.rs @@ -0,0 +1,1152 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This crate implements a double-ended queue with `O(1)` amortized inserts and removals from both +//! ends of the container. It also has `O(1)` indexing like a vector. The contained elements are +//! not required to be copyable, and the queue will be sendable if the contained type is sendable. +//! Its interface `Deque` is defined in `collections`. + +use core::prelude::*; + +use core::cmp; +use core::default::Default; +use core::fmt; +use core::iter; +use core::slice; +use std::hash::{Writer, Hash}; + +use vec::Vec; + +static INITIAL_CAPACITY: uint = 8u; // 2^3 +static MINIMUM_CAPACITY: uint = 2u; + +/// `RingBuf` is a circular buffer that implements `Deque`. +#[deriving(Clone)] +pub struct RingBuf { + nelts: uint, + lo: uint, + elts: Vec> +} + +impl Default for RingBuf { + #[inline] + fn default() -> RingBuf { RingBuf::new() } +} + +impl RingBuf { + /// Creates an empty `RingBuf`. + pub fn new() -> RingBuf { + RingBuf::with_capacity(INITIAL_CAPACITY) + } + + /// Creates an empty `RingBuf` with space for at least `n` elements. + pub fn with_capacity(n: uint) -> RingBuf { + RingBuf{nelts: 0, lo: 0, + elts: Vec::from_fn(cmp::max(MINIMUM_CAPACITY, n), |_| None)} + } + + /// Retrieves an element in the `RingBuf` by index. + /// + /// Fails if there is no element with the given index. + /// + /// # Example + /// + /// ```rust + /// # #![allow(deprecated)] + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::new(); + /// buf.push(3i); + /// buf.push(4); + /// buf.push(5); + /// *buf.get_mut(1) = 7; + /// assert_eq!(buf[1], 7); + /// ``` + #[deprecated = "use indexing instead: `buf[index] = value`"] + pub fn get_mut(&mut self, i: uint) -> &mut T { + &mut self[i] + } + + /// Swaps elements at indices `i` and `j`. + /// + /// `i` and `j` may be equal. + /// + /// Fails if there is no element with either index. + /// + /// # Example + /// + /// ```rust + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::new(); + /// buf.push(3i); + /// buf.push(4); + /// buf.push(5); + /// buf.swap(0, 2); + /// assert_eq!(buf[0], 5); + /// assert_eq!(buf[2], 3); + /// ``` + pub fn swap(&mut self, i: uint, j: uint) { + assert!(i < self.len()); + assert!(j < self.len()); + let ri = self.raw_index(i); + let rj = self.raw_index(j); + self.elts.as_mut_slice().swap(ri, rj); + } + + /// Returns the index in the underlying `Vec` for a given logical element + /// index. + fn raw_index(&self, idx: uint) -> uint { + raw_index(self.lo, self.elts.len(), idx) + } + + /// Reserves capacity for exactly `n` elements in the given `RingBuf`, + /// doing nothing if `self`'s capacity is already equal to or greater + /// than the requested capacity. + pub fn reserve_exact(&mut self, n: uint) { + self.elts.reserve_exact(n); + } + + /// Reserves capacity for at least `n` elements in the given `RingBuf`, + /// over-allocating in case the caller needs to reserve additional + /// space. + /// + /// Do nothing if `self`'s capacity is already equal to or greater + /// than the requested capacity. + pub fn reserve(&mut self, n: uint) { + self.elts.reserve(n); + } + + /// Returns a front-to-back iterator. + /// + /// # Example + /// + /// ```rust + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::new(); + /// buf.push(5i); + /// buf.push(3); + /// buf.push(4); + /// let b: &[_] = &[&5, &3, &4]; + /// assert_eq!(buf.iter().collect::>().as_slice(), b); + /// ``` + pub fn iter(&self) -> Items { + Items{index: 0, rindex: self.nelts, lo: self.lo, elts: self.elts.as_slice()} + } + + /// Returns a front-to-back iterator which returns mutable references. + /// + /// # Example + /// + /// ```rust + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::new(); + /// buf.push(5i); + /// buf.push(3); + /// buf.push(4); + /// for num in buf.iter_mut() { + /// *num = *num - 2; + /// } + /// let b: &[_] = &[&mut 3, &mut 1, &mut 2]; + /// assert_eq!(buf.iter_mut().collect::>()[], b); + /// ``` + pub fn iter_mut(&mut self) -> MutItems { + let start_index = raw_index(self.lo, self.elts.len(), 0); + let end_index = raw_index(self.lo, self.elts.len(), self.nelts); + + // Divide up the array + if end_index <= start_index { + // Items to iterate goes from: + // start_index to self.elts.len() + // and then + // 0 to end_index + let (temp, remaining1) = self.elts.split_at_mut(start_index); + let (remaining2, _) = temp.split_at_mut(end_index); + MutItems { + remaining1: remaining1.iter_mut(), + remaining2: remaining2.iter_mut(), + nelts: self.nelts, + } + } else { + // Items to iterate goes from start_index to end_index: + let (empty, elts) = self.elts.split_at_mut(0); + let remaining1 = elts[mut start_index..end_index]; + MutItems { + remaining1: remaining1.iter_mut(), + remaining2: empty.iter_mut(), + nelts: self.nelts, + } + } + } + + /// Returns the number of elements in the `RingBuf`. + /// + /// # Example + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut v = RingBuf::new(); + /// assert_eq!(v.len(), 0); + /// v.push(1i); + /// assert_eq!(v.len(), 1); + /// ``` + pub fn len(&self) -> uint { self.nelts } + + /// Returns true if the buffer contains no elements + /// + /// # Example + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut v = RingBuf::new(); + /// assert!(v.is_empty()); + /// v.push_front(1i); + /// assert!(!v.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Clears the buffer, removing all values. + /// + /// # Example + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut v = RingBuf::new(); + /// v.push(1i); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + pub fn clear(&mut self) { + for x in self.elts.iter_mut() { *x = None } + self.nelts = 0; + self.lo = 0; + } + + /// Provides a reference to the front element, or `None` if the sequence is + /// empty. + /// + /// # Example + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut d = RingBuf::new(); + /// assert_eq!(d.front(), None); + /// + /// d.push(1i); + /// d.push(2i); + /// assert_eq!(d.front(), Some(&1i)); + /// ``` + pub fn front(&self) -> Option<&T> { + if self.nelts > 0 { Some(&self[0]) } else { None } + } + + /// Provides a mutable reference to the front element, or `None` if the + /// sequence is empty. + /// + /// # Example + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut d = RingBuf::new(); + /// assert_eq!(d.front_mut(), None); + /// + /// d.push(1i); + /// d.push(2i); + /// match d.front_mut() { + /// Some(x) => *x = 9i, + /// None => (), + /// } + /// assert_eq!(d.front(), Some(&9i)); + /// ``` + pub fn front_mut(&mut self) -> Option<&mut T> { + if self.nelts > 0 { Some(&mut self[0]) } else { None } + } + + /// Provides a reference to the back element, or `None` if the sequence is + /// empty. + /// + /// # Example + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut d = RingBuf::new(); + /// assert_eq!(d.back(), None); + /// + /// d.push(1i); + /// d.push(2i); + /// assert_eq!(d.back(), Some(&2i)); + /// ``` + pub fn back(&self) -> Option<&T> { + if self.nelts > 0 { Some(&self[self.nelts - 1]) } else { None } + } + + /// Provides a mutable reference to the back element, or `None` if the + /// sequence is empty. + /// + /// # Example + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut d = RingBuf::new(); + /// assert_eq!(d.back(), None); + /// + /// d.push(1i); + /// d.push(2i); + /// match d.back_mut() { + /// Some(x) => *x = 9i, + /// None => (), + /// } + /// assert_eq!(d.back(), Some(&9i)); + /// ``` + pub fn back_mut(&mut self) -> Option<&mut T> { + let nelts = self.nelts; + if nelts > 0 { Some(&mut self[nelts - 1]) } else { None } + } + + /// Removes the first element and returns it, or `None` if the sequence is + /// empty. + /// + /// # Example + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut d = RingBuf::new(); + /// d.push(1i); + /// d.push(2i); + /// + /// assert_eq!(d.pop_front(), Some(1i)); + /// assert_eq!(d.pop_front(), Some(2i)); + /// assert_eq!(d.pop_front(), None); + /// ``` + pub fn pop_front(&mut self) -> Option { + let result = self.elts[self.lo].take(); + if result.is_some() { + self.lo = (self.lo + 1u) % self.elts.len(); + self.nelts -= 1u; + } + result + } + + /// Inserts an element first in the sequence. + /// + /// # Example + /// + /// ``` + /// use std::collections::RingBuf; + /// + /// let mut d = RingBuf::new(); + /// d.push_front(1i); + /// d.push_front(2i); + /// assert_eq!(d.front(), Some(&2i)); + /// ``` + pub fn push_front(&mut self, t: T) { + if self.nelts == self.elts.len() { + grow(self.nelts, &mut self.lo, &mut self.elts); + } + if self.lo == 0u { + self.lo = self.elts.len() - 1u; + } else { self.lo -= 1u; } + self.elts[self.lo] = Some(t); + self.nelts += 1u; + } + + /// Appends an element to the back of a buffer + /// + /// # Example + /// + /// ```rust + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::new(); + /// buf.push(1i); + /// buf.push(3); + /// assert_eq!(3, *buf.back().unwrap()); + /// ``` + pub fn push(&mut self, t: T) { + if self.nelts == self.elts.len() { + grow(self.nelts, &mut self.lo, &mut self.elts); + } + let hi = self.raw_index(self.nelts); + self.elts[hi] = Some(t); + self.nelts += 1u; + } + + /// Removes the last element from a buffer and returns it, or `None` if + /// it is empty. + /// + /// # Example + /// + /// ```rust + /// use std::collections::RingBuf; + /// + /// let mut buf = RingBuf::new(); + /// assert_eq!(buf.pop(), None); + /// buf.push(1i); + /// buf.push(3); + /// assert_eq!(buf.pop(), Some(3)); + /// ``` + pub fn pop(&mut self) -> Option { + if self.nelts > 0 { + self.nelts -= 1; + let hi = self.raw_index(self.nelts); + self.elts[hi].take() + } else { + None + } + } +} + +/// `RingBuf` iterator. +pub struct Items<'a, T:'a> { + lo: uint, + index: uint, + rindex: uint, + elts: &'a [Option], +} + +impl<'a, T> Iterator<&'a T> for Items<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a T> { + if self.index == self.rindex { + return None; + } + let raw_index = raw_index(self.lo, self.elts.len(), self.index); + self.index += 1; + Some(self.elts[raw_index].as_ref().unwrap()) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let len = self.rindex - self.index; + (len, Some(len)) + } +} + +impl<'a, T> DoubleEndedIterator<&'a T> for Items<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a T> { + if self.index == self.rindex { + return None; + } + self.rindex -= 1; + let raw_index = raw_index(self.lo, self.elts.len(), self.rindex); + Some(self.elts[raw_index].as_ref().unwrap()) + } +} + +impl<'a, T> ExactSize<&'a T> for Items<'a, T> {} + +impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> { + #[inline] + fn indexable(&self) -> uint { self.rindex - self.index } + + #[inline] + fn idx(&mut self, j: uint) -> Option<&'a T> { + if j >= self.indexable() { + None + } else { + let raw_index = raw_index(self.lo, self.elts.len(), self.index + j); + Some(self.elts[raw_index].as_ref().unwrap()) + } + } +} + +/// `RingBuf` mutable iterator. +pub struct MutItems<'a, T:'a> { + remaining1: slice::MutItems<'a, Option>, + remaining2: slice::MutItems<'a, Option>, + nelts: uint, +} + +impl<'a, T> Iterator<&'a mut T> for MutItems<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a mut T> { + if self.nelts == 0 { + return None; + } + self.nelts -= 1; + match self.remaining1.next() { + Some(ptr) => return Some(ptr.as_mut().unwrap()), + None => {} + } + match self.remaining2.next() { + Some(ptr) => return Some(ptr.as_mut().unwrap()), + None => unreachable!(), + } + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + (self.nelts, Some(self.nelts)) + } +} + +impl<'a, T> DoubleEndedIterator<&'a mut T> for MutItems<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<&'a mut T> { + if self.nelts == 0 { + return None; + } + self.nelts -= 1; + match self.remaining2.next_back() { + Some(ptr) => return Some(ptr.as_mut().unwrap()), + None => {} + } + match self.remaining1.next_back() { + Some(ptr) => return Some(ptr.as_mut().unwrap()), + None => unreachable!(), + } + } +} + +impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {} + +/// Grow is only called on full elts, so nelts is also len(elts), unlike +/// elsewhere. +fn grow(nelts: uint, loptr: &mut uint, elts: &mut Vec>) { + assert_eq!(nelts, elts.len()); + let lo = *loptr; + elts.reserve(nelts * 2); + let newlen = elts.capacity(); + + /* fill with None */ + for _ in range(elts.len(), newlen) { + elts.push(None); + } + + /* + Move the shortest half into the newly reserved area. + lo ---->| + nelts ----------->| + [o o o|o o o o o] + A [. . .|o o o o o o o o|. . . . .] + B [o o o|. . . . . . . .|o o o o o] + */ + + assert!(newlen - nelts/2 >= nelts); + if lo <= (nelts - lo) { // A + for i in range(0u, lo) { + elts.as_mut_slice().swap(i, nelts + i); + } + } else { // B + for i in range(lo, nelts) { + elts.as_mut_slice().swap(i, newlen - nelts + i); + } + *loptr += newlen - nelts; + } +} + +/// Returns the index in the underlying `Vec` for a given logical element index. +fn raw_index(lo: uint, len: uint, index: uint) -> uint { + if lo >= len - index { + lo + index - len + } else { + lo + index + } +} + +impl PartialEq for RingBuf { + fn eq(&self, other: &RingBuf) -> bool { + self.nelts == other.nelts && + self.iter().zip(other.iter()).all(|(a, b)| a.eq(b)) + } + fn ne(&self, other: &RingBuf) -> bool { + !self.eq(other) + } +} + +impl Eq for RingBuf {} + +impl PartialOrd for RingBuf { + fn partial_cmp(&self, other: &RingBuf) -> Option { + iter::order::partial_cmp(self.iter(), other.iter()) + } +} + +impl Ord for RingBuf { + #[inline] + fn cmp(&self, other: &RingBuf) -> Ordering { + iter::order::cmp(self.iter(), other.iter()) + } +} + +impl> Hash for RingBuf { + fn hash(&self, state: &mut S) { + self.len().hash(state); + for elt in self.iter() { + elt.hash(state); + } + } +} + +impl Index for RingBuf { + #[inline] + fn index<'a>(&'a self, i: &uint) -> &'a A { + let idx = self.raw_index(*i); + match self.elts[idx] { + None => panic!(), + Some(ref v) => v, + } + } +} + +impl IndexMut for RingBuf { + #[inline] + fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut A { + let idx = self.raw_index(*i); + match *(&mut self.elts[idx]) { + None => panic!(), + Some(ref mut v) => v + } + } +} + +impl FromIterator for RingBuf { + fn from_iter>(iterator: T) -> RingBuf { + let (lower, _) = iterator.size_hint(); + let mut deq = RingBuf::with_capacity(lower); + deq.extend(iterator); + deq + } +} + +impl Extendable for RingBuf { + fn extend>(&mut self, mut iterator: T) { + for elt in iterator { + self.push(elt); + } + } +} + +impl fmt::Show for RingBuf { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "[")); + + for (i, e) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}", *e)); + } + + write!(f, "]") + } +} + +#[cfg(test)] +mod tests { + use std::fmt::Show; + use std::prelude::*; + use std::hash; + use test::Bencher; + use test; + + use super::RingBuf; + use vec::Vec; + + #[test] + #[allow(deprecated)] + fn test_simple() { + let mut d = RingBuf::new(); + assert_eq!(d.len(), 0u); + d.push_front(17i); + d.push_front(42i); + d.push(137); + assert_eq!(d.len(), 3u); + d.push(137); + assert_eq!(d.len(), 4u); + debug!("{}", d.front()); + assert_eq!(*d.front().unwrap(), 42); + debug!("{}", d.back()); + assert_eq!(*d.back().unwrap(), 137); + let mut i = d.pop_front(); + debug!("{}", i); + assert_eq!(i, Some(42)); + i = d.pop(); + debug!("{}", i); + assert_eq!(i, Some(137)); + i = d.pop(); + debug!("{}", i); + assert_eq!(i, Some(137)); + i = d.pop(); + debug!("{}", i); + assert_eq!(i, Some(17)); + assert_eq!(d.len(), 0u); + d.push(3); + assert_eq!(d.len(), 1u); + d.push_front(2); + assert_eq!(d.len(), 2u); + d.push(4); + assert_eq!(d.len(), 3u); + d.push_front(1); + assert_eq!(d.len(), 4u); + debug!("{}", d[0]); + debug!("{}", d[1]); + debug!("{}", d[2]); + debug!("{}", d[3]); + assert_eq!(d[0], 1); + assert_eq!(d[1], 2); + assert_eq!(d[2], 3); + assert_eq!(d[3], 4); + } + + #[cfg(test)] + fn test_parameterized(a: T, b: T, c: T, d: T) { + let mut deq = RingBuf::new(); + assert_eq!(deq.len(), 0); + deq.push_front(a.clone()); + deq.push_front(b.clone()); + deq.push(c.clone()); + assert_eq!(deq.len(), 3); + deq.push(d.clone()); + assert_eq!(deq.len(), 4); + assert_eq!((*deq.front().unwrap()).clone(), b.clone()); + assert_eq!((*deq.back().unwrap()).clone(), d.clone()); + assert_eq!(deq.pop_front().unwrap(), b.clone()); + assert_eq!(deq.pop().unwrap(), d.clone()); + assert_eq!(deq.pop().unwrap(), c.clone()); + assert_eq!(deq.pop().unwrap(), a.clone()); + assert_eq!(deq.len(), 0); + deq.push(c.clone()); + assert_eq!(deq.len(), 1); + deq.push_front(b.clone()); + assert_eq!(deq.len(), 2); + deq.push(d.clone()); + assert_eq!(deq.len(), 3); + deq.push_front(a.clone()); + assert_eq!(deq.len(), 4); + assert_eq!(deq[0].clone(), a.clone()); + assert_eq!(deq[1].clone(), b.clone()); + assert_eq!(deq[2].clone(), c.clone()); + assert_eq!(deq[3].clone(), d.clone()); + } + + #[test] + fn test_push_front_grow() { + let mut deq = RingBuf::new(); + for i in range(0u, 66) { + deq.push_front(i); + } + assert_eq!(deq.len(), 66); + + for i in range(0u, 66) { + assert_eq!(deq[i], 65 - i); + } + + let mut deq = RingBuf::new(); + for i in range(0u, 66) { + deq.push(i); + } + + for i in range(0u, 66) { + assert_eq!(deq[i], i); + } + } + + #[test] + fn test_index() { + let mut deq = RingBuf::new(); + for i in range(1u, 4) { + deq.push_front(i); + } + assert_eq!(deq[1], 2); + } + + #[test] + #[should_fail] + fn test_index_out_of_bounds() { + let mut deq = RingBuf::new(); + for i in range(1u, 4) { + deq.push_front(i); + } + deq[3]; + } + + #[bench] + fn bench_new(b: &mut test::Bencher) { + b.iter(|| { + let _: RingBuf = RingBuf::new(); + }) + } + + #[bench] + fn bench_push_back(b: &mut test::Bencher) { + let mut deq = RingBuf::new(); + b.iter(|| { + deq.push(0i); + }) + } + + #[bench] + fn bench_push_front(b: &mut test::Bencher) { + let mut deq = RingBuf::new(); + b.iter(|| { + deq.push_front(0i); + }) + } + + #[bench] + fn bench_grow(b: &mut test::Bencher) { + let mut deq = RingBuf::new(); + b.iter(|| { + for _ in range(0i, 65) { + deq.push_front(1i); + } + }) + } + + #[deriving(Clone, PartialEq, Show)] + enum Taggy { + One(int), + Two(int, int), + Three(int, int, int), + } + + #[deriving(Clone, PartialEq, Show)] + enum Taggypar { + Onepar(int), + Twopar(int, int), + Threepar(int, int, int), + } + + #[deriving(Clone, PartialEq, Show)] + struct RecCy { + x: int, + y: int, + t: Taggy + } + + #[test] + fn test_param_int() { + test_parameterized::(5, 72, 64, 175); + } + + #[test] + fn test_param_taggy() { + test_parameterized::(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); + } + + #[test] + fn test_param_taggypar() { + test_parameterized::>(Onepar::(1), + Twopar::(1, 2), + Threepar::(1, 2, 3), + Twopar::(17, 42)); + } + + #[test] + fn test_param_reccy() { + let reccy1 = RecCy { x: 1, y: 2, t: One(1) }; + let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) }; + let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) }; + let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) }; + test_parameterized::(reccy1, reccy2, reccy3, reccy4); + } + + #[test] + fn test_with_capacity() { + let mut d = RingBuf::with_capacity(0); + d.push(1i); + assert_eq!(d.len(), 1); + let mut d = RingBuf::with_capacity(50); + d.push(1i); + assert_eq!(d.len(), 1); + } + + #[test] + fn test_with_capacity_non_power_two() { + let mut d3 = RingBuf::with_capacity(3); + d3.push(1i); + + // X = None, | = lo + // [|1, X, X] + assert_eq!(d3.pop_front(), Some(1)); + // [X, |X, X] + assert_eq!(d3.front(), None); + + // [X, |3, X] + d3.push(3); + // [X, |3, 6] + d3.push(6); + // [X, X, |6] + assert_eq!(d3.pop_front(), Some(3)); + + // Pushing the lo past half way point to trigger + // the 'B' scenario for growth + // [9, X, |6] + d3.push(9); + // [9, 12, |6] + d3.push(12); + + d3.push(15); + // There used to be a bug here about how the + // RingBuf made growth assumptions about the + // underlying Vec which didn't hold and lead + // to corruption. + // (Vec grows to next power of two) + //good- [9, 12, 15, X, X, X, X, |6] + //bug- [15, 12, X, X, X, |6, X, X] + assert_eq!(d3.pop_front(), Some(6)); + + // Which leads us to the following state which + // would be a failure case. + //bug- [15, 12, X, X, X, X, |X, X] + assert_eq!(d3.front(), Some(&9)); + } + + #[test] + fn test_reserve_exact() { + let mut d = RingBuf::new(); + d.push(0u64); + d.reserve_exact(50); + assert_eq!(d.elts.capacity(), 50); + let mut d = RingBuf::new(); + d.push(0u32); + d.reserve_exact(50); + assert_eq!(d.elts.capacity(), 50); + } + + #[test] + fn test_reserve() { + let mut d = RingBuf::new(); + d.push(0u64); + d.reserve(50); + assert_eq!(d.elts.capacity(), 64); + let mut d = RingBuf::new(); + d.push(0u32); + d.reserve(50); + assert_eq!(d.elts.capacity(), 64); + } + + #[test] + fn test_swap() { + let mut d: RingBuf = range(0i, 5).collect(); + d.pop_front(); + d.swap(0, 3); + assert_eq!(d.iter().map(|&x|x).collect::>(), vec!(4, 2, 3, 1)); + } + + #[test] + fn test_iter() { + let mut d = RingBuf::new(); + assert_eq!(d.iter().next(), None); + assert_eq!(d.iter().size_hint(), (0, Some(0))); + + for i in range(0i, 5) { + d.push(i); + } + { + let b: &[_] = &[&0,&1,&2,&3,&4]; + assert_eq!(d.iter().collect::>().as_slice(), b); + } + + for i in range(6i, 9) { + d.push_front(i); + } + { + let b: &[_] = &[&8,&7,&6,&0,&1,&2,&3,&4]; + assert_eq!(d.iter().collect::>().as_slice(), b); + } + + let mut it = d.iter(); + let mut len = d.len(); + loop { + match it.next() { + None => break, + _ => { len -= 1; assert_eq!(it.size_hint(), (len, Some(len))) } + } + } + } + + #[test] + fn test_rev_iter() { + let mut d = RingBuf::new(); + assert_eq!(d.iter().rev().next(), None); + + for i in range(0i, 5) { + d.push(i); + } + { + let b: &[_] = &[&4,&3,&2,&1,&0]; + assert_eq!(d.iter().rev().collect::>().as_slice(), b); + } + + for i in range(6i, 9) { + d.push_front(i); + } + let b: &[_] = &[&4,&3,&2,&1,&0,&6,&7,&8]; + assert_eq!(d.iter().rev().collect::>().as_slice(), b); + } + + #[test] + fn test_mut_rev_iter_wrap() { + let mut d = RingBuf::with_capacity(3); + assert!(d.iter_mut().rev().next().is_none()); + + d.push(1i); + d.push(2); + d.push(3); + assert_eq!(d.pop_front(), Some(1)); + d.push(4); + + assert_eq!(d.iter_mut().rev().map(|x| *x).collect::>(), + vec!(4, 3, 2)); + } + + #[test] + fn test_mut_iter() { + let mut d = RingBuf::new(); + assert!(d.iter_mut().next().is_none()); + + for i in range(0u, 3) { + d.push_front(i); + } + + for (i, elt) in d.iter_mut().enumerate() { + assert_eq!(*elt, 2 - i); + *elt = i; + } + + { + let mut it = d.iter_mut(); + assert_eq!(*it.next().unwrap(), 0); + assert_eq!(*it.next().unwrap(), 1); + assert_eq!(*it.next().unwrap(), 2); + assert!(it.next().is_none()); + } + } + + #[test] + fn test_mut_rev_iter() { + let mut d = RingBuf::new(); + assert!(d.iter_mut().rev().next().is_none()); + + for i in range(0u, 3) { + d.push_front(i); + } + + for (i, elt) in d.iter_mut().rev().enumerate() { + assert_eq!(*elt, i); + *elt = i; + } + + { + let mut it = d.iter_mut().rev(); + assert_eq!(*it.next().unwrap(), 0); + assert_eq!(*it.next().unwrap(), 1); + assert_eq!(*it.next().unwrap(), 2); + assert!(it.next().is_none()); + } + } + + #[test] + fn test_from_iter() { + use std::iter; + let v = vec!(1i,2,3,4,5,6,7); + let deq: RingBuf = v.iter().map(|&x| x).collect(); + let u: Vec = deq.iter().map(|&x| x).collect(); + assert_eq!(u, v); + + let mut seq = iter::count(0u, 2).take(256); + let deq: RingBuf = seq.collect(); + for (i, &x) in deq.iter().enumerate() { + assert_eq!(2*i, x); + } + assert_eq!(deq.len(), 256); + } + + #[test] + fn test_clone() { + let mut d = RingBuf::new(); + d.push_front(17i); + d.push_front(42); + d.push(137); + d.push(137); + assert_eq!(d.len(), 4u); + let mut e = d.clone(); + assert_eq!(e.len(), 4u); + while !d.is_empty() { + assert_eq!(d.pop(), e.pop()); + } + assert_eq!(d.len(), 0u); + assert_eq!(e.len(), 0u); + } + + #[test] + fn test_eq() { + let mut d = RingBuf::new(); + assert!(d == RingBuf::with_capacity(0)); + d.push_front(137i); + d.push_front(17); + d.push_front(42); + d.push(137); + let mut e = RingBuf::with_capacity(0); + e.push(42); + e.push(17); + e.push(137); + e.push(137); + assert!(&e == &d); + e.pop(); + e.push(0); + assert!(e != d); + e.clear(); + assert!(e == RingBuf::new()); + } + + #[test] + fn test_hash() { + let mut x = RingBuf::new(); + let mut y = RingBuf::new(); + + x.push(1i); + x.push(2); + x.push(3); + + y.push(0i); + y.push(1i); + y.pop_front(); + y.push(2); + y.push(3); + + assert!(hash::hash(&x) == hash::hash(&y)); + } + + #[test] + fn test_ord() { + let x = RingBuf::new(); + let mut y = RingBuf::new(); + y.push(1i); + y.push(2); + y.push(3); + assert!(x < y); + assert!(y > x); + assert!(x <= x); + assert!(x >= x); + } + + #[test] + fn test_show() { + let ringbuf: RingBuf = range(0i, 10).collect(); + assert!(format!("{}", ringbuf).as_slice() == "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); + + let ringbuf: RingBuf<&str> = vec!["just", "one", "test", "more"].iter() + .map(|&s| s) + .collect(); + assert!(format!("{}", ringbuf).as_slice() == "[just, one, test, more]"); + } +} diff --git a/src/libcollections/ringbuf.rs b/src/libcollections/ringbuf.rs deleted file mode 100644 index 3c4c3fce61d..00000000000 --- a/src/libcollections/ringbuf.rs +++ /dev/null @@ -1,1152 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! This crate implements a double-ended queue with `O(1)` amortized inserts and removals from both -//! ends of the container. It also has `O(1)` indexing like a vector. The contained elements are -//! not required to be copyable, and the queue will be sendable if the contained type is sendable. -//! Its interface `Deque` is defined in `collections`. - -use core::prelude::*; - -use core::cmp; -use core::default::Default; -use core::fmt; -use core::iter; -use core::slice; -use std::hash::{Writer, Hash}; - -use vec::Vec; - -static INITIAL_CAPACITY: uint = 8u; // 2^3 -static MINIMUM_CAPACITY: uint = 2u; - -/// `RingBuf` is a circular buffer that implements `Deque`. -#[deriving(Clone)] -pub struct RingBuf { - nelts: uint, - lo: uint, - elts: Vec> -} - -impl Default for RingBuf { - #[inline] - fn default() -> RingBuf { RingBuf::new() } -} - -impl RingBuf { - /// Creates an empty `RingBuf`. - pub fn new() -> RingBuf { - RingBuf::with_capacity(INITIAL_CAPACITY) - } - - /// Creates an empty `RingBuf` with space for at least `n` elements. - pub fn with_capacity(n: uint) -> RingBuf { - RingBuf{nelts: 0, lo: 0, - elts: Vec::from_fn(cmp::max(MINIMUM_CAPACITY, n), |_| None)} - } - - /// Retrieves an element in the `RingBuf` by index. - /// - /// Fails if there is no element with the given index. - /// - /// # Example - /// - /// ```rust - /// # #![allow(deprecated)] - /// use std::collections::RingBuf; - /// - /// let mut buf = RingBuf::new(); - /// buf.push(3i); - /// buf.push(4); - /// buf.push(5); - /// *buf.get_mut(1) = 7; - /// assert_eq!(buf[1], 7); - /// ``` - #[deprecated = "use indexing instead: `buf[index] = value`"] - pub fn get_mut(&mut self, i: uint) -> &mut T { - &mut self[i] - } - - /// Swaps elements at indices `i` and `j`. - /// - /// `i` and `j` may be equal. - /// - /// Fails if there is no element with either index. - /// - /// # Example - /// - /// ```rust - /// use std::collections::RingBuf; - /// - /// let mut buf = RingBuf::new(); - /// buf.push(3i); - /// buf.push(4); - /// buf.push(5); - /// buf.swap(0, 2); - /// assert_eq!(buf[0], 5); - /// assert_eq!(buf[2], 3); - /// ``` - pub fn swap(&mut self, i: uint, j: uint) { - assert!(i < self.len()); - assert!(j < self.len()); - let ri = self.raw_index(i); - let rj = self.raw_index(j); - self.elts.as_mut_slice().swap(ri, rj); - } - - /// Returns the index in the underlying `Vec` for a given logical element - /// index. - fn raw_index(&self, idx: uint) -> uint { - raw_index(self.lo, self.elts.len(), idx) - } - - /// Reserves capacity for exactly `n` elements in the given `RingBuf`, - /// doing nothing if `self`'s capacity is already equal to or greater - /// than the requested capacity. - pub fn reserve_exact(&mut self, n: uint) { - self.elts.reserve_exact(n); - } - - /// Reserves capacity for at least `n` elements in the given `RingBuf`, - /// over-allocating in case the caller needs to reserve additional - /// space. - /// - /// Do nothing if `self`'s capacity is already equal to or greater - /// than the requested capacity. - pub fn reserve(&mut self, n: uint) { - self.elts.reserve(n); - } - - /// Returns a front-to-back iterator. - /// - /// # Example - /// - /// ```rust - /// use std::collections::RingBuf; - /// - /// let mut buf = RingBuf::new(); - /// buf.push(5i); - /// buf.push(3); - /// buf.push(4); - /// let b: &[_] = &[&5, &3, &4]; - /// assert_eq!(buf.iter().collect::>().as_slice(), b); - /// ``` - pub fn iter(&self) -> Items { - Items{index: 0, rindex: self.nelts, lo: self.lo, elts: self.elts.as_slice()} - } - - /// Returns a front-to-back iterator which returns mutable references. - /// - /// # Example - /// - /// ```rust - /// use std::collections::RingBuf; - /// - /// let mut buf = RingBuf::new(); - /// buf.push(5i); - /// buf.push(3); - /// buf.push(4); - /// for num in buf.iter_mut() { - /// *num = *num - 2; - /// } - /// let b: &[_] = &[&mut 3, &mut 1, &mut 2]; - /// assert_eq!(buf.iter_mut().collect::>()[], b); - /// ``` - pub fn iter_mut(&mut self) -> MutItems { - let start_index = raw_index(self.lo, self.elts.len(), 0); - let end_index = raw_index(self.lo, self.elts.len(), self.nelts); - - // Divide up the array - if end_index <= start_index { - // Items to iterate goes from: - // start_index to self.elts.len() - // and then - // 0 to end_index - let (temp, remaining1) = self.elts.split_at_mut(start_index); - let (remaining2, _) = temp.split_at_mut(end_index); - MutItems { - remaining1: remaining1.iter_mut(), - remaining2: remaining2.iter_mut(), - nelts: self.nelts, - } - } else { - // Items to iterate goes from start_index to end_index: - let (empty, elts) = self.elts.split_at_mut(0); - let remaining1 = elts[mut start_index..end_index]; - MutItems { - remaining1: remaining1.iter_mut(), - remaining2: empty.iter_mut(), - nelts: self.nelts, - } - } - } - - /// Returns the number of elements in the `RingBuf`. - /// - /// # Example - /// - /// ``` - /// use std::collections::RingBuf; - /// - /// let mut v = RingBuf::new(); - /// assert_eq!(v.len(), 0); - /// v.push(1i); - /// assert_eq!(v.len(), 1); - /// ``` - pub fn len(&self) -> uint { self.nelts } - - /// Returns true if the buffer contains no elements - /// - /// # Example - /// - /// ``` - /// use std::collections::RingBuf; - /// - /// let mut v = RingBuf::new(); - /// assert!(v.is_empty()); - /// v.push_front(1i); - /// assert!(!v.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears the buffer, removing all values. - /// - /// # Example - /// - /// ``` - /// use std::collections::RingBuf; - /// - /// let mut v = RingBuf::new(); - /// v.push(1i); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - pub fn clear(&mut self) { - for x in self.elts.iter_mut() { *x = None } - self.nelts = 0; - self.lo = 0; - } - - /// Provides a reference to the front element, or `None` if the sequence is - /// empty. - /// - /// # Example - /// - /// ``` - /// use std::collections::RingBuf; - /// - /// let mut d = RingBuf::new(); - /// assert_eq!(d.front(), None); - /// - /// d.push(1i); - /// d.push(2i); - /// assert_eq!(d.front(), Some(&1i)); - /// ``` - pub fn front(&self) -> Option<&T> { - if self.nelts > 0 { Some(&self[0]) } else { None } - } - - /// Provides a mutable reference to the front element, or `None` if the - /// sequence is empty. - /// - /// # Example - /// - /// ``` - /// use std::collections::RingBuf; - /// - /// let mut d = RingBuf::new(); - /// assert_eq!(d.front_mut(), None); - /// - /// d.push(1i); - /// d.push(2i); - /// match d.front_mut() { - /// Some(x) => *x = 9i, - /// None => (), - /// } - /// assert_eq!(d.front(), Some(&9i)); - /// ``` - pub fn front_mut(&mut self) -> Option<&mut T> { - if self.nelts > 0 { Some(&mut self[0]) } else { None } - } - - /// Provides a reference to the back element, or `None` if the sequence is - /// empty. - /// - /// # Example - /// - /// ``` - /// use std::collections::RingBuf; - /// - /// let mut d = RingBuf::new(); - /// assert_eq!(d.back(), None); - /// - /// d.push(1i); - /// d.push(2i); - /// assert_eq!(d.back(), Some(&2i)); - /// ``` - pub fn back(&self) -> Option<&T> { - if self.nelts > 0 { Some(&self[self.nelts - 1]) } else { None } - } - - /// Provides a mutable reference to the back element, or `None` if the - /// sequence is empty. - /// - /// # Example - /// - /// ``` - /// use std::collections::RingBuf; - /// - /// let mut d = RingBuf::new(); - /// assert_eq!(d.back(), None); - /// - /// d.push(1i); - /// d.push(2i); - /// match d.back_mut() { - /// Some(x) => *x = 9i, - /// None => (), - /// } - /// assert_eq!(d.back(), Some(&9i)); - /// ``` - pub fn back_mut(&mut self) -> Option<&mut T> { - let nelts = self.nelts; - if nelts > 0 { Some(&mut self[nelts - 1]) } else { None } - } - - /// Removes the first element and returns it, or `None` if the sequence is - /// empty. - /// - /// # Example - /// - /// ``` - /// use std::collections::RingBuf; - /// - /// let mut d = RingBuf::new(); - /// d.push(1i); - /// d.push(2i); - /// - /// assert_eq!(d.pop_front(), Some(1i)); - /// assert_eq!(d.pop_front(), Some(2i)); - /// assert_eq!(d.pop_front(), None); - /// ``` - pub fn pop_front(&mut self) -> Option { - let result = self.elts[self.lo].take(); - if result.is_some() { - self.lo = (self.lo + 1u) % self.elts.len(); - self.nelts -= 1u; - } - result - } - - /// Inserts an element first in the sequence. - /// - /// # Example - /// - /// ``` - /// use std::collections::RingBuf; - /// - /// let mut d = RingBuf::new(); - /// d.push_front(1i); - /// d.push_front(2i); - /// assert_eq!(d.front(), Some(&2i)); - /// ``` - pub fn push_front(&mut self, t: T) { - if self.nelts == self.elts.len() { - grow(self.nelts, &mut self.lo, &mut self.elts); - } - if self.lo == 0u { - self.lo = self.elts.len() - 1u; - } else { self.lo -= 1u; } - self.elts[self.lo] = Some(t); - self.nelts += 1u; - } - - /// Appends an element to the back of a buffer - /// - /// # Example - /// - /// ```rust - /// use std::collections::RingBuf; - /// - /// let mut buf = RingBuf::new(); - /// buf.push(1i); - /// buf.push(3); - /// assert_eq!(3, *buf.back().unwrap()); - /// ``` - pub fn push(&mut self, t: T) { - if self.nelts == self.elts.len() { - grow(self.nelts, &mut self.lo, &mut self.elts); - } - let hi = self.raw_index(self.nelts); - self.elts[hi] = Some(t); - self.nelts += 1u; - } - - /// Removes the last element from a buffer and returns it, or `None` if - /// it is empty. - /// - /// # Example - /// - /// ```rust - /// use std::collections::RingBuf; - /// - /// let mut buf = RingBuf::new(); - /// assert_eq!(buf.pop(), None); - /// buf.push(1i); - /// buf.push(3); - /// assert_eq!(buf.pop(), Some(3)); - /// ``` - pub fn pop(&mut self) -> Option { - if self.nelts > 0 { - self.nelts -= 1; - let hi = self.raw_index(self.nelts); - self.elts[hi].take() - } else { - None - } - } -} - -/// `RingBuf` iterator. -pub struct Items<'a, T:'a> { - lo: uint, - index: uint, - rindex: uint, - elts: &'a [Option], -} - -impl<'a, T> Iterator<&'a T> for Items<'a, T> { - #[inline] - fn next(&mut self) -> Option<&'a T> { - if self.index == self.rindex { - return None; - } - let raw_index = raw_index(self.lo, self.elts.len(), self.index); - self.index += 1; - Some(self.elts[raw_index].as_ref().unwrap()) - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - let len = self.rindex - self.index; - (len, Some(len)) - } -} - -impl<'a, T> DoubleEndedIterator<&'a T> for Items<'a, T> { - #[inline] - fn next_back(&mut self) -> Option<&'a T> { - if self.index == self.rindex { - return None; - } - self.rindex -= 1; - let raw_index = raw_index(self.lo, self.elts.len(), self.rindex); - Some(self.elts[raw_index].as_ref().unwrap()) - } -} - -impl<'a, T> ExactSize<&'a T> for Items<'a, T> {} - -impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> { - #[inline] - fn indexable(&self) -> uint { self.rindex - self.index } - - #[inline] - fn idx(&mut self, j: uint) -> Option<&'a T> { - if j >= self.indexable() { - None - } else { - let raw_index = raw_index(self.lo, self.elts.len(), self.index + j); - Some(self.elts[raw_index].as_ref().unwrap()) - } - } -} - -/// `RingBuf` mutable iterator. -pub struct MutItems<'a, T:'a> { - remaining1: slice::MutItems<'a, Option>, - remaining2: slice::MutItems<'a, Option>, - nelts: uint, -} - -impl<'a, T> Iterator<&'a mut T> for MutItems<'a, T> { - #[inline] - fn next(&mut self) -> Option<&'a mut T> { - if self.nelts == 0 { - return None; - } - self.nelts -= 1; - match self.remaining1.next() { - Some(ptr) => return Some(ptr.as_mut().unwrap()), - None => {} - } - match self.remaining2.next() { - Some(ptr) => return Some(ptr.as_mut().unwrap()), - None => unreachable!(), - } - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - (self.nelts, Some(self.nelts)) - } -} - -impl<'a, T> DoubleEndedIterator<&'a mut T> for MutItems<'a, T> { - #[inline] - fn next_back(&mut self) -> Option<&'a mut T> { - if self.nelts == 0 { - return None; - } - self.nelts -= 1; - match self.remaining2.next_back() { - Some(ptr) => return Some(ptr.as_mut().unwrap()), - None => {} - } - match self.remaining1.next_back() { - Some(ptr) => return Some(ptr.as_mut().unwrap()), - None => unreachable!(), - } - } -} - -impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {} - -/// Grow is only called on full elts, so nelts is also len(elts), unlike -/// elsewhere. -fn grow(nelts: uint, loptr: &mut uint, elts: &mut Vec>) { - assert_eq!(nelts, elts.len()); - let lo = *loptr; - elts.reserve(nelts * 2); - let newlen = elts.capacity(); - - /* fill with None */ - for _ in range(elts.len(), newlen) { - elts.push(None); - } - - /* - Move the shortest half into the newly reserved area. - lo ---->| - nelts ----------->| - [o o o|o o o o o] - A [. . .|o o o o o o o o|. . . . .] - B [o o o|. . . . . . . .|o o o o o] - */ - - assert!(newlen - nelts/2 >= nelts); - if lo <= (nelts - lo) { // A - for i in range(0u, lo) { - elts.as_mut_slice().swap(i, nelts + i); - } - } else { // B - for i in range(lo, nelts) { - elts.as_mut_slice().swap(i, newlen - nelts + i); - } - *loptr += newlen - nelts; - } -} - -/// Returns the index in the underlying `Vec` for a given logical element index. -fn raw_index(lo: uint, len: uint, index: uint) -> uint { - if lo >= len - index { - lo + index - len - } else { - lo + index - } -} - -impl PartialEq for RingBuf { - fn eq(&self, other: &RingBuf) -> bool { - self.nelts == other.nelts && - self.iter().zip(other.iter()).all(|(a, b)| a.eq(b)) - } - fn ne(&self, other: &RingBuf) -> bool { - !self.eq(other) - } -} - -impl Eq for RingBuf {} - -impl PartialOrd for RingBuf { - fn partial_cmp(&self, other: &RingBuf) -> Option { - iter::order::partial_cmp(self.iter(), other.iter()) - } -} - -impl Ord for RingBuf { - #[inline] - fn cmp(&self, other: &RingBuf) -> Ordering { - iter::order::cmp(self.iter(), other.iter()) - } -} - -impl> Hash for RingBuf { - fn hash(&self, state: &mut S) { - self.len().hash(state); - for elt in self.iter() { - elt.hash(state); - } - } -} - -impl Index for RingBuf { - #[inline] - fn index<'a>(&'a self, i: &uint) -> &'a A { - let idx = self.raw_index(*i); - match self.elts[idx] { - None => panic!(), - Some(ref v) => v, - } - } -} - -impl IndexMut for RingBuf { - #[inline] - fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut A { - let idx = self.raw_index(*i); - match *(&mut self.elts[idx]) { - None => panic!(), - Some(ref mut v) => v - } - } -} - -impl FromIterator for RingBuf { - fn from_iter>(iterator: T) -> RingBuf { - let (lower, _) = iterator.size_hint(); - let mut deq = RingBuf::with_capacity(lower); - deq.extend(iterator); - deq - } -} - -impl Extendable for RingBuf { - fn extend>(&mut self, mut iterator: T) { - for elt in iterator { - self.push(elt); - } - } -} - -impl fmt::Show for RingBuf { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "[")); - - for (i, e) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}", *e)); - } - - write!(f, "]") - } -} - -#[cfg(test)] -mod tests { - use std::fmt::Show; - use std::prelude::*; - use std::hash; - use test::Bencher; - use test; - - use super::RingBuf; - use vec::Vec; - - #[test] - #[allow(deprecated)] - fn test_simple() { - let mut d = RingBuf::new(); - assert_eq!(d.len(), 0u); - d.push_front(17i); - d.push_front(42i); - d.push(137); - assert_eq!(d.len(), 3u); - d.push(137); - assert_eq!(d.len(), 4u); - debug!("{}", d.front()); - assert_eq!(*d.front().unwrap(), 42); - debug!("{}", d.back()); - assert_eq!(*d.back().unwrap(), 137); - let mut i = d.pop_front(); - debug!("{}", i); - assert_eq!(i, Some(42)); - i = d.pop(); - debug!("{}", i); - assert_eq!(i, Some(137)); - i = d.pop(); - debug!("{}", i); - assert_eq!(i, Some(137)); - i = d.pop(); - debug!("{}", i); - assert_eq!(i, Some(17)); - assert_eq!(d.len(), 0u); - d.push(3); - assert_eq!(d.len(), 1u); - d.push_front(2); - assert_eq!(d.len(), 2u); - d.push(4); - assert_eq!(d.len(), 3u); - d.push_front(1); - assert_eq!(d.len(), 4u); - debug!("{}", d[0]); - debug!("{}", d[1]); - debug!("{}", d[2]); - debug!("{}", d[3]); - assert_eq!(d[0], 1); - assert_eq!(d[1], 2); - assert_eq!(d[2], 3); - assert_eq!(d[3], 4); - } - - #[cfg(test)] - fn test_parameterized(a: T, b: T, c: T, d: T) { - let mut deq = RingBuf::new(); - assert_eq!(deq.len(), 0); - deq.push_front(a.clone()); - deq.push_front(b.clone()); - deq.push(c.clone()); - assert_eq!(deq.len(), 3); - deq.push(d.clone()); - assert_eq!(deq.len(), 4); - assert_eq!((*deq.front().unwrap()).clone(), b.clone()); - assert_eq!((*deq.back().unwrap()).clone(), d.clone()); - assert_eq!(deq.pop_front().unwrap(), b.clone()); - assert_eq!(deq.pop().unwrap(), d.clone()); - assert_eq!(deq.pop().unwrap(), c.clone()); - assert_eq!(deq.pop().unwrap(), a.clone()); - assert_eq!(deq.len(), 0); - deq.push(c.clone()); - assert_eq!(deq.len(), 1); - deq.push_front(b.clone()); - assert_eq!(deq.len(), 2); - deq.push(d.clone()); - assert_eq!(deq.len(), 3); - deq.push_front(a.clone()); - assert_eq!(deq.len(), 4); - assert_eq!(deq[0].clone(), a.clone()); - assert_eq!(deq[1].clone(), b.clone()); - assert_eq!(deq[2].clone(), c.clone()); - assert_eq!(deq[3].clone(), d.clone()); - } - - #[test] - fn test_push_front_grow() { - let mut deq = RingBuf::new(); - for i in range(0u, 66) { - deq.push_front(i); - } - assert_eq!(deq.len(), 66); - - for i in range(0u, 66) { - assert_eq!(deq[i], 65 - i); - } - - let mut deq = RingBuf::new(); - for i in range(0u, 66) { - deq.push(i); - } - - for i in range(0u, 66) { - assert_eq!(deq[i], i); - } - } - - #[test] - fn test_index() { - let mut deq = RingBuf::new(); - for i in range(1u, 4) { - deq.push_front(i); - } - assert_eq!(deq[1], 2); - } - - #[test] - #[should_fail] - fn test_index_out_of_bounds() { - let mut deq = RingBuf::new(); - for i in range(1u, 4) { - deq.push_front(i); - } - deq[3]; - } - - #[bench] - fn bench_new(b: &mut test::Bencher) { - b.iter(|| { - let _: RingBuf = RingBuf::new(); - }) - } - - #[bench] - fn bench_push_back(b: &mut test::Bencher) { - let mut deq = RingBuf::new(); - b.iter(|| { - deq.push(0i); - }) - } - - #[bench] - fn bench_push_front(b: &mut test::Bencher) { - let mut deq = RingBuf::new(); - b.iter(|| { - deq.push_front(0i); - }) - } - - #[bench] - fn bench_grow(b: &mut test::Bencher) { - let mut deq = RingBuf::new(); - b.iter(|| { - for _ in range(0i, 65) { - deq.push_front(1i); - } - }) - } - - #[deriving(Clone, PartialEq, Show)] - enum Taggy { - One(int), - Two(int, int), - Three(int, int, int), - } - - #[deriving(Clone, PartialEq, Show)] - enum Taggypar { - Onepar(int), - Twopar(int, int), - Threepar(int, int, int), - } - - #[deriving(Clone, PartialEq, Show)] - struct RecCy { - x: int, - y: int, - t: Taggy - } - - #[test] - fn test_param_int() { - test_parameterized::(5, 72, 64, 175); - } - - #[test] - fn test_param_taggy() { - test_parameterized::(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); - } - - #[test] - fn test_param_taggypar() { - test_parameterized::>(Onepar::(1), - Twopar::(1, 2), - Threepar::(1, 2, 3), - Twopar::(17, 42)); - } - - #[test] - fn test_param_reccy() { - let reccy1 = RecCy { x: 1, y: 2, t: One(1) }; - let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) }; - let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) }; - let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) }; - test_parameterized::(reccy1, reccy2, reccy3, reccy4); - } - - #[test] - fn test_with_capacity() { - let mut d = RingBuf::with_capacity(0); - d.push(1i); - assert_eq!(d.len(), 1); - let mut d = RingBuf::with_capacity(50); - d.push(1i); - assert_eq!(d.len(), 1); - } - - #[test] - fn test_with_capacity_non_power_two() { - let mut d3 = RingBuf::with_capacity(3); - d3.push(1i); - - // X = None, | = lo - // [|1, X, X] - assert_eq!(d3.pop_front(), Some(1)); - // [X, |X, X] - assert_eq!(d3.front(), None); - - // [X, |3, X] - d3.push(3); - // [X, |3, 6] - d3.push(6); - // [X, X, |6] - assert_eq!(d3.pop_front(), Some(3)); - - // Pushing the lo past half way point to trigger - // the 'B' scenario for growth - // [9, X, |6] - d3.push(9); - // [9, 12, |6] - d3.push(12); - - d3.push(15); - // There used to be a bug here about how the - // RingBuf made growth assumptions about the - // underlying Vec which didn't hold and lead - // to corruption. - // (Vec grows to next power of two) - //good- [9, 12, 15, X, X, X, X, |6] - //bug- [15, 12, X, X, X, |6, X, X] - assert_eq!(d3.pop_front(), Some(6)); - - // Which leads us to the following state which - // would be a failure case. - //bug- [15, 12, X, X, X, X, |X, X] - assert_eq!(d3.front(), Some(&9)); - } - - #[test] - fn test_reserve_exact() { - let mut d = RingBuf::new(); - d.push(0u64); - d.reserve_exact(50); - assert_eq!(d.elts.capacity(), 50); - let mut d = RingBuf::new(); - d.push(0u32); - d.reserve_exact(50); - assert_eq!(d.elts.capacity(), 50); - } - - #[test] - fn test_reserve() { - let mut d = RingBuf::new(); - d.push(0u64); - d.reserve(50); - assert_eq!(d.elts.capacity(), 64); - let mut d = RingBuf::new(); - d.push(0u32); - d.reserve(50); - assert_eq!(d.elts.capacity(), 64); - } - - #[test] - fn test_swap() { - let mut d: RingBuf = range(0i, 5).collect(); - d.pop_front(); - d.swap(0, 3); - assert_eq!(d.iter().map(|&x|x).collect::>(), vec!(4, 2, 3, 1)); - } - - #[test] - fn test_iter() { - let mut d = RingBuf::new(); - assert_eq!(d.iter().next(), None); - assert_eq!(d.iter().size_hint(), (0, Some(0))); - - for i in range(0i, 5) { - d.push(i); - } - { - let b: &[_] = &[&0,&1,&2,&3,&4]; - assert_eq!(d.iter().collect::>().as_slice(), b); - } - - for i in range(6i, 9) { - d.push_front(i); - } - { - let b: &[_] = &[&8,&7,&6,&0,&1,&2,&3,&4]; - assert_eq!(d.iter().collect::>().as_slice(), b); - } - - let mut it = d.iter(); - let mut len = d.len(); - loop { - match it.next() { - None => break, - _ => { len -= 1; assert_eq!(it.size_hint(), (len, Some(len))) } - } - } - } - - #[test] - fn test_rev_iter() { - let mut d = RingBuf::new(); - assert_eq!(d.iter().rev().next(), None); - - for i in range(0i, 5) { - d.push(i); - } - { - let b: &[_] = &[&4,&3,&2,&1,&0]; - assert_eq!(d.iter().rev().collect::>().as_slice(), b); - } - - for i in range(6i, 9) { - d.push_front(i); - } - let b: &[_] = &[&4,&3,&2,&1,&0,&6,&7,&8]; - assert_eq!(d.iter().rev().collect::>().as_slice(), b); - } - - #[test] - fn test_mut_rev_iter_wrap() { - let mut d = RingBuf::with_capacity(3); - assert!(d.iter_mut().rev().next().is_none()); - - d.push(1i); - d.push(2); - d.push(3); - assert_eq!(d.pop_front(), Some(1)); - d.push(4); - - assert_eq!(d.iter_mut().rev().map(|x| *x).collect::>(), - vec!(4, 3, 2)); - } - - #[test] - fn test_mut_iter() { - let mut d = RingBuf::new(); - assert!(d.iter_mut().next().is_none()); - - for i in range(0u, 3) { - d.push_front(i); - } - - for (i, elt) in d.iter_mut().enumerate() { - assert_eq!(*elt, 2 - i); - *elt = i; - } - - { - let mut it = d.iter_mut(); - assert_eq!(*it.next().unwrap(), 0); - assert_eq!(*it.next().unwrap(), 1); - assert_eq!(*it.next().unwrap(), 2); - assert!(it.next().is_none()); - } - } - - #[test] - fn test_mut_rev_iter() { - let mut d = RingBuf::new(); - assert!(d.iter_mut().rev().next().is_none()); - - for i in range(0u, 3) { - d.push_front(i); - } - - for (i, elt) in d.iter_mut().rev().enumerate() { - assert_eq!(*elt, i); - *elt = i; - } - - { - let mut it = d.iter_mut().rev(); - assert_eq!(*it.next().unwrap(), 0); - assert_eq!(*it.next().unwrap(), 1); - assert_eq!(*it.next().unwrap(), 2); - assert!(it.next().is_none()); - } - } - - #[test] - fn test_from_iter() { - use std::iter; - let v = vec!(1i,2,3,4,5,6,7); - let deq: RingBuf = v.iter().map(|&x| x).collect(); - let u: Vec = deq.iter().map(|&x| x).collect(); - assert_eq!(u, v); - - let mut seq = iter::count(0u, 2).take(256); - let deq: RingBuf = seq.collect(); - for (i, &x) in deq.iter().enumerate() { - assert_eq!(2*i, x); - } - assert_eq!(deq.len(), 256); - } - - #[test] - fn test_clone() { - let mut d = RingBuf::new(); - d.push_front(17i); - d.push_front(42); - d.push(137); - d.push(137); - assert_eq!(d.len(), 4u); - let mut e = d.clone(); - assert_eq!(e.len(), 4u); - while !d.is_empty() { - assert_eq!(d.pop(), e.pop()); - } - assert_eq!(d.len(), 0u); - assert_eq!(e.len(), 0u); - } - - #[test] - fn test_eq() { - let mut d = RingBuf::new(); - assert!(d == RingBuf::with_capacity(0)); - d.push_front(137i); - d.push_front(17); - d.push_front(42); - d.push(137); - let mut e = RingBuf::with_capacity(0); - e.push(42); - e.push(17); - e.push(137); - e.push(137); - assert!(&e == &d); - e.pop(); - e.push(0); - assert!(e != d); - e.clear(); - assert!(e == RingBuf::new()); - } - - #[test] - fn test_hash() { - let mut x = RingBuf::new(); - let mut y = RingBuf::new(); - - x.push(1i); - x.push(2); - x.push(3); - - y.push(0i); - y.push(1i); - y.pop_front(); - y.push(2); - y.push(3); - - assert!(hash::hash(&x) == hash::hash(&y)); - } - - #[test] - fn test_ord() { - let x = RingBuf::new(); - let mut y = RingBuf::new(); - y.push(1i); - y.push(2); - y.push(3); - assert!(x < y); - assert!(y > x); - assert!(x <= x); - assert!(x >= x); - } - - #[test] - fn test_show() { - let ringbuf: RingBuf = range(0i, 10).collect(); - assert!(format!("{}", ringbuf).as_slice() == "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"); - - let ringbuf: RingBuf<&str> = vec!["just", "one", "test", "more"].iter() - .map(|&s| s) - .collect(); - assert!(format!("{}", ringbuf).as_slice() == "[just, one, test, more]"); - } -} diff --git a/src/libcollections/smallintmap.rs b/src/libcollections/smallintmap.rs deleted file mode 100644 index b2e018743da..00000000000 --- a/src/libcollections/smallintmap.rs +++ /dev/null @@ -1,1052 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A simple map based on a vector for small integer keys. Space requirements -//! are O(highest integer key). - -#![allow(missing_docs)] - -use core::prelude::*; - -use core::default::Default; -use core::fmt; -use core::iter; -use core::iter::{Enumerate, FilterMap}; -use core::mem::replace; - -use {vec, slice}; -use vec::Vec; -use hash; -use hash::Hash; - -/// A map optimized for small integer keys. -/// -/// # Example -/// -/// ``` -/// use std::collections::SmallIntMap; -/// -/// let mut months = SmallIntMap::new(); -/// months.insert(1, "Jan"); -/// months.insert(2, "Feb"); -/// months.insert(3, "Mar"); -/// -/// if !months.contains_key(&12) { -/// println!("The end is near!"); -/// } -/// -/// assert_eq!(months.find(&1), Some(&"Jan")); -/// -/// match months.find_mut(&3) { -/// Some(value) => *value = "Venus", -/// None => (), -/// } -/// -/// assert_eq!(months.find(&3), Some(&"Venus")); -/// -/// // Print out all months -/// for (key, value) in months.iter() { -/// println!("month {} is {}", key, value); -/// } -/// -/// months.clear(); -/// assert!(months.is_empty()); -/// ``` -#[deriving(PartialEq, Eq)] -pub struct SmallIntMap { - v: Vec>, -} - -impl Default for SmallIntMap { - #[inline] - fn default() -> SmallIntMap { SmallIntMap::new() } -} - -impl Clone for SmallIntMap { - #[inline] - fn clone(&self) -> SmallIntMap { - SmallIntMap { v: self.v.clone() } - } - - #[inline] - fn clone_from(&mut self, source: &SmallIntMap) { - self.v.reserve(source.v.len()); - for (i, w) in self.v.iter_mut().enumerate() { - *w = source.v[i].clone(); - } - } -} - -impl > Hash for SmallIntMap { - fn hash(&self, state: &mut S) { - self.v.hash(state) - } -} - -impl SmallIntMap { - /// Creates an empty `SmallIntMap`. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// let mut map: SmallIntMap<&str> = SmallIntMap::new(); - /// ``` - pub fn new() -> SmallIntMap { SmallIntMap{v: vec!()} } - - /// Creates an empty `SmallIntMap` with space for at least `capacity` - /// elements before resizing. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// let mut map: SmallIntMap<&str> = SmallIntMap::with_capacity(10); - /// ``` - pub fn with_capacity(capacity: uint) -> SmallIntMap { - SmallIntMap { v: Vec::with_capacity(capacity) } - } - - /// Returns an iterator visiting all keys in ascending order by the keys. - /// The iterator's element type is `uint`. - pub fn keys<'r>(&'r self) -> Keys<'r, V> { - self.iter().map(|(k, _v)| k) - } - - /// Returns an iterator visiting all values in ascending order by the keys. - /// The iterator's element type is `&'r V`. - pub fn values<'r>(&'r self) -> Values<'r, V> { - self.iter().map(|(_k, v)| v) - } - - /// Returns an iterator visiting all key-value pairs in ascending order by the keys. - /// The iterator's element type is `(uint, &'r V)`. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// map.insert(1, "a"); - /// map.insert(3, "c"); - /// map.insert(2, "b"); - /// - /// // Print `1: a` then `2: b` then `3: c` - /// for (key, value) in map.iter() { - /// println!("{}: {}", key, value); - /// } - /// ``` - pub fn iter<'r>(&'r self) -> Entries<'r, V> { - Entries { - front: 0, - back: self.v.len(), - iter: self.v.iter() - } - } - - /// Returns an iterator visiting all key-value pairs in ascending order by the keys, - /// with mutable references to the values. - /// The iterator's element type is `(uint, &'r mut V)`. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// map.insert(1, "a"); - /// map.insert(2, "b"); - /// map.insert(3, "c"); - /// - /// for (key, value) in map.iter_mut() { - /// *value = "x"; - /// } - /// - /// for (key, value) in map.iter() { - /// assert_eq!(value, &"x"); - /// } - /// ``` - pub fn iter_mut<'r>(&'r mut self) -> MutEntries<'r, V> { - MutEntries { - front: 0, - back: self.v.len(), - iter: self.v.iter_mut() - } - } - - /// Returns an iterator visiting all key-value pairs in ascending order by - /// the keys, emptying (but not consuming) the original `SmallIntMap`. - /// The iterator's element type is `(uint, &'r V)`. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// map.insert(1, "a"); - /// map.insert(3, "c"); - /// map.insert(2, "b"); - /// - /// // Not possible with .iter() - /// let vec: Vec<(uint, &str)> = map.into_iter().collect(); - /// - /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]); - /// ``` - pub fn into_iter(&mut self) - -> FilterMap<(uint, Option), (uint, V), - Enumerate>>> - { - let values = replace(&mut self.v, vec!()); - values.into_iter().enumerate().filter_map(|(i, v)| { - v.map(|v| (i, v)) - }) - } - - /// Return the number of elements in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut a = SmallIntMap::new(); - /// assert_eq!(a.len(), 0); - /// a.insert(1, "a"); - /// assert_eq!(a.len(), 1); - /// ``` - pub fn len(&self) -> uint { - self.v.iter().filter(|elt| elt.is_some()).count() - } - - /// Return true if the map contains no elements. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut a = SmallIntMap::new(); - /// assert!(a.is_empty()); - /// a.insert(1, "a"); - /// assert!(!a.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { - self.v.iter().all(|elt| elt.is_none()) - } - - /// Clears the map, removing all key-value pairs. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut a = SmallIntMap::new(); - /// a.insert(1, "a"); - /// a.clear(); - /// assert!(a.is_empty()); - /// ``` - pub fn clear(&mut self) { self.v.clear() } - - /// Returns a reference to the value corresponding to the key. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.find(&1), Some(&"a")); - /// assert_eq!(map.find(&2), None); - /// ``` - pub fn find<'a>(&'a self, key: &uint) -> Option<&'a V> { - if *key < self.v.len() { - match self.v[*key] { - Some(ref value) => Some(value), - None => None - } - } else { - None - } - } - - /// Returns true if the map contains a value for the specified key. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.contains_key(&1), true); - /// assert_eq!(map.contains_key(&2), false); - /// ``` - #[inline] - pub fn contains_key(&self, key: &uint) -> bool { - self.find(key).is_some() - } - - /// Returns a mutable reference to the value corresponding to the key. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// map.insert(1, "a"); - /// match map.find_mut(&1) { - /// Some(x) => *x = "b", - /// None => (), - /// } - /// assert_eq!(map[1], "b"); - /// ``` - pub fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut V> { - if *key < self.v.len() { - match *(&mut self.v[*key]) { - Some(ref mut value) => Some(value), - None => None - } - } else { - None - } - } - - /// Inserts a key-value pair into the map. An existing value for a - /// key is replaced by the new value. Returns `true` if the key did - /// not already exist in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// assert_eq!(map.insert(2, "value"), true); - /// assert_eq!(map.insert(2, "value2"), false); - /// assert_eq!(map[2], "value2"); - /// ``` - pub fn insert(&mut self, key: uint, value: V) -> bool { - let exists = self.contains_key(&key); - let len = self.v.len(); - if len <= key { - self.v.grow_fn(key - len + 1, |_| None); - } - self.v[key] = Some(value); - !exists - } - - /// Removes a key-value pair from the map. Returns `true` if the key - /// was present in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// assert_eq!(map.remove(&1), false); - /// map.insert(1, "a"); - /// assert_eq!(map.remove(&1), true); - /// ``` - pub fn remove(&mut self, key: &uint) -> bool { - self.pop(key).is_some() - } - - /// Inserts a key-value pair from the map. If the key already had a value - /// present in the map, that value is returned. Otherwise, `None` is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// assert_eq!(map.swap(37, "a"), None); - /// assert_eq!(map.is_empty(), false); - /// - /// map.insert(37, "b"); - /// assert_eq!(map.swap(37, "c"), Some("b")); - /// assert_eq!(map[37], "c"); - /// ``` - pub fn swap(&mut self, key: uint, value: V) -> Option { - match self.find_mut(&key) { - Some(loc) => { return Some(replace(loc, value)); } - None => () - } - self.insert(key, value); - return None; - } - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.pop(&1), Some("a")); - /// assert_eq!(map.pop(&1), None); - /// ``` - pub fn pop(&mut self, key: &uint) -> Option { - if *key >= self.v.len() { - return None; - } - self.v[*key].take() - } -} - -impl SmallIntMap { - /// Updates a value in the map. If the key already exists in the map, - /// modifies the value with `ff` taking `oldval, newval`. - /// Otherwise, sets the value to `newval`. - /// Returns `true` if the key did not already exist in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// - /// // Key does not exist, will do a simple insert - /// assert!(map.update(1, vec![1i, 2], |mut old, new| { old.extend(new.into_iter()); old })); - /// assert_eq!(map[1], vec![1i, 2]); - /// - /// // Key exists, update the value - /// assert!(!map.update(1, vec![3i, 4], |mut old, new| { old.extend(new.into_iter()); old })); - /// assert_eq!(map[1], vec![1i, 2, 3, 4]); - /// ``` - pub fn update(&mut self, key: uint, newval: V, ff: |V, V| -> V) -> bool { - self.update_with_key(key, newval, |_k, v, v1| ff(v,v1)) - } - - /// Updates a value in the map. If the key already exists in the map, - /// modifies the value with `ff` taking `key, oldval, newval`. - /// Otherwise, sets the value to `newval`. - /// Returns `true` if the key did not already exist in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::SmallIntMap; - /// - /// let mut map = SmallIntMap::new(); - /// - /// // Key does not exist, will do a simple insert - /// assert!(map.update_with_key(7, 10, |key, old, new| (old + new) % key)); - /// assert_eq!(map[7], 10); - /// - /// // Key exists, update the value - /// assert!(!map.update_with_key(7, 20, |key, old, new| (old + new) % key)); - /// assert_eq!(map[7], 2); - /// ``` - pub fn update_with_key(&mut self, - key: uint, - val: V, - ff: |uint, V, V| -> V) - -> bool { - let new_val = match self.find(&key) { - None => val, - Some(orig) => ff(key, (*orig).clone(), val) - }; - self.insert(key, new_val) - } -} - -impl PartialOrd for SmallIntMap { - #[inline] - fn partial_cmp(&self, other: &SmallIntMap) -> Option { - iter::order::partial_cmp(self.iter(), other.iter()) - } -} - -impl Ord for SmallIntMap { - #[inline] - fn cmp(&self, other: &SmallIntMap) -> Ordering { - iter::order::cmp(self.iter(), other.iter()) - } -} - -impl fmt::Show for SmallIntMap { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, (k, v)) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}: {}", k, *v)); - } - - write!(f, "}}") - } -} - -impl FromIterator<(uint, V)> for SmallIntMap { - fn from_iter>(iter: Iter) -> SmallIntMap { - let mut map = SmallIntMap::new(); - map.extend(iter); - map - } -} - -impl Extendable<(uint, V)> for SmallIntMap { - fn extend>(&mut self, mut iter: Iter) { - for (k, v) in iter { - self.insert(k, v); - } - } -} - -impl Index for SmallIntMap { - #[inline] - fn index<'a>(&'a self, i: &uint) -> &'a V { - self.find(i).expect("key not present") - } -} - -impl IndexMut for SmallIntMap { - #[inline] - fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut V { - self.find_mut(i).expect("key not present") - } -} - -macro_rules! iterator { - (impl $name:ident -> $elem:ty, $($getter:ident),+) => { - impl<'a, T> Iterator<$elem> for $name<'a, T> { - #[inline] - fn next(&mut self) -> Option<$elem> { - while self.front < self.back { - match self.iter.next() { - Some(elem) => { - if elem.is_some() { - let index = self.front; - self.front += 1; - return Some((index, elem $(. $getter ())+)); - } - } - _ => () - } - self.front += 1; - } - None - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - (0, Some(self.back - self.front)) - } - } - } -} - -macro_rules! double_ended_iterator { - (impl $name:ident -> $elem:ty, $($getter:ident),+) => { - impl<'a, T> DoubleEndedIterator<$elem> for $name<'a, T> { - #[inline] - fn next_back(&mut self) -> Option<$elem> { - while self.front < self.back { - match self.iter.next_back() { - Some(elem) => { - if elem.is_some() { - self.back -= 1; - return Some((self.back, elem$(. $getter ())+)); - } - } - _ => () - } - self.back -= 1; - } - None - } - } - } -} - -/// Forward iterator over a map. -pub struct Entries<'a, T:'a> { - front: uint, - back: uint, - iter: slice::Items<'a, Option> -} - -iterator!(impl Entries -> (uint, &'a T), as_ref, unwrap) -double_ended_iterator!(impl Entries -> (uint, &'a T), as_ref, unwrap) - -/// Forward iterator over the key-value pairs of a map, with the -/// values being mutable. -pub struct MutEntries<'a, T:'a> { - front: uint, - back: uint, - iter: slice::MutItems<'a, Option> -} - -iterator!(impl MutEntries -> (uint, &'a mut T), as_mut, unwrap) -double_ended_iterator!(impl MutEntries -> (uint, &'a mut T), as_mut, unwrap) - -/// Forward iterator over the keys of a map -pub type Keys<'a, T> = - iter::Map<'static, (uint, &'a T), uint, Entries<'a, T>>; - -/// Forward iterator over the values of a map -pub type Values<'a, T> = - iter::Map<'static, (uint, &'a T), &'a T, Entries<'a, T>>; - -#[cfg(test)] -mod test_map { - use std::prelude::*; - use vec::Vec; - use hash; - - use super::SmallIntMap; - - #[test] - fn test_find_mut() { - let mut m = SmallIntMap::new(); - assert!(m.insert(1, 12i)); - assert!(m.insert(2, 8)); - assert!(m.insert(5, 14)); - let new = 100; - match m.find_mut(&5) { - None => panic!(), Some(x) => *x = new - } - assert_eq!(m.find(&5), Some(&new)); - } - - #[test] - fn test_len() { - let mut map = SmallIntMap::new(); - assert_eq!(map.len(), 0); - assert!(map.is_empty()); - assert!(map.insert(5, 20i)); - assert_eq!(map.len(), 1); - assert!(!map.is_empty()); - assert!(map.insert(11, 12)); - assert_eq!(map.len(), 2); - assert!(!map.is_empty()); - assert!(map.insert(14, 22)); - assert_eq!(map.len(), 3); - assert!(!map.is_empty()); - } - - #[test] - fn test_clear() { - let mut map = SmallIntMap::new(); - assert!(map.insert(5, 20i)); - assert!(map.insert(11, 12)); - assert!(map.insert(14, 22)); - map.clear(); - assert!(map.is_empty()); - assert!(map.find(&5).is_none()); - assert!(map.find(&11).is_none()); - assert!(map.find(&14).is_none()); - } - - #[test] - fn test_insert_with_key() { - let mut map = SmallIntMap::new(); - - // given a new key, initialize it with this new count, - // given an existing key, add more to its count - fn add_more_to_count(_k: uint, v0: uint, v1: uint) -> uint { - v0 + v1 - } - - fn add_more_to_count_simple(v0: uint, v1: uint) -> uint { - v0 + v1 - } - - // count integers - map.update(3, 1, add_more_to_count_simple); - map.update_with_key(9, 1, add_more_to_count); - map.update(3, 7, add_more_to_count_simple); - map.update_with_key(5, 3, add_more_to_count); - map.update_with_key(3, 2, add_more_to_count); - - // check the total counts - assert_eq!(map.find(&3).unwrap(), &10); - assert_eq!(map.find(&5).unwrap(), &3); - assert_eq!(map.find(&9).unwrap(), &1); - - // sadly, no sevens were counted - assert!(map.find(&7).is_none()); - } - - #[test] - fn test_swap() { - let mut m = SmallIntMap::new(); - assert_eq!(m.swap(1, 2i), None); - assert_eq!(m.swap(1, 3i), Some(2)); - assert_eq!(m.swap(1, 4i), Some(3)); - } - - #[test] - fn test_pop() { - let mut m = SmallIntMap::new(); - m.insert(1, 2i); - assert_eq!(m.pop(&1), Some(2)); - assert_eq!(m.pop(&1), None); - } - - #[test] - fn test_keys() { - let mut map = SmallIntMap::new(); - map.insert(1, 'a'); - map.insert(2, 'b'); - map.insert(3, 'c'); - let keys = map.keys().collect::>(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let mut map = SmallIntMap::new(); - map.insert(1, 'a'); - map.insert(2, 'b'); - map.insert(3, 'c'); - let values = map.values().map(|&v| v).collect::>(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_iterator() { - let mut m = SmallIntMap::new(); - - assert!(m.insert(0, 1i)); - assert!(m.insert(1, 2)); - assert!(m.insert(3, 5)); - assert!(m.insert(6, 10)); - assert!(m.insert(10, 11)); - - let mut it = m.iter(); - assert_eq!(it.size_hint(), (0, Some(11))); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.size_hint(), (0, Some(10))); - assert_eq!(it.next().unwrap(), (1, &2)); - assert_eq!(it.size_hint(), (0, Some(9))); - assert_eq!(it.next().unwrap(), (3, &5)); - assert_eq!(it.size_hint(), (0, Some(7))); - assert_eq!(it.next().unwrap(), (6, &10)); - assert_eq!(it.size_hint(), (0, Some(4))); - assert_eq!(it.next().unwrap(), (10, &11)); - assert_eq!(it.size_hint(), (0, Some(0))); - assert!(it.next().is_none()); - } - - #[test] - fn test_iterator_size_hints() { - let mut m = SmallIntMap::new(); - - assert!(m.insert(0, 1i)); - assert!(m.insert(1, 2)); - assert!(m.insert(3, 5)); - assert!(m.insert(6, 10)); - assert!(m.insert(10, 11)); - - assert_eq!(m.iter().size_hint(), (0, Some(11))); - assert_eq!(m.iter().rev().size_hint(), (0, Some(11))); - assert_eq!(m.iter_mut().size_hint(), (0, Some(11))); - assert_eq!(m.iter_mut().rev().size_hint(), (0, Some(11))); - } - - #[test] - fn test_mut_iterator() { - let mut m = SmallIntMap::new(); - - assert!(m.insert(0, 1i)); - assert!(m.insert(1, 2)); - assert!(m.insert(3, 5)); - assert!(m.insert(6, 10)); - assert!(m.insert(10, 11)); - - for (k, v) in m.iter_mut() { - *v += k as int; - } - - let mut it = m.iter(); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.next().unwrap(), (1, &3)); - assert_eq!(it.next().unwrap(), (3, &8)); - assert_eq!(it.next().unwrap(), (6, &16)); - assert_eq!(it.next().unwrap(), (10, &21)); - assert!(it.next().is_none()); - } - - #[test] - fn test_rev_iterator() { - let mut m = SmallIntMap::new(); - - assert!(m.insert(0, 1i)); - assert!(m.insert(1, 2)); - assert!(m.insert(3, 5)); - assert!(m.insert(6, 10)); - assert!(m.insert(10, 11)); - - let mut it = m.iter().rev(); - assert_eq!(it.next().unwrap(), (10, &11)); - assert_eq!(it.next().unwrap(), (6, &10)); - assert_eq!(it.next().unwrap(), (3, &5)); - assert_eq!(it.next().unwrap(), (1, &2)); - assert_eq!(it.next().unwrap(), (0, &1)); - assert!(it.next().is_none()); - } - - #[test] - fn test_mut_rev_iterator() { - let mut m = SmallIntMap::new(); - - assert!(m.insert(0, 1i)); - assert!(m.insert(1, 2)); - assert!(m.insert(3, 5)); - assert!(m.insert(6, 10)); - assert!(m.insert(10, 11)); - - for (k, v) in m.iter_mut().rev() { - *v += k as int; - } - - let mut it = m.iter(); - assert_eq!(it.next().unwrap(), (0, &1)); - assert_eq!(it.next().unwrap(), (1, &3)); - assert_eq!(it.next().unwrap(), (3, &8)); - assert_eq!(it.next().unwrap(), (6, &16)); - assert_eq!(it.next().unwrap(), (10, &21)); - assert!(it.next().is_none()); - } - - #[test] - fn test_move_iter() { - let mut m = SmallIntMap::new(); - m.insert(1, box 2i); - let mut called = false; - for (k, v) in m.into_iter() { - assert!(!called); - called = true; - assert_eq!(k, 1); - assert_eq!(v, box 2i); - } - assert!(called); - m.insert(2, box 1i); - } - - #[test] - fn test_show() { - let mut map = SmallIntMap::new(); - let empty = SmallIntMap::::new(); - - map.insert(1, 2i); - map.insert(3, 4i); - - let map_str = map.to_string(); - let map_str = map_str.as_slice(); - assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); - assert_eq!(format!("{}", empty), "{}".to_string()); - } - - #[test] - fn test_clone() { - let mut a = SmallIntMap::new(); - - a.insert(1, 'x'); - a.insert(4, 'y'); - a.insert(6, 'z'); - - assert!(a.clone() == a); - } - - #[test] - fn test_eq() { - let mut a = SmallIntMap::new(); - let mut b = SmallIntMap::new(); - - assert!(a == b); - assert!(a.insert(0, 5i)); - assert!(a != b); - assert!(b.insert(0, 4i)); - assert!(a != b); - assert!(a.insert(5, 19)); - assert!(a != b); - assert!(!b.insert(0, 5)); - assert!(a != b); - assert!(b.insert(5, 19)); - assert!(a == b); - } - - #[test] - fn test_lt() { - let mut a = SmallIntMap::new(); - let mut b = SmallIntMap::new(); - - assert!(!(a < b) && !(b < a)); - assert!(b.insert(2u, 5i)); - assert!(a < b); - assert!(a.insert(2, 7)); - assert!(!(a < b) && b < a); - assert!(b.insert(1, 0)); - assert!(b < a); - assert!(a.insert(0, 6)); - assert!(a < b); - assert!(a.insert(6, 2)); - assert!(a < b && !(b < a)); - } - - #[test] - fn test_ord() { - let mut a = SmallIntMap::new(); - let mut b = SmallIntMap::new(); - - assert!(a <= b && a >= b); - assert!(a.insert(1u, 1i)); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - assert!(b.insert(2, 2)); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - #[test] - fn test_hash() { - let mut x = SmallIntMap::new(); - let mut y = SmallIntMap::new(); - - assert!(hash::hash(&x) == hash::hash(&y)); - x.insert(1, 'a'); - x.insert(2, 'b'); - x.insert(3, 'c'); - - y.insert(3, 'c'); - y.insert(2, 'b'); - y.insert(1, 'a'); - - assert!(hash::hash(&x) == hash::hash(&y)); - } - - #[test] - fn test_from_iter() { - let xs: Vec<(uint, char)> = vec![(1u, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]; - - let map: SmallIntMap = xs.iter().map(|&x| x).collect(); - - for &(k, v) in xs.iter() { - assert_eq!(map.find(&k), Some(&v)); - } - } - - #[test] - fn test_index() { - let mut map: SmallIntMap = SmallIntMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - assert_eq!(map[3], 4); - } - - #[test] - #[should_fail] - fn test_index_nonexistent() { - let mut map: SmallIntMap = SmallIntMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - map[4]; - } -} - -#[cfg(test)] -mod bench { - extern crate test; - use self::test::Bencher; - use super::SmallIntMap; - use bench::{insert_rand_n, insert_seq_n, find_rand_n, find_seq_n}; - - #[bench] - pub fn insert_rand_100(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); - insert_rand_n(100, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.remove(&i); }); - } - - #[bench] - pub fn insert_rand_10_000(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); - insert_rand_n(10_000, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.remove(&i); }); - } - - // Insert seq - #[bench] - pub fn insert_seq_100(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); - insert_seq_n(100, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.remove(&i); }); - } - - #[bench] - pub fn insert_seq_10_000(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); - insert_seq_n(10_000, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.remove(&i); }); - } - - // Find rand - #[bench] - pub fn find_rand_100(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); - find_rand_n(100, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.find(&i); }); - } - - #[bench] - pub fn find_rand_10_000(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); - find_rand_n(10_000, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.find(&i); }); - } - - // Find seq - #[bench] - pub fn find_seq_100(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); - find_seq_n(100, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.find(&i); }); - } - - #[bench] - pub fn find_seq_10_000(b: &mut Bencher) { - let mut m : SmallIntMap = SmallIntMap::new(); - find_seq_n(10_000, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.find(&i); }); - } -} diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 297ba71d252..2d6cf865878 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -65,7 +65,7 @@ use core::prelude::{PartialEq, PartialOrd, Result, AsSlice, Some, Tuple2}; use core::prelude::{range}; use hash; -use ringbuf::RingBuf; +use ring_buf::RingBuf; use string::String; use unicode; use vec::Vec; diff --git a/src/libcollections/tree/map.rs b/src/libcollections/tree/map.rs new file mode 100644 index 00000000000..9742bddb1f6 --- /dev/null +++ b/src/libcollections/tree/map.rs @@ -0,0 +1,1918 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; + +use alloc::boxed::Box; +use core::default::Default; +use core::fmt; +use core::fmt::Show; +use core::iter; +use core::mem::{replace, swap}; +use core::ptr; +use std::hash::{Writer, Hash}; + +use vec::Vec; + +/// This is implemented as an AA tree, which is a simplified variation of +/// a red-black tree where red (horizontal) nodes can only be added +/// as a right child. The time complexity is the same, and re-balancing +/// operations are more frequent but also cheaper. +/// +/// # Example +/// +/// ``` +/// use std::collections::TreeMap; +/// +/// let mut map = TreeMap::new(); +/// +/// map.insert(2i, "bar"); +/// map.insert(1i, "foo"); +/// map.insert(3i, "quux"); +/// +/// // In ascending order by keys +/// for (key, value) in map.iter() { +/// println!("{}: {}", key, value); +/// } +/// +/// // Prints 1, 2, 3 +/// for key in map.keys() { +/// println!("{}", key); +/// } +/// +/// // Prints `foo`, `bar`, `quux` +/// for key in map.values() { +/// println!("{}", key); +/// } +/// +/// map.remove(&1); +/// assert_eq!(map.len(), 2); +/// +/// if !map.contains_key(&1) { +/// println!("1 is no more"); +/// } +/// +/// for key in range(0, 4) { +/// match map.find(&key) { +/// Some(val) => println!("{} has a value: {}", key, val), +/// None => println!("{} not in map", key), +/// } +/// } +/// +/// map.clear(); +/// assert!(map.is_empty()); +/// ``` +/// +/// The easiest way to use `TreeMap` with a custom type as keys is to implement `Ord`. +/// We must also implement `PartialEq`, `Eq` and `PartialOrd`. +/// +/// ``` +/// use std::collections::TreeMap; +/// +/// // We need `Eq` and `PartialEq`, these can be derived. +/// #[deriving(Eq, PartialEq)] +/// struct Troll<'a> { +/// name: &'a str, +/// level: uint, +/// } +/// +/// // Implement `Ord` and sort trolls by level. +/// impl<'a> Ord for Troll<'a> { +/// fn cmp(&self, other: &Troll) -> Ordering { +/// // If we swap `self` and `other`, we get descending ordering. +/// self.level.cmp(&other.level) +/// } +/// } +/// +/// // `PartialOrd` needs to be implemented as well. +/// impl<'a> PartialOrd for Troll<'a> { +/// fn partial_cmp(&self, other: &Troll) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// // Use a map to store trolls, sorted by level, and track a list of +/// // heroes slain. +/// let mut trolls = TreeMap::new(); +/// +/// trolls.insert(Troll { name: "Orgarr", level: 2 }, +/// vec!["King Karl"]); +/// trolls.insert(Troll { name: "Blargarr", level: 3 }, +/// vec!["Odd"]); +/// trolls.insert(Troll { name: "Kron the Smelly One", level: 4 }, +/// vec!["Omar the Brave", "Peter: Slayer of Trolls"]); +/// trolls.insert(Troll { name: "Wartilda", level: 1 }, +/// vec![]); +/// +/// println!("You are facing {} trolls!", trolls.len()); +/// +/// // Print the trolls, ordered by level with smallest level first +/// for (troll, heroes) in trolls.iter() { +/// let what = if heroes.len() == 1u { "hero" } +/// else { "heroes" }; +/// +/// println!("level {}: '{}' has slain {} {}", +/// troll.level, troll.name, heroes.len(), what); +/// } +/// +/// // Kill all trolls +/// trolls.clear(); +/// assert_eq!(trolls.len(), 0); +/// ``` + +// Future improvements: + +// range search - O(log n) retrieval of an iterator from some key + +// (possibly) implement the overloads Python does for sets: +// * intersection: & +// * difference: - +// * symmetric difference: ^ +// * union: | +// These would be convenient since the methods work like `each` + +#[deriving(Clone)] +pub struct TreeMap { + root: Option>>, + length: uint +} + +impl PartialEq for TreeMap { + fn eq(&self, other: &TreeMap) -> bool { + self.len() == other.len() && + self.iter().zip(other.iter()).all(|(a, b)| a == b) + } +} + +impl Eq for TreeMap {} + +impl PartialOrd for TreeMap { + #[inline] + fn partial_cmp(&self, other: &TreeMap) -> Option { + iter::order::partial_cmp(self.iter(), other.iter()) + } +} + +impl Ord for TreeMap { + #[inline] + fn cmp(&self, other: &TreeMap) -> Ordering { + iter::order::cmp(self.iter(), other.iter()) + } +} + +impl Show for TreeMap { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, (k, v)) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}: {}", *k, *v)); + } + + write!(f, "}}") + } +} + +impl Default for TreeMap { + #[inline] + fn default() -> TreeMap { TreeMap::new() } +} + +impl Index for TreeMap { + #[inline] + fn index<'a>(&'a self, i: &K) -> &'a V { + self.find(i).expect("no entry found for key") + } +} + +impl IndexMut for TreeMap { + #[inline] + fn index_mut<'a>(&'a mut self, i: &K) -> &'a mut V { + self.find_mut(i).expect("no entry found for key") + } +} + +impl TreeMap { + /// Creates an empty `TreeMap`. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// let mut map: TreeMap<&str, int> = TreeMap::new(); + /// ``` + pub fn new() -> TreeMap { TreeMap{root: None, length: 0} } + + /// Gets a lazy iterator over the keys in the map, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// let mut map = TreeMap::new(); + /// map.insert("a", 1i); + /// map.insert("c", 3i); + /// map.insert("b", 2i); + /// + /// // Print "a", "b", "c" in order. + /// for x in map.keys() { + /// println!("{}", x); + /// } + /// ``` + pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { + self.iter().map(|(k, _v)| k) + } + + /// Gets a lazy iterator over the values in the map, in ascending order + /// with respect to the corresponding keys. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// let mut map = TreeMap::new(); + /// map.insert("a", 1i); + /// map.insert("c", 3i); + /// map.insert("b", 2i); + /// + /// // Print 1, 2, 3 ordered by keys. + /// for x in map.values() { + /// println!("{}", x); + /// } + /// ``` + pub fn values<'a>(&'a self) -> Values<'a, K, V> { + self.iter().map(|(_k, v)| v) + } + + /// Gets a lazy iterator over the key-value pairs in the map, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// let mut map = TreeMap::new(); + /// map.insert("a", 1i); + /// map.insert("c", 3i); + /// map.insert("b", 2i); + /// + /// // Print contents in ascending order + /// for (key, value) in map.iter() { + /// println!("{}: {}", key, value); + /// } + /// ``` + pub fn iter<'a>(&'a self) -> Entries<'a, K, V> { + Entries { + stack: vec!(), + node: deref(&self.root), + remaining_min: self.length, + remaining_max: self.length + } + } + + /// Gets a lazy reverse iterator over the key-value pairs in the map, in descending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// let mut map = TreeMap::new(); + /// map.insert("a", 1i); + /// map.insert("c", 3i); + /// map.insert("b", 2i); + /// + /// // Print contents in descending order + /// for (key, value) in map.rev_iter() { + /// println!("{}: {}", key, value); + /// } + /// ``` + pub fn rev_iter<'a>(&'a self) -> RevEntries<'a, K, V> { + RevEntries{iter: self.iter()} + } + + /// Gets a lazy forward iterator over the key-value pairs in the + /// map, with the values being mutable. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// let mut map = TreeMap::new(); + /// map.insert("a", 1i); + /// map.insert("c", 3i); + /// map.insert("b", 2i); + /// + /// // Add 10 until we find "b" + /// for (key, value) in map.iter_mut() { + /// *value += 10; + /// if key == &"b" { break } + /// } + /// + /// assert_eq!(map.find(&"a"), Some(&11)); + /// assert_eq!(map.find(&"b"), Some(&12)); + /// assert_eq!(map.find(&"c"), Some(&3)); + /// ``` + pub fn iter_mut<'a>(&'a mut self) -> MutEntries<'a, K, V> { + MutEntries { + stack: vec!(), + node: deref_mut(&mut self.root), + remaining_min: self.length, + remaining_max: self.length + } + } + + /// Gets a lazy reverse iterator over the key-value pairs in the + /// map, with the values being mutable. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// let mut map = TreeMap::new(); + /// map.insert("a", 1i); + /// map.insert("c", 3i); + /// map.insert("b", 2i); + /// + /// // Add 10 until we find "b" + /// for (key, value) in map.rev_iter_mut() { + /// *value += 10; + /// if key == &"b" { break } + /// } + /// + /// assert_eq!(map.find(&"a"), Some(&1)); + /// assert_eq!(map.find(&"b"), Some(&12)); + /// assert_eq!(map.find(&"c"), Some(&13)); + /// ``` + pub fn rev_iter_mut<'a>(&'a mut self) -> RevMutEntries<'a, K, V> { + RevMutEntries{iter: self.iter_mut()} + } + + /// Gets a lazy iterator that consumes the TreeMap. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// let mut map = TreeMap::new(); + /// map.insert("a", 1i); + /// map.insert("c", 3i); + /// map.insert("b", 2i); + /// + /// // Not possible with a regular `.iter()` + /// let vec: Vec<(&str, int)> = map.into_iter().collect(); + /// assert_eq!(vec, vec![("a", 1), ("b", 2), ("c", 3)]); + /// ``` + pub fn into_iter(self) -> MoveEntries { + let TreeMap { root, length } = self; + let stk = match root { + None => vec!(), + Some(box tn) => vec!(tn) + }; + MoveEntries { + stack: stk, + remaining: length + } + } + + /// Return the number of elements in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut a = TreeMap::new(); + /// assert_eq!(a.len(), 0); + /// a.insert(1u, "a"); + /// assert_eq!(a.len(), 1); + /// ``` + pub fn len(&self) -> uint { self.length } + + /// Return true if the map contains no elements. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut a = TreeMap::new(); + /// assert!(a.is_empty()); + /// a.insert(1u, "a"); + /// assert!(!a.is_empty()); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Clears the map, removing all values. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut a = TreeMap::new(); + /// a.insert(1u, "a"); + /// a.clear(); + /// assert!(a.is_empty()); + /// ``` + pub fn clear(&mut self) { + self.root = None; + self.length = 0 + } + + /// Returns a reference to the value corresponding to the key. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// map.insert(1u, "a"); + /// assert_eq!(map.find(&1), Some(&"a")); + /// assert_eq!(map.find(&2), None); + /// ``` + #[inline] + pub fn find<'a>(&'a self, key: &K) -> Option<&'a V> { + tree_find_with(&self.root, |k2| key.cmp(k2)) + } + + /// Returns true if the map contains a value for the specified key. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// map.insert(1u, "a"); + /// assert_eq!(map.contains_key(&1), true); + /// assert_eq!(map.contains_key(&2), false); + /// ``` + #[inline] + pub fn contains_key(&self, key: &K) -> bool { + self.find(key).is_some() + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// map.insert(1u, "a"); + /// match map.find_mut(&1) { + /// Some(x) => *x = "b", + /// None => (), + /// } + /// assert_eq!(map[1], "b"); + /// ``` + #[inline] + pub fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V> { + tree_find_with_mut(&mut self.root, |x| key.cmp(x)) + } + + /// Inserts a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Returns `true` if the key did + /// not already exist in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// assert_eq!(map.insert(2u, "value"), true); + /// assert_eq!(map.insert(2, "value2"), false); + /// assert_eq!(map[2], "value2"); + /// ``` + #[inline] + pub fn insert(&mut self, key: K, value: V) -> bool { + self.swap(key, value).is_none() + } + + /// Removes a key-value pair from the map. Returns `true` if the key + /// was present in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// assert_eq!(map.remove(&1u), false); + /// map.insert(1, "a"); + /// assert_eq!(map.remove(&1), true); + /// ``` + #[inline] + pub fn remove(&mut self, key: &K) -> bool { + self.pop(key).is_some() + } + + /// Inserts a key-value pair from the map. If the key already had a value + /// present in the map, that value is returned. Otherwise, `None` is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// assert_eq!(map.swap(37u, "a"), None); + /// assert_eq!(map.is_empty(), false); + /// + /// map.insert(37, "b"); + /// assert_eq!(map.swap(37, "c"), Some("b")); + /// assert_eq!(map[37], "c"); + /// ``` + pub fn swap(&mut self, key: K, value: V) -> Option { + let ret = insert(&mut self.root, key, value); + if ret.is_none() { self.length += 1 } + ret + } + + /// Removes a key from the map, returning the value at the key if the key + /// was previously in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// map.insert(1u, "a"); + /// assert_eq!(map.pop(&1), Some("a")); + /// assert_eq!(map.pop(&1), None); + /// ``` + pub fn pop(&mut self, key: &K) -> Option { + let ret = remove(&mut self.root, key); + if ret.is_some() { self.length -= 1 } + ret + } +} + +impl TreeMap { + /// Returns the value for which `f(key)` returns `Equal`. `f` is invoked + /// with current key and guides tree navigation. That means `f` should + /// be aware of natural ordering of the tree. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// fn get_headers() -> TreeMap { + /// let mut result = TreeMap::new(); + /// result.insert("Content-Type".to_string(), "application/xml".to_string()); + /// result.insert("User-Agent".to_string(), "Curl-Rust/0.1".to_string()); + /// result + /// } + /// + /// let headers = get_headers(); + /// let ua_key = "User-Agent"; + /// let ua = headers.find_with(|k| { + /// ua_key.cmp(&k.as_slice()) + /// }); + /// + /// assert_eq!((*ua.unwrap()).as_slice(), "Curl-Rust/0.1"); + /// ``` + #[inline] + pub fn find_with<'a>(&'a self, f:|&K| -> Ordering) -> Option<&'a V> { + tree_find_with(&self.root, f) + } + + /// Returns the value for which `f(key)` returns `Equal`. `f` is invoked + /// with current key and guides tree navigation. That means `f` should + /// be aware of natural ordering of the tree. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut t = TreeMap::new(); + /// t.insert("Content-Type", "application/xml"); + /// t.insert("User-Agent", "Curl-Rust/0.1"); + /// + /// let new_ua = "Safari/156.0"; + /// match t.find_with_mut(|k| "User-Agent".cmp(k)) { + /// Some(x) => *x = new_ua, + /// None => panic!(), + /// } + /// + /// assert_eq!(t.find(&"User-Agent"), Some(&new_ua)); + /// ``` + #[inline] + pub fn find_with_mut<'a>(&'a mut self, f:|&K| -> Ordering) -> Option<&'a mut V> { + tree_find_with_mut(&mut self.root, f) + } +} + +// range iterators. + +macro_rules! bound_setup { + // initialiser of the iterator to manipulate + ($iter:expr, $k:expr, + // whether we are looking for the lower or upper bound. + $is_lower_bound:expr) => { + { + let mut iter = $iter; + loop { + if !iter.node.is_null() { + let node_k = unsafe {&(*iter.node).key}; + match $k.cmp(node_k) { + Less => iter.traverse_left(), + Greater => iter.traverse_right(), + Equal => { + if $is_lower_bound { + iter.traverse_complete(); + return iter; + } else { + iter.traverse_right() + } + } + } + } else { + iter.traverse_complete(); + return iter; + } + } + } + } +} + + +impl TreeMap { + /// Gets a lazy iterator that should be initialized using + /// `traverse_left`/`traverse_right`/`traverse_complete`. + fn iter_for_traversal<'a>(&'a self) -> Entries<'a, K, V> { + Entries { + stack: vec!(), + node: deref(&self.root), + remaining_min: 0, + remaining_max: self.length + } + } + + /// Returns a lazy iterator to the first key-value pair whose key is not less than `k` + /// If all keys in map are less than `k` an empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// map.insert(2i, "a"); + /// map.insert(4, "b"); + /// map.insert(6, "c"); + /// map.insert(8, "d"); + /// + /// assert_eq!(map.lower_bound(&4).next(), Some((&4, &"b"))); + /// assert_eq!(map.lower_bound(&5).next(), Some((&6, &"c"))); + /// assert_eq!(map.lower_bound(&10).next(), None); + /// ``` + pub fn lower_bound<'a>(&'a self, k: &K) -> Entries<'a, K, V> { + bound_setup!(self.iter_for_traversal(), k, true) + } + + /// Returns a lazy iterator to the first key-value pair whose key is greater than `k` + /// If all keys in map are less than or equal to `k` an empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// map.insert(2i, "a"); + /// map.insert(4, "b"); + /// map.insert(6, "c"); + /// map.insert(8, "d"); + /// + /// assert_eq!(map.upper_bound(&4).next(), Some((&6, &"c"))); + /// assert_eq!(map.upper_bound(&5).next(), Some((&6, &"c"))); + /// assert_eq!(map.upper_bound(&10).next(), None); + /// ``` + pub fn upper_bound<'a>(&'a self, k: &K) -> Entries<'a, K, V> { + bound_setup!(self.iter_for_traversal(), k, false) + } + + /// Gets a lazy iterator that should be initialized using + /// `traverse_left`/`traverse_right`/`traverse_complete`. + fn iter_mut_for_traversal<'a>(&'a mut self) -> MutEntries<'a, K, V> { + MutEntries { + stack: vec!(), + node: deref_mut(&mut self.root), + remaining_min: 0, + remaining_max: self.length + } + } + + /// Returns a lazy value iterator to the first key-value pair (with + /// the value being mutable) whose key is not less than `k`. + /// + /// If all keys in map are less than `k` an empty iterator is + /// returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// map.insert(2i, "a"); + /// map.insert(4, "b"); + /// map.insert(6, "c"); + /// map.insert(8, "d"); + /// + /// assert_eq!(map.lower_bound_mut(&4).next(), Some((&4, &mut "b"))); + /// assert_eq!(map.lower_bound_mut(&5).next(), Some((&6, &mut "c"))); + /// assert_eq!(map.lower_bound_mut(&10).next(), None); + /// + /// for (key, value) in map.lower_bound_mut(&4) { + /// *value = "changed"; + /// } + /// + /// assert_eq!(map.find(&2), Some(&"a")); + /// assert_eq!(map.find(&4), Some(&"changed")); + /// assert_eq!(map.find(&6), Some(&"changed")); + /// assert_eq!(map.find(&8), Some(&"changed")); + /// ``` + pub fn lower_bound_mut<'a>(&'a mut self, k: &K) -> MutEntries<'a, K, V> { + bound_setup!(self.iter_mut_for_traversal(), k, true) + } + + /// Returns a lazy iterator to the first key-value pair (with the + /// value being mutable) whose key is greater than `k`. + /// + /// If all keys in map are less than or equal to `k` an empty iterator + /// is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeMap; + /// + /// let mut map = TreeMap::new(); + /// map.insert(2i, "a"); + /// map.insert(4, "b"); + /// map.insert(6, "c"); + /// map.insert(8, "d"); + /// + /// assert_eq!(map.upper_bound_mut(&4).next(), Some((&6, &mut "c"))); + /// assert_eq!(map.upper_bound_mut(&5).next(), Some((&6, &mut "c"))); + /// assert_eq!(map.upper_bound_mut(&10).next(), None); + /// + /// for (key, value) in map.upper_bound_mut(&4) { + /// *value = "changed"; + /// } + /// + /// assert_eq!(map.find(&2), Some(&"a")); + /// assert_eq!(map.find(&4), Some(&"b")); + /// assert_eq!(map.find(&6), Some(&"changed")); + /// assert_eq!(map.find(&8), Some(&"changed")); + /// ``` + pub fn upper_bound_mut<'a>(&'a mut self, k: &K) -> MutEntries<'a, K, V> { + bound_setup!(self.iter_mut_for_traversal(), k, false) + } +} + +/// Lazy forward iterator over a map +pub struct Entries<'a, K:'a, V:'a> { + stack: Vec<&'a TreeNode>, + // See the comment on MutEntries; this is just to allow + // code-sharing (for this immutable-values iterator it *could* very + // well be Option<&'a TreeNode>). + node: *const TreeNode, + remaining_min: uint, + remaining_max: uint +} + +/// Lazy backward iterator over a map +pub struct RevEntries<'a, K:'a, V:'a> { + iter: Entries<'a, K, V>, +} + +/// Lazy forward iterator over a map that allows for the mutation of +/// the values. +pub struct MutEntries<'a, K:'a, V:'a> { + stack: Vec<&'a mut TreeNode>, + // Unfortunately, we require some unsafe-ness to get around the + // fact that we would be storing a reference *into* one of the + // nodes in the stack. + // + // As far as the compiler knows, this would let us invalidate the + // reference by assigning a new value to this node's position in + // its parent, which would cause this current one to be + // deallocated so this reference would be invalid. (i.e. the + // compilers complaints are 100% correct.) + // + // However, as far as you humans reading this code know (or are + // about to know, if you haven't read far enough down yet), we are + // only reading from the TreeNode.{left,right} fields. the only + // thing that is ever mutated is the .value field (although any + // actual mutation that happens is done externally, by the + // iterator consumer). So, don't be so concerned, rustc, we've got + // it under control. + // + // (This field can legitimately be null.) + node: *mut TreeNode, + remaining_min: uint, + remaining_max: uint +} + +/// Lazy backward iterator over a map +pub struct RevMutEntries<'a, K:'a, V:'a> { + iter: MutEntries<'a, K, V>, +} + +/// TreeMap keys iterator. +pub type Keys<'a, K, V> = + iter::Map<'static, (&'a K, &'a V), &'a K, Entries<'a, K, V>>; + +/// TreeMap values iterator. +pub type Values<'a, K, V> = + iter::Map<'static, (&'a K, &'a V), &'a V, Entries<'a, K, V>>; + + +// FIXME #5846 we want to be able to choose between &x and &mut x +// (with many different `x`) below, so we need to optionally pass mut +// as a tt, but the only thing we can do with a `tt` is pass them to +// other macros, so this takes the `& ` token +// sequence and forces their evaluation as an expression. +macro_rules! addr { ($e:expr) => { $e }} +// putting an optional mut into type signatures +macro_rules! item { ($i:item) => { $i }} + +macro_rules! define_iterator { + ($name:ident, + $rev_name:ident, + + // the function to go from &m Option> to *m TreeNode + deref = $deref:ident, + + // see comment on `addr!`, this is just an optional `mut`, but + // there's no support for 0-or-1 repeats. + addr_mut = $($addr_mut:tt)* + ) => { + // private methods on the forward iterator (item!() for the + // addr_mut in the next_ return value) + item!(impl<'a, K, V> $name<'a, K, V> { + #[inline(always)] + fn next_(&mut self, forward: bool) -> Option<(&'a K, &'a $($addr_mut)* V)> { + while !self.stack.is_empty() || !self.node.is_null() { + if !self.node.is_null() { + let node = unsafe {addr!(& $($addr_mut)* *self.node)}; + { + let next_node = if forward { + addr!(& $($addr_mut)* node.left) + } else { + addr!(& $($addr_mut)* node.right) + }; + self.node = $deref(next_node); + } + self.stack.push(node); + } else { + let node = self.stack.pop().unwrap(); + let next_node = if forward { + addr!(& $($addr_mut)* node.right) + } else { + addr!(& $($addr_mut)* node.left) + }; + self.node = $deref(next_node); + self.remaining_max -= 1; + if self.remaining_min > 0 { + self.remaining_min -= 1; + } + return Some((&node.key, addr!(& $($addr_mut)* node.value))); + } + } + None + } + + /// traverse_left, traverse_right and traverse_complete are + /// used to initialize Entries/MutEntries + /// pointing to element inside tree structure. + /// + /// They should be used in following manner: + /// - create iterator using TreeMap::[mut_]iter_for_traversal + /// - find required node using `traverse_left`/`traverse_right` + /// (current node is `Entries::node` field) + /// - complete initialization with `traverse_complete` + /// + /// After this, iteration will start from `self.node`. If + /// `self.node` is None iteration will start from last + /// node from which we traversed left. + #[inline] + fn traverse_left(&mut self) { + let node = unsafe {addr!(& $($addr_mut)* *self.node)}; + self.node = $deref(addr!(& $($addr_mut)* node.left)); + self.stack.push(node); + } + + #[inline] + fn traverse_right(&mut self) { + let node = unsafe {addr!(& $($addr_mut)* *self.node)}; + self.node = $deref(addr!(& $($addr_mut)* node.right)); + } + + #[inline] + fn traverse_complete(&mut self) { + if !self.node.is_null() { + unsafe { + self.stack.push(addr!(& $($addr_mut)* *self.node)); + } + self.node = ptr::RawPtr::null(); + } + } + }) + + // the forward Iterator impl. + item!(impl<'a, K, V> Iterator<(&'a K, &'a $($addr_mut)* V)> for $name<'a, K, V> { + /// Advances the iterator to the next node (in order) and return a + /// tuple with a reference to the key and value. If there are no + /// more nodes, return `None`. + fn next(&mut self) -> Option<(&'a K, &'a $($addr_mut)* V)> { + self.next_(true) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + (self.remaining_min, Some(self.remaining_max)) + } + }) + + // the reverse Iterator impl. + item!(impl<'a, K, V> Iterator<(&'a K, &'a $($addr_mut)* V)> for $rev_name<'a, K, V> { + fn next(&mut self) -> Option<(&'a K, &'a $($addr_mut)* V)> { + self.iter.next_(false) + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.iter.size_hint() + } + }) + } +} // end of define_iterator + +define_iterator! { + Entries, + RevEntries, + deref = deref, + + // immutable, so no mut + addr_mut = +} +define_iterator! { + MutEntries, + RevMutEntries, + deref = deref_mut, + + addr_mut = mut +} + +fn deref<'a, K, V>(node: &'a Option>>) -> *const TreeNode { + match *node { + Some(ref n) => { + let n: &TreeNode = &**n; + n as *const TreeNode + } + None => ptr::null() + } +} + +fn deref_mut(x: &mut Option>>) + -> *mut TreeNode { + match *x { + Some(ref mut n) => { + let n: &mut TreeNode = &mut **n; + n as *mut TreeNode + } + None => ptr::null_mut() + } +} + +/// Lazy forward iterator over a map that consumes the map while iterating +pub struct MoveEntries { + stack: Vec>, + remaining: uint +} + +impl Iterator<(K, V)> for MoveEntries { + #[inline] + fn next(&mut self) -> Option<(K, V)> { + while !self.stack.is_empty() { + let TreeNode { + key, + value, + left, + right, + level, + } = self.stack.pop().unwrap(); + + match left { + Some(box left) => { + let n = TreeNode { + key: key, + value: value, + left: None, + right: right, + level: level + }; + self.stack.push(n); + self.stack.push(left); + } + None => { + match right { + Some(box right) => self.stack.push(right), + None => () + } + self.remaining -= 1; + return Some((key, value)) + } + } + } + None + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + (self.remaining, Some(self.remaining)) + } + +} + + + +// Nodes keep track of their level in the tree, starting at 1 in the +// leaves and with a red child sharing the level of the parent. +#[deriving(Clone)] +struct TreeNode { + key: K, + value: V, + left: Option>>, + right: Option>>, + level: uint +} + +impl TreeNode { + /// Creates a new tree node. + #[inline] + pub fn new(key: K, value: V) -> TreeNode { + TreeNode{key: key, value: value, left: None, right: None, level: 1} + } +} + +// Remove left horizontal link by rotating right +fn skew(node: &mut Box>) { + if node.left.as_ref().map_or(false, |x| x.level == node.level) { + let mut save = node.left.take().unwrap(); + swap(&mut node.left, &mut save.right); // save.right now None + swap(node, &mut save); + node.right = Some(save); + } +} + +// Remove dual horizontal link by rotating left and increasing level of +// the parent +fn split(node: &mut Box>) { + if node.right.as_ref().map_or(false, + |x| x.right.as_ref().map_or(false, |y| y.level == node.level)) { + let mut save = node.right.take().unwrap(); + swap(&mut node.right, &mut save.left); // save.left now None + save.level += 1; + swap(node, &mut save); + node.left = Some(save); + } +} + +// Next 2 functions have the same convention: comparator gets +// at input current key and returns search_key cmp cur_key +// (i.e. search_key.cmp(&cur_key)) +fn tree_find_with<'r, K, V>(node: &'r Option>>, + f: |&K| -> Ordering) -> Option<&'r V> { + let mut current: &'r Option>> = node; + loop { + match *current { + Some(ref r) => { + match f(&r.key) { + Less => current = &r.left, + Greater => current = &r.right, + Equal => return Some(&r.value) + } + } + None => return None + } + } +} + +// See comments above tree_find_with +fn tree_find_with_mut<'r, K, V>(node: &'r mut Option>>, + f: |&K| -> Ordering) -> Option<&'r mut V> { + + let mut current = node; + loop { + let temp = current; // hack to appease borrowck + match *temp { + Some(ref mut r) => { + match f(&r.key) { + Less => current = &mut r.left, + Greater => current = &mut r.right, + Equal => return Some(&mut r.value) + } + } + None => return None + } + } +} + +fn insert(node: &mut Option>>, + key: K, value: V) -> Option { + match *node { + Some(ref mut save) => { + match key.cmp(&save.key) { + Less => { + let inserted = insert(&mut save.left, key, value); + skew(save); + split(save); + inserted + } + Greater => { + let inserted = insert(&mut save.right, key, value); + skew(save); + split(save); + inserted + } + Equal => { + save.key = key; + Some(replace(&mut save.value, value)) + } + } + } + None => { + *node = Some(box TreeNode::new(key, value)); + None + } + } +} + +fn remove(node: &mut Option>>, + key: &K) -> Option { + fn heir_swap(node: &mut Box>, + child: &mut Option>>) { + // *could* be done without recursion, but it won't borrow check + for x in child.iter_mut() { + if x.right.is_some() { + heir_swap(node, &mut x.right); + } else { + swap(&mut node.key, &mut x.key); + swap(&mut node.value, &mut x.value); + } + } + } + + match *node { + None => { + return None; // bottom of tree + } + Some(ref mut save) => { + let (ret, rebalance) = match key.cmp(&save.key) { + Less => (remove(&mut save.left, key), true), + Greater => (remove(&mut save.right, key), true), + Equal => { + if save.left.is_some() { + if save.right.is_some() { + let mut left = save.left.take().unwrap(); + if left.right.is_some() { + heir_swap(save, &mut left.right); + } else { + swap(&mut save.key, &mut left.key); + swap(&mut save.value, &mut left.value); + } + save.left = Some(left); + (remove(&mut save.left, key), true) + } else { + let new = save.left.take().unwrap(); + let box TreeNode{value, ..} = replace(save, new); + *save = save.left.take().unwrap(); + (Some(value), true) + } + } else if save.right.is_some() { + let new = save.right.take().unwrap(); + let box TreeNode{value, ..} = replace(save, new); + (Some(value), true) + } else { + (None, false) + } + } + }; + + if rebalance { + let left_level = save.left.as_ref().map_or(0, |x| x.level); + let right_level = save.right.as_ref().map_or(0, |x| x.level); + + // re-balance, if necessary + if left_level < save.level - 1 || right_level < save.level - 1 { + save.level -= 1; + + if right_level > save.level { + let save_level = save.level; + for x in save.right.iter_mut() { x.level = save_level } + } + + skew(save); + + for right in save.right.iter_mut() { + skew(right); + for x in right.right.iter_mut() { skew(x) } + } + + split(save); + for x in save.right.iter_mut() { split(x) } + } + + return ret; + } + } + } + return match node.take() { + Some(box TreeNode{value, ..}) => Some(value), None => panic!() + }; +} + +impl FromIterator<(K, V)> for TreeMap { + fn from_iter>(iter: T) -> TreeMap { + let mut map = TreeMap::new(); + map.extend(iter); + map + } +} + +impl Extendable<(K, V)> for TreeMap { + #[inline] + fn extend>(&mut self, mut iter: T) { + for (k, v) in iter { + self.insert(k, v); + } + } +} + +impl, V: Hash> Hash for TreeMap { + fn hash(&self, state: &mut S) { + for elt in self.iter() { + elt.hash(state); + } + } +} + + +#[cfg(test)] +mod test_treemap { + use std::prelude::*; + use std::rand::Rng; + use std::rand; + + use super::{TreeMap, TreeNode}; + + #[test] + fn find_empty() { + let m: TreeMap = TreeMap::new(); + assert!(m.find(&5) == None); + } + + #[test] + fn find_not_found() { + let mut m = TreeMap::new(); + assert!(m.insert(1i, 2i)); + assert!(m.insert(5i, 3i)); + assert!(m.insert(9i, 3i)); + assert_eq!(m.find(&2), None); + } + + #[test] + fn find_with_empty() { + let m: TreeMap<&'static str,int> = TreeMap::new(); + assert!(m.find_with(|k| "test".cmp(k)) == None); + } + + #[test] + fn find_with_not_found() { + let mut m = TreeMap::new(); + assert!(m.insert("test1", 2i)); + assert!(m.insert("test2", 3i)); + assert!(m.insert("test3", 3i)); + assert_eq!(m.find_with(|k| "test4".cmp(k)), None); + } + + #[test] + fn find_with_found() { + let mut m = TreeMap::new(); + assert!(m.insert("test1", 2i)); + assert!(m.insert("test2", 3i)); + assert!(m.insert("test3", 4i)); + assert_eq!(m.find_with(|k| "test2".cmp(k)), Some(&3i)); + } + + #[test] + fn test_find_mut() { + let mut m = TreeMap::new(); + assert!(m.insert(1i, 12i)); + assert!(m.insert(2, 8)); + assert!(m.insert(5, 14)); + let new = 100; + match m.find_mut(&5) { + None => panic!(), Some(x) => *x = new + } + assert_eq!(m.find(&5), Some(&new)); + } + + #[test] + fn test_find_with_mut() { + let mut m = TreeMap::new(); + assert!(m.insert("t1", 12i)); + assert!(m.insert("t2", 8)); + assert!(m.insert("t5", 14)); + let new = 100; + match m.find_with_mut(|k| "t5".cmp(k)) { + None => panic!(), Some(x) => *x = new + } + assert_eq!(m.find_with(|k| "t5".cmp(k)), Some(&new)); + } + + #[test] + fn insert_replace() { + let mut m = TreeMap::new(); + assert!(m.insert(5i, 2i)); + assert!(m.insert(2, 9)); + assert!(!m.insert(2, 11)); + assert_eq!(m.find(&2).unwrap(), &11); + } + + #[test] + fn test_clear() { + let mut m = TreeMap::new(); + m.clear(); + assert!(m.insert(5i, 11i)); + assert!(m.insert(12, -3)); + assert!(m.insert(19, 2)); + m.clear(); + assert!(m.find(&5).is_none()); + assert!(m.find(&12).is_none()); + assert!(m.find(&19).is_none()); + assert!(m.is_empty()); + } + + #[test] + fn u8_map() { + let mut m = TreeMap::new(); + + let k1 = "foo".as_bytes(); + let k2 = "bar".as_bytes(); + let v1 = "baz".as_bytes(); + let v2 = "foobar".as_bytes(); + + m.insert(k1.clone(), v1.clone()); + m.insert(k2.clone(), v2.clone()); + + assert_eq!(m.find(&k2), Some(&v2)); + assert_eq!(m.find(&k1), Some(&v1)); + } + + fn check_equal(ctrl: &[(K, V)], + map: &TreeMap) { + assert_eq!(ctrl.is_empty(), map.is_empty()); + for x in ctrl.iter() { + let &(ref k, ref v) = x; + assert!(map.find(k).unwrap() == v) + } + for (map_k, map_v) in map.iter() { + let mut found = false; + for x in ctrl.iter() { + let &(ref ctrl_k, ref ctrl_v) = x; + if *map_k == *ctrl_k { + assert!(*map_v == *ctrl_v); + found = true; + break; + } + } + assert!(found); + } + } + + fn check_left(node: &Option>>, + parent: &Box>) { + match *node { + Some(ref r) => { + assert_eq!(r.key.cmp(&parent.key), Less); + assert!(r.level == parent.level - 1); // left is black + check_left(&r.left, r); + check_right(&r.right, r, false); + } + None => assert!(parent.level == 1) // parent is leaf + } + } + + fn check_right(node: &Option>>, + parent: &Box>, + parent_red: bool) { + match *node { + Some(ref r) => { + assert_eq!(r.key.cmp(&parent.key), Greater); + let red = r.level == parent.level; + if parent_red { assert!(!red) } // no dual horizontal links + // Right red or black + assert!(red || r.level == parent.level - 1); + check_left(&r.left, r); + check_right(&r.right, r, red); + } + None => assert!(parent.level == 1) // parent is leaf + } + } + + fn check_structure(map: &TreeMap) { + match map.root { + Some(ref r) => { + check_left(&r.left, r); + check_right(&r.right, r, false); + } + None => () + } + } + + #[test] + fn test_rand_int() { + let mut map: TreeMap = TreeMap::new(); + let mut ctrl = vec![]; + + check_equal(ctrl.as_slice(), &map); + assert!(map.find(&5).is_none()); + + let seed: &[_] = &[42]; + let mut rng: rand::IsaacRng = rand::SeedableRng::from_seed(seed); + + for _ in range(0u, 3) { + for _ in range(0u, 90) { + let k = rng.gen(); + let v = rng.gen(); + if !ctrl.iter().any(|x| x == &(k, v)) { + assert!(map.insert(k, v)); + ctrl.push((k, v)); + check_structure(&map); + check_equal(ctrl.as_slice(), &map); + } + } + + for _ in range(0u, 30) { + let r = rng.gen_range(0, ctrl.len()); + let (key, _) = ctrl.remove(r).unwrap(); + assert!(map.remove(&key)); + check_structure(&map); + check_equal(ctrl.as_slice(), &map); + } + } + } + + #[test] + fn test_len() { + let mut m = TreeMap::new(); + assert!(m.insert(3i, 6i)); + assert_eq!(m.len(), 1); + assert!(m.insert(0, 0)); + assert_eq!(m.len(), 2); + assert!(m.insert(4, 8)); + assert_eq!(m.len(), 3); + assert!(m.remove(&3)); + assert_eq!(m.len(), 2); + assert!(!m.remove(&5)); + assert_eq!(m.len(), 2); + assert!(m.insert(2, 4)); + assert_eq!(m.len(), 3); + assert!(m.insert(1, 2)); + assert_eq!(m.len(), 4); + } + + #[test] + fn test_iterator() { + let mut m = TreeMap::new(); + + assert!(m.insert(3i, 6i)); + assert!(m.insert(0, 0)); + assert!(m.insert(4, 8)); + assert!(m.insert(2, 4)); + assert!(m.insert(1, 2)); + + let mut n = 0; + for (k, v) in m.iter() { + assert_eq!(*k, n); + assert_eq!(*v, n * 2); + n += 1; + } + assert_eq!(n, 5); + } + + #[test] + fn test_interval_iteration() { + let mut m = TreeMap::new(); + for i in range(1i, 100i) { + assert!(m.insert(i * 2, i * 4)); + } + + for i in range(1i, 198i) { + let mut lb_it = m.lower_bound(&i); + let (&k, &v) = lb_it.next().unwrap(); + let lb = i + i % 2; + assert_eq!(lb, k); + assert_eq!(lb * 2, v); + + let mut ub_it = m.upper_bound(&i); + let (&k, &v) = ub_it.next().unwrap(); + let ub = i + 2 - i % 2; + assert_eq!(ub, k); + assert_eq!(ub * 2, v); + } + let mut end_it = m.lower_bound(&199); + assert_eq!(end_it.next(), None); + } + + #[test] + fn test_rev_iter() { + let mut m = TreeMap::new(); + + assert!(m.insert(3i, 6i)); + assert!(m.insert(0, 0)); + assert!(m.insert(4, 8)); + assert!(m.insert(2, 4)); + assert!(m.insert(1, 2)); + + let mut n = 4; + for (k, v) in m.rev_iter() { + assert_eq!(*k, n); + assert_eq!(*v, n * 2); + n -= 1; + } + } + + #[test] + fn test_mut_iter() { + let mut m = TreeMap::new(); + for i in range(0u, 10) { + assert!(m.insert(i, 100 * i)); + } + + for (i, (&k, v)) in m.iter_mut().enumerate() { + *v += k * 10 + i; // 000 + 00 + 0, 100 + 10 + 1, ... + } + + for (&k, &v) in m.iter() { + assert_eq!(v, 111 * k); + } + } + #[test] + fn test_mut_rev_iter() { + let mut m = TreeMap::new(); + for i in range(0u, 10) { + assert!(m.insert(i, 100 * i)); + } + + for (i, (&k, v)) in m.rev_iter_mut().enumerate() { + *v += k * 10 + (9 - i); // 900 + 90 + (9 - 0), 800 + 80 + (9 - 1), ... + } + + for (&k, &v) in m.iter() { + assert_eq!(v, 111 * k); + } + } + + #[test] + fn test_mut_interval_iter() { + let mut m_lower = TreeMap::new(); + let mut m_upper = TreeMap::new(); + for i in range(1i, 100i) { + assert!(m_lower.insert(i * 2, i * 4)); + assert!(m_upper.insert(i * 2, i * 4)); + } + + for i in range(1i, 199) { + let mut lb_it = m_lower.lower_bound_mut(&i); + let (&k, v) = lb_it.next().unwrap(); + let lb = i + i % 2; + assert_eq!(lb, k); + *v -= k; + } + for i in range(0i, 198) { + let mut ub_it = m_upper.upper_bound_mut(&i); + let (&k, v) = ub_it.next().unwrap(); + let ub = i + 2 - i % 2; + assert_eq!(ub, k); + *v -= k; + } + + assert!(m_lower.lower_bound_mut(&199).next().is_none()); + + assert!(m_upper.upper_bound_mut(&198).next().is_none()); + + assert!(m_lower.iter().all(|(_, &x)| x == 0)); + assert!(m_upper.iter().all(|(_, &x)| x == 0)); + } + + #[test] + fn test_keys() { + let vec = vec![(1i, 'a'), (2i, 'b'), (3i, 'c')]; + let map = vec.into_iter().collect::>(); + let keys = map.keys().map(|&k| k).collect::>(); + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); + } + + #[test] + fn test_values() { + let vec = vec![(1i, 'a'), (2i, 'b'), (3i, 'c')]; + let map = vec.into_iter().collect::>(); + let values = map.values().map(|&v| v).collect::>(); + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); + } + + #[test] + fn test_eq() { + let mut a = TreeMap::new(); + let mut b = TreeMap::new(); + + assert!(a == b); + assert!(a.insert(0i, 5i)); + assert!(a != b); + assert!(b.insert(0, 4)); + assert!(a != b); + assert!(a.insert(5, 19)); + assert!(a != b); + assert!(!b.insert(0, 5)); + assert!(a != b); + assert!(b.insert(5, 19)); + assert!(a == b); + } + + #[test] + fn test_lt() { + let mut a = TreeMap::new(); + let mut b = TreeMap::new(); + + assert!(!(a < b) && !(b < a)); + assert!(b.insert(0i, 5i)); + assert!(a < b); + assert!(a.insert(0, 7)); + assert!(!(a < b) && b < a); + assert!(b.insert(-2, 0)); + assert!(b < a); + assert!(a.insert(-5, 2)); + assert!(a < b); + assert!(a.insert(6, 2)); + assert!(a < b && !(b < a)); + } + + #[test] + fn test_ord() { + let mut a = TreeMap::new(); + let mut b = TreeMap::new(); + + assert!(a <= b && a >= b); + assert!(a.insert(1i, 1i)); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + assert!(b.insert(2, 2)); + assert!(b > a && b >= a); + assert!(a < b && a <= b); + } + + #[test] + fn test_show() { + let mut map: TreeMap = TreeMap::new(); + let empty: TreeMap = TreeMap::new(); + + map.insert(1, 2); + map.insert(3, 4); + + let map_str = format!("{}", map); + + assert!(map_str == "{1: 2, 3: 4}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } + + #[test] + fn test_lazy_iterator() { + let mut m = TreeMap::new(); + let (x1, y1) = (2i, 5i); + let (x2, y2) = (9, 12); + let (x3, y3) = (20, -3); + let (x4, y4) = (29, 5); + let (x5, y5) = (103, 3); + + assert!(m.insert(x1, y1)); + assert!(m.insert(x2, y2)); + assert!(m.insert(x3, y3)); + assert!(m.insert(x4, y4)); + assert!(m.insert(x5, y5)); + + let m = m; + let mut a = m.iter(); + + assert_eq!(a.next().unwrap(), (&x1, &y1)); + assert_eq!(a.next().unwrap(), (&x2, &y2)); + assert_eq!(a.next().unwrap(), (&x3, &y3)); + assert_eq!(a.next().unwrap(), (&x4, &y4)); + assert_eq!(a.next().unwrap(), (&x5, &y5)); + + assert!(a.next().is_none()); + + let mut b = m.iter(); + + let expected = [(&x1, &y1), (&x2, &y2), (&x3, &y3), (&x4, &y4), + (&x5, &y5)]; + let mut i = 0; + + for x in b { + assert_eq!(expected[i], x); + i += 1; + + if i == 2 { + break + } + } + + for x in b { + assert_eq!(expected[i], x); + i += 1; + } + } + + #[test] + fn test_from_iter() { + let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; + + let map: TreeMap = xs.iter().map(|&x| x).collect(); + + for &(k, v) in xs.iter() { + assert_eq!(map.find(&k), Some(&v)); + } + } + + #[test] + fn test_index() { + let mut map: TreeMap = TreeMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + assert_eq!(map[2], 1); + } + + #[test] + #[should_fail] + fn test_index_nonexistent() { + let mut map: TreeMap = TreeMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + map[4]; + } + + #[test] + fn test_swap() { + let mut m = TreeMap::new(); + assert_eq!(m.swap(1u, 2i), None); + assert_eq!(m.swap(1u, 3i), Some(2)); + assert_eq!(m.swap(1u, 4i), Some(3)); + } + + #[test] + fn test_pop() { + let mut m = TreeMap::new(); + m.insert(1u, 2i); + assert_eq!(m.pop(&1), Some(2)); + assert_eq!(m.pop(&1), None); + } +} + +#[cfg(test)] +mod bench { + use std::prelude::*; + use std::rand::{weak_rng, Rng}; + use test::{Bencher, black_box}; + + use super::TreeMap; + use bench::{insert_rand_n, insert_seq_n, find_rand_n, find_seq_n}; + + #[bench] + pub fn insert_rand_100(b: &mut Bencher) { + let mut m : TreeMap = TreeMap::new(); + insert_rand_n(100, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.remove(&i); }); + } + + #[bench] + pub fn insert_rand_10_000(b: &mut Bencher) { + let mut m : TreeMap = TreeMap::new(); + insert_rand_n(10_000, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.remove(&i); }); + } + + // Insert seq + #[bench] + pub fn insert_seq_100(b: &mut Bencher) { + let mut m : TreeMap = TreeMap::new(); + insert_seq_n(100, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.remove(&i); }); + } + + #[bench] + pub fn insert_seq_10_000(b: &mut Bencher) { + let mut m : TreeMap = TreeMap::new(); + insert_seq_n(10_000, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.remove(&i); }); + } + + // Find rand + #[bench] + pub fn find_rand_100(b: &mut Bencher) { + let mut m : TreeMap = TreeMap::new(); + find_rand_n(100, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.find(&i); }); + } + + #[bench] + pub fn find_rand_10_000(b: &mut Bencher) { + let mut m : TreeMap = TreeMap::new(); + find_rand_n(10_000, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.find(&i); }); + } + + // Find seq + #[bench] + pub fn find_seq_100(b: &mut Bencher) { + let mut m : TreeMap = TreeMap::new(); + find_seq_n(100, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.find(&i); }); + } + + #[bench] + pub fn find_seq_10_000(b: &mut Bencher) { + let mut m : TreeMap = TreeMap::new(); + find_seq_n(10_000, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.find(&i); }); + } + + fn bench_iter(b: &mut Bencher, size: uint) { + let mut map = TreeMap::::new(); + let mut rng = weak_rng(); + + for _ in range(0, size) { + map.swap(rng.gen(), rng.gen()); + } + + b.iter(|| { + for entry in map.iter() { + black_box(entry); + } + }); + } + + #[bench] + pub fn iter_20(b: &mut Bencher) { + bench_iter(b, 20); + } + + #[bench] + pub fn iter_1000(b: &mut Bencher) { + bench_iter(b, 1000); + } + + #[bench] + pub fn iter_100000(b: &mut Bencher) { + bench_iter(b, 100000); + } +} + diff --git a/src/libcollections/tree/mod.rs b/src/libcollections/tree/mod.rs new file mode 100644 index 00000000000..ac8279c92fe --- /dev/null +++ b/src/libcollections/tree/mod.rs @@ -0,0 +1,36 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Maps are collections of unique keys with corresponding values, and sets are +//! just unique keys without a corresponding value. The `Map` and `Set` traits in +//! `std::container` define the basic interface. +//! +//! This crate defines the `TreeMap` and `TreeSet` types. Their keys must implement `Ord`. +//! +//! `TreeMap`s are ordered. +//! +//! ## Example +//! +//! ```{rust} +//! use std::collections::TreeSet; +//! +//! let mut tree_set = TreeSet::new(); +//! +//! tree_set.insert(2i); +//! tree_set.insert(1i); +//! tree_set.insert(3i); +//! +//! for i in tree_set.iter() { +//! println!("{}", i) // prints 1, then 2, then 3 +//! } +//! ``` + +pub mod map; +pub mod set; \ No newline at end of file diff --git a/src/libcollections/tree/set.rs b/src/libcollections/tree/set.rs new file mode 100644 index 00000000000..d24a8234b20 --- /dev/null +++ b/src/libcollections/tree/set.rs @@ -0,0 +1,950 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; + +use core::default::Default; +use core::fmt; +use core::fmt::Show; +use core::iter::Peekable; +use core::iter; +use std::hash::{Writer, Hash}; + +use tree_map::{TreeMap, Entries, RevEntries, MoveEntries}; + +/// An implementation of the `Set` trait on top of the `TreeMap` container. The +/// only requirement is that the type of the elements contained ascribes to the +/// `Ord` trait. +/// +/// ## Example +/// +/// ```{rust} +/// use std::collections::TreeSet; +/// +/// let mut set = TreeSet::new(); +/// +/// set.insert(2i); +/// set.insert(1i); +/// set.insert(3i); +/// +/// for i in set.iter() { +/// println!("{}", i) // prints 1, then 2, then 3 +/// } +/// +/// set.remove(&3); +/// +/// if !set.contains(&3) { +/// println!("set does not contain a 3 anymore"); +/// } +/// ``` +/// +/// The easiest way to use `TreeSet` with a custom type is to implement `Ord`. +/// We must also implement `PartialEq`, `Eq` and `PartialOrd`. +/// +/// ``` +/// use std::collections::TreeSet; +/// +/// // We need `Eq` and `PartialEq`, these can be derived. +/// #[deriving(Eq, PartialEq)] +/// struct Troll<'a> { +/// name: &'a str, +/// level: uint, +/// } +/// +/// // Implement `Ord` and sort trolls by level. +/// impl<'a> Ord for Troll<'a> { +/// fn cmp(&self, other: &Troll) -> Ordering { +/// // If we swap `self` and `other`, we get descending ordering. +/// self.level.cmp(&other.level) +/// } +/// } +/// +/// // `PartialOrd` needs to be implemented as well. +/// impl<'a> PartialOrd for Troll<'a> { +/// fn partial_cmp(&self, other: &Troll) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// let mut trolls = TreeSet::new(); +/// +/// trolls.insert(Troll { name: "Orgarr", level: 2 }); +/// trolls.insert(Troll { name: "Blargarr", level: 3 }); +/// trolls.insert(Troll { name: "Kron the Smelly One", level: 4 }); +/// trolls.insert(Troll { name: "Wartilda", level: 1 }); +/// +/// println!("You are facing {} trolls!", trolls.len()); +/// +/// // Print the trolls, ordered by level with smallest level first +/// for x in trolls.iter() { +/// println!("level {}: {}!", x.level, x.name); +/// } +/// +/// // Kill all trolls +/// trolls.clear(); +/// assert_eq!(trolls.len(), 0); +/// ``` +#[deriving(Clone)] +pub struct TreeSet { + map: TreeMap +} + +impl PartialEq for TreeSet { + #[inline] + fn eq(&self, other: &TreeSet) -> bool { self.map == other.map } +} + +impl Eq for TreeSet {} + +impl PartialOrd for TreeSet { + #[inline] + fn partial_cmp(&self, other: &TreeSet) -> Option { + self.map.partial_cmp(&other.map) + } +} + +impl Ord for TreeSet { + #[inline] + fn cmp(&self, other: &TreeSet) -> Ordering { + iter::order::cmp(self.iter(), other.iter()) + } +} + +impl Show for TreeSet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, x) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}", *x)); + } + + write!(f, "}}") + } +} + +impl Default for TreeSet { + #[inline] + fn default() -> TreeSet { TreeSet::new() } +} + +impl TreeSet { + /// Creates an empty `TreeSet`. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let mut set: TreeSet = TreeSet::new(); + /// ``` + #[inline] + pub fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } + + /// Gets a lazy iterator over the values in the set, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); + /// + /// // Will print in ascending order. + /// for x in set.iter() { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn iter<'a>(&'a self) -> SetItems<'a, T> { + SetItems{iter: self.map.iter()} + } + + /// Gets a lazy iterator over the values in the set, in descending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); + /// + /// // Will print in descending order. + /// for x in set.rev_iter() { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn rev_iter<'a>(&'a self) -> RevSetItems<'a, T> { + RevSetItems{iter: self.map.rev_iter()} + } + + /// Creates a consuming iterator, that is, one that moves each value out of the + /// set in ascending order. The set cannot be used after calling this. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); + /// + /// // Not possible with a regular `.iter()` + /// let v: Vec = set.into_iter().collect(); + /// assert_eq!(v, vec![1, 2, 3, 4, 5]); + /// ``` + #[inline] + pub fn into_iter(self) -> MoveSetItems { + self.map.into_iter().map(|(value, _)| value) + } + + /// Gets a lazy iterator pointing to the first value not less than `v` (greater or equal). + /// If all elements in the set are less than `v` empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let set: TreeSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); + /// + /// assert_eq!(set.lower_bound(&4).next(), Some(&4)); + /// assert_eq!(set.lower_bound(&5).next(), Some(&6)); + /// assert_eq!(set.lower_bound(&10).next(), None); + /// ``` + #[inline] + pub fn lower_bound<'a>(&'a self, v: &T) -> SetItems<'a, T> { + SetItems{iter: self.map.lower_bound(v)} + } + + /// Gets a lazy iterator pointing to the first value greater than `v`. + /// If all elements in the set are less than or equal to `v` an + /// empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// let set: TreeSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); + /// + /// assert_eq!(set.upper_bound(&4).next(), Some(&6)); + /// assert_eq!(set.upper_bound(&5).next(), Some(&6)); + /// assert_eq!(set.upper_bound(&10).next(), None); + /// ``` + #[inline] + pub fn upper_bound<'a>(&'a self, v: &T) -> SetItems<'a, T> { + SetItems{iter: self.map.upper_bound(v)} + } + + /// Visits the values representing the difference, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); + /// + /// // Can be seen as `a - b`. + /// for x in a.difference(&b) { + /// println!("{}", x); // Print 1 then 2 + /// } + /// + /// let diff: TreeSet = a.difference(&b).map(|&x| x).collect(); + /// assert_eq!(diff, [1, 2].iter().map(|&x| x).collect()); + /// + /// // Note that difference is not symmetric, + /// // and `b - a` means something else: + /// let diff: TreeSet = b.difference(&a).map(|&x| x).collect(); + /// assert_eq!(diff, [4, 5].iter().map(|&x| x).collect()); + /// ``` + pub fn difference<'a>(&'a self, other: &'a TreeSet) -> DifferenceItems<'a, T> { + DifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visits the values representing the symmetric difference, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); + /// + /// // Print 1, 2, 4, 5 in ascending order. + /// for x in a.symmetric_difference(&b) { + /// println!("{}", x); + /// } + /// + /// let diff1: TreeSet = a.symmetric_difference(&b).map(|&x| x).collect(); + /// let diff2: TreeSet = b.symmetric_difference(&a).map(|&x| x).collect(); + /// + /// assert_eq!(diff1, diff2); + /// assert_eq!(diff1, [1, 2, 4, 5].iter().map(|&x| x).collect()); + /// ``` + pub fn symmetric_difference<'a>(&'a self, other: &'a TreeSet) + -> SymDifferenceItems<'a, T> { + SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visits the values representing the intersection, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: TreeSet = [2, 3, 4].iter().map(|&x| x).collect(); + /// + /// // Print 2, 3 in ascending order. + /// for x in a.intersection(&b) { + /// println!("{}", x); + /// } + /// + /// let diff: TreeSet = a.intersection(&b).map(|&x| x).collect(); + /// assert_eq!(diff, [2, 3].iter().map(|&x| x).collect()); + /// ``` + pub fn intersection<'a>(&'a self, other: &'a TreeSet) + -> IntersectionItems<'a, T> { + IntersectionItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visits the values representing the union, in ascending order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); + /// + /// // Print 1, 2, 3, 4, 5 in ascending order. + /// for x in a.union(&b) { + /// println!("{}", x); + /// } + /// + /// let diff: TreeSet = a.union(&b).map(|&x| x).collect(); + /// assert_eq!(diff, [1, 2, 3, 4, 5].iter().map(|&x| x).collect()); + /// ``` + pub fn union<'a>(&'a self, other: &'a TreeSet) -> UnionItems<'a, T> { + UnionItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Return the number of elements in the set + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let mut v = TreeSet::new(); + /// assert_eq!(v.len(), 0); + /// v.insert(1i); + /// assert_eq!(v.len(), 1); + /// ``` + #[inline] + pub fn len(&self) -> uint { self.map.len() } + + /// Returns true if the set contains no elements + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let mut v = TreeSet::new(); + /// assert!(v.is_empty()); + /// v.insert(1i); + /// assert!(!v.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Clears the set, removing all values. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let mut v = TreeSet::new(); + /// v.insert(1i); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + #[inline] + pub fn clear(&mut self) { self.map.clear() } + + /// Returns `true` if the set contains a value. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let set: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// assert_eq!(set.contains(&1), true); + /// assert_eq!(set.contains(&4), false); + /// ``` + #[inline] + pub fn contains(&self, value: &T) -> bool { + self.map.contains_key(value) + } + + /// Returns `true` if the set has no elements in common with `other`. + /// This is equivalent to checking for an empty intersection. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let a: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let mut b: TreeSet = TreeSet::new(); + /// + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(4); + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(1); + /// assert_eq!(a.is_disjoint(&b), false); + /// ``` + pub fn is_disjoint(&self, other: &TreeSet) -> bool { + self.intersection(other).next().is_none() + } + + /// Returns `true` if the set is a subset of another. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let sup: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let mut set: TreeSet = TreeSet::new(); + /// + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(2); + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(4); + /// assert_eq!(set.is_subset(&sup), false); + /// ``` + pub fn is_subset(&self, other: &TreeSet) -> bool { + let mut x = self.iter(); + let mut y = other.iter(); + let mut a = x.next(); + let mut b = y.next(); + while a.is_some() { + if b.is_none() { + return false; + } + + let a1 = a.unwrap(); + let b1 = b.unwrap(); + + match b1.cmp(a1) { + Less => (), + Greater => return false, + Equal => a = x.next(), + } + + b = y.next(); + } + true + } + + /// Returns `true` if the set is a superset of another. + /// + /// # Example + /// + /// ``` + /// use std::collections::TreeSet; + /// + /// let sub: TreeSet = [1i, 2].iter().map(|&x| x).collect(); + /// let mut set: TreeSet = TreeSet::new(); + /// + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(0); + /// set.insert(1); + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(2); + /// assert_eq!(set.is_superset(&sub), true); + /// ``` + pub fn is_superset(&self, other: &TreeSet) -> bool { + other.is_subset(self) + } + + /// Adds a value to the set. Returns `true` if the value was not already + /// present in the set. + /// + /// # Example + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// assert_eq!(set.insert(2i), true); + /// assert_eq!(set.insert(2i), false); + /// assert_eq!(set.len(), 1); + /// ``` + #[inline] + pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } + + /// Removes a value from the set. Returns `true` if the value was + /// present in the set. + /// + /// # Example + /// + /// ``` + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// set.insert(2i); + /// assert_eq!(set.remove(&2), true); + /// assert_eq!(set.remove(&2), false); + /// ``` + #[inline] + pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } +} + +/// A lazy forward iterator over a set. +pub struct SetItems<'a, T:'a> { + iter: Entries<'a, T, ()> +} + +/// A lazy backward iterator over a set. +pub struct RevSetItems<'a, T:'a> { + iter: RevEntries<'a, T, ()> +} + +/// A lazy forward iterator over a set that consumes the set while iterating. +pub type MoveSetItems = iter::Map<'static, (T, ()), T, MoveEntries>; + +/// A lazy iterator producing elements in the set difference (in-order). +pub struct DifferenceItems<'a, T:'a> { + a: Peekable<&'a T, SetItems<'a, T>>, + b: Peekable<&'a T, SetItems<'a, T>>, +} + +/// A lazy iterator producing elements in the set symmetric difference (in-order). +pub struct SymDifferenceItems<'a, T:'a> { + a: Peekable<&'a T, SetItems<'a, T>>, + b: Peekable<&'a T, SetItems<'a, T>>, +} + +/// A lazy iterator producing elements in the set intersection (in-order). +pub struct IntersectionItems<'a, T:'a> { + a: Peekable<&'a T, SetItems<'a, T>>, + b: Peekable<&'a T, SetItems<'a, T>>, +} + +/// A lazy iterator producing elements in the set union (in-order). +pub struct UnionItems<'a, T:'a> { + a: Peekable<&'a T, SetItems<'a, T>>, + b: Peekable<&'a T, SetItems<'a, T>>, +} + +/// Compare `x` and `y`, but return `short` if x is None and `long` if y is None +fn cmp_opt(x: Option<&T>, y: Option<&T>, + short: Ordering, long: Ordering) -> Ordering { + match (x, y) { + (None , _ ) => short, + (_ , None ) => long, + (Some(x1), Some(y1)) => x1.cmp(y1), + } +} + + +impl<'a, T> Iterator<&'a T> for SetItems<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a T> { + self.iter.next().map(|(value, _)| value) + } +} + +impl<'a, T> Iterator<&'a T> for RevSetItems<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a T> { + self.iter.next().map(|(value, _)| value) + } +} + +impl<'a, T: Ord> Iterator<&'a T> for DifferenceItems<'a, T> { + fn next(&mut self) -> Option<&'a T> { + loop { + match cmp_opt(self.a.peek(), self.b.peek(), Less, Less) { + Less => return self.a.next(), + Equal => { self.a.next(); self.b.next(); } + Greater => { self.b.next(); } + } + } + } +} + +impl<'a, T: Ord> Iterator<&'a T> for SymDifferenceItems<'a, T> { + fn next(&mut self) -> Option<&'a T> { + loop { + match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { + Less => return self.a.next(), + Equal => { self.a.next(); self.b.next(); } + Greater => return self.b.next(), + } + } + } +} + +impl<'a, T: Ord> Iterator<&'a T> for IntersectionItems<'a, T> { + fn next(&mut self) -> Option<&'a T> { + loop { + let o_cmp = match (self.a.peek(), self.b.peek()) { + (None , _ ) => None, + (_ , None ) => None, + (Some(a1), Some(b1)) => Some(a1.cmp(b1)), + }; + match o_cmp { + None => return None, + Some(Less) => { self.a.next(); } + Some(Equal) => { self.b.next(); return self.a.next() } + Some(Greater) => { self.b.next(); } + } + } + } +} + +impl<'a, T: Ord> Iterator<&'a T> for UnionItems<'a, T> { + fn next(&mut self) -> Option<&'a T> { + loop { + match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { + Less => return self.a.next(), + Equal => { self.b.next(); return self.a.next() } + Greater => return self.b.next(), + } + } + } +} + +impl FromIterator for TreeSet { + fn from_iter>(iter: Iter) -> TreeSet { + let mut set = TreeSet::new(); + set.extend(iter); + set + } +} + +impl Extendable for TreeSet { + #[inline] + fn extend>(&mut self, mut iter: Iter) { + for elem in iter { + self.insert(elem); + } + } +} + +impl> Hash for TreeSet { + fn hash(&self, state: &mut S) { + for elt in self.iter() { + elt.hash(state); + } + } +} + +#[cfg(test)] +mod test { + use std::prelude::*; + use std::hash; + + use super::TreeSet; + + #[test] + fn test_clear() { + let mut s = TreeSet::new(); + s.clear(); + assert!(s.insert(5i)); + assert!(s.insert(12)); + assert!(s.insert(19)); + s.clear(); + assert!(!s.contains(&5)); + assert!(!s.contains(&12)); + assert!(!s.contains(&19)); + assert!(s.is_empty()); + } + + #[test] + fn test_disjoint() { + let mut xs = TreeSet::new(); + let mut ys = TreeSet::new(); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert(5i)); + assert!(ys.insert(11i)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert(7)); + assert!(xs.insert(19)); + assert!(xs.insert(4)); + assert!(ys.insert(2)); + assert!(ys.insert(-11)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(ys.insert(7)); + assert!(!xs.is_disjoint(&ys)); + assert!(!ys.is_disjoint(&xs)); + } + + #[test] + fn test_subset_and_superset() { + let mut a = TreeSet::new(); + assert!(a.insert(0i)); + assert!(a.insert(5)); + assert!(a.insert(11)); + assert!(a.insert(7)); + + let mut b = TreeSet::new(); + assert!(b.insert(0i)); + assert!(b.insert(7)); + assert!(b.insert(19)); + assert!(b.insert(250)); + assert!(b.insert(11)); + assert!(b.insert(200)); + + assert!(!a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(!b.is_superset(&a)); + + assert!(b.insert(5)); + + assert!(a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(b.is_superset(&a)); + } + + #[test] + fn test_iterator() { + let mut m = TreeSet::new(); + + assert!(m.insert(3i)); + assert!(m.insert(0)); + assert!(m.insert(4)); + assert!(m.insert(2)); + assert!(m.insert(1)); + + let mut n = 0; + for x in m.iter() { + assert_eq!(*x, n); + n += 1 + } + } + + #[test] + fn test_rev_iter() { + let mut m = TreeSet::new(); + + assert!(m.insert(3i)); + assert!(m.insert(0)); + assert!(m.insert(4)); + assert!(m.insert(2)); + assert!(m.insert(1)); + + let mut n = 4; + for x in m.rev_iter() { + assert_eq!(*x, n); + n -= 1; + } + } + + #[test] + fn test_move_iter() { + let s: TreeSet = range(0i, 5).collect(); + + let mut n = 0; + for x in s.into_iter() { + assert_eq!(x, n); + n += 1; + } + } + + #[test] + fn test_move_iter_size_hint() { + let s: TreeSet = vec!(0i, 1).into_iter().collect(); + + let mut it = s.into_iter(); + + assert_eq!(it.size_hint(), (2, Some(2))); + assert!(it.next() != None); + + assert_eq!(it.size_hint(), (1, Some(1))); + assert!(it.next() != None); + + assert_eq!(it.size_hint(), (0, Some(0))); + assert_eq!(it.next(), None); + } + + #[test] + fn test_clone_eq() { + let mut m = TreeSet::new(); + + m.insert(1i); + m.insert(2); + + assert!(m.clone() == m); + } + + #[test] + fn test_hash() { + let mut x = TreeSet::new(); + let mut y = TreeSet::new(); + + x.insert(1i); + x.insert(2); + x.insert(3); + + y.insert(3i); + y.insert(2); + y.insert(1); + + assert!(hash::hash(&x) == hash::hash(&y)); + } + + fn check(a: &[int], + b: &[int], + expected: &[int], + f: |&TreeSet, &TreeSet, f: |&int| -> bool| -> bool) { + let mut set_a = TreeSet::new(); + let mut set_b = TreeSet::new(); + + for x in a.iter() { assert!(set_a.insert(*x)) } + for y in b.iter() { assert!(set_b.insert(*y)) } + + let mut i = 0; + f(&set_a, &set_b, |x| { + assert_eq!(*x, expected[i]); + i += 1; + true + }); + assert_eq!(i, expected.len()); + } + + #[test] + fn test_intersection() { + fn check_intersection(a: &[int], b: &[int], expected: &[int]) { + check(a, b, expected, |x, y, f| x.intersection(y).all(f)) + } + + check_intersection([], [], []); + check_intersection([1, 2, 3], [], []); + check_intersection([], [1, 2, 3], []); + check_intersection([2], [1, 2, 3], [2]); + check_intersection([1, 2, 3], [2], [2]); + check_intersection([11, 1, 3, 77, 103, 5, -5], + [2, 11, 77, -9, -42, 5, 3], + [3, 5, 11, 77]); + } + + #[test] + fn test_difference() { + fn check_difference(a: &[int], b: &[int], expected: &[int]) { + check(a, b, expected, |x, y, f| x.difference(y).all(f)) + } + + check_difference([], [], []); + check_difference([1, 12], [], [1, 12]); + check_difference([], [1, 2, 3, 9], []); + check_difference([1, 3, 5, 9, 11], + [3, 9], + [1, 5, 11]); + check_difference([-5, 11, 22, 33, 40, 42], + [-12, -5, 14, 23, 34, 38, 39, 50], + [11, 22, 33, 40, 42]); + } + + #[test] + fn test_symmetric_difference() { + fn check_symmetric_difference(a: &[int], b: &[int], + expected: &[int]) { + check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) + } + + check_symmetric_difference([], [], []); + check_symmetric_difference([1, 2, 3], [2], [1, 3]); + check_symmetric_difference([2], [1, 2, 3], [1, 3]); + check_symmetric_difference([1, 3, 5, 9, 11], + [-2, 3, 9, 14, 22], + [-2, 1, 5, 11, 14, 22]); + } + + #[test] + fn test_union() { + fn check_union(a: &[int], b: &[int], + expected: &[int]) { + check(a, b, expected, |x, y, f| x.union(y).all(f)) + } + + check_union([], [], []); + check_union([1, 2, 3], [2], [1, 2, 3]); + check_union([2], [1, 2, 3], [1, 2, 3]); + check_union([1, 3, 5, 9, 11, 16, 19, 24], + [-2, 1, 5, 9, 13, 19], + [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); + } + + #[test] + fn test_zip() { + let mut x = TreeSet::new(); + x.insert(5u); + x.insert(12u); + x.insert(11u); + + let mut y = TreeSet::new(); + y.insert("foo"); + y.insert("bar"); + + let x = x; + let y = y; + let mut z = x.iter().zip(y.iter()); + + // FIXME: #5801: this needs a type hint to compile... + let result: Option<(&uint, & &'static str)> = z.next(); + assert_eq!(result.unwrap(), (&5u, &("bar"))); + + let result: Option<(&uint, & &'static str)> = z.next(); + assert_eq!(result.unwrap(), (&11u, &("foo"))); + + let result: Option<(&uint, & &'static str)> = z.next(); + assert!(result.is_none()); + } + + #[test] + fn test_from_iter() { + let xs = [1i, 2, 3, 4, 5, 6, 7, 8, 9]; + + let set: TreeSet = xs.iter().map(|&x| x).collect(); + + for x in xs.iter() { + assert!(set.contains(x)); + } + } + + #[test] + fn test_show() { + let mut set: TreeSet = TreeSet::new(); + let empty: TreeSet = TreeSet::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{}", set); + + assert!(set_str == "{1, 2}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } +} diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs deleted file mode 100644 index 7e6efcb3d12..00000000000 --- a/src/libcollections/treemap.rs +++ /dev/null @@ -1,2867 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Maps are collections of unique keys with corresponding values, and sets are -//! just unique keys without a corresponding value. The `Map` and `Set` traits in -//! `std::container` define the basic interface. -//! -//! This crate defines the `TreeMap` and `TreeSet` types. Their keys must implement `Ord`. -//! -//! `TreeMap`s are ordered. -//! -//! ## Example -//! -//! ```{rust} -//! use std::collections::TreeSet; -//! -//! let mut tree_set = TreeSet::new(); -//! -//! tree_set.insert(2i); -//! tree_set.insert(1i); -//! tree_set.insert(3i); -//! -//! for i in tree_set.iter() { -//! println!("{}", i) // prints 1, then 2, then 3 -//! } -//! ``` - -use core::prelude::*; - -use alloc::boxed::Box; -use core::default::Default; -use core::fmt; -use core::fmt::Show; -use core::iter::Peekable; -use core::iter; -use core::mem::{replace, swap}; -use core::ptr; -use std::hash::{Writer, Hash}; - -use vec::Vec; - -/// This is implemented as an AA tree, which is a simplified variation of -/// a red-black tree where red (horizontal) nodes can only be added -/// as a right child. The time complexity is the same, and re-balancing -/// operations are more frequent but also cheaper. -/// -/// # Example -/// -/// ``` -/// use std::collections::TreeMap; -/// -/// let mut map = TreeMap::new(); -/// -/// map.insert(2i, "bar"); -/// map.insert(1i, "foo"); -/// map.insert(3i, "quux"); -/// -/// // In ascending order by keys -/// for (key, value) in map.iter() { -/// println!("{}: {}", key, value); -/// } -/// -/// // Prints 1, 2, 3 -/// for key in map.keys() { -/// println!("{}", key); -/// } -/// -/// // Prints `foo`, `bar`, `quux` -/// for key in map.values() { -/// println!("{}", key); -/// } -/// -/// map.remove(&1); -/// assert_eq!(map.len(), 2); -/// -/// if !map.contains_key(&1) { -/// println!("1 is no more"); -/// } -/// -/// for key in range(0, 4) { -/// match map.find(&key) { -/// Some(val) => println!("{} has a value: {}", key, val), -/// None => println!("{} not in map", key), -/// } -/// } -/// -/// map.clear(); -/// assert!(map.is_empty()); -/// ``` -/// -/// The easiest way to use `TreeMap` with a custom type as keys is to implement `Ord`. -/// We must also implement `PartialEq`, `Eq` and `PartialOrd`. -/// -/// ``` -/// use std::collections::TreeMap; -/// -/// // We need `Eq` and `PartialEq`, these can be derived. -/// #[deriving(Eq, PartialEq)] -/// struct Troll<'a> { -/// name: &'a str, -/// level: uint, -/// } -/// -/// // Implement `Ord` and sort trolls by level. -/// impl<'a> Ord for Troll<'a> { -/// fn cmp(&self, other: &Troll) -> Ordering { -/// // If we swap `self` and `other`, we get descending ordering. -/// self.level.cmp(&other.level) -/// } -/// } -/// -/// // `PartialOrd` needs to be implemented as well. -/// impl<'a> PartialOrd for Troll<'a> { -/// fn partial_cmp(&self, other: &Troll) -> Option { -/// Some(self.cmp(other)) -/// } -/// } -/// -/// // Use a map to store trolls, sorted by level, and track a list of -/// // heroes slain. -/// let mut trolls = TreeMap::new(); -/// -/// trolls.insert(Troll { name: "Orgarr", level: 2 }, -/// vec!["King Karl"]); -/// trolls.insert(Troll { name: "Blargarr", level: 3 }, -/// vec!["Odd"]); -/// trolls.insert(Troll { name: "Kron the Smelly One", level: 4 }, -/// vec!["Omar the Brave", "Peter: Slayer of Trolls"]); -/// trolls.insert(Troll { name: "Wartilda", level: 1 }, -/// vec![]); -/// -/// println!("You are facing {} trolls!", trolls.len()); -/// -/// // Print the trolls, ordered by level with smallest level first -/// for (troll, heroes) in trolls.iter() { -/// let what = if heroes.len() == 1u { "hero" } -/// else { "heroes" }; -/// -/// println!("level {}: '{}' has slain {} {}", -/// troll.level, troll.name, heroes.len(), what); -/// } -/// -/// // Kill all trolls -/// trolls.clear(); -/// assert_eq!(trolls.len(), 0); -/// ``` - -// Future improvements: - -// range search - O(log n) retrieval of an iterator from some key - -// (possibly) implement the overloads Python does for sets: -// * intersection: & -// * difference: - -// * symmetric difference: ^ -// * union: | -// These would be convenient since the methods work like `each` - -#[deriving(Clone)] -pub struct TreeMap { - root: Option>>, - length: uint -} - -impl PartialEq for TreeMap { - fn eq(&self, other: &TreeMap) -> bool { - self.len() == other.len() && - self.iter().zip(other.iter()).all(|(a, b)| a == b) - } -} - -impl Eq for TreeMap {} - -impl PartialOrd for TreeMap { - #[inline] - fn partial_cmp(&self, other: &TreeMap) -> Option { - iter::order::partial_cmp(self.iter(), other.iter()) - } -} - -impl Ord for TreeMap { - #[inline] - fn cmp(&self, other: &TreeMap) -> Ordering { - iter::order::cmp(self.iter(), other.iter()) - } -} - -impl Show for TreeMap { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, (k, v)) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}: {}", *k, *v)); - } - - write!(f, "}}") - } -} - -impl Default for TreeMap { - #[inline] - fn default() -> TreeMap { TreeMap::new() } -} - -impl Index for TreeMap { - #[inline] - fn index<'a>(&'a self, i: &K) -> &'a V { - self.find(i).expect("no entry found for key") - } -} - -impl IndexMut for TreeMap { - #[inline] - fn index_mut<'a>(&'a mut self, i: &K) -> &'a mut V { - self.find_mut(i).expect("no entry found for key") - } -} - -impl TreeMap { - /// Creates an empty `TreeMap`. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// let mut map: TreeMap<&str, int> = TreeMap::new(); - /// ``` - pub fn new() -> TreeMap { TreeMap{root: None, length: 0} } - - /// Gets a lazy iterator over the keys in the map, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// let mut map = TreeMap::new(); - /// map.insert("a", 1i); - /// map.insert("c", 3i); - /// map.insert("b", 2i); - /// - /// // Print "a", "b", "c" in order. - /// for x in map.keys() { - /// println!("{}", x); - /// } - /// ``` - pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { - self.iter().map(|(k, _v)| k) - } - - /// Gets a lazy iterator over the values in the map, in ascending order - /// with respect to the corresponding keys. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// let mut map = TreeMap::new(); - /// map.insert("a", 1i); - /// map.insert("c", 3i); - /// map.insert("b", 2i); - /// - /// // Print 1, 2, 3 ordered by keys. - /// for x in map.values() { - /// println!("{}", x); - /// } - /// ``` - pub fn values<'a>(&'a self) -> Values<'a, K, V> { - self.iter().map(|(_k, v)| v) - } - - /// Gets a lazy iterator over the key-value pairs in the map, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// let mut map = TreeMap::new(); - /// map.insert("a", 1i); - /// map.insert("c", 3i); - /// map.insert("b", 2i); - /// - /// // Print contents in ascending order - /// for (key, value) in map.iter() { - /// println!("{}: {}", key, value); - /// } - /// ``` - pub fn iter<'a>(&'a self) -> Entries<'a, K, V> { - Entries { - stack: vec!(), - node: deref(&self.root), - remaining_min: self.length, - remaining_max: self.length - } - } - - /// Gets a lazy reverse iterator over the key-value pairs in the map, in descending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// let mut map = TreeMap::new(); - /// map.insert("a", 1i); - /// map.insert("c", 3i); - /// map.insert("b", 2i); - /// - /// // Print contents in descending order - /// for (key, value) in map.rev_iter() { - /// println!("{}: {}", key, value); - /// } - /// ``` - pub fn rev_iter<'a>(&'a self) -> RevEntries<'a, K, V> { - RevEntries{iter: self.iter()} - } - - /// Gets a lazy forward iterator over the key-value pairs in the - /// map, with the values being mutable. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// let mut map = TreeMap::new(); - /// map.insert("a", 1i); - /// map.insert("c", 3i); - /// map.insert("b", 2i); - /// - /// // Add 10 until we find "b" - /// for (key, value) in map.iter_mut() { - /// *value += 10; - /// if key == &"b" { break } - /// } - /// - /// assert_eq!(map.find(&"a"), Some(&11)); - /// assert_eq!(map.find(&"b"), Some(&12)); - /// assert_eq!(map.find(&"c"), Some(&3)); - /// ``` - pub fn iter_mut<'a>(&'a mut self) -> MutEntries<'a, K, V> { - MutEntries { - stack: vec!(), - node: deref_mut(&mut self.root), - remaining_min: self.length, - remaining_max: self.length - } - } - - /// Gets a lazy reverse iterator over the key-value pairs in the - /// map, with the values being mutable. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// let mut map = TreeMap::new(); - /// map.insert("a", 1i); - /// map.insert("c", 3i); - /// map.insert("b", 2i); - /// - /// // Add 10 until we find "b" - /// for (key, value) in map.rev_iter_mut() { - /// *value += 10; - /// if key == &"b" { break } - /// } - /// - /// assert_eq!(map.find(&"a"), Some(&1)); - /// assert_eq!(map.find(&"b"), Some(&12)); - /// assert_eq!(map.find(&"c"), Some(&13)); - /// ``` - pub fn rev_iter_mut<'a>(&'a mut self) -> RevMutEntries<'a, K, V> { - RevMutEntries{iter: self.iter_mut()} - } - - /// Gets a lazy iterator that consumes the treemap. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// let mut map = TreeMap::new(); - /// map.insert("a", 1i); - /// map.insert("c", 3i); - /// map.insert("b", 2i); - /// - /// // Not possible with a regular `.iter()` - /// let vec: Vec<(&str, int)> = map.into_iter().collect(); - /// assert_eq!(vec, vec![("a", 1), ("b", 2), ("c", 3)]); - /// ``` - pub fn into_iter(self) -> MoveEntries { - let TreeMap { root, length } = self; - let stk = match root { - None => vec!(), - Some(box tn) => vec!(tn) - }; - MoveEntries { - stack: stk, - remaining: length - } - } - - /// Return the number of elements in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut a = TreeMap::new(); - /// assert_eq!(a.len(), 0); - /// a.insert(1u, "a"); - /// assert_eq!(a.len(), 1); - /// ``` - pub fn len(&self) -> uint { self.length } - - /// Return true if the map contains no elements. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut a = TreeMap::new(); - /// assert!(a.is_empty()); - /// a.insert(1u, "a"); - /// assert!(!a.is_empty()); - /// ``` - #[inline] - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears the map, removing all values. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut a = TreeMap::new(); - /// a.insert(1u, "a"); - /// a.clear(); - /// assert!(a.is_empty()); - /// ``` - pub fn clear(&mut self) { - self.root = None; - self.length = 0 - } - - /// Returns a reference to the value corresponding to the key. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// map.insert(1u, "a"); - /// assert_eq!(map.find(&1), Some(&"a")); - /// assert_eq!(map.find(&2), None); - /// ``` - #[inline] - pub fn find<'a>(&'a self, key: &K) -> Option<&'a V> { - tree_find_with(&self.root, |k2| key.cmp(k2)) - } - - /// Returns true if the map contains a value for the specified key. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// map.insert(1u, "a"); - /// assert_eq!(map.contains_key(&1), true); - /// assert_eq!(map.contains_key(&2), false); - /// ``` - #[inline] - pub fn contains_key(&self, key: &K) -> bool { - self.find(key).is_some() - } - - /// Returns a mutable reference to the value corresponding to the key. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// map.insert(1u, "a"); - /// match map.find_mut(&1) { - /// Some(x) => *x = "b", - /// None => (), - /// } - /// assert_eq!(map[1], "b"); - /// ``` - #[inline] - pub fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V> { - tree_find_with_mut(&mut self.root, |x| key.cmp(x)) - } - - /// Inserts a key-value pair into the map. An existing value for a - /// key is replaced by the new value. Returns `true` if the key did - /// not already exist in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// assert_eq!(map.insert(2u, "value"), true); - /// assert_eq!(map.insert(2, "value2"), false); - /// assert_eq!(map[2], "value2"); - /// ``` - #[inline] - pub fn insert(&mut self, key: K, value: V) -> bool { - self.swap(key, value).is_none() - } - - /// Removes a key-value pair from the map. Returns `true` if the key - /// was present in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// assert_eq!(map.remove(&1u), false); - /// map.insert(1, "a"); - /// assert_eq!(map.remove(&1), true); - /// ``` - #[inline] - pub fn remove(&mut self, key: &K) -> bool { - self.pop(key).is_some() - } - - /// Inserts a key-value pair from the map. If the key already had a value - /// present in the map, that value is returned. Otherwise, `None` is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// assert_eq!(map.swap(37u, "a"), None); - /// assert_eq!(map.is_empty(), false); - /// - /// map.insert(37, "b"); - /// assert_eq!(map.swap(37, "c"), Some("b")); - /// assert_eq!(map[37], "c"); - /// ``` - pub fn swap(&mut self, key: K, value: V) -> Option { - let ret = insert(&mut self.root, key, value); - if ret.is_none() { self.length += 1 } - ret - } - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// map.insert(1u, "a"); - /// assert_eq!(map.pop(&1), Some("a")); - /// assert_eq!(map.pop(&1), None); - /// ``` - pub fn pop(&mut self, key: &K) -> Option { - let ret = remove(&mut self.root, key); - if ret.is_some() { self.length -= 1 } - ret - } -} - -impl TreeMap { - /// Returns the value for which `f(key)` returns `Equal`. `f` is invoked - /// with current key and guides tree navigation. That means `f` should - /// be aware of natural ordering of the tree. - /// - /// # Example - /// - /// ``` - /// use collections::treemap::TreeMap; - /// - /// fn get_headers() -> TreeMap { - /// let mut result = TreeMap::new(); - /// result.insert("Content-Type".to_string(), "application/xml".to_string()); - /// result.insert("User-Agent".to_string(), "Curl-Rust/0.1".to_string()); - /// result - /// } - /// - /// let headers = get_headers(); - /// let ua_key = "User-Agent"; - /// let ua = headers.find_with(|k| { - /// ua_key.cmp(&k.as_slice()) - /// }); - /// - /// assert_eq!((*ua.unwrap()).as_slice(), "Curl-Rust/0.1"); - /// ``` - #[inline] - pub fn find_with<'a>(&'a self, f:|&K| -> Ordering) -> Option<&'a V> { - tree_find_with(&self.root, f) - } - - /// Returns the value for which `f(key)` returns `Equal`. `f` is invoked - /// with current key and guides tree navigation. That means `f` should - /// be aware of natural ordering of the tree. - /// - /// # Example - /// - /// ``` - /// let mut t = collections::treemap::TreeMap::new(); - /// t.insert("Content-Type", "application/xml"); - /// t.insert("User-Agent", "Curl-Rust/0.1"); - /// - /// let new_ua = "Safari/156.0"; - /// match t.find_with_mut(|k| "User-Agent".cmp(k)) { - /// Some(x) => *x = new_ua, - /// None => panic!(), - /// } - /// - /// assert_eq!(t.find(&"User-Agent"), Some(&new_ua)); - /// ``` - #[inline] - pub fn find_with_mut<'a>(&'a mut self, f:|&K| -> Ordering) -> Option<&'a mut V> { - tree_find_with_mut(&mut self.root, f) - } -} - -// range iterators. - -macro_rules! bound_setup { - // initialiser of the iterator to manipulate - ($iter:expr, $k:expr, - // whether we are looking for the lower or upper bound. - $is_lower_bound:expr) => { - { - let mut iter = $iter; - loop { - if !iter.node.is_null() { - let node_k = unsafe {&(*iter.node).key}; - match $k.cmp(node_k) { - Less => iter.traverse_left(), - Greater => iter.traverse_right(), - Equal => { - if $is_lower_bound { - iter.traverse_complete(); - return iter; - } else { - iter.traverse_right() - } - } - } - } else { - iter.traverse_complete(); - return iter; - } - } - } - } -} - - -impl TreeMap { - /// Gets a lazy iterator that should be initialized using - /// `traverse_left`/`traverse_right`/`traverse_complete`. - fn iter_for_traversal<'a>(&'a self) -> Entries<'a, K, V> { - Entries { - stack: vec!(), - node: deref(&self.root), - remaining_min: 0, - remaining_max: self.length - } - } - - /// Returns a lazy iterator to the first key-value pair whose key is not less than `k` - /// If all keys in map are less than `k` an empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// map.insert(2i, "a"); - /// map.insert(4, "b"); - /// map.insert(6, "c"); - /// map.insert(8, "d"); - /// - /// assert_eq!(map.lower_bound(&4).next(), Some((&4, &"b"))); - /// assert_eq!(map.lower_bound(&5).next(), Some((&6, &"c"))); - /// assert_eq!(map.lower_bound(&10).next(), None); - /// ``` - pub fn lower_bound<'a>(&'a self, k: &K) -> Entries<'a, K, V> { - bound_setup!(self.iter_for_traversal(), k, true) - } - - /// Returns a lazy iterator to the first key-value pair whose key is greater than `k` - /// If all keys in map are less than or equal to `k` an empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// map.insert(2i, "a"); - /// map.insert(4, "b"); - /// map.insert(6, "c"); - /// map.insert(8, "d"); - /// - /// assert_eq!(map.upper_bound(&4).next(), Some((&6, &"c"))); - /// assert_eq!(map.upper_bound(&5).next(), Some((&6, &"c"))); - /// assert_eq!(map.upper_bound(&10).next(), None); - /// ``` - pub fn upper_bound<'a>(&'a self, k: &K) -> Entries<'a, K, V> { - bound_setup!(self.iter_for_traversal(), k, false) - } - - /// Gets a lazy iterator that should be initialized using - /// `traverse_left`/`traverse_right`/`traverse_complete`. - fn iter_mut_for_traversal<'a>(&'a mut self) -> MutEntries<'a, K, V> { - MutEntries { - stack: vec!(), - node: deref_mut(&mut self.root), - remaining_min: 0, - remaining_max: self.length - } - } - - /// Returns a lazy value iterator to the first key-value pair (with - /// the value being mutable) whose key is not less than `k`. - /// - /// If all keys in map are less than `k` an empty iterator is - /// returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// map.insert(2i, "a"); - /// map.insert(4, "b"); - /// map.insert(6, "c"); - /// map.insert(8, "d"); - /// - /// assert_eq!(map.lower_bound_mut(&4).next(), Some((&4, &mut "b"))); - /// assert_eq!(map.lower_bound_mut(&5).next(), Some((&6, &mut "c"))); - /// assert_eq!(map.lower_bound_mut(&10).next(), None); - /// - /// for (key, value) in map.lower_bound_mut(&4) { - /// *value = "changed"; - /// } - /// - /// assert_eq!(map.find(&2), Some(&"a")); - /// assert_eq!(map.find(&4), Some(&"changed")); - /// assert_eq!(map.find(&6), Some(&"changed")); - /// assert_eq!(map.find(&8), Some(&"changed")); - /// ``` - pub fn lower_bound_mut<'a>(&'a mut self, k: &K) -> MutEntries<'a, K, V> { - bound_setup!(self.iter_mut_for_traversal(), k, true) - } - - /// Returns a lazy iterator to the first key-value pair (with the - /// value being mutable) whose key is greater than `k`. - /// - /// If all keys in map are less than or equal to `k` an empty iterator - /// is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeMap; - /// - /// let mut map = TreeMap::new(); - /// map.insert(2i, "a"); - /// map.insert(4, "b"); - /// map.insert(6, "c"); - /// map.insert(8, "d"); - /// - /// assert_eq!(map.upper_bound_mut(&4).next(), Some((&6, &mut "c"))); - /// assert_eq!(map.upper_bound_mut(&5).next(), Some((&6, &mut "c"))); - /// assert_eq!(map.upper_bound_mut(&10).next(), None); - /// - /// for (key, value) in map.upper_bound_mut(&4) { - /// *value = "changed"; - /// } - /// - /// assert_eq!(map.find(&2), Some(&"a")); - /// assert_eq!(map.find(&4), Some(&"b")); - /// assert_eq!(map.find(&6), Some(&"changed")); - /// assert_eq!(map.find(&8), Some(&"changed")); - /// ``` - pub fn upper_bound_mut<'a>(&'a mut self, k: &K) -> MutEntries<'a, K, V> { - bound_setup!(self.iter_mut_for_traversal(), k, false) - } -} - -/// Lazy forward iterator over a map -pub struct Entries<'a, K:'a, V:'a> { - stack: Vec<&'a TreeNode>, - // See the comment on MutEntries; this is just to allow - // code-sharing (for this immutable-values iterator it *could* very - // well be Option<&'a TreeNode>). - node: *const TreeNode, - remaining_min: uint, - remaining_max: uint -} - -/// Lazy backward iterator over a map -pub struct RevEntries<'a, K:'a, V:'a> { - iter: Entries<'a, K, V>, -} - -/// Lazy forward iterator over a map that allows for the mutation of -/// the values. -pub struct MutEntries<'a, K:'a, V:'a> { - stack: Vec<&'a mut TreeNode>, - // Unfortunately, we require some unsafe-ness to get around the - // fact that we would be storing a reference *into* one of the - // nodes in the stack. - // - // As far as the compiler knows, this would let us invalidate the - // reference by assigning a new value to this node's position in - // its parent, which would cause this current one to be - // deallocated so this reference would be invalid. (i.e. the - // compilers complaints are 100% correct.) - // - // However, as far as you humans reading this code know (or are - // about to know, if you haven't read far enough down yet), we are - // only reading from the TreeNode.{left,right} fields. the only - // thing that is ever mutated is the .value field (although any - // actual mutation that happens is done externally, by the - // iterator consumer). So, don't be so concerned, rustc, we've got - // it under control. - // - // (This field can legitimately be null.) - node: *mut TreeNode, - remaining_min: uint, - remaining_max: uint -} - -/// Lazy backward iterator over a map -pub struct RevMutEntries<'a, K:'a, V:'a> { - iter: MutEntries<'a, K, V>, -} - -/// TreeMap keys iterator. -pub type Keys<'a, K, V> = - iter::Map<'static, (&'a K, &'a V), &'a K, Entries<'a, K, V>>; - -/// TreeMap values iterator. -pub type Values<'a, K, V> = - iter::Map<'static, (&'a K, &'a V), &'a V, Entries<'a, K, V>>; - - -// FIXME #5846 we want to be able to choose between &x and &mut x -// (with many different `x`) below, so we need to optionally pass mut -// as a tt, but the only thing we can do with a `tt` is pass them to -// other macros, so this takes the `& ` token -// sequence and forces their evaluation as an expression. -macro_rules! addr { ($e:expr) => { $e }} -// putting an optional mut into type signatures -macro_rules! item { ($i:item) => { $i }} - -macro_rules! define_iterator { - ($name:ident, - $rev_name:ident, - - // the function to go from &m Option> to *m TreeNode - deref = $deref:ident, - - // see comment on `addr!`, this is just an optional `mut`, but - // there's no support for 0-or-1 repeats. - addr_mut = $($addr_mut:tt)* - ) => { - // private methods on the forward iterator (item!() for the - // addr_mut in the next_ return value) - item!(impl<'a, K, V> $name<'a, K, V> { - #[inline(always)] - fn next_(&mut self, forward: bool) -> Option<(&'a K, &'a $($addr_mut)* V)> { - while !self.stack.is_empty() || !self.node.is_null() { - if !self.node.is_null() { - let node = unsafe {addr!(& $($addr_mut)* *self.node)}; - { - let next_node = if forward { - addr!(& $($addr_mut)* node.left) - } else { - addr!(& $($addr_mut)* node.right) - }; - self.node = $deref(next_node); - } - self.stack.push(node); - } else { - let node = self.stack.pop().unwrap(); - let next_node = if forward { - addr!(& $($addr_mut)* node.right) - } else { - addr!(& $($addr_mut)* node.left) - }; - self.node = $deref(next_node); - self.remaining_max -= 1; - if self.remaining_min > 0 { - self.remaining_min -= 1; - } - return Some((&node.key, addr!(& $($addr_mut)* node.value))); - } - } - None - } - - /// traverse_left, traverse_right and traverse_complete are - /// used to initialize Entries/MutEntries - /// pointing to element inside tree structure. - /// - /// They should be used in following manner: - /// - create iterator using TreeMap::[mut_]iter_for_traversal - /// - find required node using `traverse_left`/`traverse_right` - /// (current node is `Entries::node` field) - /// - complete initialization with `traverse_complete` - /// - /// After this, iteration will start from `self.node`. If - /// `self.node` is None iteration will start from last - /// node from which we traversed left. - #[inline] - fn traverse_left(&mut self) { - let node = unsafe {addr!(& $($addr_mut)* *self.node)}; - self.node = $deref(addr!(& $($addr_mut)* node.left)); - self.stack.push(node); - } - - #[inline] - fn traverse_right(&mut self) { - let node = unsafe {addr!(& $($addr_mut)* *self.node)}; - self.node = $deref(addr!(& $($addr_mut)* node.right)); - } - - #[inline] - fn traverse_complete(&mut self) { - if !self.node.is_null() { - unsafe { - self.stack.push(addr!(& $($addr_mut)* *self.node)); - } - self.node = ptr::RawPtr::null(); - } - } - }) - - // the forward Iterator impl. - item!(impl<'a, K, V> Iterator<(&'a K, &'a $($addr_mut)* V)> for $name<'a, K, V> { - /// Advances the iterator to the next node (in order) and return a - /// tuple with a reference to the key and value. If there are no - /// more nodes, return `None`. - fn next(&mut self) -> Option<(&'a K, &'a $($addr_mut)* V)> { - self.next_(true) - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - (self.remaining_min, Some(self.remaining_max)) - } - }) - - // the reverse Iterator impl. - item!(impl<'a, K, V> Iterator<(&'a K, &'a $($addr_mut)* V)> for $rev_name<'a, K, V> { - fn next(&mut self) -> Option<(&'a K, &'a $($addr_mut)* V)> { - self.iter.next_(false) - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - self.iter.size_hint() - } - }) - } -} // end of define_iterator - -define_iterator! { - Entries, - RevEntries, - deref = deref, - - // immutable, so no mut - addr_mut = -} -define_iterator! { - MutEntries, - RevMutEntries, - deref = deref_mut, - - addr_mut = mut -} - -fn deref<'a, K, V>(node: &'a Option>>) -> *const TreeNode { - match *node { - Some(ref n) => { - let n: &TreeNode = &**n; - n as *const TreeNode - } - None => ptr::null() - } -} - -fn deref_mut(x: &mut Option>>) - -> *mut TreeNode { - match *x { - Some(ref mut n) => { - let n: &mut TreeNode = &mut **n; - n as *mut TreeNode - } - None => ptr::null_mut() - } -} - -/// Lazy forward iterator over a map that consumes the map while iterating -pub struct MoveEntries { - stack: Vec>, - remaining: uint -} - -impl Iterator<(K, V)> for MoveEntries { - #[inline] - fn next(&mut self) -> Option<(K, V)> { - while !self.stack.is_empty() { - let TreeNode { - key, - value, - left, - right, - level, - } = self.stack.pop().unwrap(); - - match left { - Some(box left) => { - let n = TreeNode { - key: key, - value: value, - left: None, - right: right, - level: level - }; - self.stack.push(n); - self.stack.push(left); - } - None => { - match right { - Some(box right) => self.stack.push(right), - None => () - } - self.remaining -= 1; - return Some((key, value)) - } - } - } - None - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - (self.remaining, Some(self.remaining)) - } - -} - -impl<'a, T> Iterator<&'a T> for SetItems<'a, T> { - #[inline] - fn next(&mut self) -> Option<&'a T> { - self.iter.next().map(|(value, _)| value) - } -} - -impl<'a, T> Iterator<&'a T> for RevSetItems<'a, T> { - #[inline] - fn next(&mut self) -> Option<&'a T> { - self.iter.next().map(|(value, _)| value) - } -} - -/// An implementation of the `Set` trait on top of the `TreeMap` container. The -/// only requirement is that the type of the elements contained ascribes to the -/// `Ord` trait. -/// -/// ## Example -/// -/// ```{rust} -/// use std::collections::TreeSet; -/// -/// let mut set = TreeSet::new(); -/// -/// set.insert(2i); -/// set.insert(1i); -/// set.insert(3i); -/// -/// for i in set.iter() { -/// println!("{}", i) // prints 1, then 2, then 3 -/// } -/// -/// set.remove(&3); -/// -/// if !set.contains(&3) { -/// println!("set does not contain a 3 anymore"); -/// } -/// ``` -/// -/// The easiest way to use `TreeSet` with a custom type is to implement `Ord`. -/// We must also implement `PartialEq`, `Eq` and `PartialOrd`. -/// -/// ``` -/// use std::collections::TreeSet; -/// -/// // We need `Eq` and `PartialEq`, these can be derived. -/// #[deriving(Eq, PartialEq)] -/// struct Troll<'a> { -/// name: &'a str, -/// level: uint, -/// } -/// -/// // Implement `Ord` and sort trolls by level. -/// impl<'a> Ord for Troll<'a> { -/// fn cmp(&self, other: &Troll) -> Ordering { -/// // If we swap `self` and `other`, we get descending ordering. -/// self.level.cmp(&other.level) -/// } -/// } -/// -/// // `PartialOrd` needs to be implemented as well. -/// impl<'a> PartialOrd for Troll<'a> { -/// fn partial_cmp(&self, other: &Troll) -> Option { -/// Some(self.cmp(other)) -/// } -/// } -/// -/// let mut trolls = TreeSet::new(); -/// -/// trolls.insert(Troll { name: "Orgarr", level: 2 }); -/// trolls.insert(Troll { name: "Blargarr", level: 3 }); -/// trolls.insert(Troll { name: "Kron the Smelly One", level: 4 }); -/// trolls.insert(Troll { name: "Wartilda", level: 1 }); -/// -/// println!("You are facing {} trolls!", trolls.len()); -/// -/// // Print the trolls, ordered by level with smallest level first -/// for x in trolls.iter() { -/// println!("level {}: {}!", x.level, x.name); -/// } -/// -/// // Kill all trolls -/// trolls.clear(); -/// assert_eq!(trolls.len(), 0); -/// ``` -#[deriving(Clone)] -pub struct TreeSet { - map: TreeMap -} - -impl PartialEq for TreeSet { - #[inline] - fn eq(&self, other: &TreeSet) -> bool { self.map == other.map } -} - -impl Eq for TreeSet {} - -impl PartialOrd for TreeSet { - #[inline] - fn partial_cmp(&self, other: &TreeSet) -> Option { - self.map.partial_cmp(&other.map) - } -} - -impl Ord for TreeSet { - #[inline] - fn cmp(&self, other: &TreeSet) -> Ordering { - iter::order::cmp(self.iter(), other.iter()) - } -} - -impl Show for TreeSet { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, x) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}", *x)); - } - - write!(f, "}}") - } -} - -impl Default for TreeSet { - #[inline] - fn default() -> TreeSet { TreeSet::new() } -} - -impl TreeSet { - /// Creates an empty `TreeSet`. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let mut set: TreeSet = TreeSet::new(); - /// ``` - #[inline] - pub fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } - - /// Gets a lazy iterator over the values in the set, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); - /// - /// // Will print in ascending order. - /// for x in set.iter() { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn iter<'a>(&'a self) -> SetItems<'a, T> { - SetItems{iter: self.map.iter()} - } - - /// Gets a lazy iterator over the values in the set, in descending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); - /// - /// // Will print in descending order. - /// for x in set.rev_iter() { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn rev_iter<'a>(&'a self) -> RevSetItems<'a, T> { - RevSetItems{iter: self.map.rev_iter()} - } - - /// Creates a consuming iterator, that is, one that moves each value out of the - /// set in ascending order. The set cannot be used after calling this. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let set: TreeSet = [1i, 4, 3, 5, 2].iter().map(|&x| x).collect(); - /// - /// // Not possible with a regular `.iter()` - /// let v: Vec = set.into_iter().collect(); - /// assert_eq!(v, vec![1, 2, 3, 4, 5]); - /// ``` - #[inline] - pub fn into_iter(self) -> MoveSetItems { - self.map.into_iter().map(|(value, _)| value) - } - - /// Gets a lazy iterator pointing to the first value not less than `v` (greater or equal). - /// If all elements in the set are less than `v` empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let set: TreeSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); - /// - /// assert_eq!(set.lower_bound(&4).next(), Some(&4)); - /// assert_eq!(set.lower_bound(&5).next(), Some(&6)); - /// assert_eq!(set.lower_bound(&10).next(), None); - /// ``` - #[inline] - pub fn lower_bound<'a>(&'a self, v: &T) -> SetItems<'a, T> { - SetItems{iter: self.map.lower_bound(v)} - } - - /// Gets a lazy iterator pointing to the first value greater than `v`. - /// If all elements in the set are less than or equal to `v` an - /// empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// let set: TreeSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); - /// - /// assert_eq!(set.upper_bound(&4).next(), Some(&6)); - /// assert_eq!(set.upper_bound(&5).next(), Some(&6)); - /// assert_eq!(set.upper_bound(&10).next(), None); - /// ``` - #[inline] - pub fn upper_bound<'a>(&'a self, v: &T) -> SetItems<'a, T> { - SetItems{iter: self.map.upper_bound(v)} - } - - /// Visits the values representing the difference, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); - /// - /// // Can be seen as `a - b`. - /// for x in a.difference(&b) { - /// println!("{}", x); // Print 1 then 2 - /// } - /// - /// let diff: TreeSet = a.difference(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1, 2].iter().map(|&x| x).collect()); - /// - /// // Note that difference is not symmetric, - /// // and `b - a` means something else: - /// let diff: TreeSet = b.difference(&a).map(|&x| x).collect(); - /// assert_eq!(diff, [4, 5].iter().map(|&x| x).collect()); - /// ``` - pub fn difference<'a>(&'a self, other: &'a TreeSet) -> DifferenceItems<'a, T> { - DifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Visits the values representing the symmetric difference, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); - /// - /// // Print 1, 2, 4, 5 in ascending order. - /// for x in a.symmetric_difference(&b) { - /// println!("{}", x); - /// } - /// - /// let diff1: TreeSet = a.symmetric_difference(&b).map(|&x| x).collect(); - /// let diff2: TreeSet = b.symmetric_difference(&a).map(|&x| x).collect(); - /// - /// assert_eq!(diff1, diff2); - /// assert_eq!(diff1, [1, 2, 4, 5].iter().map(|&x| x).collect()); - /// ``` - pub fn symmetric_difference<'a>(&'a self, other: &'a TreeSet) - -> SymDifferenceItems<'a, T> { - SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Visits the values representing the intersection, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: TreeSet = [2, 3, 4].iter().map(|&x| x).collect(); - /// - /// // Print 2, 3 in ascending order. - /// for x in a.intersection(&b) { - /// println!("{}", x); - /// } - /// - /// let diff: TreeSet = a.intersection(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [2, 3].iter().map(|&x| x).collect()); - /// ``` - pub fn intersection<'a>(&'a self, other: &'a TreeSet) - -> IntersectionItems<'a, T> { - IntersectionItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Visits the values representing the union, in ascending order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let a: TreeSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let b: TreeSet = [3, 4, 5].iter().map(|&x| x).collect(); - /// - /// // Print 1, 2, 3, 4, 5 in ascending order. - /// for x in a.union(&b) { - /// println!("{}", x); - /// } - /// - /// let diff: TreeSet = a.union(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1, 2, 3, 4, 5].iter().map(|&x| x).collect()); - /// ``` - pub fn union<'a>(&'a self, other: &'a TreeSet) -> UnionItems<'a, T> { - UnionItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Return the number of elements in the set - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let mut v = TreeSet::new(); - /// assert_eq!(v.len(), 0); - /// v.insert(1i); - /// assert_eq!(v.len(), 1); - /// ``` - #[inline] - pub fn len(&self) -> uint { self.map.len() } - - /// Returns true if the set contains no elements - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let mut v = TreeSet::new(); - /// assert!(v.is_empty()); - /// v.insert(1i); - /// assert!(!v.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears the set, removing all values. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let mut v = TreeSet::new(); - /// v.insert(1i); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - #[inline] - pub fn clear(&mut self) { self.map.clear() } - - /// Returns `true` if the set contains a value. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let set: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// assert_eq!(set.contains(&1), true); - /// assert_eq!(set.contains(&4), false); - /// ``` - #[inline] - pub fn contains(&self, value: &T) -> bool { - self.map.contains_key(value) - } - - /// Returns `true` if the set has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let a: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let mut b: TreeSet = TreeSet::new(); - /// - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(4); - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(1); - /// assert_eq!(a.is_disjoint(&b), false); - /// ``` - pub fn is_disjoint(&self, other: &TreeSet) -> bool { - self.intersection(other).next().is_none() - } - - /// Returns `true` if the set is a subset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let sup: TreeSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let mut set: TreeSet = TreeSet::new(); - /// - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(2); - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(4); - /// assert_eq!(set.is_subset(&sup), false); - /// ``` - pub fn is_subset(&self, other: &TreeSet) -> bool { - let mut x = self.iter(); - let mut y = other.iter(); - let mut a = x.next(); - let mut b = y.next(); - while a.is_some() { - if b.is_none() { - return false; - } - - let a1 = a.unwrap(); - let b1 = b.unwrap(); - - match b1.cmp(a1) { - Less => (), - Greater => return false, - Equal => a = x.next(), - } - - b = y.next(); - } - true - } - - /// Returns `true` if the set is a superset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::TreeSet; - /// - /// let sub: TreeSet = [1i, 2].iter().map(|&x| x).collect(); - /// let mut set: TreeSet = TreeSet::new(); - /// - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(0); - /// set.insert(1); - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(2); - /// assert_eq!(set.is_superset(&sub), true); - /// ``` - pub fn is_superset(&self, other: &TreeSet) -> bool { - other.is_subset(self) - } - - /// Adds a value to the set. Returns `true` if the value was not already - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::BTreeSet; - /// - /// let mut set = BTreeSet::new(); - /// - /// assert_eq!(set.insert(2i), true); - /// assert_eq!(set.insert(2i), false); - /// assert_eq!(set.len(), 1); - /// ``` - #[inline] - pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } - - /// Removes a value from the set. Returns `true` if the value was - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::BTreeSet; - /// - /// let mut set = BTreeSet::new(); - /// - /// set.insert(2i); - /// assert_eq!(set.remove(&2), true); - /// assert_eq!(set.remove(&2), false); - /// ``` - #[inline] - pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } -} - -/// A lazy forward iterator over a set. -pub struct SetItems<'a, T:'a> { - iter: Entries<'a, T, ()> -} - -/// A lazy backward iterator over a set. -pub struct RevSetItems<'a, T:'a> { - iter: RevEntries<'a, T, ()> -} - -/// A lazy forward iterator over a set that consumes the set while iterating. -pub type MoveSetItems = iter::Map<'static, (T, ()), T, MoveEntries>; - -/// A lazy iterator producing elements in the set difference (in-order). -pub struct DifferenceItems<'a, T:'a> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, -} - -/// A lazy iterator producing elements in the set symmetric difference (in-order). -pub struct SymDifferenceItems<'a, T:'a> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, -} - -/// A lazy iterator producing elements in the set intersection (in-order). -pub struct IntersectionItems<'a, T:'a> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, -} - -/// A lazy iterator producing elements in the set union (in-order). -pub struct UnionItems<'a, T:'a> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, -} - -/// Compare `x` and `y`, but return `short` if x is None and `long` if y is None -fn cmp_opt(x: Option<&T>, y: Option<&T>, - short: Ordering, long: Ordering) -> Ordering { - match (x, y) { - (None , _ ) => short, - (_ , None ) => long, - (Some(x1), Some(y1)) => x1.cmp(y1), - } -} - -impl<'a, T: Ord> Iterator<&'a T> for DifferenceItems<'a, T> { - fn next(&mut self) -> Option<&'a T> { - loop { - match cmp_opt(self.a.peek(), self.b.peek(), Less, Less) { - Less => return self.a.next(), - Equal => { self.a.next(); self.b.next(); } - Greater => { self.b.next(); } - } - } - } -} - -impl<'a, T: Ord> Iterator<&'a T> for SymDifferenceItems<'a, T> { - fn next(&mut self) -> Option<&'a T> { - loop { - match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { - Less => return self.a.next(), - Equal => { self.a.next(); self.b.next(); } - Greater => return self.b.next(), - } - } - } -} - -impl<'a, T: Ord> Iterator<&'a T> for IntersectionItems<'a, T> { - fn next(&mut self) -> Option<&'a T> { - loop { - let o_cmp = match (self.a.peek(), self.b.peek()) { - (None , _ ) => None, - (_ , None ) => None, - (Some(a1), Some(b1)) => Some(a1.cmp(b1)), - }; - match o_cmp { - None => return None, - Some(Less) => { self.a.next(); } - Some(Equal) => { self.b.next(); return self.a.next() } - Some(Greater) => { self.b.next(); } - } - } - } -} - -impl<'a, T: Ord> Iterator<&'a T> for UnionItems<'a, T> { - fn next(&mut self) -> Option<&'a T> { - loop { - match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { - Less => return self.a.next(), - Equal => { self.b.next(); return self.a.next() } - Greater => return self.b.next(), - } - } - } -} - - -// Nodes keep track of their level in the tree, starting at 1 in the -// leaves and with a red child sharing the level of the parent. -#[deriving(Clone)] -struct TreeNode { - key: K, - value: V, - left: Option>>, - right: Option>>, - level: uint -} - -impl TreeNode { - /// Creates a new tree node. - #[inline] - pub fn new(key: K, value: V) -> TreeNode { - TreeNode{key: key, value: value, left: None, right: None, level: 1} - } -} - -// Remove left horizontal link by rotating right -fn skew(node: &mut Box>) { - if node.left.as_ref().map_or(false, |x| x.level == node.level) { - let mut save = node.left.take().unwrap(); - swap(&mut node.left, &mut save.right); // save.right now None - swap(node, &mut save); - node.right = Some(save); - } -} - -// Remove dual horizontal link by rotating left and increasing level of -// the parent -fn split(node: &mut Box>) { - if node.right.as_ref().map_or(false, - |x| x.right.as_ref().map_or(false, |y| y.level == node.level)) { - let mut save = node.right.take().unwrap(); - swap(&mut node.right, &mut save.left); // save.left now None - save.level += 1; - swap(node, &mut save); - node.left = Some(save); - } -} - -// Next 2 functions have the same convention: comparator gets -// at input current key and returns search_key cmp cur_key -// (i.e. search_key.cmp(&cur_key)) -fn tree_find_with<'r, K, V>(node: &'r Option>>, - f: |&K| -> Ordering) -> Option<&'r V> { - let mut current: &'r Option>> = node; - loop { - match *current { - Some(ref r) => { - match f(&r.key) { - Less => current = &r.left, - Greater => current = &r.right, - Equal => return Some(&r.value) - } - } - None => return None - } - } -} - -// See comments above tree_find_with -fn tree_find_with_mut<'r, K, V>(node: &'r mut Option>>, - f: |&K| -> Ordering) -> Option<&'r mut V> { - - let mut current = node; - loop { - let temp = current; // hack to appease borrowck - match *temp { - Some(ref mut r) => { - match f(&r.key) { - Less => current = &mut r.left, - Greater => current = &mut r.right, - Equal => return Some(&mut r.value) - } - } - None => return None - } - } -} - -fn insert(node: &mut Option>>, - key: K, value: V) -> Option { - match *node { - Some(ref mut save) => { - match key.cmp(&save.key) { - Less => { - let inserted = insert(&mut save.left, key, value); - skew(save); - split(save); - inserted - } - Greater => { - let inserted = insert(&mut save.right, key, value); - skew(save); - split(save); - inserted - } - Equal => { - save.key = key; - Some(replace(&mut save.value, value)) - } - } - } - None => { - *node = Some(box TreeNode::new(key, value)); - None - } - } -} - -fn remove(node: &mut Option>>, - key: &K) -> Option { - fn heir_swap(node: &mut Box>, - child: &mut Option>>) { - // *could* be done without recursion, but it won't borrow check - for x in child.iter_mut() { - if x.right.is_some() { - heir_swap(node, &mut x.right); - } else { - swap(&mut node.key, &mut x.key); - swap(&mut node.value, &mut x.value); - } - } - } - - match *node { - None => { - return None; // bottom of tree - } - Some(ref mut save) => { - let (ret, rebalance) = match key.cmp(&save.key) { - Less => (remove(&mut save.left, key), true), - Greater => (remove(&mut save.right, key), true), - Equal => { - if save.left.is_some() { - if save.right.is_some() { - let mut left = save.left.take().unwrap(); - if left.right.is_some() { - heir_swap(save, &mut left.right); - } else { - swap(&mut save.key, &mut left.key); - swap(&mut save.value, &mut left.value); - } - save.left = Some(left); - (remove(&mut save.left, key), true) - } else { - let new = save.left.take().unwrap(); - let box TreeNode{value, ..} = replace(save, new); - *save = save.left.take().unwrap(); - (Some(value), true) - } - } else if save.right.is_some() { - let new = save.right.take().unwrap(); - let box TreeNode{value, ..} = replace(save, new); - (Some(value), true) - } else { - (None, false) - } - } - }; - - if rebalance { - let left_level = save.left.as_ref().map_or(0, |x| x.level); - let right_level = save.right.as_ref().map_or(0, |x| x.level); - - // re-balance, if necessary - if left_level < save.level - 1 || right_level < save.level - 1 { - save.level -= 1; - - if right_level > save.level { - let save_level = save.level; - for x in save.right.iter_mut() { x.level = save_level } - } - - skew(save); - - for right in save.right.iter_mut() { - skew(right); - for x in right.right.iter_mut() { skew(x) } - } - - split(save); - for x in save.right.iter_mut() { split(x) } - } - - return ret; - } - } - } - return match node.take() { - Some(box TreeNode{value, ..}) => Some(value), None => panic!() - }; -} - -impl FromIterator<(K, V)> for TreeMap { - fn from_iter>(iter: T) -> TreeMap { - let mut map = TreeMap::new(); - map.extend(iter); - map - } -} - -impl Extendable<(K, V)> for TreeMap { - #[inline] - fn extend>(&mut self, mut iter: T) { - for (k, v) in iter { - self.insert(k, v); - } - } -} - -impl, V: Hash> Hash for TreeMap { - fn hash(&self, state: &mut S) { - for elt in self.iter() { - elt.hash(state); - } - } -} - -impl FromIterator for TreeSet { - fn from_iter>(iter: Iter) -> TreeSet { - let mut set = TreeSet::new(); - set.extend(iter); - set - } -} - -impl Extendable for TreeSet { - #[inline] - fn extend>(&mut self, mut iter: Iter) { - for elem in iter { - self.insert(elem); - } - } -} - -impl> Hash for TreeSet { - fn hash(&self, state: &mut S) { - for elt in self.iter() { - elt.hash(state); - } - } -} - -#[cfg(test)] -mod test_treemap { - use std::prelude::*; - use std::rand::Rng; - use std::rand; - - use super::{TreeMap, TreeNode}; - - #[test] - fn find_empty() { - let m: TreeMap = TreeMap::new(); - assert!(m.find(&5) == None); - } - - #[test] - fn find_not_found() { - let mut m = TreeMap::new(); - assert!(m.insert(1i, 2i)); - assert!(m.insert(5i, 3i)); - assert!(m.insert(9i, 3i)); - assert_eq!(m.find(&2), None); - } - - #[test] - fn find_with_empty() { - let m: TreeMap<&'static str,int> = TreeMap::new(); - assert!(m.find_with(|k| "test".cmp(k)) == None); - } - - #[test] - fn find_with_not_found() { - let mut m = TreeMap::new(); - assert!(m.insert("test1", 2i)); - assert!(m.insert("test2", 3i)); - assert!(m.insert("test3", 3i)); - assert_eq!(m.find_with(|k| "test4".cmp(k)), None); - } - - #[test] - fn find_with_found() { - let mut m = TreeMap::new(); - assert!(m.insert("test1", 2i)); - assert!(m.insert("test2", 3i)); - assert!(m.insert("test3", 4i)); - assert_eq!(m.find_with(|k| "test2".cmp(k)), Some(&3i)); - } - - #[test] - fn test_find_mut() { - let mut m = TreeMap::new(); - assert!(m.insert(1i, 12i)); - assert!(m.insert(2, 8)); - assert!(m.insert(5, 14)); - let new = 100; - match m.find_mut(&5) { - None => panic!(), Some(x) => *x = new - } - assert_eq!(m.find(&5), Some(&new)); - } - - #[test] - fn test_find_with_mut() { - let mut m = TreeMap::new(); - assert!(m.insert("t1", 12i)); - assert!(m.insert("t2", 8)); - assert!(m.insert("t5", 14)); - let new = 100; - match m.find_with_mut(|k| "t5".cmp(k)) { - None => panic!(), Some(x) => *x = new - } - assert_eq!(m.find_with(|k| "t5".cmp(k)), Some(&new)); - } - - #[test] - fn insert_replace() { - let mut m = TreeMap::new(); - assert!(m.insert(5i, 2i)); - assert!(m.insert(2, 9)); - assert!(!m.insert(2, 11)); - assert_eq!(m.find(&2).unwrap(), &11); - } - - #[test] - fn test_clear() { - let mut m = TreeMap::new(); - m.clear(); - assert!(m.insert(5i, 11i)); - assert!(m.insert(12, -3)); - assert!(m.insert(19, 2)); - m.clear(); - assert!(m.find(&5).is_none()); - assert!(m.find(&12).is_none()); - assert!(m.find(&19).is_none()); - assert!(m.is_empty()); - } - - #[test] - fn u8_map() { - let mut m = TreeMap::new(); - - let k1 = "foo".as_bytes(); - let k2 = "bar".as_bytes(); - let v1 = "baz".as_bytes(); - let v2 = "foobar".as_bytes(); - - m.insert(k1.clone(), v1.clone()); - m.insert(k2.clone(), v2.clone()); - - assert_eq!(m.find(&k2), Some(&v2)); - assert_eq!(m.find(&k1), Some(&v1)); - } - - fn check_equal(ctrl: &[(K, V)], - map: &TreeMap) { - assert_eq!(ctrl.is_empty(), map.is_empty()); - for x in ctrl.iter() { - let &(ref k, ref v) = x; - assert!(map.find(k).unwrap() == v) - } - for (map_k, map_v) in map.iter() { - let mut found = false; - for x in ctrl.iter() { - let &(ref ctrl_k, ref ctrl_v) = x; - if *map_k == *ctrl_k { - assert!(*map_v == *ctrl_v); - found = true; - break; - } - } - assert!(found); - } - } - - fn check_left(node: &Option>>, - parent: &Box>) { - match *node { - Some(ref r) => { - assert_eq!(r.key.cmp(&parent.key), Less); - assert!(r.level == parent.level - 1); // left is black - check_left(&r.left, r); - check_right(&r.right, r, false); - } - None => assert!(parent.level == 1) // parent is leaf - } - } - - fn check_right(node: &Option>>, - parent: &Box>, - parent_red: bool) { - match *node { - Some(ref r) => { - assert_eq!(r.key.cmp(&parent.key), Greater); - let red = r.level == parent.level; - if parent_red { assert!(!red) } // no dual horizontal links - // Right red or black - assert!(red || r.level == parent.level - 1); - check_left(&r.left, r); - check_right(&r.right, r, red); - } - None => assert!(parent.level == 1) // parent is leaf - } - } - - fn check_structure(map: &TreeMap) { - match map.root { - Some(ref r) => { - check_left(&r.left, r); - check_right(&r.right, r, false); - } - None => () - } - } - - #[test] - fn test_rand_int() { - let mut map: TreeMap = TreeMap::new(); - let mut ctrl = vec![]; - - check_equal(ctrl.as_slice(), &map); - assert!(map.find(&5).is_none()); - - let seed: &[_] = &[42]; - let mut rng: rand::IsaacRng = rand::SeedableRng::from_seed(seed); - - for _ in range(0u, 3) { - for _ in range(0u, 90) { - let k = rng.gen(); - let v = rng.gen(); - if !ctrl.iter().any(|x| x == &(k, v)) { - assert!(map.insert(k, v)); - ctrl.push((k, v)); - check_structure(&map); - check_equal(ctrl.as_slice(), &map); - } - } - - for _ in range(0u, 30) { - let r = rng.gen_range(0, ctrl.len()); - let (key, _) = ctrl.remove(r).unwrap(); - assert!(map.remove(&key)); - check_structure(&map); - check_equal(ctrl.as_slice(), &map); - } - } - } - - #[test] - fn test_len() { - let mut m = TreeMap::new(); - assert!(m.insert(3i, 6i)); - assert_eq!(m.len(), 1); - assert!(m.insert(0, 0)); - assert_eq!(m.len(), 2); - assert!(m.insert(4, 8)); - assert_eq!(m.len(), 3); - assert!(m.remove(&3)); - assert_eq!(m.len(), 2); - assert!(!m.remove(&5)); - assert_eq!(m.len(), 2); - assert!(m.insert(2, 4)); - assert_eq!(m.len(), 3); - assert!(m.insert(1, 2)); - assert_eq!(m.len(), 4); - } - - #[test] - fn test_iterator() { - let mut m = TreeMap::new(); - - assert!(m.insert(3i, 6i)); - assert!(m.insert(0, 0)); - assert!(m.insert(4, 8)); - assert!(m.insert(2, 4)); - assert!(m.insert(1, 2)); - - let mut n = 0; - for (k, v) in m.iter() { - assert_eq!(*k, n); - assert_eq!(*v, n * 2); - n += 1; - } - assert_eq!(n, 5); - } - - #[test] - fn test_interval_iteration() { - let mut m = TreeMap::new(); - for i in range(1i, 100i) { - assert!(m.insert(i * 2, i * 4)); - } - - for i in range(1i, 198i) { - let mut lb_it = m.lower_bound(&i); - let (&k, &v) = lb_it.next().unwrap(); - let lb = i + i % 2; - assert_eq!(lb, k); - assert_eq!(lb * 2, v); - - let mut ub_it = m.upper_bound(&i); - let (&k, &v) = ub_it.next().unwrap(); - let ub = i + 2 - i % 2; - assert_eq!(ub, k); - assert_eq!(ub * 2, v); - } - let mut end_it = m.lower_bound(&199); - assert_eq!(end_it.next(), None); - } - - #[test] - fn test_rev_iter() { - let mut m = TreeMap::new(); - - assert!(m.insert(3i, 6i)); - assert!(m.insert(0, 0)); - assert!(m.insert(4, 8)); - assert!(m.insert(2, 4)); - assert!(m.insert(1, 2)); - - let mut n = 4; - for (k, v) in m.rev_iter() { - assert_eq!(*k, n); - assert_eq!(*v, n * 2); - n -= 1; - } - } - - #[test] - fn test_mut_iter() { - let mut m = TreeMap::new(); - for i in range(0u, 10) { - assert!(m.insert(i, 100 * i)); - } - - for (i, (&k, v)) in m.iter_mut().enumerate() { - *v += k * 10 + i; // 000 + 00 + 0, 100 + 10 + 1, ... - } - - for (&k, &v) in m.iter() { - assert_eq!(v, 111 * k); - } - } - #[test] - fn test_mut_rev_iter() { - let mut m = TreeMap::new(); - for i in range(0u, 10) { - assert!(m.insert(i, 100 * i)); - } - - for (i, (&k, v)) in m.rev_iter_mut().enumerate() { - *v += k * 10 + (9 - i); // 900 + 90 + (9 - 0), 800 + 80 + (9 - 1), ... - } - - for (&k, &v) in m.iter() { - assert_eq!(v, 111 * k); - } - } - - #[test] - fn test_mut_interval_iter() { - let mut m_lower = TreeMap::new(); - let mut m_upper = TreeMap::new(); - for i in range(1i, 100i) { - assert!(m_lower.insert(i * 2, i * 4)); - assert!(m_upper.insert(i * 2, i * 4)); - } - - for i in range(1i, 199) { - let mut lb_it = m_lower.lower_bound_mut(&i); - let (&k, v) = lb_it.next().unwrap(); - let lb = i + i % 2; - assert_eq!(lb, k); - *v -= k; - } - for i in range(0i, 198) { - let mut ub_it = m_upper.upper_bound_mut(&i); - let (&k, v) = ub_it.next().unwrap(); - let ub = i + 2 - i % 2; - assert_eq!(ub, k); - *v -= k; - } - - assert!(m_lower.lower_bound_mut(&199).next().is_none()); - - assert!(m_upper.upper_bound_mut(&198).next().is_none()); - - assert!(m_lower.iter().all(|(_, &x)| x == 0)); - assert!(m_upper.iter().all(|(_, &x)| x == 0)); - } - - #[test] - fn test_keys() { - let vec = vec![(1i, 'a'), (2i, 'b'), (3i, 'c')]; - let map = vec.into_iter().collect::>(); - let keys = map.keys().map(|&k| k).collect::>(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let vec = vec![(1i, 'a'), (2i, 'b'), (3i, 'c')]; - let map = vec.into_iter().collect::>(); - let values = map.values().map(|&v| v).collect::>(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_eq() { - let mut a = TreeMap::new(); - let mut b = TreeMap::new(); - - assert!(a == b); - assert!(a.insert(0i, 5i)); - assert!(a != b); - assert!(b.insert(0, 4)); - assert!(a != b); - assert!(a.insert(5, 19)); - assert!(a != b); - assert!(!b.insert(0, 5)); - assert!(a != b); - assert!(b.insert(5, 19)); - assert!(a == b); - } - - #[test] - fn test_lt() { - let mut a = TreeMap::new(); - let mut b = TreeMap::new(); - - assert!(!(a < b) && !(b < a)); - assert!(b.insert(0i, 5i)); - assert!(a < b); - assert!(a.insert(0, 7)); - assert!(!(a < b) && b < a); - assert!(b.insert(-2, 0)); - assert!(b < a); - assert!(a.insert(-5, 2)); - assert!(a < b); - assert!(a.insert(6, 2)); - assert!(a < b && !(b < a)); - } - - #[test] - fn test_ord() { - let mut a = TreeMap::new(); - let mut b = TreeMap::new(); - - assert!(a <= b && a >= b); - assert!(a.insert(1i, 1i)); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - assert!(b.insert(2, 2)); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - #[test] - fn test_show() { - let mut map: TreeMap = TreeMap::new(); - let empty: TreeMap = TreeMap::new(); - - map.insert(1, 2); - map.insert(3, 4); - - let map_str = format!("{}", map); - - assert!(map_str == "{1: 2, 3: 4}".to_string()); - assert_eq!(format!("{}", empty), "{}".to_string()); - } - - #[test] - fn test_lazy_iterator() { - let mut m = TreeMap::new(); - let (x1, y1) = (2i, 5i); - let (x2, y2) = (9, 12); - let (x3, y3) = (20, -3); - let (x4, y4) = (29, 5); - let (x5, y5) = (103, 3); - - assert!(m.insert(x1, y1)); - assert!(m.insert(x2, y2)); - assert!(m.insert(x3, y3)); - assert!(m.insert(x4, y4)); - assert!(m.insert(x5, y5)); - - let m = m; - let mut a = m.iter(); - - assert_eq!(a.next().unwrap(), (&x1, &y1)); - assert_eq!(a.next().unwrap(), (&x2, &y2)); - assert_eq!(a.next().unwrap(), (&x3, &y3)); - assert_eq!(a.next().unwrap(), (&x4, &y4)); - assert_eq!(a.next().unwrap(), (&x5, &y5)); - - assert!(a.next().is_none()); - - let mut b = m.iter(); - - let expected = [(&x1, &y1), (&x2, &y2), (&x3, &y3), (&x4, &y4), - (&x5, &y5)]; - let mut i = 0; - - for x in b { - assert_eq!(expected[i], x); - i += 1; - - if i == 2 { - break - } - } - - for x in b { - assert_eq!(expected[i], x); - i += 1; - } - } - - #[test] - fn test_from_iter() { - let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: TreeMap = xs.iter().map(|&x| x).collect(); - - for &(k, v) in xs.iter() { - assert_eq!(map.find(&k), Some(&v)); - } - } - - #[test] - fn test_index() { - let mut map: TreeMap = TreeMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - assert_eq!(map[2], 1); - } - - #[test] - #[should_fail] - fn test_index_nonexistent() { - let mut map: TreeMap = TreeMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - map[4]; - } -} - -#[cfg(test)] -mod bench { - use std::prelude::*; - use std::rand::{weak_rng, Rng}; - use test::{Bencher, black_box}; - - use super::TreeMap; - use bench::{insert_rand_n, insert_seq_n, find_rand_n, find_seq_n}; - - #[bench] - pub fn insert_rand_100(b: &mut Bencher) { - let mut m : TreeMap = TreeMap::new(); - insert_rand_n(100, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.remove(&i); }); - } - - #[bench] - pub fn insert_rand_10_000(b: &mut Bencher) { - let mut m : TreeMap = TreeMap::new(); - insert_rand_n(10_000, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.remove(&i); }); - } - - // Insert seq - #[bench] - pub fn insert_seq_100(b: &mut Bencher) { - let mut m : TreeMap = TreeMap::new(); - insert_seq_n(100, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.remove(&i); }); - } - - #[bench] - pub fn insert_seq_10_000(b: &mut Bencher) { - let mut m : TreeMap = TreeMap::new(); - insert_seq_n(10_000, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.remove(&i); }); - } - - // Find rand - #[bench] - pub fn find_rand_100(b: &mut Bencher) { - let mut m : TreeMap = TreeMap::new(); - find_rand_n(100, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.find(&i); }); - } - - #[bench] - pub fn find_rand_10_000(b: &mut Bencher) { - let mut m : TreeMap = TreeMap::new(); - find_rand_n(10_000, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.find(&i); }); - } - - // Find seq - #[bench] - pub fn find_seq_100(b: &mut Bencher) { - let mut m : TreeMap = TreeMap::new(); - find_seq_n(100, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.find(&i); }); - } - - #[bench] - pub fn find_seq_10_000(b: &mut Bencher) { - let mut m : TreeMap = TreeMap::new(); - find_seq_n(10_000, &mut m, b, - |m, i| { m.insert(i, 1); }, - |m, i| { m.find(&i); }); - } - - fn bench_iter(b: &mut Bencher, size: uint) { - let mut map = TreeMap::::new(); - let mut rng = weak_rng(); - - for _ in range(0, size) { - map.swap(rng.gen(), rng.gen()); - } - - b.iter(|| { - for entry in map.iter() { - black_box(entry); - } - }); - } - - #[bench] - pub fn iter_20(b: &mut Bencher) { - bench_iter(b, 20); - } - - #[bench] - pub fn iter_1000(b: &mut Bencher) { - bench_iter(b, 1000); - } - - #[bench] - pub fn iter_100000(b: &mut Bencher) { - bench_iter(b, 100000); - } -} - -#[cfg(test)] -mod test_set { - use std::prelude::*; - use std::hash; - - use super::{TreeMap, TreeSet}; - - #[test] - fn test_clear() { - let mut s = TreeSet::new(); - s.clear(); - assert!(s.insert(5i)); - assert!(s.insert(12)); - assert!(s.insert(19)); - s.clear(); - assert!(!s.contains(&5)); - assert!(!s.contains(&12)); - assert!(!s.contains(&19)); - assert!(s.is_empty()); - } - - #[test] - fn test_disjoint() { - let mut xs = TreeSet::new(); - let mut ys = TreeSet::new(); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(5i)); - assert!(ys.insert(11i)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(7)); - assert!(xs.insert(19)); - assert!(xs.insert(4)); - assert!(ys.insert(2)); - assert!(ys.insert(-11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(ys.insert(7)); - assert!(!xs.is_disjoint(&ys)); - assert!(!ys.is_disjoint(&xs)); - } - - #[test] - fn test_subset_and_superset() { - let mut a = TreeSet::new(); - assert!(a.insert(0i)); - assert!(a.insert(5)); - assert!(a.insert(11)); - assert!(a.insert(7)); - - let mut b = TreeSet::new(); - assert!(b.insert(0i)); - assert!(b.insert(7)); - assert!(b.insert(19)); - assert!(b.insert(250)); - assert!(b.insert(11)); - assert!(b.insert(200)); - - assert!(!a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(!b.is_superset(&a)); - - assert!(b.insert(5)); - - assert!(a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(b.is_superset(&a)); - } - - #[test] - fn test_iterator() { - let mut m = TreeSet::new(); - - assert!(m.insert(3i)); - assert!(m.insert(0)); - assert!(m.insert(4)); - assert!(m.insert(2)); - assert!(m.insert(1)); - - let mut n = 0; - for x in m.iter() { - assert_eq!(*x, n); - n += 1 - } - } - - #[test] - fn test_rev_iter() { - let mut m = TreeSet::new(); - - assert!(m.insert(3i)); - assert!(m.insert(0)); - assert!(m.insert(4)); - assert!(m.insert(2)); - assert!(m.insert(1)); - - let mut n = 4; - for x in m.rev_iter() { - assert_eq!(*x, n); - n -= 1; - } - } - - #[test] - fn test_move_iter() { - let s: TreeSet = range(0i, 5).collect(); - - let mut n = 0; - for x in s.into_iter() { - assert_eq!(x, n); - n += 1; - } - } - - #[test] - fn test_move_iter_size_hint() { - let s: TreeSet = vec!(0i, 1).into_iter().collect(); - - let mut it = s.into_iter(); - - assert_eq!(it.size_hint(), (2, Some(2))); - assert!(it.next() != None); - - assert_eq!(it.size_hint(), (1, Some(1))); - assert!(it.next() != None); - - assert_eq!(it.size_hint(), (0, Some(0))); - assert_eq!(it.next(), None); - } - - #[test] - fn test_clone_eq() { - let mut m = TreeSet::new(); - - m.insert(1i); - m.insert(2); - - assert!(m.clone() == m); - } - - #[test] - fn test_hash() { - let mut x = TreeSet::new(); - let mut y = TreeSet::new(); - - x.insert(1i); - x.insert(2); - x.insert(3); - - y.insert(3i); - y.insert(2); - y.insert(1); - - assert!(hash::hash(&x) == hash::hash(&y)); - } - - fn check(a: &[int], - b: &[int], - expected: &[int], - f: |&TreeSet, &TreeSet, f: |&int| -> bool| -> bool) { - let mut set_a = TreeSet::new(); - let mut set_b = TreeSet::new(); - - for x in a.iter() { assert!(set_a.insert(*x)) } - for y in b.iter() { assert!(set_b.insert(*y)) } - - let mut i = 0; - f(&set_a, &set_b, |x| { - assert_eq!(*x, expected[i]); - i += 1; - true - }); - assert_eq!(i, expected.len()); - } - - #[test] - fn test_intersection() { - fn check_intersection(a: &[int], b: &[int], expected: &[int]) { - check(a, b, expected, |x, y, f| x.intersection(y).all(f)) - } - - check_intersection([], [], []); - check_intersection([1, 2, 3], [], []); - check_intersection([], [1, 2, 3], []); - check_intersection([2], [1, 2, 3], [2]); - check_intersection([1, 2, 3], [2], [2]); - check_intersection([11, 1, 3, 77, 103, 5, -5], - [2, 11, 77, -9, -42, 5, 3], - [3, 5, 11, 77]); - } - - #[test] - fn test_difference() { - fn check_difference(a: &[int], b: &[int], expected: &[int]) { - check(a, b, expected, |x, y, f| x.difference(y).all(f)) - } - - check_difference([], [], []); - check_difference([1, 12], [], [1, 12]); - check_difference([], [1, 2, 3, 9], []); - check_difference([1, 3, 5, 9, 11], - [3, 9], - [1, 5, 11]); - check_difference([-5, 11, 22, 33, 40, 42], - [-12, -5, 14, 23, 34, 38, 39, 50], - [11, 22, 33, 40, 42]); - } - - #[test] - fn test_symmetric_difference() { - fn check_symmetric_difference(a: &[int], b: &[int], - expected: &[int]) { - check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) - } - - check_symmetric_difference([], [], []); - check_symmetric_difference([1, 2, 3], [2], [1, 3]); - check_symmetric_difference([2], [1, 2, 3], [1, 3]); - check_symmetric_difference([1, 3, 5, 9, 11], - [-2, 3, 9, 14, 22], - [-2, 1, 5, 11, 14, 22]); - } - - #[test] - fn test_union() { - fn check_union(a: &[int], b: &[int], - expected: &[int]) { - check(a, b, expected, |x, y, f| x.union(y).all(f)) - } - - check_union([], [], []); - check_union([1, 2, 3], [2], [1, 2, 3]); - check_union([2], [1, 2, 3], [1, 2, 3]); - check_union([1, 3, 5, 9, 11, 16, 19, 24], - [-2, 1, 5, 9, 13, 19], - [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); - } - - #[test] - fn test_zip() { - let mut x = TreeSet::new(); - x.insert(5u); - x.insert(12u); - x.insert(11u); - - let mut y = TreeSet::new(); - y.insert("foo"); - y.insert("bar"); - - let x = x; - let y = y; - let mut z = x.iter().zip(y.iter()); - - // FIXME: #5801: this needs a type hint to compile... - let result: Option<(&uint, & &'static str)> = z.next(); - assert_eq!(result.unwrap(), (&5u, &("bar"))); - - let result: Option<(&uint, & &'static str)> = z.next(); - assert_eq!(result.unwrap(), (&11u, &("foo"))); - - let result: Option<(&uint, & &'static str)> = z.next(); - assert!(result.is_none()); - } - - #[test] - fn test_swap() { - let mut m = TreeMap::new(); - assert_eq!(m.swap(1u, 2i), None); - assert_eq!(m.swap(1u, 3i), Some(2)); - assert_eq!(m.swap(1u, 4i), Some(3)); - } - - #[test] - fn test_pop() { - let mut m = TreeMap::new(); - m.insert(1u, 2i); - assert_eq!(m.pop(&1), Some(2)); - assert_eq!(m.pop(&1), None); - } - - #[test] - fn test_from_iter() { - let xs = [1i, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: TreeSet = xs.iter().map(|&x| x).collect(); - - for x in xs.iter() { - assert!(set.contains(x)); - } - } - - #[test] - fn test_show() { - let mut set: TreeSet = TreeSet::new(); - let empty: TreeSet = TreeSet::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{}", set); - - assert!(set_str == "{1, 2}".to_string()); - assert_eq!(format!("{}", empty), "{}".to_string()); - } -} diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs deleted file mode 100644 index 7a8cc5df55a..00000000000 --- a/src/libcollections/trie.rs +++ /dev/null @@ -1,1899 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Maps are collections of unique keys with corresponding values, and sets are -//! just unique keys without a corresponding value. The `Map` and `Set` traits in -//! `std::container` define the basic interface. -//! -//! This crate defines `TrieMap` and `TrieSet`, which require `uint` keys. -//! -//! `TrieMap` is ordered. - -use core::prelude::*; - -use alloc::boxed::Box; -use core::default::Default; -use core::fmt; -use core::fmt::Show; -use core::mem::zeroed; -use core::mem; -use core::ops::{Slice,SliceMut}; -use core::uint; -use core::iter; -use std::hash::{Writer, Hash}; - -use slice::{Items, MutItems}; -use slice; - -// FIXME: #5244: need to manually update the TrieNode constructor -const SHIFT: uint = 4; -const SIZE: uint = 1 << SHIFT; -const MASK: uint = SIZE - 1; -const NUM_CHUNKS: uint = uint::BITS / SHIFT; - -#[deriving(Clone)] -enum Child { - Internal(Box>), - External(uint, T), - Nothing -} - -/// A map implemented as a radix trie. -/// -/// # Example -/// -/// ``` -/// use std::collections::TrieMap; -/// -/// let mut map = TrieMap::new(); -/// map.insert(27, "Olaf"); -/// map.insert(1, "Edgar"); -/// map.insert(13, "Ruth"); -/// map.insert(1, "Martin"); -/// -/// assert_eq!(map.len(), 3); -/// assert_eq!(map.find(&1), Some(&"Martin")); -/// -/// if !map.contains_key(&90) { -/// println!("Nobody is keyed 90"); -/// } -/// -/// // Update a key -/// match map.find_mut(&1) { -/// Some(value) => *value = "Olga", -/// None => (), -/// } -/// -/// map.remove(&13); -/// assert_eq!(map.len(), 2); -/// -/// // Print the key value pairs, ordered by key. -/// for (key, value) in map.iter() { -/// // Prints `1: Olga` then `27: Olaf` -/// println!("{}: {}", key, value); -/// } -/// -/// map.clear(); -/// assert!(map.is_empty()); -/// ``` -#[deriving(Clone)] -pub struct TrieMap { - root: TrieNode, - length: uint -} - -impl PartialEq for TrieMap { - fn eq(&self, other: &TrieMap) -> bool { - self.len() == other.len() && - self.iter().zip(other.iter()).all(|(a, b)| a == b) - } -} - -impl Eq for TrieMap {} - -impl PartialOrd for TrieMap { - #[inline] - fn partial_cmp(&self, other: &TrieMap) -> Option { - iter::order::partial_cmp(self.iter(), other.iter()) - } -} - -impl Ord for TrieMap { - #[inline] - fn cmp(&self, other: &TrieMap) -> Ordering { - iter::order::cmp(self.iter(), other.iter()) - } -} - -impl Show for TrieMap { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, (k, v)) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}: {}", k, *v)); - } - - write!(f, "}}") - } -} - -impl Default for TrieMap { - #[inline] - fn default() -> TrieMap { TrieMap::new() } -} - -impl TrieMap { - /// Creates an empty `TrieMap`. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// let mut map: TrieMap<&str> = TrieMap::new(); - /// ``` - #[inline] - pub fn new() -> TrieMap { - TrieMap{root: TrieNode::new(), length: 0} - } - - /// Visits all key-value pairs in reverse order. Aborts traversal when `f` returns `false`. - /// Returns `true` if `f` returns `true` for all elements. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// let map: TrieMap<&str> = [(1, "a"), (2, "b"), (3, "c")].iter().map(|&x| x).collect(); - /// - /// let mut vec = Vec::new(); - /// assert_eq!(true, map.each_reverse(|&key, &value| { vec.push((key, value)); true })); - /// assert_eq!(vec, vec![(3, "c"), (2, "b"), (1, "a")]); - /// - /// // Stop when we reach 2 - /// let mut vec = Vec::new(); - /// assert_eq!(false, map.each_reverse(|&key, &value| { vec.push(value); key != 2 })); - /// assert_eq!(vec, vec!["c", "b"]); - /// ``` - #[inline] - pub fn each_reverse<'a>(&'a self, f: |&uint, &'a T| -> bool) -> bool { - self.root.each_reverse(f) - } - - /// Gets an iterator visiting all keys in ascending order by the keys. - /// The iterator's element type is `uint`. - pub fn keys<'r>(&'r self) -> Keys<'r, T> { - self.iter().map(|(k, _v)| k) - } - - /// Gets an iterator visiting all values in ascending order by the keys. - /// The iterator's element type is `&'r T`. - pub fn values<'r>(&'r self) -> Values<'r, T> { - self.iter().map(|(_k, v)| v) - } - - /// Gets an iterator over the key-value pairs in the map, ordered by keys. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// let map: TrieMap<&str> = [(3, "c"), (1, "a"), (2, "b")].iter().map(|&x| x).collect(); - /// - /// for (key, value) in map.iter() { - /// println!("{}: {}", key, value); - /// } - /// ``` - pub fn iter<'a>(&'a self) -> Entries<'a, T> { - let mut iter = unsafe {Entries::new()}; - iter.stack[0] = self.root.children.iter(); - iter.length = 1; - iter.remaining_min = self.length; - iter.remaining_max = self.length; - - iter - } - - /// Gets an iterator over the key-value pairs in the map, with the - /// ability to mutate the values. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// let mut map: TrieMap = [(1, 2), (2, 4), (3, 6)].iter().map(|&x| x).collect(); - /// - /// for (key, value) in map.iter_mut() { - /// *value = -(key as int); - /// } - /// - /// assert_eq!(map.find(&1), Some(&-1)); - /// assert_eq!(map.find(&2), Some(&-2)); - /// assert_eq!(map.find(&3), Some(&-3)); - /// ``` - pub fn iter_mut<'a>(&'a mut self) -> MutEntries<'a, T> { - let mut iter = unsafe {MutEntries::new()}; - iter.stack[0] = self.root.children.iter_mut(); - iter.length = 1; - iter.remaining_min = self.length; - iter.remaining_max = self.length; - - iter - } - - /// Return the number of elements in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// - /// let mut a = TrieMap::new(); - /// assert_eq!(a.len(), 0); - /// a.insert(1, "a"); - /// assert_eq!(a.len(), 1); - /// ``` - #[inline] - pub fn len(&self) -> uint { self.length } - - /// Return true if the map contains no elements. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// - /// let mut a = TrieMap::new(); - /// assert!(a.is_empty()); - /// a.insert(1, "a"); - /// assert!(!a.is_empty()); - /// ``` - #[inline] - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears the map, removing all values. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// - /// let mut a = TrieMap::new(); - /// a.insert(1, "a"); - /// a.clear(); - /// assert!(a.is_empty()); - /// ``` - #[inline] - pub fn clear(&mut self) { - self.root = TrieNode::new(); - self.length = 0; - } - - /// Returns a reference to the value corresponding to the key. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// - /// let mut map = TrieMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.find(&1), Some(&"a")); - /// assert_eq!(map.find(&2), None); - /// ``` - #[inline] - pub fn find<'a>(&'a self, key: &uint) -> Option<&'a T> { - let mut node: &'a TrieNode = &self.root; - let mut idx = 0; - loop { - match node.children[chunk(*key, idx)] { - Internal(ref x) => node = &**x, - External(stored, ref value) => { - if stored == *key { - return Some(value) - } else { - return None - } - } - Nothing => return None - } - idx += 1; - } - } - - /// Returns true if the map contains a value for the specified key. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// - /// let mut map = TrieMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.contains_key(&1), true); - /// assert_eq!(map.contains_key(&2), false); - /// ``` - #[inline] - pub fn contains_key(&self, key: &uint) -> bool { - self.find(key).is_some() - } - - /// Returns a mutable reference to the value corresponding to the key. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// - /// let mut map = TrieMap::new(); - /// map.insert(1, "a"); - /// match map.find_mut(&1) { - /// Some(x) => *x = "b", - /// None => (), - /// } - /// assert_eq!(map[1], "b"); - /// ``` - #[inline] - pub fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut T> { - find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) - } - - /// Inserts a key-value pair into the map. An existing value for a - /// key is replaced by the new value. Returns `true` if the key did - /// not already exist in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// - /// let mut map = TrieMap::new(); - /// assert_eq!(map.insert(2, "value"), true); - /// assert_eq!(map.insert(2, "value2"), false); - /// assert_eq!(map[2], "value2"); - /// ``` - #[inline] - pub fn insert(&mut self, key: uint, value: T) -> bool { - self.swap(key, value).is_none() - } - - /// Removes a key-value pair from the map. Returns `true` if the key - /// was present in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// - /// let mut map = TrieMap::new(); - /// assert_eq!(map.remove(&1), false); - /// map.insert(1, "a"); - /// assert_eq!(map.remove(&1), true); - /// ``` - #[inline] - pub fn remove(&mut self, key: &uint) -> bool { - self.pop(key).is_some() - } - - /// Inserts a key-value pair from the map. If the key already had a value - /// present in the map, that value is returned. Otherwise, `None` is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// - /// let mut map = TrieMap::new(); - /// assert_eq!(map.swap(37, "a"), None); - /// assert_eq!(map.is_empty(), false); - /// - /// map.insert(37, "b"); - /// assert_eq!(map.swap(37, "c"), Some("b")); - /// assert_eq!(map[37], "c"); - /// ``` - pub fn swap(&mut self, key: uint, value: T) -> Option { - let ret = insert(&mut self.root.count, - &mut self.root.children[chunk(key, 0)], - key, value, 1); - if ret.is_none() { self.length += 1 } - ret - } - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// - /// let mut map = TrieMap::new(); - /// map.insert(1, "a"); - /// assert_eq!(map.pop(&1), Some("a")); - /// assert_eq!(map.pop(&1), None); - /// ``` - pub fn pop(&mut self, key: &uint) -> Option { - let ret = remove(&mut self.root.count, - &mut self.root.children[chunk(*key, 0)], - *key, 1); - if ret.is_some() { self.length -= 1 } - ret - } -} - -// FIXME #5846 we want to be able to choose between &x and &mut x -// (with many different `x`) below, so we need to optionally pass mut -// as a tt, but the only thing we can do with a `tt` is pass them to -// other macros, so this takes the `& ` token -// sequence and forces their evaluation as an expression. (see also -// `item!` below.) -macro_rules! addr { ($e:expr) => { $e } } - -macro_rules! bound { - ($iterator_name:ident, - // the current treemap - self = $this:expr, - // the key to look for - key = $key:expr, - // are we looking at the upper bound? - is_upper = $upper:expr, - - // method names for slicing/iterating. - slice_from = $slice_from:ident, - iter = $iter:ident, - - // see the comment on `addr!`, this is just an optional mut, but - // there's no 0-or-1 repeats yet. - mutability = $($mut_:tt)*) => { - { - // # For `mut` - // We need an unsafe pointer here because we are borrowing - // mutable references to the internals of each of these - // mutable nodes, while still using the outer node. - // - // However, we're allowed to flaunt rustc like this because we - // never actually modify the "shape" of the nodes. The only - // place that mutation is can actually occur is of the actual - // values of the TrieMap (as the return value of the - // iterator), i.e. we can never cause a deallocation of any - // TrieNodes so the raw pointer is always valid. - // - // # For non-`mut` - // We like sharing code so much that even a little unsafe won't - // stop us. - let this = $this; - let mut node = unsafe { - mem::transmute::<_, uint>(&this.root) as *mut TrieNode - }; - - let key = $key; - - let mut it = unsafe {$iterator_name::new()}; - // everything else is zero'd, as we want. - it.remaining_max = this.length; - - // this addr is necessary for the `Internal` pattern. - addr!(loop { - let children = unsafe {addr!(& $($mut_)* (*node).children)}; - // it.length is the current depth in the iterator and the - // current depth through the `uint` key we've traversed. - let child_id = chunk(key, it.length); - let (slice_idx, ret) = match children[child_id] { - Internal(ref $($mut_)* n) => { - node = unsafe { - mem::transmute::<_, uint>(&**n) - as *mut TrieNode - }; - (child_id + 1, false) - } - External(stored, _) => { - (if stored < key || ($upper && stored == key) { - child_id + 1 - } else { - child_id - }, true) - } - Nothing => { - (child_id + 1, true) - } - }; - // push to the stack. - it.stack[it.length] = children.$slice_from(&slice_idx).$iter(); - it.length += 1; - if ret { return it } - }) - } - } -} - -impl TrieMap { - // If `upper` is true then returns upper_bound else returns lower_bound. - #[inline] - fn bound<'a>(&'a self, key: uint, upper: bool) -> Entries<'a, T> { - bound!(Entries, self = self, - key = key, is_upper = upper, - slice_from = slice_from_or_fail, iter = iter, - mutability = ) - } - - /// Gets an iterator pointing to the first key-value pair whose key is not less than `key`. - /// If all keys in the map are less than `key` an empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// let map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect(); - /// - /// assert_eq!(map.lower_bound(4).next(), Some((4, &"b"))); - /// assert_eq!(map.lower_bound(5).next(), Some((6, &"c"))); - /// assert_eq!(map.lower_bound(10).next(), None); - /// ``` - pub fn lower_bound<'a>(&'a self, key: uint) -> Entries<'a, T> { - self.bound(key, false) - } - - /// Gets an iterator pointing to the first key-value pair whose key is greater than `key`. - /// If all keys in the map are not greater than `key` an empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// let map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect(); - /// - /// assert_eq!(map.upper_bound(4).next(), Some((6, &"c"))); - /// assert_eq!(map.upper_bound(5).next(), Some((6, &"c"))); - /// assert_eq!(map.upper_bound(10).next(), None); - /// ``` - pub fn upper_bound<'a>(&'a self, key: uint) -> Entries<'a, T> { - self.bound(key, true) - } - // If `upper` is true then returns upper_bound else returns lower_bound. - #[inline] - fn bound_mut<'a>(&'a mut self, key: uint, upper: bool) -> MutEntries<'a, T> { - bound!(MutEntries, self = self, - key = key, is_upper = upper, - slice_from = slice_from_or_fail_mut, iter = iter_mut, - mutability = mut) - } - - /// Gets an iterator pointing to the first key-value pair whose key is not less than `key`. - /// If all keys in the map are less than `key` an empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// let mut map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect(); - /// - /// assert_eq!(map.lower_bound_mut(4).next(), Some((4, &mut "b"))); - /// assert_eq!(map.lower_bound_mut(5).next(), Some((6, &mut "c"))); - /// assert_eq!(map.lower_bound_mut(10).next(), None); - /// - /// for (key, value) in map.lower_bound_mut(4) { - /// *value = "changed"; - /// } - /// - /// assert_eq!(map.find(&2), Some(&"a")); - /// assert_eq!(map.find(&4), Some(&"changed")); - /// assert_eq!(map.find(&6), Some(&"changed")); - /// ``` - pub fn lower_bound_mut<'a>(&'a mut self, key: uint) -> MutEntries<'a, T> { - self.bound_mut(key, false) - } - - /// Gets an iterator pointing to the first key-value pair whose key is greater than `key`. - /// If all keys in the map are not greater than `key` an empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieMap; - /// let mut map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect(); - /// - /// assert_eq!(map.upper_bound_mut(4).next(), Some((6, &mut "c"))); - /// assert_eq!(map.upper_bound_mut(5).next(), Some((6, &mut "c"))); - /// assert_eq!(map.upper_bound_mut(10).next(), None); - /// - /// for (key, value) in map.upper_bound_mut(4) { - /// *value = "changed"; - /// } - /// - /// assert_eq!(map.find(&2), Some(&"a")); - /// assert_eq!(map.find(&4), Some(&"b")); - /// assert_eq!(map.find(&6), Some(&"changed")); - /// ``` - pub fn upper_bound_mut<'a>(&'a mut self, key: uint) -> MutEntries<'a, T> { - self.bound_mut(key, true) - } -} - -impl FromIterator<(uint, T)> for TrieMap { - fn from_iter>(iter: Iter) -> TrieMap { - let mut map = TrieMap::new(); - map.extend(iter); - map - } -} - -impl Extendable<(uint, T)> for TrieMap { - fn extend>(&mut self, mut iter: Iter) { - for (k, v) in iter { - self.insert(k, v); - } - } -} - -impl> Hash for TrieMap { - fn hash(&self, state: &mut S) { - for elt in self.iter() { - elt.hash(state); - } - } -} - -impl Index for TrieMap { - #[inline] - fn index<'a>(&'a self, i: &uint) -> &'a T { - self.find(i).expect("key not present") - } -} - -impl IndexMut for TrieMap { - #[inline] - fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut T { - self.find_mut(i).expect("key not present") - } -} - -/// A set implemented as a radix trie. -/// -/// # Example -/// -/// ``` -/// use std::collections::TrieSet; -/// -/// let mut set = TrieSet::new(); -/// set.insert(6); -/// set.insert(28); -/// set.insert(6); -/// -/// assert_eq!(set.len(), 2); -/// -/// if !set.contains(&3) { -/// println!("3 is not in the set"); -/// } -/// -/// // Print contents in order -/// for x in set.iter() { -/// println!("{}", x); -/// } -/// -/// set.remove(&6); -/// assert_eq!(set.len(), 1); -/// -/// set.clear(); -/// assert!(set.is_empty()); -/// ``` -#[deriving(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct TrieSet { - map: TrieMap<()> -} - -impl Show for TrieSet { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, x) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}", x)); - } - - write!(f, "}}") - } -} - -impl Default for TrieSet { - #[inline] - fn default() -> TrieSet { TrieSet::new() } -} - -impl TrieSet { - /// Creates an empty TrieSet. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// let mut set = TrieSet::new(); - /// ``` - #[inline] - pub fn new() -> TrieSet { - TrieSet{map: TrieMap::new()} - } - - /// Visits all values in reverse order. Aborts traversal when `f` returns `false`. - /// Returns `true` if `f` returns `true` for all elements. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let set: TrieSet = [1, 2, 3, 4, 5].iter().map(|&x| x).collect(); - /// - /// let mut vec = Vec::new(); - /// assert_eq!(true, set.each_reverse(|&x| { vec.push(x); true })); - /// assert_eq!(vec, vec![5, 4, 3, 2, 1]); - /// - /// // Stop when we reach 3 - /// let mut vec = Vec::new(); - /// assert_eq!(false, set.each_reverse(|&x| { vec.push(x); x != 3 })); - /// assert_eq!(vec, vec![5, 4, 3]); - /// ``` - #[inline] - pub fn each_reverse(&self, f: |&uint| -> bool) -> bool { - self.map.each_reverse(|k, _| f(k)) - } - - /// Gets an iterator over the values in the set, in sorted order. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut set = TrieSet::new(); - /// set.insert(3); - /// set.insert(2); - /// set.insert(1); - /// set.insert(2); - /// - /// // Print 1, 2, 3 - /// for x in set.iter() { - /// println!("{}", x); - /// } - /// ``` - #[inline] - pub fn iter<'a>(&'a self) -> SetItems<'a> { - SetItems{iter: self.map.iter()} - } - - /// Gets an iterator pointing to the first value that is not less than `val`. - /// If all values in the set are less than `val` an empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let set: TrieSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); - /// assert_eq!(set.lower_bound(4).next(), Some(4)); - /// assert_eq!(set.lower_bound(5).next(), Some(6)); - /// assert_eq!(set.lower_bound(10).next(), None); - /// ``` - pub fn lower_bound<'a>(&'a self, val: uint) -> SetItems<'a> { - SetItems{iter: self.map.lower_bound(val)} - } - - /// Gets an iterator pointing to the first value that key is greater than `val`. - /// If all values in the set are less than or equal to `val` an empty iterator is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let set: TrieSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); - /// assert_eq!(set.upper_bound(4).next(), Some(6)); - /// assert_eq!(set.upper_bound(5).next(), Some(6)); - /// assert_eq!(set.upper_bound(10).next(), None); - /// ``` - pub fn upper_bound<'a>(&'a self, val: uint) -> SetItems<'a> { - SetItems{iter: self.map.upper_bound(val)} - } - - /// Return the number of elements in the set - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut v = TrieSet::new(); - /// assert_eq!(v.len(), 0); - /// v.insert(1); - /// assert_eq!(v.len(), 1); - /// ``` - #[inline] - pub fn len(&self) -> uint { self.map.len() } - - /// Returns true if the set contains no elements - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut v = TrieSet::new(); - /// assert!(v.is_empty()); - /// v.insert(1); - /// assert!(!v.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears the set, removing all values. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut v = TrieSet::new(); - /// v.insert(1); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - #[inline] - pub fn clear(&mut self) { self.map.clear() } - - /// Returns `true` if the set contains a value. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let set: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// assert_eq!(set.contains(&1), true); - /// assert_eq!(set.contains(&4), false); - /// ``` - #[inline] - pub fn contains(&self, value: &uint) -> bool { - self.map.contains_key(value) - } - - /// Returns `true` if the set has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let a: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let mut b: TrieSet = TrieSet::new(); - /// - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(4); - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(1); - /// assert_eq!(a.is_disjoint(&b), false); - /// ``` - #[inline] - pub fn is_disjoint(&self, other: &TrieSet) -> bool { - self.iter().all(|v| !other.contains(&v)) - } - - /// Returns `true` if the set is a subset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let sup: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let mut set: TrieSet = TrieSet::new(); - /// - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(2); - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(4); - /// assert_eq!(set.is_subset(&sup), false); - /// ``` - #[inline] - pub fn is_subset(&self, other: &TrieSet) -> bool { - self.iter().all(|v| other.contains(&v)) - } - - /// Returns `true` if the set is a superset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let sub: TrieSet = [1, 2].iter().map(|&x| x).collect(); - /// let mut set: TrieSet = TrieSet::new(); - /// - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(0); - /// set.insert(1); - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(2); - /// assert_eq!(set.is_superset(&sub), true); - /// ``` - #[inline] - pub fn is_superset(&self, other: &TrieSet) -> bool { - other.is_subset(self) - } - - /// Adds a value to the set. Returns `true` if the value was not already - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut set = TrieSet::new(); - /// - /// assert_eq!(set.insert(2), true); - /// assert_eq!(set.insert(2), false); - /// assert_eq!(set.len(), 1); - /// ``` - #[inline] - pub fn insert(&mut self, value: uint) -> bool { - self.map.insert(value, ()) - } - - /// Removes a value from the set. Returns `true` if the value was - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::TrieSet; - /// - /// let mut set = TrieSet::new(); - /// - /// set.insert(2); - /// assert_eq!(set.remove(&2), true); - /// assert_eq!(set.remove(&2), false); - /// ``` - #[inline] - pub fn remove(&mut self, value: &uint) -> bool { - self.map.remove(value) - } -} - -impl FromIterator for TrieSet { - fn from_iter>(iter: Iter) -> TrieSet { - let mut set = TrieSet::new(); - set.extend(iter); - set - } -} - -impl Extendable for TrieSet { - fn extend>(&mut self, mut iter: Iter) { - for elem in iter { - self.insert(elem); - } - } -} - -struct TrieNode { - count: uint, - children: [Child, ..SIZE] -} - -impl Clone for TrieNode { - #[inline] - fn clone(&self) -> TrieNode { - let ch = &self.children; - TrieNode { - count: self.count, - children: [ch[0].clone(), ch[1].clone(), ch[2].clone(), ch[3].clone(), - ch[4].clone(), ch[5].clone(), ch[6].clone(), ch[7].clone(), - ch[8].clone(), ch[9].clone(), ch[10].clone(), ch[11].clone(), - ch[12].clone(), ch[13].clone(), ch[14].clone(), ch[15].clone()]} - } -} - -impl TrieNode { - #[inline] - fn new() -> TrieNode { - // FIXME: #5244: [Nothing, ..SIZE] should be possible without implicit - // copyability - TrieNode{count: 0, - children: [Nothing, Nothing, Nothing, Nothing, - Nothing, Nothing, Nothing, Nothing, - Nothing, Nothing, Nothing, Nothing, - Nothing, Nothing, Nothing, Nothing]} - } -} - -impl TrieNode { - fn each_reverse<'a>(&'a self, f: |&uint, &'a T| -> bool) -> bool { - for elt in self.children.iter().rev() { - match *elt { - Internal(ref x) => if !x.each_reverse(|i,t| f(i,t)) { return false }, - External(k, ref v) => if !f(&k, v) { return false }, - Nothing => () - } - } - true - } -} - -// if this was done via a trait, the key could be generic -#[inline] -fn chunk(n: uint, idx: uint) -> uint { - let sh = uint::BITS - (SHIFT * (idx + 1)); - (n >> sh) & MASK -} - -fn find_mut<'r, T>(child: &'r mut Child, key: uint, idx: uint) -> Option<&'r mut T> { - match *child { - External(stored, ref mut value) if stored == key => Some(value), - External(..) => None, - Internal(ref mut x) => find_mut(&mut x.children[chunk(key, idx)], key, idx + 1), - Nothing => None - } -} - -fn insert(count: &mut uint, child: &mut Child, key: uint, value: T, - idx: uint) -> Option { - // we branch twice to avoid having to do the `replace` when we - // don't need to; this is much faster, especially for keys that - // have long shared prefixes. - match *child { - Nothing => { - *count += 1; - *child = External(key, value); - return None; - } - Internal(box ref mut x) => { - return insert(&mut x.count, &mut x.children[chunk(key, idx)], key, value, idx + 1); - } - External(stored_key, ref mut stored_value) if stored_key == key => { - // swap in the new value and return the old. - return Some(mem::replace(stored_value, value)); - } - _ => {} - } - - // conflict, an external node with differing keys: we have to - // split the node, so we need the old value by value; hence we - // have to move out of `child`. - match mem::replace(child, Nothing) { - External(stored_key, stored_value) => { - let mut new = box TrieNode::new(); - - let ret = { - let new_interior = &mut *new; - insert(&mut new_interior.count, - &mut new_interior.children[chunk(stored_key, idx)], - stored_key, stored_value, idx + 1); - insert(&mut new_interior.count, - &mut new_interior.children[chunk(key, idx)], - key, value, idx + 1) - }; - - *child = Internal(new); - return ret; - } - _ => panic!("unreachable code"), - } -} - -fn remove(count: &mut uint, child: &mut Child, key: uint, - idx: uint) -> Option { - let (ret, this) = match *child { - External(stored, _) if stored == key => { - match mem::replace(child, Nothing) { - External(_, value) => (Some(value), true), - _ => panic!() - } - } - External(..) => (None, false), - Internal(box ref mut x) => { - let ret = remove(&mut x.count, &mut x.children[chunk(key, idx)], - key, idx + 1); - (ret, x.count == 0) - } - Nothing => (None, false) - }; - - if this { - *child = Nothing; - *count -= 1; - } - return ret; -} - -/// A forward iterator over a map. -pub struct Entries<'a, T:'a> { - stack: [slice::Items<'a, Child>, .. NUM_CHUNKS], - length: uint, - remaining_min: uint, - remaining_max: uint -} - -/// A forward iterator over the key-value pairs of a map, with the -/// values being mutable. -pub struct MutEntries<'a, T:'a> { - stack: [slice::MutItems<'a, Child>, .. NUM_CHUNKS], - length: uint, - remaining_min: uint, - remaining_max: uint -} - -/// A forward iterator over the keys of a map. -pub type Keys<'a, T> = - iter::Map<'static, (uint, &'a T), uint, Entries<'a, T>>; - -/// A forward iterator over the values of a map. -pub type Values<'a, T> = - iter::Map<'static, (uint, &'a T), &'a T, Entries<'a, T>>; - -// FIXME #5846: see `addr!` above. -macro_rules! item { ($i:item) => {$i}} - -macro_rules! iterator_impl { - ($name:ident, - iter = $iter:ident, - mutability = $($mut_:tt)*) => { - impl<'a, T> $name<'a, T> { - // Create new zero'd iterator. We have a thin gilding of safety by - // using init rather than uninit, so that the worst that can happen - // from failing to initialise correctly after calling these is a - // segfault. - #[cfg(target_word_size="32")] - unsafe fn new() -> $name<'a, T> { - $name { - remaining_min: 0, - remaining_max: 0, - length: 0, - // ick :( ... at least the compiler will tell us if we screwed up. - stack: [zeroed(), zeroed(), zeroed(), zeroed(), zeroed(), - zeroed(), zeroed(), zeroed()] - } - } - - #[cfg(target_word_size="64")] - unsafe fn new() -> $name<'a, T> { - $name { - remaining_min: 0, - remaining_max: 0, - length: 0, - stack: [zeroed(), zeroed(), zeroed(), zeroed(), - zeroed(), zeroed(), zeroed(), zeroed(), - zeroed(), zeroed(), zeroed(), zeroed(), - zeroed(), zeroed(), zeroed(), zeroed()] - } - } - } - - item!(impl<'a, T> Iterator<(uint, &'a $($mut_)* T)> for $name<'a, T> { - // you might wonder why we're not even trying to act within the - // rules, and are just manipulating raw pointers like there's no - // such thing as invalid pointers and memory unsafety. The - // reason is performance, without doing this we can get the - // (now replaced) bench_iter_large microbenchmark down to about - // 30000 ns/iter (using .unsafe_get to index self.stack directly, 38000 - // ns/iter with [] checked indexing), but this smashes that down - // to 13500 ns/iter. - // - // Fortunately, it's still safe... - // - // We have an invariant that every Internal node - // corresponds to one push to self.stack, and one pop, - // nested appropriately. self.stack has enough storage - // to store the maximum depth of Internal nodes in the - // trie (8 on 32-bit platforms, 16 on 64-bit). - fn next(&mut self) -> Option<(uint, &'a $($mut_)* T)> { - let start_ptr = self.stack.as_mut_ptr(); - - unsafe { - // write_ptr is the next place to write to the stack. - // invariant: start_ptr <= write_ptr < end of the - // vector. - let mut write_ptr = start_ptr.offset(self.length as int); - while write_ptr != start_ptr { - // indexing back one is safe, since write_ptr > - // start_ptr now. - match (*write_ptr.offset(-1)).next() { - // exhausted this iterator (i.e. finished this - // Internal node), so pop from the stack. - // - // don't bother clearing the memory, because the - // next time we use it we'll've written to it - // first. - None => write_ptr = write_ptr.offset(-1), - Some(child) => { - addr!(match *child { - Internal(ref $($mut_)* node) => { - // going down a level, so push - // to the stack (this is the - // write referenced above) - *write_ptr = node.children.$iter(); - write_ptr = write_ptr.offset(1); - } - External(key, ref $($mut_)* value) => { - self.remaining_max -= 1; - if self.remaining_min > 0 { - self.remaining_min -= 1; - } - // store the new length of the - // stack, based on our current - // position. - self.length = (write_ptr as uint - - start_ptr as uint) / - mem::size_of_val(&*write_ptr); - - return Some((key, value)); - } - Nothing => {} - }) - } - } - } - } - return None; - } - - #[inline] - fn size_hint(&self) -> (uint, Option) { - (self.remaining_min, Some(self.remaining_max)) - } - }) - } -} - -iterator_impl! { Entries, iter = iter, mutability = } -iterator_impl! { MutEntries, iter = iter_mut, mutability = mut } - -/// A forward iterator over a set. -pub struct SetItems<'a> { - iter: Entries<'a, ()> -} - -impl<'a> Iterator for SetItems<'a> { - fn next(&mut self) -> Option { - self.iter.next().map(|(key, _)| key) - } - - fn size_hint(&self) -> (uint, Option) { - self.iter.size_hint() - } -} - -#[cfg(test)] -mod test_map { - use std::prelude::*; - use std::iter::range_step; - use std::uint; - use std::hash; - - use super::{TrieMap, TrieNode, Internal, External, Nothing}; - - fn check_integrity(trie: &TrieNode) { - assert!(trie.count != 0); - - let mut sum = 0; - - for x in trie.children.iter() { - match *x { - Nothing => (), - Internal(ref y) => { - check_integrity(&**y); - sum += 1 - } - External(_, _) => { sum += 1 } - } - } - - assert_eq!(sum, trie.count); - } - - #[test] - fn test_find_mut() { - let mut m = TrieMap::new(); - assert!(m.insert(1u, 12i)); - assert!(m.insert(2u, 8i)); - assert!(m.insert(5u, 14i)); - let new = 100; - match m.find_mut(&5) { - None => panic!(), Some(x) => *x = new - } - assert_eq!(m.find(&5), Some(&new)); - } - - #[test] - fn test_find_mut_missing() { - let mut m = TrieMap::new(); - assert!(m.find_mut(&0).is_none()); - assert!(m.insert(1u, 12i)); - assert!(m.find_mut(&0).is_none()); - assert!(m.insert(2, 8)); - assert!(m.find_mut(&0).is_none()); - } - - #[test] - fn test_step() { - let mut trie = TrieMap::new(); - let n = 300u; - - for x in range_step(1u, n, 2) { - assert!(trie.insert(x, x + 1)); - assert!(trie.contains_key(&x)); - check_integrity(&trie.root); - } - - for x in range_step(0u, n, 2) { - assert!(!trie.contains_key(&x)); - assert!(trie.insert(x, x + 1)); - check_integrity(&trie.root); - } - - for x in range(0u, n) { - assert!(trie.contains_key(&x)); - assert!(!trie.insert(x, x + 1)); - check_integrity(&trie.root); - } - - for x in range_step(1u, n, 2) { - assert!(trie.remove(&x)); - assert!(!trie.contains_key(&x)); - check_integrity(&trie.root); - } - - for x in range_step(0u, n, 2) { - assert!(trie.contains_key(&x)); - assert!(!trie.insert(x, x + 1)); - check_integrity(&trie.root); - } - } - - #[test] - fn test_each_reverse() { - let mut m = TrieMap::new(); - - assert!(m.insert(3, 6)); - assert!(m.insert(0, 0)); - assert!(m.insert(4, 8)); - assert!(m.insert(2, 4)); - assert!(m.insert(1, 2)); - - let mut n = 4; - m.each_reverse(|k, v| { - assert_eq!(*k, n); - assert_eq!(*v, n * 2); - n -= 1; - true - }); - } - - #[test] - fn test_each_reverse_break() { - let mut m = TrieMap::new(); - - for x in range(uint::MAX - 10000, uint::MAX).rev() { - m.insert(x, x / 2); - } - - let mut n = uint::MAX - 1; - m.each_reverse(|k, v| { - if n == uint::MAX - 5000 { false } else { - assert!(n > uint::MAX - 5000); - - assert_eq!(*k, n); - assert_eq!(*v, n / 2); - n -= 1; - true - } - }); - } - - #[test] - fn test_swap() { - let mut m = TrieMap::new(); - assert_eq!(m.swap(1u, 2i), None); - assert_eq!(m.swap(1u, 3i), Some(2)); - assert_eq!(m.swap(1u, 4i), Some(3)); - } - - #[test] - fn test_pop() { - let mut m = TrieMap::new(); - m.insert(1u, 2i); - assert_eq!(m.pop(&1), Some(2)); - assert_eq!(m.pop(&1), None); - } - - #[test] - fn test_from_iter() { - let xs = vec![(1u, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: TrieMap = xs.iter().map(|&x| x).collect(); - - for &(k, v) in xs.iter() { - assert_eq!(map.find(&k), Some(&v)); - } - } - - #[test] - fn test_keys() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map = vec.into_iter().collect::>(); - let keys = map.keys().collect::>(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; - let map = vec.into_iter().collect::>(); - let values = map.values().map(|&v| v).collect::>(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_iteration() { - let empty_map : TrieMap = TrieMap::new(); - assert_eq!(empty_map.iter().next(), None); - - let first = uint::MAX - 10000; - let last = uint::MAX; - - let mut map = TrieMap::new(); - for x in range(first, last).rev() { - map.insert(x, x / 2); - } - - let mut i = 0; - for (k, &v) in map.iter() { - assert_eq!(k, first + i); - assert_eq!(v, k / 2); - i += 1; - } - assert_eq!(i, last - first); - } - - #[test] - fn test_mut_iter() { - let mut empty_map : TrieMap = TrieMap::new(); - assert!(empty_map.iter_mut().next().is_none()); - - let first = uint::MAX - 10000; - let last = uint::MAX; - - let mut map = TrieMap::new(); - for x in range(first, last).rev() { - map.insert(x, x / 2); - } - - let mut i = 0; - for (k, v) in map.iter_mut() { - assert_eq!(k, first + i); - *v -= k / 2; - i += 1; - } - assert_eq!(i, last - first); - - assert!(map.iter().all(|(_, &v)| v == 0)); - } - - #[test] - fn test_bound() { - let empty_map : TrieMap = TrieMap::new(); - assert_eq!(empty_map.lower_bound(0).next(), None); - assert_eq!(empty_map.upper_bound(0).next(), None); - - let last = 999u; - let step = 3u; - let value = 42u; - - let mut map : TrieMap = TrieMap::new(); - for x in range_step(0u, last, step) { - assert!(x % step == 0); - map.insert(x, value); - } - - for i in range(0u, last - step) { - let mut lb = map.lower_bound(i); - let mut ub = map.upper_bound(i); - let next_key = i - i % step + step; - let next_pair = (next_key, &value); - if i % step == 0 { - assert_eq!(lb.next(), Some((i, &value))); - } else { - assert_eq!(lb.next(), Some(next_pair)); - } - assert_eq!(ub.next(), Some(next_pair)); - } - - let mut lb = map.lower_bound(last - step); - assert_eq!(lb.next(), Some((last - step, &value))); - let mut ub = map.upper_bound(last - step); - assert_eq!(ub.next(), None); - - for i in range(last - step + 1, last) { - let mut lb = map.lower_bound(i); - assert_eq!(lb.next(), None); - let mut ub = map.upper_bound(i); - assert_eq!(ub.next(), None); - } - } - - #[test] - fn test_mut_bound() { - let empty_map : TrieMap = TrieMap::new(); - assert_eq!(empty_map.lower_bound(0).next(), None); - assert_eq!(empty_map.upper_bound(0).next(), None); - - let mut m_lower = TrieMap::new(); - let mut m_upper = TrieMap::new(); - for i in range(0u, 100) { - m_lower.insert(2 * i, 4 * i); - m_upper.insert(2 * i, 4 * i); - } - - for i in range(0u, 199) { - let mut lb_it = m_lower.lower_bound_mut(i); - let (k, v) = lb_it.next().unwrap(); - let lb = i + i % 2; - assert_eq!(lb, k); - *v -= k; - } - - for i in range(0u, 198) { - let mut ub_it = m_upper.upper_bound_mut(i); - let (k, v) = ub_it.next().unwrap(); - let ub = i + 2 - i % 2; - assert_eq!(ub, k); - *v -= k; - } - - assert!(m_lower.lower_bound_mut(199).next().is_none()); - assert!(m_upper.upper_bound_mut(198).next().is_none()); - - assert!(m_lower.iter().all(|(_, &x)| x == 0)); - assert!(m_upper.iter().all(|(_, &x)| x == 0)); - } - - #[test] - fn test_clone() { - let mut a = TrieMap::new(); - - a.insert(1, 'a'); - a.insert(2, 'b'); - a.insert(3, 'c'); - - assert!(a.clone() == a); - } - - #[test] - fn test_eq() { - let mut a = TrieMap::new(); - let mut b = TrieMap::new(); - - assert!(a == b); - assert!(a.insert(0, 5i)); - assert!(a != b); - assert!(b.insert(0, 4i)); - assert!(a != b); - assert!(a.insert(5, 19)); - assert!(a != b); - assert!(!b.insert(0, 5)); - assert!(a != b); - assert!(b.insert(5, 19)); - assert!(a == b); - } - - #[test] - fn test_lt() { - let mut a = TrieMap::new(); - let mut b = TrieMap::new(); - - assert!(!(a < b) && !(b < a)); - assert!(b.insert(2u, 5i)); - assert!(a < b); - assert!(a.insert(2, 7)); - assert!(!(a < b) && b < a); - assert!(b.insert(1, 0)); - assert!(b < a); - assert!(a.insert(0, 6)); - assert!(a < b); - assert!(a.insert(6, 2)); - assert!(a < b && !(b < a)); - } - - #[test] - fn test_ord() { - let mut a = TrieMap::new(); - let mut b = TrieMap::new(); - - assert!(a <= b && a >= b); - assert!(a.insert(1u, 1i)); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - assert!(b.insert(2, 2)); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } - - #[test] - fn test_hash() { - let mut x = TrieMap::new(); - let mut y = TrieMap::new(); - - assert!(hash::hash(&x) == hash::hash(&y)); - x.insert(1, 'a'); - x.insert(2, 'b'); - x.insert(3, 'c'); - - y.insert(3, 'c'); - y.insert(2, 'b'); - y.insert(1, 'a'); - - assert!(hash::hash(&x) == hash::hash(&y)); - } - - #[test] - fn test_show() { - let mut map = TrieMap::new(); - let empty: TrieMap = TrieMap::new(); - - map.insert(1, 'a'); - map.insert(2, 'b'); - - let map_str = format!("{}", map); - - assert!(map_str == "{1: a, 2: b}".to_string()); - assert_eq!(format!("{}", empty), "{}".to_string()); - } - - #[test] - fn test_index() { - let mut map = TrieMap::new(); - - map.insert(1, 2i); - map.insert(2, 1i); - map.insert(3, 4i); - - assert_eq!(map[2], 1); - } - - #[test] - #[should_fail] - fn test_index_nonexistent() { - let mut map = TrieMap::new(); - - map.insert(1, 2i); - map.insert(2, 1i); - map.insert(3, 4i); - - map[4]; - } -} - -#[cfg(test)] -mod bench_map { - use std::prelude::*; - use std::rand::{weak_rng, Rng}; - use test::{Bencher, black_box}; - - use super::TrieMap; - - fn bench_iter(b: &mut Bencher, size: uint) { - let mut map = TrieMap::::new(); - let mut rng = weak_rng(); - - for _ in range(0, size) { - map.swap(rng.gen(), rng.gen()); - } - - b.iter(|| { - for entry in map.iter() { - black_box(entry); - } - }); - } - - #[bench] - pub fn iter_20(b: &mut Bencher) { - bench_iter(b, 20); - } - - #[bench] - pub fn iter_1000(b: &mut Bencher) { - bench_iter(b, 1000); - } - - #[bench] - pub fn iter_100000(b: &mut Bencher) { - bench_iter(b, 100000); - } - - #[bench] - fn bench_lower_bound(b: &mut Bencher) { - let mut m = TrieMap::::new(); - let mut rng = weak_rng(); - for _ in range(0u, 1000) { - m.insert(rng.gen(), rng.gen()); - } - - b.iter(|| { - for _ in range(0u, 10) { - m.lower_bound(rng.gen()); - } - }); - } - - #[bench] - fn bench_upper_bound(b: &mut Bencher) { - let mut m = TrieMap::::new(); - let mut rng = weak_rng(); - for _ in range(0u, 1000) { - m.insert(rng.gen(), rng.gen()); - } - - b.iter(|| { - for _ in range(0u, 10) { - m.upper_bound(rng.gen()); - } - }); - } - - #[bench] - fn bench_insert_large(b: &mut Bencher) { - let mut m = TrieMap::<[uint, .. 10]>::new(); - let mut rng = weak_rng(); - - b.iter(|| { - for _ in range(0u, 1000) { - m.insert(rng.gen(), [1, .. 10]); - } - }) - } - #[bench] - fn bench_insert_large_low_bits(b: &mut Bencher) { - let mut m = TrieMap::<[uint, .. 10]>::new(); - let mut rng = weak_rng(); - - b.iter(|| { - for _ in range(0u, 1000) { - // only have the last few bits set. - m.insert(rng.gen::() & 0xff_ff, [1, .. 10]); - } - }) - } - - #[bench] - fn bench_insert_small(b: &mut Bencher) { - let mut m = TrieMap::<()>::new(); - let mut rng = weak_rng(); - - b.iter(|| { - for _ in range(0u, 1000) { - m.insert(rng.gen(), ()); - } - }) - } - #[bench] - fn bench_insert_small_low_bits(b: &mut Bencher) { - let mut m = TrieMap::<()>::new(); - let mut rng = weak_rng(); - - b.iter(|| { - for _ in range(0u, 1000) { - // only have the last few bits set. - m.insert(rng.gen::() & 0xff_ff, ()); - } - }) - } -} - -#[cfg(test)] -mod test_set { - use std::prelude::*; - use std::uint; - - use super::TrieSet; - - #[test] - fn test_sane_chunk() { - let x = 1; - let y = 1 << (uint::BITS - 1); - - let mut trie = TrieSet::new(); - - assert!(trie.insert(x)); - assert!(trie.insert(y)); - - assert_eq!(trie.len(), 2); - - let expected = [x, y]; - - for (i, x) in trie.iter().enumerate() { - assert_eq!(expected[i], x); - } - } - - #[test] - fn test_from_iter() { - let xs = vec![9u, 8, 7, 6, 5, 4, 3, 2, 1]; - - let set: TrieSet = xs.iter().map(|&x| x).collect(); - - for x in xs.iter() { - assert!(set.contains(x)); - } - } - - #[test] - fn test_show() { - let mut set = TrieSet::new(); - let empty = TrieSet::new(); - - set.insert(1); - set.insert(2); - - let set_str = format!("{}", set); - - assert!(set_str == "{1, 2}".to_string()); - assert_eq!(format!("{}", empty), "{}".to_string()); - } - - #[test] - fn test_clone() { - let mut a = TrieSet::new(); - - a.insert(1); - a.insert(2); - a.insert(3); - - assert!(a.clone() == a); - } - - #[test] - fn test_lt() { - let mut a = TrieSet::new(); - let mut b = TrieSet::new(); - - assert!(!(a < b) && !(b < a)); - assert!(b.insert(2u)); - assert!(a < b); - assert!(a.insert(3u)); - assert!(!(a < b) && b < a); - assert!(b.insert(1)); - assert!(b < a); - assert!(a.insert(0)); - assert!(a < b); - assert!(a.insert(6)); - assert!(a < b && !(b < a)); - } - - #[test] - fn test_ord() { - let mut a = TrieSet::new(); - let mut b = TrieSet::new(); - - assert!(a <= b && a >= b); - assert!(a.insert(1u)); - assert!(a > b && a >= b); - assert!(b < a && b <= a); - assert!(b.insert(2u)); - assert!(b > a && b >= a); - assert!(a < b && a <= b); - } -} diff --git a/src/libcollections/trie/map.rs b/src/libcollections/trie/map.rs new file mode 100644 index 00000000000..27486de6f19 --- /dev/null +++ b/src/libcollections/trie/map.rs @@ -0,0 +1,1460 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Maps are collections of unique keys with corresponding values, and sets are +//! just unique keys without a corresponding value. The `Map` and `Set` traits in +//! `std::container` define the basic interface. +//! +//! This crate defines `TrieMap` and `TrieSet`, which require `uint` keys. +//! +//! `TrieMap` is ordered. + +use core::prelude::*; + +use alloc::boxed::Box; +use core::default::Default; +use core::fmt; +use core::fmt::Show; +use core::mem::zeroed; +use core::mem; +use core::ops::{Slice,SliceMut}; +use core::uint; +use core::iter; +use std::hash::{Writer, Hash}; + +use slice::{Items, MutItems}; +use slice; + +// FIXME: #5244: need to manually update the TrieNode constructor +const SHIFT: uint = 4; +const SIZE: uint = 1 << SHIFT; +const MASK: uint = SIZE - 1; +const NUM_CHUNKS: uint = uint::BITS / SHIFT; + +#[deriving(Clone)] +enum Child { + Internal(Box>), + External(uint, T), + Nothing +} + +/// A map implemented as a radix trie. +/// +/// # Example +/// +/// ``` +/// use std::collections::TrieMap; +/// +/// let mut map = TrieMap::new(); +/// map.insert(27, "Olaf"); +/// map.insert(1, "Edgar"); +/// map.insert(13, "Ruth"); +/// map.insert(1, "Martin"); +/// +/// assert_eq!(map.len(), 3); +/// assert_eq!(map.find(&1), Some(&"Martin")); +/// +/// if !map.contains_key(&90) { +/// println!("Nobody is keyed 90"); +/// } +/// +/// // Update a key +/// match map.find_mut(&1) { +/// Some(value) => *value = "Olga", +/// None => (), +/// } +/// +/// map.remove(&13); +/// assert_eq!(map.len(), 2); +/// +/// // Print the key value pairs, ordered by key. +/// for (key, value) in map.iter() { +/// // Prints `1: Olga` then `27: Olaf` +/// println!("{}: {}", key, value); +/// } +/// +/// map.clear(); +/// assert!(map.is_empty()); +/// ``` +#[deriving(Clone)] +pub struct TrieMap { + root: TrieNode, + length: uint +} + +impl PartialEq for TrieMap { + fn eq(&self, other: &TrieMap) -> bool { + self.len() == other.len() && + self.iter().zip(other.iter()).all(|(a, b)| a == b) + } +} + +impl Eq for TrieMap {} + +impl PartialOrd for TrieMap { + #[inline] + fn partial_cmp(&self, other: &TrieMap) -> Option { + iter::order::partial_cmp(self.iter(), other.iter()) + } +} + +impl Ord for TrieMap { + #[inline] + fn cmp(&self, other: &TrieMap) -> Ordering { + iter::order::cmp(self.iter(), other.iter()) + } +} + +impl Show for TrieMap { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, (k, v)) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}: {}", k, *v)); + } + + write!(f, "}}") + } +} + +impl Default for TrieMap { + #[inline] + fn default() -> TrieMap { TrieMap::new() } +} + +impl TrieMap { + /// Creates an empty `TrieMap`. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// let mut map: TrieMap<&str> = TrieMap::new(); + /// ``` + #[inline] + pub fn new() -> TrieMap { + TrieMap{root: TrieNode::new(), length: 0} + } + + /// Visits all key-value pairs in reverse order. Aborts traversal when `f` returns `false`. + /// Returns `true` if `f` returns `true` for all elements. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// let map: TrieMap<&str> = [(1, "a"), (2, "b"), (3, "c")].iter().map(|&x| x).collect(); + /// + /// let mut vec = Vec::new(); + /// assert_eq!(true, map.each_reverse(|&key, &value| { vec.push((key, value)); true })); + /// assert_eq!(vec, vec![(3, "c"), (2, "b"), (1, "a")]); + /// + /// // Stop when we reach 2 + /// let mut vec = Vec::new(); + /// assert_eq!(false, map.each_reverse(|&key, &value| { vec.push(value); key != 2 })); + /// assert_eq!(vec, vec!["c", "b"]); + /// ``` + #[inline] + pub fn each_reverse<'a>(&'a self, f: |&uint, &'a T| -> bool) -> bool { + self.root.each_reverse(f) + } + + /// Gets an iterator visiting all keys in ascending order by the keys. + /// The iterator's element type is `uint`. + pub fn keys<'r>(&'r self) -> Keys<'r, T> { + self.iter().map(|(k, _v)| k) + } + + /// Gets an iterator visiting all values in ascending order by the keys. + /// The iterator's element type is `&'r T`. + pub fn values<'r>(&'r self) -> Values<'r, T> { + self.iter().map(|(_k, v)| v) + } + + /// Gets an iterator over the key-value pairs in the map, ordered by keys. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// let map: TrieMap<&str> = [(3, "c"), (1, "a"), (2, "b")].iter().map(|&x| x).collect(); + /// + /// for (key, value) in map.iter() { + /// println!("{}: {}", key, value); + /// } + /// ``` + pub fn iter<'a>(&'a self) -> Entries<'a, T> { + let mut iter = unsafe {Entries::new()}; + iter.stack[0] = self.root.children.iter(); + iter.length = 1; + iter.remaining_min = self.length; + iter.remaining_max = self.length; + + iter + } + + /// Gets an iterator over the key-value pairs in the map, with the + /// ability to mutate the values. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// let mut map: TrieMap = [(1, 2), (2, 4), (3, 6)].iter().map(|&x| x).collect(); + /// + /// for (key, value) in map.iter_mut() { + /// *value = -(key as int); + /// } + /// + /// assert_eq!(map.find(&1), Some(&-1)); + /// assert_eq!(map.find(&2), Some(&-2)); + /// assert_eq!(map.find(&3), Some(&-3)); + /// ``` + pub fn iter_mut<'a>(&'a mut self) -> MutEntries<'a, T> { + let mut iter = unsafe {MutEntries::new()}; + iter.stack[0] = self.root.children.iter_mut(); + iter.length = 1; + iter.remaining_min = self.length; + iter.remaining_max = self.length; + + iter + } + + /// Return the number of elements in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// + /// let mut a = TrieMap::new(); + /// assert_eq!(a.len(), 0); + /// a.insert(1, "a"); + /// assert_eq!(a.len(), 1); + /// ``` + #[inline] + pub fn len(&self) -> uint { self.length } + + /// Return true if the map contains no elements. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// + /// let mut a = TrieMap::new(); + /// assert!(a.is_empty()); + /// a.insert(1, "a"); + /// assert!(!a.is_empty()); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Clears the map, removing all values. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// + /// let mut a = TrieMap::new(); + /// a.insert(1, "a"); + /// a.clear(); + /// assert!(a.is_empty()); + /// ``` + #[inline] + pub fn clear(&mut self) { + self.root = TrieNode::new(); + self.length = 0; + } + + /// Returns a reference to the value corresponding to the key. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// + /// let mut map = TrieMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.find(&1), Some(&"a")); + /// assert_eq!(map.find(&2), None); + /// ``` + #[inline] + pub fn find<'a>(&'a self, key: &uint) -> Option<&'a T> { + let mut node: &'a TrieNode = &self.root; + let mut idx = 0; + loop { + match node.children[chunk(*key, idx)] { + Internal(ref x) => node = &**x, + External(stored, ref value) => { + if stored == *key { + return Some(value) + } else { + return None + } + } + Nothing => return None + } + idx += 1; + } + } + + /// Returns true if the map contains a value for the specified key. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// + /// let mut map = TrieMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.contains_key(&1), true); + /// assert_eq!(map.contains_key(&2), false); + /// ``` + #[inline] + pub fn contains_key(&self, key: &uint) -> bool { + self.find(key).is_some() + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// + /// let mut map = TrieMap::new(); + /// map.insert(1, "a"); + /// match map.find_mut(&1) { + /// Some(x) => *x = "b", + /// None => (), + /// } + /// assert_eq!(map[1], "b"); + /// ``` + #[inline] + pub fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut T> { + find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1) + } + + /// Inserts a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Returns `true` if the key did + /// not already exist in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// + /// let mut map = TrieMap::new(); + /// assert_eq!(map.insert(2, "value"), true); + /// assert_eq!(map.insert(2, "value2"), false); + /// assert_eq!(map[2], "value2"); + /// ``` + #[inline] + pub fn insert(&mut self, key: uint, value: T) -> bool { + self.swap(key, value).is_none() + } + + /// Removes a key-value pair from the map. Returns `true` if the key + /// was present in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// + /// let mut map = TrieMap::new(); + /// assert_eq!(map.remove(&1), false); + /// map.insert(1, "a"); + /// assert_eq!(map.remove(&1), true); + /// ``` + #[inline] + pub fn remove(&mut self, key: &uint) -> bool { + self.pop(key).is_some() + } + + /// Inserts a key-value pair from the map. If the key already had a value + /// present in the map, that value is returned. Otherwise, `None` is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// + /// let mut map = TrieMap::new(); + /// assert_eq!(map.swap(37, "a"), None); + /// assert_eq!(map.is_empty(), false); + /// + /// map.insert(37, "b"); + /// assert_eq!(map.swap(37, "c"), Some("b")); + /// assert_eq!(map[37], "c"); + /// ``` + pub fn swap(&mut self, key: uint, value: T) -> Option { + let ret = insert(&mut self.root.count, + &mut self.root.children[chunk(key, 0)], + key, value, 1); + if ret.is_none() { self.length += 1 } + ret + } + + /// Removes a key from the map, returning the value at the key if the key + /// was previously in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// + /// let mut map = TrieMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.pop(&1), Some("a")); + /// assert_eq!(map.pop(&1), None); + /// ``` + pub fn pop(&mut self, key: &uint) -> Option { + let ret = remove(&mut self.root.count, + &mut self.root.children[chunk(*key, 0)], + *key, 1); + if ret.is_some() { self.length -= 1 } + ret + } +} + +// FIXME #5846 we want to be able to choose between &x and &mut x +// (with many different `x`) below, so we need to optionally pass mut +// as a tt, but the only thing we can do with a `tt` is pass them to +// other macros, so this takes the `& ` token +// sequence and forces their evaluation as an expression. (see also +// `item!` below.) +macro_rules! addr { ($e:expr) => { $e } } + +macro_rules! bound { + ($iterator_name:ident, + // the current treemap + self = $this:expr, + // the key to look for + key = $key:expr, + // are we looking at the upper bound? + is_upper = $upper:expr, + + // method names for slicing/iterating. + slice_from = $slice_from:ident, + iter = $iter:ident, + + // see the comment on `addr!`, this is just an optional mut, but + // there's no 0-or-1 repeats yet. + mutability = $($mut_:tt)*) => { + { + // # For `mut` + // We need an unsafe pointer here because we are borrowing + // mutable references to the internals of each of these + // mutable nodes, while still using the outer node. + // + // However, we're allowed to flaunt rustc like this because we + // never actually modify the "shape" of the nodes. The only + // place that mutation is can actually occur is of the actual + // values of the TrieMap (as the return value of the + // iterator), i.e. we can never cause a deallocation of any + // TrieNodes so the raw pointer is always valid. + // + // # For non-`mut` + // We like sharing code so much that even a little unsafe won't + // stop us. + let this = $this; + let mut node = unsafe { + mem::transmute::<_, uint>(&this.root) as *mut TrieNode + }; + + let key = $key; + + let mut it = unsafe {$iterator_name::new()}; + // everything else is zero'd, as we want. + it.remaining_max = this.length; + + // this addr is necessary for the `Internal` pattern. + addr!(loop { + let children = unsafe {addr!(& $($mut_)* (*node).children)}; + // it.length is the current depth in the iterator and the + // current depth through the `uint` key we've traversed. + let child_id = chunk(key, it.length); + let (slice_idx, ret) = match children[child_id] { + Internal(ref $($mut_)* n) => { + node = unsafe { + mem::transmute::<_, uint>(&**n) + as *mut TrieNode + }; + (child_id + 1, false) + } + External(stored, _) => { + (if stored < key || ($upper && stored == key) { + child_id + 1 + } else { + child_id + }, true) + } + Nothing => { + (child_id + 1, true) + } + }; + // push to the stack. + it.stack[it.length] = children.$slice_from(&slice_idx).$iter(); + it.length += 1; + if ret { return it } + }) + } + } +} + +impl TrieMap { + // If `upper` is true then returns upper_bound else returns lower_bound. + #[inline] + fn bound<'a>(&'a self, key: uint, upper: bool) -> Entries<'a, T> { + bound!(Entries, self = self, + key = key, is_upper = upper, + slice_from = slice_from_or_fail, iter = iter, + mutability = ) + } + + /// Gets an iterator pointing to the first key-value pair whose key is not less than `key`. + /// If all keys in the map are less than `key` an empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// let map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect(); + /// + /// assert_eq!(map.lower_bound(4).next(), Some((4, &"b"))); + /// assert_eq!(map.lower_bound(5).next(), Some((6, &"c"))); + /// assert_eq!(map.lower_bound(10).next(), None); + /// ``` + pub fn lower_bound<'a>(&'a self, key: uint) -> Entries<'a, T> { + self.bound(key, false) + } + + /// Gets an iterator pointing to the first key-value pair whose key is greater than `key`. + /// If all keys in the map are not greater than `key` an empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// let map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect(); + /// + /// assert_eq!(map.upper_bound(4).next(), Some((6, &"c"))); + /// assert_eq!(map.upper_bound(5).next(), Some((6, &"c"))); + /// assert_eq!(map.upper_bound(10).next(), None); + /// ``` + pub fn upper_bound<'a>(&'a self, key: uint) -> Entries<'a, T> { + self.bound(key, true) + } + // If `upper` is true then returns upper_bound else returns lower_bound. + #[inline] + fn bound_mut<'a>(&'a mut self, key: uint, upper: bool) -> MutEntries<'a, T> { + bound!(MutEntries, self = self, + key = key, is_upper = upper, + slice_from = slice_from_or_fail_mut, iter = iter_mut, + mutability = mut) + } + + /// Gets an iterator pointing to the first key-value pair whose key is not less than `key`. + /// If all keys in the map are less than `key` an empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// let mut map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect(); + /// + /// assert_eq!(map.lower_bound_mut(4).next(), Some((4, &mut "b"))); + /// assert_eq!(map.lower_bound_mut(5).next(), Some((6, &mut "c"))); + /// assert_eq!(map.lower_bound_mut(10).next(), None); + /// + /// for (key, value) in map.lower_bound_mut(4) { + /// *value = "changed"; + /// } + /// + /// assert_eq!(map.find(&2), Some(&"a")); + /// assert_eq!(map.find(&4), Some(&"changed")); + /// assert_eq!(map.find(&6), Some(&"changed")); + /// ``` + pub fn lower_bound_mut<'a>(&'a mut self, key: uint) -> MutEntries<'a, T> { + self.bound_mut(key, false) + } + + /// Gets an iterator pointing to the first key-value pair whose key is greater than `key`. + /// If all keys in the map are not greater than `key` an empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieMap; + /// let mut map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect(); + /// + /// assert_eq!(map.upper_bound_mut(4).next(), Some((6, &mut "c"))); + /// assert_eq!(map.upper_bound_mut(5).next(), Some((6, &mut "c"))); + /// assert_eq!(map.upper_bound_mut(10).next(), None); + /// + /// for (key, value) in map.upper_bound_mut(4) { + /// *value = "changed"; + /// } + /// + /// assert_eq!(map.find(&2), Some(&"a")); + /// assert_eq!(map.find(&4), Some(&"b")); + /// assert_eq!(map.find(&6), Some(&"changed")); + /// ``` + pub fn upper_bound_mut<'a>(&'a mut self, key: uint) -> MutEntries<'a, T> { + self.bound_mut(key, true) + } +} + +impl FromIterator<(uint, T)> for TrieMap { + fn from_iter>(iter: Iter) -> TrieMap { + let mut map = TrieMap::new(); + map.extend(iter); + map + } +} + +impl Extendable<(uint, T)> for TrieMap { + fn extend>(&mut self, mut iter: Iter) { + for (k, v) in iter { + self.insert(k, v); + } + } +} + +impl> Hash for TrieMap { + fn hash(&self, state: &mut S) { + for elt in self.iter() { + elt.hash(state); + } + } +} + +impl Index for TrieMap { + #[inline] + fn index<'a>(&'a self, i: &uint) -> &'a T { + self.find(i).expect("key not present") + } +} + +impl IndexMut for TrieMap { + #[inline] + fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut T { + self.find_mut(i).expect("key not present") + } +} + +struct TrieNode { + count: uint, + children: [Child, ..SIZE] +} + +impl Clone for TrieNode { + #[inline] + fn clone(&self) -> TrieNode { + let ch = &self.children; + TrieNode { + count: self.count, + children: [ch[0].clone(), ch[1].clone(), ch[2].clone(), ch[3].clone(), + ch[4].clone(), ch[5].clone(), ch[6].clone(), ch[7].clone(), + ch[8].clone(), ch[9].clone(), ch[10].clone(), ch[11].clone(), + ch[12].clone(), ch[13].clone(), ch[14].clone(), ch[15].clone()]} + } +} + +impl TrieNode { + #[inline] + fn new() -> TrieNode { + // FIXME: #5244: [Nothing, ..SIZE] should be possible without implicit + // copyability + TrieNode{count: 0, + children: [Nothing, Nothing, Nothing, Nothing, + Nothing, Nothing, Nothing, Nothing, + Nothing, Nothing, Nothing, Nothing, + Nothing, Nothing, Nothing, Nothing]} + } +} + +impl TrieNode { + fn each_reverse<'a>(&'a self, f: |&uint, &'a T| -> bool) -> bool { + for elt in self.children.iter().rev() { + match *elt { + Internal(ref x) => if !x.each_reverse(|i,t| f(i,t)) { return false }, + External(k, ref v) => if !f(&k, v) { return false }, + Nothing => () + } + } + true + } +} + +// if this was done via a trait, the key could be generic +#[inline] +fn chunk(n: uint, idx: uint) -> uint { + let sh = uint::BITS - (SHIFT * (idx + 1)); + (n >> sh) & MASK +} + +fn find_mut<'r, T>(child: &'r mut Child, key: uint, idx: uint) -> Option<&'r mut T> { + match *child { + External(stored, ref mut value) if stored == key => Some(value), + External(..) => None, + Internal(ref mut x) => find_mut(&mut x.children[chunk(key, idx)], key, idx + 1), + Nothing => None + } +} + +fn insert(count: &mut uint, child: &mut Child, key: uint, value: T, + idx: uint) -> Option { + // we branch twice to avoid having to do the `replace` when we + // don't need to; this is much faster, especially for keys that + // have long shared prefixes. + match *child { + Nothing => { + *count += 1; + *child = External(key, value); + return None; + } + Internal(box ref mut x) => { + return insert(&mut x.count, &mut x.children[chunk(key, idx)], key, value, idx + 1); + } + External(stored_key, ref mut stored_value) if stored_key == key => { + // swap in the new value and return the old. + return Some(mem::replace(stored_value, value)); + } + _ => {} + } + + // conflict, an external node with differing keys: we have to + // split the node, so we need the old value by value; hence we + // have to move out of `child`. + match mem::replace(child, Nothing) { + External(stored_key, stored_value) => { + let mut new = box TrieNode::new(); + + let ret = { + let new_interior = &mut *new; + insert(&mut new_interior.count, + &mut new_interior.children[chunk(stored_key, idx)], + stored_key, stored_value, idx + 1); + insert(&mut new_interior.count, + &mut new_interior.children[chunk(key, idx)], + key, value, idx + 1) + }; + + *child = Internal(new); + return ret; + } + _ => panic!("unreachable code"), + } +} + +fn remove(count: &mut uint, child: &mut Child, key: uint, + idx: uint) -> Option { + let (ret, this) = match *child { + External(stored, _) if stored == key => { + match mem::replace(child, Nothing) { + External(_, value) => (Some(value), true), + _ => panic!() + } + } + External(..) => (None, false), + Internal(box ref mut x) => { + let ret = remove(&mut x.count, &mut x.children[chunk(key, idx)], + key, idx + 1); + (ret, x.count == 0) + } + Nothing => (None, false) + }; + + if this { + *child = Nothing; + *count -= 1; + } + return ret; +} + +/// A forward iterator over a map. +pub struct Entries<'a, T:'a> { + stack: [slice::Items<'a, Child>, .. NUM_CHUNKS], + length: uint, + remaining_min: uint, + remaining_max: uint +} + +/// A forward iterator over the key-value pairs of a map, with the +/// values being mutable. +pub struct MutEntries<'a, T:'a> { + stack: [slice::MutItems<'a, Child>, .. NUM_CHUNKS], + length: uint, + remaining_min: uint, + remaining_max: uint +} + +/// A forward iterator over the keys of a map. +pub type Keys<'a, T> = + iter::Map<'static, (uint, &'a T), uint, Entries<'a, T>>; + +/// A forward iterator over the values of a map. +pub type Values<'a, T> = + iter::Map<'static, (uint, &'a T), &'a T, Entries<'a, T>>; + +// FIXME #5846: see `addr!` above. +macro_rules! item { ($i:item) => {$i}} + +macro_rules! iterator_impl { + ($name:ident, + iter = $iter:ident, + mutability = $($mut_:tt)*) => { + impl<'a, T> $name<'a, T> { + // Create new zero'd iterator. We have a thin gilding of safety by + // using init rather than uninit, so that the worst that can happen + // from failing to initialise correctly after calling these is a + // segfault. + #[cfg(target_word_size="32")] + unsafe fn new() -> $name<'a, T> { + $name { + remaining_min: 0, + remaining_max: 0, + length: 0, + // ick :( ... at least the compiler will tell us if we screwed up. + stack: [zeroed(), zeroed(), zeroed(), zeroed(), zeroed(), + zeroed(), zeroed(), zeroed()] + } + } + + #[cfg(target_word_size="64")] + unsafe fn new() -> $name<'a, T> { + $name { + remaining_min: 0, + remaining_max: 0, + length: 0, + stack: [zeroed(), zeroed(), zeroed(), zeroed(), + zeroed(), zeroed(), zeroed(), zeroed(), + zeroed(), zeroed(), zeroed(), zeroed(), + zeroed(), zeroed(), zeroed(), zeroed()] + } + } + } + + item!(impl<'a, T> Iterator<(uint, &'a $($mut_)* T)> for $name<'a, T> { + // you might wonder why we're not even trying to act within the + // rules, and are just manipulating raw pointers like there's no + // such thing as invalid pointers and memory unsafety. The + // reason is performance, without doing this we can get the + // (now replaced) bench_iter_large microbenchmark down to about + // 30000 ns/iter (using .unsafe_get to index self.stack directly, 38000 + // ns/iter with [] checked indexing), but this smashes that down + // to 13500 ns/iter. + // + // Fortunately, it's still safe... + // + // We have an invariant that every Internal node + // corresponds to one push to self.stack, and one pop, + // nested appropriately. self.stack has enough storage + // to store the maximum depth of Internal nodes in the + // trie (8 on 32-bit platforms, 16 on 64-bit). + fn next(&mut self) -> Option<(uint, &'a $($mut_)* T)> { + let start_ptr = self.stack.as_mut_ptr(); + + unsafe { + // write_ptr is the next place to write to the stack. + // invariant: start_ptr <= write_ptr < end of the + // vector. + let mut write_ptr = start_ptr.offset(self.length as int); + while write_ptr != start_ptr { + // indexing back one is safe, since write_ptr > + // start_ptr now. + match (*write_ptr.offset(-1)).next() { + // exhausted this iterator (i.e. finished this + // Internal node), so pop from the stack. + // + // don't bother clearing the memory, because the + // next time we use it we'll've written to it + // first. + None => write_ptr = write_ptr.offset(-1), + Some(child) => { + addr!(match *child { + Internal(ref $($mut_)* node) => { + // going down a level, so push + // to the stack (this is the + // write referenced above) + *write_ptr = node.children.$iter(); + write_ptr = write_ptr.offset(1); + } + External(key, ref $($mut_)* value) => { + self.remaining_max -= 1; + if self.remaining_min > 0 { + self.remaining_min -= 1; + } + // store the new length of the + // stack, based on our current + // position. + self.length = (write_ptr as uint + - start_ptr as uint) / + mem::size_of_val(&*write_ptr); + + return Some((key, value)); + } + Nothing => {} + }) + } + } + } + } + return None; + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + (self.remaining_min, Some(self.remaining_max)) + } + }) + } +} + +iterator_impl! { Entries, iter = iter, mutability = } +iterator_impl! { MutEntries, iter = iter_mut, mutability = mut } + +#[cfg(test)] +mod test { + use std::prelude::*; + use std::iter::range_step; + use std::uint; + use std::hash; + + use super::{TrieMap, TrieNode, Internal, External, Nothing}; + + fn check_integrity(trie: &TrieNode) { + assert!(trie.count != 0); + + let mut sum = 0; + + for x in trie.children.iter() { + match *x { + Nothing => (), + Internal(ref y) => { + check_integrity(&**y); + sum += 1 + } + External(_, _) => { sum += 1 } + } + } + + assert_eq!(sum, trie.count); + } + + #[test] + fn test_find_mut() { + let mut m = TrieMap::new(); + assert!(m.insert(1u, 12i)); + assert!(m.insert(2u, 8i)); + assert!(m.insert(5u, 14i)); + let new = 100; + match m.find_mut(&5) { + None => panic!(), Some(x) => *x = new + } + assert_eq!(m.find(&5), Some(&new)); + } + + #[test] + fn test_find_mut_missing() { + let mut m = TrieMap::new(); + assert!(m.find_mut(&0).is_none()); + assert!(m.insert(1u, 12i)); + assert!(m.find_mut(&0).is_none()); + assert!(m.insert(2, 8)); + assert!(m.find_mut(&0).is_none()); + } + + #[test] + fn test_step() { + let mut trie = TrieMap::new(); + let n = 300u; + + for x in range_step(1u, n, 2) { + assert!(trie.insert(x, x + 1)); + assert!(trie.contains_key(&x)); + check_integrity(&trie.root); + } + + for x in range_step(0u, n, 2) { + assert!(!trie.contains_key(&x)); + assert!(trie.insert(x, x + 1)); + check_integrity(&trie.root); + } + + for x in range(0u, n) { + assert!(trie.contains_key(&x)); + assert!(!trie.insert(x, x + 1)); + check_integrity(&trie.root); + } + + for x in range_step(1u, n, 2) { + assert!(trie.remove(&x)); + assert!(!trie.contains_key(&x)); + check_integrity(&trie.root); + } + + for x in range_step(0u, n, 2) { + assert!(trie.contains_key(&x)); + assert!(!trie.insert(x, x + 1)); + check_integrity(&trie.root); + } + } + + #[test] + fn test_each_reverse() { + let mut m = TrieMap::new(); + + assert!(m.insert(3, 6)); + assert!(m.insert(0, 0)); + assert!(m.insert(4, 8)); + assert!(m.insert(2, 4)); + assert!(m.insert(1, 2)); + + let mut n = 4; + m.each_reverse(|k, v| { + assert_eq!(*k, n); + assert_eq!(*v, n * 2); + n -= 1; + true + }); + } + + #[test] + fn test_each_reverse_break() { + let mut m = TrieMap::new(); + + for x in range(uint::MAX - 10000, uint::MAX).rev() { + m.insert(x, x / 2); + } + + let mut n = uint::MAX - 1; + m.each_reverse(|k, v| { + if n == uint::MAX - 5000 { false } else { + assert!(n > uint::MAX - 5000); + + assert_eq!(*k, n); + assert_eq!(*v, n / 2); + n -= 1; + true + } + }); + } + + #[test] + fn test_swap() { + let mut m = TrieMap::new(); + assert_eq!(m.swap(1u, 2i), None); + assert_eq!(m.swap(1u, 3i), Some(2)); + assert_eq!(m.swap(1u, 4i), Some(3)); + } + + #[test] + fn test_pop() { + let mut m = TrieMap::new(); + m.insert(1u, 2i); + assert_eq!(m.pop(&1), Some(2)); + assert_eq!(m.pop(&1), None); + } + + #[test] + fn test_from_iter() { + let xs = vec![(1u, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; + + let map: TrieMap = xs.iter().map(|&x| x).collect(); + + for &(k, v) in xs.iter() { + assert_eq!(map.find(&k), Some(&v)); + } + } + + #[test] + fn test_keys() { + let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; + let map = vec.into_iter().collect::>(); + let keys = map.keys().collect::>(); + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); + } + + #[test] + fn test_values() { + let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; + let map = vec.into_iter().collect::>(); + let values = map.values().map(|&v| v).collect::>(); + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); + } + + #[test] + fn test_iteration() { + let empty_map : TrieMap = TrieMap::new(); + assert_eq!(empty_map.iter().next(), None); + + let first = uint::MAX - 10000; + let last = uint::MAX; + + let mut map = TrieMap::new(); + for x in range(first, last).rev() { + map.insert(x, x / 2); + } + + let mut i = 0; + for (k, &v) in map.iter() { + assert_eq!(k, first + i); + assert_eq!(v, k / 2); + i += 1; + } + assert_eq!(i, last - first); + } + + #[test] + fn test_mut_iter() { + let mut empty_map : TrieMap = TrieMap::new(); + assert!(empty_map.iter_mut().next().is_none()); + + let first = uint::MAX - 10000; + let last = uint::MAX; + + let mut map = TrieMap::new(); + for x in range(first, last).rev() { + map.insert(x, x / 2); + } + + let mut i = 0; + for (k, v) in map.iter_mut() { + assert_eq!(k, first + i); + *v -= k / 2; + i += 1; + } + assert_eq!(i, last - first); + + assert!(map.iter().all(|(_, &v)| v == 0)); + } + + #[test] + fn test_bound() { + let empty_map : TrieMap = TrieMap::new(); + assert_eq!(empty_map.lower_bound(0).next(), None); + assert_eq!(empty_map.upper_bound(0).next(), None); + + let last = 999u; + let step = 3u; + let value = 42u; + + let mut map : TrieMap = TrieMap::new(); + for x in range_step(0u, last, step) { + assert!(x % step == 0); + map.insert(x, value); + } + + for i in range(0u, last - step) { + let mut lb = map.lower_bound(i); + let mut ub = map.upper_bound(i); + let next_key = i - i % step + step; + let next_pair = (next_key, &value); + if i % step == 0 { + assert_eq!(lb.next(), Some((i, &value))); + } else { + assert_eq!(lb.next(), Some(next_pair)); + } + assert_eq!(ub.next(), Some(next_pair)); + } + + let mut lb = map.lower_bound(last - step); + assert_eq!(lb.next(), Some((last - step, &value))); + let mut ub = map.upper_bound(last - step); + assert_eq!(ub.next(), None); + + for i in range(last - step + 1, last) { + let mut lb = map.lower_bound(i); + assert_eq!(lb.next(), None); + let mut ub = map.upper_bound(i); + assert_eq!(ub.next(), None); + } + } + + #[test] + fn test_mut_bound() { + let empty_map : TrieMap = TrieMap::new(); + assert_eq!(empty_map.lower_bound(0).next(), None); + assert_eq!(empty_map.upper_bound(0).next(), None); + + let mut m_lower = TrieMap::new(); + let mut m_upper = TrieMap::new(); + for i in range(0u, 100) { + m_lower.insert(2 * i, 4 * i); + m_upper.insert(2 * i, 4 * i); + } + + for i in range(0u, 199) { + let mut lb_it = m_lower.lower_bound_mut(i); + let (k, v) = lb_it.next().unwrap(); + let lb = i + i % 2; + assert_eq!(lb, k); + *v -= k; + } + + for i in range(0u, 198) { + let mut ub_it = m_upper.upper_bound_mut(i); + let (k, v) = ub_it.next().unwrap(); + let ub = i + 2 - i % 2; + assert_eq!(ub, k); + *v -= k; + } + + assert!(m_lower.lower_bound_mut(199).next().is_none()); + assert!(m_upper.upper_bound_mut(198).next().is_none()); + + assert!(m_lower.iter().all(|(_, &x)| x == 0)); + assert!(m_upper.iter().all(|(_, &x)| x == 0)); + } + + #[test] + fn test_clone() { + let mut a = TrieMap::new(); + + a.insert(1, 'a'); + a.insert(2, 'b'); + a.insert(3, 'c'); + + assert!(a.clone() == a); + } + + #[test] + fn test_eq() { + let mut a = TrieMap::new(); + let mut b = TrieMap::new(); + + assert!(a == b); + assert!(a.insert(0, 5i)); + assert!(a != b); + assert!(b.insert(0, 4i)); + assert!(a != b); + assert!(a.insert(5, 19)); + assert!(a != b); + assert!(!b.insert(0, 5)); + assert!(a != b); + assert!(b.insert(5, 19)); + assert!(a == b); + } + + #[test] + fn test_lt() { + let mut a = TrieMap::new(); + let mut b = TrieMap::new(); + + assert!(!(a < b) && !(b < a)); + assert!(b.insert(2u, 5i)); + assert!(a < b); + assert!(a.insert(2, 7)); + assert!(!(a < b) && b < a); + assert!(b.insert(1, 0)); + assert!(b < a); + assert!(a.insert(0, 6)); + assert!(a < b); + assert!(a.insert(6, 2)); + assert!(a < b && !(b < a)); + } + + #[test] + fn test_ord() { + let mut a = TrieMap::new(); + let mut b = TrieMap::new(); + + assert!(a <= b && a >= b); + assert!(a.insert(1u, 1i)); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + assert!(b.insert(2, 2)); + assert!(b > a && b >= a); + assert!(a < b && a <= b); + } + + #[test] + fn test_hash() { + let mut x = TrieMap::new(); + let mut y = TrieMap::new(); + + assert!(hash::hash(&x) == hash::hash(&y)); + x.insert(1, 'a'); + x.insert(2, 'b'); + x.insert(3, 'c'); + + y.insert(3, 'c'); + y.insert(2, 'b'); + y.insert(1, 'a'); + + assert!(hash::hash(&x) == hash::hash(&y)); + } + + #[test] + fn test_show() { + let mut map = TrieMap::new(); + let empty: TrieMap = TrieMap::new(); + + map.insert(1, 'a'); + map.insert(2, 'b'); + + let map_str = format!("{}", map); + + assert!(map_str == "{1: a, 2: b}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } + + #[test] + fn test_index() { + let mut map = TrieMap::new(); + + map.insert(1, 2i); + map.insert(2, 1i); + map.insert(3, 4i); + + assert_eq!(map[2], 1); + } + + #[test] + #[should_fail] + fn test_index_nonexistent() { + let mut map = TrieMap::new(); + + map.insert(1, 2i); + map.insert(2, 1i); + map.insert(3, 4i); + + map[4]; + } +} + +#[cfg(test)] +mod bench { + use std::prelude::*; + use std::rand::{weak_rng, Rng}; + use test::{Bencher, black_box}; + + use super::TrieMap; + + fn bench_iter(b: &mut Bencher, size: uint) { + let mut map = TrieMap::::new(); + let mut rng = weak_rng(); + + for _ in range(0, size) { + map.swap(rng.gen(), rng.gen()); + } + + b.iter(|| { + for entry in map.iter() { + black_box(entry); + } + }); + } + + #[bench] + pub fn iter_20(b: &mut Bencher) { + bench_iter(b, 20); + } + + #[bench] + pub fn iter_1000(b: &mut Bencher) { + bench_iter(b, 1000); + } + + #[bench] + pub fn iter_100000(b: &mut Bencher) { + bench_iter(b, 100000); + } + + #[bench] + fn bench_lower_bound(b: &mut Bencher) { + let mut m = TrieMap::::new(); + let mut rng = weak_rng(); + for _ in range(0u, 1000) { + m.insert(rng.gen(), rng.gen()); + } + + b.iter(|| { + for _ in range(0u, 10) { + m.lower_bound(rng.gen()); + } + }); + } + + #[bench] + fn bench_upper_bound(b: &mut Bencher) { + let mut m = TrieMap::::new(); + let mut rng = weak_rng(); + for _ in range(0u, 1000) { + m.insert(rng.gen(), rng.gen()); + } + + b.iter(|| { + for _ in range(0u, 10) { + m.upper_bound(rng.gen()); + } + }); + } + + #[bench] + fn bench_insert_large(b: &mut Bencher) { + let mut m = TrieMap::<[uint, .. 10]>::new(); + let mut rng = weak_rng(); + + b.iter(|| { + for _ in range(0u, 1000) { + m.insert(rng.gen(), [1, .. 10]); + } + }) + } + #[bench] + fn bench_insert_large_low_bits(b: &mut Bencher) { + let mut m = TrieMap::<[uint, .. 10]>::new(); + let mut rng = weak_rng(); + + b.iter(|| { + for _ in range(0u, 1000) { + // only have the last few bits set. + m.insert(rng.gen::() & 0xff_ff, [1, .. 10]); + } + }) + } + + #[bench] + fn bench_insert_small(b: &mut Bencher) { + let mut m = TrieMap::<()>::new(); + let mut rng = weak_rng(); + + b.iter(|| { + for _ in range(0u, 1000) { + m.insert(rng.gen(), ()); + } + }) + } + #[bench] + fn bench_insert_small_low_bits(b: &mut Bencher) { + let mut m = TrieMap::<()>::new(); + let mut rng = weak_rng(); + + b.iter(|| { + for _ in range(0u, 1000) { + // only have the last few bits set. + m.insert(rng.gen::() & 0xff_ff, ()); + } + }) + } +} diff --git a/src/libcollections/trie/mod.rs b/src/libcollections/trie/mod.rs new file mode 100644 index 00000000000..f0f8f00a6a0 --- /dev/null +++ b/src/libcollections/trie/mod.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Maps are collections of unique keys with corresponding values, and sets are +//! just unique keys without a corresponding value. The `Map` and `Set` traits in +//! `std::container` define the basic interface. +//! +//! This crate defines `TrieMap` and `TrieSet`, which require `uint` keys. +//! +//! `TrieMap` is ordered. + +pub mod map; +pub mod set; \ No newline at end of file diff --git a/src/libcollections/trie/set.rs b/src/libcollections/trie/set.rs new file mode 100644 index 00000000000..ddddd279b04 --- /dev/null +++ b/src/libcollections/trie/set.rs @@ -0,0 +1,457 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; + +use core::default::Default; +use core::fmt; +use core::fmt::Show; +use std::hash::Hash; + +use trie_map::{TrieMap, Entries}; + +/// A set implemented as a radix trie. +/// +/// # Example +/// +/// ``` +/// use std::collections::TrieSet; +/// +/// let mut set = TrieSet::new(); +/// set.insert(6); +/// set.insert(28); +/// set.insert(6); +/// +/// assert_eq!(set.len(), 2); +/// +/// if !set.contains(&3) { +/// println!("3 is not in the set"); +/// } +/// +/// // Print contents in order +/// for x in set.iter() { +/// println!("{}", x); +/// } +/// +/// set.remove(&6); +/// assert_eq!(set.len(), 1); +/// +/// set.clear(); +/// assert!(set.is_empty()); +/// ``` +#[deriving(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct TrieSet { + map: TrieMap<()> +} + +impl Show for TrieSet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, x) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}", x)); + } + + write!(f, "}}") + } +} + +impl Default for TrieSet { + #[inline] + fn default() -> TrieSet { TrieSet::new() } +} + +impl TrieSet { + /// Creates an empty TrieSet. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// let mut set = TrieSet::new(); + /// ``` + #[inline] + pub fn new() -> TrieSet { + TrieSet{map: TrieMap::new()} + } + + /// Visits all values in reverse order. Aborts traversal when `f` returns `false`. + /// Returns `true` if `f` returns `true` for all elements. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let set: TrieSet = [1, 2, 3, 4, 5].iter().map(|&x| x).collect(); + /// + /// let mut vec = Vec::new(); + /// assert_eq!(true, set.each_reverse(|&x| { vec.push(x); true })); + /// assert_eq!(vec, vec![5, 4, 3, 2, 1]); + /// + /// // Stop when we reach 3 + /// let mut vec = Vec::new(); + /// assert_eq!(false, set.each_reverse(|&x| { vec.push(x); x != 3 })); + /// assert_eq!(vec, vec![5, 4, 3]); + /// ``` + #[inline] + pub fn each_reverse(&self, f: |&uint| -> bool) -> bool { + self.map.each_reverse(|k, _| f(k)) + } + + /// Gets an iterator over the values in the set, in sorted order. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut set = TrieSet::new(); + /// set.insert(3); + /// set.insert(2); + /// set.insert(1); + /// set.insert(2); + /// + /// // Print 1, 2, 3 + /// for x in set.iter() { + /// println!("{}", x); + /// } + /// ``` + #[inline] + pub fn iter<'a>(&'a self) -> SetItems<'a> { + SetItems{iter: self.map.iter()} + } + + /// Gets an iterator pointing to the first value that is not less than `val`. + /// If all values in the set are less than `val` an empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let set: TrieSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); + /// assert_eq!(set.lower_bound(4).next(), Some(4)); + /// assert_eq!(set.lower_bound(5).next(), Some(6)); + /// assert_eq!(set.lower_bound(10).next(), None); + /// ``` + pub fn lower_bound<'a>(&'a self, val: uint) -> SetItems<'a> { + SetItems{iter: self.map.lower_bound(val)} + } + + /// Gets an iterator pointing to the first value that key is greater than `val`. + /// If all values in the set are less than or equal to `val` an empty iterator is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let set: TrieSet = [2, 4, 6, 8].iter().map(|&x| x).collect(); + /// assert_eq!(set.upper_bound(4).next(), Some(6)); + /// assert_eq!(set.upper_bound(5).next(), Some(6)); + /// assert_eq!(set.upper_bound(10).next(), None); + /// ``` + pub fn upper_bound<'a>(&'a self, val: uint) -> SetItems<'a> { + SetItems{iter: self.map.upper_bound(val)} + } + + /// Return the number of elements in the set + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut v = TrieSet::new(); + /// assert_eq!(v.len(), 0); + /// v.insert(1); + /// assert_eq!(v.len(), 1); + /// ``` + #[inline] + pub fn len(&self) -> uint { self.map.len() } + + /// Returns true if the set contains no elements + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut v = TrieSet::new(); + /// assert!(v.is_empty()); + /// v.insert(1); + /// assert!(!v.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Clears the set, removing all values. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut v = TrieSet::new(); + /// v.insert(1); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + #[inline] + pub fn clear(&mut self) { self.map.clear() } + + /// Returns `true` if the set contains a value. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let set: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// assert_eq!(set.contains(&1), true); + /// assert_eq!(set.contains(&4), false); + /// ``` + #[inline] + pub fn contains(&self, value: &uint) -> bool { + self.map.contains_key(value) + } + + /// Returns `true` if the set has no elements in common with `other`. + /// This is equivalent to checking for an empty intersection. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let a: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let mut b: TrieSet = TrieSet::new(); + /// + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(4); + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(1); + /// assert_eq!(a.is_disjoint(&b), false); + /// ``` + #[inline] + pub fn is_disjoint(&self, other: &TrieSet) -> bool { + self.iter().all(|v| !other.contains(&v)) + } + + /// Returns `true` if the set is a subset of another. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let sup: TrieSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let mut set: TrieSet = TrieSet::new(); + /// + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(2); + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(4); + /// assert_eq!(set.is_subset(&sup), false); + /// ``` + #[inline] + pub fn is_subset(&self, other: &TrieSet) -> bool { + self.iter().all(|v| other.contains(&v)) + } + + /// Returns `true` if the set is a superset of another. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let sub: TrieSet = [1, 2].iter().map(|&x| x).collect(); + /// let mut set: TrieSet = TrieSet::new(); + /// + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(0); + /// set.insert(1); + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(2); + /// assert_eq!(set.is_superset(&sub), true); + /// ``` + #[inline] + pub fn is_superset(&self, other: &TrieSet) -> bool { + other.is_subset(self) + } + + /// Adds a value to the set. Returns `true` if the value was not already + /// present in the set. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut set = TrieSet::new(); + /// + /// assert_eq!(set.insert(2), true); + /// assert_eq!(set.insert(2), false); + /// assert_eq!(set.len(), 1); + /// ``` + #[inline] + pub fn insert(&mut self, value: uint) -> bool { + self.map.insert(value, ()) + } + + /// Removes a value from the set. Returns `true` if the value was + /// present in the set. + /// + /// # Example + /// + /// ``` + /// use std::collections::TrieSet; + /// + /// let mut set = TrieSet::new(); + /// + /// set.insert(2); + /// assert_eq!(set.remove(&2), true); + /// assert_eq!(set.remove(&2), false); + /// ``` + #[inline] + pub fn remove(&mut self, value: &uint) -> bool { + self.map.remove(value) + } +} + +impl FromIterator for TrieSet { + fn from_iter>(iter: Iter) -> TrieSet { + let mut set = TrieSet::new(); + set.extend(iter); + set + } +} + +impl Extendable for TrieSet { + fn extend>(&mut self, mut iter: Iter) { + for elem in iter { + self.insert(elem); + } + } +} + +/// A forward iterator over a set. +pub struct SetItems<'a> { + iter: Entries<'a, ()> +} + +impl<'a> Iterator for SetItems<'a> { + fn next(&mut self) -> Option { + self.iter.next().map(|(key, _)| key) + } + + fn size_hint(&self) -> (uint, Option) { + self.iter.size_hint() + } +} + +#[cfg(test)] +mod test { + use std::prelude::*; + use std::uint; + + use super::TrieSet; + + #[test] + fn test_sane_chunk() { + let x = 1; + let y = 1 << (uint::BITS - 1); + + let mut trie = TrieSet::new(); + + assert!(trie.insert(x)); + assert!(trie.insert(y)); + + assert_eq!(trie.len(), 2); + + let expected = [x, y]; + + for (i, x) in trie.iter().enumerate() { + assert_eq!(expected[i], x); + } + } + + #[test] + fn test_from_iter() { + let xs = vec![9u, 8, 7, 6, 5, 4, 3, 2, 1]; + + let set: TrieSet = xs.iter().map(|&x| x).collect(); + + for x in xs.iter() { + assert!(set.contains(x)); + } + } + + #[test] + fn test_show() { + let mut set = TrieSet::new(); + let empty = TrieSet::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{}", set); + + assert!(set_str == "{1, 2}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } + + #[test] + fn test_clone() { + let mut a = TrieSet::new(); + + a.insert(1); + a.insert(2); + a.insert(3); + + assert!(a.clone() == a); + } + + #[test] + fn test_lt() { + let mut a = TrieSet::new(); + let mut b = TrieSet::new(); + + assert!(!(a < b) && !(b < a)); + assert!(b.insert(2u)); + assert!(a < b); + assert!(a.insert(3u)); + assert!(!(a < b) && b < a); + assert!(b.insert(1)); + assert!(b < a); + assert!(a.insert(0)); + assert!(a < b); + assert!(a.insert(6)); + assert!(a < b && !(b < a)); + } + + #[test] + fn test_ord() { + let mut a = TrieSet::new(); + let mut b = TrieSet::new(); + + assert!(a <= b && a >= b); + assert!(a.insert(1u)); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + assert!(b.insert(2u)); + assert!(b > a && b >= a); + assert!(a < b && a <= b); + } +} diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs new file mode 100644 index 00000000000..c0bc785126c --- /dev/null +++ b/src/libcollections/vec_map.rs @@ -0,0 +1,1052 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A simple map based on a vector for small integer keys. Space requirements +//! are O(highest integer key). + +#![allow(missing_docs)] + +use core::prelude::*; + +use core::default::Default; +use core::fmt; +use core::iter; +use core::iter::{Enumerate, FilterMap}; +use core::mem::replace; + +use {vec, slice}; +use vec::Vec; +use hash; +use hash::Hash; + +/// A map optimized for small integer keys. +/// +/// # Example +/// +/// ``` +/// use std::collections::VecMap; +/// +/// let mut months = VecMap::new(); +/// months.insert(1, "Jan"); +/// months.insert(2, "Feb"); +/// months.insert(3, "Mar"); +/// +/// if !months.contains_key(&12) { +/// println!("The end is near!"); +/// } +/// +/// assert_eq!(months.find(&1), Some(&"Jan")); +/// +/// match months.find_mut(&3) { +/// Some(value) => *value = "Venus", +/// None => (), +/// } +/// +/// assert_eq!(months.find(&3), Some(&"Venus")); +/// +/// // Print out all months +/// for (key, value) in months.iter() { +/// println!("month {} is {}", key, value); +/// } +/// +/// months.clear(); +/// assert!(months.is_empty()); +/// ``` +#[deriving(PartialEq, Eq)] +pub struct VecMap { + v: Vec>, +} + +impl Default for VecMap { + #[inline] + fn default() -> VecMap { VecMap::new() } +} + +impl Clone for VecMap { + #[inline] + fn clone(&self) -> VecMap { + VecMap { v: self.v.clone() } + } + + #[inline] + fn clone_from(&mut self, source: &VecMap) { + self.v.reserve(source.v.len()); + for (i, w) in self.v.iter_mut().enumerate() { + *w = source.v[i].clone(); + } + } +} + +impl > Hash for VecMap { + fn hash(&self, state: &mut S) { + self.v.hash(state) + } +} + +impl VecMap { + /// Creates an empty `VecMap`. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// let mut map: VecMap<&str> = VecMap::new(); + /// ``` + pub fn new() -> VecMap { VecMap{v: vec!()} } + + /// Creates an empty `VecMap` with space for at least `capacity` + /// elements before resizing. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// let mut map: VecMap<&str> = VecMap::with_capacity(10); + /// ``` + pub fn with_capacity(capacity: uint) -> VecMap { + VecMap { v: Vec::with_capacity(capacity) } + } + + /// Returns an iterator visiting all keys in ascending order by the keys. + /// The iterator's element type is `uint`. + pub fn keys<'r>(&'r self) -> Keys<'r, V> { + self.iter().map(|(k, _v)| k) + } + + /// Returns an iterator visiting all values in ascending order by the keys. + /// The iterator's element type is `&'r V`. + pub fn values<'r>(&'r self) -> Values<'r, V> { + self.iter().map(|(_k, v)| v) + } + + /// Returns an iterator visiting all key-value pairs in ascending order by the keys. + /// The iterator's element type is `(uint, &'r V)`. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// map.insert(3, "c"); + /// map.insert(2, "b"); + /// + /// // Print `1: a` then `2: b` then `3: c` + /// for (key, value) in map.iter() { + /// println!("{}: {}", key, value); + /// } + /// ``` + pub fn iter<'r>(&'r self) -> Entries<'r, V> { + Entries { + front: 0, + back: self.v.len(), + iter: self.v.iter() + } + } + + /// Returns an iterator visiting all key-value pairs in ascending order by the keys, + /// with mutable references to the values. + /// The iterator's element type is `(uint, &'r mut V)`. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// map.insert(2, "b"); + /// map.insert(3, "c"); + /// + /// for (key, value) in map.iter_mut() { + /// *value = "x"; + /// } + /// + /// for (key, value) in map.iter() { + /// assert_eq!(value, &"x"); + /// } + /// ``` + pub fn iter_mut<'r>(&'r mut self) -> MutEntries<'r, V> { + MutEntries { + front: 0, + back: self.v.len(), + iter: self.v.iter_mut() + } + } + + /// Returns an iterator visiting all key-value pairs in ascending order by + /// the keys, emptying (but not consuming) the original `VecMap`. + /// The iterator's element type is `(uint, &'r V)`. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// map.insert(3, "c"); + /// map.insert(2, "b"); + /// + /// // Not possible with .iter() + /// let vec: Vec<(uint, &str)> = map.into_iter().collect(); + /// + /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]); + /// ``` + pub fn into_iter(&mut self) + -> FilterMap<(uint, Option), (uint, V), + Enumerate>>> + { + let values = replace(&mut self.v, vec!()); + values.into_iter().enumerate().filter_map(|(i, v)| { + v.map(|v| (i, v)) + }) + } + + /// Return the number of elements in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut a = VecMap::new(); + /// assert_eq!(a.len(), 0); + /// a.insert(1, "a"); + /// assert_eq!(a.len(), 1); + /// ``` + pub fn len(&self) -> uint { + self.v.iter().filter(|elt| elt.is_some()).count() + } + + /// Return true if the map contains no elements. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut a = VecMap::new(); + /// assert!(a.is_empty()); + /// a.insert(1, "a"); + /// assert!(!a.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + self.v.iter().all(|elt| elt.is_none()) + } + + /// Clears the map, removing all key-value pairs. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut a = VecMap::new(); + /// a.insert(1, "a"); + /// a.clear(); + /// assert!(a.is_empty()); + /// ``` + pub fn clear(&mut self) { self.v.clear() } + + /// Returns a reference to the value corresponding to the key. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.find(&1), Some(&"a")); + /// assert_eq!(map.find(&2), None); + /// ``` + pub fn find<'a>(&'a self, key: &uint) -> Option<&'a V> { + if *key < self.v.len() { + match self.v[*key] { + Some(ref value) => Some(value), + None => None + } + } else { + None + } + } + + /// Returns true if the map contains a value for the specified key. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.contains_key(&1), true); + /// assert_eq!(map.contains_key(&2), false); + /// ``` + #[inline] + pub fn contains_key(&self, key: &uint) -> bool { + self.find(key).is_some() + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// match map.find_mut(&1) { + /// Some(x) => *x = "b", + /// None => (), + /// } + /// assert_eq!(map[1], "b"); + /// ``` + pub fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut V> { + if *key < self.v.len() { + match *(&mut self.v[*key]) { + Some(ref mut value) => Some(value), + None => None + } + } else { + None + } + } + + /// Inserts a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Returns `true` if the key did + /// not already exist in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// assert_eq!(map.insert(2, "value"), true); + /// assert_eq!(map.insert(2, "value2"), false); + /// assert_eq!(map[2], "value2"); + /// ``` + pub fn insert(&mut self, key: uint, value: V) -> bool { + let exists = self.contains_key(&key); + let len = self.v.len(); + if len <= key { + self.v.grow_fn(key - len + 1, |_| None); + } + self.v[key] = Some(value); + !exists + } + + /// Removes a key-value pair from the map. Returns `true` if the key + /// was present in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// assert_eq!(map.remove(&1), false); + /// map.insert(1, "a"); + /// assert_eq!(map.remove(&1), true); + /// ``` + pub fn remove(&mut self, key: &uint) -> bool { + self.pop(key).is_some() + } + + /// Inserts a key-value pair from the map. If the key already had a value + /// present in the map, that value is returned. Otherwise, `None` is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// assert_eq!(map.swap(37, "a"), None); + /// assert_eq!(map.is_empty(), false); + /// + /// map.insert(37, "b"); + /// assert_eq!(map.swap(37, "c"), Some("b")); + /// assert_eq!(map[37], "c"); + /// ``` + pub fn swap(&mut self, key: uint, value: V) -> Option { + match self.find_mut(&key) { + Some(loc) => { return Some(replace(loc, value)); } + None => () + } + self.insert(key, value); + return None; + } + + /// Removes a key from the map, returning the value at the key if the key + /// was previously in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.pop(&1), Some("a")); + /// assert_eq!(map.pop(&1), None); + /// ``` + pub fn pop(&mut self, key: &uint) -> Option { + if *key >= self.v.len() { + return None; + } + self.v[*key].take() + } +} + +impl VecMap { + /// Updates a value in the map. If the key already exists in the map, + /// modifies the value with `ff` taking `oldval, newval`. + /// Otherwise, sets the value to `newval`. + /// Returns `true` if the key did not already exist in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// + /// // Key does not exist, will do a simple insert + /// assert!(map.update(1, vec![1i, 2], |mut old, new| { old.extend(new.into_iter()); old })); + /// assert_eq!(map[1], vec![1i, 2]); + /// + /// // Key exists, update the value + /// assert!(!map.update(1, vec![3i, 4], |mut old, new| { old.extend(new.into_iter()); old })); + /// assert_eq!(map[1], vec![1i, 2, 3, 4]); + /// ``` + pub fn update(&mut self, key: uint, newval: V, ff: |V, V| -> V) -> bool { + self.update_with_key(key, newval, |_k, v, v1| ff(v,v1)) + } + + /// Updates a value in the map. If the key already exists in the map, + /// modifies the value with `ff` taking `key, oldval, newval`. + /// Otherwise, sets the value to `newval`. + /// Returns `true` if the key did not already exist in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// + /// // Key does not exist, will do a simple insert + /// assert!(map.update_with_key(7, 10, |key, old, new| (old + new) % key)); + /// assert_eq!(map[7], 10); + /// + /// // Key exists, update the value + /// assert!(!map.update_with_key(7, 20, |key, old, new| (old + new) % key)); + /// assert_eq!(map[7], 2); + /// ``` + pub fn update_with_key(&mut self, + key: uint, + val: V, + ff: |uint, V, V| -> V) + -> bool { + let new_val = match self.find(&key) { + None => val, + Some(orig) => ff(key, (*orig).clone(), val) + }; + self.insert(key, new_val) + } +} + +impl PartialOrd for VecMap { + #[inline] + fn partial_cmp(&self, other: &VecMap) -> Option { + iter::order::partial_cmp(self.iter(), other.iter()) + } +} + +impl Ord for VecMap { + #[inline] + fn cmp(&self, other: &VecMap) -> Ordering { + iter::order::cmp(self.iter(), other.iter()) + } +} + +impl fmt::Show for VecMap { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, (k, v)) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}: {}", k, *v)); + } + + write!(f, "}}") + } +} + +impl FromIterator<(uint, V)> for VecMap { + fn from_iter>(iter: Iter) -> VecMap { + let mut map = VecMap::new(); + map.extend(iter); + map + } +} + +impl Extendable<(uint, V)> for VecMap { + fn extend>(&mut self, mut iter: Iter) { + for (k, v) in iter { + self.insert(k, v); + } + } +} + +impl Index for VecMap { + #[inline] + fn index<'a>(&'a self, i: &uint) -> &'a V { + self.find(i).expect("key not present") + } +} + +impl IndexMut for VecMap { + #[inline] + fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut V { + self.find_mut(i).expect("key not present") + } +} + +macro_rules! iterator { + (impl $name:ident -> $elem:ty, $($getter:ident),+) => { + impl<'a, T> Iterator<$elem> for $name<'a, T> { + #[inline] + fn next(&mut self) -> Option<$elem> { + while self.front < self.back { + match self.iter.next() { + Some(elem) => { + if elem.is_some() { + let index = self.front; + self.front += 1; + return Some((index, elem $(. $getter ())+)); + } + } + _ => () + } + self.front += 1; + } + None + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + (0, Some(self.back - self.front)) + } + } + } +} + +macro_rules! double_ended_iterator { + (impl $name:ident -> $elem:ty, $($getter:ident),+) => { + impl<'a, T> DoubleEndedIterator<$elem> for $name<'a, T> { + #[inline] + fn next_back(&mut self) -> Option<$elem> { + while self.front < self.back { + match self.iter.next_back() { + Some(elem) => { + if elem.is_some() { + self.back -= 1; + return Some((self.back, elem$(. $getter ())+)); + } + } + _ => () + } + self.back -= 1; + } + None + } + } + } +} + +/// Forward iterator over a map. +pub struct Entries<'a, T:'a> { + front: uint, + back: uint, + iter: slice::Items<'a, Option> +} + +iterator!(impl Entries -> (uint, &'a T), as_ref, unwrap) +double_ended_iterator!(impl Entries -> (uint, &'a T), as_ref, unwrap) + +/// Forward iterator over the key-value pairs of a map, with the +/// values being mutable. +pub struct MutEntries<'a, T:'a> { + front: uint, + back: uint, + iter: slice::MutItems<'a, Option> +} + +iterator!(impl MutEntries -> (uint, &'a mut T), as_mut, unwrap) +double_ended_iterator!(impl MutEntries -> (uint, &'a mut T), as_mut, unwrap) + +/// Forward iterator over the keys of a map +pub type Keys<'a, T> = + iter::Map<'static, (uint, &'a T), uint, Entries<'a, T>>; + +/// Forward iterator over the values of a map +pub type Values<'a, T> = + iter::Map<'static, (uint, &'a T), &'a T, Entries<'a, T>>; + +#[cfg(test)] +mod test_map { + use std::prelude::*; + use vec::Vec; + use hash; + + use super::VecMap; + + #[test] + fn test_find_mut() { + let mut m = VecMap::new(); + assert!(m.insert(1, 12i)); + assert!(m.insert(2, 8)); + assert!(m.insert(5, 14)); + let new = 100; + match m.find_mut(&5) { + None => panic!(), Some(x) => *x = new + } + assert_eq!(m.find(&5), Some(&new)); + } + + #[test] + fn test_len() { + let mut map = VecMap::new(); + assert_eq!(map.len(), 0); + assert!(map.is_empty()); + assert!(map.insert(5, 20i)); + assert_eq!(map.len(), 1); + assert!(!map.is_empty()); + assert!(map.insert(11, 12)); + assert_eq!(map.len(), 2); + assert!(!map.is_empty()); + assert!(map.insert(14, 22)); + assert_eq!(map.len(), 3); + assert!(!map.is_empty()); + } + + #[test] + fn test_clear() { + let mut map = VecMap::new(); + assert!(map.insert(5, 20i)); + assert!(map.insert(11, 12)); + assert!(map.insert(14, 22)); + map.clear(); + assert!(map.is_empty()); + assert!(map.find(&5).is_none()); + assert!(map.find(&11).is_none()); + assert!(map.find(&14).is_none()); + } + + #[test] + fn test_insert_with_key() { + let mut map = VecMap::new(); + + // given a new key, initialize it with this new count, + // given an existing key, add more to its count + fn add_more_to_count(_k: uint, v0: uint, v1: uint) -> uint { + v0 + v1 + } + + fn add_more_to_count_simple(v0: uint, v1: uint) -> uint { + v0 + v1 + } + + // count integers + map.update(3, 1, add_more_to_count_simple); + map.update_with_key(9, 1, add_more_to_count); + map.update(3, 7, add_more_to_count_simple); + map.update_with_key(5, 3, add_more_to_count); + map.update_with_key(3, 2, add_more_to_count); + + // check the total counts + assert_eq!(map.find(&3).unwrap(), &10); + assert_eq!(map.find(&5).unwrap(), &3); + assert_eq!(map.find(&9).unwrap(), &1); + + // sadly, no sevens were counted + assert!(map.find(&7).is_none()); + } + + #[test] + fn test_swap() { + let mut m = VecMap::new(); + assert_eq!(m.swap(1, 2i), None); + assert_eq!(m.swap(1, 3i), Some(2)); + assert_eq!(m.swap(1, 4i), Some(3)); + } + + #[test] + fn test_pop() { + let mut m = VecMap::new(); + m.insert(1, 2i); + assert_eq!(m.pop(&1), Some(2)); + assert_eq!(m.pop(&1), None); + } + + #[test] + fn test_keys() { + let mut map = VecMap::new(); + map.insert(1, 'a'); + map.insert(2, 'b'); + map.insert(3, 'c'); + let keys = map.keys().collect::>(); + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); + } + + #[test] + fn test_values() { + let mut map = VecMap::new(); + map.insert(1, 'a'); + map.insert(2, 'b'); + map.insert(3, 'c'); + let values = map.values().map(|&v| v).collect::>(); + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); + } + + #[test] + fn test_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1i)); + assert!(m.insert(1, 2)); + assert!(m.insert(3, 5)); + assert!(m.insert(6, 10)); + assert!(m.insert(10, 11)); + + let mut it = m.iter(); + assert_eq!(it.size_hint(), (0, Some(11))); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.size_hint(), (0, Some(10))); + assert_eq!(it.next().unwrap(), (1, &2)); + assert_eq!(it.size_hint(), (0, Some(9))); + assert_eq!(it.next().unwrap(), (3, &5)); + assert_eq!(it.size_hint(), (0, Some(7))); + assert_eq!(it.next().unwrap(), (6, &10)); + assert_eq!(it.size_hint(), (0, Some(4))); + assert_eq!(it.next().unwrap(), (10, &11)); + assert_eq!(it.size_hint(), (0, Some(0))); + assert!(it.next().is_none()); + } + + #[test] + fn test_iterator_size_hints() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1i)); + assert!(m.insert(1, 2)); + assert!(m.insert(3, 5)); + assert!(m.insert(6, 10)); + assert!(m.insert(10, 11)); + + assert_eq!(m.iter().size_hint(), (0, Some(11))); + assert_eq!(m.iter().rev().size_hint(), (0, Some(11))); + assert_eq!(m.iter_mut().size_hint(), (0, Some(11))); + assert_eq!(m.iter_mut().rev().size_hint(), (0, Some(11))); + } + + #[test] + fn test_mut_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1i)); + assert!(m.insert(1, 2)); + assert!(m.insert(3, 5)); + assert!(m.insert(6, 10)); + assert!(m.insert(10, 11)); + + for (k, v) in m.iter_mut() { + *v += k as int; + } + + let mut it = m.iter(); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.next().unwrap(), (1, &3)); + assert_eq!(it.next().unwrap(), (3, &8)); + assert_eq!(it.next().unwrap(), (6, &16)); + assert_eq!(it.next().unwrap(), (10, &21)); + assert!(it.next().is_none()); + } + + #[test] + fn test_rev_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1i)); + assert!(m.insert(1, 2)); + assert!(m.insert(3, 5)); + assert!(m.insert(6, 10)); + assert!(m.insert(10, 11)); + + let mut it = m.iter().rev(); + assert_eq!(it.next().unwrap(), (10, &11)); + assert_eq!(it.next().unwrap(), (6, &10)); + assert_eq!(it.next().unwrap(), (3, &5)); + assert_eq!(it.next().unwrap(), (1, &2)); + assert_eq!(it.next().unwrap(), (0, &1)); + assert!(it.next().is_none()); + } + + #[test] + fn test_mut_rev_iterator() { + let mut m = VecMap::new(); + + assert!(m.insert(0, 1i)); + assert!(m.insert(1, 2)); + assert!(m.insert(3, 5)); + assert!(m.insert(6, 10)); + assert!(m.insert(10, 11)); + + for (k, v) in m.iter_mut().rev() { + *v += k as int; + } + + let mut it = m.iter(); + assert_eq!(it.next().unwrap(), (0, &1)); + assert_eq!(it.next().unwrap(), (1, &3)); + assert_eq!(it.next().unwrap(), (3, &8)); + assert_eq!(it.next().unwrap(), (6, &16)); + assert_eq!(it.next().unwrap(), (10, &21)); + assert!(it.next().is_none()); + } + + #[test] + fn test_move_iter() { + let mut m = VecMap::new(); + m.insert(1, box 2i); + let mut called = false; + for (k, v) in m.into_iter() { + assert!(!called); + called = true; + assert_eq!(k, 1); + assert_eq!(v, box 2i); + } + assert!(called); + m.insert(2, box 1i); + } + + #[test] + fn test_show() { + let mut map = VecMap::new(); + let empty = VecMap::::new(); + + map.insert(1, 2i); + map.insert(3, 4i); + + let map_str = map.to_string(); + let map_str = map_str.as_slice(); + assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); + assert_eq!(format!("{}", empty), "{}".to_string()); + } + + #[test] + fn test_clone() { + let mut a = VecMap::new(); + + a.insert(1, 'x'); + a.insert(4, 'y'); + a.insert(6, 'z'); + + assert!(a.clone() == a); + } + + #[test] + fn test_eq() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(a == b); + assert!(a.insert(0, 5i)); + assert!(a != b); + assert!(b.insert(0, 4i)); + assert!(a != b); + assert!(a.insert(5, 19)); + assert!(a != b); + assert!(!b.insert(0, 5)); + assert!(a != b); + assert!(b.insert(5, 19)); + assert!(a == b); + } + + #[test] + fn test_lt() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(!(a < b) && !(b < a)); + assert!(b.insert(2u, 5i)); + assert!(a < b); + assert!(a.insert(2, 7)); + assert!(!(a < b) && b < a); + assert!(b.insert(1, 0)); + assert!(b < a); + assert!(a.insert(0, 6)); + assert!(a < b); + assert!(a.insert(6, 2)); + assert!(a < b && !(b < a)); + } + + #[test] + fn test_ord() { + let mut a = VecMap::new(); + let mut b = VecMap::new(); + + assert!(a <= b && a >= b); + assert!(a.insert(1u, 1i)); + assert!(a > b && a >= b); + assert!(b < a && b <= a); + assert!(b.insert(2, 2)); + assert!(b > a && b >= a); + assert!(a < b && a <= b); + } + + #[test] + fn test_hash() { + let mut x = VecMap::new(); + let mut y = VecMap::new(); + + assert!(hash::hash(&x) == hash::hash(&y)); + x.insert(1, 'a'); + x.insert(2, 'b'); + x.insert(3, 'c'); + + y.insert(3, 'c'); + y.insert(2, 'b'); + y.insert(1, 'a'); + + assert!(hash::hash(&x) == hash::hash(&y)); + } + + #[test] + fn test_from_iter() { + let xs: Vec<(uint, char)> = vec![(1u, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]; + + let map: VecMap = xs.iter().map(|&x| x).collect(); + + for &(k, v) in xs.iter() { + assert_eq!(map.find(&k), Some(&v)); + } + } + + #[test] + fn test_index() { + let mut map: VecMap = VecMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + assert_eq!(map[3], 4); + } + + #[test] + #[should_fail] + fn test_index_nonexistent() { + let mut map: VecMap = VecMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + map[4]; + } +} + +#[cfg(test)] +mod bench { + extern crate test; + use self::test::Bencher; + use super::VecMap; + use bench::{insert_rand_n, insert_seq_n, find_rand_n, find_seq_n}; + + #[bench] + pub fn insert_rand_100(b: &mut Bencher) { + let mut m : VecMap = VecMap::new(); + insert_rand_n(100, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.remove(&i); }); + } + + #[bench] + pub fn insert_rand_10_000(b: &mut Bencher) { + let mut m : VecMap = VecMap::new(); + insert_rand_n(10_000, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.remove(&i); }); + } + + // Insert seq + #[bench] + pub fn insert_seq_100(b: &mut Bencher) { + let mut m : VecMap = VecMap::new(); + insert_seq_n(100, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.remove(&i); }); + } + + #[bench] + pub fn insert_seq_10_000(b: &mut Bencher) { + let mut m : VecMap = VecMap::new(); + insert_seq_n(10_000, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.remove(&i); }); + } + + // Find rand + #[bench] + pub fn find_rand_100(b: &mut Bencher) { + let mut m : VecMap = VecMap::new(); + find_rand_n(100, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.find(&i); }); + } + + #[bench] + pub fn find_rand_10_000(b: &mut Bencher) { + let mut m : VecMap = VecMap::new(); + find_rand_n(10_000, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.find(&i); }); + } + + // Find seq + #[bench] + pub fn find_seq_100(b: &mut Bencher) { + let mut m : VecMap = VecMap::new(); + find_seq_n(100, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.find(&i); }); + } + + #[bench] + pub fn find_seq_10_000(b: &mut Bencher) { + let mut m : VecMap = VecMap::new(); + find_seq_n(10_000, &mut m, b, + |m, i| { m.insert(i, 1); }, + |m, i| { m.find(&i); }); + } +} diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index ace5ba26fdb..a889093852d 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -31,7 +31,7 @@ use syntax::parse; use syntax::parse::token::InternedString; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use getopts::{optopt, optmulti, optflag, optflagopt}; use getopts; use std::cell::{RefCell}; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 3e53620cbd4..e20f76622c9 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -36,7 +36,7 @@ use lint::{Context, LintPass, LintArray}; use std::cmp; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use std::slice; use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; use syntax::abi; diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 92b2382ae64..f53b46dc786 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -24,7 +24,7 @@ use plugin::load::PluginMetadata; use std::rc::Rc; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use syntax::ast; use syntax::abi; use syntax::attr; diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index e6a0363fcbf..ff78491c2ad 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -31,7 +31,7 @@ use syntax::attr; use syntax::diagnostic::expect; use syntax::parse::token; -use std::collections::hashmap::HashMap; +use std::collections::hash_map::HashMap; pub struct MethodInfo { pub name: ast::Name, diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 0df98bfb0b1..20171ecfd99 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -34,7 +34,7 @@ use std::hash::Hash; use std::hash; use std::io::extensions::u64_from_be_bytes; use std::io; -use std::collections::hashmap::HashMap; +use std::collections::hash_map::HashMap; use std::rc::Rc; use std::u64; use rbml::reader; diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 623a763bd74..7b67def4051 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -237,7 +237,7 @@ use std::slice; use std::string; use std::collections::{HashMap, HashSet}; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use flate; use time; diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index ad0040608ec..ce91bd1b153 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -28,7 +28,7 @@ use syntax::visit; use syntax::{ast, ast_map, ast_util, codemap}; use std::rc::Rc; -use std::collections::hashmap::Vacant; +use std::collections::hash_map::Vacant; // // This pass classifies expressions by their constant-ness. diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index c297bdc6ca2..a2bea790c9f 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -58,7 +58,7 @@ use syntax::visit; use syntax::visit::Visitor; use std::collections::{HashMap, HashSet}; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use std::cell::{Cell, RefCell}; use std::mem::replace; use std::rc::{Rc, Weak}; diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index f8c1c37452b..d78c9e3a6e2 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -29,7 +29,7 @@ use middle::typeck::infer; use middle::typeck::infer::{InferCtxt, TypeSkolemizer}; use middle::ty_fold::TypeFoldable; use std::cell::RefCell; -use std::collections::hashmap::HashMap; +use std::collections::hash_map::HashMap; use std::rc::Rc; use syntax::ast; use util::ppaux::Repr; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b9af31665a1..4c088e42243 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -43,7 +43,7 @@ use std::mem; use std::ops; use std::rc::Rc; use std::collections::{HashMap, HashSet}; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use arena::TypedArena; use syntax::abi; use syntax::ast::{CrateNum, DefId, FnStyle, Ident, ItemTrait, LOCAL_CRATE}; diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 97c6cf24f0e..a686a5e72a0 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -19,7 +19,7 @@ use middle::typeck::require_same_types; use std::cmp; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use syntax::ast; use syntax::ast_util; use syntax::codemap::{Span, Spanned}; diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index f334d801692..c280474a076 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -118,7 +118,7 @@ use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; use std::cell::{Cell, Ref, RefCell}; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use std::mem::replace; use std::rc::Rc; use syntax::abi; diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index d0338333bad..acc3cf0307b 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -142,7 +142,7 @@ use syntax::visit::Visitor; use std::cell::{RefCell}; use std::collections::HashMap; -use std::collections::hashmap::{Vacant, Occupied}; +use std::collections::hash_map::{Vacant, Occupied}; /////////////////////////////////////////////////////////////////////////// // PUBLIC ENTRY POINTS diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index 225a3162af9..91e9c18853c 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -18,7 +18,7 @@ use middle::ty_fold::{TypeFolder, TypeFoldable}; use syntax::ast; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use util::ppaux::Repr; // Helper functions related to manipulating region types. diff --git a/src/librustc/middle/typeck/infer/skolemize.rs b/src/librustc/middle/typeck/infer/skolemize.rs index 0fe1e2b565b..6e5e8d72839 100644 --- a/src/librustc/middle/typeck/infer/skolemize.rs +++ b/src/librustc/middle/typeck/infer/skolemize.rs @@ -44,7 +44,7 @@ use middle::ty; use middle::ty_fold; use middle::ty_fold::TypeFoldable; use middle::ty_fold::TypeFolder; -use std::collections::hashmap; +use std::collections::hash_map; use super::InferCtxt; use super::unify::InferCtxtMethodsForSimplyUnifiableTypes; @@ -52,7 +52,7 @@ use super::unify::InferCtxtMethodsForSimplyUnifiableTypes; pub struct TypeSkolemizer<'a, 'tcx:'a> { infcx: &'a InferCtxt<'a, 'tcx>, skolemization_count: uint, - skolemization_map: hashmap::HashMap, + skolemization_map: hash_map::HashMap, } impl<'a, 'tcx> TypeSkolemizer<'a, 'tcx> { @@ -60,7 +60,7 @@ impl<'a, 'tcx> TypeSkolemizer<'a, 'tcx> { TypeSkolemizer { infcx: infcx, skolemization_count: 0, - skolemization_map: hashmap::HashMap::new(), + skolemization_map: hash_map::HashMap::new(), } } @@ -76,8 +76,8 @@ impl<'a, 'tcx> TypeSkolemizer<'a, 'tcx> { } match self.skolemization_map.entry(key) { - hashmap::Occupied(entry) => *entry.get(), - hashmap::Vacant(entry) => { + hash_map::Occupied(entry) => *entry.get(), + hash_map::Vacant(entry) => { let index = self.skolemization_count; self.skolemization_count += 1; let t = ty::mk_infer(self.infcx.tcx, skolemizer(index)); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d1d9702a134..9af2b22adea 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -34,7 +34,7 @@ //! both occur before the crate is rendered. use std::collections::{HashMap, HashSet}; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use std::fmt; use std::io::fs::PathExtensions; use std::io::{fs, File, BufferedWriter, MemWriter, BufferedReader}; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 5f404238beb..bd3c618a5ed 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -31,7 +31,7 @@ extern crate time; use std::io; use std::io::{File, MemWriter}; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; use serialize::{json, Decodable, Encodable}; use externalfiles::ExternalHtml; diff --git a/src/librustrt/local_data.rs b/src/librustrt/local_data.rs index ee69f5f5235..7129f147209 100644 --- a/src/librustrt/local_data.rs +++ b/src/librustrt/local_data.rs @@ -41,7 +41,7 @@ assert_eq!(*key_vector.get().unwrap(), vec![4]); use core::prelude::*; use alloc::heap; -use collections::treemap::TreeMap; +use collections::TreeMap; use core::cmp; use core::kinds::marker; use core::mem; diff --git a/src/libstd/collections/hash/bench.rs b/src/libstd/collections/hash/bench.rs new file mode 100644 index 00000000000..62b93336a34 --- /dev/null +++ b/src/libstd/collections/hash/bench.rs @@ -0,0 +1,130 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg(test)] + +extern crate test; +use prelude::*; + +use self::test::Bencher; +use iter::{range_inclusive}; + +#[bench] +fn new_drop(b : &mut Bencher) { + use super::map::HashMap; + + b.iter(|| { + let m : HashMap = HashMap::new(); + assert_eq!(m.len(), 0); + }) +} + +#[bench] +fn new_insert_drop(b : &mut Bencher) { + use super::map::HashMap; + + b.iter(|| { + let mut m = HashMap::new(); + m.insert(0i, 0i); + assert_eq!(m.len(), 1); + }) +} + +#[bench] +fn grow_by_insertion(b: &mut Bencher) { + use super::map::HashMap; + + let mut m = HashMap::new(); + + for i in range_inclusive(1i, 1000) { + m.insert(i, i); + } + + let mut k = 1001; + + b.iter(|| { + m.insert(k, k); + k += 1; + }); +} + +#[bench] +fn find_existing(b: &mut Bencher) { + use super::map::HashMap; + + let mut m = HashMap::new(); + + for i in range_inclusive(1i, 1000) { + m.insert(i, i); + } + + b.iter(|| { + for i in range_inclusive(1i, 1000) { + m.contains_key(&i); + } + }); +} + +#[bench] +fn find_nonexisting(b: &mut Bencher) { + use super::map::HashMap; + + let mut m = HashMap::new(); + + for i in range_inclusive(1i, 1000) { + m.insert(i, i); + } + + b.iter(|| { + for i in range_inclusive(1001i, 2000) { + m.contains_key(&i); + } + }); +} + +#[bench] +fn hashmap_as_queue(b: &mut Bencher) { + use super::map::HashMap; + + let mut m = HashMap::new(); + + for i in range_inclusive(1i, 1000) { + m.insert(i, i); + } + + let mut k = 1i; + + b.iter(|| { + m.pop(&k); + m.insert(k + 1000, k + 1000); + k += 1; + }); +} + +#[bench] +fn find_pop_insert(b: &mut Bencher) { + use super::map::HashMap; + + let mut m = HashMap::new(); + + for i in range_inclusive(1i, 1000) { + m.insert(i, i); + } + + let mut k = 1i; + + b.iter(|| { + m.find(&(k + 400)); + m.find(&(k + 2000)); + m.pop(&k); + m.insert(k + 1000, k + 1000); + k += 1; + }) +} diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs new file mode 100644 index 00000000000..596e483c2f6 --- /dev/null +++ b/src/libstd/collections/hash/map.rs @@ -0,0 +1,2133 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// ignore-lexer-test FIXME #15883 + +use clone::Clone; +use cmp::{max, Eq, Equiv, PartialEq}; +use default::Default; +use fmt::{mod, Show}; +use hash::{Hash, Hasher, RandomSipHasher}; +use iter::{mod, Iterator, FromIterator, Extendable}; +use kinds::Sized; +use mem::{mod, replace}; +use num; +use ops::{Deref, Index, IndexMut}; +use option::{Some, None, Option}; +use result::{Result, Ok, Err}; + +use super::table; +use super::table::{ + Bucket, + Empty, + EmptyBucket, + Full, + FullBucket, + FullBucketImm, + FullBucketMut, + RawTable, + SafeHash +}; + +const INITIAL_LOG2_CAP: uint = 5; +pub const INITIAL_CAPACITY: uint = 1 << INITIAL_LOG2_CAP; // 2^5 + +/// The default behavior of HashMap implements a load factor of 90.9%. +/// This behavior is characterized by the following conditions: +/// +/// - if size > 0.909 * capacity: grow +/// - if size < 0.25 * capacity: shrink (if this won't bring capacity lower +/// than the minimum) +#[deriving(Clone)] +struct DefaultResizePolicy { + /// Doubled minimal capacity. The capacity must never drop below + /// the minimum capacity. (The check happens before the capacity + /// is potentially halved.) + minimum_capacity2: uint +} + +impl DefaultResizePolicy { + fn new(new_capacity: uint) -> DefaultResizePolicy { + DefaultResizePolicy { + minimum_capacity2: new_capacity << 1 + } + } + + #[inline] + fn capacity_range(&self, new_size: uint) -> (uint, uint) { + // Here, we are rephrasing the logic by specifying the ranges: + // + // - if `size * 1.1 < cap < size * 4`: don't resize + // - if `cap < minimum_capacity * 2`: don't shrink + // - otherwise, resize accordingly + ((new_size * 11) / 10, max(new_size << 2, self.minimum_capacity2)) + } + + #[inline] + fn reserve(&mut self, new_capacity: uint) { + self.minimum_capacity2 = new_capacity << 1; + } +} + +// The main performance trick in this hashmap is called Robin Hood Hashing. +// It gains its excellent performance from one essential operation: +// +// If an insertion collides with an existing element, and that element's +// "probe distance" (how far away the element is from its ideal location) +// is higher than how far we've already probed, swap the elements. +// +// This massively lowers variance in probe distance, and allows us to get very +// high load factors with good performance. The 90% load factor I use is rather +// conservative. +// +// > Why a load factor of approximately 90%? +// +// In general, all the distances to initial buckets will converge on the mean. +// At a load factor of α, the odds of finding the target bucket after k +// probes is approximately 1-α^k. If we set this equal to 50% (since we converge +// on the mean) and set k=8 (64-byte cache line / 8-byte hash), α=0.92. I round +// this down to make the math easier on the CPU and avoid its FPU. +// Since on average we start the probing in the middle of a cache line, this +// strategy pulls in two cache lines of hashes on every lookup. I think that's +// pretty good, but if you want to trade off some space, it could go down to one +// cache line on average with an α of 0.84. +// +// > Wait, what? Where did you get 1-α^k from? +// +// On the first probe, your odds of a collision with an existing element is α. +// The odds of doing this twice in a row is approximately α^2. For three times, +// α^3, etc. Therefore, the odds of colliding k times is α^k. The odds of NOT +// colliding after k tries is 1-α^k. +// +// The paper from 1986 cited below mentions an implementation which keeps track +// of the distance-to-initial-bucket histogram. This approach is not suitable +// for modern architectures because it requires maintaining an internal data +// structure. This allows very good first guesses, but we are most concerned +// with guessing entire cache lines, not individual indexes. Furthermore, array +// accesses are no longer linear and in one direction, as we have now. There +// is also memory and cache pressure that this would entail that would be very +// difficult to properly see in a microbenchmark. +// +// ## Future Improvements (FIXME!) +// +// Allow the load factor to be changed dynamically and/or at initialization. +// +// Also, would it be possible for us to reuse storage when growing the +// underlying table? This is exactly the use case for 'realloc', and may +// be worth exploring. +// +// ## Future Optimizations (FIXME!) +// +// Another possible design choice that I made without any real reason is +// parameterizing the raw table over keys and values. Technically, all we need +// is the size and alignment of keys and values, and the code should be just as +// efficient (well, we might need one for power-of-two size and one for not...). +// This has the potential to reduce code bloat in rust executables, without +// really losing anything except 4 words (key size, key alignment, val size, +// val alignment) which can be passed in to every call of a `RawTable` function. +// This would definitely be an avenue worth exploring if people start complaining +// about the size of rust executables. +// +// Annotate exceedingly likely branches in `table::make_hash` +// and `search_hashed_generic` to reduce instruction cache pressure +// and mispredictions once it becomes possible (blocked on issue #11092). +// +// Shrinking the table could simply reallocate in place after moving buckets +// to the first half. +// +// The growth algorithm (fragment of the Proof of Correctness) +// -------------------- +// +// The growth algorithm is basically a fast path of the naive reinsertion- +// during-resize algorithm. Other paths should never be taken. +// +// Consider growing a robin hood hashtable of capacity n. Normally, we do this +// by allocating a new table of capacity `2n`, and then individually reinsert +// each element in the old table into the new one. This guarantees that the +// new table is a valid robin hood hashtable with all the desired statistical +// properties. Remark that the order we reinsert the elements in should not +// matter. For simplicity and efficiency, we will consider only linear +// reinsertions, which consist of reinserting all elements in the old table +// into the new one by increasing order of index. However we will not be +// starting our reinsertions from index 0 in general. If we start from index +// i, for the purpose of reinsertion we will consider all elements with real +// index j < i to have virtual index n + j. +// +// Our hash generation scheme consists of generating a 64-bit hash and +// truncating the most significant bits. When moving to the new table, we +// simply introduce a new bit to the front of the hash. Therefore, if an +// elements has ideal index i in the old table, it can have one of two ideal +// locations in the new table. If the new bit is 0, then the new ideal index +// is i. If the new bit is 1, then the new ideal index is n + i. Intutively, +// we are producing two independent tables of size n, and for each element we +// independently choose which table to insert it into with equal probability. +// However the rather than wrapping around themselves on overflowing their +// indexes, the first table overflows into the first, and the first into the +// second. Visually, our new table will look something like: +// +// [yy_xxx_xxxx_xxx|xx_yyy_yyyy_yyy] +// +// Where x's are elements inserted into the first table, y's are elements +// inserted into the second, and _'s are empty sections. We now define a few +// key concepts that we will use later. Note that this is a very abstract +// perspective of the table. A real resized table would be at least half +// empty. +// +// Theorem: A linear robin hood reinsertion from the first ideal element +// produces identical results to a linear naive reinsertion from the same +// element. +// +// FIXME(Gankro, pczarn): review the proof and put it all in a separate doc.rs + +/// A hash map implementation which uses linear probing with Robin +/// Hood bucket stealing. +/// +/// The hashes are all keyed by the task-local random number generator +/// on creation by default. This means that the ordering of the keys is +/// randomized, but makes the tables more resistant to +/// denial-of-service attacks (Hash DoS). This behaviour can be +/// overridden with one of the constructors. +/// +/// It is required that the keys implement the `Eq` and `Hash` traits, although +/// this can frequently be achieved by using `#[deriving(Eq, Hash)]`. +/// +/// Relevant papers/articles: +/// +/// 1. Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf) +/// 2. Emmanuel Goossaert. ["Robin Hood +/// hashing"](http://codecapsule.com/2013/11/11/robin-hood-hashing/) +/// 3. Emmanuel Goossaert. ["Robin Hood hashing: backward shift +/// deletion"](http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/) +/// +/// # Example +/// +/// ``` +/// use std::collections::HashMap; +/// +/// // type inference lets us omit an explicit type signature (which +/// // would be `HashMap<&str, &str>` in this example). +/// let mut book_reviews = HashMap::new(); +/// +/// // review some books. +/// book_reviews.insert("Adventures of Huckleberry Finn", "My favorite book."); +/// book_reviews.insert("Grimms' Fairy Tales", "Masterpiece."); +/// book_reviews.insert("Pride and Prejudice", "Very enjoyable."); +/// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot."); +/// +/// // check for a specific one. +/// if !book_reviews.contains_key(&("Les Misérables")) { +/// println!("We've got {} reviews, but Les Misérables ain't one.", +/// book_reviews.len()); +/// } +/// +/// // oops, this review has a lot of spelling mistakes, let's delete it. +/// book_reviews.remove(&("The Adventures of Sherlock Holmes")); +/// +/// // look up the values associated with some keys. +/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"]; +/// for book in to_find.iter() { +/// match book_reviews.find(book) { +/// Some(review) => println!("{}: {}", *book, *review), +/// None => println!("{} is unreviewed.", *book) +/// } +/// } +/// +/// // iterate over everything. +/// for (book, review) in book_reviews.iter() { +/// println!("{}: \"{}\"", *book, *review); +/// } +/// ``` +/// +/// The easiest way to use `HashMap` with a custom type is to derive `Eq` and `Hash`. +/// We must also derive `PartialEq`. +/// +/// ``` +/// use std::collections::HashMap; +/// +/// #[deriving(Hash, Eq, PartialEq, Show)] +/// struct Viking<'a> { +/// name: &'a str, +/// power: uint, +/// } +/// +/// let mut vikings = HashMap::new(); +/// +/// vikings.insert("Norway", Viking { name: "Einar", power: 9u }); +/// vikings.insert("Denmark", Viking { name: "Olaf", power: 4u }); +/// vikings.insert("Iceland", Viking { name: "Harald", power: 8u }); +/// +/// // Use derived implementation to print the vikings. +/// for (land, viking) in vikings.iter() { +/// println!("{} at {}", viking, land); +/// } +/// ``` +#[deriving(Clone)] +pub struct HashMap { + // All hashes are keyed on these values, to prevent hash collision attacks. + hasher: H, + + table: RawTable, + + // We keep this at the end since it might as well have tail padding. + resize_policy: DefaultResizePolicy, +} + +/// Search for a pre-hashed key. +fn search_hashed_generic>>(table: M, + hash: &SafeHash, + is_match: |&K| -> bool) + -> SearchResult { + let size = table.size(); + let mut probe = Bucket::new(table, hash); + let ib = probe.index(); + + while probe.index() != ib + size { + let full = match probe.peek() { + Empty(b) => return TableRef(b.into_table()), // hit an empty bucket + Full(b) => b + }; + + if full.distance() + ib < full.index() { + // We can finish the search early if we hit any bucket + // with a lower distance to initial bucket than we've probed. + return TableRef(full.into_table()); + } + + // If the hash doesn't match, it can't be this one.. + if *hash == full.hash() { + let matched = { + let (k, _) = full.read(); + is_match(k) + }; + + // If the key doesn't match, it can't be this one.. + if matched { + return FoundExisting(full); + } + } + + probe = full.next(); + } + + TableRef(probe.into_table()) +} + +fn search_hashed>>(table: M, hash: &SafeHash, k: &K) + -> SearchResult { + search_hashed_generic(table, hash, |k_| *k == *k_) +} + +fn pop_internal(starting_bucket: FullBucketMut) -> (K, V) { + let (empty, retkey, retval) = starting_bucket.take(); + let mut gap = match empty.gap_peek() { + Some(b) => b, + None => return (retkey, retval) + }; + + while gap.full().distance() != 0 { + gap = match gap.shift() { + Some(b) => b, + None => break + }; + } + + // Now we've done all our shifting. Return the value we grabbed earlier. + return (retkey, retval); +} + +/// Perform robin hood bucket stealing at the given `bucket`. You must +/// also pass the position of that bucket's initial bucket so we don't have +/// to recalculate it. +/// +/// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable. +fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>, + mut ib: uint, + mut hash: SafeHash, + mut k: K, + mut v: V) + -> &'a mut V { + let starting_index = bucket.index(); + let size = { + let table = bucket.table(); // FIXME "lifetime too short". + table.size() + }; + // There can be at most `size - dib` buckets to displace, because + // in the worst case, there are `size` elements and we already are + // `distance` buckets away from the initial one. + let idx_end = starting_index + size - bucket.distance(); + + loop { + let (old_hash, old_key, old_val) = bucket.replace(hash, k, v); + loop { + let probe = bucket.next(); + assert!(probe.index() != idx_end); + + let full_bucket = match probe.peek() { + table::Empty(bucket) => { + // Found a hole! + let b = bucket.put(old_hash, old_key, old_val); + // Now that it's stolen, just read the value's pointer + // right out of the table! + let (_, v) = Bucket::at_index(b.into_table(), starting_index).peek() + .expect_full() + .into_mut_refs(); + return v; + }, + table::Full(bucket) => bucket + }; + + let probe_ib = full_bucket.index() - full_bucket.distance(); + + bucket = full_bucket; + + // Robin hood! Steal the spot. + if ib < probe_ib { + ib = probe_ib; + hash = old_hash; + k = old_key; + v = old_val; + break; + } + } + } +} + +/// A result that works like Option> but preserves +/// the reference that grants us access to the table in any case. +enum SearchResult { + // This is an entry that holds the given key: + FoundExisting(FullBucket), + + // There was no such entry. The reference is given back: + TableRef(M) +} + +impl SearchResult { + fn into_option(self) -> Option> { + match self { + FoundExisting(bucket) => Some(bucket), + TableRef(_) => None + } + } +} + +impl, V, S, H: Hasher> HashMap { + fn make_hash>(&self, x: &X) -> SafeHash { + table::make_hash(&self.hasher, x) + } + + fn search_equiv<'a, Sized? Q: Hash + Equiv>(&'a self, q: &Q) + -> Option> { + let hash = self.make_hash(q); + search_hashed_generic(&self.table, &hash, |k| q.equiv(k)).into_option() + } + + fn search_equiv_mut<'a, Sized? Q: Hash + Equiv>(&'a mut self, q: &Q) + -> Option> { + let hash = self.make_hash(q); + search_hashed_generic(&mut self.table, &hash, |k| q.equiv(k)).into_option() + } + + /// Search for a key, yielding the index if it's found in the hashtable. + /// If you already have the hash for the key lying around, use + /// search_hashed. + fn search<'a>(&'a self, k: &K) -> Option> { + let hash = self.make_hash(k); + search_hashed(&self.table, &hash, k).into_option() + } + + fn search_mut<'a>(&'a mut self, k: &K) -> Option> { + let hash = self.make_hash(k); + search_hashed(&mut self.table, &hash, k).into_option() + } + + // The caller should ensure that invariants by Robin Hood Hashing hold. + fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) { + let cap = self.table.capacity(); + let mut buckets = Bucket::new(&mut self.table, &hash); + let ib = buckets.index(); + + while buckets.index() != ib + cap { + // We don't need to compare hashes for value swap. + // Not even DIBs for Robin Hood. + buckets = match buckets.peek() { + Empty(empty) => { + empty.put(hash, k, v); + return; + } + Full(b) => b.into_bucket() + }; + buckets.next(); + } + panic!("Internal HashMap error: Out of space."); + } +} + +impl HashMap { + /// Create an empty HashMap. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10); + /// ``` + #[inline] + pub fn new() -> HashMap { + let hasher = RandomSipHasher::new(); + HashMap::with_hasher(hasher) + } + + /// Creates an empty hash map with the given initial capacity. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10); + /// ``` + #[inline] + pub fn with_capacity(capacity: uint) -> HashMap { + let hasher = RandomSipHasher::new(); + HashMap::with_capacity_and_hasher(capacity, hasher) + } +} + +impl, V, S, H: Hasher> HashMap { + /// Creates an empty hashmap which will use the given hasher to hash keys. + /// + /// The creates map has the default initial capacity. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// use std::hash::sip::SipHasher; + /// + /// let h = SipHasher::new(); + /// let mut map = HashMap::with_hasher(h); + /// map.insert(1i, 2u); + /// ``` + #[inline] + pub fn with_hasher(hasher: H) -> HashMap { + HashMap { + hasher: hasher, + resize_policy: DefaultResizePolicy::new(INITIAL_CAPACITY), + table: RawTable::new(0), + } + } + + /// Create an empty HashMap with space for at least `capacity` + /// elements, using `hasher` to hash the keys. + /// + /// Warning: `hasher` is normally randomly generated, and + /// is designed to allow HashMaps to be resistant to attacks that + /// cause many collisions and very poor performance. Setting it + /// manually using this function can expose a DoS attack vector. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// use std::hash::sip::SipHasher; + /// + /// let h = SipHasher::new(); + /// let mut map = HashMap::with_capacity_and_hasher(10, h); + /// map.insert(1i, 2u); + /// ``` + #[inline] + pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap { + let cap = num::next_power_of_two(max(INITIAL_CAPACITY, capacity)); + HashMap { + hasher: hasher, + resize_policy: DefaultResizePolicy::new(cap), + table: RawTable::new(cap), + } + } + + /// The hashtable will never try to shrink below this size. You can use + /// this function to reduce reallocations if your hashtable frequently + /// grows and shrinks by large amounts. + /// + /// This function has no effect on the operational semantics of the + /// hashtable, only on performance. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// let mut map: HashMap<&str, int> = HashMap::new(); + /// map.reserve(10); + /// ``` + pub fn reserve(&mut self, new_minimum_capacity: uint) { + let cap = num::next_power_of_two( + max(INITIAL_CAPACITY, new_minimum_capacity)); + + self.resize_policy.reserve(cap); + + if self.table.capacity() < cap { + self.resize(cap); + } + } + + /// Resizes the internal vectors to a new capacity. It's your responsibility to: + /// 1) Make sure the new capacity is enough for all the elements, accounting + /// for the load factor. + /// 2) Ensure new_capacity is a power of two. + fn resize(&mut self, new_capacity: uint) { + assert!(self.table.size() <= new_capacity); + assert!(num::is_power_of_two(new_capacity)); + + let mut old_table = replace(&mut self.table, RawTable::new(new_capacity)); + let old_size = old_table.size(); + + if old_table.capacity() == 0 || old_table.size() == 0 { + return; + } + + if new_capacity < old_table.capacity() { + // Shrink the table. Naive algorithm for resizing: + for (h, k, v) in old_table.into_iter() { + self.insert_hashed_nocheck(h, k, v); + } + } else { + // Grow the table. + // Specialization of the other branch. + let mut bucket = Bucket::first(&mut old_table); + + // "So a few of the first shall be last: for many be called, + // but few chosen." + // + // We'll most likely encounter a few buckets at the beginning that + // have their initial buckets near the end of the table. They were + // placed at the beginning as the probe wrapped around the table + // during insertion. We must skip forward to a bucket that won't + // get reinserted too early and won't unfairly steal others spot. + // This eliminates the need for robin hood. + loop { + bucket = match bucket.peek() { + Full(full) => { + if full.distance() == 0 { + // This bucket occupies its ideal spot. + // It indicates the start of another "cluster". + bucket = full.into_bucket(); + break; + } + // Leaving this bucket in the last cluster for later. + full.into_bucket() + } + Empty(b) => { + // Encountered a hole between clusters. + b.into_bucket() + } + }; + bucket.next(); + } + + // This is how the buckets might be laid out in memory: + // ($ marks an initialized bucket) + // ________________ + // |$$$_$$$$$$_$$$$$| + // + // But we've skipped the entire initial cluster of buckets + // and will continue iteration in this order: + // ________________ + // |$$$$$$_$$$$$ + // ^ wrap around once end is reached + // ________________ + // $$$_____________| + // ^ exit once table.size == 0 + loop { + bucket = match bucket.peek() { + Full(bucket) => { + let h = bucket.hash(); + let (b, k, v) = bucket.take(); + self.insert_hashed_ordered(h, k, v); + { + let t = b.table(); // FIXME "lifetime too short". + if t.size() == 0 { break } + }; + b.into_bucket() + } + Empty(b) => b.into_bucket() + }; + bucket.next(); + } + } + + assert_eq!(self.table.size(), old_size); + } + + /// Performs any necessary resize operations, such that there's space for + /// new_size elements. + fn make_some_room(&mut self, new_size: uint) { + let (grow_at, shrink_at) = self.resize_policy.capacity_range(new_size); + let cap = self.table.capacity(); + + // An invalid value shouldn't make us run out of space. + debug_assert!(grow_at >= new_size); + + if cap <= grow_at { + let new_capacity = max(cap << 1, INITIAL_CAPACITY); + self.resize(new_capacity); + } else if shrink_at <= cap { + let new_capacity = cap >> 1; + self.resize(new_capacity); + } + } + + /// Insert a pre-hashed key-value pair, without first checking + /// that there's enough room in the buckets. Returns a reference to the + /// newly insert value. + /// + /// If the key already exists, the hashtable will be returned untouched + /// and a reference to the existing element will be returned. + fn insert_hashed_nocheck(&mut self, hash: SafeHash, k: K, v: V) -> &mut V { + self.insert_or_replace_with(hash, k, v, |_, _, _| ()) + } + + fn insert_or_replace_with<'a>(&'a mut self, + hash: SafeHash, + k: K, + v: V, + found_existing: |&mut K, &mut V, V|) + -> &'a mut V { + // Worst case, we'll find one empty bucket among `size + 1` buckets. + let size = self.table.size(); + let mut probe = Bucket::new(&mut self.table, &hash); + let ib = probe.index(); + + loop { + let mut bucket = match probe.peek() { + Empty(bucket) => { + // Found a hole! + let bucket = bucket.put(hash, k, v); + let (_, val) = bucket.into_mut_refs(); + return val; + }, + Full(bucket) => bucket + }; + + if bucket.hash() == hash { + let found_match = { + let (bucket_k, _) = bucket.read_mut(); + k == *bucket_k + }; + if found_match { + let (bucket_k, bucket_v) = bucket.into_mut_refs(); + debug_assert!(k == *bucket_k); + // Key already exists. Get its reference. + found_existing(bucket_k, bucket_v, v); + return bucket_v; + } + } + + let robin_ib = bucket.index() as int - bucket.distance() as int; + + if (ib as int) < robin_ib { + // Found a luckier bucket than me. Better steal his spot. + return robin_hood(bucket, robin_ib as uint, hash, k, v); + } + + probe = bucket.next(); + assert!(probe.index() != ib + size + 1); + } + } + + /// Retrieves a mutable value for the given key. + /// See [`find_mut`](../trait.MutableMap.html#tymethod.find_mut) for a non-panicking + /// alternative. + /// + /// # Failure + /// + /// Fails if the key is not present. + /// + /// # Example + /// + /// ``` + /// # #![allow(deprecated)] + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1i); + /// { + /// // val will freeze map to prevent usage during its lifetime + /// let val = map.get_mut(&"a"); + /// *val = 40; + /// } + /// assert_eq!(map["a"], 40); + /// + /// // A more direct way could be: + /// *map.get_mut(&"a") = -2; + /// assert_eq!(map["a"], -2); + /// ``` + #[deprecated = "use indexing instead: `&mut map[key]`"] + pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V { + &mut self[*k] + } + + /// Return true if the map contains a value for the specified key, + /// using equivalence. + /// + /// See [pop_equiv](#method.pop_equiv) for an extended example. + pub fn contains_key_equiv + Equiv>(&self, key: &Q) -> bool { + self.search_equiv(key).is_some() + } + + /// Return the value corresponding to the key in the map, using + /// equivalence. + /// + /// See [pop_equiv](#method.pop_equiv) for an extended example. + pub fn find_equiv<'a, Sized? Q: Hash + Equiv>(&'a self, k: &Q) -> Option<&'a V> { + match self.search_equiv(k) { + None => None, + Some(bucket) => { + let (_, v_ref) = bucket.into_refs(); + Some(v_ref) + } + } + } + + /// Remove an equivalent key from the map, returning the value at the + /// key if the key was previously in the map. + /// + /// # Example + /// + /// This is a slightly silly example where we define the number's + /// parity as the equivalence class. It is important that the + /// values hash the same, which is why we implement `Hash`. + /// + /// ``` + /// use std::collections::HashMap; + /// use std::hash::Hash; + /// use std::hash::sip::SipState; + /// + /// #[deriving(Eq, PartialEq)] + /// struct EvenOrOdd { + /// num: uint + /// }; + /// + /// impl Hash for EvenOrOdd { + /// fn hash(&self, state: &mut SipState) { + /// let parity = self.num % 2; + /// parity.hash(state); + /// } + /// } + /// + /// impl Equiv for EvenOrOdd { + /// fn equiv(&self, other: &EvenOrOdd) -> bool { + /// self.num % 2 == other.num % 2 + /// } + /// } + /// + /// let mut map = HashMap::new(); + /// map.insert(EvenOrOdd { num: 3 }, "foo"); + /// + /// assert!(map.contains_key_equiv(&EvenOrOdd { num: 1 })); + /// assert!(!map.contains_key_equiv(&EvenOrOdd { num: 4 })); + /// + /// assert_eq!(map.find_equiv(&EvenOrOdd { num: 5 }), Some(&"foo")); + /// assert_eq!(map.find_equiv(&EvenOrOdd { num: 2 }), None); + /// + /// assert_eq!(map.pop_equiv(&EvenOrOdd { num: 1 }), Some("foo")); + /// assert_eq!(map.pop_equiv(&EvenOrOdd { num: 2 }), None); + /// + /// ``` + #[experimental] + pub fn pop_equiv + Equiv>(&mut self, k: &Q) -> Option { + if self.table.size() == 0 { + return None + } + + let potential_new_size = self.table.size() - 1; + self.make_some_room(potential_new_size); + + match self.search_equiv_mut(k) { + Some(bucket) => { + let (_k, val) = pop_internal(bucket); + Some(val) + } + _ => None + } + } + + /// An iterator visiting all keys in arbitrary order. + /// Iterator element type is `&'a K`. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1i); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// for key in map.keys() { + /// println!("{}", key); + /// } + /// ``` + pub fn keys(&self) -> Keys { + self.iter().map(|(k, _v)| k) + } + + /// An iterator visiting all values in arbitrary order. + /// Iterator element type is `&'a V`. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1i); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// for key in map.values() { + /// println!("{}", key); + /// } + /// ``` + pub fn values(&self) -> Values { + self.iter().map(|(_k, v)| v) + } + + /// An iterator visiting all key-value pairs in arbitrary order. + /// Iterator element type is `(&'a K, &'a V)`. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1i); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// for (key, val) in map.iter() { + /// println!("key: {} val: {}", key, val); + /// } + /// ``` + pub fn iter(&self) -> Entries { + Entries { inner: self.table.iter() } + } + + /// An iterator visiting all key-value pairs in arbitrary order, + /// with mutable references to the values. + /// Iterator element type is `(&'a K, &'a mut V)`. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1i); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// // Update all values + /// for (_, val) in map.iter_mut() { + /// *val *= 2; + /// } + /// + /// for (key, val) in map.iter() { + /// println!("key: {} val: {}", key, val); + /// } + /// ``` + pub fn iter_mut(&mut self) -> MutEntries { + MutEntries { inner: self.table.iter_mut() } + } + + /// Creates a consuming iterator, that is, one that moves each key-value + /// pair out of the map in arbitrary order. The map cannot be used after + /// calling this. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert("a", 1i); + /// map.insert("b", 2); + /// map.insert("c", 3); + /// + /// // Not possible with .iter() + /// let vec: Vec<(&str, int)> = map.into_iter().collect(); + /// ``` + pub fn into_iter(self) -> MoveEntries { + MoveEntries { + inner: self.table.into_iter().map(|(_, k, v)| (k, v)) + } + } + + /// Gets the given key's corresponding entry in the map for in-place manipulation + pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V> { + // Gotta resize now, and we don't know which direction, so try both? + let size = self.table.size(); + self.make_some_room(size + 1); + if size > 0 { + self.make_some_room(size - 1); + } + + let hash = self.make_hash(&key); + search_entry_hashed(&mut self.table, hash, key) + } + + /// Return the number of elements in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut a = HashMap::new(); + /// assert_eq!(a.len(), 0); + /// a.insert(1u, "a"); + /// assert_eq!(a.len(), 1); + /// ``` + pub fn len(&self) -> uint { self.table.size() } + + /// Return true if the map contains no elements. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut a = HashMap::new(); + /// assert!(a.is_empty()); + /// a.insert(1u, "a"); + /// assert!(!a.is_empty()); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Clears the map, removing all key-value pairs. Keeps the allocated memory + /// for reuse. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut a = HashMap::new(); + /// a.insert(1u, "a"); + /// a.clear(); + /// assert!(a.is_empty()); + /// ``` + pub fn clear(&mut self) { + // Prevent reallocations from happening from now on. Makes it possible + // for the map to be reused but has a downside: reserves permanently. + self.resize_policy.reserve(self.table.size()); + + let cap = self.table.capacity(); + let mut buckets = Bucket::first(&mut self.table); + + while buckets.index() != cap { + buckets = match buckets.peek() { + Empty(b) => b.next(), + Full(full) => { + let (b, _, _) = full.take(); + b.next() + } + }; + } + } + + /// Returns a reference to the value corresponding to the key. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert(1u, "a"); + /// assert_eq!(map.find(&1), Some(&"a")); + /// assert_eq!(map.find(&2), None); + /// ``` + pub fn find<'a>(&'a self, k: &K) -> Option<&'a V> { + self.search(k).map(|bucket| { + let (_, v) = bucket.into_refs(); + v + }) + } + + /// Returns true if the map contains a value for the specified key. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert(1u, "a"); + /// assert_eq!(map.contains_key(&1), true); + /// assert_eq!(map.contains_key(&2), false); + /// ``` + pub fn contains_key(&self, k: &K) -> bool { + self.search(k).is_some() + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert(1u, "a"); + /// match map.find_mut(&1) { + /// Some(x) => *x = "b", + /// None => (), + /// } + /// assert_eq!(map[1], "b"); + /// ``` + pub fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> { + match self.search_mut(k) { + Some(bucket) => { + let (_, v) = bucket.into_mut_refs(); + Some(v) + } + _ => None + } + } + + /// Inserts a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Returns `true` if the key did + /// not already exist in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// assert_eq!(map.insert(2u, "value"), true); + /// assert_eq!(map.insert(2, "value2"), false); + /// assert_eq!(map[2], "value2"); + /// ``` + #[inline] + pub fn insert(&mut self, key: K, value: V) -> bool { + self.swap(key, value).is_none() + } + + /// Removes a key-value pair from the map. Returns `true` if the key + /// was present in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// assert_eq!(map.remove(&1u), false); + /// map.insert(1, "a"); + /// assert_eq!(map.remove(&1), true); + /// ``` + #[inline] + pub fn remove(&mut self, key: &K) -> bool { + self.pop(key).is_some() + } + + /// Inserts a key-value pair from the map. If the key already had a value + /// present in the map, that value is returned. Otherwise, `None` is returned. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// assert_eq!(map.swap(37u, "a"), None); + /// assert_eq!(map.is_empty(), false); + /// + /// map.insert(37, "b"); + /// assert_eq!(map.swap(37, "c"), Some("b")); + /// assert_eq!(map[37], "c"); + /// ``` + pub fn swap(&mut self, k: K, v: V) -> Option { + let hash = self.make_hash(&k); + let potential_new_size = self.table.size() + 1; + self.make_some_room(potential_new_size); + + let mut retval = None; + self.insert_or_replace_with(hash, k, v, |_, val_ref, val| { + retval = Some(replace(val_ref, val)); + }); + retval + } + + /// Removes a key from the map, returning the value at the key if the key + /// was previously in the map. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert(1u, "a"); + /// assert_eq!(map.pop(&1), Some("a")); + /// assert_eq!(map.pop(&1), None); + /// ``` + pub fn pop(&mut self, k: &K) -> Option { + if self.table.size() == 0 { + return None + } + + let potential_new_size = self.table.size() - 1; + self.make_some_room(potential_new_size); + + self.search_mut(k).map(|bucket| { + let (_k, val) = pop_internal(bucket); + val + }) + } +} + +fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable, hash: SafeHash, k: K) + -> Entry<'a, K, V> { + // Worst case, we'll find one empty bucket among `size + 1` buckets. + let size = table.size(); + let mut probe = Bucket::new(table, &hash); + let ib = probe.index(); + + loop { + let bucket = match probe.peek() { + Empty(bucket) => { + // Found a hole! + return Vacant(VacantEntry { + hash: hash, + key: k, + elem: NoElem(bucket), + }); + }, + Full(bucket) => bucket + }; + + if bucket.hash() == hash { + let is_eq = { + let (bucket_k, _) = bucket.read(); + k == *bucket_k + }; + + if is_eq { + return Occupied(OccupiedEntry{ + elem: bucket, + }); + } + } + + let robin_ib = bucket.index() as int - bucket.distance() as int; + + if (ib as int) < robin_ib { + // Found a luckier bucket than me. Better steal his spot. + return Vacant(VacantEntry { + hash: hash, + key: k, + elem: NeqElem(bucket, robin_ib as uint), + }); + } + + probe = bucket.next(); + assert!(probe.index() != ib + size + 1); + } +} + +impl, V: Clone, S, H: Hasher> HashMap { + /// Return a copy of the value corresponding to the key. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map: HashMap = HashMap::new(); + /// map.insert(1u, "foo".to_string()); + /// let s: String = map.find_copy(&1).unwrap(); + /// ``` + pub fn find_copy(&self, k: &K) -> Option { + self.find(k).map(|v| (*v).clone()) + } + + /// Return a copy of the value corresponding to the key. + /// + /// # Failure + /// + /// Fails if the key is not present. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map: HashMap = HashMap::new(); + /// map.insert(1u, "foo".to_string()); + /// let s: String = map.get_copy(&1); + /// ``` + pub fn get_copy(&self, k: &K) -> V { + self[*k].clone() + } +} + +impl, V: PartialEq, S, H: Hasher> PartialEq for HashMap { + fn eq(&self, other: &HashMap) -> bool { + if self.len() != other.len() { return false; } + + self.iter().all(|(key, value)| + other.find(key).map_or(false, |v| *value == *v) + ) + } +} + +impl, V: Eq, S, H: Hasher> Eq for HashMap {} + +impl + Show, V: Show, S, H: Hasher> Show for HashMap { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, (k, v)) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}: {}", *k, *v)); + } + + write!(f, "}}") + } +} + +impl, V, S, H: Hasher + Default> Default for HashMap { + fn default() -> HashMap { + HashMap::with_hasher(Default::default()) + } +} + +impl, V, S, H: Hasher> Index for HashMap { + #[inline] + fn index<'a>(&'a self, index: &K) -> &'a V { + self.find(index).expect("no entry found for key") + } +} + +impl, V, S, H: Hasher> IndexMut for HashMap { + #[inline] + fn index_mut<'a>(&'a mut self, index: &K) -> &'a mut V { + match self.find_mut(index) { + Some(v) => v, + None => panic!("no entry found for key") + } + } +} + +/// HashMap iterator +pub struct Entries<'a, K: 'a, V: 'a> { + inner: table::Entries<'a, K, V> +} + +/// HashMap mutable values iterator +pub struct MutEntries<'a, K: 'a, V: 'a> { + inner: table::MutEntries<'a, K, V> +} + +/// HashMap move iterator +pub struct MoveEntries { + inner: iter::Map<'static, (SafeHash, K, V), (K, V), table::MoveEntries> +} + +/// A view into a single occupied location in a HashMap +pub struct OccupiedEntry<'a, K:'a, V:'a> { + elem: FullBucket>, +} + +/// A view into a single empty location in a HashMap +pub struct VacantEntry<'a, K:'a, V:'a> { + hash: SafeHash, + key: K, + elem: VacantEntryState>, +} + +/// A view into a single location in a map, which may be vacant or occupied +pub enum Entry<'a, K:'a, V:'a> { + /// An occupied Entry + Occupied(OccupiedEntry<'a, K, V>), + /// A vacant Entry + Vacant(VacantEntry<'a, K, V>), +} + +/// Possible states of a VacantEntry +enum VacantEntryState { + /// The index is occupied, but the key to insert has precedence, + /// and will kick the current one out on insertion + NeqElem(FullBucket, uint), + /// The index is genuinely vacant + NoElem(EmptyBucket), +} + +impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> { + #[inline] + fn next(&mut self) -> Option<(&'a K, &'a V)> { + self.inner.next() + } + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.inner.size_hint() + } +} + +impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> { + #[inline] + fn next(&mut self) -> Option<(&'a K, &'a mut V)> { + self.inner.next() + } + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.inner.size_hint() + } +} + +impl Iterator<(K, V)> for MoveEntries { + #[inline] + fn next(&mut self) -> Option<(K, V)> { + self.inner.next() + } + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.inner.size_hint() + } +} + +impl<'a, K, V> OccupiedEntry<'a, K, V> { + /// Gets a reference to the value in the entry + pub fn get(&self) -> &V { + let (_, v) = self.elem.read(); + v + } + + /// Gets a mutable reference to the value in the entry + pub fn get_mut(&mut self) -> &mut V { + let (_, v) = self.elem.read_mut(); + v + } + + /// Converts the OccupiedEntry into a mutable reference to the value in the entry + /// with a lifetime bound to the map itself + pub fn into_mut(self) -> &'a mut V { + let (_, v) = self.elem.into_mut_refs(); + v + } + + /// Sets the value of the entry, and returns the entry's old value + pub fn set(&mut self, mut value: V) -> V { + let old_value = self.get_mut(); + mem::swap(&mut value, old_value); + value + } + + /// Takes the value out of the entry, and returns it + pub fn take(self) -> V { + let (_, _, v) = self.elem.take(); + v + } +} + +impl<'a, K, V> VacantEntry<'a, K, V> { + /// Sets the value of the entry with the VacantEntry's key, + /// and returns a mutable reference to it + pub fn set(self, value: V) -> &'a mut V { + match self.elem { + NeqElem(bucket, ib) => { + robin_hood(bucket, ib, self.hash, self.key, value) + } + NoElem(bucket) => { + let full = bucket.put(self.hash, self.key, value); + let (_, v) = full.into_mut_refs(); + v + } + } + } +} + +/// HashMap keys iterator +pub type Keys<'a, K, V> = + iter::Map<'static, (&'a K, &'a V), &'a K, Entries<'a, K, V>>; + +/// HashMap values iterator +pub type Values<'a, K, V> = + iter::Map<'static, (&'a K, &'a V), &'a V, Entries<'a, K, V>>; + +impl, V, S, H: Hasher + Default> FromIterator<(K, V)> for HashMap { + fn from_iter>(iter: T) -> HashMap { + let (lower, _) = iter.size_hint(); + let mut map = HashMap::with_capacity_and_hasher(lower, Default::default()); + map.extend(iter); + map + } +} + +impl, V, S, H: Hasher + Default> Extendable<(K, V)> for HashMap { + fn extend>(&mut self, mut iter: T) { + for (k, v) in iter { + self.insert(k, v); + } + } +} + +#[cfg(test)] +mod test_map { + use prelude::*; + + use super::HashMap; + use super::{Occupied, Vacant}; + use cmp::Equiv; + use hash; + use iter::{Iterator,range_inclusive,range_step_inclusive}; + use cell::RefCell; + + struct KindaIntLike(int); + + impl Equiv for KindaIntLike { + fn equiv(&self, other: &int) -> bool { + let KindaIntLike(this) = *self; + this == *other + } + } + impl hash::Hash for KindaIntLike { + fn hash(&self, state: &mut S) { + let KindaIntLike(this) = *self; + this.hash(state) + } + } + + #[test] + fn test_create_capacity_zero() { + let mut m = HashMap::with_capacity(0); + + assert!(m.insert(1i, 1i)); + + assert!(m.contains_key(&1)); + assert!(!m.contains_key(&0)); + } + + #[test] + fn test_insert() { + let mut m = HashMap::new(); + assert_eq!(m.len(), 0); + assert!(m.insert(1i, 2i)); + assert_eq!(m.len(), 1); + assert!(m.insert(2i, 4i)); + assert_eq!(m.len(), 2); + assert_eq!(*m.find(&1).unwrap(), 2); + assert_eq!(*m.find(&2).unwrap(), 4); + } + + local_data_key!(drop_vector: RefCell>) + + #[deriving(Hash, PartialEq, Eq)] + struct Dropable { + k: uint + } + + impl Dropable { + fn new(k: uint) -> Dropable { + let v = drop_vector.get().unwrap(); + v.borrow_mut().as_mut_slice()[k] += 1; + + Dropable { k: k } + } + } + + impl Drop for Dropable { + fn drop(&mut self) { + let v = drop_vector.get().unwrap(); + v.borrow_mut().as_mut_slice()[self.k] -= 1; + } + } + + impl Clone for Dropable { + fn clone(&self) -> Dropable { + Dropable::new(self.k) + } + } + + #[test] + fn test_drops() { + drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0i)))); + + { + let mut m = HashMap::new(); + + let v = drop_vector.get().unwrap(); + for i in range(0u, 200) { + assert_eq!(v.borrow().as_slice()[i], 0); + } + drop(v); + + for i in range(0u, 100) { + let d1 = Dropable::new(i); + let d2 = Dropable::new(i+100); + m.insert(d1, d2); + } + + let v = drop_vector.get().unwrap(); + for i in range(0u, 200) { + assert_eq!(v.borrow().as_slice()[i], 1); + } + drop(v); + + for i in range(0u, 50) { + let k = Dropable::new(i); + let v = m.pop(&k); + + assert!(v.is_some()); + + let v = drop_vector.get().unwrap(); + assert_eq!(v.borrow().as_slice()[i], 1); + assert_eq!(v.borrow().as_slice()[i+100], 1); + } + + let v = drop_vector.get().unwrap(); + for i in range(0u, 50) { + assert_eq!(v.borrow().as_slice()[i], 0); + assert_eq!(v.borrow().as_slice()[i+100], 0); + } + + for i in range(50u, 100) { + assert_eq!(v.borrow().as_slice()[i], 1); + assert_eq!(v.borrow().as_slice()[i+100], 1); + } + } + + let v = drop_vector.get().unwrap(); + for i in range(0u, 200) { + assert_eq!(v.borrow().as_slice()[i], 0); + } + } + + #[test] + fn test_move_iter_drops() { + drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0i)))); + + let hm = { + let mut hm = HashMap::new(); + + let v = drop_vector.get().unwrap(); + for i in range(0u, 200) { + assert_eq!(v.borrow().as_slice()[i], 0); + } + drop(v); + + for i in range(0u, 100) { + let d1 = Dropable::new(i); + let d2 = Dropable::new(i+100); + hm.insert(d1, d2); + } + + let v = drop_vector.get().unwrap(); + for i in range(0u, 200) { + assert_eq!(v.borrow().as_slice()[i], 1); + } + drop(v); + + hm + }; + + // By the way, ensure that cloning doesn't screw up the dropping. + drop(hm.clone()); + + { + let mut half = hm.into_iter().take(50); + + let v = drop_vector.get().unwrap(); + for i in range(0u, 200) { + assert_eq!(v.borrow().as_slice()[i], 1); + } + drop(v); + + for _ in half {} + + let v = drop_vector.get().unwrap(); + let nk = range(0u, 100).filter(|&i| { + v.borrow().as_slice()[i] == 1 + }).count(); + + let nv = range(0u, 100).filter(|&i| { + v.borrow().as_slice()[i+100] == 1 + }).count(); + + assert_eq!(nk, 50); + assert_eq!(nv, 50); + }; + + let v = drop_vector.get().unwrap(); + for i in range(0u, 200) { + assert_eq!(v.borrow().as_slice()[i], 0); + } + } + + #[test] + fn test_empty_pop() { + let mut m: HashMap = HashMap::new(); + assert_eq!(m.pop(&0), None); + } + + #[test] + fn test_lots_of_insertions() { + let mut m = HashMap::new(); + + // Try this a few times to make sure we never screw up the hashmap's + // internal state. + for _ in range(0i, 10) { + assert!(m.is_empty()); + + for i in range_inclusive(1i, 1000) { + assert!(m.insert(i, i)); + + for j in range_inclusive(1, i) { + let r = m.find(&j); + assert_eq!(r, Some(&j)); + } + + for j in range_inclusive(i+1, 1000) { + let r = m.find(&j); + assert_eq!(r, None); + } + } + + for i in range_inclusive(1001i, 2000) { + assert!(!m.contains_key(&i)); + } + + // remove forwards + for i in range_inclusive(1i, 1000) { + assert!(m.remove(&i)); + + for j in range_inclusive(1, i) { + assert!(!m.contains_key(&j)); + } + + for j in range_inclusive(i+1, 1000) { + assert!(m.contains_key(&j)); + } + } + + for i in range_inclusive(1i, 1000) { + assert!(!m.contains_key(&i)); + } + + for i in range_inclusive(1i, 1000) { + assert!(m.insert(i, i)); + } + + // remove backwards + for i in range_step_inclusive(1000i, 1, -1) { + assert!(m.remove(&i)); + + for j in range_inclusive(i, 1000) { + assert!(!m.contains_key(&j)); + } + + for j in range_inclusive(1, i-1) { + assert!(m.contains_key(&j)); + } + } + } + } + + #[test] + fn test_find_mut() { + let mut m = HashMap::new(); + assert!(m.insert(1i, 12i)); + assert!(m.insert(2i, 8i)); + assert!(m.insert(5i, 14i)); + let new = 100; + match m.find_mut(&5) { + None => panic!(), Some(x) => *x = new + } + assert_eq!(m.find(&5), Some(&new)); + } + + #[test] + fn test_insert_overwrite() { + let mut m = HashMap::new(); + assert!(m.insert(1i, 2i)); + assert_eq!(*m.find(&1).unwrap(), 2); + assert!(!m.insert(1i, 3i)); + assert_eq!(*m.find(&1).unwrap(), 3); + } + + #[test] + fn test_insert_conflicts() { + let mut m = HashMap::with_capacity(4); + assert!(m.insert(1i, 2i)); + assert!(m.insert(5i, 3i)); + assert!(m.insert(9i, 4i)); + assert_eq!(*m.find(&9).unwrap(), 4); + assert_eq!(*m.find(&5).unwrap(), 3); + assert_eq!(*m.find(&1).unwrap(), 2); + } + + #[test] + fn test_conflict_remove() { + let mut m = HashMap::with_capacity(4); + assert!(m.insert(1i, 2i)); + assert_eq!(*m.find(&1).unwrap(), 2); + assert!(m.insert(5, 3)); + assert_eq!(*m.find(&1).unwrap(), 2); + assert_eq!(*m.find(&5).unwrap(), 3); + assert!(m.insert(9, 4)); + assert_eq!(*m.find(&1).unwrap(), 2); + assert_eq!(*m.find(&5).unwrap(), 3); + assert_eq!(*m.find(&9).unwrap(), 4); + assert!(m.remove(&1)); + assert_eq!(*m.find(&9).unwrap(), 4); + assert_eq!(*m.find(&5).unwrap(), 3); + } + + #[test] + fn test_is_empty() { + let mut m = HashMap::with_capacity(4); + assert!(m.insert(1i, 2i)); + assert!(!m.is_empty()); + assert!(m.remove(&1)); + assert!(m.is_empty()); + } + + #[test] + fn test_pop() { + let mut m = HashMap::new(); + m.insert(1i, 2i); + assert_eq!(m.pop(&1), Some(2)); + assert_eq!(m.pop(&1), None); + } + + #[test] + #[allow(experimental)] + fn test_pop_equiv() { + let mut m = HashMap::new(); + m.insert(1i, 2i); + assert_eq!(m.pop_equiv(&KindaIntLike(1)), Some(2)); + assert_eq!(m.pop_equiv(&KindaIntLike(1)), None); + } + + #[test] + fn test_swap() { + let mut m = HashMap::new(); + assert_eq!(m.swap(1i, 2i), None); + assert_eq!(m.swap(1i, 3i), Some(2)); + assert_eq!(m.swap(1i, 4i), Some(3)); + } + + #[test] + fn test_iterate() { + let mut m = HashMap::with_capacity(4); + for i in range(0u, 32) { + assert!(m.insert(i, i*2)); + } + assert_eq!(m.len(), 32); + + let mut observed: u32 = 0; + + for (k, v) in m.iter() { + assert_eq!(*v, *k * 2); + observed |= 1 << *k; + } + assert_eq!(observed, 0xFFFF_FFFF); + } + + #[test] + fn test_keys() { + let vec = vec![(1i, 'a'), (2i, 'b'), (3i, 'c')]; + let map = vec.into_iter().collect::>(); + let keys = map.keys().map(|&k| k).collect::>(); + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); + } + + #[test] + fn test_values() { + let vec = vec![(1i, 'a'), (2i, 'b'), (3i, 'c')]; + let map = vec.into_iter().collect::>(); + let values = map.values().map(|&v| v).collect::>(); + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); + } + + #[test] + fn test_find() { + let mut m = HashMap::new(); + assert!(m.find(&1i).is_none()); + m.insert(1i, 2i); + match m.find(&1) { + None => panic!(), + Some(v) => assert_eq!(*v, 2) + } + } + + #[test] + fn test_find_copy() { + let mut m = HashMap::new(); + assert!(m.find(&1i).is_none()); + + for i in range(1i, 10000) { + m.insert(i, i + 7); + match m.find_copy(&i) { + None => panic!(), + Some(v) => assert_eq!(v, i + 7) + } + for j in range(1i, i/100) { + match m.find_copy(&j) { + None => panic!(), + Some(v) => assert_eq!(v, j + 7) + } + } + } + } + + #[test] + fn test_eq() { + let mut m1 = HashMap::new(); + m1.insert(1i, 2i); + m1.insert(2i, 3i); + m1.insert(3i, 4i); + + let mut m2 = HashMap::new(); + m2.insert(1i, 2i); + m2.insert(2i, 3i); + + assert!(m1 != m2); + + m2.insert(3i, 4i); + + assert_eq!(m1, m2); + } + + #[test] + fn test_show() { + let mut map: HashMap = HashMap::new(); + let empty: HashMap = HashMap::new(); + + map.insert(1i, 2i); + map.insert(3i, 4i); + + let map_str = format!("{}", map); + + assert!(map_str == "{1: 2, 3: 4}".to_string() || map_str == "{3: 4, 1: 2}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } + + #[test] + fn test_expand() { + let mut m = HashMap::new(); + + assert_eq!(m.len(), 0); + assert!(m.is_empty()); + + let mut i = 0u; + let old_cap = m.table.capacity(); + while old_cap == m.table.capacity() { + m.insert(i, i); + i += 1; + } + + assert_eq!(m.len(), i); + assert!(!m.is_empty()); + } + + #[test] + fn test_resize_policy() { + let mut m = HashMap::new(); + + assert_eq!(m.len(), 0); + assert_eq!(m.table.capacity(), 0); + assert!(m.is_empty()); + + m.insert(0, 0); + m.remove(&0); + assert!(m.is_empty()); + let initial_cap = m.table.capacity(); + m.reserve(initial_cap * 2); + let cap = m.table.capacity(); + + assert_eq!(cap, initial_cap * 2); + + let mut i = 0u; + for _ in range(0, cap * 3 / 4) { + m.insert(i, i); + i += 1; + } + // three quarters full + + assert_eq!(m.len(), i); + assert_eq!(m.table.capacity(), cap); + + for _ in range(0, cap / 4) { + m.insert(i, i); + i += 1; + } + // half full + + let new_cap = m.table.capacity(); + assert_eq!(new_cap, cap * 2); + + for _ in range(0, cap / 2 - 1) { + i -= 1; + m.remove(&i); + assert_eq!(m.table.capacity(), new_cap); + } + // A little more than one quarter full. + // Shrinking starts as we remove more elements: + for _ in range(0, cap / 2 - 1) { + i -= 1; + m.remove(&i); + } + + assert_eq!(m.len(), i); + assert!(!m.is_empty()); + assert_eq!(m.table.capacity(), cap); + } + + #[test] + fn test_find_equiv() { + let mut m = HashMap::new(); + + let (foo, bar, baz) = (1i,2i,3i); + m.insert("foo".to_string(), foo); + m.insert("bar".to_string(), bar); + m.insert("baz".to_string(), baz); + + + assert_eq!(m.find_equiv("foo"), Some(&foo)); + assert_eq!(m.find_equiv("bar"), Some(&bar)); + assert_eq!(m.find_equiv("baz"), Some(&baz)); + + assert_eq!(m.find_equiv("qux"), None); + } + + #[test] + fn test_from_iter() { + let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; + + let map: HashMap = xs.iter().map(|&x| x).collect(); + + for &(k, v) in xs.iter() { + assert_eq!(map.find(&k), Some(&v)); + } + } + + #[test] + fn test_size_hint() { + let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; + + let map: HashMap = xs.iter().map(|&x| x).collect(); + + let mut iter = map.iter(); + + for _ in iter.by_ref().take(3) {} + + assert_eq!(iter.size_hint(), (3, Some(3))); + } + + #[test] + fn test_mut_size_hint() { + let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; + + let mut map: HashMap = xs.iter().map(|&x| x).collect(); + + let mut iter = map.iter_mut(); + + for _ in iter.by_ref().take(3) {} + + assert_eq!(iter.size_hint(), (3, Some(3))); + } + + #[test] + fn test_index() { + let mut map: HashMap = HashMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + assert_eq!(map[2], 1); + } + + #[test] + #[should_fail] + fn test_index_nonexistent() { + let mut map: HashMap = HashMap::new(); + + map.insert(1, 2); + map.insert(2, 1); + map.insert(3, 4); + + map[4]; + } + + #[test] + fn test_entry(){ + let xs = [(1i, 10i), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; + + let mut map: HashMap = xs.iter().map(|&x| x).collect(); + + // Existing key (insert) + match map.entry(1) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + assert_eq!(view.get(), &10); + assert_eq!(view.set(100), 10); + } + } + assert_eq!(map.find(&1).unwrap(), &100); + assert_eq!(map.len(), 6); + + + // Existing key (update) + match map.entry(2) { + Vacant(_) => unreachable!(), + Occupied(mut view) => { + let v = view.get_mut(); + let new_v = (*v) * 10; + *v = new_v; + } + } + assert_eq!(map.find(&2).unwrap(), &200); + assert_eq!(map.len(), 6); + + // Existing key (take) + match map.entry(3) { + Vacant(_) => unreachable!(), + Occupied(view) => { + assert_eq!(view.take(), 30); + } + } + assert_eq!(map.find(&3), None); + assert_eq!(map.len(), 5); + + + // Inexistent key (insert) + match map.entry(10) { + Occupied(_) => unreachable!(), + Vacant(view) => { + assert_eq!(*view.set(1000), 1000); + } + } + assert_eq!(map.find(&10).unwrap(), &1000); + assert_eq!(map.len(), 6); + } +} diff --git a/src/libstd/collections/hash/mod.rs b/src/libstd/collections/hash/mod.rs new file mode 100644 index 00000000000..ee3fc1e6ac3 --- /dev/null +++ b/src/libstd/collections/hash/mod.rs @@ -0,0 +1,16 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unordered containers, implemented as hash-tables + +mod bench; +pub mod map; +pub mod set; +mod table; diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs new file mode 100644 index 00000000000..823bd49d7a6 --- /dev/null +++ b/src/libstd/collections/hash/set.rs @@ -0,0 +1,834 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// ignore-lexer-test FIXME #15883 + +use clone::Clone; +use cmp::{Eq, Equiv, PartialEq}; +use core::kinds::Sized; +use default::Default; +use fmt::Show; +use fmt; +use hash::{Hash, Hasher, RandomSipHasher}; +use iter::{Iterator, FromIterator, FilterMap, Chain, Repeat, Zip, Extendable}; +use iter; +use option::{Some, None}; +use result::{Ok, Err}; + +use super::map::{HashMap, Entries, MoveEntries, INITIAL_CAPACITY}; + + +// Future Optimization (FIXME!) +// ============================= +// +// Iteration over zero sized values is a noop. There is no need +// for `bucket.val` in the case of HashSet. I suppose we would need HKT +// to get rid of it properly. + +/// An implementation of a hash set using the underlying representation of a +/// HashMap where the value is (). As with the `HashMap` type, a `HashSet` +/// requires that the elements implement the `Eq` and `Hash` traits. +/// +/// # Example +/// +/// ``` +/// use std::collections::HashSet; +/// // Type inference lets us omit an explicit type signature (which +/// // would be `HashSet<&str>` in this example). +/// let mut books = HashSet::new(); +/// +/// // Add some books. +/// books.insert("A Dance With Dragons"); +/// books.insert("To Kill a Mockingbird"); +/// books.insert("The Odyssey"); +/// books.insert("The Great Gatsby"); +/// +/// // Check for a specific one. +/// if !books.contains(&("The Winds of Winter")) { +/// println!("We have {} books, but The Winds of Winter ain't one.", +/// books.len()); +/// } +/// +/// // Remove a book. +/// books.remove(&"The Odyssey"); +/// +/// // Iterate over everything. +/// for book in books.iter() { +/// println!("{}", *book); +/// } +/// ``` +/// +/// The easiest way to use `HashSet` with a custom type is to derive +/// `Eq` and `Hash`. We must also derive `PartialEq`, this will in the +/// future be implied by `Eq`. +/// +/// ``` +/// use std::collections::HashSet; +/// #[deriving(Hash, Eq, PartialEq, Show)] +/// struct Viking<'a> { +/// name: &'a str, +/// power: uint, +/// } +/// +/// let mut vikings = HashSet::new(); +/// +/// vikings.insert(Viking { name: "Einar", power: 9u }); +/// vikings.insert(Viking { name: "Einar", power: 9u }); +/// vikings.insert(Viking { name: "Olaf", power: 4u }); +/// vikings.insert(Viking { name: "Harald", power: 8u }); +/// +/// // Use derived implementation to print the vikings. +/// for x in vikings.iter() { +/// println!("{}", x); +/// } +/// ``` +#[deriving(Clone)] +pub struct HashSet { + map: HashMap +} + +impl HashSet { + /// Create an empty HashSet. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let mut set: HashSet = HashSet::new(); + /// ``` + #[inline] + pub fn new() -> HashSet { + HashSet::with_capacity(INITIAL_CAPACITY) + } + + /// Create an empty HashSet with space for at least `n` elements in + /// the hash table. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let mut set: HashSet = HashSet::with_capacity(10); + /// ``` + #[inline] + pub fn with_capacity(capacity: uint) -> HashSet { + HashSet { map: HashMap::with_capacity(capacity) } + } +} + +impl, S, H: Hasher> HashSet { + /// Creates a new empty hash set which will use the given hasher to hash + /// keys. + /// + /// The hash set is also created with the default initial capacity. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// use std::hash::sip::SipHasher; + /// + /// let h = SipHasher::new(); + /// let mut set = HashSet::with_hasher(h); + /// set.insert(2u); + /// ``` + #[inline] + pub fn with_hasher(hasher: H) -> HashSet { + HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher) + } + + /// Create an empty HashSet with space for at least `capacity` + /// elements in the hash table, using `hasher` to hash the keys. + /// + /// Warning: `hasher` is normally randomly generated, and + /// is designed to allow `HashSet`s to be resistant to attacks that + /// cause many collisions and very poor performance. Setting it + /// manually using this function can expose a DoS attack vector. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// use std::hash::sip::SipHasher; + /// + /// let h = SipHasher::new(); + /// let mut set = HashSet::with_capacity_and_hasher(10u, h); + /// set.insert(1i); + /// ``` + #[inline] + pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet { + HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) } + } + + /// Reserve space for at least `n` elements in the hash table. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let mut set: HashSet = HashSet::new(); + /// set.reserve(10); + /// ``` + pub fn reserve(&mut self, n: uint) { + self.map.reserve(n) + } + + /// Returns true if the hash set contains a value equivalent to the + /// given query value. + /// + /// # Example + /// + /// This is a slightly silly example where we define the number's + /// parity as the equivalance class. It is important that the + /// values hash the same, which is why we implement `Hash`. + /// + /// ``` + /// use std::collections::HashSet; + /// use std::hash::Hash; + /// use std::hash::sip::SipState; + /// + /// #[deriving(Eq, PartialEq)] + /// struct EvenOrOdd { + /// num: uint + /// }; + /// + /// impl Hash for EvenOrOdd { + /// fn hash(&self, state: &mut SipState) { + /// let parity = self.num % 2; + /// parity.hash(state); + /// } + /// } + /// + /// impl Equiv for EvenOrOdd { + /// fn equiv(&self, other: &EvenOrOdd) -> bool { + /// self.num % 2 == other.num % 2 + /// } + /// } + /// + /// let mut set = HashSet::new(); + /// set.insert(EvenOrOdd { num: 3u }); + /// + /// assert!(set.contains_equiv(&EvenOrOdd { num: 3u })); + /// assert!(set.contains_equiv(&EvenOrOdd { num: 5u })); + /// assert!(!set.contains_equiv(&EvenOrOdd { num: 4u })); + /// assert!(!set.contains_equiv(&EvenOrOdd { num: 2u })); + /// + /// ``` + pub fn contains_equiv + Equiv>(&self, value: &Q) -> bool { + self.map.contains_key_equiv(value) + } + + /// An iterator visiting all elements in arbitrary order. + /// Iterator element type is &'a T. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let mut set = HashSet::new(); + /// set.insert("a"); + /// set.insert("b"); + /// + /// // Will print in an arbitrary order. + /// for x in set.iter() { + /// println!("{}", x); + /// } + /// ``` + pub fn iter<'a>(&'a self) -> SetItems<'a, T> { + self.map.keys() + } + + /// Deprecated: use `into_iter`. + #[deprecated = "use into_iter"] + pub fn move_iter(self) -> SetMoveItems { + self.into_iter() + } + + /// Creates a consuming iterator, that is, one that moves each value out + /// of the set in arbitrary order. The set cannot be used after calling + /// this. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let mut set = HashSet::new(); + /// set.insert("a".to_string()); + /// set.insert("b".to_string()); + /// + /// // Not possible to collect to a Vec with a regular `.iter()`. + /// let v: Vec = set.into_iter().collect(); + /// + /// // Will print in an arbitrary order. + /// for x in v.iter() { + /// println!("{}", x); + /// } + /// ``` + pub fn into_iter(self) -> SetMoveItems { + self.map.into_iter().map(|(k, _)| k) + } + + /// Visit the values representing the difference. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); + /// + /// // Can be seen as `a - b`. + /// for x in a.difference(&b) { + /// println!("{}", x); // Print 1 + /// } + /// + /// let diff: HashSet = a.difference(&b).map(|&x| x).collect(); + /// assert_eq!(diff, [1i].iter().map(|&x| x).collect()); + /// + /// // Note that difference is not symmetric, + /// // and `b - a` means something else: + /// let diff: HashSet = b.difference(&a).map(|&x| x).collect(); + /// assert_eq!(diff, [4i].iter().map(|&x| x).collect()); + /// ``` + pub fn difference<'a>(&'a self, other: &'a HashSet) -> SetAlgebraItems<'a, T, H> { + Repeat::new(other).zip(self.iter()) + .filter_map(|(other, elt)| { + if !other.contains(elt) { Some(elt) } else { None } + }) + } + + /// Visit the values representing the symmetric difference. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); + /// + /// // Print 1, 4 in arbitrary order. + /// for x in a.symmetric_difference(&b) { + /// println!("{}", x); + /// } + /// + /// let diff1: HashSet = a.symmetric_difference(&b).map(|&x| x).collect(); + /// let diff2: HashSet = b.symmetric_difference(&a).map(|&x| x).collect(); + /// + /// assert_eq!(diff1, diff2); + /// assert_eq!(diff1, [1i, 4].iter().map(|&x| x).collect()); + /// ``` + pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet) + -> Chain, SetAlgebraItems<'a, T, H>> { + self.difference(other).chain(other.difference(self)) + } + + /// Visit the values representing the intersection. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); + /// + /// // Print 2, 3 in arbitrary order. + /// for x in a.intersection(&b) { + /// println!("{}", x); + /// } + /// + /// let diff: HashSet = a.intersection(&b).map(|&x| x).collect(); + /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect()); + /// ``` + pub fn intersection<'a>(&'a self, other: &'a HashSet) + -> SetAlgebraItems<'a, T, H> { + Repeat::new(other).zip(self.iter()) + .filter_map(|(other, elt)| { + if other.contains(elt) { Some(elt) } else { None } + }) + } + + /// Visit the values representing the union. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); + /// + /// // Print 1, 2, 3, 4 in arbitrary order. + /// for x in a.union(&b) { + /// println!("{}", x); + /// } + /// + /// let diff: HashSet = a.union(&b).map(|&x| x).collect(); + /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect()); + /// ``` + pub fn union<'a>(&'a self, other: &'a HashSet) + -> Chain, SetAlgebraItems<'a, T, H>> { + self.iter().chain(other.difference(self)) + } + + /// Return the number of elements in the set + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let mut v = HashSet::new(); + /// assert_eq!(v.len(), 0); + /// v.insert(1u); + /// assert_eq!(v.len(), 1); + /// ``` + pub fn len(&self) -> uint { self.map.len() } + + /// Returns true if the set contains no elements + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let mut v = HashSet::new(); + /// assert!(v.is_empty()); + /// v.insert(1u); + /// assert!(!v.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { self.map.len() == 0 } + + /// Clears the set, removing all values. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let mut v = HashSet::new(); + /// v.insert(1u); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + pub fn clear(&mut self) { self.map.clear() } + + /// Returns `true` if the set contains a value. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let set: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// assert_eq!(set.contains(&1), true); + /// assert_eq!(set.contains(&4), false); + /// ``` + pub fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } + + /// Returns `true` if the set has no elements in common with `other`. + /// This is equivalent to checking for an empty intersection. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let mut b: HashSet = HashSet::new(); + /// + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(4); + /// assert_eq!(a.is_disjoint(&b), true); + /// b.insert(1); + /// assert_eq!(a.is_disjoint(&b), false); + /// ``` + pub fn is_disjoint(&self, other: &HashSet) -> bool { + self.iter().all(|v| !other.contains(v)) + } + + /// Returns `true` if the set is a subset of another. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let sup: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let mut set: HashSet = HashSet::new(); + /// + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(2); + /// assert_eq!(set.is_subset(&sup), true); + /// set.insert(4); + /// assert_eq!(set.is_subset(&sup), false); + /// ``` + pub fn is_subset(&self, other: &HashSet) -> bool { + self.iter().all(|v| other.contains(v)) + } + + /// Returns `true` if the set is a superset of another. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let sub: HashSet = [1, 2].iter().map(|&x| x).collect(); + /// let mut set: HashSet = HashSet::new(); + /// + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(0); + /// set.insert(1); + /// assert_eq!(set.is_superset(&sub), false); + /// + /// set.insert(2); + /// assert_eq!(set.is_superset(&sub), true); + /// ``` + #[inline] + pub fn is_superset(&self, other: &HashSet) -> bool { + other.is_subset(self) + } + + /// Adds a value to the set. Returns `true` if the value was not already + /// present in the set. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::new(); + /// + /// assert_eq!(set.insert(2u), true); + /// assert_eq!(set.insert(2), false); + /// assert_eq!(set.len(), 1); + /// ``` + pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } + + /// Removes a value from the set. Returns `true` if the value was + /// present in the set. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::new(); + /// + /// set.insert(2u); + /// assert_eq!(set.remove(&2), true); + /// assert_eq!(set.remove(&2), false); + /// ``` + pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } +} + +impl, S, H: Hasher> PartialEq for HashSet { + fn eq(&self, other: &HashSet) -> bool { + if self.len() != other.len() { return false; } + + self.iter().all(|key| other.contains(key)) + } +} + +impl, S, H: Hasher> Eq for HashSet {} + +impl + fmt::Show, S, H: Hasher> fmt::Show for HashSet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, x) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}", *x)); + } + + write!(f, "}}") + } +} + +impl, S, H: Hasher + Default> FromIterator for HashSet { + fn from_iter>(iter: I) -> HashSet { + let (lower, _) = iter.size_hint(); + let mut set = HashSet::with_capacity_and_hasher(lower, Default::default()); + set.extend(iter); + set + } +} + +impl, S, H: Hasher + Default> Extendable for HashSet { + fn extend>(&mut self, mut iter: I) { + for k in iter { + self.insert(k); + } + } +} + +impl, S, H: Hasher + Default> Default for HashSet { + fn default() -> HashSet { + HashSet::with_hasher(Default::default()) + } +} + +/// HashSet iterator +pub type SetItems<'a, K> = + iter::Map<'static, (&'a K, &'a ()), &'a K, Entries<'a, K, ()>>; + +/// HashSet move iterator +pub type SetMoveItems = + iter::Map<'static, (K, ()), K, MoveEntries>; + +// `Repeat` is used to feed the filter closure an explicit capture +// of a reference to the other set +/// Set operations iterator +pub type SetAlgebraItems<'a, T, H> = + FilterMap<'static, (&'a HashSet, &'a T), &'a T, + Zip>, SetItems<'a, T>>>; + +#[cfg(test)] +mod test_set { + use prelude::*; + + use super::HashSet; + use slice::ImmutablePartialEqSlice; + + #[test] + fn test_disjoint() { + let mut xs = HashSet::new(); + let mut ys = HashSet::new(); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert(5i)); + assert!(ys.insert(11i)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert(7)); + assert!(xs.insert(19)); + assert!(xs.insert(4)); + assert!(ys.insert(2)); + assert!(ys.insert(-11)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(ys.insert(7)); + assert!(!xs.is_disjoint(&ys)); + assert!(!ys.is_disjoint(&xs)); + } + + #[test] + fn test_subset_and_superset() { + let mut a = HashSet::new(); + assert!(a.insert(0i)); + assert!(a.insert(5)); + assert!(a.insert(11)); + assert!(a.insert(7)); + + let mut b = HashSet::new(); + assert!(b.insert(0i)); + assert!(b.insert(7)); + assert!(b.insert(19)); + assert!(b.insert(250)); + assert!(b.insert(11)); + assert!(b.insert(200)); + + assert!(!a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(!b.is_superset(&a)); + + assert!(b.insert(5)); + + assert!(a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(b.is_superset(&a)); + } + + #[test] + fn test_iterate() { + let mut a = HashSet::new(); + for i in range(0u, 32) { + assert!(a.insert(i)); + } + let mut observed: u32 = 0; + for k in a.iter() { + observed |= 1 << *k; + } + assert_eq!(observed, 0xFFFF_FFFF); + } + + #[test] + fn test_intersection() { + let mut a = HashSet::new(); + let mut b = HashSet::new(); + + assert!(a.insert(11i)); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(77)); + assert!(a.insert(103)); + assert!(a.insert(5)); + assert!(a.insert(-5)); + + assert!(b.insert(2i)); + assert!(b.insert(11)); + assert!(b.insert(77)); + assert!(b.insert(-9)); + assert!(b.insert(-42)); + assert!(b.insert(5)); + assert!(b.insert(3)); + + let mut i = 0; + let expected = [3, 5, 11, 77]; + for x in a.intersection(&b) { + assert!(expected.contains(x)); + i += 1 + } + assert_eq!(i, expected.len()); + } + + #[test] + fn test_difference() { + let mut a = HashSet::new(); + let mut b = HashSet::new(); + + assert!(a.insert(1i)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + + assert!(b.insert(3i)); + assert!(b.insert(9)); + + let mut i = 0; + let expected = [1, 5, 11]; + for x in a.difference(&b) { + assert!(expected.contains(x)); + i += 1 + } + assert_eq!(i, expected.len()); + } + + #[test] + fn test_symmetric_difference() { + let mut a = HashSet::new(); + let mut b = HashSet::new(); + + assert!(a.insert(1i)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + + assert!(b.insert(-2i)); + assert!(b.insert(3)); + assert!(b.insert(9)); + assert!(b.insert(14)); + assert!(b.insert(22)); + + let mut i = 0; + let expected = [-2, 1, 5, 11, 14, 22]; + for x in a.symmetric_difference(&b) { + assert!(expected.contains(x)); + i += 1 + } + assert_eq!(i, expected.len()); + } + + #[test] + fn test_union() { + let mut a = HashSet::new(); + let mut b = HashSet::new(); + + assert!(a.insert(1i)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + assert!(a.insert(16)); + assert!(a.insert(19)); + assert!(a.insert(24)); + + assert!(b.insert(-2i)); + assert!(b.insert(1)); + assert!(b.insert(5)); + assert!(b.insert(9)); + assert!(b.insert(13)); + assert!(b.insert(19)); + + let mut i = 0; + let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; + for x in a.union(&b) { + assert!(expected.contains(x)); + i += 1 + } + assert_eq!(i, expected.len()); + } + + #[test] + fn test_from_iter() { + let xs = [1i, 2, 3, 4, 5, 6, 7, 8, 9]; + + let set: HashSet = xs.iter().map(|&x| x).collect(); + + for x in xs.iter() { + assert!(set.contains(x)); + } + } + + #[test] + fn test_move_iter() { + let hs = { + let mut hs = HashSet::new(); + + hs.insert('a'); + hs.insert('b'); + + hs + }; + + let v = hs.into_iter().collect::>(); + assert!(['a', 'b'] == v.as_slice() || ['b', 'a'] == v.as_slice()); + } + + #[test] + fn test_eq() { + // These constants once happened to expose a bug in insert(). + // I'm keeping them around to prevent a regression. + let mut s1 = HashSet::new(); + + s1.insert(1i); + s1.insert(2); + s1.insert(3); + + let mut s2 = HashSet::new(); + + s2.insert(1i); + s2.insert(2); + + assert!(s1 != s2); + + s2.insert(3); + + assert_eq!(s1, s2); + } + + #[test] + fn test_show() { + let mut set: HashSet = HashSet::new(); + let empty: HashSet = HashSet::new(); + + set.insert(1i); + set.insert(2); + + let set_str = format!("{}", set); + + assert!(set_str == "{1, 2}".to_string() || set_str == "{2, 1}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } +} diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs new file mode 100644 index 00000000000..4d73029b7b0 --- /dev/null +++ b/src/libstd/collections/hash/table.rs @@ -0,0 +1,907 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// ignore-lexer-test FIXME #15883 + +use clone::Clone; +use cmp; +use hash::{Hash, Hasher}; +use iter::{Iterator, count}; +use kinds::{Sized, marker}; +use mem::{min_align_of, size_of}; +use mem; +use num::{CheckedAdd, CheckedMul, is_power_of_two}; +use ops::{Deref, DerefMut, Drop}; +use option::{Some, None, Option}; +use ptr::{RawPtr, copy_nonoverlapping_memory, zero_memory}; +use ptr; +use rt::heap::{allocate, deallocate}; + +const EMPTY_BUCKET: u64 = 0u64; + +/// The raw hashtable, providing safe-ish access to the unzipped and highly +/// optimized arrays of hashes, keys, and values. +/// +/// This design uses less memory and is a lot faster than the naive +/// `Vec>`, because we don't pay for the overhead of an +/// option on every element, and we get a generally more cache-aware design. +/// +/// Essential invariants of this structure: +/// +/// - if t.hashes[i] == EMPTY_BUCKET, then `Bucket::at_index(&t, i).raw` +/// points to 'undefined' contents. Don't read from it. This invariant is +/// enforced outside this module with the `EmptyBucket`, `FullBucket`, +/// and `SafeHash` types. +/// +/// - An `EmptyBucket` is only constructed at an index with +/// a hash of EMPTY_BUCKET. +/// +/// - A `FullBucket` is only constructed at an index with a +/// non-EMPTY_BUCKET hash. +/// +/// - A `SafeHash` is only constructed for non-`EMPTY_BUCKET` hash. We get +/// around hashes of zero by changing them to 0x8000_0000_0000_0000, +/// which will likely map to the same bucket, while not being confused +/// with "empty". +/// +/// - All three "arrays represented by pointers" are the same length: +/// `capacity`. This is set at creation and never changes. The arrays +/// are unzipped to save space (we don't have to pay for the padding +/// between odd sized elements, such as in a map from u64 to u8), and +/// be more cache aware (scanning through 8 hashes brings in at most +/// 2 cache lines, since they're all right beside each other). +/// +/// You can kind of think of this module/data structure as a safe wrapper +/// around just the "table" part of the hashtable. It enforces some +/// invariants at the type level and employs some performance trickery, +/// but in general is just a tricked out `Vec>`. +#[unsafe_no_drop_flag] +pub struct RawTable { + capacity: uint, + size: uint, + hashes: *mut u64, + // Because K/V do not appear directly in any of the types in the struct, + // inform rustc that in fact instances of K and V are reachable from here. + marker: marker::CovariantType<(K,V)>, +} + +struct RawBucket { + hash: *mut u64, + key: *mut K, + val: *mut V +} + +pub struct Bucket { + raw: RawBucket, + idx: uint, + table: M +} + +pub struct EmptyBucket { + raw: RawBucket, + idx: uint, + table: M +} + +pub struct FullBucket { + raw: RawBucket, + idx: uint, + table: M +} + +pub type EmptyBucketImm<'table, K, V> = EmptyBucket>; +pub type FullBucketImm<'table, K, V> = FullBucket>; + +pub type EmptyBucketMut<'table, K, V> = EmptyBucket>; +pub type FullBucketMut<'table, K, V> = FullBucket>; + +pub enum BucketState { + Empty(EmptyBucket), + Full(FullBucket), +} + +// A GapThenFull encapsulates the state of two consecutive buckets at once. +// The first bucket, called the gap, is known to be empty. +// The second bucket is full. +struct GapThenFull { + gap: EmptyBucket, + full: FullBucket, +} + +/// A hash that is not zero, since we use a hash of zero to represent empty +/// buckets. +#[deriving(PartialEq)] +pub struct SafeHash { + hash: u64, +} + +impl SafeHash { + /// Peek at the hash value, which is guaranteed to be non-zero. + #[inline(always)] + pub fn inspect(&self) -> u64 { self.hash } +} + +/// We need to remove hashes of 0. That's reserved for empty buckets. +/// This function wraps up `hash_keyed` to be the only way outside this +/// module to generate a SafeHash. +pub fn make_hash, S, H: Hasher>(hasher: &H, t: &T) -> SafeHash { + match hasher.hash(t) { + // This constant is exceedingly likely to hash to the same + // bucket, but it won't be counted as empty! Just so we can maintain + // our precious uniform distribution of initial indexes. + EMPTY_BUCKET => SafeHash { hash: 0x8000_0000_0000_0000 }, + h => SafeHash { hash: h }, + } +} + +// `replace` casts a `*u64` to a `*SafeHash`. Since we statically +// ensure that a `FullBucket` points to an index with a non-zero hash, +// and a `SafeHash` is just a `u64` with a different name, this is +// safe. +// +// This test ensures that a `SafeHash` really IS the same size as a +// `u64`. If you need to change the size of `SafeHash` (and +// consequently made this test fail), `replace` needs to be +// modified to no longer assume this. +#[test] +fn can_alias_safehash_as_u64() { + assert_eq!(size_of::(), size_of::()) +} + +impl RawBucket { + unsafe fn offset(self, count: int) -> RawBucket { + RawBucket { + hash: self.hash.offset(count), + key: self.key.offset(count), + val: self.val.offset(count), + } + } +} + +// For parameterizing over mutability. +impl<'t, K, V> Deref> for &'t RawTable { + fn deref(&self) -> &RawTable { + &**self + } +} + +impl<'t, K, V> Deref> for &'t mut RawTable { + fn deref(&self) -> &RawTable { + &**self + } +} + +impl<'t, K, V> DerefMut> for &'t mut RawTable { + fn deref_mut(&mut self) -> &mut RawTable { + &mut **self + } +} + +// Buckets hold references to the table. +impl FullBucket { + /// Borrow a reference to the table. + pub fn table(&self) -> &M { + &self.table + } + /// Move out the reference to the table. + pub fn into_table(self) -> M { + self.table + } + /// Get the raw index. + pub fn index(&self) -> uint { + self.idx + } +} + +impl EmptyBucket { + /// Borrow a reference to the table. + pub fn table(&self) -> &M { + &self.table + } + /// Move out the reference to the table. + pub fn into_table(self) -> M { + self.table + } +} + +impl Bucket { + /// Move out the reference to the table. + pub fn into_table(self) -> M { + self.table + } + /// Get the raw index. + pub fn index(&self) -> uint { + self.idx + } +} + +impl>> Bucket { + pub fn new(table: M, hash: &SafeHash) -> Bucket { + Bucket::at_index(table, hash.inspect() as uint) + } + + pub fn at_index(table: M, ib_index: uint) -> Bucket { + let ib_index = ib_index & (table.capacity() - 1); + Bucket { + raw: unsafe { + table.first_bucket_raw().offset(ib_index as int) + }, + idx: ib_index, + table: table + } + } + + pub fn first(table: M) -> Bucket { + Bucket { + raw: table.first_bucket_raw(), + idx: 0, + table: table + } + } + + /// Reads a bucket at a given index, returning an enum indicating whether + /// it's initialized or not. You need to match on this enum to get + /// the appropriate types to call most of the other functions in + /// this module. + pub fn peek(self) -> BucketState { + match unsafe { *self.raw.hash } { + EMPTY_BUCKET => + Empty(EmptyBucket { + raw: self.raw, + idx: self.idx, + table: self.table + }), + _ => + Full(FullBucket { + raw: self.raw, + idx: self.idx, + table: self.table + }) + } + } + + /// Modifies the bucket pointer in place to make it point to the next slot. + pub fn next(&mut self) { + // Branchless bucket iteration step. + // As we reach the end of the table... + // We take the current idx: 0111111b + // Xor it by its increment: ^ 1000000b + // ------------ + // 1111111b + // Then AND with the capacity: & 1000000b + // ------------ + // to get the backwards offset: 1000000b + // ... and it's zero at all other times. + let maybe_wraparound_dist = (self.idx ^ (self.idx + 1)) & self.table.capacity(); + // Finally, we obtain the offset 1 or the offset -cap + 1. + let dist = 1i - (maybe_wraparound_dist as int); + + self.idx += 1; + + unsafe { + self.raw = self.raw.offset(dist); + } + } +} + +impl>> EmptyBucket { + #[inline] + pub fn next(self) -> Bucket { + let mut bucket = self.into_bucket(); + bucket.next(); + bucket + } + + #[inline] + pub fn into_bucket(self) -> Bucket { + Bucket { + raw: self.raw, + idx: self.idx, + table: self.table + } + } + + pub fn gap_peek(self) -> Option> { + let gap = EmptyBucket { + raw: self.raw, + idx: self.idx, + table: () + }; + + match self.next().peek() { + Full(bucket) => { + Some(GapThenFull { + gap: gap, + full: bucket + }) + } + Empty(..) => None + } + } +} + +impl>> EmptyBucket { + /// Puts given key and value pair, along with the key's hash, + /// into this bucket in the hashtable. Note how `self` is 'moved' into + /// this function, because this slot will no longer be empty when + /// we return! A `FullBucket` is returned for later use, pointing to + /// the newly-filled slot in the hashtable. + /// + /// Use `make_hash` to construct a `SafeHash` to pass to this function. + pub fn put(mut self, hash: SafeHash, key: K, value: V) + -> FullBucket { + unsafe { + *self.raw.hash = hash.inspect(); + ptr::write(self.raw.key, key); + ptr::write(self.raw.val, value); + } + + self.table.size += 1; + + FullBucket { raw: self.raw, idx: self.idx, table: self.table } + } +} + +impl>> FullBucket { + #[inline] + pub fn next(self) -> Bucket { + let mut bucket = self.into_bucket(); + bucket.next(); + bucket + } + + #[inline] + pub fn into_bucket(self) -> Bucket { + Bucket { + raw: self.raw, + idx: self.idx, + table: self.table + } + } + + /// Get the distance between this bucket and the 'ideal' location + /// as determined by the key's hash stored in it. + /// + /// In the cited blog posts above, this is called the "distance to + /// initial bucket", or DIB. Also known as "probe count". + pub fn distance(&self) -> uint { + // Calculates the distance one has to travel when going from + // `hash mod capacity` onwards to `idx mod capacity`, wrapping around + // if the destination is not reached before the end of the table. + (self.idx - self.hash().inspect() as uint) & (self.table.capacity() - 1) + } + + #[inline] + pub fn hash(&self) -> SafeHash { + unsafe { + SafeHash { + hash: *self.raw.hash + } + } + } + + /// Gets references to the key and value at a given index. + pub fn read(&self) -> (&K, &V) { + unsafe { + (&*self.raw.key, + &*self.raw.val) + } + } +} + +impl>> FullBucket { + /// Removes this bucket's key and value from the hashtable. + /// + /// This works similarly to `put`, building an `EmptyBucket` out of the + /// taken bucket. + pub fn take(mut self) -> (EmptyBucket, K, V) { + let key = self.raw.key as *const K; + let val = self.raw.val as *const V; + + self.table.size -= 1; + + unsafe { + *self.raw.hash = EMPTY_BUCKET; + ( + EmptyBucket { + raw: self.raw, + idx: self.idx, + table: self.table + }, + ptr::read(key), + ptr::read(val) + ) + } + } + + pub fn replace(&mut self, h: SafeHash, k: K, v: V) -> (SafeHash, K, V) { + unsafe { + let old_hash = ptr::replace(self.raw.hash as *mut SafeHash, h); + let old_key = ptr::replace(self.raw.key, k); + let old_val = ptr::replace(self.raw.val, v); + + (old_hash, old_key, old_val) + } + } + + /// Gets mutable references to the key and value at a given index. + pub fn read_mut(&mut self) -> (&mut K, &mut V) { + unsafe { + (&mut *self.raw.key, + &mut *self.raw.val) + } + } +} + +impl<'t, K, V, M: Deref> + 't> FullBucket { + /// Exchange a bucket state for immutable references into the table. + /// Because the underlying reference to the table is also consumed, + /// no further changes to the structure of the table are possible; + /// in exchange for this, the returned references have a longer lifetime + /// than the references returned by `read()`. + pub fn into_refs(self) -> (&'t K, &'t V) { + unsafe { + (&*self.raw.key, + &*self.raw.val) + } + } +} + +impl<'t, K, V, M: DerefMut> + 't> FullBucket { + /// This works similarly to `into_refs`, exchanging a bucket state + /// for mutable references into the table. + pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) { + unsafe { + (&mut *self.raw.key, + &mut *self.raw.val) + } + } +} + +impl BucketState { + // For convenience. + pub fn expect_full(self) -> FullBucket { + match self { + Full(full) => full, + Empty(..) => panic!("Expected full bucket") + } + } +} + +impl>> GapThenFull { + #[inline] + pub fn full(&self) -> &FullBucket { + &self.full + } + + pub fn shift(mut self) -> Option> { + unsafe { + *self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET); + copy_nonoverlapping_memory(self.gap.raw.key, self.full.raw.key as *const K, 1); + copy_nonoverlapping_memory(self.gap.raw.val, self.full.raw.val as *const V, 1); + } + + let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full; + + match self.full.next().peek() { + Full(bucket) => { + self.gap.raw = prev_raw; + self.gap.idx = prev_idx; + + self.full = bucket; + + Some(self) + } + Empty(..) => None + } + } +} + + +/// Rounds up to a multiple of a power of two. Returns the closest multiple +/// of `target_alignment` that is higher or equal to `unrounded`. +/// +/// # Failure +/// +/// Fails if `target_alignment` is not a power of two. +fn round_up_to_next(unrounded: uint, target_alignment: uint) -> uint { + assert!(is_power_of_two(target_alignment)); + (unrounded + target_alignment - 1) & !(target_alignment - 1) +} + +#[test] +fn test_rounding() { + assert_eq!(round_up_to_next(0, 4), 0); + assert_eq!(round_up_to_next(1, 4), 4); + assert_eq!(round_up_to_next(2, 4), 4); + assert_eq!(round_up_to_next(3, 4), 4); + assert_eq!(round_up_to_next(4, 4), 4); + assert_eq!(round_up_to_next(5, 4), 8); +} + +// Returns a tuple of (key_offset, val_offset), +// from the start of a mallocated array. +fn calculate_offsets(hashes_size: uint, + keys_size: uint, keys_align: uint, + vals_align: uint) + -> (uint, uint) { + let keys_offset = round_up_to_next(hashes_size, keys_align); + let end_of_keys = keys_offset + keys_size; + + let vals_offset = round_up_to_next(end_of_keys, vals_align); + + (keys_offset, vals_offset) +} + +// Returns a tuple of (minimum required malloc alignment, hash_offset, +// array_size), from the start of a mallocated array. +fn calculate_allocation(hash_size: uint, hash_align: uint, + keys_size: uint, keys_align: uint, + vals_size: uint, vals_align: uint) + -> (uint, uint, uint) { + let hash_offset = 0; + let (_, vals_offset) = calculate_offsets(hash_size, + keys_size, keys_align, + vals_align); + let end_of_vals = vals_offset + vals_size; + + let min_align = cmp::max(hash_align, cmp::max(keys_align, vals_align)); + + (min_align, hash_offset, end_of_vals) +} + +#[test] +fn test_offset_calculation() { + assert_eq!(calculate_allocation(128, 8, 15, 1, 4, 4), (8, 0, 148)); + assert_eq!(calculate_allocation(3, 1, 2, 1, 1, 1), (1, 0, 6)); + assert_eq!(calculate_allocation(6, 2, 12, 4, 24, 8), (8, 0, 48)); + assert_eq!(calculate_offsets(128, 15, 1, 4), (128, 144)); + assert_eq!(calculate_offsets(3, 2, 1, 1), (3, 5)); + assert_eq!(calculate_offsets(6, 12, 4, 8), (8, 24)); +} + +impl RawTable { + /// Does not initialize the buckets. The caller should ensure they, + /// at the very least, set every hash to EMPTY_BUCKET. + unsafe fn new_uninitialized(capacity: uint) -> RawTable { + if capacity == 0 { + return RawTable { + size: 0, + capacity: 0, + hashes: 0 as *mut u64, + marker: marker::CovariantType, + }; + } + // No need for `checked_mul` before a more restrictive check performed + // later in this method. + let hashes_size = capacity * size_of::(); + let keys_size = capacity * size_of::< K >(); + let vals_size = capacity * size_of::< V >(); + + // Allocating hashmaps is a little tricky. We need to allocate three + // arrays, but since we know their sizes and alignments up front, + // we just allocate a single array, and then have the subarrays + // point into it. + // + // This is great in theory, but in practice getting the alignment + // right is a little subtle. Therefore, calculating offsets has been + // factored out into a different function. + let (malloc_alignment, hash_offset, size) = + calculate_allocation( + hashes_size, min_align_of::(), + keys_size, min_align_of::< K >(), + vals_size, min_align_of::< V >()); + + // One check for overflow that covers calculation and rounding of size. + let size_of_bucket = size_of::().checked_add(&size_of::()).unwrap() + .checked_add(&size_of::()).unwrap(); + assert!(size >= capacity.checked_mul(&size_of_bucket) + .expect("capacity overflow"), + "capacity overflow"); + + let buffer = allocate(size, malloc_alignment); + if buffer.is_null() { ::alloc::oom() } + + let hashes = buffer.offset(hash_offset as int) as *mut u64; + + RawTable { + capacity: capacity, + size: 0, + hashes: hashes, + marker: marker::CovariantType, + } + } + + fn first_bucket_raw(&self) -> RawBucket { + let hashes_size = self.capacity * size_of::(); + let keys_size = self.capacity * size_of::(); + + let buffer = self.hashes as *mut u8; + let (keys_offset, vals_offset) = calculate_offsets(hashes_size, + keys_size, min_align_of::(), + min_align_of::()); + + unsafe { + RawBucket { + hash: self.hashes, + key: buffer.offset(keys_offset as int) as *mut K, + val: buffer.offset(vals_offset as int) as *mut V + } + } + } + + /// Creates a new raw table from a given capacity. All buckets are + /// initially empty. + #[allow(experimental)] + pub fn new(capacity: uint) -> RawTable { + unsafe { + let ret = RawTable::new_uninitialized(capacity); + zero_memory(ret.hashes, capacity); + ret + } + } + + /// The hashtable's capacity, similar to a vector's. + pub fn capacity(&self) -> uint { + self.capacity + } + + /// The number of elements ever `put` in the hashtable, minus the number + /// of elements ever `take`n. + pub fn size(&self) -> uint { + self.size + } + + fn raw_buckets(&self) -> RawBuckets { + RawBuckets { + raw: self.first_bucket_raw(), + hashes_end: unsafe { + self.hashes.offset(self.capacity as int) + }, + marker: marker::ContravariantLifetime, + } + } + + pub fn iter(&self) -> Entries { + Entries { + iter: self.raw_buckets(), + elems_left: self.size(), + } + } + + pub fn iter_mut(&mut self) -> MutEntries { + MutEntries { + iter: self.raw_buckets(), + elems_left: self.size(), + } + } + + pub fn into_iter(self) -> MoveEntries { + let RawBuckets { raw, hashes_end, .. } = self.raw_buckets(); + // Replace the marker regardless of lifetime bounds on parameters. + MoveEntries { + iter: RawBuckets { + raw: raw, + hashes_end: hashes_end, + marker: marker::ContravariantLifetime, + }, + table: self, + } + } + + /// Returns an iterator that copies out each entry. Used while the table + /// is being dropped. + unsafe fn rev_move_buckets(&mut self) -> RevMoveBuckets { + let raw_bucket = self.first_bucket_raw(); + RevMoveBuckets { + raw: raw_bucket.offset(self.capacity as int), + hashes_end: raw_bucket.hash, + elems_left: self.size, + marker: marker::ContravariantLifetime, + } + } +} + +/// A raw iterator. The basis for some other iterators in this module. Although +/// this interface is safe, it's not used outside this module. +struct RawBuckets<'a, K, V> { + raw: RawBucket, + hashes_end: *mut u64, + marker: marker::ContravariantLifetime<'a>, +} + +impl<'a, K, V> Iterator> for RawBuckets<'a, K, V> { + fn next(&mut self) -> Option> { + while self.raw.hash != self.hashes_end { + unsafe { + // We are swapping out the pointer to a bucket and replacing + // it with the pointer to the next one. + let prev = ptr::replace(&mut self.raw, self.raw.offset(1)); + if *prev.hash != EMPTY_BUCKET { + return Some(prev); + } + } + } + + None + } +} + +/// An iterator that moves out buckets in reverse order. It leaves the table +/// in an an inconsistent state and should only be used for dropping +/// the table's remaining entries. It's used in the implementation of Drop. +struct RevMoveBuckets<'a, K, V> { + raw: RawBucket, + hashes_end: *mut u64, + elems_left: uint, + marker: marker::ContravariantLifetime<'a>, +} + +impl<'a, K, V> Iterator<(K, V)> for RevMoveBuckets<'a, K, V> { + fn next(&mut self) -> Option<(K, V)> { + if self.elems_left == 0 { + return None; + } + + loop { + debug_assert!(self.raw.hash != self.hashes_end); + + unsafe { + self.raw = self.raw.offset(-1); + + if *self.raw.hash != EMPTY_BUCKET { + self.elems_left -= 1; + return Some(( + ptr::read(self.raw.key as *const K), + ptr::read(self.raw.val as *const V) + )); + } + } + } + } +} + +/// Iterator over shared references to entries in a table. +pub struct Entries<'a, K: 'a, V: 'a> { + iter: RawBuckets<'a, K, V>, + elems_left: uint, +} + +/// Iterator over mutable references to entries in a table. +pub struct MutEntries<'a, K: 'a, V: 'a> { + iter: RawBuckets<'a, K, V>, + elems_left: uint, +} + +/// Iterator over the entries in a table, consuming the table. +pub struct MoveEntries { + table: RawTable, + iter: RawBuckets<'static, K, V> +} + +impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> { + fn next(&mut self) -> Option<(&'a K, &'a V)> { + self.iter.next().map(|bucket| { + self.elems_left -= 1; + unsafe { + (&*bucket.key, + &*bucket.val) + } + }) + } + + fn size_hint(&self) -> (uint, Option) { + (self.elems_left, Some(self.elems_left)) + } +} + +impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> { + fn next(&mut self) -> Option<(&'a K, &'a mut V)> { + self.iter.next().map(|bucket| { + self.elems_left -= 1; + unsafe { + (&*bucket.key, + &mut *bucket.val) + } + }) + } + + fn size_hint(&self) -> (uint, Option) { + (self.elems_left, Some(self.elems_left)) + } +} + +impl Iterator<(SafeHash, K, V)> for MoveEntries { + fn next(&mut self) -> Option<(SafeHash, K, V)> { + self.iter.next().map(|bucket| { + self.table.size -= 1; + unsafe { + ( + SafeHash { + hash: *bucket.hash, + }, + ptr::read(bucket.key as *const K), + ptr::read(bucket.val as *const V) + ) + } + }) + } + + fn size_hint(&self) -> (uint, Option) { + let size = self.table.size(); + (size, Some(size)) + } +} + +impl Clone for RawTable { + fn clone(&self) -> RawTable { + unsafe { + let mut new_ht = RawTable::new_uninitialized(self.capacity()); + + { + let cap = self.capacity(); + let mut new_buckets = Bucket::first(&mut new_ht); + let mut buckets = Bucket::first(self); + while buckets.index() != cap { + match buckets.peek() { + Full(full) => { + let (h, k, v) = { + let (k, v) = full.read(); + (full.hash(), k.clone(), v.clone()) + }; + *new_buckets.raw.hash = h.inspect(); + ptr::write(new_buckets.raw.key, k); + ptr::write(new_buckets.raw.val, v); + } + Empty(..) => { + *new_buckets.raw.hash = EMPTY_BUCKET; + } + } + new_buckets.next(); + buckets.next(); + } + }; + + new_ht.size = self.size(); + + new_ht + } + } +} + +#[unsafe_destructor] +impl Drop for RawTable { + fn drop(&mut self) { + if self.hashes.is_null() { + return; + } + // This is done in reverse because we've likely partially taken + // some elements out with `.into_iter()` from the front. + // Check if the size is 0, so we don't do a useless scan when + // dropping empty tables such as on resize. + // Also avoid double drop of elements that have been already moved out. + unsafe { + for _ in self.rev_move_buckets() {} + } + + let hashes_size = self.capacity * size_of::(); + let keys_size = self.capacity * size_of::(); + let vals_size = self.capacity * size_of::(); + let (align, _, size) = calculate_allocation(hashes_size, min_align_of::(), + keys_size, min_align_of::(), + vals_size, min_align_of::()); + + unsafe { + deallocate(self.hashes as *mut u8, size, align); + // Remember how everything was allocated out of one buffer + // during initialization? We only need one call to free here. + } + } +} diff --git a/src/libstd/collections/hashmap/bench.rs b/src/libstd/collections/hashmap/bench.rs deleted file mode 100644 index 21bbb38f489..00000000000 --- a/src/libstd/collections/hashmap/bench.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![cfg(test)] - -extern crate test; -use prelude::*; - -use self::test::Bencher; -use iter::{range_inclusive}; - -#[bench] -fn new_drop(b : &mut Bencher) { - use super::HashMap; - - b.iter(|| { - let m : HashMap = HashMap::new(); - assert_eq!(m.len(), 0); - }) -} - -#[bench] -fn new_insert_drop(b : &mut Bencher) { - use super::HashMap; - - b.iter(|| { - let mut m = HashMap::new(); - m.insert(0i, 0i); - assert_eq!(m.len(), 1); - }) -} - -#[bench] -fn grow_by_insertion(b: &mut Bencher) { - use super::HashMap; - - let mut m = HashMap::new(); - - for i in range_inclusive(1i, 1000) { - m.insert(i, i); - } - - let mut k = 1001; - - b.iter(|| { - m.insert(k, k); - k += 1; - }); -} - -#[bench] -fn find_existing(b: &mut Bencher) { - use super::HashMap; - - let mut m = HashMap::new(); - - for i in range_inclusive(1i, 1000) { - m.insert(i, i); - } - - b.iter(|| { - for i in range_inclusive(1i, 1000) { - m.contains_key(&i); - } - }); -} - -#[bench] -fn find_nonexisting(b: &mut Bencher) { - use super::HashMap; - - let mut m = HashMap::new(); - - for i in range_inclusive(1i, 1000) { - m.insert(i, i); - } - - b.iter(|| { - for i in range_inclusive(1001i, 2000) { - m.contains_key(&i); - } - }); -} - -#[bench] -fn hashmap_as_queue(b: &mut Bencher) { - use super::HashMap; - - let mut m = HashMap::new(); - - for i in range_inclusive(1i, 1000) { - m.insert(i, i); - } - - let mut k = 1i; - - b.iter(|| { - m.pop(&k); - m.insert(k + 1000, k + 1000); - k += 1; - }); -} - -#[bench] -fn find_pop_insert(b: &mut Bencher) { - use super::HashMap; - - let mut m = HashMap::new(); - - for i in range_inclusive(1i, 1000) { - m.insert(i, i); - } - - let mut k = 1i; - - b.iter(|| { - m.find(&(k + 400)); - m.find(&(k + 2000)); - m.pop(&k); - m.insert(k + 1000, k + 1000); - k += 1; - }) -} diff --git a/src/libstd/collections/hashmap/map.rs b/src/libstd/collections/hashmap/map.rs deleted file mode 100644 index 596e483c2f6..00000000000 --- a/src/libstd/collections/hashmap/map.rs +++ /dev/null @@ -1,2133 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// ignore-lexer-test FIXME #15883 - -use clone::Clone; -use cmp::{max, Eq, Equiv, PartialEq}; -use default::Default; -use fmt::{mod, Show}; -use hash::{Hash, Hasher, RandomSipHasher}; -use iter::{mod, Iterator, FromIterator, Extendable}; -use kinds::Sized; -use mem::{mod, replace}; -use num; -use ops::{Deref, Index, IndexMut}; -use option::{Some, None, Option}; -use result::{Result, Ok, Err}; - -use super::table; -use super::table::{ - Bucket, - Empty, - EmptyBucket, - Full, - FullBucket, - FullBucketImm, - FullBucketMut, - RawTable, - SafeHash -}; - -const INITIAL_LOG2_CAP: uint = 5; -pub const INITIAL_CAPACITY: uint = 1 << INITIAL_LOG2_CAP; // 2^5 - -/// The default behavior of HashMap implements a load factor of 90.9%. -/// This behavior is characterized by the following conditions: -/// -/// - if size > 0.909 * capacity: grow -/// - if size < 0.25 * capacity: shrink (if this won't bring capacity lower -/// than the minimum) -#[deriving(Clone)] -struct DefaultResizePolicy { - /// Doubled minimal capacity. The capacity must never drop below - /// the minimum capacity. (The check happens before the capacity - /// is potentially halved.) - minimum_capacity2: uint -} - -impl DefaultResizePolicy { - fn new(new_capacity: uint) -> DefaultResizePolicy { - DefaultResizePolicy { - minimum_capacity2: new_capacity << 1 - } - } - - #[inline] - fn capacity_range(&self, new_size: uint) -> (uint, uint) { - // Here, we are rephrasing the logic by specifying the ranges: - // - // - if `size * 1.1 < cap < size * 4`: don't resize - // - if `cap < minimum_capacity * 2`: don't shrink - // - otherwise, resize accordingly - ((new_size * 11) / 10, max(new_size << 2, self.minimum_capacity2)) - } - - #[inline] - fn reserve(&mut self, new_capacity: uint) { - self.minimum_capacity2 = new_capacity << 1; - } -} - -// The main performance trick in this hashmap is called Robin Hood Hashing. -// It gains its excellent performance from one essential operation: -// -// If an insertion collides with an existing element, and that element's -// "probe distance" (how far away the element is from its ideal location) -// is higher than how far we've already probed, swap the elements. -// -// This massively lowers variance in probe distance, and allows us to get very -// high load factors with good performance. The 90% load factor I use is rather -// conservative. -// -// > Why a load factor of approximately 90%? -// -// In general, all the distances to initial buckets will converge on the mean. -// At a load factor of α, the odds of finding the target bucket after k -// probes is approximately 1-α^k. If we set this equal to 50% (since we converge -// on the mean) and set k=8 (64-byte cache line / 8-byte hash), α=0.92. I round -// this down to make the math easier on the CPU and avoid its FPU. -// Since on average we start the probing in the middle of a cache line, this -// strategy pulls in two cache lines of hashes on every lookup. I think that's -// pretty good, but if you want to trade off some space, it could go down to one -// cache line on average with an α of 0.84. -// -// > Wait, what? Where did you get 1-α^k from? -// -// On the first probe, your odds of a collision with an existing element is α. -// The odds of doing this twice in a row is approximately α^2. For three times, -// α^3, etc. Therefore, the odds of colliding k times is α^k. The odds of NOT -// colliding after k tries is 1-α^k. -// -// The paper from 1986 cited below mentions an implementation which keeps track -// of the distance-to-initial-bucket histogram. This approach is not suitable -// for modern architectures because it requires maintaining an internal data -// structure. This allows very good first guesses, but we are most concerned -// with guessing entire cache lines, not individual indexes. Furthermore, array -// accesses are no longer linear and in one direction, as we have now. There -// is also memory and cache pressure that this would entail that would be very -// difficult to properly see in a microbenchmark. -// -// ## Future Improvements (FIXME!) -// -// Allow the load factor to be changed dynamically and/or at initialization. -// -// Also, would it be possible for us to reuse storage when growing the -// underlying table? This is exactly the use case for 'realloc', and may -// be worth exploring. -// -// ## Future Optimizations (FIXME!) -// -// Another possible design choice that I made without any real reason is -// parameterizing the raw table over keys and values. Technically, all we need -// is the size and alignment of keys and values, and the code should be just as -// efficient (well, we might need one for power-of-two size and one for not...). -// This has the potential to reduce code bloat in rust executables, without -// really losing anything except 4 words (key size, key alignment, val size, -// val alignment) which can be passed in to every call of a `RawTable` function. -// This would definitely be an avenue worth exploring if people start complaining -// about the size of rust executables. -// -// Annotate exceedingly likely branches in `table::make_hash` -// and `search_hashed_generic` to reduce instruction cache pressure -// and mispredictions once it becomes possible (blocked on issue #11092). -// -// Shrinking the table could simply reallocate in place after moving buckets -// to the first half. -// -// The growth algorithm (fragment of the Proof of Correctness) -// -------------------- -// -// The growth algorithm is basically a fast path of the naive reinsertion- -// during-resize algorithm. Other paths should never be taken. -// -// Consider growing a robin hood hashtable of capacity n. Normally, we do this -// by allocating a new table of capacity `2n`, and then individually reinsert -// each element in the old table into the new one. This guarantees that the -// new table is a valid robin hood hashtable with all the desired statistical -// properties. Remark that the order we reinsert the elements in should not -// matter. For simplicity and efficiency, we will consider only linear -// reinsertions, which consist of reinserting all elements in the old table -// into the new one by increasing order of index. However we will not be -// starting our reinsertions from index 0 in general. If we start from index -// i, for the purpose of reinsertion we will consider all elements with real -// index j < i to have virtual index n + j. -// -// Our hash generation scheme consists of generating a 64-bit hash and -// truncating the most significant bits. When moving to the new table, we -// simply introduce a new bit to the front of the hash. Therefore, if an -// elements has ideal index i in the old table, it can have one of two ideal -// locations in the new table. If the new bit is 0, then the new ideal index -// is i. If the new bit is 1, then the new ideal index is n + i. Intutively, -// we are producing two independent tables of size n, and for each element we -// independently choose which table to insert it into with equal probability. -// However the rather than wrapping around themselves on overflowing their -// indexes, the first table overflows into the first, and the first into the -// second. Visually, our new table will look something like: -// -// [yy_xxx_xxxx_xxx|xx_yyy_yyyy_yyy] -// -// Where x's are elements inserted into the first table, y's are elements -// inserted into the second, and _'s are empty sections. We now define a few -// key concepts that we will use later. Note that this is a very abstract -// perspective of the table. A real resized table would be at least half -// empty. -// -// Theorem: A linear robin hood reinsertion from the first ideal element -// produces identical results to a linear naive reinsertion from the same -// element. -// -// FIXME(Gankro, pczarn): review the proof and put it all in a separate doc.rs - -/// A hash map implementation which uses linear probing with Robin -/// Hood bucket stealing. -/// -/// The hashes are all keyed by the task-local random number generator -/// on creation by default. This means that the ordering of the keys is -/// randomized, but makes the tables more resistant to -/// denial-of-service attacks (Hash DoS). This behaviour can be -/// overridden with one of the constructors. -/// -/// It is required that the keys implement the `Eq` and `Hash` traits, although -/// this can frequently be achieved by using `#[deriving(Eq, Hash)]`. -/// -/// Relevant papers/articles: -/// -/// 1. Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf) -/// 2. Emmanuel Goossaert. ["Robin Hood -/// hashing"](http://codecapsule.com/2013/11/11/robin-hood-hashing/) -/// 3. Emmanuel Goossaert. ["Robin Hood hashing: backward shift -/// deletion"](http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/) -/// -/// # Example -/// -/// ``` -/// use std::collections::HashMap; -/// -/// // type inference lets us omit an explicit type signature (which -/// // would be `HashMap<&str, &str>` in this example). -/// let mut book_reviews = HashMap::new(); -/// -/// // review some books. -/// book_reviews.insert("Adventures of Huckleberry Finn", "My favorite book."); -/// book_reviews.insert("Grimms' Fairy Tales", "Masterpiece."); -/// book_reviews.insert("Pride and Prejudice", "Very enjoyable."); -/// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot."); -/// -/// // check for a specific one. -/// if !book_reviews.contains_key(&("Les Misérables")) { -/// println!("We've got {} reviews, but Les Misérables ain't one.", -/// book_reviews.len()); -/// } -/// -/// // oops, this review has a lot of spelling mistakes, let's delete it. -/// book_reviews.remove(&("The Adventures of Sherlock Holmes")); -/// -/// // look up the values associated with some keys. -/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"]; -/// for book in to_find.iter() { -/// match book_reviews.find(book) { -/// Some(review) => println!("{}: {}", *book, *review), -/// None => println!("{} is unreviewed.", *book) -/// } -/// } -/// -/// // iterate over everything. -/// for (book, review) in book_reviews.iter() { -/// println!("{}: \"{}\"", *book, *review); -/// } -/// ``` -/// -/// The easiest way to use `HashMap` with a custom type is to derive `Eq` and `Hash`. -/// We must also derive `PartialEq`. -/// -/// ``` -/// use std::collections::HashMap; -/// -/// #[deriving(Hash, Eq, PartialEq, Show)] -/// struct Viking<'a> { -/// name: &'a str, -/// power: uint, -/// } -/// -/// let mut vikings = HashMap::new(); -/// -/// vikings.insert("Norway", Viking { name: "Einar", power: 9u }); -/// vikings.insert("Denmark", Viking { name: "Olaf", power: 4u }); -/// vikings.insert("Iceland", Viking { name: "Harald", power: 8u }); -/// -/// // Use derived implementation to print the vikings. -/// for (land, viking) in vikings.iter() { -/// println!("{} at {}", viking, land); -/// } -/// ``` -#[deriving(Clone)] -pub struct HashMap { - // All hashes are keyed on these values, to prevent hash collision attacks. - hasher: H, - - table: RawTable, - - // We keep this at the end since it might as well have tail padding. - resize_policy: DefaultResizePolicy, -} - -/// Search for a pre-hashed key. -fn search_hashed_generic>>(table: M, - hash: &SafeHash, - is_match: |&K| -> bool) - -> SearchResult { - let size = table.size(); - let mut probe = Bucket::new(table, hash); - let ib = probe.index(); - - while probe.index() != ib + size { - let full = match probe.peek() { - Empty(b) => return TableRef(b.into_table()), // hit an empty bucket - Full(b) => b - }; - - if full.distance() + ib < full.index() { - // We can finish the search early if we hit any bucket - // with a lower distance to initial bucket than we've probed. - return TableRef(full.into_table()); - } - - // If the hash doesn't match, it can't be this one.. - if *hash == full.hash() { - let matched = { - let (k, _) = full.read(); - is_match(k) - }; - - // If the key doesn't match, it can't be this one.. - if matched { - return FoundExisting(full); - } - } - - probe = full.next(); - } - - TableRef(probe.into_table()) -} - -fn search_hashed>>(table: M, hash: &SafeHash, k: &K) - -> SearchResult { - search_hashed_generic(table, hash, |k_| *k == *k_) -} - -fn pop_internal(starting_bucket: FullBucketMut) -> (K, V) { - let (empty, retkey, retval) = starting_bucket.take(); - let mut gap = match empty.gap_peek() { - Some(b) => b, - None => return (retkey, retval) - }; - - while gap.full().distance() != 0 { - gap = match gap.shift() { - Some(b) => b, - None => break - }; - } - - // Now we've done all our shifting. Return the value we grabbed earlier. - return (retkey, retval); -} - -/// Perform robin hood bucket stealing at the given `bucket`. You must -/// also pass the position of that bucket's initial bucket so we don't have -/// to recalculate it. -/// -/// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable. -fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>, - mut ib: uint, - mut hash: SafeHash, - mut k: K, - mut v: V) - -> &'a mut V { - let starting_index = bucket.index(); - let size = { - let table = bucket.table(); // FIXME "lifetime too short". - table.size() - }; - // There can be at most `size - dib` buckets to displace, because - // in the worst case, there are `size` elements and we already are - // `distance` buckets away from the initial one. - let idx_end = starting_index + size - bucket.distance(); - - loop { - let (old_hash, old_key, old_val) = bucket.replace(hash, k, v); - loop { - let probe = bucket.next(); - assert!(probe.index() != idx_end); - - let full_bucket = match probe.peek() { - table::Empty(bucket) => { - // Found a hole! - let b = bucket.put(old_hash, old_key, old_val); - // Now that it's stolen, just read the value's pointer - // right out of the table! - let (_, v) = Bucket::at_index(b.into_table(), starting_index).peek() - .expect_full() - .into_mut_refs(); - return v; - }, - table::Full(bucket) => bucket - }; - - let probe_ib = full_bucket.index() - full_bucket.distance(); - - bucket = full_bucket; - - // Robin hood! Steal the spot. - if ib < probe_ib { - ib = probe_ib; - hash = old_hash; - k = old_key; - v = old_val; - break; - } - } - } -} - -/// A result that works like Option> but preserves -/// the reference that grants us access to the table in any case. -enum SearchResult { - // This is an entry that holds the given key: - FoundExisting(FullBucket), - - // There was no such entry. The reference is given back: - TableRef(M) -} - -impl SearchResult { - fn into_option(self) -> Option> { - match self { - FoundExisting(bucket) => Some(bucket), - TableRef(_) => None - } - } -} - -impl, V, S, H: Hasher> HashMap { - fn make_hash>(&self, x: &X) -> SafeHash { - table::make_hash(&self.hasher, x) - } - - fn search_equiv<'a, Sized? Q: Hash + Equiv>(&'a self, q: &Q) - -> Option> { - let hash = self.make_hash(q); - search_hashed_generic(&self.table, &hash, |k| q.equiv(k)).into_option() - } - - fn search_equiv_mut<'a, Sized? Q: Hash + Equiv>(&'a mut self, q: &Q) - -> Option> { - let hash = self.make_hash(q); - search_hashed_generic(&mut self.table, &hash, |k| q.equiv(k)).into_option() - } - - /// Search for a key, yielding the index if it's found in the hashtable. - /// If you already have the hash for the key lying around, use - /// search_hashed. - fn search<'a>(&'a self, k: &K) -> Option> { - let hash = self.make_hash(k); - search_hashed(&self.table, &hash, k).into_option() - } - - fn search_mut<'a>(&'a mut self, k: &K) -> Option> { - let hash = self.make_hash(k); - search_hashed(&mut self.table, &hash, k).into_option() - } - - // The caller should ensure that invariants by Robin Hood Hashing hold. - fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) { - let cap = self.table.capacity(); - let mut buckets = Bucket::new(&mut self.table, &hash); - let ib = buckets.index(); - - while buckets.index() != ib + cap { - // We don't need to compare hashes for value swap. - // Not even DIBs for Robin Hood. - buckets = match buckets.peek() { - Empty(empty) => { - empty.put(hash, k, v); - return; - } - Full(b) => b.into_bucket() - }; - buckets.next(); - } - panic!("Internal HashMap error: Out of space."); - } -} - -impl HashMap { - /// Create an empty HashMap. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10); - /// ``` - #[inline] - pub fn new() -> HashMap { - let hasher = RandomSipHasher::new(); - HashMap::with_hasher(hasher) - } - - /// Creates an empty hash map with the given initial capacity. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10); - /// ``` - #[inline] - pub fn with_capacity(capacity: uint) -> HashMap { - let hasher = RandomSipHasher::new(); - HashMap::with_capacity_and_hasher(capacity, hasher) - } -} - -impl, V, S, H: Hasher> HashMap { - /// Creates an empty hashmap which will use the given hasher to hash keys. - /// - /// The creates map has the default initial capacity. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// use std::hash::sip::SipHasher; - /// - /// let h = SipHasher::new(); - /// let mut map = HashMap::with_hasher(h); - /// map.insert(1i, 2u); - /// ``` - #[inline] - pub fn with_hasher(hasher: H) -> HashMap { - HashMap { - hasher: hasher, - resize_policy: DefaultResizePolicy::new(INITIAL_CAPACITY), - table: RawTable::new(0), - } - } - - /// Create an empty HashMap with space for at least `capacity` - /// elements, using `hasher` to hash the keys. - /// - /// Warning: `hasher` is normally randomly generated, and - /// is designed to allow HashMaps to be resistant to attacks that - /// cause many collisions and very poor performance. Setting it - /// manually using this function can expose a DoS attack vector. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// use std::hash::sip::SipHasher; - /// - /// let h = SipHasher::new(); - /// let mut map = HashMap::with_capacity_and_hasher(10, h); - /// map.insert(1i, 2u); - /// ``` - #[inline] - pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap { - let cap = num::next_power_of_two(max(INITIAL_CAPACITY, capacity)); - HashMap { - hasher: hasher, - resize_policy: DefaultResizePolicy::new(cap), - table: RawTable::new(cap), - } - } - - /// The hashtable will never try to shrink below this size. You can use - /// this function to reduce reallocations if your hashtable frequently - /// grows and shrinks by large amounts. - /// - /// This function has no effect on the operational semantics of the - /// hashtable, only on performance. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// let mut map: HashMap<&str, int> = HashMap::new(); - /// map.reserve(10); - /// ``` - pub fn reserve(&mut self, new_minimum_capacity: uint) { - let cap = num::next_power_of_two( - max(INITIAL_CAPACITY, new_minimum_capacity)); - - self.resize_policy.reserve(cap); - - if self.table.capacity() < cap { - self.resize(cap); - } - } - - /// Resizes the internal vectors to a new capacity. It's your responsibility to: - /// 1) Make sure the new capacity is enough for all the elements, accounting - /// for the load factor. - /// 2) Ensure new_capacity is a power of two. - fn resize(&mut self, new_capacity: uint) { - assert!(self.table.size() <= new_capacity); - assert!(num::is_power_of_two(new_capacity)); - - let mut old_table = replace(&mut self.table, RawTable::new(new_capacity)); - let old_size = old_table.size(); - - if old_table.capacity() == 0 || old_table.size() == 0 { - return; - } - - if new_capacity < old_table.capacity() { - // Shrink the table. Naive algorithm for resizing: - for (h, k, v) in old_table.into_iter() { - self.insert_hashed_nocheck(h, k, v); - } - } else { - // Grow the table. - // Specialization of the other branch. - let mut bucket = Bucket::first(&mut old_table); - - // "So a few of the first shall be last: for many be called, - // but few chosen." - // - // We'll most likely encounter a few buckets at the beginning that - // have their initial buckets near the end of the table. They were - // placed at the beginning as the probe wrapped around the table - // during insertion. We must skip forward to a bucket that won't - // get reinserted too early and won't unfairly steal others spot. - // This eliminates the need for robin hood. - loop { - bucket = match bucket.peek() { - Full(full) => { - if full.distance() == 0 { - // This bucket occupies its ideal spot. - // It indicates the start of another "cluster". - bucket = full.into_bucket(); - break; - } - // Leaving this bucket in the last cluster for later. - full.into_bucket() - } - Empty(b) => { - // Encountered a hole between clusters. - b.into_bucket() - } - }; - bucket.next(); - } - - // This is how the buckets might be laid out in memory: - // ($ marks an initialized bucket) - // ________________ - // |$$$_$$$$$$_$$$$$| - // - // But we've skipped the entire initial cluster of buckets - // and will continue iteration in this order: - // ________________ - // |$$$$$$_$$$$$ - // ^ wrap around once end is reached - // ________________ - // $$$_____________| - // ^ exit once table.size == 0 - loop { - bucket = match bucket.peek() { - Full(bucket) => { - let h = bucket.hash(); - let (b, k, v) = bucket.take(); - self.insert_hashed_ordered(h, k, v); - { - let t = b.table(); // FIXME "lifetime too short". - if t.size() == 0 { break } - }; - b.into_bucket() - } - Empty(b) => b.into_bucket() - }; - bucket.next(); - } - } - - assert_eq!(self.table.size(), old_size); - } - - /// Performs any necessary resize operations, such that there's space for - /// new_size elements. - fn make_some_room(&mut self, new_size: uint) { - let (grow_at, shrink_at) = self.resize_policy.capacity_range(new_size); - let cap = self.table.capacity(); - - // An invalid value shouldn't make us run out of space. - debug_assert!(grow_at >= new_size); - - if cap <= grow_at { - let new_capacity = max(cap << 1, INITIAL_CAPACITY); - self.resize(new_capacity); - } else if shrink_at <= cap { - let new_capacity = cap >> 1; - self.resize(new_capacity); - } - } - - /// Insert a pre-hashed key-value pair, without first checking - /// that there's enough room in the buckets. Returns a reference to the - /// newly insert value. - /// - /// If the key already exists, the hashtable will be returned untouched - /// and a reference to the existing element will be returned. - fn insert_hashed_nocheck(&mut self, hash: SafeHash, k: K, v: V) -> &mut V { - self.insert_or_replace_with(hash, k, v, |_, _, _| ()) - } - - fn insert_or_replace_with<'a>(&'a mut self, - hash: SafeHash, - k: K, - v: V, - found_existing: |&mut K, &mut V, V|) - -> &'a mut V { - // Worst case, we'll find one empty bucket among `size + 1` buckets. - let size = self.table.size(); - let mut probe = Bucket::new(&mut self.table, &hash); - let ib = probe.index(); - - loop { - let mut bucket = match probe.peek() { - Empty(bucket) => { - // Found a hole! - let bucket = bucket.put(hash, k, v); - let (_, val) = bucket.into_mut_refs(); - return val; - }, - Full(bucket) => bucket - }; - - if bucket.hash() == hash { - let found_match = { - let (bucket_k, _) = bucket.read_mut(); - k == *bucket_k - }; - if found_match { - let (bucket_k, bucket_v) = bucket.into_mut_refs(); - debug_assert!(k == *bucket_k); - // Key already exists. Get its reference. - found_existing(bucket_k, bucket_v, v); - return bucket_v; - } - } - - let robin_ib = bucket.index() as int - bucket.distance() as int; - - if (ib as int) < robin_ib { - // Found a luckier bucket than me. Better steal his spot. - return robin_hood(bucket, robin_ib as uint, hash, k, v); - } - - probe = bucket.next(); - assert!(probe.index() != ib + size + 1); - } - } - - /// Retrieves a mutable value for the given key. - /// See [`find_mut`](../trait.MutableMap.html#tymethod.find_mut) for a non-panicking - /// alternative. - /// - /// # Failure - /// - /// Fails if the key is not present. - /// - /// # Example - /// - /// ``` - /// # #![allow(deprecated)] - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1i); - /// { - /// // val will freeze map to prevent usage during its lifetime - /// let val = map.get_mut(&"a"); - /// *val = 40; - /// } - /// assert_eq!(map["a"], 40); - /// - /// // A more direct way could be: - /// *map.get_mut(&"a") = -2; - /// assert_eq!(map["a"], -2); - /// ``` - #[deprecated = "use indexing instead: `&mut map[key]`"] - pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V { - &mut self[*k] - } - - /// Return true if the map contains a value for the specified key, - /// using equivalence. - /// - /// See [pop_equiv](#method.pop_equiv) for an extended example. - pub fn contains_key_equiv + Equiv>(&self, key: &Q) -> bool { - self.search_equiv(key).is_some() - } - - /// Return the value corresponding to the key in the map, using - /// equivalence. - /// - /// See [pop_equiv](#method.pop_equiv) for an extended example. - pub fn find_equiv<'a, Sized? Q: Hash + Equiv>(&'a self, k: &Q) -> Option<&'a V> { - match self.search_equiv(k) { - None => None, - Some(bucket) => { - let (_, v_ref) = bucket.into_refs(); - Some(v_ref) - } - } - } - - /// Remove an equivalent key from the map, returning the value at the - /// key if the key was previously in the map. - /// - /// # Example - /// - /// This is a slightly silly example where we define the number's - /// parity as the equivalence class. It is important that the - /// values hash the same, which is why we implement `Hash`. - /// - /// ``` - /// use std::collections::HashMap; - /// use std::hash::Hash; - /// use std::hash::sip::SipState; - /// - /// #[deriving(Eq, PartialEq)] - /// struct EvenOrOdd { - /// num: uint - /// }; - /// - /// impl Hash for EvenOrOdd { - /// fn hash(&self, state: &mut SipState) { - /// let parity = self.num % 2; - /// parity.hash(state); - /// } - /// } - /// - /// impl Equiv for EvenOrOdd { - /// fn equiv(&self, other: &EvenOrOdd) -> bool { - /// self.num % 2 == other.num % 2 - /// } - /// } - /// - /// let mut map = HashMap::new(); - /// map.insert(EvenOrOdd { num: 3 }, "foo"); - /// - /// assert!(map.contains_key_equiv(&EvenOrOdd { num: 1 })); - /// assert!(!map.contains_key_equiv(&EvenOrOdd { num: 4 })); - /// - /// assert_eq!(map.find_equiv(&EvenOrOdd { num: 5 }), Some(&"foo")); - /// assert_eq!(map.find_equiv(&EvenOrOdd { num: 2 }), None); - /// - /// assert_eq!(map.pop_equiv(&EvenOrOdd { num: 1 }), Some("foo")); - /// assert_eq!(map.pop_equiv(&EvenOrOdd { num: 2 }), None); - /// - /// ``` - #[experimental] - pub fn pop_equiv + Equiv>(&mut self, k: &Q) -> Option { - if self.table.size() == 0 { - return None - } - - let potential_new_size = self.table.size() - 1; - self.make_some_room(potential_new_size); - - match self.search_equiv_mut(k) { - Some(bucket) => { - let (_k, val) = pop_internal(bucket); - Some(val) - } - _ => None - } - } - - /// An iterator visiting all keys in arbitrary order. - /// Iterator element type is `&'a K`. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1i); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for key in map.keys() { - /// println!("{}", key); - /// } - /// ``` - pub fn keys(&self) -> Keys { - self.iter().map(|(k, _v)| k) - } - - /// An iterator visiting all values in arbitrary order. - /// Iterator element type is `&'a V`. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1i); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for key in map.values() { - /// println!("{}", key); - /// } - /// ``` - pub fn values(&self) -> Values { - self.iter().map(|(_k, v)| v) - } - - /// An iterator visiting all key-value pairs in arbitrary order. - /// Iterator element type is `(&'a K, &'a V)`. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1i); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// for (key, val) in map.iter() { - /// println!("key: {} val: {}", key, val); - /// } - /// ``` - pub fn iter(&self) -> Entries { - Entries { inner: self.table.iter() } - } - - /// An iterator visiting all key-value pairs in arbitrary order, - /// with mutable references to the values. - /// Iterator element type is `(&'a K, &'a mut V)`. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1i); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// // Update all values - /// for (_, val) in map.iter_mut() { - /// *val *= 2; - /// } - /// - /// for (key, val) in map.iter() { - /// println!("key: {} val: {}", key, val); - /// } - /// ``` - pub fn iter_mut(&mut self) -> MutEntries { - MutEntries { inner: self.table.iter_mut() } - } - - /// Creates a consuming iterator, that is, one that moves each key-value - /// pair out of the map in arbitrary order. The map cannot be used after - /// calling this. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1i); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// // Not possible with .iter() - /// let vec: Vec<(&str, int)> = map.into_iter().collect(); - /// ``` - pub fn into_iter(self) -> MoveEntries { - MoveEntries { - inner: self.table.into_iter().map(|(_, k, v)| (k, v)) - } - } - - /// Gets the given key's corresponding entry in the map for in-place manipulation - pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V> { - // Gotta resize now, and we don't know which direction, so try both? - let size = self.table.size(); - self.make_some_room(size + 1); - if size > 0 { - self.make_some_room(size - 1); - } - - let hash = self.make_hash(&key); - search_entry_hashed(&mut self.table, hash, key) - } - - /// Return the number of elements in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut a = HashMap::new(); - /// assert_eq!(a.len(), 0); - /// a.insert(1u, "a"); - /// assert_eq!(a.len(), 1); - /// ``` - pub fn len(&self) -> uint { self.table.size() } - - /// Return true if the map contains no elements. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut a = HashMap::new(); - /// assert!(a.is_empty()); - /// a.insert(1u, "a"); - /// assert!(!a.is_empty()); - /// ``` - #[inline] - pub fn is_empty(&self) -> bool { self.len() == 0 } - - /// Clears the map, removing all key-value pairs. Keeps the allocated memory - /// for reuse. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut a = HashMap::new(); - /// a.insert(1u, "a"); - /// a.clear(); - /// assert!(a.is_empty()); - /// ``` - pub fn clear(&mut self) { - // Prevent reallocations from happening from now on. Makes it possible - // for the map to be reused but has a downside: reserves permanently. - self.resize_policy.reserve(self.table.size()); - - let cap = self.table.capacity(); - let mut buckets = Bucket::first(&mut self.table); - - while buckets.index() != cap { - buckets = match buckets.peek() { - Empty(b) => b.next(), - Full(full) => { - let (b, _, _) = full.take(); - b.next() - } - }; - } - } - - /// Returns a reference to the value corresponding to the key. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1u, "a"); - /// assert_eq!(map.find(&1), Some(&"a")); - /// assert_eq!(map.find(&2), None); - /// ``` - pub fn find<'a>(&'a self, k: &K) -> Option<&'a V> { - self.search(k).map(|bucket| { - let (_, v) = bucket.into_refs(); - v - }) - } - - /// Returns true if the map contains a value for the specified key. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1u, "a"); - /// assert_eq!(map.contains_key(&1), true); - /// assert_eq!(map.contains_key(&2), false); - /// ``` - pub fn contains_key(&self, k: &K) -> bool { - self.search(k).is_some() - } - - /// Returns a mutable reference to the value corresponding to the key. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1u, "a"); - /// match map.find_mut(&1) { - /// Some(x) => *x = "b", - /// None => (), - /// } - /// assert_eq!(map[1], "b"); - /// ``` - pub fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> { - match self.search_mut(k) { - Some(bucket) => { - let (_, v) = bucket.into_mut_refs(); - Some(v) - } - _ => None - } - } - - /// Inserts a key-value pair into the map. An existing value for a - /// key is replaced by the new value. Returns `true` if the key did - /// not already exist in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// assert_eq!(map.insert(2u, "value"), true); - /// assert_eq!(map.insert(2, "value2"), false); - /// assert_eq!(map[2], "value2"); - /// ``` - #[inline] - pub fn insert(&mut self, key: K, value: V) -> bool { - self.swap(key, value).is_none() - } - - /// Removes a key-value pair from the map. Returns `true` if the key - /// was present in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// assert_eq!(map.remove(&1u), false); - /// map.insert(1, "a"); - /// assert_eq!(map.remove(&1), true); - /// ``` - #[inline] - pub fn remove(&mut self, key: &K) -> bool { - self.pop(key).is_some() - } - - /// Inserts a key-value pair from the map. If the key already had a value - /// present in the map, that value is returned. Otherwise, `None` is returned. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// assert_eq!(map.swap(37u, "a"), None); - /// assert_eq!(map.is_empty(), false); - /// - /// map.insert(37, "b"); - /// assert_eq!(map.swap(37, "c"), Some("b")); - /// assert_eq!(map[37], "c"); - /// ``` - pub fn swap(&mut self, k: K, v: V) -> Option { - let hash = self.make_hash(&k); - let potential_new_size = self.table.size() + 1; - self.make_some_room(potential_new_size); - - let mut retval = None; - self.insert_or_replace_with(hash, k, v, |_, val_ref, val| { - retval = Some(replace(val_ref, val)); - }); - retval - } - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert(1u, "a"); - /// assert_eq!(map.pop(&1), Some("a")); - /// assert_eq!(map.pop(&1), None); - /// ``` - pub fn pop(&mut self, k: &K) -> Option { - if self.table.size() == 0 { - return None - } - - let potential_new_size = self.table.size() - 1; - self.make_some_room(potential_new_size); - - self.search_mut(k).map(|bucket| { - let (_k, val) = pop_internal(bucket); - val - }) - } -} - -fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable, hash: SafeHash, k: K) - -> Entry<'a, K, V> { - // Worst case, we'll find one empty bucket among `size + 1` buckets. - let size = table.size(); - let mut probe = Bucket::new(table, &hash); - let ib = probe.index(); - - loop { - let bucket = match probe.peek() { - Empty(bucket) => { - // Found a hole! - return Vacant(VacantEntry { - hash: hash, - key: k, - elem: NoElem(bucket), - }); - }, - Full(bucket) => bucket - }; - - if bucket.hash() == hash { - let is_eq = { - let (bucket_k, _) = bucket.read(); - k == *bucket_k - }; - - if is_eq { - return Occupied(OccupiedEntry{ - elem: bucket, - }); - } - } - - let robin_ib = bucket.index() as int - bucket.distance() as int; - - if (ib as int) < robin_ib { - // Found a luckier bucket than me. Better steal his spot. - return Vacant(VacantEntry { - hash: hash, - key: k, - elem: NeqElem(bucket, robin_ib as uint), - }); - } - - probe = bucket.next(); - assert!(probe.index() != ib + size + 1); - } -} - -impl, V: Clone, S, H: Hasher> HashMap { - /// Return a copy of the value corresponding to the key. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map: HashMap = HashMap::new(); - /// map.insert(1u, "foo".to_string()); - /// let s: String = map.find_copy(&1).unwrap(); - /// ``` - pub fn find_copy(&self, k: &K) -> Option { - self.find(k).map(|v| (*v).clone()) - } - - /// Return a copy of the value corresponding to the key. - /// - /// # Failure - /// - /// Fails if the key is not present. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map: HashMap = HashMap::new(); - /// map.insert(1u, "foo".to_string()); - /// let s: String = map.get_copy(&1); - /// ``` - pub fn get_copy(&self, k: &K) -> V { - self[*k].clone() - } -} - -impl, V: PartialEq, S, H: Hasher> PartialEq for HashMap { - fn eq(&self, other: &HashMap) -> bool { - if self.len() != other.len() { return false; } - - self.iter().all(|(key, value)| - other.find(key).map_or(false, |v| *value == *v) - ) - } -} - -impl, V: Eq, S, H: Hasher> Eq for HashMap {} - -impl + Show, V: Show, S, H: Hasher> Show for HashMap { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, (k, v)) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}: {}", *k, *v)); - } - - write!(f, "}}") - } -} - -impl, V, S, H: Hasher + Default> Default for HashMap { - fn default() -> HashMap { - HashMap::with_hasher(Default::default()) - } -} - -impl, V, S, H: Hasher> Index for HashMap { - #[inline] - fn index<'a>(&'a self, index: &K) -> &'a V { - self.find(index).expect("no entry found for key") - } -} - -impl, V, S, H: Hasher> IndexMut for HashMap { - #[inline] - fn index_mut<'a>(&'a mut self, index: &K) -> &'a mut V { - match self.find_mut(index) { - Some(v) => v, - None => panic!("no entry found for key") - } - } -} - -/// HashMap iterator -pub struct Entries<'a, K: 'a, V: 'a> { - inner: table::Entries<'a, K, V> -} - -/// HashMap mutable values iterator -pub struct MutEntries<'a, K: 'a, V: 'a> { - inner: table::MutEntries<'a, K, V> -} - -/// HashMap move iterator -pub struct MoveEntries { - inner: iter::Map<'static, (SafeHash, K, V), (K, V), table::MoveEntries> -} - -/// A view into a single occupied location in a HashMap -pub struct OccupiedEntry<'a, K:'a, V:'a> { - elem: FullBucket>, -} - -/// A view into a single empty location in a HashMap -pub struct VacantEntry<'a, K:'a, V:'a> { - hash: SafeHash, - key: K, - elem: VacantEntryState>, -} - -/// A view into a single location in a map, which may be vacant or occupied -pub enum Entry<'a, K:'a, V:'a> { - /// An occupied Entry - Occupied(OccupiedEntry<'a, K, V>), - /// A vacant Entry - Vacant(VacantEntry<'a, K, V>), -} - -/// Possible states of a VacantEntry -enum VacantEntryState { - /// The index is occupied, but the key to insert has precedence, - /// and will kick the current one out on insertion - NeqElem(FullBucket, uint), - /// The index is genuinely vacant - NoElem(EmptyBucket), -} - -impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> { - #[inline] - fn next(&mut self) -> Option<(&'a K, &'a V)> { - self.inner.next() - } - #[inline] - fn size_hint(&self) -> (uint, Option) { - self.inner.size_hint() - } -} - -impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> { - #[inline] - fn next(&mut self) -> Option<(&'a K, &'a mut V)> { - self.inner.next() - } - #[inline] - fn size_hint(&self) -> (uint, Option) { - self.inner.size_hint() - } -} - -impl Iterator<(K, V)> for MoveEntries { - #[inline] - fn next(&mut self) -> Option<(K, V)> { - self.inner.next() - } - #[inline] - fn size_hint(&self) -> (uint, Option) { - self.inner.size_hint() - } -} - -impl<'a, K, V> OccupiedEntry<'a, K, V> { - /// Gets a reference to the value in the entry - pub fn get(&self) -> &V { - let (_, v) = self.elem.read(); - v - } - - /// Gets a mutable reference to the value in the entry - pub fn get_mut(&mut self) -> &mut V { - let (_, v) = self.elem.read_mut(); - v - } - - /// Converts the OccupiedEntry into a mutable reference to the value in the entry - /// with a lifetime bound to the map itself - pub fn into_mut(self) -> &'a mut V { - let (_, v) = self.elem.into_mut_refs(); - v - } - - /// Sets the value of the entry, and returns the entry's old value - pub fn set(&mut self, mut value: V) -> V { - let old_value = self.get_mut(); - mem::swap(&mut value, old_value); - value - } - - /// Takes the value out of the entry, and returns it - pub fn take(self) -> V { - let (_, _, v) = self.elem.take(); - v - } -} - -impl<'a, K, V> VacantEntry<'a, K, V> { - /// Sets the value of the entry with the VacantEntry's key, - /// and returns a mutable reference to it - pub fn set(self, value: V) -> &'a mut V { - match self.elem { - NeqElem(bucket, ib) => { - robin_hood(bucket, ib, self.hash, self.key, value) - } - NoElem(bucket) => { - let full = bucket.put(self.hash, self.key, value); - let (_, v) = full.into_mut_refs(); - v - } - } - } -} - -/// HashMap keys iterator -pub type Keys<'a, K, V> = - iter::Map<'static, (&'a K, &'a V), &'a K, Entries<'a, K, V>>; - -/// HashMap values iterator -pub type Values<'a, K, V> = - iter::Map<'static, (&'a K, &'a V), &'a V, Entries<'a, K, V>>; - -impl, V, S, H: Hasher + Default> FromIterator<(K, V)> for HashMap { - fn from_iter>(iter: T) -> HashMap { - let (lower, _) = iter.size_hint(); - let mut map = HashMap::with_capacity_and_hasher(lower, Default::default()); - map.extend(iter); - map - } -} - -impl, V, S, H: Hasher + Default> Extendable<(K, V)> for HashMap { - fn extend>(&mut self, mut iter: T) { - for (k, v) in iter { - self.insert(k, v); - } - } -} - -#[cfg(test)] -mod test_map { - use prelude::*; - - use super::HashMap; - use super::{Occupied, Vacant}; - use cmp::Equiv; - use hash; - use iter::{Iterator,range_inclusive,range_step_inclusive}; - use cell::RefCell; - - struct KindaIntLike(int); - - impl Equiv for KindaIntLike { - fn equiv(&self, other: &int) -> bool { - let KindaIntLike(this) = *self; - this == *other - } - } - impl hash::Hash for KindaIntLike { - fn hash(&self, state: &mut S) { - let KindaIntLike(this) = *self; - this.hash(state) - } - } - - #[test] - fn test_create_capacity_zero() { - let mut m = HashMap::with_capacity(0); - - assert!(m.insert(1i, 1i)); - - assert!(m.contains_key(&1)); - assert!(!m.contains_key(&0)); - } - - #[test] - fn test_insert() { - let mut m = HashMap::new(); - assert_eq!(m.len(), 0); - assert!(m.insert(1i, 2i)); - assert_eq!(m.len(), 1); - assert!(m.insert(2i, 4i)); - assert_eq!(m.len(), 2); - assert_eq!(*m.find(&1).unwrap(), 2); - assert_eq!(*m.find(&2).unwrap(), 4); - } - - local_data_key!(drop_vector: RefCell>) - - #[deriving(Hash, PartialEq, Eq)] - struct Dropable { - k: uint - } - - impl Dropable { - fn new(k: uint) -> Dropable { - let v = drop_vector.get().unwrap(); - v.borrow_mut().as_mut_slice()[k] += 1; - - Dropable { k: k } - } - } - - impl Drop for Dropable { - fn drop(&mut self) { - let v = drop_vector.get().unwrap(); - v.borrow_mut().as_mut_slice()[self.k] -= 1; - } - } - - impl Clone for Dropable { - fn clone(&self) -> Dropable { - Dropable::new(self.k) - } - } - - #[test] - fn test_drops() { - drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0i)))); - - { - let mut m = HashMap::new(); - - let v = drop_vector.get().unwrap(); - for i in range(0u, 200) { - assert_eq!(v.borrow().as_slice()[i], 0); - } - drop(v); - - for i in range(0u, 100) { - let d1 = Dropable::new(i); - let d2 = Dropable::new(i+100); - m.insert(d1, d2); - } - - let v = drop_vector.get().unwrap(); - for i in range(0u, 200) { - assert_eq!(v.borrow().as_slice()[i], 1); - } - drop(v); - - for i in range(0u, 50) { - let k = Dropable::new(i); - let v = m.pop(&k); - - assert!(v.is_some()); - - let v = drop_vector.get().unwrap(); - assert_eq!(v.borrow().as_slice()[i], 1); - assert_eq!(v.borrow().as_slice()[i+100], 1); - } - - let v = drop_vector.get().unwrap(); - for i in range(0u, 50) { - assert_eq!(v.borrow().as_slice()[i], 0); - assert_eq!(v.borrow().as_slice()[i+100], 0); - } - - for i in range(50u, 100) { - assert_eq!(v.borrow().as_slice()[i], 1); - assert_eq!(v.borrow().as_slice()[i+100], 1); - } - } - - let v = drop_vector.get().unwrap(); - for i in range(0u, 200) { - assert_eq!(v.borrow().as_slice()[i], 0); - } - } - - #[test] - fn test_move_iter_drops() { - drop_vector.replace(Some(RefCell::new(Vec::from_elem(200, 0i)))); - - let hm = { - let mut hm = HashMap::new(); - - let v = drop_vector.get().unwrap(); - for i in range(0u, 200) { - assert_eq!(v.borrow().as_slice()[i], 0); - } - drop(v); - - for i in range(0u, 100) { - let d1 = Dropable::new(i); - let d2 = Dropable::new(i+100); - hm.insert(d1, d2); - } - - let v = drop_vector.get().unwrap(); - for i in range(0u, 200) { - assert_eq!(v.borrow().as_slice()[i], 1); - } - drop(v); - - hm - }; - - // By the way, ensure that cloning doesn't screw up the dropping. - drop(hm.clone()); - - { - let mut half = hm.into_iter().take(50); - - let v = drop_vector.get().unwrap(); - for i in range(0u, 200) { - assert_eq!(v.borrow().as_slice()[i], 1); - } - drop(v); - - for _ in half {} - - let v = drop_vector.get().unwrap(); - let nk = range(0u, 100).filter(|&i| { - v.borrow().as_slice()[i] == 1 - }).count(); - - let nv = range(0u, 100).filter(|&i| { - v.borrow().as_slice()[i+100] == 1 - }).count(); - - assert_eq!(nk, 50); - assert_eq!(nv, 50); - }; - - let v = drop_vector.get().unwrap(); - for i in range(0u, 200) { - assert_eq!(v.borrow().as_slice()[i], 0); - } - } - - #[test] - fn test_empty_pop() { - let mut m: HashMap = HashMap::new(); - assert_eq!(m.pop(&0), None); - } - - #[test] - fn test_lots_of_insertions() { - let mut m = HashMap::new(); - - // Try this a few times to make sure we never screw up the hashmap's - // internal state. - for _ in range(0i, 10) { - assert!(m.is_empty()); - - for i in range_inclusive(1i, 1000) { - assert!(m.insert(i, i)); - - for j in range_inclusive(1, i) { - let r = m.find(&j); - assert_eq!(r, Some(&j)); - } - - for j in range_inclusive(i+1, 1000) { - let r = m.find(&j); - assert_eq!(r, None); - } - } - - for i in range_inclusive(1001i, 2000) { - assert!(!m.contains_key(&i)); - } - - // remove forwards - for i in range_inclusive(1i, 1000) { - assert!(m.remove(&i)); - - for j in range_inclusive(1, i) { - assert!(!m.contains_key(&j)); - } - - for j in range_inclusive(i+1, 1000) { - assert!(m.contains_key(&j)); - } - } - - for i in range_inclusive(1i, 1000) { - assert!(!m.contains_key(&i)); - } - - for i in range_inclusive(1i, 1000) { - assert!(m.insert(i, i)); - } - - // remove backwards - for i in range_step_inclusive(1000i, 1, -1) { - assert!(m.remove(&i)); - - for j in range_inclusive(i, 1000) { - assert!(!m.contains_key(&j)); - } - - for j in range_inclusive(1, i-1) { - assert!(m.contains_key(&j)); - } - } - } - } - - #[test] - fn test_find_mut() { - let mut m = HashMap::new(); - assert!(m.insert(1i, 12i)); - assert!(m.insert(2i, 8i)); - assert!(m.insert(5i, 14i)); - let new = 100; - match m.find_mut(&5) { - None => panic!(), Some(x) => *x = new - } - assert_eq!(m.find(&5), Some(&new)); - } - - #[test] - fn test_insert_overwrite() { - let mut m = HashMap::new(); - assert!(m.insert(1i, 2i)); - assert_eq!(*m.find(&1).unwrap(), 2); - assert!(!m.insert(1i, 3i)); - assert_eq!(*m.find(&1).unwrap(), 3); - } - - #[test] - fn test_insert_conflicts() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1i, 2i)); - assert!(m.insert(5i, 3i)); - assert!(m.insert(9i, 4i)); - assert_eq!(*m.find(&9).unwrap(), 4); - assert_eq!(*m.find(&5).unwrap(), 3); - assert_eq!(*m.find(&1).unwrap(), 2); - } - - #[test] - fn test_conflict_remove() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1i, 2i)); - assert_eq!(*m.find(&1).unwrap(), 2); - assert!(m.insert(5, 3)); - assert_eq!(*m.find(&1).unwrap(), 2); - assert_eq!(*m.find(&5).unwrap(), 3); - assert!(m.insert(9, 4)); - assert_eq!(*m.find(&1).unwrap(), 2); - assert_eq!(*m.find(&5).unwrap(), 3); - assert_eq!(*m.find(&9).unwrap(), 4); - assert!(m.remove(&1)); - assert_eq!(*m.find(&9).unwrap(), 4); - assert_eq!(*m.find(&5).unwrap(), 3); - } - - #[test] - fn test_is_empty() { - let mut m = HashMap::with_capacity(4); - assert!(m.insert(1i, 2i)); - assert!(!m.is_empty()); - assert!(m.remove(&1)); - assert!(m.is_empty()); - } - - #[test] - fn test_pop() { - let mut m = HashMap::new(); - m.insert(1i, 2i); - assert_eq!(m.pop(&1), Some(2)); - assert_eq!(m.pop(&1), None); - } - - #[test] - #[allow(experimental)] - fn test_pop_equiv() { - let mut m = HashMap::new(); - m.insert(1i, 2i); - assert_eq!(m.pop_equiv(&KindaIntLike(1)), Some(2)); - assert_eq!(m.pop_equiv(&KindaIntLike(1)), None); - } - - #[test] - fn test_swap() { - let mut m = HashMap::new(); - assert_eq!(m.swap(1i, 2i), None); - assert_eq!(m.swap(1i, 3i), Some(2)); - assert_eq!(m.swap(1i, 4i), Some(3)); - } - - #[test] - fn test_iterate() { - let mut m = HashMap::with_capacity(4); - for i in range(0u, 32) { - assert!(m.insert(i, i*2)); - } - assert_eq!(m.len(), 32); - - let mut observed: u32 = 0; - - for (k, v) in m.iter() { - assert_eq!(*v, *k * 2); - observed |= 1 << *k; - } - assert_eq!(observed, 0xFFFF_FFFF); - } - - #[test] - fn test_keys() { - let vec = vec![(1i, 'a'), (2i, 'b'), (3i, 'c')]; - let map = vec.into_iter().collect::>(); - let keys = map.keys().map(|&k| k).collect::>(); - assert_eq!(keys.len(), 3); - assert!(keys.contains(&1)); - assert!(keys.contains(&2)); - assert!(keys.contains(&3)); - } - - #[test] - fn test_values() { - let vec = vec![(1i, 'a'), (2i, 'b'), (3i, 'c')]; - let map = vec.into_iter().collect::>(); - let values = map.values().map(|&v| v).collect::>(); - assert_eq!(values.len(), 3); - assert!(values.contains(&'a')); - assert!(values.contains(&'b')); - assert!(values.contains(&'c')); - } - - #[test] - fn test_find() { - let mut m = HashMap::new(); - assert!(m.find(&1i).is_none()); - m.insert(1i, 2i); - match m.find(&1) { - None => panic!(), - Some(v) => assert_eq!(*v, 2) - } - } - - #[test] - fn test_find_copy() { - let mut m = HashMap::new(); - assert!(m.find(&1i).is_none()); - - for i in range(1i, 10000) { - m.insert(i, i + 7); - match m.find_copy(&i) { - None => panic!(), - Some(v) => assert_eq!(v, i + 7) - } - for j in range(1i, i/100) { - match m.find_copy(&j) { - None => panic!(), - Some(v) => assert_eq!(v, j + 7) - } - } - } - } - - #[test] - fn test_eq() { - let mut m1 = HashMap::new(); - m1.insert(1i, 2i); - m1.insert(2i, 3i); - m1.insert(3i, 4i); - - let mut m2 = HashMap::new(); - m2.insert(1i, 2i); - m2.insert(2i, 3i); - - assert!(m1 != m2); - - m2.insert(3i, 4i); - - assert_eq!(m1, m2); - } - - #[test] - fn test_show() { - let mut map: HashMap = HashMap::new(); - let empty: HashMap = HashMap::new(); - - map.insert(1i, 2i); - map.insert(3i, 4i); - - let map_str = format!("{}", map); - - assert!(map_str == "{1: 2, 3: 4}".to_string() || map_str == "{3: 4, 1: 2}".to_string()); - assert_eq!(format!("{}", empty), "{}".to_string()); - } - - #[test] - fn test_expand() { - let mut m = HashMap::new(); - - assert_eq!(m.len(), 0); - assert!(m.is_empty()); - - let mut i = 0u; - let old_cap = m.table.capacity(); - while old_cap == m.table.capacity() { - m.insert(i, i); - i += 1; - } - - assert_eq!(m.len(), i); - assert!(!m.is_empty()); - } - - #[test] - fn test_resize_policy() { - let mut m = HashMap::new(); - - assert_eq!(m.len(), 0); - assert_eq!(m.table.capacity(), 0); - assert!(m.is_empty()); - - m.insert(0, 0); - m.remove(&0); - assert!(m.is_empty()); - let initial_cap = m.table.capacity(); - m.reserve(initial_cap * 2); - let cap = m.table.capacity(); - - assert_eq!(cap, initial_cap * 2); - - let mut i = 0u; - for _ in range(0, cap * 3 / 4) { - m.insert(i, i); - i += 1; - } - // three quarters full - - assert_eq!(m.len(), i); - assert_eq!(m.table.capacity(), cap); - - for _ in range(0, cap / 4) { - m.insert(i, i); - i += 1; - } - // half full - - let new_cap = m.table.capacity(); - assert_eq!(new_cap, cap * 2); - - for _ in range(0, cap / 2 - 1) { - i -= 1; - m.remove(&i); - assert_eq!(m.table.capacity(), new_cap); - } - // A little more than one quarter full. - // Shrinking starts as we remove more elements: - for _ in range(0, cap / 2 - 1) { - i -= 1; - m.remove(&i); - } - - assert_eq!(m.len(), i); - assert!(!m.is_empty()); - assert_eq!(m.table.capacity(), cap); - } - - #[test] - fn test_find_equiv() { - let mut m = HashMap::new(); - - let (foo, bar, baz) = (1i,2i,3i); - m.insert("foo".to_string(), foo); - m.insert("bar".to_string(), bar); - m.insert("baz".to_string(), baz); - - - assert_eq!(m.find_equiv("foo"), Some(&foo)); - assert_eq!(m.find_equiv("bar"), Some(&bar)); - assert_eq!(m.find_equiv("baz"), Some(&baz)); - - assert_eq!(m.find_equiv("qux"), None); - } - - #[test] - fn test_from_iter() { - let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap = xs.iter().map(|&x| x).collect(); - - for &(k, v) in xs.iter() { - assert_eq!(map.find(&k), Some(&v)); - } - } - - #[test] - fn test_size_hint() { - let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let map: HashMap = xs.iter().map(|&x| x).collect(); - - let mut iter = map.iter(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.size_hint(), (3, Some(3))); - } - - #[test] - fn test_mut_size_hint() { - let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)]; - - let mut map: HashMap = xs.iter().map(|&x| x).collect(); - - let mut iter = map.iter_mut(); - - for _ in iter.by_ref().take(3) {} - - assert_eq!(iter.size_hint(), (3, Some(3))); - } - - #[test] - fn test_index() { - let mut map: HashMap = HashMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - assert_eq!(map[2], 1); - } - - #[test] - #[should_fail] - fn test_index_nonexistent() { - let mut map: HashMap = HashMap::new(); - - map.insert(1, 2); - map.insert(2, 1); - map.insert(3, 4); - - map[4]; - } - - #[test] - fn test_entry(){ - let xs = [(1i, 10i), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: HashMap = xs.iter().map(|&x| x).collect(); - - // Existing key (insert) - match map.entry(1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.set(100), 10); - } - } - assert_eq!(map.find(&1).unwrap(), &100); - assert_eq!(map.len(), 6); - - - // Existing key (update) - match map.entry(2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - let new_v = (*v) * 10; - *v = new_v; - } - } - assert_eq!(map.find(&2).unwrap(), &200); - assert_eq!(map.len(), 6); - - // Existing key (take) - match map.entry(3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.take(), 30); - } - } - assert_eq!(map.find(&3), None); - assert_eq!(map.len(), 5); - - - // Inexistent key (insert) - match map.entry(10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(*view.set(1000), 1000); - } - } - assert_eq!(map.find(&10).unwrap(), &1000); - assert_eq!(map.len(), 6); - } -} diff --git a/src/libstd/collections/hashmap/mod.rs b/src/libstd/collections/hashmap/mod.rs deleted file mode 100644 index 6508d4609f1..00000000000 --- a/src/libstd/collections/hashmap/mod.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Unordered containers, implemented as hash-tables - -pub use self::map::HashMap; -pub use self::map::Entries; -pub use self::map::MutEntries; -pub use self::map::MoveEntries; -pub use self::map::Entry; -pub use self::map::Occupied; -pub use self::map::Vacant; -pub use self::map::OccupiedEntry; -pub use self::map::VacantEntry; -pub use self::map::Keys; -pub use self::map::Values; -pub use self::map::INITIAL_CAPACITY; -pub use self::set::HashSet; -pub use self::set::SetItems; -pub use self::set::SetMoveItems; -pub use self::set::SetAlgebraItems; - -mod bench; -mod map; -mod set; -mod table; diff --git a/src/libstd/collections/hashmap/set.rs b/src/libstd/collections/hashmap/set.rs deleted file mode 100644 index 69f3812425f..00000000000 --- a/src/libstd/collections/hashmap/set.rs +++ /dev/null @@ -1,834 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// ignore-lexer-test FIXME #15883 - -use clone::Clone; -use cmp::{Eq, Equiv, PartialEq}; -use core::kinds::Sized; -use default::Default; -use fmt::Show; -use fmt; -use hash::{Hash, Hasher, RandomSipHasher}; -use iter::{Iterator, FromIterator, FilterMap, Chain, Repeat, Zip, Extendable}; -use iter; -use option::{Some, None}; -use result::{Ok, Err}; - -use super::{HashMap, Entries, MoveEntries, INITIAL_CAPACITY}; - - -// Future Optimization (FIXME!) -// ============================= -// -// Iteration over zero sized values is a noop. There is no need -// for `bucket.val` in the case of HashSet. I suppose we would need HKT -// to get rid of it properly. - -/// An implementation of a hash set using the underlying representation of a -/// HashMap where the value is (). As with the `HashMap` type, a `HashSet` -/// requires that the elements implement the `Eq` and `Hash` traits. -/// -/// # Example -/// -/// ``` -/// use std::collections::HashSet; -/// // Type inference lets us omit an explicit type signature (which -/// // would be `HashSet<&str>` in this example). -/// let mut books = HashSet::new(); -/// -/// // Add some books. -/// books.insert("A Dance With Dragons"); -/// books.insert("To Kill a Mockingbird"); -/// books.insert("The Odyssey"); -/// books.insert("The Great Gatsby"); -/// -/// // Check for a specific one. -/// if !books.contains(&("The Winds of Winter")) { -/// println!("We have {} books, but The Winds of Winter ain't one.", -/// books.len()); -/// } -/// -/// // Remove a book. -/// books.remove(&"The Odyssey"); -/// -/// // Iterate over everything. -/// for book in books.iter() { -/// println!("{}", *book); -/// } -/// ``` -/// -/// The easiest way to use `HashSet` with a custom type is to derive -/// `Eq` and `Hash`. We must also derive `PartialEq`, this will in the -/// future be implied by `Eq`. -/// -/// ``` -/// use std::collections::HashSet; -/// #[deriving(Hash, Eq, PartialEq, Show)] -/// struct Viking<'a> { -/// name: &'a str, -/// power: uint, -/// } -/// -/// let mut vikings = HashSet::new(); -/// -/// vikings.insert(Viking { name: "Einar", power: 9u }); -/// vikings.insert(Viking { name: "Einar", power: 9u }); -/// vikings.insert(Viking { name: "Olaf", power: 4u }); -/// vikings.insert(Viking { name: "Harald", power: 8u }); -/// -/// // Use derived implementation to print the vikings. -/// for x in vikings.iter() { -/// println!("{}", x); -/// } -/// ``` -#[deriving(Clone)] -pub struct HashSet { - map: HashMap -} - -impl HashSet { - /// Create an empty HashSet. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set: HashSet = HashSet::new(); - /// ``` - #[inline] - pub fn new() -> HashSet { - HashSet::with_capacity(INITIAL_CAPACITY) - } - - /// Create an empty HashSet with space for at least `n` elements in - /// the hash table. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set: HashSet = HashSet::with_capacity(10); - /// ``` - #[inline] - pub fn with_capacity(capacity: uint) -> HashSet { - HashSet { map: HashMap::with_capacity(capacity) } - } -} - -impl, S, H: Hasher> HashSet { - /// Creates a new empty hash set which will use the given hasher to hash - /// keys. - /// - /// The hash set is also created with the default initial capacity. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// use std::hash::sip::SipHasher; - /// - /// let h = SipHasher::new(); - /// let mut set = HashSet::with_hasher(h); - /// set.insert(2u); - /// ``` - #[inline] - pub fn with_hasher(hasher: H) -> HashSet { - HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher) - } - - /// Create an empty HashSet with space for at least `capacity` - /// elements in the hash table, using `hasher` to hash the keys. - /// - /// Warning: `hasher` is normally randomly generated, and - /// is designed to allow `HashSet`s to be resistant to attacks that - /// cause many collisions and very poor performance. Setting it - /// manually using this function can expose a DoS attack vector. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// use std::hash::sip::SipHasher; - /// - /// let h = SipHasher::new(); - /// let mut set = HashSet::with_capacity_and_hasher(10u, h); - /// set.insert(1i); - /// ``` - #[inline] - pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet { - HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) } - } - - /// Reserve space for at least `n` elements in the hash table. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set: HashSet = HashSet::new(); - /// set.reserve(10); - /// ``` - pub fn reserve(&mut self, n: uint) { - self.map.reserve(n) - } - - /// Returns true if the hash set contains a value equivalent to the - /// given query value. - /// - /// # Example - /// - /// This is a slightly silly example where we define the number's - /// parity as the equivalance class. It is important that the - /// values hash the same, which is why we implement `Hash`. - /// - /// ``` - /// use std::collections::HashSet; - /// use std::hash::Hash; - /// use std::hash::sip::SipState; - /// - /// #[deriving(Eq, PartialEq)] - /// struct EvenOrOdd { - /// num: uint - /// }; - /// - /// impl Hash for EvenOrOdd { - /// fn hash(&self, state: &mut SipState) { - /// let parity = self.num % 2; - /// parity.hash(state); - /// } - /// } - /// - /// impl Equiv for EvenOrOdd { - /// fn equiv(&self, other: &EvenOrOdd) -> bool { - /// self.num % 2 == other.num % 2 - /// } - /// } - /// - /// let mut set = HashSet::new(); - /// set.insert(EvenOrOdd { num: 3u }); - /// - /// assert!(set.contains_equiv(&EvenOrOdd { num: 3u })); - /// assert!(set.contains_equiv(&EvenOrOdd { num: 5u })); - /// assert!(!set.contains_equiv(&EvenOrOdd { num: 4u })); - /// assert!(!set.contains_equiv(&EvenOrOdd { num: 2u })); - /// - /// ``` - pub fn contains_equiv + Equiv>(&self, value: &Q) -> bool { - self.map.contains_key_equiv(value) - } - - /// An iterator visiting all elements in arbitrary order. - /// Iterator element type is &'a T. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a"); - /// set.insert("b"); - /// - /// // Will print in an arbitrary order. - /// for x in set.iter() { - /// println!("{}", x); - /// } - /// ``` - pub fn iter<'a>(&'a self) -> SetItems<'a, T> { - self.map.keys() - } - - /// Deprecated: use `into_iter`. - #[deprecated = "use into_iter"] - pub fn move_iter(self) -> SetMoveItems { - self.into_iter() - } - - /// Creates a consuming iterator, that is, one that moves each value out - /// of the set in arbitrary order. The set cannot be used after calling - /// this. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let mut set = HashSet::new(); - /// set.insert("a".to_string()); - /// set.insert("b".to_string()); - /// - /// // Not possible to collect to a Vec with a regular `.iter()`. - /// let v: Vec = set.into_iter().collect(); - /// - /// // Will print in an arbitrary order. - /// for x in v.iter() { - /// println!("{}", x); - /// } - /// ``` - pub fn into_iter(self) -> SetMoveItems { - self.map.into_iter().map(|(k, _)| k) - } - - /// Visit the values representing the difference. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); - /// - /// // Can be seen as `a - b`. - /// for x in a.difference(&b) { - /// println!("{}", x); // Print 1 - /// } - /// - /// let diff: HashSet = a.difference(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1i].iter().map(|&x| x).collect()); - /// - /// // Note that difference is not symmetric, - /// // and `b - a` means something else: - /// let diff: HashSet = b.difference(&a).map(|&x| x).collect(); - /// assert_eq!(diff, [4i].iter().map(|&x| x).collect()); - /// ``` - pub fn difference<'a>(&'a self, other: &'a HashSet) -> SetAlgebraItems<'a, T, H> { - Repeat::new(other).zip(self.iter()) - .filter_map(|(other, elt)| { - if !other.contains(elt) { Some(elt) } else { None } - }) - } - - /// Visit the values representing the symmetric difference. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); - /// - /// // Print 1, 4 in arbitrary order. - /// for x in a.symmetric_difference(&b) { - /// println!("{}", x); - /// } - /// - /// let diff1: HashSet = a.symmetric_difference(&b).map(|&x| x).collect(); - /// let diff2: HashSet = b.symmetric_difference(&a).map(|&x| x).collect(); - /// - /// assert_eq!(diff1, diff2); - /// assert_eq!(diff1, [1i, 4].iter().map(|&x| x).collect()); - /// ``` - pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet) - -> Chain, SetAlgebraItems<'a, T, H>> { - self.difference(other).chain(other.difference(self)) - } - - /// Visit the values representing the intersection. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); - /// - /// // Print 2, 3 in arbitrary order. - /// for x in a.intersection(&b) { - /// println!("{}", x); - /// } - /// - /// let diff: HashSet = a.intersection(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect()); - /// ``` - pub fn intersection<'a>(&'a self, other: &'a HashSet) - -> SetAlgebraItems<'a, T, H> { - Repeat::new(other).zip(self.iter()) - .filter_map(|(other, elt)| { - if other.contains(elt) { Some(elt) } else { None } - }) - } - - /// Visit the values representing the union. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// let a: HashSet = [1i, 2, 3].iter().map(|&x| x).collect(); - /// let b: HashSet = [4i, 2, 3, 4].iter().map(|&x| x).collect(); - /// - /// // Print 1, 2, 3, 4 in arbitrary order. - /// for x in a.union(&b) { - /// println!("{}", x); - /// } - /// - /// let diff: HashSet = a.union(&b).map(|&x| x).collect(); - /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect()); - /// ``` - pub fn union<'a>(&'a self, other: &'a HashSet) - -> Chain, SetAlgebraItems<'a, T, H>> { - self.iter().chain(other.difference(self)) - } - - /// Return the number of elements in the set - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut v = HashSet::new(); - /// assert_eq!(v.len(), 0); - /// v.insert(1u); - /// assert_eq!(v.len(), 1); - /// ``` - pub fn len(&self) -> uint { self.map.len() } - - /// Returns true if the set contains no elements - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut v = HashSet::new(); - /// assert!(v.is_empty()); - /// v.insert(1u); - /// assert!(!v.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { self.map.len() == 0 } - - /// Clears the set, removing all values. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut v = HashSet::new(); - /// v.insert(1u); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - pub fn clear(&mut self) { self.map.clear() } - - /// Returns `true` if the set contains a value. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let set: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// assert_eq!(set.contains(&1), true); - /// assert_eq!(set.contains(&4), false); - /// ``` - pub fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } - - /// Returns `true` if the set has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let mut b: HashSet = HashSet::new(); - /// - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(4); - /// assert_eq!(a.is_disjoint(&b), true); - /// b.insert(1); - /// assert_eq!(a.is_disjoint(&b), false); - /// ``` - pub fn is_disjoint(&self, other: &HashSet) -> bool { - self.iter().all(|v| !other.contains(v)) - } - - /// Returns `true` if the set is a subset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let sup: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); - /// let mut set: HashSet = HashSet::new(); - /// - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(2); - /// assert_eq!(set.is_subset(&sup), true); - /// set.insert(4); - /// assert_eq!(set.is_subset(&sup), false); - /// ``` - pub fn is_subset(&self, other: &HashSet) -> bool { - self.iter().all(|v| other.contains(v)) - } - - /// Returns `true` if the set is a superset of another. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let sub: HashSet = [1, 2].iter().map(|&x| x).collect(); - /// let mut set: HashSet = HashSet::new(); - /// - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(0); - /// set.insert(1); - /// assert_eq!(set.is_superset(&sub), false); - /// - /// set.insert(2); - /// assert_eq!(set.is_superset(&sub), true); - /// ``` - #[inline] - pub fn is_superset(&self, other: &HashSet) -> bool { - other.is_subset(self) - } - - /// Adds a value to the set. Returns `true` if the value was not already - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut set = HashSet::new(); - /// - /// assert_eq!(set.insert(2u), true); - /// assert_eq!(set.insert(2), false); - /// assert_eq!(set.len(), 1); - /// ``` - pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) } - - /// Removes a value from the set. Returns `true` if the value was - /// present in the set. - /// - /// # Example - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let mut set = HashSet::new(); - /// - /// set.insert(2u); - /// assert_eq!(set.remove(&2), true); - /// assert_eq!(set.remove(&2), false); - /// ``` - pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value) } -} - -impl, S, H: Hasher> PartialEq for HashSet { - fn eq(&self, other: &HashSet) -> bool { - if self.len() != other.len() { return false; } - - self.iter().all(|key| other.contains(key)) - } -} - -impl, S, H: Hasher> Eq for HashSet {} - -impl + fmt::Show, S, H: Hasher> fmt::Show for HashSet { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); - - for (i, x) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{}", *x)); - } - - write!(f, "}}") - } -} - -impl, S, H: Hasher + Default> FromIterator for HashSet { - fn from_iter>(iter: I) -> HashSet { - let (lower, _) = iter.size_hint(); - let mut set = HashSet::with_capacity_and_hasher(lower, Default::default()); - set.extend(iter); - set - } -} - -impl, S, H: Hasher + Default> Extendable for HashSet { - fn extend>(&mut self, mut iter: I) { - for k in iter { - self.insert(k); - } - } -} - -impl, S, H: Hasher + Default> Default for HashSet { - fn default() -> HashSet { - HashSet::with_hasher(Default::default()) - } -} - -/// HashSet iterator -pub type SetItems<'a, K> = - iter::Map<'static, (&'a K, &'a ()), &'a K, Entries<'a, K, ()>>; - -/// HashSet move iterator -pub type SetMoveItems = - iter::Map<'static, (K, ()), K, MoveEntries>; - -// `Repeat` is used to feed the filter closure an explicit capture -// of a reference to the other set -/// Set operations iterator -pub type SetAlgebraItems<'a, T, H> = - FilterMap<'static, (&'a HashSet, &'a T), &'a T, - Zip>, SetItems<'a, T>>>; - -#[cfg(test)] -mod test_set { - use prelude::*; - - use super::HashSet; - use slice::ImmutablePartialEqSlice; - - #[test] - fn test_disjoint() { - let mut xs = HashSet::new(); - let mut ys = HashSet::new(); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(5i)); - assert!(ys.insert(11i)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(xs.insert(7)); - assert!(xs.insert(19)); - assert!(xs.insert(4)); - assert!(ys.insert(2)); - assert!(ys.insert(-11)); - assert!(xs.is_disjoint(&ys)); - assert!(ys.is_disjoint(&xs)); - assert!(ys.insert(7)); - assert!(!xs.is_disjoint(&ys)); - assert!(!ys.is_disjoint(&xs)); - } - - #[test] - fn test_subset_and_superset() { - let mut a = HashSet::new(); - assert!(a.insert(0i)); - assert!(a.insert(5)); - assert!(a.insert(11)); - assert!(a.insert(7)); - - let mut b = HashSet::new(); - assert!(b.insert(0i)); - assert!(b.insert(7)); - assert!(b.insert(19)); - assert!(b.insert(250)); - assert!(b.insert(11)); - assert!(b.insert(200)); - - assert!(!a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(!b.is_superset(&a)); - - assert!(b.insert(5)); - - assert!(a.is_subset(&b)); - assert!(!a.is_superset(&b)); - assert!(!b.is_subset(&a)); - assert!(b.is_superset(&a)); - } - - #[test] - fn test_iterate() { - let mut a = HashSet::new(); - for i in range(0u, 32) { - assert!(a.insert(i)); - } - let mut observed: u32 = 0; - for k in a.iter() { - observed |= 1 << *k; - } - assert_eq!(observed, 0xFFFF_FFFF); - } - - #[test] - fn test_intersection() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(11i)); - assert!(a.insert(1)); - assert!(a.insert(3)); - assert!(a.insert(77)); - assert!(a.insert(103)); - assert!(a.insert(5)); - assert!(a.insert(-5)); - - assert!(b.insert(2i)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(-9)); - assert!(b.insert(-42)); - assert!(b.insert(5)); - assert!(b.insert(3)); - - let mut i = 0; - let expected = [3, 5, 11, 77]; - for x in a.intersection(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1i)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(3i)); - assert!(b.insert(9)); - - let mut i = 0; - let expected = [1, 5, 11]; - for x in a.difference(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_symmetric_difference() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1i)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - - assert!(b.insert(-2i)); - assert!(b.insert(3)); - assert!(b.insert(9)); - assert!(b.insert(14)); - assert!(b.insert(22)); - - let mut i = 0; - let expected = [-2, 1, 5, 11, 14, 22]; - for x in a.symmetric_difference(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_union() { - let mut a = HashSet::new(); - let mut b = HashSet::new(); - - assert!(a.insert(1i)); - assert!(a.insert(3)); - assert!(a.insert(5)); - assert!(a.insert(9)); - assert!(a.insert(11)); - assert!(a.insert(16)); - assert!(a.insert(19)); - assert!(a.insert(24)); - - assert!(b.insert(-2i)); - assert!(b.insert(1)); - assert!(b.insert(5)); - assert!(b.insert(9)); - assert!(b.insert(13)); - assert!(b.insert(19)); - - let mut i = 0; - let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; - for x in a.union(&b) { - assert!(expected.contains(x)); - i += 1 - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_from_iter() { - let xs = [1i, 2, 3, 4, 5, 6, 7, 8, 9]; - - let set: HashSet = xs.iter().map(|&x| x).collect(); - - for x in xs.iter() { - assert!(set.contains(x)); - } - } - - #[test] - fn test_move_iter() { - let hs = { - let mut hs = HashSet::new(); - - hs.insert('a'); - hs.insert('b'); - - hs - }; - - let v = hs.into_iter().collect::>(); - assert!(['a', 'b'] == v.as_slice() || ['b', 'a'] == v.as_slice()); - } - - #[test] - fn test_eq() { - // These constants once happened to expose a bug in insert(). - // I'm keeping them around to prevent a regression. - let mut s1 = HashSet::new(); - - s1.insert(1i); - s1.insert(2); - s1.insert(3); - - let mut s2 = HashSet::new(); - - s2.insert(1i); - s2.insert(2); - - assert!(s1 != s2); - - s2.insert(3); - - assert_eq!(s1, s2); - } - - #[test] - fn test_show() { - let mut set: HashSet = HashSet::new(); - let empty: HashSet = HashSet::new(); - - set.insert(1i); - set.insert(2); - - let set_str = format!("{}", set); - - assert!(set_str == "{1, 2}".to_string() || set_str == "{2, 1}".to_string()); - assert_eq!(format!("{}", empty), "{}".to_string()); - } -} diff --git a/src/libstd/collections/hashmap/table.rs b/src/libstd/collections/hashmap/table.rs deleted file mode 100644 index 4d73029b7b0..00000000000 --- a/src/libstd/collections/hashmap/table.rs +++ /dev/null @@ -1,907 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// ignore-lexer-test FIXME #15883 - -use clone::Clone; -use cmp; -use hash::{Hash, Hasher}; -use iter::{Iterator, count}; -use kinds::{Sized, marker}; -use mem::{min_align_of, size_of}; -use mem; -use num::{CheckedAdd, CheckedMul, is_power_of_two}; -use ops::{Deref, DerefMut, Drop}; -use option::{Some, None, Option}; -use ptr::{RawPtr, copy_nonoverlapping_memory, zero_memory}; -use ptr; -use rt::heap::{allocate, deallocate}; - -const EMPTY_BUCKET: u64 = 0u64; - -/// The raw hashtable, providing safe-ish access to the unzipped and highly -/// optimized arrays of hashes, keys, and values. -/// -/// This design uses less memory and is a lot faster than the naive -/// `Vec>`, because we don't pay for the overhead of an -/// option on every element, and we get a generally more cache-aware design. -/// -/// Essential invariants of this structure: -/// -/// - if t.hashes[i] == EMPTY_BUCKET, then `Bucket::at_index(&t, i).raw` -/// points to 'undefined' contents. Don't read from it. This invariant is -/// enforced outside this module with the `EmptyBucket`, `FullBucket`, -/// and `SafeHash` types. -/// -/// - An `EmptyBucket` is only constructed at an index with -/// a hash of EMPTY_BUCKET. -/// -/// - A `FullBucket` is only constructed at an index with a -/// non-EMPTY_BUCKET hash. -/// -/// - A `SafeHash` is only constructed for non-`EMPTY_BUCKET` hash. We get -/// around hashes of zero by changing them to 0x8000_0000_0000_0000, -/// which will likely map to the same bucket, while not being confused -/// with "empty". -/// -/// - All three "arrays represented by pointers" are the same length: -/// `capacity`. This is set at creation and never changes. The arrays -/// are unzipped to save space (we don't have to pay for the padding -/// between odd sized elements, such as in a map from u64 to u8), and -/// be more cache aware (scanning through 8 hashes brings in at most -/// 2 cache lines, since they're all right beside each other). -/// -/// You can kind of think of this module/data structure as a safe wrapper -/// around just the "table" part of the hashtable. It enforces some -/// invariants at the type level and employs some performance trickery, -/// but in general is just a tricked out `Vec>`. -#[unsafe_no_drop_flag] -pub struct RawTable { - capacity: uint, - size: uint, - hashes: *mut u64, - // Because K/V do not appear directly in any of the types in the struct, - // inform rustc that in fact instances of K and V are reachable from here. - marker: marker::CovariantType<(K,V)>, -} - -struct RawBucket { - hash: *mut u64, - key: *mut K, - val: *mut V -} - -pub struct Bucket { - raw: RawBucket, - idx: uint, - table: M -} - -pub struct EmptyBucket { - raw: RawBucket, - idx: uint, - table: M -} - -pub struct FullBucket { - raw: RawBucket, - idx: uint, - table: M -} - -pub type EmptyBucketImm<'table, K, V> = EmptyBucket>; -pub type FullBucketImm<'table, K, V> = FullBucket>; - -pub type EmptyBucketMut<'table, K, V> = EmptyBucket>; -pub type FullBucketMut<'table, K, V> = FullBucket>; - -pub enum BucketState { - Empty(EmptyBucket), - Full(FullBucket), -} - -// A GapThenFull encapsulates the state of two consecutive buckets at once. -// The first bucket, called the gap, is known to be empty. -// The second bucket is full. -struct GapThenFull { - gap: EmptyBucket, - full: FullBucket, -} - -/// A hash that is not zero, since we use a hash of zero to represent empty -/// buckets. -#[deriving(PartialEq)] -pub struct SafeHash { - hash: u64, -} - -impl SafeHash { - /// Peek at the hash value, which is guaranteed to be non-zero. - #[inline(always)] - pub fn inspect(&self) -> u64 { self.hash } -} - -/// We need to remove hashes of 0. That's reserved for empty buckets. -/// This function wraps up `hash_keyed` to be the only way outside this -/// module to generate a SafeHash. -pub fn make_hash, S, H: Hasher>(hasher: &H, t: &T) -> SafeHash { - match hasher.hash(t) { - // This constant is exceedingly likely to hash to the same - // bucket, but it won't be counted as empty! Just so we can maintain - // our precious uniform distribution of initial indexes. - EMPTY_BUCKET => SafeHash { hash: 0x8000_0000_0000_0000 }, - h => SafeHash { hash: h }, - } -} - -// `replace` casts a `*u64` to a `*SafeHash`. Since we statically -// ensure that a `FullBucket` points to an index with a non-zero hash, -// and a `SafeHash` is just a `u64` with a different name, this is -// safe. -// -// This test ensures that a `SafeHash` really IS the same size as a -// `u64`. If you need to change the size of `SafeHash` (and -// consequently made this test fail), `replace` needs to be -// modified to no longer assume this. -#[test] -fn can_alias_safehash_as_u64() { - assert_eq!(size_of::(), size_of::()) -} - -impl RawBucket { - unsafe fn offset(self, count: int) -> RawBucket { - RawBucket { - hash: self.hash.offset(count), - key: self.key.offset(count), - val: self.val.offset(count), - } - } -} - -// For parameterizing over mutability. -impl<'t, K, V> Deref> for &'t RawTable { - fn deref(&self) -> &RawTable { - &**self - } -} - -impl<'t, K, V> Deref> for &'t mut RawTable { - fn deref(&self) -> &RawTable { - &**self - } -} - -impl<'t, K, V> DerefMut> for &'t mut RawTable { - fn deref_mut(&mut self) -> &mut RawTable { - &mut **self - } -} - -// Buckets hold references to the table. -impl FullBucket { - /// Borrow a reference to the table. - pub fn table(&self) -> &M { - &self.table - } - /// Move out the reference to the table. - pub fn into_table(self) -> M { - self.table - } - /// Get the raw index. - pub fn index(&self) -> uint { - self.idx - } -} - -impl EmptyBucket { - /// Borrow a reference to the table. - pub fn table(&self) -> &M { - &self.table - } - /// Move out the reference to the table. - pub fn into_table(self) -> M { - self.table - } -} - -impl Bucket { - /// Move out the reference to the table. - pub fn into_table(self) -> M { - self.table - } - /// Get the raw index. - pub fn index(&self) -> uint { - self.idx - } -} - -impl>> Bucket { - pub fn new(table: M, hash: &SafeHash) -> Bucket { - Bucket::at_index(table, hash.inspect() as uint) - } - - pub fn at_index(table: M, ib_index: uint) -> Bucket { - let ib_index = ib_index & (table.capacity() - 1); - Bucket { - raw: unsafe { - table.first_bucket_raw().offset(ib_index as int) - }, - idx: ib_index, - table: table - } - } - - pub fn first(table: M) -> Bucket { - Bucket { - raw: table.first_bucket_raw(), - idx: 0, - table: table - } - } - - /// Reads a bucket at a given index, returning an enum indicating whether - /// it's initialized or not. You need to match on this enum to get - /// the appropriate types to call most of the other functions in - /// this module. - pub fn peek(self) -> BucketState { - match unsafe { *self.raw.hash } { - EMPTY_BUCKET => - Empty(EmptyBucket { - raw: self.raw, - idx: self.idx, - table: self.table - }), - _ => - Full(FullBucket { - raw: self.raw, - idx: self.idx, - table: self.table - }) - } - } - - /// Modifies the bucket pointer in place to make it point to the next slot. - pub fn next(&mut self) { - // Branchless bucket iteration step. - // As we reach the end of the table... - // We take the current idx: 0111111b - // Xor it by its increment: ^ 1000000b - // ------------ - // 1111111b - // Then AND with the capacity: & 1000000b - // ------------ - // to get the backwards offset: 1000000b - // ... and it's zero at all other times. - let maybe_wraparound_dist = (self.idx ^ (self.idx + 1)) & self.table.capacity(); - // Finally, we obtain the offset 1 or the offset -cap + 1. - let dist = 1i - (maybe_wraparound_dist as int); - - self.idx += 1; - - unsafe { - self.raw = self.raw.offset(dist); - } - } -} - -impl>> EmptyBucket { - #[inline] - pub fn next(self) -> Bucket { - let mut bucket = self.into_bucket(); - bucket.next(); - bucket - } - - #[inline] - pub fn into_bucket(self) -> Bucket { - Bucket { - raw: self.raw, - idx: self.idx, - table: self.table - } - } - - pub fn gap_peek(self) -> Option> { - let gap = EmptyBucket { - raw: self.raw, - idx: self.idx, - table: () - }; - - match self.next().peek() { - Full(bucket) => { - Some(GapThenFull { - gap: gap, - full: bucket - }) - } - Empty(..) => None - } - } -} - -impl>> EmptyBucket { - /// Puts given key and value pair, along with the key's hash, - /// into this bucket in the hashtable. Note how `self` is 'moved' into - /// this function, because this slot will no longer be empty when - /// we return! A `FullBucket` is returned for later use, pointing to - /// the newly-filled slot in the hashtable. - /// - /// Use `make_hash` to construct a `SafeHash` to pass to this function. - pub fn put(mut self, hash: SafeHash, key: K, value: V) - -> FullBucket { - unsafe { - *self.raw.hash = hash.inspect(); - ptr::write(self.raw.key, key); - ptr::write(self.raw.val, value); - } - - self.table.size += 1; - - FullBucket { raw: self.raw, idx: self.idx, table: self.table } - } -} - -impl>> FullBucket { - #[inline] - pub fn next(self) -> Bucket { - let mut bucket = self.into_bucket(); - bucket.next(); - bucket - } - - #[inline] - pub fn into_bucket(self) -> Bucket { - Bucket { - raw: self.raw, - idx: self.idx, - table: self.table - } - } - - /// Get the distance between this bucket and the 'ideal' location - /// as determined by the key's hash stored in it. - /// - /// In the cited blog posts above, this is called the "distance to - /// initial bucket", or DIB. Also known as "probe count". - pub fn distance(&self) -> uint { - // Calculates the distance one has to travel when going from - // `hash mod capacity` onwards to `idx mod capacity`, wrapping around - // if the destination is not reached before the end of the table. - (self.idx - self.hash().inspect() as uint) & (self.table.capacity() - 1) - } - - #[inline] - pub fn hash(&self) -> SafeHash { - unsafe { - SafeHash { - hash: *self.raw.hash - } - } - } - - /// Gets references to the key and value at a given index. - pub fn read(&self) -> (&K, &V) { - unsafe { - (&*self.raw.key, - &*self.raw.val) - } - } -} - -impl>> FullBucket { - /// Removes this bucket's key and value from the hashtable. - /// - /// This works similarly to `put`, building an `EmptyBucket` out of the - /// taken bucket. - pub fn take(mut self) -> (EmptyBucket, K, V) { - let key = self.raw.key as *const K; - let val = self.raw.val as *const V; - - self.table.size -= 1; - - unsafe { - *self.raw.hash = EMPTY_BUCKET; - ( - EmptyBucket { - raw: self.raw, - idx: self.idx, - table: self.table - }, - ptr::read(key), - ptr::read(val) - ) - } - } - - pub fn replace(&mut self, h: SafeHash, k: K, v: V) -> (SafeHash, K, V) { - unsafe { - let old_hash = ptr::replace(self.raw.hash as *mut SafeHash, h); - let old_key = ptr::replace(self.raw.key, k); - let old_val = ptr::replace(self.raw.val, v); - - (old_hash, old_key, old_val) - } - } - - /// Gets mutable references to the key and value at a given index. - pub fn read_mut(&mut self) -> (&mut K, &mut V) { - unsafe { - (&mut *self.raw.key, - &mut *self.raw.val) - } - } -} - -impl<'t, K, V, M: Deref> + 't> FullBucket { - /// Exchange a bucket state for immutable references into the table. - /// Because the underlying reference to the table is also consumed, - /// no further changes to the structure of the table are possible; - /// in exchange for this, the returned references have a longer lifetime - /// than the references returned by `read()`. - pub fn into_refs(self) -> (&'t K, &'t V) { - unsafe { - (&*self.raw.key, - &*self.raw.val) - } - } -} - -impl<'t, K, V, M: DerefMut> + 't> FullBucket { - /// This works similarly to `into_refs`, exchanging a bucket state - /// for mutable references into the table. - pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) { - unsafe { - (&mut *self.raw.key, - &mut *self.raw.val) - } - } -} - -impl BucketState { - // For convenience. - pub fn expect_full(self) -> FullBucket { - match self { - Full(full) => full, - Empty(..) => panic!("Expected full bucket") - } - } -} - -impl>> GapThenFull { - #[inline] - pub fn full(&self) -> &FullBucket { - &self.full - } - - pub fn shift(mut self) -> Option> { - unsafe { - *self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET); - copy_nonoverlapping_memory(self.gap.raw.key, self.full.raw.key as *const K, 1); - copy_nonoverlapping_memory(self.gap.raw.val, self.full.raw.val as *const V, 1); - } - - let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full; - - match self.full.next().peek() { - Full(bucket) => { - self.gap.raw = prev_raw; - self.gap.idx = prev_idx; - - self.full = bucket; - - Some(self) - } - Empty(..) => None - } - } -} - - -/// Rounds up to a multiple of a power of two. Returns the closest multiple -/// of `target_alignment` that is higher or equal to `unrounded`. -/// -/// # Failure -/// -/// Fails if `target_alignment` is not a power of two. -fn round_up_to_next(unrounded: uint, target_alignment: uint) -> uint { - assert!(is_power_of_two(target_alignment)); - (unrounded + target_alignment - 1) & !(target_alignment - 1) -} - -#[test] -fn test_rounding() { - assert_eq!(round_up_to_next(0, 4), 0); - assert_eq!(round_up_to_next(1, 4), 4); - assert_eq!(round_up_to_next(2, 4), 4); - assert_eq!(round_up_to_next(3, 4), 4); - assert_eq!(round_up_to_next(4, 4), 4); - assert_eq!(round_up_to_next(5, 4), 8); -} - -// Returns a tuple of (key_offset, val_offset), -// from the start of a mallocated array. -fn calculate_offsets(hashes_size: uint, - keys_size: uint, keys_align: uint, - vals_align: uint) - -> (uint, uint) { - let keys_offset = round_up_to_next(hashes_size, keys_align); - let end_of_keys = keys_offset + keys_size; - - let vals_offset = round_up_to_next(end_of_keys, vals_align); - - (keys_offset, vals_offset) -} - -// Returns a tuple of (minimum required malloc alignment, hash_offset, -// array_size), from the start of a mallocated array. -fn calculate_allocation(hash_size: uint, hash_align: uint, - keys_size: uint, keys_align: uint, - vals_size: uint, vals_align: uint) - -> (uint, uint, uint) { - let hash_offset = 0; - let (_, vals_offset) = calculate_offsets(hash_size, - keys_size, keys_align, - vals_align); - let end_of_vals = vals_offset + vals_size; - - let min_align = cmp::max(hash_align, cmp::max(keys_align, vals_align)); - - (min_align, hash_offset, end_of_vals) -} - -#[test] -fn test_offset_calculation() { - assert_eq!(calculate_allocation(128, 8, 15, 1, 4, 4), (8, 0, 148)); - assert_eq!(calculate_allocation(3, 1, 2, 1, 1, 1), (1, 0, 6)); - assert_eq!(calculate_allocation(6, 2, 12, 4, 24, 8), (8, 0, 48)); - assert_eq!(calculate_offsets(128, 15, 1, 4), (128, 144)); - assert_eq!(calculate_offsets(3, 2, 1, 1), (3, 5)); - assert_eq!(calculate_offsets(6, 12, 4, 8), (8, 24)); -} - -impl RawTable { - /// Does not initialize the buckets. The caller should ensure they, - /// at the very least, set every hash to EMPTY_BUCKET. - unsafe fn new_uninitialized(capacity: uint) -> RawTable { - if capacity == 0 { - return RawTable { - size: 0, - capacity: 0, - hashes: 0 as *mut u64, - marker: marker::CovariantType, - }; - } - // No need for `checked_mul` before a more restrictive check performed - // later in this method. - let hashes_size = capacity * size_of::(); - let keys_size = capacity * size_of::< K >(); - let vals_size = capacity * size_of::< V >(); - - // Allocating hashmaps is a little tricky. We need to allocate three - // arrays, but since we know their sizes and alignments up front, - // we just allocate a single array, and then have the subarrays - // point into it. - // - // This is great in theory, but in practice getting the alignment - // right is a little subtle. Therefore, calculating offsets has been - // factored out into a different function. - let (malloc_alignment, hash_offset, size) = - calculate_allocation( - hashes_size, min_align_of::(), - keys_size, min_align_of::< K >(), - vals_size, min_align_of::< V >()); - - // One check for overflow that covers calculation and rounding of size. - let size_of_bucket = size_of::().checked_add(&size_of::()).unwrap() - .checked_add(&size_of::()).unwrap(); - assert!(size >= capacity.checked_mul(&size_of_bucket) - .expect("capacity overflow"), - "capacity overflow"); - - let buffer = allocate(size, malloc_alignment); - if buffer.is_null() { ::alloc::oom() } - - let hashes = buffer.offset(hash_offset as int) as *mut u64; - - RawTable { - capacity: capacity, - size: 0, - hashes: hashes, - marker: marker::CovariantType, - } - } - - fn first_bucket_raw(&self) -> RawBucket { - let hashes_size = self.capacity * size_of::(); - let keys_size = self.capacity * size_of::(); - - let buffer = self.hashes as *mut u8; - let (keys_offset, vals_offset) = calculate_offsets(hashes_size, - keys_size, min_align_of::(), - min_align_of::()); - - unsafe { - RawBucket { - hash: self.hashes, - key: buffer.offset(keys_offset as int) as *mut K, - val: buffer.offset(vals_offset as int) as *mut V - } - } - } - - /// Creates a new raw table from a given capacity. All buckets are - /// initially empty. - #[allow(experimental)] - pub fn new(capacity: uint) -> RawTable { - unsafe { - let ret = RawTable::new_uninitialized(capacity); - zero_memory(ret.hashes, capacity); - ret - } - } - - /// The hashtable's capacity, similar to a vector's. - pub fn capacity(&self) -> uint { - self.capacity - } - - /// The number of elements ever `put` in the hashtable, minus the number - /// of elements ever `take`n. - pub fn size(&self) -> uint { - self.size - } - - fn raw_buckets(&self) -> RawBuckets { - RawBuckets { - raw: self.first_bucket_raw(), - hashes_end: unsafe { - self.hashes.offset(self.capacity as int) - }, - marker: marker::ContravariantLifetime, - } - } - - pub fn iter(&self) -> Entries { - Entries { - iter: self.raw_buckets(), - elems_left: self.size(), - } - } - - pub fn iter_mut(&mut self) -> MutEntries { - MutEntries { - iter: self.raw_buckets(), - elems_left: self.size(), - } - } - - pub fn into_iter(self) -> MoveEntries { - let RawBuckets { raw, hashes_end, .. } = self.raw_buckets(); - // Replace the marker regardless of lifetime bounds on parameters. - MoveEntries { - iter: RawBuckets { - raw: raw, - hashes_end: hashes_end, - marker: marker::ContravariantLifetime, - }, - table: self, - } - } - - /// Returns an iterator that copies out each entry. Used while the table - /// is being dropped. - unsafe fn rev_move_buckets(&mut self) -> RevMoveBuckets { - let raw_bucket = self.first_bucket_raw(); - RevMoveBuckets { - raw: raw_bucket.offset(self.capacity as int), - hashes_end: raw_bucket.hash, - elems_left: self.size, - marker: marker::ContravariantLifetime, - } - } -} - -/// A raw iterator. The basis for some other iterators in this module. Although -/// this interface is safe, it's not used outside this module. -struct RawBuckets<'a, K, V> { - raw: RawBucket, - hashes_end: *mut u64, - marker: marker::ContravariantLifetime<'a>, -} - -impl<'a, K, V> Iterator> for RawBuckets<'a, K, V> { - fn next(&mut self) -> Option> { - while self.raw.hash != self.hashes_end { - unsafe { - // We are swapping out the pointer to a bucket and replacing - // it with the pointer to the next one. - let prev = ptr::replace(&mut self.raw, self.raw.offset(1)); - if *prev.hash != EMPTY_BUCKET { - return Some(prev); - } - } - } - - None - } -} - -/// An iterator that moves out buckets in reverse order. It leaves the table -/// in an an inconsistent state and should only be used for dropping -/// the table's remaining entries. It's used in the implementation of Drop. -struct RevMoveBuckets<'a, K, V> { - raw: RawBucket, - hashes_end: *mut u64, - elems_left: uint, - marker: marker::ContravariantLifetime<'a>, -} - -impl<'a, K, V> Iterator<(K, V)> for RevMoveBuckets<'a, K, V> { - fn next(&mut self) -> Option<(K, V)> { - if self.elems_left == 0 { - return None; - } - - loop { - debug_assert!(self.raw.hash != self.hashes_end); - - unsafe { - self.raw = self.raw.offset(-1); - - if *self.raw.hash != EMPTY_BUCKET { - self.elems_left -= 1; - return Some(( - ptr::read(self.raw.key as *const K), - ptr::read(self.raw.val as *const V) - )); - } - } - } - } -} - -/// Iterator over shared references to entries in a table. -pub struct Entries<'a, K: 'a, V: 'a> { - iter: RawBuckets<'a, K, V>, - elems_left: uint, -} - -/// Iterator over mutable references to entries in a table. -pub struct MutEntries<'a, K: 'a, V: 'a> { - iter: RawBuckets<'a, K, V>, - elems_left: uint, -} - -/// Iterator over the entries in a table, consuming the table. -pub struct MoveEntries { - table: RawTable, - iter: RawBuckets<'static, K, V> -} - -impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> { - fn next(&mut self) -> Option<(&'a K, &'a V)> { - self.iter.next().map(|bucket| { - self.elems_left -= 1; - unsafe { - (&*bucket.key, - &*bucket.val) - } - }) - } - - fn size_hint(&self) -> (uint, Option) { - (self.elems_left, Some(self.elems_left)) - } -} - -impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> { - fn next(&mut self) -> Option<(&'a K, &'a mut V)> { - self.iter.next().map(|bucket| { - self.elems_left -= 1; - unsafe { - (&*bucket.key, - &mut *bucket.val) - } - }) - } - - fn size_hint(&self) -> (uint, Option) { - (self.elems_left, Some(self.elems_left)) - } -} - -impl Iterator<(SafeHash, K, V)> for MoveEntries { - fn next(&mut self) -> Option<(SafeHash, K, V)> { - self.iter.next().map(|bucket| { - self.table.size -= 1; - unsafe { - ( - SafeHash { - hash: *bucket.hash, - }, - ptr::read(bucket.key as *const K), - ptr::read(bucket.val as *const V) - ) - } - }) - } - - fn size_hint(&self) -> (uint, Option) { - let size = self.table.size(); - (size, Some(size)) - } -} - -impl Clone for RawTable { - fn clone(&self) -> RawTable { - unsafe { - let mut new_ht = RawTable::new_uninitialized(self.capacity()); - - { - let cap = self.capacity(); - let mut new_buckets = Bucket::first(&mut new_ht); - let mut buckets = Bucket::first(self); - while buckets.index() != cap { - match buckets.peek() { - Full(full) => { - let (h, k, v) = { - let (k, v) = full.read(); - (full.hash(), k.clone(), v.clone()) - }; - *new_buckets.raw.hash = h.inspect(); - ptr::write(new_buckets.raw.key, k); - ptr::write(new_buckets.raw.val, v); - } - Empty(..) => { - *new_buckets.raw.hash = EMPTY_BUCKET; - } - } - new_buckets.next(); - buckets.next(); - } - }; - - new_ht.size = self.size(); - - new_ht - } - } -} - -#[unsafe_destructor] -impl Drop for RawTable { - fn drop(&mut self) { - if self.hashes.is_null() { - return; - } - // This is done in reverse because we've likely partially taken - // some elements out with `.into_iter()` from the front. - // Check if the size is 0, so we don't do a useless scan when - // dropping empty tables such as on resize. - // Also avoid double drop of elements that have been already moved out. - unsafe { - for _ in self.rev_move_buckets() {} - } - - let hashes_size = self.capacity * size_of::(); - let keys_size = self.capacity * size_of::(); - let vals_size = self.capacity * size_of::(); - let (align, _, size) = calculate_allocation(hashes_size, min_align_of::(), - keys_size, min_align_of::(), - vals_size, min_align_of::()); - - unsafe { - deallocate(self.hashes as *mut u8, size, align); - // Remember how everything was allocated out of one buffer - // during initialization? We only need one call to free here. - } - } -} diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index be9e22ee9d1..13486d4b8f8 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -24,9 +24,9 @@ //! Rust's collections can be grouped into four major categories: //! //! * Sequences: `Vec`, `RingBuf`, `DList`, `BitV` -//! * Maps: `HashMap`, `BTreeMap`, `TreeMap`, `TrieMap`, `SmallIntMap`, `LruCache` +//! * Maps: `HashMap`, `BTreeMap`, `TreeMap`, `TrieMap`, `VecMap`, `LruCache` //! * Sets: `HashSet`, `BTreeSet`, `TreeSet`, `TrieSet`, `BitVSet`, `EnumSet` -//! * Misc: `PriorityQueue` +//! * Misc: `BinaryHeap` //! //! # When Should You Use Which Collection? //! @@ -74,7 +74,7 @@ //! * You want a `HashMap`, but with many potentially large `uint` keys. //! * You want a `BTreeMap`, but with potentially large `uint` keys. //! -//! ### Use a `SmallIntMap` when: +//! ### Use a `VecMap` when: //! * You want a `HashMap` but with known to be small `uint` keys. //! * You want a `BTreeMap`, but with known to be small `uint` keys. //! @@ -88,12 +88,12 @@ //! * You want a bitvector. //! //! ### Use a `BitVSet` when: -//! * You want a `SmallIntSet`. +//! * You want a `VecSet`. //! //! ### Use an `EnumSet` when: //! * You want a C-like enum, stored in a single `uint`. //! -//! ### Use a `PriorityQueue` when: +//! ### Use a `BinaryHeap` when: //! * You want to store a bunch of elements, but only ever want to process the "biggest" //! or "most important" one at any given time. //! * You want a priority queue. @@ -266,7 +266,7 @@ //! #### Counting the number of times each character in a string occurs //! //! ``` -//! use std::collections::btree::{BTreeMap, Occupied, Vacant}; +//! use std::collections::btree_map::{BTreeMap, Occupied, Vacant}; //! //! let mut count = BTreeMap::new(); //! let message = "she sells sea shells by the sea shore"; @@ -293,7 +293,7 @@ //! #### Tracking the inebriation of customers at a bar //! //! ``` -//! use std::collections::btree::{BTreeMap, Occupied, Vacant}; +//! use std::collections::btree_map::{BTreeMap, Occupied, Vacant}; //! //! // A client of the bar. They have an id and a blood alcohol level. //! struct Person { id: u32, blood_alcohol: f32 }; @@ -328,14 +328,27 @@ #![experimental] -pub use core_collections::{Bitv, BitvSet, BTreeMap, BTreeSet, DList, EnumSet}; -pub use core_collections::{PriorityQueue, RingBuf, SmallIntMap}; -pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet}; -pub use core_collections::{bitv, btree, dlist, enum_set}; -pub use core_collections::{priority_queue, ringbuf, smallintmap, treemap, trie}; +pub use core_collections::{BinaryHeap, Bitv, BitvSet, BTreeMap, BTreeSet}; +pub use core_collections::{DList, EnumSet, RingBuf}; +pub use core_collections::{TreeMap, TreeSet, TrieMap, TrieSet, VecMap}; -pub use self::hashmap::{HashMap, HashSet}; +pub use core_collections::{binary_heap, bitv, bitv_set, btree_map, btree_set, dlist, enum_set}; +pub use core_collections::{ring_buf, tree_map, tree_set, trie_map, trie_set, vec_map}; + +pub use self::hash_map::HashMap; +pub use self::hash_set::HashSet; pub use self::lru_cache::LruCache; -pub mod hashmap; +mod hash; + +pub mod hash_map { + //! A hashmap + pub use super::hash::map::*; +} + +pub mod hash_set { + //! A hashset + pub use super::hash::set::*; +} + pub mod lru_cache; diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index 840468176ab..bebe16286c9 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -20,7 +20,7 @@ use ast::{Ident, Mrk, Name, SyntaxContext}; use std::cell::RefCell; use std::rc::Rc; use std::collections::HashMap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map::{Occupied, Vacant}; /// The SCTable contains a table of SyntaxContext_'s. It /// represents a flattened tree structure, to avoid having diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 2cc694176de..8c184ccbe43 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -10,8 +10,8 @@ #![allow(missing_docs)] -use std::collections::hashmap; -use std::collections::hashmap::{Occupied, Vacant}; +use std::collections::hash_map; +use std::collections::hash_map::{Occupied, Vacant}; use std::fmt::Show; use std::hash::Hash; use std::io; @@ -440,8 +440,8 @@ pub fn write_boxplot( /// Returns a HashMap with the number of occurrences of every element in the /// sequence that the iterator exposes. -pub fn freq_count, U: Eq+Hash>(mut iter: T) -> hashmap::HashMap { - let mut map: hashmap::HashMap = hashmap::HashMap::new(); +pub fn freq_count, U: Eq+Hash>(mut iter: T) -> hash_map::HashMap { + let mut map: hash_map::HashMap = hash_map::HashMap::new(); for elem in iter { match map.entry(elem) { Occupied(mut entry) => { *entry.get_mut() += 1; }, diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index 4833467922b..8151f2718e3 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -14,7 +14,7 @@ extern crate collections; extern crate rand; extern crate time; -use std::collections::bitv::BitvSet; +use std::collections::BitvSet; use std::collections::TreeSet; use std::hash::Hash; use std::collections::HashSet; diff --git a/src/test/bench/std-smallintmap.rs b/src/test/bench/std-smallintmap.rs index 2086980b016..cdcb88d87c6 100644 --- a/src/test/bench/std-smallintmap.rs +++ b/src/test/bench/std-smallintmap.rs @@ -13,17 +13,17 @@ extern crate collections; extern crate time; -use std::collections::SmallIntMap; +use std::collections::VecMap; use std::os; use std::uint; -fn append_sequential(min: uint, max: uint, map: &mut SmallIntMap) { +fn append_sequential(min: uint, max: uint, map: &mut VecMap) { for i in range(min, max) { map.insert(i, i + 22u); } } -fn check_sequential(min: uint, max: uint, map: &SmallIntMap) { +fn check_sequential(min: uint, max: uint, map: &VecMap) { for i in range(min, max) { assert_eq!(map[i], i + 22u); } @@ -45,7 +45,7 @@ fn main() { let mut appendf = 0.0; for _ in range(0u, rep) { - let mut map = SmallIntMap::new(); + let mut map = VecMap::new(); let start = time::precise_time_s(); append_sequential(0u, max, &mut map); let mid = time::precise_time_s(); diff --git a/src/test/run-fail/hashmap-capacity-overflow.rs b/src/test/run-fail/hashmap-capacity-overflow.rs index f68b511d0aa..c86f8a38f63 100644 --- a/src/test/run-fail/hashmap-capacity-overflow.rs +++ b/src/test/run-fail/hashmap-capacity-overflow.rs @@ -10,7 +10,7 @@ // error-pattern:capacity overflow -use std::collections::hashmap::HashMap; +use std::collections::hash_map::HashMap; use std::uint; use std::mem::size_of; diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs index 10c3df9388a..44006a0039a 100644 --- a/src/test/run-pass/auto-encode.rs +++ b/src/test/run-pass/auto-encode.rs @@ -17,7 +17,7 @@ extern crate time; // These tests used to be separate files, but I wanted to refactor all // the common code. -use std::hashmap::{HashMap, HashSet}; +use std::collections::{HashMap, HashSet}; use rbml::reader as EBReader; use rbml::writer as EBWriter; diff --git a/src/test/run-pass/while-let.rs b/src/test/run-pass/while-let.rs index 41f54d47ad4..449b3099dfa 100644 --- a/src/test/run-pass/while-let.rs +++ b/src/test/run-pass/while-let.rs @@ -10,10 +10,10 @@ #![feature(while_let)] -use std::collections::PriorityQueue; +use std::collections::BinaryHeap; -fn make_pq() -> PriorityQueue { - PriorityQueue::from_vec(vec![1i,2,3]) +fn make_pq() -> BinaryHeap { + BinaryHeap::from_vec(vec![1i,2,3]) } pub fn main() { -- cgit 1.4.1-3-g733a5