Skip to content

Commit aab37fa

Browse files
committed
Merge pull request #3240 from Dretch/bitvfixes
Bitvfixes
2 parents 8c68432 + 69d66a7 commit aab37fa

File tree

1 file changed

+125
-46
lines changed

1 file changed

+125
-46
lines changed

src/libstd/bitv.rs

+125-46
Original file line numberDiff line numberDiff line change
@@ -19,37 +19,42 @@ export to_str;
1919
export eq_vec;
2020
export methods;
2121

22+
/// a mask that has a 1 for each defined bit in a small_bitv, assuming n bits
23+
#[inline(always)]
24+
fn small_mask(nbits: uint) -> u32 {
25+
(1 << nbits) - 1
26+
}
27+
2228
struct small_bitv {
29+
/// only the lowest nbits of this value are used. the rest is undefined.
2330
let mut bits: u32;
2431
new(bits: u32) { self.bits = bits; }
2532
priv {
2633
#[inline(always)]
27-
fn bits_op(right_bits: u32, f: fn(u32, u32) -> u32) -> bool {
34+
fn bits_op(right_bits: u32, nbits: uint, f: fn(u32, u32) -> u32)
35+
-> bool {
36+
let mask = small_mask(nbits);
2837
let old_b: u32 = self.bits;
2938
let new_b = f(old_b, right_bits);
3039
self.bits = new_b;
31-
old_b != new_b
40+
mask & old_b != mask & new_b
3241
}
3342
}
3443
#[inline(always)]
35-
fn union(s: &small_bitv) -> bool {
36-
self.bits_op(s.bits, |u1, u2| { u1 | u2 })
44+
fn union(s: &small_bitv, nbits: uint) -> bool {
45+
self.bits_op(s.bits, nbits, |u1, u2| u1 | u2)
3746
}
3847
#[inline(always)]
39-
fn intersect(s: &small_bitv) -> bool {
40-
self.bits_op(s.bits, |u1, u2| { u1 & u2 })
48+
fn intersect(s: &small_bitv, nbits: uint) -> bool {
49+
self.bits_op(s.bits, nbits, |u1, u2| u1 & u2)
4150
}
4251
#[inline(always)]
43-
fn become(s: &small_bitv) -> bool {
44-
let old = self.bits;
45-
self.bits = s.bits;
46-
old != self.bits
52+
fn become(s: &small_bitv, nbits: uint) -> bool {
53+
self.bits_op(s.bits, nbits, |_u1, u2| u2)
4754
}
4855
#[inline(always)]
49-
fn difference(s: &small_bitv) -> bool {
50-
let old = self.bits;
51-
self.bits &= !s.bits;
52-
old != self.bits
56+
fn difference(s: &small_bitv, nbits: uint) -> bool {
57+
self.bits_op(s.bits, nbits, |u1, u2| u1 ^ u2)
5358
}
5459
#[inline(always)]
5560
pure fn get(i: uint) -> bool {
@@ -61,42 +66,70 @@ struct small_bitv {
6166
self.bits |= 1<<i;
6267
}
6368
else {
64-
self.bits &= !(i as u32);
69+
self.bits &= !(1<<i as u32);
6570
}
6671
}
6772
#[inline(always)]
68-
fn equals(b: &small_bitv) -> bool { self.bits == b.bits }
73+
fn equals(b: &small_bitv, nbits: uint) -> bool {
74+
let mask = small_mask(nbits);
75+
mask & self.bits == mask & b.bits
76+
}
6977
#[inline(always)]
7078
fn clear() { self.bits = 0; }
7179
#[inline(always)]
7280
fn set_all() { self.bits = !0; }
7381
#[inline(always)]
74-
fn is_true() -> bool { self.bits == !0 }
82+
fn is_true(nbits: uint) -> bool {
83+
small_mask(nbits) & !self.bits == 0
84+
}
7585
#[inline(always)]
76-
fn is_false() -> bool { self.bits == 0 }
86+
fn is_false(nbits: uint) -> bool {
87+
small_mask(nbits) & self.bits == 0
88+
}
7789
#[inline(always)]
7890
fn invert() { self.bits = !self.bits; }
7991
}
8092

93+
/**
94+
* a mask that has a 1 for each defined bit in the nth element of a big_bitv,
95+
* assuming n bits.
96+
*/
97+
#[inline(always)]
98+
fn big_mask(nbits: uint, elem: uint) -> uint {
99+
let rmd = nbits % uint_bits;
100+
let nelems = nbits/uint_bits + if rmd == 0 {0} else {1};
101+
102+
if elem < nelems - 1 || rmd == 0 {
103+
!0
104+
} else {
105+
(1 << rmd) - 1
106+
}
107+
}
108+
81109
struct big_bitv {
82-
// only mut b/c of clone and lack of other constructor
110+
// only mut b/c of clone and lack of other constructor
83111
let mut storage: ~[mut uint];
84112
new(-storage: ~[mut uint]) {
85113
self.storage <- storage;
86114
}
87115
priv {
88116
#[inline(always)]
89-
fn process(b: &big_bitv, op: fn(uint, uint) -> uint) -> bool {
117+
fn process(b: &big_bitv, nbits: uint, op: fn(uint, uint) -> uint)
118+
-> bool {
90119
let len = b.storage.len();
91120
assert (self.storage.len() == len);
92121
let mut changed = false;
93122
do uint::range(0, len) |i| {
94-
let w0 = self.storage[i];
95-
let w1 = b.storage[i];
96-
let w = op(w0, w1);
97-
if w0 != w unchecked { changed = true; self.storage[i] = w; };
123+
let mask = big_mask(nbits, i);
124+
let w0 = self.storage[i] & mask;
125+
let w1 = b.storage[i] & mask;
126+
let w = op(w0, w1) & mask;
127+
if w0 != w unchecked {
128+
changed = true;
129+
self.storage[i] = w;
130+
}
98131
true
99-
};
132+
}
100133
changed
101134
}
102135
}
@@ -112,15 +145,21 @@ struct big_bitv {
112145
#[inline(always)]
113146
fn invert() { for self.each_storage() |w| { w = !w } }
114147
#[inline(always)]
115-
fn union(b: &big_bitv) -> bool { self.process(b, lor) }
148+
fn union(b: &big_bitv, nbits: uint) -> bool {
149+
self.process(b, nbits, lor)
150+
}
116151
#[inline(always)]
117-
fn intersect(b: &big_bitv) -> bool { self.process(b, land) }
152+
fn intersect(b: &big_bitv, nbits: uint) -> bool {
153+
self.process(b, nbits, land)
154+
}
118155
#[inline(always)]
119-
fn become(b: &big_bitv) -> bool { self.process(b, right) }
156+
fn become(b: &big_bitv, nbits: uint) -> bool {
157+
self.process(b, nbits, right)
158+
}
120159
#[inline(always)]
121-
fn difference(b: &big_bitv) -> bool {
160+
fn difference(b: &big_bitv, nbits: uint) -> bool {
122161
self.invert();
123-
let b = self.intersect(b);
162+
let b = self.intersect(b, nbits);
124163
self.invert();
125164
b
126165
}
@@ -140,10 +179,13 @@ struct big_bitv {
140179
else { self.storage[w] & !flag };
141180
}
142181
#[inline(always)]
143-
fn equals(b: &big_bitv) -> bool {
182+
fn equals(b: &big_bitv, nbits: uint) -> bool {
144183
let len = b.storage.len();
145184
for uint::iterate(0, len) |i| {
146-
if self.storage[i] != b.storage[i] { return false; }
185+
let mask = big_mask(nbits, i);
186+
if mask & self.storage[i] != mask & b.storage[i] {
187+
return false;
188+
}
147189
}
148190
}
149191
}
@@ -163,8 +205,10 @@ struct bitv {
163205
self.rep = small(~small_bitv(if init {!0} else {0}));
164206
}
165207
else {
166-
let s = to_mut(from_elem(nbits / uint_bits + 1,
167-
if init {!0} else {0}));
208+
let nelems = nbits/uint_bits +
209+
if nbits % uint_bits == 0 {0} else {1};
210+
let elem = if init {!0} else {0};
211+
let s = to_mut(from_elem(nelems, elem));
168212
self.rep = big(~big_bitv(s));
169213
};
170214
}
@@ -182,20 +226,20 @@ struct bitv {
182226
match self.rep {
183227
small(s) => match other.rep {
184228
small(s1) => match op {
185-
union => s.union(s1),
186-
intersect => s.intersect(s1),
187-
assign => s.become(s1),
188-
difference => s.difference(s1)
229+
union => s.union(s1, self.nbits),
230+
intersect => s.intersect(s1, self.nbits),
231+
assign => s.become(s1, self.nbits),
232+
difference => s.difference(s1, self.nbits)
189233
},
190234
big(s1) => self.die()
191235
},
192236
big(s) => match other.rep {
193237
small(_) => self.die(),
194238
big(s1) => match op {
195-
union => s.union(s1),
196-
intersect => s.intersect(s1),
197-
assign => s.become(s1),
198-
difference => s.difference(s1)
239+
union => s.union(s1, self.nbits),
240+
intersect => s.intersect(s1, self.nbits),
241+
assign => s.become(s1, self.nbits),
242+
difference => s.difference(s1, self.nbits)
199243
}
200244
}
201245
}
@@ -280,11 +324,11 @@ struct bitv {
280324
if self.nbits != v1.nbits { return false; }
281325
match self.rep {
282326
small(b) => match v1.rep {
283-
small(b1) => b.equals(b1),
327+
small(b1) => b.equals(b1, self.nbits),
284328
_ => false
285329
},
286330
big(s) => match v1.rep {
287-
big(s1) => s.equals(s1),
331+
big(s1) => s.equals(s1, self.nbits),
288332
small(_) => return false
289333
}
290334
}
@@ -330,7 +374,7 @@ struct bitv {
330374
#[inline(always)]
331375
fn is_true() -> bool {
332376
match self.rep {
333-
small(b) => b.is_true(),
377+
small(b) => b.is_true(self.nbits),
334378
_ => {
335379
for self.each() |i| { if !i { return false; } }
336380
true
@@ -351,7 +395,7 @@ struct bitv {
351395
352396
fn is_false() -> bool {
353397
match self.rep {
354-
small(b) => b.is_false(),
398+
small(b) => b.is_false(self.nbits),
355399
big(_) => {
356400
for self.each() |i| { if i { return false; } }
357401
true
@@ -456,6 +500,14 @@ mod tests {
456500
assert act.eq_vec(~[1u]);
457501
}
458502

503+
#[test]
504+
fn test_2_elements() {
505+
let b = bitv::bitv(2, false);
506+
b.set(0, true);
507+
b.set(1, false);
508+
assert b.to_str() == ~"10";
509+
}
510+
459511
#[test]
460512
fn test_10_elements() {
461513
let mut act;
@@ -732,6 +784,33 @@ mod tests {
732784
let v1 = bitv(110u, false);
733785
assert !v0.equal(v1);
734786
}
787+
788+
#[test]
789+
fn test_equal_sneaky_small() {
790+
let a = bitv::bitv(1, false);
791+
a.set(0, true);
792+
793+
let b = bitv::bitv(1, true);
794+
b.set(0, true);
795+
796+
assert a.equal(b);
797+
}
798+
799+
#[test]
800+
fn test_equal_sneaky_big() {
801+
let a = bitv::bitv(100, false);
802+
for uint::range(0, 100) |i| {
803+
a.set(i, true);
804+
}
805+
806+
let b = bitv::bitv(100, true);
807+
for uint::range(0, 100) |i| {
808+
b.set(i, true);
809+
}
810+
811+
assert a.equal(b);
812+
}
813+
735814
}
736815

737816
//

0 commit comments

Comments
 (0)