Skip to content

Commit 6dfb0e5

Browse files
committed
auto merge of #7703 : sfackler/rust/bitv, r=alexcrichton
Switched Bitv and BitvSet to external iterators. They still use some internal iterators internally (ha). Derived clone for all Bitv types. Removed indirection in BitvVariant. It previously held a unique pointer to the appropriate Bitv struct, even though those structs are the size of a pointer themselves. BitvVariant is the same size (16 bytes) as it was previously.
2 parents ff34064 + fd757a8 commit 6dfb0e5

File tree

1 file changed

+149
-51
lines changed

1 file changed

+149
-51
lines changed

src/libextra/bitv.rs

+149-51
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use std::ops;
1717
use std::uint;
1818
use std::vec;
1919

20+
#[deriving(Clone)]
2021
struct SmallBitv {
2122
/// only the lowest nbits of this value are used. the rest is undefined.
2223
bits: uint
@@ -107,6 +108,7 @@ impl SmallBitv {
107108
pub fn negate(&mut self) { self.bits = !self.bits; }
108109
}
109110

111+
#[deriving(Clone)]
110112
struct BigBitv {
111113
storage: ~[uint]
112114
}
@@ -212,11 +214,13 @@ impl BigBitv {
212214
}
213215
}
214216

215-
enum BitvVariant { Big(~BigBitv), Small(~SmallBitv) }
217+
#[deriving(Clone)]
218+
enum BitvVariant { Big(BigBitv), Small(SmallBitv) }
216219

217220
enum Op {Union, Intersect, Assign, Difference}
218221

