Clean up the implementations of Bitv and BitvSet.

Functions that add bits now ensure that any unused bits are set to 0.
`into_bitv` sanitizes the nbits of the Bitv/BitvSet it returns by setting the nbits to the current capacity.
Fix a bug with `union_with` and `symmetric_difference` with due to not updating nbits properly
Add test cases to the _with functions
Remove `get_mut_ref`

This is a [breaking-change]. The things you will need to fix are:

1. BitvSet's `unwrap()` has been renamed to `into_bitv`
2. BitvSet's `get_mut_ref()` has been removed. Use `into_bitv()` and `from_bitv()` instead.
This commit is contained in:
Kasey Carrothers 2014-09-25 23:49:17 -07:00
parent 63fe80e1ff
commit dd4fa906fc

View File

@ -235,11 +235,20 @@ impl Bitv {
/// }
/// ```
pub fn with_capacity(nbits: uint, init: bool) -> Bitv {
Bitv {
let mut bitv = Bitv {
storage: Vec::from_elem((nbits + uint::BITS - 1) / uint::BITS,
if init { !0u } else { 0u }),
nbits: nbits
};
// Zero out any unused bits in the highest word if necessary
let used_bits = bitv.nbits % uint::BITS;
if init && used_bits != 0 {
let largest_used_word = (bitv.nbits + uint::BITS - 1) / uint::BITS - 1;
*bitv.storage.get_mut(largest_used_word) &= (1 << used_bits) - 1;
}
bitv
}
/// Retrieves the value at index `i`.
@ -629,9 +638,9 @@ impl Bitv {
/// ```
pub fn reserve(&mut self, size: uint) {
let old_size = self.storage.len();
let size = (size + uint::BITS - 1) / uint::BITS;
if old_size < size {
self.storage.grow(size - old_size, 0);
let new_size = (size + uint::BITS - 1) / uint::BITS;
if old_size < new_size {
self.storage.grow(new_size - old_size, 0);
}
}
@ -686,8 +695,15 @@ impl Bitv {
}
// 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);
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 % uint::BITS;
*self.storage.get_mut(tail_word) &= (1 << used_bits) - 1;
}
}
// Adjust internal bit count
self.nbits = new_nbits;
@ -970,9 +986,8 @@ impl<'a> RandomAccessIterator<bool> for Bits<'a> {
/// }
///
/// // Can convert back to a `Bitv`
/// let bv: Bitv = s.unwrap();
/// assert!(bv.eq_vec([true, true, false, true,
/// false, false, false, false]));
/// let bv: Bitv = s.into_bitv();
/// assert!(bv.get(3));
/// ```
#[deriving(Clone)]
pub struct BitvSet(Bitv);
@ -993,7 +1008,8 @@ impl FromIterator<bool> for BitvSet {
impl Extendable<bool> for BitvSet {
#[inline]
fn extend<I: Iterator<bool>>(&mut self, iterator: I) {
self.get_mut_ref().extend(iterator);
let &BitvSet(ref mut self_bitv) = self;
self_bitv.extend(iterator);
}
}
@ -1049,7 +1065,8 @@ impl BitvSet {
/// ```
#[inline]
pub fn with_capacity(nbits: uint) -> BitvSet {
BitvSet(Bitv::with_capacity(nbits, false))
let bitv = Bitv::with_capacity(nbits, false);
BitvSet::from_bitv(bitv)
}
/// Creates a new bit vector set from the given bit vector.
@ -1068,7 +1085,9 @@ impl BitvSet {
/// }
/// ```
#[inline]
pub fn from_bitv(bitv: Bitv) -> BitvSet {
pub fn from_bitv(mut bitv: Bitv) -> BitvSet {
// Mark every bit as valid
bitv.nbits = bitv.capacity();
BitvSet(bitv)
}
@ -1102,7 +1121,10 @@ impl BitvSet {
/// ```
pub fn reserve(&mut self, size: uint) {
let &BitvSet(ref mut bitv) = self;
bitv.reserve(size)
bitv.reserve(size);
if bitv.nbits < size {
bitv.nbits = bitv.capacity();
}
}
/// Consumes this set to return the underlying bit vector.
@ -1116,11 +1138,12 @@ impl BitvSet {
/// s.insert(0);
/// s.insert(3);
///
/// let bv = s.unwrap();
/// assert!(bv.eq_vec([true, false, false, true]));
/// let bv = s.into_bitv();
/// assert!(bv.get(0));
/// assert!(bv.get(3));
/// ```
#[inline]
pub fn unwrap(self) -> Bitv {
pub fn into_bitv(self) -> Bitv {
let BitvSet(bitv) = self;
bitv
}
@ -1144,38 +1167,15 @@ impl BitvSet {
bitv
}
/// Returns a mutable reference to the underlying bit vector.
///
/// # Example
///
/// ```
/// use std::collections::BitvSet;
///
/// let mut s = BitvSet::new();
/// s.insert(0);
/// assert_eq!(s.contains(&0), true);
/// {
/// // Will free the set during bv's lifetime
/// let bv = s.get_mut_ref();
/// bv.set(0, false);
/// }
/// assert_eq!(s.contains(&0), false);
/// ```
#[inline]
pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut Bitv {
let &BitvSet(ref mut bitv) = self;
bitv
}
#[inline]
fn other_op(&mut self, other: &BitvSet, f: |uint, uint| -> uint) {
// Expand the vector if necessary
self.reserve(other.capacity());
// Unwrap Bitvs
let &BitvSet(ref mut self_bitv) = self;
let &BitvSet(ref other_bitv) = other;
// Expand the vector if necessary
self_bitv.reserve(other_bitv.capacity());
// virtually pad other with 0's for equal lengths
let mut other_words = {
let (_, result) = match_words(self_bitv, other_bitv);
@ -1376,9 +1376,10 @@ impl BitvSet {
///
/// 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.unwrap(), bitv::from_bytes([res]));
/// assert_eq!(a, res);
/// ```
#[inline]
pub fn union_with(&mut self, other: &BitvSet) {
@ -1399,9 +1400,10 @@ impl BitvSet {
///
/// 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.unwrap(), bitv::from_bytes([res]));
/// assert_eq!(a, res);
/// ```
#[inline]
pub fn intersect_with(&mut self, other: &BitvSet) {
@ -1424,15 +1426,17 @@ impl BitvSet {
///
/// 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.unwrap(), bitv::from_bytes([a_b]));
/// 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.unwrap(), bitv::from_bytes([b_a]));
/// assert_eq!(bvb, bvb_a);
/// ```
#[inline]
pub fn difference_with(&mut self, other: &BitvSet) {
@ -1454,9 +1458,10 @@ impl BitvSet {
///
/// 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.unwrap(), bitv::from_bytes([res]));
/// assert_eq!(a, res);
/// ```
#[inline]
pub fn symmetric_difference_with(&mut self, other: &BitvSet) {
@ -1538,20 +1543,14 @@ impl MutableSet<uint> for BitvSet {
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;
if value >= bitv.nbits {
// If we are increasing nbits, make sure we mask out any previously-unconsidered bits
let old_rem = bitv.nbits % uint::BITS;
if old_rem != 0 {
let old_last_word = (bitv.nbits + uint::BITS - 1) / uint::BITS - 1;
*bitv.storage.get_mut(old_last_word) &= (1 << old_rem) - 1;
}
bitv.nbits = value + 1;
}
bitv.set(value, true);
return true;
}
@ -2225,6 +2224,7 @@ mod tests {
assert!(a.insert(160));
assert!(a.insert(19));
assert!(a.insert(24));
assert!(a.insert(200));
assert!(b.insert(1));
assert!(b.insert(5));
@ -2232,7 +2232,7 @@ mod tests {
assert!(b.insert(13));
assert!(b.insert(19));
let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160];
let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160, 200];
let actual = a.union(&b).collect::<Vec<uint>>();
assert_eq!(actual.as_slice(), expected.as_slice());
}
@ -2281,6 +2281,27 @@ mod tests {
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
@ -2311,6 +2332,59 @@ mod tests {
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]));