Skip to content

Commit 6d55211

Browse files
committed
auto merge of #11615 : adwhit/rust/master, r=cmr
This is my first patch so feedback appreciated! Bug when initialising `bitv:Bitv::new(int,bool)` when `bool=true`. It created a `Bitv` with underlying representation `!0u` rather than the actual desired bit layout ( e.g. `11111111` instead of `00001111`). This works OK because a size attribute is included which keeps access to legal bounds. However when using `BitvSet::from_bitv(Bitv)`, we then find that `bitvset.contains(i)` can return true when `i` should not in fact be in the set. ``` let bs = BitvSet::from_bitv(Bitv::new(100, true)); assert!(!bs.contains(&127)) //fails ``` The fix is to create the correct representation by treating various cases separately and using a bitshift `(1<<nbits) - 1` to generate correct number of `1`s where necessary.
2 parents 1a9641b + 32408a6 commit 6d55211

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

src/libextra/bitv.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -269,14 +269,23 @@ impl Bitv {
269269

270270
impl Bitv {
271271
pub fn new(nbits: uint, init: bool) -> Bitv {
272-
let rep = if nbits <= uint::bits {
272+
let rep = if nbits < uint::bits {
273+
Small(SmallBitv::new(if init {(1<<nbits)-1} else {0}))
274+
} else if nbits == uint::bits {
273275
Small(SmallBitv::new(if init {!0} else {0}))
274-
}
275-
else {
276-
let nelems = nbits/uint::bits +
277-
if nbits % uint::bits == 0 {0} else {1};
278-
let elem = if init {!0u} else {0u};
279-
let s = vec::from_elem(nelems, elem);
276+
} else {
277+
let exact = nbits % uint::bits == 0;
278+
let nelems = nbits/uint::bits + if exact {0} else {1};
279+
let s =
280+
if init {
281+
if exact {
282+
vec::from_elem(nelems, !0u)
283+
} else {
284+
let mut v = vec::from_elem(nelems-1, !0u);
285+
v.push((1<<nbits % uint::bits)-1);
286+
v
287+
}
288+
} else { vec::from_elem(nelems, 0u)};
280289
Big(BigBitv::new(s))
281290
};
282291
Bitv {rep: rep, nbits: nbits}
@@ -1329,6 +1338,20 @@ mod tests {
13291338
assert_eq!(idxs, ~[0, 2, 3]);
13301339
}
13311340
1341+
#[test]
1342+
fn test_bitv_set_frombitv_init() {
1343+
let bools = [true, false];
1344+
let lengths = [10, 64, 100];
1345+
for &b in bools.iter() {
1346+
for &l in lengths.iter() {
1347+
let bitset = BitvSet::from_bitv(Bitv::new(l, b));
1348+
assert_eq!(bitset.contains(&1u), b)
1349+
assert_eq!(bitset.contains(&(l-1u)), b)
1350+
assert!(!bitset.contains(&l))
1351+
}
1352+
}
1353+
}
1354+
13321355
#[test]
13331356
fn test_small_difference() {
13341357
let mut b1 = Bitv::new(3, false);

0 commit comments

Comments
 (0)