From 9c5101542d2a4983ade627bc593e16c0bb5f23ba Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Fri, 21 Nov 2014 20:47:40 -0500 Subject: [PATCH 1/6] Conventions and cleanup for Bitv and BitvSet Part of #18424 This commit changes the semantics of `reserve` and `capacity` for Bitv and BitvSet to match conventions. It also introduces the notion of `reserve_index` and `reserve_index_exact` for collections with maximum-index-based capacity semantics. Deprecates free function constructors in favour of functions on Bitv itself. Changes `Bitv::pop` to return an Option rather than panicking. Deprecates and renames several methods in favour of conventions. Marks several blessed methods as unstable. This commit also substantially refactors Bitv and BitvSet's implementations. The new implementation is simpler, cleaner, better documented, and more robust against overflows. It also reduces coupling between Bitv and BitvSet. Tests have been seperated into seperate submodules. Fixes #16958 [breaking-change] --- src/libcollections/bit.rs | 1619 +++++++++++++++------------ src/test/run-pass/bitv-perf-test.rs | 4 +- src/test/run-pass/issue-11736.rs | 2 +- 3 files changed, 897 insertions(+), 728 deletions(-) diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index f59fb1c5d3daa..41a5ccb7a0645 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -11,6 +11,16 @@ // 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. +// First rule of Bitv club: almost everything can actually overflow because we're working with +// bits and not bytes. +// +// Second rule of Bitv club: the last "block" of bits may be partially used. We must ensure that +// those unused bits are zeroed out, as other methods will assume this is the case. It may be +// the case that this isn't a great design, but having "undefined" bits is headache-inducing. +// +// Third rule of Bitv club: BitvSet is fairly tightly coupled to Bitv's implementation details. +// Make sure any changes to Bitv are properly addressed in BitvSet. + //! Collections implemented with bit vectors. //! //! # Examples @@ -31,7 +41,7 @@ //! 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); +//! let mut bv = Bitv::from_elem(max_prime, true); //! //! // Neither 0 nor 1 are prime //! bv.set(0, false); @@ -68,18 +78,19 @@ use core::prelude::*; use core::cmp; use core::default::Default; use core::fmt; -use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat}; +use core::iter::{Cloned, Chain, Enumerate, Repeat, Skip, Take}; use core::iter; use core::num::Int; -use core::slice; -use core::u32; +use core::slice::{Items, MutItems}; +use core::{u32, uint}; use std::hash; use vec::Vec; -// FIXME(conventions): look, we just need to refactor this whole thing. Inside and out. +type Blocks<'a> = Cloned> +type MutBlocks<'a> MutItems<'a, u32>; +type MatchWords<'a> = Chain>, Skip>>>>; -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>) { @@ -88,11 +99,11 @@ fn match_words <'a,'b>(a: &'a Bitv, b: &'b Bitv) -> (MatchWords<'a>, MatchWords< // have to uselessly pretend to pad the longer one for type matching if a_len < b_len { - (a.mask_words(0).chain(repeat(0u32).enumerate().take(b_len).skip(a_len)), - b.mask_words(0).chain(repeat(0u32).enumerate().take(0).skip(0))) + (a.blocks().enumerate().chain(iter::repeat(0u32).enumerate().take(b_len).skip(a_len)), + b.blocks().enumerate().chain(iter::repeat(0u32).enumerate().take(0).skip(0))) } else { - (a.mask_words(0).chain(repeat(0u32).enumerate().take(0).skip(0)), - b.mask_words(0).chain(repeat(0u32).enumerate().take(a_len).skip(b_len))) + (a.blocks().enumerate().chain(iter::repeat(0u32).enumerate().take(0).skip(0)), + b.blocks().enumerate().chain(iter::repeat(0u32).enumerate().take(a_len).skip(b_len))) } } @@ -106,7 +117,7 @@ static FALSE: bool = false; /// ```rust /// use collections::Bitv; /// -/// let mut bv = Bitv::with_capacity(10, false); +/// let mut bv = Bitv::from_elem(10, false); /// /// // insert all primes less than 10 /// bv.set(2, true); @@ -133,10 +144,11 @@ pub struct Bitv { nbits: uint } +// FIXME(Gankro): NopeNopeNopeNopeNope (wait for IndexGet to be a thing) impl Index for Bitv { #[inline] fn index<'a>(&'a self, i: &uint) -> &'a bool { - if self.get(*i) { + if self.get(*i).expect("index out of bounds") { &TRUE } else { &FALSE @@ -144,35 +156,27 @@ impl Index for Bitv { } } -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(&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 - } +/// Computes how many blocks are needed to store that many bits +fn blocks_for_bits(bits: uint) -> uint { + // If we want 17 bits, dividing by 32 will produce 0. So we add 1 to make sure we + // reserve enough. But if we want exactly a multiple of 32, this will actually allocate + // one too many. So we need to check if that's the case. We can do that by computing if + // bitwise AND by `32 - 1` is 0. But LLVM should be able to optimize the semantically + // superior modulo operator on a power of two to this. + // + // Note that we can technically avoid this branch with the expression + // `(nbits + u32::BITS - 1) / 32::BITS`, but if nbits is almost uint::MAX this will overflow. + if bits % u32::BITS == 0 { + bits / u32::BITS + } else { + bits / u32::BITS + 1 } + } impl Bitv { + /// Applies the given operation to the blocks of self and other, and sets self to + /// be the result. #[inline] fn process(&mut self, other: &Bitv, mut op: F) -> bool where F: FnMut(u32, u32) -> u32 { let len = other.storage.len(); @@ -182,8 +186,7 @@ impl Bitv { // `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)) { + for (a, b) in self.blocks_mut().zip(other.blocks()) { let w = op(*a, b); if *a != w { changed = true; @@ -193,22 +196,27 @@ impl Bitv { 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 + /// Iterator over mutable refs to the underlying blocks of data. + fn blocks_mut(&mut self) -> MutBlocks { + let blocks = blocks_for_bits(self.len()); + self.storage[..blocks].iter_mut() + } + + /// Iterator over the underlying blocks of data + fn blocks(&self) -> Blocks { + let blocks = blocks_for_bits(self.len()); + self.storage[..blocks].iter().cloned() + } + + /// An operation might screw up the unused bits in the last block of the Bitv. + /// It's assumed to be all 0's. This fixes it up. + fn fix_last_block(&mut self) { + let len = self.len(); + let extra_bits = len % u32::BITS; + if extra_bits > 0 { + let mask = (1 << extra_bits) - 1; + let storage_len = self.storage.len(); + self.storage[storage_len - 1] &= mask; } } @@ -226,61 +234,111 @@ impl Bitv { } /// Creates a `Bitv` that holds `nbits` elements, setting each element - /// to `init`. + /// to `bit`. /// /// # Examples /// /// ``` /// use std::collections::Bitv; /// - /// let mut bv = Bitv::with_capacity(10u, false); + /// let mut bv = Bitv::from_elem(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 { + pub fn from_elem(nbits: uint, bit: bool) -> Bitv { + let nblocks = blocks_for_bits(nbits); let mut bitv = Bitv { - storage: Vec::from_elem((nbits + u32::BITS - 1) / u32::BITS, - if init { !0u32 } else { 0u32 }), + storage: Vec::from_elem(nblocks, if bit { !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.fix_last_block(); + bitv + } + + /// Constructs a new, empty `Bitv` with the specified capacity. + /// + /// The bitvector will be able to hold at least `capacity` bits without + /// reallocating. If `capacity` is 0, it will not allocate. + /// + /// It is important to note that this function does not specify the + /// *length* of the returned bitvector, but only the *capacity*. + #[unstable = "matches collection reform specification, waiting for dust to settle"] + pub fn with_capacity(nbits: uint) -> Bitv { + Bitv { + storage: Vec::with_capacity(blocks_for_bits(nbits)), + nbits: 0, } + } - bitv + /// 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. + /// + /// # Examples + /// + /// ``` + /// 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 { + Bitv::from_fn(bytes.len() * 8, |i| { + let b = bytes[i / 8] as u32; + let offset = i % 8; + b >> (7 - offset) & 1 == 1 + }) } - /// Retrieves the value at index `i`. + /// Creates a `Bitv` of the specified length where the value at each + /// index is `f(index)`. /// - /// # Panics + /// # Examples /// - /// Panics if `i` is out of bounds. + /// ``` + /// use std::collections::Bitv; + /// + /// let bv = Bitv::from_fn(5, |i| { i % 2 == 0 }); + /// assert!(bv.eq_vec(&[true, false, true, false, true])); + /// ``` + pub fn from_fn(len: uint, mut f: F) -> Bitv where F: FnMut(uint) -> bool { + let mut bitv = Bitv::from_elem(len, false); + for i in range(0u, len) { + bitv.set(i, f(i)); + } + bitv + } + + /// Retrieves the value at index `i`, or `None` if the index is out of bounds. /// /// # Examples /// /// ``` - /// use std::collections::bitv; + /// use std::collections::Bitv; /// - /// let bv = bitv::from_bytes(&[0b01100000]); - /// assert_eq!(bv.get(0), false); - /// assert_eq!(bv.get(1), true); + /// let bv = Bitv::from_bytes(&[0b01100000]); + /// assert_eq!(bv.get(0), Some(false)); + /// assert_eq!(bv.get(1), Some(true)); + /// assert_eq!(bv.get(100), None); /// /// // Can also use array indexing /// assert_eq!(bv[1], true); /// ``` #[inline] - pub fn get(&self, i: uint) -> bool { + #[unstable = "panic semantics are likely to change in the future"] + pub fn get(&self, i: uint) -> Option { assert!(i < self.nbits); let w = i / u32::BITS; let b = i % u32::BITS; - let x = self.storage[w] & (1 << b); - x != 0 + self.storage.get(w).map(|block| + (block & (1 << b)) != 0 + ) } /// Sets the value of a bit at an index `i`. @@ -294,11 +352,12 @@ impl Bitv { /// ``` /// use std::collections::Bitv; /// - /// let mut bv = Bitv::with_capacity(5, false); + /// let mut bv = Bitv::from_elem(5, false); /// bv.set(3, true); /// assert_eq!(bv[3], true); /// ``` #[inline] + #[unstable = "panic semantics are likely to change in the future"] pub fn set(&mut self, i: uint, x: bool) { assert!(i < self.nbits); let w = i / u32::BITS; @@ -314,18 +373,19 @@ impl Bitv { /// # Examples /// /// ``` - /// use std::collections::bitv; + /// use std::collections::Bitv; /// /// let before = 0b01100000; /// let after = 0b11111111; /// - /// let mut bv = bitv::from_bytes(&[before]); + /// let mut bv = Bitv::from_bytes(&[before]); /// bv.set_all(); - /// assert_eq!(bv, bitv::from_bytes(&[after])); + /// assert_eq!(bv, Bitv::from_bytes(&[after])); /// ``` #[inline] pub fn set_all(&mut self) { for w in self.storage.iter_mut() { *w = !0u32; } + self.fix_last_block(); } /// Flips all bits. @@ -333,18 +393,19 @@ impl Bitv { /// # Examples /// /// ``` - /// use std::collections::bitv; + /// use std::collections::Bitv; /// /// let before = 0b01100000; /// let after = 0b10011111; /// - /// let mut bv = bitv::from_bytes(&[before]); + /// let mut bv = Bitv::from_bytes(&[before]); /// bv.negate(); - /// assert_eq!(bv, bitv::from_bytes(&[after])); + /// assert_eq!(bv, Bitv::from_bytes(&[after])); /// ``` #[inline] pub fn negate(&mut self) { for w in self.storage.iter_mut() { *w = !*w; } + self.fix_last_block(); } /// Calculates the union of two bitvectors. This acts like the bitwise `or` @@ -360,17 +421,17 @@ impl Bitv { /// # Examples /// /// ``` - /// use std::collections::bitv; + /// 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]); + /// let mut a = Bitv::from_bytes(&[a]); + /// let b = Bitv::from_bytes(&[b]); /// /// assert!(a.union(&b)); - /// assert_eq!(a, bitv::from_bytes(&[res])); + /// assert_eq!(a, Bitv::from_bytes(&[res])); /// ``` #[inline] pub fn union(&mut self, other: &Bitv) -> bool { @@ -390,17 +451,17 @@ impl Bitv { /// # Examples /// /// ``` - /// use std::collections::bitv; + /// 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]); + /// let mut a = Bitv::from_bytes(&[a]); + /// let b = Bitv::from_bytes(&[b]); /// /// assert!(a.intersect(&b)); - /// assert_eq!(a, bitv::from_bytes(&[res])); + /// assert_eq!(a, Bitv::from_bytes(&[res])); /// ``` #[inline] pub fn intersect(&mut self, other: &Bitv) -> bool { @@ -420,24 +481,24 @@ impl Bitv { /// # Examples /// /// ``` - /// use std::collections::bitv; + /// 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]); + /// 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])); + /// assert_eq!(bva, Bitv::from_bytes(&[a_b])); /// - /// let bva = bitv::from_bytes(&[a]); - /// let mut bvb = bitv::from_bytes(&[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])); + /// assert_eq!(bvb, Bitv::from_bytes(&[b_a])); /// ``` #[inline] pub fn difference(&mut self, other: &Bitv) -> bool { @@ -451,20 +512,21 @@ impl Bitv { /// ``` /// use std::collections::Bitv; /// - /// let mut bv = Bitv::with_capacity(5, true); + /// let mut bv = Bitv::from_elem(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) + // Check that every block but the last is all-ones... + self.blocks().all(|elem| { + let tmp = last_word; + last_word = elem; + tmp == !0u32 + // and then check the last one has enough ones + }) && (last_word == ((1 << self.nbits % u32::BITS) - 1) || last_word == !0u32) } /// Returns an iterator over the elements of the vector in order. @@ -472,12 +534,13 @@ impl Bitv { /// # Examples /// /// ``` - /// use std::collections::bitv; + /// use std::collections::Bitv; /// - /// let bv = bitv::from_bytes(&[0b01110100, 0b10010010]); + /// let bv = Bitv::from_bytes(&[0b01110100, 0b10010010]); /// assert_eq!(bv.iter().filter(|x| *x).count(), 7); /// ``` #[inline] + #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn iter<'a>(&'a self) -> Bits<'a> { Bits {bitv: self, next_idx: 0, end_idx: self.nbits} } @@ -489,14 +552,14 @@ impl Bitv { /// ``` /// use std::collections::Bitv; /// - /// let mut bv = Bitv::with_capacity(10, false); + /// let mut bv = Bitv::from_elem(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) + self.blocks().all(|w| w == 0) } /// Returns `true` if any bit is 1. @@ -506,7 +569,7 @@ impl Bitv { /// ``` /// use std::collections::Bitv; /// - /// let mut bv = Bitv::with_capacity(10, false); + /// let mut bv = Bitv::from_elem(10, false); /// assert_eq!(bv.any(), false); /// /// bv.set(3, true); @@ -527,12 +590,12 @@ impl Bitv { /// ``` /// use std::collections::Bitv; /// - /// let mut bv = Bitv::with_capacity(3, true); + /// let mut bv = Bitv::from_elem(3, true); /// bv.set(1, false); /// /// assert_eq!(bv.to_bytes(), vec!(0b10100000)); /// - /// let mut bv = Bitv::with_capacity(9, false); + /// let mut bv = Bitv::from_elem(9, false); /// bv.set(2, true); /// bv.set(8, true); /// @@ -544,7 +607,7 @@ impl Bitv { if offset >= bitv.nbits { 0 } else { - bitv.get(offset) as u8 << (7 - bit) + bitv[offset] as u8 << (7 - bit) } } @@ -562,19 +625,10 @@ impl Bitv { ) } - /// Transforms `self` into a `Vec` by turning each bit into a `bool`. - /// - /// # Examples - /// - /// ``` - /// use std::collections::bitv; - /// - /// let bv = bitv::from_bytes(&[0b10100000]); - /// assert_eq!(bv.to_bools(), vec!(true, false, true, false, - /// false, false, false, false)); - /// ``` + /// Deprecated: Use `iter().collect()`. + #[deprecated = "Use `iter().collect()`"] pub fn to_bools(&self) -> Vec { - Vec::from_fn(self.nbits, |i| self.get(i)) + Vec::from_fn(self.nbits, |i| self[i]) } /// Compares a `Bitv` to a slice of `bool`s. @@ -587,9 +641,9 @@ impl Bitv { /// # Examples /// /// ``` - /// use std::collections::bitv; + /// use std::collections::Bitv; /// - /// let bv = bitv::from_bytes(&[0b10100000]); + /// let bv = Bitv::from_bytes(&[0b10100000]); /// /// assert!(bv.eq_vec(&[true, false, true, false, /// false, false, false, false])); @@ -598,7 +652,7 @@ impl Bitv { assert_eq!(self.nbits, v.len()); let mut i = 0; while i < self.nbits { - if self.get(i) != v[i] { return false; } + if self[i] != v[i] { return false; } i = i + 1; } true @@ -612,9 +666,9 @@ impl Bitv { /// # Examples /// /// ``` - /// use std::collections::bitv; + /// use std::collections::Bitv; /// - /// let mut bv = bitv::from_bytes(&[0b01001011]); + /// let mut bv = Bitv::from_bytes(&[0b01001011]); /// bv.truncate(2); /// assert!(bv.eq_vec(&[false, true])); /// ``` @@ -622,32 +676,72 @@ impl Bitv { 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; + self.storage.truncate(blocks_for_bits(len)); + self.fix_last_block(); + } + } + + /// Reserves capacity for at least `additional` more bits to be inserted in the given + /// `Bitv`. The collection may reserve more space to avoid frequent reallocations. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `uint`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::Bitv; + /// + /// let mut bv = Bitv::from_elem(3, false); + /// bv.reserve(10); + /// assert_eq!(bv.len(), 3); + /// assert!(bv.capacity() >= 13); + /// ``` + #[unstable = "matches collection reform specification, waiting for dust to settle"] + pub fn reserve(&mut self, additional: uint) { + let desired_cap = self.len().checked_add(additional).expect("capacity overflow"); + match self.storage.len().checked_mul(u32::BITS) { + None => {} // Vec has more initialized capacity than we can ever use + Some(initialized_cap) => { + if desired_cap > initialized_cap { + self.storage.reserve(blocks_for_bits(desired_cap - initialized_cap)); + } } } } - /// Grows the vector to be able to store `size` bits without resizing. + /// Reserves the minimum capacity for exactly `additional` more bits to be inserted in the + /// given `Bitv`. Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it requests. Therefore + /// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future + /// insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `uint`. /// /// # Examples /// /// ``` /// use std::collections::Bitv; /// - /// let mut bv = Bitv::with_capacity(3, false); + /// let mut bv = Bitv::from_elem(3, false); /// bv.reserve(10); /// assert_eq!(bv.len(), 3); - /// assert!(bv.capacity() >= 10); + /// assert!(bv.capacity() >= 13); /// ``` - 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); + #[unstable = "matches collection reform specification, waiting for dust to settle"] + pub fn reserve_exact(&mut self, additional: uint) { + let desired_cap = self.len().checked_add(additional).expect("capacity overflow"); + match self.storage.len().checked_mul(u32::BITS) { + None => {} // Vec has more initialized capacity than we can ever use + Some(initialized_cap) => { + if desired_cap > initialized_cap { + self.storage.reserve_exact(blocks_for_bits(desired_cap - initialized_cap)); + } + } } } @@ -664,83 +758,89 @@ impl Bitv { /// assert!(bv.capacity() >= 10); /// ``` #[inline] + #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn capacity(&self) -> uint { - self.storage.len() * u32::BITS + self.storage.capacity().checked_mul(u32::BITS).unwrap_or(uint::MAX) } /// Grows the `Bitv` in-place, adding `n` copies of `value` to the `Bitv`. /// + /// # Panics + /// + /// Panics if the new len overflows a `uint`. + /// /// # Examples /// /// ``` - /// use std::collections::bitv; + /// use std::collections::Bitv; /// - /// let mut bv = bitv::from_bytes(&[0b01001011]); + /// 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; + // Note: we just bulk set all the bits in the last word in this fn in multiple places + // which is technically wrong if not all of these bits are to be used. However, at the end + // of this fn we call `fix_last_block` at the end of this fn, which should fix this. + + let new_nbits = self.nbits.checked_add(n).expect("capacity overflow"); + let new_nblocks = blocks_for_bits(new_nbits); 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; + let old_last_word = blocks_for_bits(self.nbits) - 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 + 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); + let stop_idx = cmp::min(self.storage.len(), new_nblocks); 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(); + if new_nblocks > self.storage.len() { + let to_add = new_nblocks - 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; + + self.fix_last_block(); } - /// Shortens by one element and returns the removed element. - /// - /// # Panics - /// - /// Assert if empty. + /// Removes the last bit from the Bitv, and returns it. Returns None if the Bitv is empty. /// /// # Examples /// /// ``` - /// use std::collections::bitv; + /// use std::collections::Bitv; /// - /// let mut bv = bitv::from_bytes(&[0b01001001]); - /// assert_eq!(bv.pop(), true); - /// assert_eq!(bv.pop(), false); + /// let mut bv = Bitv::from_bytes(&[0b01001001]); + /// assert_eq!(bv.pop(), Some(true)); + /// assert_eq!(bv.pop(), Some(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; + #[unstable = "matches collection reform specification, waiting for dust to settle"] + pub fn pop(&mut self) -> Option { + if self.is_empty() { + None + } else { + let ret = self[self.nbits - 1]; + // Second rule of Bitv Club + self.set(self.nbits - 1, false); + self.nbits -= 1; + Some(ret) } - self.nbits -= 1; - ret } /// Pushes a `bool` onto the end. @@ -755,10 +855,11 @@ impl Bitv { /// bv.push(false); /// assert!(bv.eq_vec(&[true, false])); /// ``` + #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn push(&mut self, elem: bool) { let insert_pos = self.nbits; - self.nbits += 1; - if self.storage.len() * u32::BITS < self.nbits { + self.nbits = self.nbits.checked_add(1).expect("Capacity overflow"); + if self.storage.len().checked_mul(u32::BITS).unwrap_or(uint::MAX) < self.nbits { self.storage.push(0); } self.set(insert_pos, elem); @@ -782,46 +883,16 @@ impl Bitv { } } -/// 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. -/// -/// # Examples -/// -/// ``` -/// 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])); -/// ``` +/// Deprecated: Now a static method on Bitv. +#[deprecated = "Now a static method on Bitv"] 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 - }) + Bitv::from_bytes(bytes) } -/// Creates a `Bitv` of the specified length where the value at each -/// index is `f(index)`. -/// -/// # Examples -/// -/// ``` -/// use std::collections::bitv::from_fn; -/// -/// let bv = from_fn(5, |i| { i % 2 == 0 }); -/// assert!(bv.eq_vec(&[true, false, true, false, true])); -/// ``` +/// Deprecated: Now a static method on Bitv. +#[deprecated = "Now a static method on Bitv"] pub fn from_fn(len: uint, mut f: F) -> Bitv where F: FnMut(uint) -> bool { - let mut bitv = Bitv::with_capacity(len, false); - for i in range(0u, len) { - bitv.set(i, f(i)); - } - bitv + Bitv::from_fn(len, f) } #[stable] @@ -843,8 +914,7 @@ impl Extend for Bitv { #[inline] fn extend>(&mut self, mut iterator: I) { let (min, _) = iterator.size_hint(); - let nbits = self.nbits; - self.reserve(nbits + min); + self.reserve(min); for element in iterator { self.push(element) } @@ -890,7 +960,7 @@ impl fmt::Show for Bitv { impl hash::Hash for Bitv { fn hash(&self, state: &mut S) { self.nbits.hash(state); - for (_, elem) in self.mask_words(0) { + for elem in self.blocks() { elem.hash(state); } } @@ -902,7 +972,7 @@ impl cmp::PartialEq for Bitv { if self.nbits != other.nbits { return false; } - self.mask_words(0).zip(other.mask_words(0)).all(|((_, w1), (_, w2))| w1 == w2) + self.blocks().zip(other.blocks()).all(|(w1, w2)| w1 == w2) } } @@ -921,7 +991,7 @@ impl<'a> Iterator for Bits<'a> { if self.next_idx != self.end_idx { let idx = self.next_idx; self.next_idx += 1; - Some(self.bitv.get(idx)) + Some(self.bitv[idx]) } else { None } @@ -938,7 +1008,7 @@ impl<'a> DoubleEndedIterator for Bits<'a> { fn next_back(&mut self) -> Option { if self.next_idx != self.end_idx { self.end_idx -= 1; - Some(self.bitv.get(self.end_idx)) + Some(self.bitv[self.end_idx]) } else { None } @@ -958,7 +1028,7 @@ impl<'a> RandomAccessIterator for Bits<'a> { if index >= self.indexable() { None } else { - Some(self.bitv.get(index)) + Some(self.bitv[index]) } } } @@ -974,7 +1044,6 @@ impl<'a> RandomAccessIterator for Bits<'a> { /// /// ``` /// use std::collections::{BitvSet, Bitv}; -/// use std::collections::bitv; /// /// // It's a regular set /// let mut s = BitvSet::new(); @@ -989,7 +1058,7 @@ impl<'a> RandomAccessIterator for Bits<'a> { /// } /// /// // Can initialize from a `Bitv` -/// let other = BitvSet::from_bitv(bitv::from_bytes(&[0b11010000])); +/// let other = BitvSet::from_bitv(Bitv::from_bytes(&[0b11010000])); /// /// s.union_with(&other); /// @@ -1000,10 +1069,12 @@ impl<'a> RandomAccessIterator for Bits<'a> { /// /// // Can convert back to a `Bitv` /// let bv: Bitv = s.into_bitv(); -/// assert!(bv.get(3)); +/// assert!(bv[3]); /// ``` #[deriving(Clone)] -pub struct BitvSet(Bitv); +pub struct BitvSet { + bitv: Bitv, +} impl Default for BitvSet { #[inline] @@ -1021,8 +1092,7 @@ impl FromIterator for BitvSet { impl Extend for BitvSet { #[inline] fn extend>(&mut self, iterator: I) { - let &BitvSet(ref mut self_bitv) = self; - self_bitv.extend(iterator); + self.bitv.extend(iterator); } } @@ -1053,45 +1123,47 @@ impl cmp::PartialEq for BitvSet { impl cmp::Eq for BitvSet {} impl BitvSet { - /// Creates a new bit vector set with initially no contents. + /// Creates a new empty `BitvSet`. /// /// # Examples /// /// ``` /// use std::collections::BitvSet; + /// /// let mut s = BitvSet::new(); /// ``` #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn new() -> BitvSet { - BitvSet(Bitv::new()) + BitvSet { bitv: Bitv::new() } } - /// Creates a new bit vector set with initially no contents, able to + /// Creates a new `BitvSet` with initially no contents, able to /// hold `nbits` elements without resizing. /// /// # Examples /// /// ``` /// use std::collections::BitvSet; + /// /// let mut s = BitvSet::with_capacity(100); /// assert!(s.capacity() >= 100); /// ``` #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn with_capacity(nbits: uint) -> BitvSet { - let bitv = Bitv::with_capacity(nbits, false); + let bitv = Bitv::from_elem(nbits, false); BitvSet::from_bitv(bitv) } - /// Creates a new bit vector set from the given bit vector. + /// Creates a new `BitvSet` from the given bit vector. /// /// # Examples /// /// ``` - /// use std::collections::{bitv, BitvSet}; + /// use std::collections::{Bitv, BitvSet}; /// - /// let bv = bitv::from_bytes(&[0b01100000]); + /// let bv = Bitv::from_bytes(&[0b01100000]); /// let s = BitvSet::from_bitv(bv); /// /// // Print 1, 2 in arbitrary order @@ -1100,10 +1172,8 @@ impl BitvSet { /// } /// ``` #[inline] - pub fn from_bitv(mut bitv: Bitv) -> BitvSet { - // Mark every bit as valid - bitv.nbits = bitv.capacity(); - BitvSet(bitv) + pub fn from_bitv(bitv: Bitv) -> BitvSet { + BitvSet { bitv: bitv } } /// Returns the capacity in bits for this bit vector. Inserting any @@ -1120,11 +1190,43 @@ impl BitvSet { #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn capacity(&self) -> uint { - let &BitvSet(ref bitv) = self; - bitv.capacity() + self.bitv.capacity() + } + + /// Reserves capacity for an element to be inserted at `index` in the given + /// `Bitv`. The collection may reserve more space to avoid frequent reallocations. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `uint`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::BitvSet; + /// + /// let mut s = BitvSet::new(); + /// s.reserve_index(10); + /// assert!(s.capacity() >= 11); + /// ``` + #[unstable = "matches collection reform specification, waiting for dust to settle"] + pub fn reserve_index(&mut self, index: uint) { + let len = self.bitv.len(); + if index >= len { + self.bitv.reserve(index - len + 1); + } } - /// Grows the underlying vector to be able to store `size` bits. + /// Reserves the minimum capacity for an element to be inserted at `index` + /// in the given `BitvSet`. Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it requests. Therefore + /// capacity can not be relied upon to be precisely minimal. Prefer `reserve_index` if future + /// insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `uint`. /// /// # Examples /// @@ -1132,17 +1234,18 @@ impl BitvSet { /// 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(); + /// s.reserve_index_exact(10); + /// assert!(s.capacity() >= 11); + /// ``` + #[unstable = "matches collection reform specification, waiting for dust to settle"] + pub fn reserve_index_exact(&mut self, index: uint) { + let len = self.bitv.len(); + if index >= len { + self.bitv.reserve_exact(index - len + 1); } } + /// Consumes this set to return the underlying bit vector. /// /// # Examples @@ -1155,13 +1258,12 @@ impl BitvSet { /// s.insert(3); /// /// let bv = s.into_bitv(); - /// assert!(bv.get(0)); - /// assert!(bv.get(3)); + /// assert!(bv[0]); + /// assert!(bv[3]); /// ``` #[inline] pub fn into_bitv(self) -> Bitv { - let BitvSet(bitv) = self; - bitv + self.bitv } /// Returns a reference to the underlying bit vector. @@ -1179,18 +1281,22 @@ impl BitvSet { /// ``` #[inline] pub fn get_ref<'a>(&'a self) -> &'a Bitv { - let &BitvSet(ref bitv) = self; - bitv + &self.bitv } #[inline] fn other_op(&mut self, other: &BitvSet, mut f: F) where F: FnMut(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; + let self_bitv = &mut self.bitv; + let other_bitv = &other.bitv; + + let self_len = self_bitv.len(); + let other_len = other_bitv.len(); + + // Expand the vector if necessary + if self_len < other_len { + self_bitv.grow(other_len - self_len, false); + } // virtually pad other with 0's for equal lengths let mut other_words = { @@ -1227,7 +1333,7 @@ impl BitvSet { #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn shrink_to_fit(&mut self) { - let &BitvSet(ref mut bitv) = self; + let bitv = &mut self.bitv; // Obtain original length let old_len = bitv.storage.len(); // Obtain coarse trailing zero length @@ -1243,10 +1349,9 @@ impl BitvSet { /// # Examples /// /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; + /// use std::collections::{Bitv, BitvSet}; /// - /// let s = BitvSet::from_bitv(bitv::from_bytes(&[0b01001010])); + /// let s = BitvSet::from_bitv(Bitv::from_bytes(&[0b01001010])); /// /// // Print 1, 4, 6 in arbitrary order /// for x in s.iter() { @@ -1265,11 +1370,10 @@ impl BitvSet { /// # Examples /// /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; + /// use std::collections::{Bitv, BitvSet}; /// - /// let a = BitvSet::from_bitv(bitv::from_bytes(&[0b01101000])); - /// let b = BitvSet::from_bitv(bitv::from_bytes(&[0b10100000])); + /// 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) { @@ -1296,11 +1400,10 @@ impl BitvSet { /// # Examples /// /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; + /// use std::collections::{Bitv, BitvSet}; /// - /// let a = BitvSet::from_bitv(bitv::from_bytes(&[0b01101000])); - /// let b = BitvSet::from_bitv(bitv::from_bytes(&[0b10100000])); + /// 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) { @@ -1311,8 +1414,7 @@ impl BitvSet { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn intersection<'a>(&'a self, other: &'a BitvSet) -> Take> { fn bitand(w1: u32, w2: u32) -> u32 { w1 & w2 } - - let min = cmp::min(self.capacity(), other.capacity()); + let min = cmp::min(self.bitv.len(), other.bitv.len()); TwoBitPositions { set: self, other: other, @@ -1328,11 +1430,10 @@ impl BitvSet { /// # Examples /// /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; + /// use std::collections::{BitvSet, Bitv}; /// - /// let a = BitvSet::from_bitv(bitv::from_bytes(&[0b01101000])); - /// let b = BitvSet::from_bitv(bitv::from_bytes(&[0b10100000])); + /// 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) { @@ -1367,11 +1468,10 @@ impl BitvSet { /// # Examples /// /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; + /// use std::collections::{BitvSet, Bitv}; /// - /// let a = BitvSet::from_bitv(bitv::from_bytes(&[0b01101000])); - /// let b = BitvSet::from_bitv(bitv::from_bytes(&[0b10100000])); + /// 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) { @@ -1397,16 +1497,15 @@ impl BitvSet { /// # Examples /// /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; + /// use std::collections::{BitvSet, 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])); + /// 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); @@ -1421,16 +1520,15 @@ impl BitvSet { /// # Examples /// /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; + /// use std::collections::{BitvSet, 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])); + /// 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); @@ -1446,24 +1544,23 @@ impl BitvSet { /// # Examples /// /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; + /// use std::collections::{BitvSet, 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])); + /// 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])); + /// 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); @@ -1479,16 +1576,15 @@ impl BitvSet { /// # Examples /// /// ``` - /// use std::collections::BitvSet; - /// use std::collections::bitv; + /// use std::collections::{BitvSet, 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])); + /// 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); @@ -1502,32 +1598,29 @@ impl BitvSet { #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn len(&self) -> uint { - let &BitvSet(ref bitv) = self; - bitv.storage.iter().fold(0, |acc, &n| acc + n.count_ones()) + self.bitv.blocks().fold(0, |acc, n| acc + n.count_ones()) } /// Returns whether there are no bits set in this set #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn is_empty(&self) -> bool { - let &BitvSet(ref bitv) = self; - bitv.storage.iter().all(|&n| n == 0) + self.bitv.none() } /// Clears all bits in this set #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn clear(&mut self) { - let &BitvSet(ref mut bitv) = self; - bitv.clear(); + self.bitv.clear(); } /// Returns `true` if this set contains the specified integer. #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn contains(&self, value: &uint) -> bool { - let &BitvSet(ref bitv) = self; - *value < bitv.nbits && bitv.get(*value) + let bitv = &self.bitv; + *value < bitv.nbits && bitv[*value] } /// Returns `true` if the set has no elements in common with `other`. @@ -1542,14 +1635,14 @@ impl BitvSet { #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn is_subset(&self, other: &BitvSet) -> bool { - let &BitvSet(ref self_bitv) = self; - let &BitvSet(ref other_bitv) = other; + let self_bitv = &self.bitv; + let other_bitv = &other.bitv; + let other_blocks = blocks_for_bits(other_bitv.len()); // 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) + self_bitv.blocks().zip(other_bitv.blocks()).all(|(w1, w2)| w1 & w2 == w1) && + // Make sure if `self` has any more blocks than `other`, they're all 0 + self_bitv.blocks().skip(other_blocks).all(|w| w == 0) } /// Returns `true` if the set is a superset of another. @@ -1568,13 +1661,12 @@ impl BitvSet { } // 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 len = self.bitv.len(); + if value >= len { + self.bitv.grow(value - len + 1, false) } - let &BitvSet(ref mut bitv) = self; - bitv.set(value, true); + self.bitv.set(value, true); return true; } @@ -1585,8 +1677,9 @@ impl BitvSet { if !self.contains(value) { return false; } - let &BitvSet(ref mut bitv) = self; - bitv.set(*value, false); + + self.bitv.set(*value, false); + return true; } } @@ -1631,7 +1724,7 @@ pub struct TwoBitPositions<'a> { impl<'a> Iterator for BitPositions<'a> { fn next(&mut self) -> Option { - while self.next_idx < self.set.capacity() { + while self.next_idx < self.set.bitv.len() { let idx = self.next_idx; self.next_idx += 1; @@ -1645,18 +1738,18 @@ impl<'a> Iterator for BitPositions<'a> { #[inline] fn size_hint(&self) -> (uint, Option) { - (0, Some(self.set.capacity() - self.next_idx)) + (0, Some(self.set.bitv.len() - 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() { + while self.next_idx < self.set.bitv.len() || + self.next_idx < self.other.bitv.len() { 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; + let s_bitv = &self.set.bitv; + let o_bitv = &self.other.bitv; // 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; @@ -1679,11 +1772,15 @@ impl<'a> Iterator for TwoBitPositions<'a> { #[inline] fn size_hint(&self) -> (uint, Option) { - let cap = cmp::max(self.set.capacity(), self.other.capacity()); + let cap = cmp::max(self.set.bitv.len(), self.other.bitv.len()); (0, Some(cap - self.next_idx)) } } + + + + #[cfg(test)] mod tests { use prelude::*; @@ -1696,14 +1793,12 @@ mod tests { use super::{Bitv, BitvSet, from_fn, from_bytes}; use bitv; - static BENCH_BITS : uint = 1 << 14; - #[test] fn test_to_str() { let zerolen = Bitv::new(); assert_eq!(zerolen.to_string(), ""); - let eightbits = Bitv::with_capacity(8u, false); + let eightbits = Bitv::from_elem(8u, false); assert_eq!(eightbits.to_string(), "00000000") } @@ -1716,15 +1811,15 @@ mod tests { #[test] fn test_1_element() { - let mut act = Bitv::with_capacity(1u, false); + let mut act = Bitv::from_elem(1u, false); assert!(act.eq_vec(&[false])); - act = Bitv::with_capacity(1u, true); + act = Bitv::from_elem(1u, true); assert!(act.eq_vec(&[true])); } #[test] fn test_2_elements() { - let mut b = bitv::Bitv::with_capacity(2, false); + let mut b = Bitv::from_elem(2, false); b.set(0, true); b.set(1, false); assert_eq!(b.to_string(), "10"); @@ -1735,16 +1830,16 @@ mod tests { let mut act; // all 0 - act = Bitv::with_capacity(10u, false); + act = Bitv::from_elem(10u, false); assert!((act.eq_vec( &[false, false, false, false, false, false, false, false, false, false]))); // all 1 - act = Bitv::with_capacity(10u, true); + act = Bitv::from_elem(10u, true); assert!((act.eq_vec(&[true, true, true, true, true, true, true, true, true, true]))); // mixed - act = Bitv::with_capacity(10u, false); + act = Bitv::from_elem(10u, false); act.set(0u, true); act.set(1u, true); act.set(2u, true); @@ -1753,7 +1848,7 @@ mod tests { assert!((act.eq_vec(&[true, true, true, true, true, false, false, false, false, false]))); // mixed - act = Bitv::with_capacity(10u, false); + act = Bitv::from_elem(10u, false); act.set(5u, true); act.set(6u, true); act.set(7u, true); @@ -1762,7 +1857,7 @@ mod tests { assert!((act.eq_vec(&[false, false, false, false, false, true, true, true, true, true]))); // mixed - act = Bitv::with_capacity(10u, false); + act = Bitv::from_elem(10u, false); act.set(0u, true); act.set(3u, true); act.set(6u, true); @@ -1775,21 +1870,21 @@ mod tests { let mut act; // all 0 - act = Bitv::with_capacity(31u, false); + act = Bitv::from_elem(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); + act = Bitv::from_elem(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 = Bitv::from_elem(31u, false); act.set(0u, true); act.set(1u, true); act.set(2u, true); @@ -1804,7 +1899,7 @@ mod tests { false, false, false, false, false, false, false])); // mixed - act = Bitv::with_capacity(31u, false); + act = Bitv::from_elem(31u, false); act.set(16u, true); act.set(17u, true); act.set(18u, true); @@ -1819,7 +1914,7 @@ mod tests { false, false, false, false, false, false, false])); // mixed - act = Bitv::with_capacity(31u, false); + act = Bitv::from_elem(31u, false); act.set(24u, true); act.set(25u, true); act.set(26u, true); @@ -1833,7 +1928,7 @@ mod tests { false, false, true, true, true, true, true, true, true])); // mixed - act = Bitv::with_capacity(31u, false); + act = Bitv::from_elem(31u, false); act.set(3u, true); act.set(17u, true); act.set(30u, true); @@ -1848,21 +1943,21 @@ mod tests { let mut act; // all 0 - act = Bitv::with_capacity(32u, false); + act = Bitv::from_elem(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); + act = Bitv::from_elem(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 = Bitv::from_elem(32u, false); act.set(0u, true); act.set(1u, true); act.set(2u, true); @@ -1877,7 +1972,7 @@ mod tests { false, false, false, false, false, false, false, false])); // mixed - act = Bitv::with_capacity(32u, false); + act = Bitv::from_elem(32u, false); act.set(16u, true); act.set(17u, true); act.set(18u, true); @@ -1892,7 +1987,7 @@ mod tests { false, false, false, false, false, false, false, false])); // mixed - act = Bitv::with_capacity(32u, false); + act = Bitv::from_elem(32u, false); act.set(24u, true); act.set(25u, true); act.set(26u, true); @@ -1907,7 +2002,7 @@ mod tests { false, false, true, true, true, true, true, true, true, true])); // mixed - act = Bitv::with_capacity(32u, false); + act = Bitv::from_elem(32u, false); act.set(3u, true); act.set(17u, true); act.set(30u, true); @@ -1923,21 +2018,21 @@ mod tests { let mut act; // all 0 - act = Bitv::with_capacity(33u, false); + act = Bitv::from_elem(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); + act = Bitv::from_elem(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 = Bitv::from_elem(33u, false); act.set(0u, true); act.set(1u, true); act.set(2u, true); @@ -1952,7 +2047,7 @@ mod tests { false, false, false, false, false, false, false, false, false])); // mixed - act = Bitv::with_capacity(33u, false); + act = Bitv::from_elem(33u, false); act.set(16u, true); act.set(17u, true); act.set(18u, true); @@ -1967,7 +2062,7 @@ mod tests { false, false, false, false, false, false, false, false, false])); // mixed - act = Bitv::with_capacity(33u, false); + act = Bitv::from_elem(33u, false); act.set(24u, true); act.set(25u, true); act.set(26u, true); @@ -1982,7 +2077,7 @@ mod tests { false, false, true, true, true, true, true, true, true, true, false])); // mixed - act = Bitv::with_capacity(33u, false); + act = Bitv::from_elem(33u, false); act.set(3u, true); act.set(17u, true); act.set(30u, true); @@ -1996,24 +2091,24 @@ mod tests { #[test] fn test_equal_differing_sizes() { - let v0 = Bitv::with_capacity(10u, false); - let v1 = Bitv::with_capacity(11u, false); + let v0 = Bitv::from_elem(10u, false); + let v1 = Bitv::from_elem(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); + let v0 = Bitv::from_elem(10u, false); + let v1 = Bitv::from_elem(110u, false); assert!(v0 != v1); } #[test] fn test_equal_sneaky_small() { - let mut a = bitv::Bitv::with_capacity(1, false); + let mut a = Bitv::from_elem(1, false); a.set(0, true); - let mut b = bitv::Bitv::with_capacity(1, true); + let mut b = Bitv::from_elem(1, true); b.set(0, true); assert_eq!(a, b); @@ -2021,12 +2116,12 @@ mod tests { #[test] fn test_equal_sneaky_big() { - let mut a = bitv::Bitv::with_capacity(100, false); + let mut a = Bitv::from_elem(100, false); for i in range(0u, 100) { a.set(i, true); } - let mut b = bitv::Bitv::with_capacity(100, true); + let mut b = Bitv::from_elem(100, true); for i in range(0u, 100) { b.set(i, true); } @@ -2036,18 +2131,18 @@ mod tests { #[test] fn test_from_bytes() { - let bitv = from_bytes(&[0b10110110, 0b00000000, 0b11111111]); + let bitv = Bitv::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); let str = concat!("10110110", "00000000", "11111111"); assert_eq!(bitv.to_string(), str); } #[test] fn test_to_bytes() { - let mut bv = Bitv::with_capacity(3, true); + let mut bv = Bitv::from_elem(3, true); bv.set(1, false); assert_eq!(bv.to_bytes(), vec!(0b10100000)); - let mut bv = Bitv::with_capacity(9, false); + let mut bv = Bitv::from_elem(9, false); bv.set(2, true); bv.set(8, true); assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000)); @@ -2060,21 +2155,10 @@ mod tests { assert_eq!(bitv.to_string(), "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); + assert_eq!(Bitv::from_bytes(&[0b00100110]).iter().collect::>(), bools); } #[test] @@ -2120,107 +2204,436 @@ mod tests { #[test] fn test_small_difference() { - let mut b1 = Bitv::with_capacity(3, false); - let mut b2 = Bitv::with_capacity(3, false); + let mut b1 = Bitv::from_elem(3, false); + let mut b2 = Bitv::from_elem(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)); + assert!(b1[0]); + assert!(!b1[1]); + assert!(!b1[2]); } #[test] fn test_big_difference() { - let mut b1 = Bitv::with_capacity(100, false); - let mut b2 = Bitv::with_capacity(100, false); + let mut b1 = Bitv::from_elem(100, false); + let mut b2 = Bitv::from_elem(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)); + assert!(b1[0]); + assert!(!b1[40]); + assert!(!b1[80]); } #[test] fn test_small_clear() { - let mut b = Bitv::with_capacity(14, true); + let mut b = Bitv::from_elem(14, true); b.clear(); assert!(b.none()); } #[test] fn test_big_clear() { - let mut b = Bitv::with_capacity(140, true); + let mut b = Bitv::from_elem(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)); + fn test_bitv_lt() { + let mut a = Bitv::from_elem(5u, false); + let mut b = Bitv::from_elem(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_bitv_set_basic() { - // calculate nbits with u32::BITS granularity - fn calc_nbits(bits: uint) -> uint { - u32::BITS * ((bits + u32::BITS - 1) / u32::BITS) - } + fn test_ord() { + let mut a = Bitv::from_elem(5u, false); + let mut b = Bitv::from_elem(5u, false); - 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); + 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_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)); + #[test] + fn test_small_bitv_tests() { + let v = Bitv::from_bytes(&[0]); + assert!(!v.all()); + assert!(!v.any()); + assert!(v.none()); - assert!(b.insert(2)); - assert!(b.insert(11)); - assert!(b.insert(77)); - assert!(b.insert(5)); - assert!(b.insert(3)); + let v = Bitv::from_bytes(&[0b00010100]); + assert!(!v.all()); + assert!(v.any()); + assert!(!v.none()); - let expected = [3, 5, 11, 77]; - let actual = a.intersection(&b).collect::>(); - assert_eq!(actual, expected); + let v = Bitv::from_bytes(&[0xFF]); + assert!(v.all()); + assert!(v.any()); + assert!(!v.none()); } #[test] - fn test_bitv_set_difference() { + fn test_big_bitv_tests() { + let v = Bitv::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 = Bitv::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 = Bitv::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::from_elem(5 * u32::BITS - 2, false); + assert_eq!(s.len(), 5 * u32::BITS - 2); + assert_eq!(s[5 * u32::BITS - 3], false); + s.push(true); + s.push(true); + assert_eq!(s[5 * u32::BITS - 2], true); + assert_eq!(s[5 * u32::BITS - 1], true); + // Here the internal vector will need to be extended + s.push(false); + assert_eq!(s[5 * u32::BITS], false); + s.push(false); + assert_eq!(s[5 * u32::BITS + 1], false); + assert_eq!(s.len(), 5 * u32::BITS + 2); + // Pop it all off + assert_eq!(s.pop(), Some(false)); + assert_eq!(s.pop(), Some(false)); + assert_eq!(s.pop(), Some(true)); + assert_eq!(s.pop(), Some(true)); + assert_eq!(s.len(), 5 * u32::BITS - 2); + } + + #[test] + fn test_bitv_truncate() { + let mut s = Bitv::from_elem(5 * u32::BITS, true); + + assert_eq!(s, Bitv::from_elem(5 * u32::BITS, true)); + assert_eq!(s.len(), 5 * u32::BITS); + s.truncate(4 * u32::BITS); + assert_eq!(s, Bitv::from_elem(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::from_elem(4 * u32::BITS, true)); + assert_eq!(s.len(), 4 * u32::BITS); + s.truncate(3 * u32::BITS - 10); + assert_eq!(s, Bitv::from_elem(3 * u32::BITS - 10, true)); + assert_eq!(s.len(), 3 * u32::BITS - 10); + s.truncate(0); + assert_eq!(s, Bitv::from_elem(0, true)); + assert_eq!(s.len(), 0); + } + + #[test] + fn test_bitv_reserve() { + let mut s = Bitv::from_elem(5 * u32::BITS, true); + // Check capacity + assert!(s.capacity() >= 5 * u32::BITS); + s.reserve(2 * u32::BITS); + assert!(s.capacity() >= 7 * u32::BITS); + s.reserve(7 * u32::BITS); + assert!(s.capacity() >= 12 * u32::BITS); + s.reserve_exact(7 * u32::BITS); + assert!(s.capacity() >= 12 * u32::BITS); + s.reserve(7 * u32::BITS + 1); + assert!(s.capacity() >= 12 * u32::BITS + 1); + // 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[5 * u32::BITS - 1], true); + assert_eq!(s[5 * u32::BITS - 0], true); + assert_eq!(s[5 * u32::BITS + 1], false); + assert_eq!(s[5 * u32::BITS + 2], true); + } + + #[test] + fn test_bitv_grow() { + let mut bitv = Bitv::from_bytes(&[0b10110110, 0b00000000, 0b10101010]); + bitv.grow(32, true); + assert_eq!(bitv, Bitv::from_bytes(&[0b10110110, 0b00000000, 0b10101010, + 0xFF, 0xFF, 0xFF, 0xFF])); + bitv.grow(64, false); + assert_eq!(bitv, 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, 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 = Bitv::from_bytes(&[0b10110110, 0b00000000, 0b11111111]); + let ext = Bitv::from_bytes(&[0b01001001, 0b10010010, 0b10111101]); + bitv.extend(ext.iter()); + assert_eq!(bitv, Bitv::from_bytes(&[0b10110110, 0b00000000, 0b11111111, + 0b01001001, 0b10010010, 0b10111101])); + } +} + + + + +#[cfg(test)] +mod bitv_bench { + use std::prelude::*; + use std::rand; + use std::rand::Rng; + use std::u32; + use test::{Bencher, black_box}; + + use super::Bitv; + + static BENCH_BITS : uint = 1 << 14; + + 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); + } + black_box(&bitv) + }); + } + + #[bench] + fn bench_bitv_set_big_fixed(b: &mut Bencher) { + let mut r = rng(); + let mut bitv = Bitv::from_elem(BENCH_BITS, false); + b.iter(|| { + for _ in range(0u, 100) { + bitv.set((r.next_u32() as uint) % BENCH_BITS, true); + } + black_box(&bitv) + }); + } + + #[bench] + fn bench_bitv_set_big_variable(b: &mut Bencher) { + let mut r = rng(); + let mut bitv = Bitv::from_elem(BENCH_BITS, false); + b.iter(|| { + for _ in range(0u, 100) { + bitv.set((r.next_u32() as uint) % BENCH_BITS, r.gen()); + } + black_box(&bitv); + }); + } + + #[bench] + fn bench_bitv_set_small(b: &mut Bencher) { + let mut r = rng(); + let mut bitv = Bitv::from_elem(u32::BITS, false); + b.iter(|| { + for _ in range(0u, 100) { + bitv.set((r.next_u32() as uint) % u32::BITS, true); + } + black_box(&bitv); + }); + } + + #[bench] + fn bench_bitv_big_union(b: &mut Bencher) { + let mut b1 = Bitv::from_elem(BENCH_BITS, false); + let b2 = Bitv::from_elem(BENCH_BITS, false); + b.iter(|| { + b1.union(&b2) + }) + } + + #[bench] + fn bench_bitv_small_iter(b: &mut Bencher) { + let bitv = Bitv::from_elem(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::from_elem(BENCH_BITS, false); + b.iter(|| { + let mut sum = 0u; + for pres in bitv.iter() { + sum += pres as uint; + } + sum + }) + } +} + + + + + + + +#[cfg(test)] +mod bitv_set_test { + use std::prelude::*; + use std::iter::range_step; + + use super::{Bitv, BitvSet}; + use vec::Vec; + + #[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}", s.to_string()); + } + + #[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_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::from_elem(l, b)); + assert_eq!(bitset.contains(&1u), b) + assert_eq!(bitset.contains(&(l-1u)), b) + assert!(!bitset.contains(&l)) + } + } + } + + #[test] + fn test_bitv_masking() { + let b = Bitv::from_elem(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() { + let mut b = BitvSet::new(); + assert!(b.insert(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!(!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, expected); + } + + #[test] + fn test_bitv_set_difference() { let mut a = BitvSet::new(); let mut b = BitvSet::new(); @@ -2312,10 +2725,10 @@ mod tests { #[test] fn test_bitv_set_is_disjoint() { - let a = BitvSet::from_bitv(from_bytes(&[0b10100010])); - let b = BitvSet::from_bitv(from_bytes(&[0b01000000])); + let a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010])); + let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b01000000])); let c = BitvSet::new(); - let d = BitvSet::from_bitv(from_bytes(&[0b00110000])); + let d = BitvSet::from_bitv(Bitv::from_bytes(&[0b00110000])); assert!(!a.is_disjoint(&d)); assert!(!d.is_disjoint(&a)); @@ -2335,13 +2748,13 @@ mod tests { a.insert(0); let mut b = BitvSet::new(); b.insert(5); - let expected = BitvSet::from_bitv(from_bytes(&[0b10000100])); + let expected = BitvSet::from_bitv(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 mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010])); + let mut b = BitvSet::from_bitv(Bitv::from_bytes(&[0b01100010])); let c = a.clone(); a.union_with(&b); b.union_with(&c); @@ -2352,8 +2765,8 @@ mod tests { #[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 mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010])); + let mut b = BitvSet::from_bitv(Bitv::from_bytes(&[0b00000000])); let c = a.clone(); a.intersect_with(&b); b.intersect_with(&c); @@ -2361,7 +2774,7 @@ mod tests { assert!(b.is_empty()); // Uninitialized bits should behave like 0's - let mut a = BitvSet::from_bitv(from_bytes(&[0b10100010])); + let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010])); let mut b = BitvSet::new(); let c = a.clone(); a.intersect_with(&b); @@ -2370,8 +2783,8 @@ mod tests { assert!(b.is_empty()); // Standard - let mut a = BitvSet::from_bitv(from_bytes(&[0b10100010])); - let mut b = BitvSet::from_bitv(from_bytes(&[0b01100010])); + let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010])); + let mut b = BitvSet::from_bitv(Bitv::from_bytes(&[0b01100010])); let c = a.clone(); a.intersect_with(&b); b.intersect_with(&c); @@ -2382,20 +2795,20 @@ mod tests { #[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])); + let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b00000000])); + let b = BitvSet::from_bitv(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])); + let b = BitvSet::from_bitv(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 mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010])); + let mut b = BitvSet::from_bitv(Bitv::from_bytes(&[0b01100010])); let c = a.clone(); a.difference_with(&b); b.difference_with(&c); @@ -2412,19 +2825,19 @@ mod tests { let mut b = BitvSet::new(); b.insert(1); b.insert(5); - let expected = BitvSet::from_bitv(from_bytes(&[0b10000100])); + let expected = BitvSet::from_bitv(Bitv::from_bytes(&[0b10000100])); a.symmetric_difference_with(&b); assert_eq!(a, expected); - let mut a = BitvSet::from_bitv(from_bytes(&[0b10100010])); + let mut a = BitvSet::from_bitv(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 mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b11100010])); + let mut b = BitvSet::from_bitv(Bitv::from_bytes(&[0b01101010])); let c = a.clone(); a.symmetric_difference_with(&b); b.symmetric_difference_with(&c); @@ -2434,8 +2847,8 @@ mod tests { #[test] fn test_bitv_set_eq() { - let a = BitvSet::from_bitv(from_bytes(&[0b10100010])); - let b = BitvSet::from_bitv(from_bytes(&[0b00000000])); + let a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010])); + let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b00000000])); let c = BitvSet::new(); assert!(a == a); @@ -2448,8 +2861,8 @@ mod tests { #[test] fn test_bitv_set_cmp() { - let a = BitvSet::from_bitv(from_bytes(&[0b10100010])); - let b = BitvSet::from_bitv(from_bytes(&[0b00000000])); + let a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010])); + let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b00000000])); let c = BitvSet::new(); assert_eq!(a.cmp(&b), Greater); @@ -2473,38 +2886,6 @@ mod tests { 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] @@ -2525,206 +2906,29 @@ mod tests { 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); - } +#[cfg(test)] +mod bitv_set_bench { + use std::prelude::*; + use std::rand; + use std::rand::Rng; + use std::u32; + use test::{Bencher, black_box}; - #[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])); - } + use super::{Bitv, BitvSet}; - #[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}", s.to_string()); - } + static BENCH_BITS : uint = 1 << 14; 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); - } - black_box(&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); - } - black_box(&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()); - } - black_box(&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); - } - black_box(&bitv); - }); - } - #[bench] fn bench_bitvset_small(b: &mut Bencher) { let mut r = rng(); @@ -2749,44 +2953,9 @@ mod tests { }); } - #[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, + let bitv = BitvSet::from_bitv(Bitv::from_fn(BENCH_BITS, |idx| {idx % 3 == 0})); b.iter(|| { let mut sum = 0u; diff --git a/src/test/run-pass/bitv-perf-test.rs b/src/test/run-pass/bitv-perf-test.rs index 281167ff46c86..c5f69f249db6b 100644 --- a/src/test/run-pass/bitv-perf-test.rs +++ b/src/test/run-pass/bitv-perf-test.rs @@ -13,8 +13,8 @@ extern crate collections; use std::collections::Bitv; fn bitv_test() { - let mut v1 = box Bitv::with_capacity(31, false); - let v2 = box Bitv::with_capacity(31, true); + let mut v1 = box Bitv::from_elem(31, false); + let v2 = box Bitv::from_elem(31, true); v1.union(&*v2); } diff --git a/src/test/run-pass/issue-11736.rs b/src/test/run-pass/issue-11736.rs index 912a62b5b0f6a..bc4ceb38de33c 100644 --- a/src/test/run-pass/issue-11736.rs +++ b/src/test/run-pass/issue-11736.rs @@ -16,7 +16,7 @@ use std::num::Float; fn main() { // Generate sieve of Eratosthenes for n up to 1e6 let n = 1000000u; - let mut sieve = Bitv::with_capacity(n+1, true); + let mut sieve = Bitv::from_elem(n+1, true); let limit: uint = (n as f32).sqrt() as uint; for i in range(2, limit+1) { if sieve[i] { From 8f194de95d00fe540d848cc9a7d3e049ce3684ab Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 9 Dec 2014 21:47:10 -0800 Subject: [PATCH 2/6] bitv: correct build failures - Fix typos on Blocks and MutBlocks. - Use slice_to_mut() for creating blocks_mut(). - Deref the block parameter in get(). - Access nbits separately from mutating set in pop(). --- src/libcollections/bit.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 41a5ccb7a0645..9ea7d52b7c6fb 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -87,8 +87,8 @@ use std::hash; use vec::Vec; -type Blocks<'a> = Cloned> -type MutBlocks<'a> MutItems<'a, u32>; +type Blocks<'a> = Cloned>; +type MutBlocks<'a> = MutItems<'a, u32>; type MatchWords<'a> = Chain>, Skip>>>>; // Take two BitV's, and return iterators of their words, where the shorter one @@ -199,7 +199,7 @@ impl Bitv { /// Iterator over mutable refs to the underlying blocks of data. fn blocks_mut(&mut self) -> MutBlocks { let blocks = blocks_for_bits(self.len()); - self.storage[..blocks].iter_mut() + self.storage.slice_to_mut(blocks).iter_mut() } /// Iterator over the underlying blocks of data @@ -336,7 +336,7 @@ impl Bitv { assert!(i < self.nbits); let w = i / u32::BITS; let b = i % u32::BITS; - self.storage.get(w).map(|block| + self.storage.get(w).map(|&block| (block & (1 << b)) != 0 ) } @@ -835,10 +835,11 @@ impl Bitv { if self.is_empty() { None } else { - let ret = self[self.nbits - 1]; + let i = self.nbits - 1; + let ret = self[i]; // Second rule of Bitv Club - self.set(self.nbits - 1, false); - self.nbits -= 1; + self.set(i, false); + self.nbits = i; Some(ret) } } From 3deb97f5d02ddbdbf20a587815fe84934cda948c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 9 Dec 2014 22:06:52 -0800 Subject: [PATCH 3/6] bitv: Fix all() for nbits that are multiples of u32::BITS The old logic would be ok with *either* 0 or all 1s in the last word, because it didn't compute a proper mask for the case where nbits is an exact multiple of u32::BITS. Add mask_for_bits() to compute this properly, and use it in all(). Add all/none assertions to most of the tests. Note in particular, the all-zero bitv in test_32_elements() was incorrectly all()==true before this patch. --- src/libcollections/bit.rs | 51 +++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 9ea7d52b7c6fb..5cf5183d25d5e 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -174,6 +174,12 @@ fn blocks_for_bits(bits: uint) -> uint { } +/// Computes the bitmask for the final word of the vector +fn mask_for_bits(bits: uint) -> u32 { + // Note especially that a perfect multiple of u32::BITS should mask all 1s. + !0u32 >> (u32::BITS - bits % u32::BITS) % u32::BITS +} + impl Bitv { /// Applies the given operation to the blocks of self and other, and sets self to /// be the result. @@ -526,7 +532,7 @@ impl Bitv { last_word = elem; tmp == !0u32 // and then check the last one has enough ones - }) && (last_word == ((1 << self.nbits % u32::BITS) - 1) || last_word == !0u32) + }) && (last_word == mask_for_bits(self.nbits)) } /// Returns an iterator over the elements of the vector in order. @@ -788,15 +794,15 @@ impl Bitv { let new_nblocks = blocks_for_bits(new_nbits); let full_value = if value { !0 } else { 0 }; - // Correct the old tail word + // Correct the old tail word, setting or clearing formerly unused bits let old_last_word = blocks_for_bits(self.nbits) - 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 + let mask = mask_for_bits(self.nbits); if value { - self.storage[old_last_word] |= mask; + self.storage[old_last_word] |= !mask; } else { - self.storage[old_last_word] &= !mask; + // Extra bits are already supposed to be zero by invariant, but play it safe... + self.storage[old_last_word] &= mask; } } @@ -1808,14 +1814,17 @@ mod tests { let act = Bitv::new(); let exp = Vec::from_elem(0u, false); assert!(act.eq_vec(exp.as_slice())); + assert!(act.none() && act.all()); } #[test] fn test_1_element() { let mut act = Bitv::from_elem(1u, false); assert!(act.eq_vec(&[false])); + assert!(act.none() && !act.all()); act = Bitv::from_elem(1u, true); assert!(act.eq_vec(&[true])); + assert!(!act.none() && act.all()); } #[test] @@ -1824,6 +1833,7 @@ mod tests { b.set(0, true); b.set(1, false); assert_eq!(b.to_string(), "10"); + assert!(!b.none() && !b.all()); } #[test] @@ -1834,10 +1844,12 @@ mod tests { act = Bitv::from_elem(10u, false); assert!((act.eq_vec( &[false, false, false, false, false, false, false, false, false, false]))); + assert!(act.none() && !act.all()); // all 1 act = Bitv::from_elem(10u, true); assert!((act.eq_vec(&[true, true, true, true, true, true, true, true, true, true]))); + assert!(!act.none() && act.all()); // mixed act = Bitv::from_elem(10u, false); @@ -1847,6 +1859,7 @@ mod tests { act.set(3u, true); act.set(4u, true); assert!((act.eq_vec(&[true, true, true, true, true, false, false, false, false, false]))); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(10u, false); @@ -1856,6 +1869,7 @@ mod tests { act.set(8u, true); act.set(9u, true); assert!((act.eq_vec(&[false, false, false, false, false, true, true, true, true, true]))); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(10u, false); @@ -1864,6 +1878,7 @@ mod tests { act.set(6u, true); act.set(9u, true); assert!((act.eq_vec(&[true, false, false, true, false, false, true, false, false, true]))); + assert!(!act.none() && !act.all()); } #[test] @@ -1876,6 +1891,7 @@ mod tests { &[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])); + assert!(act.none() && !act.all()); // all 1 act = Bitv::from_elem(31u, true); @@ -1883,6 +1899,7 @@ mod tests { &[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])); + assert!(!act.none() && act.all()); // mixed act = Bitv::from_elem(31u, false); @@ -1898,6 +1915,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(31u, false); @@ -1913,6 +1931,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(31u, false); @@ -1927,6 +1946,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(31u, false); @@ -1937,6 +1957,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); } #[test] @@ -1949,6 +1970,7 @@ mod tests { &[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])); + assert!(act.none() && !act.all()); // all 1 act = Bitv::from_elem(32u, true); @@ -1956,6 +1978,7 @@ mod tests { &[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])); + assert!(!act.none() && act.all()); // mixed act = Bitv::from_elem(32u, false); @@ -1971,6 +1994,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(32u, false); @@ -1986,6 +2010,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(32u, false); @@ -2001,6 +2026,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(32u, false); @@ -2012,6 +2038,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); } #[test] @@ -2024,6 +2051,7 @@ mod tests { &[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])); + assert!(act.none() && !act.all()); // all 1 act = Bitv::from_elem(33u, true); @@ -2031,6 +2059,7 @@ mod tests { &[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])); + assert!(!act.none() && act.all()); // mixed act = Bitv::from_elem(33u, false); @@ -2046,6 +2075,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(33u, false); @@ -2061,6 +2091,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(33u, false); @@ -2076,6 +2107,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); // mixed act = Bitv::from_elem(33u, false); @@ -2088,6 +2120,7 @@ mod tests { &[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])); + assert!(!act.none() && !act.all()); } #[test] @@ -2234,15 +2267,17 @@ mod tests { #[test] fn test_small_clear() { let mut b = Bitv::from_elem(14, true); + assert!(!b.none() && b.all()); b.clear(); - assert!(b.none()); + assert!(b.none() && !b.all()); } #[test] fn test_big_clear() { let mut b = Bitv::from_elem(140, true); + assert!(!b.none() && b.all()); b.clear(); - assert!(b.none()); + assert!(b.none() && !b.all()); } #[test] From e84a3833077825893b5bf0fb5abf07bdbd58d988 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Sat, 13 Dec 2014 02:13:06 +0100 Subject: [PATCH 4/6] Add a new invariant to `Bitv` The length of the underlying vector must now be exactly as long as it needs to be. --- src/libcollections/bit.rs | 154 +++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 70 deletions(-) diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 5cf5183d25d5e..3f33d85ba569e 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -8,18 +8,25 @@ // 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. - -// First rule of Bitv club: almost everything can actually overflow because we're working with -// bits and not bytes. -// -// Second rule of Bitv club: the last "block" of bits may be partially used. We must ensure that -// those unused bits are zeroed out, as other methods will assume this is the case. It may be -// the case that this isn't a great design, but having "undefined" bits is headache-inducing. -// -// Third rule of Bitv club: BitvSet is fairly tightly coupled to Bitv's implementation details. -// Make sure any changes to Bitv are properly addressed in BitvSet. +// 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. This will be hard for performance though, because +// `Bitv` will not want to leak its internal representation while its internal +// representation as `u32`s must be assumed for best performance. + +// FIXME(tbu-): `Bitv`'s methods shouldn't be `union`, `intersection`, but +// rather `or` and `and`. + +// (1) Be careful, most things can overflow here because the amount of bits in +// memory can overflow `uint`. +// (2) Make sure that the underlying vector has no excess length: +// E. g. `nbits == 16`, `storage.len() == 2` would be excess length, +// because the last word isn't used at all. This is important because some +// methods rely on it (for *CORRECTNESS*). +// (3) Make sure that the unused bits in the last word are zeroed out, again +// other methods rely on it for *CORRECTNESS*. +// (4) `BitvSet` is tightly coupled with `Bitv`, so any changes you make in +// `Bitv` will need to be reflected in `BitvSet`. //! Collections implemented with bit vectors. //! @@ -82,10 +89,10 @@ use core::iter::{Cloned, Chain, Enumerate, Repeat, Skip, Take}; use core::iter; use core::num::Int; use core::slice::{Items, MutItems}; -use core::{u32, uint}; -use std::hash; +use core::{u8, u32, uint}; -use vec::Vec; +use hash; +use Vec; type Blocks<'a> = Cloned>; type MutBlocks<'a> = MutItems<'a, u32>; @@ -181,17 +188,15 @@ fn mask_for_bits(bits: uint) -> u32 { } impl Bitv { - /// Applies the given operation to the blocks of self and other, and sets self to - /// be the result. + /// Applies the given operation to the blocks of self and other, and sets + /// self to be the result. This relies on the caller not to corrupt the + /// last word. #[inline] fn process(&mut self, other: &Bitv, mut op: F) -> bool where F: FnMut(u32, u32) -> u32 { - let len = other.storage.len(); - assert_eq!(self.storage.len(), len); + assert_eq!(self.len(), other.len()); + // This could theoretically be a `debug_assert!`. + assert_eq!(self.storage.len(), other.storage.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.blocks_mut().zip(other.blocks()) { let w = op(*a, b); if *a != w { @@ -204,21 +209,20 @@ impl Bitv { /// Iterator over mutable refs to the underlying blocks of data. fn blocks_mut(&mut self) -> MutBlocks { - let blocks = blocks_for_bits(self.len()); - self.storage.slice_to_mut(blocks).iter_mut() + // (2) + self.storage.iter_mut() } /// Iterator over the underlying blocks of data fn blocks(&self) -> Blocks { - let blocks = blocks_for_bits(self.len()); - self.storage[..blocks].iter().cloned() + // (2) + self.storage.iter().cloned() } - /// An operation might screw up the unused bits in the last block of the Bitv. - /// It's assumed to be all 0's. This fixes it up. + /// An operation might screw up the unused bits in the last block of the + /// `Bitv`. As per (3), it's assumed to be all 0s. This method fixes it up. fn fix_last_block(&mut self) { - let len = self.len(); - let extra_bits = len % u32::BITS; + let extra_bits = self.len() % u32::BITS; if extra_bits > 0 { let mask = (1 << extra_bits) - 1; let storage_len = self.storage.len(); @@ -259,7 +263,6 @@ impl Bitv { storage: Vec::from_elem(nblocks, if bit { !0u32 } else { 0u32 }), nbits: nbits }; - bitv.fix_last_block(); bitv } @@ -295,15 +298,33 @@ impl Bitv { /// false, false, true, false])); /// ``` pub fn from_bytes(bytes: &[u8]) -> Bitv { - Bitv::from_fn(bytes.len() * 8, |i| { - let b = bytes[i / 8] as u32; - let offset = i % 8; - b >> (7 - offset) & 1 == 1 - }) + let len = bytes.len().checked_mul(u8::BITS).expect("capacity overflow"); + let mut bitv = Bitv::with_capacity(len); + let complete_words = bytes.len() / 4; + let extra_bytes = bytes.len() % 4; + + for i in range(0, complete_words) { + bitv.storage.push( + (bytes[i * 4 + 0] as u32 << 0) | + (bytes[i * 4 + 1] as u32 << 8) | + (bytes[i * 4 + 2] as u32 << 16) | + (bytes[i * 4 + 3] as u32 << 24) + ); + } + + if extra_bytes > 0 { + let mut last_word = 0u32; + for (i, &byte) in bytes[complete_words*4..].iter().enumerate() { + last_word |= byte as u32 << (i * 8); + } + bitv.storage.push(last_word); + } + + bitv } - /// Creates a `Bitv` of the specified length where the value at each - /// index is `f(index)`. + /// Creates a `Bitv` of the specified length where the value at each index + /// is `f(index)`. /// /// # Examples /// @@ -339,7 +360,9 @@ impl Bitv { #[inline] #[unstable = "panic semantics are likely to change in the future"] pub fn get(&self, i: uint) -> Option { - assert!(i < self.nbits); + if i >= self.nbits { + return None; + } let w = i / u32::BITS; let b = i % u32::BITS; self.storage.get(w).map(|&block| @@ -548,7 +571,7 @@ impl Bitv { #[inline] #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn iter<'a>(&'a self) -> Bits<'a> { - Bits {bitv: self, next_idx: 0, end_idx: self.nbits} + Bits { bitv: self, next_idx: 0, end_idx: self.nbits } } /// Returns `true` if all bits are 0. @@ -608,7 +631,7 @@ impl Bitv { /// assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000)); /// ``` pub fn to_bytes(&self) -> Vec { - fn bit (bitv: &Bitv, byte: uint, bit: uint) -> u8 { + fn bit(bitv: &Bitv, byte: uint, bit: uint) -> u8 { let offset = byte * 8 + bit; if offset >= bitv.nbits { 0 @@ -634,7 +657,7 @@ impl Bitv { /// Deprecated: Use `iter().collect()`. #[deprecated = "Use `iter().collect()`"] pub fn to_bools(&self) -> Vec { - Vec::from_fn(self.nbits, |i| self[i]) + self.iter().collect() } /// Compares a `Bitv` to a slice of `bool`s. @@ -656,12 +679,7 @@ impl Bitv { /// ``` pub fn eq_vec(&self, v: &[bool]) -> bool { assert_eq!(self.nbits, v.len()); - let mut i = 0; - while i < self.nbits { - if self[i] != v[i] { return false; } - i = i + 1; - } - true + iter::order::eq(self.iter(), v.iter().cloned()) } /// Shortens a `Bitv`, dropping excess elements. @@ -682,6 +700,7 @@ impl Bitv { pub fn truncate(&mut self, len: uint) { if len < self.len() { self.nbits = len; + // This fixes (2). self.storage.truncate(blocks_for_bits(len)); self.fix_last_block(); } @@ -707,13 +726,9 @@ impl Bitv { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn reserve(&mut self, additional: uint) { let desired_cap = self.len().checked_add(additional).expect("capacity overflow"); - match self.storage.len().checked_mul(u32::BITS) { - None => {} // Vec has more initialized capacity than we can ever use - Some(initialized_cap) => { - if desired_cap > initialized_cap { - self.storage.reserve(blocks_for_bits(desired_cap - initialized_cap)); - } - } + let storage_len = self.storage.len(); + if desired_cap > self.capacity() { + self.storage.reserve(blocks_for_bits(desired_cap) - storage_len); } } @@ -741,13 +756,9 @@ impl Bitv { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn reserve_exact(&mut self, additional: uint) { let desired_cap = self.len().checked_add(additional).expect("capacity overflow"); - match self.storage.len().checked_mul(u32::BITS) { - None => {} // Vec has more initialized capacity than we can ever use - Some(initialized_cap) => { - if desired_cap > initialized_cap { - self.storage.reserve_exact(blocks_for_bits(desired_cap - initialized_cap)); - } - } + let storage_len = self.storage.len(); + if desired_cap > self.capacity() { + self.storage.reserve_exact(blocks_for_bits(desired_cap) - storage_len); } } @@ -801,8 +812,7 @@ impl Bitv { if value { self.storage[old_last_word] |= !mask; } else { - // Extra bits are already supposed to be zero by invariant, but play it safe... - self.storage[old_last_word] &= mask; + // Extra bits are already zero by invariant. } } @@ -843,9 +853,13 @@ impl Bitv { } else { let i = self.nbits - 1; let ret = self[i]; - // Second rule of Bitv Club + // (3) self.set(i, false); self.nbits = i; + if self.nbits % u32::BITS == 0 { + // (2) + self.storage.pop(); + } Some(ret) } } @@ -864,11 +878,11 @@ impl Bitv { /// ``` #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn push(&mut self, elem: bool) { - let insert_pos = self.nbits; - self.nbits = self.nbits.checked_add(1).expect("Capacity overflow"); - if self.storage.len().checked_mul(u32::BITS).unwrap_or(uint::MAX) < self.nbits { + if self.nbits % u32::BITS == 0 { self.storage.push(0); } + let insert_pos = self.nbits; + self.nbits = self.nbits.checked_add(1).expect("Capacity overflow"); self.set(insert_pos, elem); } @@ -958,7 +972,7 @@ impl Ord for Bitv { 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 })); + try!(write!(fmt, "{}", if bit { 1u32 } else { 0u32 })); } Ok(()) } From 24329d72935c2753454e2187e632579c2405b6fc Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 15 Dec 2014 15:57:34 +0100 Subject: [PATCH 5/6] Change `Extend` and `FromIterator` functionality of `BitvSet` Also fix up some tests from last commit. --- src/libcollections/bit.rs | 46 ++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 3f33d85ba569e..dd3369ea1da75 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -98,6 +98,14 @@ type Blocks<'a> = Cloned>; type MutBlocks<'a> = MutItems<'a, u32>; type MatchWords<'a> = Chain>, Skip>>>>; +fn reverse_bits(byte: u8) -> u8 { + let mut result = 0; + for i in range(0, u8::BITS) { + result |= ((byte >> i) & 1) << (u8::BITS - 1 - i); + } + result +} + // 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>) { @@ -303,19 +311,21 @@ impl Bitv { let complete_words = bytes.len() / 4; let extra_bytes = bytes.len() % 4; + bitv.nbits = len; + for i in range(0, complete_words) { bitv.storage.push( - (bytes[i * 4 + 0] as u32 << 0) | - (bytes[i * 4 + 1] as u32 << 8) | - (bytes[i * 4 + 2] as u32 << 16) | - (bytes[i * 4 + 3] as u32 << 24) + (reverse_bits(bytes[i * 4 + 0]) as u32 << 0) | + (reverse_bits(bytes[i * 4 + 1]) as u32 << 8) | + (reverse_bits(bytes[i * 4 + 2]) as u32 << 16) | + (reverse_bits(bytes[i * 4 + 3]) as u32 << 24) ); } if extra_bytes > 0 { let mut last_word = 0u32; for (i, &byte) in bytes[complete_words*4..].iter().enumerate() { - last_word |= byte as u32 << (i * 8); + last_word |= reverse_bits(byte) as u32 << (i * 8); } bitv.storage.push(last_word); } @@ -1102,18 +1112,20 @@ impl Default for BitvSet { fn default() -> BitvSet { BitvSet::new() } } -impl FromIterator for BitvSet { - fn from_iter>(iterator: I) -> BitvSet { +impl FromIterator for BitvSet { + fn from_iter>(iterator: I) -> BitvSet { let mut ret = BitvSet::new(); ret.extend(iterator); ret } } -impl Extend for BitvSet { +impl Extend for BitvSet { #[inline] - fn extend>(&mut self, iterator: I) { - self.bitv.extend(iterator); + fn extend>(&mut self, mut iterator: I) { + for i in iterator { + self.insert(i); + } } } @@ -2592,9 +2604,9 @@ mod bitv_set_test { } #[test] - fn test_bitv_set_from_bools() { - let bools = vec![true, false, true, true]; - let a: BitvSet = bools.iter().map(|n| *n).collect(); + fn test_bitv_set_from_uints() { + let uints = vec![0, 2, 2, 3]; + let a: BitvSet = uints.into_iter().collect(); let mut b = BitvSet::new(); b.insert(0); b.insert(2); @@ -2604,13 +2616,13 @@ mod bitv_set_test { #[test] fn test_bitv_set_iterator() { - let bools = [true, false, true, true]; - let bitv: BitvSet = bools.iter().map(|n| *n).collect(); + let uints = vec![0, 2, 2, 3]; + let bitv: BitvSet = uints.into_iter().collect(); let idxs: Vec = bitv.iter().collect(); - assert_eq!(idxs, vec!(0, 2, 3)); + assert_eq!(idxs, vec![0, 2, 3]); - let long: BitvSet = range(0u, 10000).map(|n| n % 2 == 0).collect(); + let long: BitvSet = range(0u, 10000).filter(|&n| n % 2 == 0).collect(); let real = range_step(0, 10000, 2).collect::>(); let idxs: Vec = long.iter().collect(); From 20d7a5fc3cc33ed39aff7e5879e6f73d64cb0474 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Mon, 15 Dec 2014 11:54:35 -0500 Subject: [PATCH 6/6] Make bitv's APIs match RFC + fixup --- src/libcollections/bit.rs | 84 ++++++++++++--------------------------- 1 file changed, 26 insertions(+), 58 deletions(-) diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index dd3369ea1da75..f50e13c1b3c0a 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -91,7 +91,7 @@ use core::num::Int; use core::slice::{Items, MutItems}; use core::{u8, u32, uint}; -use hash; +use core::hash; use Vec; type Blocks<'a> = Cloned>; @@ -922,7 +922,7 @@ pub fn from_bytes(bytes: &[u8]) -> Bitv { /// Deprecated: Now a static method on Bitv. #[deprecated = "Now a static method on Bitv"] -pub fn from_fn(len: uint, mut f: F) -> Bitv where F: FnMut(uint) -> bool { +pub fn from_fn(len: uint, f: F) -> Bitv where F: FnMut(uint) -> bool { Bitv::from_fn(len, f) } @@ -1226,12 +1226,12 @@ impl BitvSet { self.bitv.capacity() } - /// Reserves capacity for an element to be inserted at `index` in the given - /// `Bitv`. The collection may reserve more space to avoid frequent reallocations. + /// Reserves capacity for the given `BitvSet` to contain `len` distinct elements. In the case + /// of `BitvSet` this means reallocations will not occur as long as all inserted elements + /// are less than `len`. /// - /// # Panics + /// The collection may reserve more space to avoid frequent reallocations. /// - /// Panics if the new capacity overflows `uint`. /// /// # Examples /// @@ -1239,27 +1239,25 @@ impl BitvSet { /// use std::collections::BitvSet; /// /// let mut s = BitvSet::new(); - /// s.reserve_index(10); - /// assert!(s.capacity() >= 11); + /// s.reserve_len(10); + /// assert!(s.capacity() >= 10); /// ``` #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn reserve_index(&mut self, index: uint) { - let len = self.bitv.len(); - if index >= len { - self.bitv.reserve(index - len + 1); + pub fn reserve_len(&mut self, len: uint) { + let cur_len = self.bitv.len(); + if len >= cur_len { + self.bitv.reserve(len - cur_len); } } - /// Reserves the minimum capacity for an element to be inserted at `index` - /// in the given `BitvSet`. Does nothing if the capacity is already sufficient. + /// Reserves the minimum capacity for the given `BitvSet` to contain `len` distinct elements. + /// In the case of `BitvSet` this means reallocations will not occur as long as all inserted + /// elements are less than `len`. /// /// Note that the allocator may give the collection more space than it requests. Therefore - /// capacity can not be relied upon to be precisely minimal. Prefer `reserve_index` if future + /// capacity can not be relied upon to be precisely minimal. Prefer `reserve_len` if future /// insertions are expected. /// - /// # Panics - /// - /// Panics if the new capacity overflows `uint`. /// /// # Examples /// @@ -1267,14 +1265,14 @@ impl BitvSet { /// use std::collections::BitvSet; /// /// let mut s = BitvSet::new(); - /// s.reserve_index_exact(10); - /// assert!(s.capacity() >= 11); + /// s.reserve_len_exact(10); + /// assert!(s.capacity() >= 10); /// ``` #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn reserve_index_exact(&mut self, index: uint) { - let len = self.bitv.len(); - if index >= len { - self.bitv.reserve_exact(index - len + 1); + pub fn reserve_len_exact(&mut self, len: uint) { + let cur_len = self.bitv.len(); + if len >= cur_len { + self.bitv.reserve_exact(len - cur_len); } } @@ -2233,35 +2231,6 @@ mod tests { 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::from_elem(3, false); @@ -2587,11 +2556,10 @@ mod bitv_bench { #[cfg(test)] mod bitv_set_test { - use std::prelude::*; + use prelude::*; use std::iter::range_step; use super::{Bitv, BitvSet}; - use vec::Vec; #[test] fn test_bitv_set_show() { @@ -2636,9 +2604,9 @@ mod bitv_set_test { for &b in bools.iter() { for &l in lengths.iter() { let bitset = BitvSet::from_bitv(Bitv::from_elem(l, b)); - assert_eq!(bitset.contains(&1u), b) - assert_eq!(bitset.contains(&(l-1u)), b) - assert!(!bitset.contains(&l)) + assert_eq!(bitset.contains(&1u), b); + assert_eq!(bitset.contains(&(l-1u)), b); + assert!(!bitset.contains(&l)); } } }