diff options
| author | Andrew Poelstra <apoelstra@wpsoftware.net> | 2014-07-02 11:10:32 -0700 |
|---|---|---|
| committer | Andrew Poelstra <apoelstra@wpsoftware.net> | 2014-07-02 15:31:08 -0700 |
| commit | 8ef0165a56bc788968fcec6debb510b58134f0d9 (patch) | |
| tree | 0c50a05adbcb3a00f42850366c95bfdd6f52cd96 | |
| parent | 78b674152ed09f2e7f30f0080171b43e11f56f31 (diff) | |
| download | rust-8ef0165a56bc788968fcec6debb510b58134f0d9.tar.gz rust-8ef0165a56bc788968fcec6debb510b58134f0d9.zip | |
collections::bitv: clean up and unit test `BitvSet::is_subset`
| -rw-r--r-- | src/libcollections/bitv.rs | 91 |
1 files changed, 36 insertions, 55 deletions
diff --git a/src/libcollections/bitv.rs b/src/libcollections/bitv.rs index fdd690ccdd9..6d7c91ccfee 100644 --- a/src/libcollections/bitv.rs +++ b/src/libcollections/bitv.rs @@ -15,7 +15,7 @@ use core::prelude::*; use core::cmp; use core::default::Default; use core::fmt; -use core::iter::{Map, Take, Zip}; +use core::iter::Take; use core::ops; use core::slice; use core::uint; @@ -825,23 +825,16 @@ impl Set<uint> for BitvSet { self.intersection(other).count() > 0 } + #[inline] fn is_subset(&self, other: &BitvSet) -> bool { - for (_, w1, w2) in self.commons(other) { - if w1 & w2 != w1 { - return false; - } - } - /* If anything is not ours, then everything is not ours so we're - definitely a subset in that case. Otherwise if there's any stray - ones that 'other' doesn't have, we're not a subset. */ - for (mine, _, w) in self.outliers(other) { - if !mine { - return true; - } else if w != 0 { - return false; - } - } - return true; + 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) } #[inline] @@ -883,44 +876,6 @@ impl MutableSet<uint> for BitvSet { } } -impl BitvSet { - /// Visits each of the words that the two bit vectors (`self` and `other`) - /// both have in common. The three yielded arguments are (bit location, - /// w1, w2) where the bit location is the number of bits offset so far, - /// and w1/w2 are the words coming from the two vectors self, other. - fn commons<'a>(&'a self, other: &'a BitvSet) - -> Map<((uint, uint), (uint, uint)), (uint, uint, uint), - Zip<MaskWords<'a>, MaskWords<'a>>> { - let &BitvSet(ref self_bitv) = self; - let &BitvSet(ref other_bitv) = other; - self_bitv.mask_words(0).zip(other_bitv.mask_words(0)) - .map(|((i, w1), (_, w2))| (i * uint::BITS, w1, w2)) - } - - /// Visits each word in `self` or `other` that extends beyond the other. This - /// will only iterate through one of the vectors, and it only iterates - /// over the portion that doesn't overlap with the other one. - /// - /// The yielded arguments are a `bool`, the bit offset, and a word. The `bool` - /// is true if the word comes from `self`, and `false` if it comes from - /// `other`. - fn outliers<'a>(&'a self, other: &'a BitvSet) - -> Map<(uint, uint), (bool, uint, uint), MaskWords<'a>> { - let slen = self.capacity() / uint::BITS; - let olen = other.capacity() / uint::BITS; - let &BitvSet(ref self_bitv) = self; - let &BitvSet(ref other_bitv) = other; - - if olen < slen { - self_bitv.mask_words(olen) - .map(|(i, w)| (true, i * uint::BITS, w)) - } else { - other_bitv.mask_words(slen) - .map(|(i, w)| (false, i * uint::BITS, w)) - } - } -} - pub struct BitPositions<'a> { set: &'a BitvSet, next_idx: uint @@ -1595,6 +1550,32 @@ mod tests { } #[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_remove() { let mut a = BitvSet::new(); |
