collections::bitv: clean up and unit test BitvSet::is_subset

This commit is contained in:
Andrew Poelstra 2014-07-02 11:10:32 -07:00
parent 78b674152e
commit 8ef0165a56

View File

@ -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
@ -1594,6 +1549,32 @@ mod tests {
assert_eq!(i, expected.len());
}
#[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();