about summary refs log tree commit diff
path: root/src/libcollections
diff options
context:
space:
mode:
authorJosh Stone <cuviper@gmail.com>2014-12-09 22:06:52 -0800
committerAlexis Beingessner <a.beingessner@gmail.com>2014-12-20 09:10:04 -0500
commit3deb97f5d02ddbdbf20a587815fe84934cda948c (patch)
treeb74e83efd28a5a494e7d272aaddef319fd9e79dc /src/libcollections
parent8f194de95d00fe540d848cc9a7d3e049ce3684ab (diff)
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.
Diffstat (limited to 'src/libcollections')
-rw-r--r--src/libcollections/bit.rs51
1 files changed, 43 insertions, 8 deletions
diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs
index 9ea7d52b7c6..5cf5183d25d 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]