219222
/// The bitvector type
223+
#[deriving(Clone)]
220224
pub struct Bitv {
221225
/// Internal representation of the bit vector (small or large)
222226
rep: BitvVariant,
@@ -237,20 +241,20 @@ impl Bitv {
237241
match self.rep {
238242
Small(ref mut s) => match other.rep {
239243
Small(ref s1) => match op {
240-
Union => s.union(*s1, self.nbits),
241-
Intersect => s.intersect(*s1, self.nbits),
242-
Assign => s.become(*s1, self.nbits),
243-
Difference => s.difference(*s1, self.nbits)
244+
Union => s.union(s1, self.nbits),
245+
Intersect => s.intersect(s1, self.nbits),
246+
Assign => s.become(s1, self.nbits),
247+
Difference => s.difference(s1, self.nbits)
244248
},
245249
Big(_) => die()
246250
},
247251
Big(ref mut s) => match other.rep {
248252
Small(_) => die(),
249253
Big(ref s1) => match op {
250-
Union => s.union(*s1, self.nbits),
251-
Intersect => s.intersect(*s1, self.nbits),
252-
Assign => s.become(*s1, self.nbits),
253-
Difference => s.difference(*s1, self.nbits)
254+
Union => s.union(s1, self.nbits),
255+
Intersect => s.intersect(s1, self.nbits),
256+
Assign => s.become(s1, self.nbits),
257+
Difference => s.difference(s1, self.nbits)
254258
}
255259
}
256260
}
@@ -261,14 +265,14 @@ impl Bitv {
261265
impl Bitv {
262266
pub fn new(nbits: uint, init: bool) -> Bitv {
263267
let rep = if nbits <= uint::bits {
264-
Small(~SmallBitv::new(if init {!0} else {0}))
268+
Small(SmallBitv::new(if init {!0} else {0}))
265269
}
266270
else {
267271
let nelems = nbits/uint::bits +
268272
if nbits % uint::bits == 0 {0} else {1};
269273
let elem = if init {!0u} else {0u};
270274
let s = vec::from_elem(nelems, elem);
271-
Big(~BigBitv::new(s))
275+
Big(BigBitv::new(s))
272276
};
273277
Bitv {rep: rep, nbits: nbits}
274278
}
@@ -337,11 +341,11 @@ impl Bitv {
337341
if self.nbits != v1.nbits { return false; }
338342
match self.rep {
339343
Small(ref b) => match v1.rep {
340-
Small(ref b1) => b.equals(*b1, self.nbits),
344+
Small(ref b1) => b.equals(b1, self.nbits),
341345
_ => false
342346
},
343347
Big(ref s) => match v1.rep {
344-
Big(ref s1) => s.equals(*s1, self.nbits),
348+
Big(ref s1) => s.equals(s1, self.nbits),
345349
Small(_) => return false
346350
}
347351
}
@@ -392,28 +396,23 @@ impl Bitv {
392396
match self.rep {
393397
Small(ref b) => b.is_true(self.nbits),
394398
_ => {
395-
for self.each() |i| { if !i { return false; } }
399+
for self.iter().advance |i| { if !i { return false; } }
396400
true
397401
}
398402
}
399403
}
400404

401405
#[inline]
402-
pub fn each(&self, f: &fn(bool) -> bool) -> bool {
403-
let mut i = 0;
404-
while i < self.nbits {
405-
if !f(self.get(i)) { return false; }
406-
i += 1;
407-
}
408-
return true;
406+
pub fn iter<'a>(&'a self) -> BitvIterator<'a> {
407+
BitvIterator {bitv: self, next_idx: 0}
409408
}
410409

411410
/// Returns true if all bits are 0
412411
pub fn is_false(&self) -> bool {
413412
match self.rep {
414413
Small(ref b) => b.is_false(self.nbits),
415414
Big(_) => {
416-
for self.each() |i| { if i { return false; } }
415+
for self.iter().advance |i| { if i { return false; } }
417416
true
418417
}
419418
}
@@ -477,7 +476,7 @@ impl Bitv {
477476
*/
478477
pub fn to_str(&self) -> ~str {
479478
let mut rs = ~"";
480-
for self.each() |i| {
479+
for self.iter().advance |i| {
481480
if i {
482481
rs.push_char('1');
483482
} else {
@@ -509,24 +508,6 @@ impl Bitv {
509508

510509
}
511510

512-
impl Clone for Bitv {
513-
/// Makes a copy of a bitvector
514-
#[inline]
515-
fn clone(&self) -> Bitv {
516-
match self.rep {
517-
Small(ref b) => {
518-
Bitv{nbits: self.nbits, rep: Small(~SmallBitv{bits: b.bits})}
519-
}
520-
Big(ref b) => {
521-
let mut st = vec::from_elem(self.nbits / uint::bits + 1, 0u);
522-
let len = st.len();
523-
for uint::range(0, len) |i| { st[i] = b.storage[i]; };
524-
Bitv{nbits: self.nbits, rep: Big(~BigBitv{storage: st})}
525-
}
526-
}
527-
}
528-
}
529-
530511
/**
531512
* Transform a byte-vector into a bitv. Each byte becomes 8 bits,
532513
* with the most significant bits of each byte coming first. Each
@@ -580,12 +561,37 @@ fn iterate_bits(base: uint, bits: uint, f: &fn(uint) -> bool) -> bool {
580561
return true;
581562
}
582563

564+
/// An iterator for Bitv
565+
pub struct BitvIterator<'self> {
566+
priv bitv: &'self Bitv,
567+
priv next_idx: uint
568+
}
569+
570+
impl<'self> Iterator<bool> for BitvIterator<'self> {
571+
#[inline]
572+
fn next(&mut self) -> Option<bool> {
573+
if self.next_idx < self.bitv.nbits {
574+
let idx = self.next_idx;
575+
self.next_idx += 1;
576+
Some(self.bitv.get(idx))
577+
} else {
578+
None
579+
}
580+
}
581+
582+
fn size_hint(&self) -> (uint, Option<uint>) {
583+
let rem = self.bitv.nbits - self.next_idx;
584+
(rem, Some(rem))
585+
}
586+
}
587+
583588
/// An implementation of a set using a bit vector as an underlying
584589
/// representation for holding numerical elements.
585590
///
586591
/// It should also be noted that the amount of storage necessary for holding a
587592
/// set of objects is proportional to the maximum of the objects when viewed
588593
/// as a uint.
594+
#[deriving(Clone)]
589595
pub struct BitvSet {
590596
priv size: uint,
591597

@@ -609,8 +615,8 @@ impl BitvSet {
609615
}
610616
let Bitv{rep, _} = bitv;
611617
match rep {
612-
Big(~b) => BitvSet{ size: size, bitv: b },
613-
Small(~SmallBitv{bits}) =>
618+
Big(b) => BitvSet{ size: size, bitv: b },
619+
Small(SmallBitv{bits}) =>
614620
BitvSet{ size: size, bitv: BigBitv{ storage: ~[bits] } },
615621
}
616622
}
@@ -623,7 +629,7 @@ impl BitvSet {
623629
pub fn unwrap(self) -> Bitv {
624630
let cap = self.capacity();
625631
let BitvSet{bitv, _} = self;
626-
return Bitv{ nbits:cap, rep: Big(~bitv) };
632+
return Bitv{ nbits:cap, rep: Big(bitv) };
627633
}
628634

629635
#[inline]
@@ -670,13 +676,8 @@ impl BitvSet {
670676
self.other_op(other, |w1, w2| w1 ^ w2);
671677
}
672678

673-
pub fn each(&self, blk: &fn(v: &uint) -> bool) -> bool {
674-
for self.bitv.storage.iter().enumerate().advance |(i, &w)| {
675-
if !iterate_bits(i * uint::bits, w, |b| blk(&b)) {
676-
return false;
677-
}
678-
}
679-
return true;
679+
pub fn iter<'a>(&'a self) -> BitvSetIterator<'a> {
680+
BitvSetIterator {set: self, next_idx: 0}
680681
}
681682
}
682683

@@ -860,6 +861,31 @@ impl BitvSet {
860861
}
861862
}
862863

864+
pub struct BitvSetIterator<'self> {
865+
priv set: &'self BitvSet,
866+
priv next_idx: uint
867+
}
868+
869+
impl<'self> Iterator<uint> for BitvSetIterator<'self> {
870+
#[inline]
871+
fn next(&mut self) -> Option<uint> {
872+
while self.next_idx < self.set.capacity() {
873+
let idx = self.next_idx;
874+
self.next_idx += 1;
875+
876+
if self.set.contains(&idx) {
877+
return Some(idx);
878+
}
879+
}
880+
881+
return None;
882+
}
883+
884+
fn size_hint(&self) -> (uint, Option<uint>) {
885+
(0, Some(self.set.capacity() - self.next_idx))
886+
}
887+
}
888+
863889
#[cfg(test)]
864890
mod tests {
865891
use extra::test::BenchHarness;
@@ -1241,6 +1267,25 @@ mod tests {
12411267
assert_eq!(from_bytes([0b00100110]).to_bools(), bools);
12421268
}
12431269
1270+
#[test]
1271+
fn test_bitv_iterator() {
1272+
let bools = [true, false, true, true];
1273+
let bitv = from_bools(bools);
1274+
1275+
for bitv.iter().zip(bools.iter()).advance |(act, &ex)| {
1276+
assert_eq!(ex, act);
1277+
}
1278+
}
1279+
1280+
#[test]
1281+
fn test_bitv_set_iterator() {
1282+
let bools = [true, false, true, true];
1283+
let bitv = BitvSet::from_bitv(from_bools(bools));
1284+
1285+
let idxs: ~[uint] = bitv.iter().collect();
1286+
assert_eq!(idxs, ~[0, 2, 3]);
1287+
}
1288+
12441289
#[test]
12451290
fn test_small_difference() {
12461291
let mut b1 = Bitv::new(3, false);
@@ -1417,6 +1462,25 @@ mod tests {
14171462
assert_eq!(a.capacity(), uint::bits);
14181463
}
14191464

1465+
#[test]
1466+
fn test_bitv_clone() {
1467+
let mut a = BitvSet::new();
1468+
1469+
assert!(a.insert(1));
1470+
assert!(a.insert(100));
1471+
assert!(a.insert(1000));
1472+
1473+
let mut b = a.clone();
1474+
1475+
assert_eq!(&a, &b);
1476+
1477+
assert!(b.remove(&1));
1478+
assert!(a.contains(&1));
1479+
1480+
assert!(a.remove(&1000));
1481+
assert!(b.contains(&1000));
1482+
}
1483+
14201484
fn rng() -> rand::IsaacRng {
14211485
let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
14221486
rand::IsaacRng::new_seeded(seed)
@@ -1504,4 +1568,38 @@ mod tests {
15041568
b1.union(&b2);
15051569
}
15061570
}
1571+
1572+
#[bench]
1573+
fn bench_btv_small_iter(b: &mut BenchHarness) {
1574+
let bitv = Bitv::new(uint::bits, false);
1575+
do b.iter {
1576+
let mut sum = 0;
1577+
for bitv.iter().advance |pres| {
1578+
sum += pres as uint;
1579+
}
1580+
}
1581+
}
1582+
1583+
#[bench]
1584+
fn bench_bitv_big_iter(b: &mut BenchHarness) {
1585+
let bitv = Bitv::new(BENCH_BITS, false);
1586+
do b.iter {
1587+
let mut sum = 0;
1588+
for bitv.iter().advance |pres| {
1589+
sum += pres as uint;
1590+
}
1591+
}
1592+
}
1593+
1594+
#[bench]
1595+
fn bench_bitvset_iter(b: &mut BenchHarness) {
1596+
let bitv = BitvSet::from_bitv(from_fn(BENCH_BITS,
1597+
|idx| {idx % 3 == 0}));
1598+
do b.iter {
1599+
let mut sum = 0;
1600+
for bitv.iter().advance |idx| {
1601+
sum += idx;
1602+
}
1603+
}
1604+
}
15071605
}

0 commit comments

Comments
 (0)