]> git.lizzy.rs Git - rust.git/commitdiff
Implement `append` and `split_off` for BitSet (RFC 509)
authorJohannes Oertel <johannes.oertel@uni-due.de>
Tue, 28 Apr 2015 16:01:23 +0000 (18:01 +0200)
committerJohannes Oertel <johannes.oertel@uni-due.de>
Sun, 10 May 2015 19:46:32 +0000 (21:46 +0200)
src/libcollections/bit.rs
src/libcollectionstest/bit/set.rs
src/libcollectionstest/lib.rs

index 1271a6276aec910bc7761b747a9a51e0ca06cc85..5ea5f566d108f761dc10552cd6fa882a63b7792f 100644 (file)
@@ -1792,6 +1792,89 @@ pub fn symmetric_difference_with(&mut self, other: &BitSet) {
         self.other_op(other, |w1, w2| w1 ^ w2);
     }
 
+    /// Moves all elements from `other` into `Self`, leaving `other` empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(collections, bit_set_append_split_off)]
+    /// use std::collections::{BitVec, BitSet};
+    ///
+    /// let mut a = BitSet::new();
+    /// a.insert(2);
+    /// a.insert(6);
+    ///
+    /// let mut b = BitSet::new();
+    /// b.insert(1);
+    /// b.insert(3);
+    /// b.insert(6);
+    ///
+    /// a.append(&mut b);
+    ///
+    /// assert_eq!(a.len(), 4);
+    /// assert_eq!(b.len(), 0);
+    /// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01110010])));
+    /// ```
+    #[unstable(feature = "bit_set_append_split_off",
+               reason = "recently added as part of collections reform 2")]
+    pub fn append(&mut self, other: &mut Self) {
+        self.union_with(other);
+        other.clear();
+    }
+
+    /// Splits the `BitSet` into two at the given key including the key.
+    /// Retains the first part in-place while returning the second part.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(collections, bit_set_append_split_off)]
+    /// use std::collections::{BitSet, BitVec};
+    /// let mut a = BitSet::new();
+    /// a.insert(2);
+    /// a.insert(6);
+    /// a.insert(1);
+    /// a.insert(3);
+    ///
+    /// let b = a.split_off(3);
+    ///
+    /// assert_eq!(a.len(), 2);
+    /// assert_eq!(b.len(), 2);
+    /// assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100000])));
+    /// assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0b00010010])));
+    /// ```
+    #[unstable(feature = "bit_set_append_split_off",
+               reason = "recently added as part of collections reform 2")]
+    pub fn split_off(&mut self, at: usize) -> Self {
+        let mut other = BitSet::new();
+
+        if at == 0 {
+            swap(self, &mut other);
+            return other;
+        } else if at >= self.bit_vec.len() {
+            return other;
+        }
+
+        // Calculate block and bit at which to split
+        let w = at / u32::BITS;
+        let b = at % u32::BITS;
+
+        // Pad `other` with `w` zero blocks,
+        // append `self`'s blocks in the range from `w` to the end to `other`
+        other.bit_vec.storage.extend(repeat(0u32).take(w)
+                                     .chain(self.bit_vec.storage[w..].iter().cloned()));
+        other.bit_vec.nbits = self.bit_vec.nbits;
+
+        if b > 0 {
+            other.bit_vec.storage[w] &= !0 << b;
+        }
+
+        // Sets `bit_vec.len()` and fixes the last block as well
+        self.bit_vec.truncate(at);
+
+        other
+    }
+
     /// Returns the number of set bits in this set.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
index d020f551dd55dcd842df23048ce9db885ef4f6ad..e6aa15608f03eb0297afcae622927e105a55c92d 100644 (file)
@@ -387,6 +387,67 @@ fn test_bit_vec_clone() {
     assert!(b.contains(&1000));
 }
 
+#[test]
+fn test_bit_set_append() {
+    let mut a = BitSet::new();
+    a.insert(2);
+    a.insert(6);
+
+    let mut b = BitSet::new();
+    b.insert(1);
+    b.insert(3);
+    b.insert(6);
+
+    a.append(&mut b);
+
+    assert_eq!(a.len(), 4);
+    assert_eq!(b.len(), 0);
+    assert!(b.capacity() >= 6);
+
+    assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b01110010])));
+}
+
+#[test]
+fn test_bit_set_split_off() {
+    // Split at 0
+    let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
+                                                          0b00110011, 0b01101011, 0b10101101]));
+
+    let b = a.split_off(0);
+
+    assert_eq!(a.len(), 0);
+    assert_eq!(b.len(), 21);
+
+    assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
+                                                            0b00110011, 0b01101011, 0b10101101])));
+
+    // Split behind last element
+    let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
+                                                          0b00110011, 0b01101011, 0b10101101]));
+
+    let b = a.split_off(50);
+
+    assert_eq!(a.len(), 21);
+    assert_eq!(b.len(), 0);
+
+    assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
+                                                            0b00110011, 0b01101011, 0b10101101])));
+
+    // Split at arbitrary element
+    let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
+                                                          0b00110011, 0b01101011, 0b10101101]));
+
+    let b = a.split_off(34);
+
+    assert_eq!(a.len(), 12);
+    assert_eq!(b.len(), 9);
+
+    assert_eq!(a, BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000, 0b00010010, 0b10010010,
+                                                            0b00110011, 0b01000000])));
+    assert_eq!(b, BitSet::from_bit_vec(BitVec::from_bytes(&[0, 0, 0, 0,
+                                                            0b00101011, 0b10101101])));
+}
+
 mod bench {
     use std::collections::{BitSet, BitVec};
     use std::__rand::{Rng, thread_rng, ThreadRng};
index 154bdd56c5a68ca76f987d1dc831e5fc2bc0af41..9b50478472fa92d30ad3f3e5c63a2c7217b174ef 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(bit_set_append_split_off)]
 #![feature(bit_vec_append_split_off)]
 #![feature(box_syntax)]
 #![feature(collections)]