commit
aab37fa811
1 changed files with 125 additions and 46 deletions
|
@ -19,37 +19,42 @@ export to_str;
|
||||||
export eq_vec;
|
export eq_vec;
|
||||||
export methods;
|
export methods;
|
||||||
|
|
||||||
|
/// a mask that has a 1 for each defined bit in a small_bitv, assuming n bits
|
||||||
|
#[inline(always)]
|
||||||
|
fn small_mask(nbits: uint) -> u32 {
|
||||||
|
(1 << nbits) - 1
|
||||||
|
}
|
||||||
|
|
||||||
struct small_bitv {
|
struct small_bitv {
|
||||||
|
/// only the lowest nbits of this value are used. the rest is undefined.
|
||||||
let mut bits: u32;
|
let mut bits: u32;
|
||||||
new(bits: u32) { self.bits = bits; }
|
new(bits: u32) { self.bits = bits; }
|
||||||
priv {
|
priv {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn bits_op(right_bits: u32, f: fn(u32, u32) -> u32) -> bool {
|
fn bits_op(right_bits: u32, nbits: uint, f: fn(u32, u32) -> u32)
|
||||||
|
-> bool {
|
||||||
|
let mask = small_mask(nbits);
|
||||||
let old_b: u32 = self.bits;
|
let old_b: u32 = self.bits;
|
||||||
let new_b = f(old_b, right_bits);
|
let new_b = f(old_b, right_bits);
|
||||||
self.bits = new_b;
|
self.bits = new_b;
|
||||||
old_b != new_b
|
mask & old_b != mask & new_b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn union(s: &small_bitv) -> bool {
|
fn union(s: &small_bitv, nbits: uint) -> bool {
|
||||||
self.bits_op(s.bits, |u1, u2| { u1 | u2 })
|
self.bits_op(s.bits, nbits, |u1, u2| u1 | u2)
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn intersect(s: &small_bitv) -> bool {
|
fn intersect(s: &small_bitv, nbits: uint) -> bool {
|
||||||
self.bits_op(s.bits, |u1, u2| { u1 & u2 })
|
self.bits_op(s.bits, nbits, |u1, u2| u1 & u2)
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn become(s: &small_bitv) -> bool {
|
fn become(s: &small_bitv, nbits: uint) -> bool {
|
||||||
let old = self.bits;
|
self.bits_op(s.bits, nbits, |_u1, u2| u2)
|
||||||
self.bits = s.bits;
|
|
||||||
old != self.bits
|
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn difference(s: &small_bitv) -> bool {
|
fn difference(s: &small_bitv, nbits: uint) -> bool {
|
||||||
let old = self.bits;
|
self.bits_op(s.bits, nbits, |u1, u2| u1 ^ u2)
|
||||||
self.bits &= !s.bits;
|
|
||||||
old != self.bits
|
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pure fn get(i: uint) -> bool {
|
pure fn get(i: uint) -> bool {
|
||||||
|
@ -61,42 +66,70 @@ struct small_bitv {
|
||||||
self.bits |= 1<<i;
|
self.bits |= 1<<i;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.bits &= !(i as u32);
|
self.bits &= !(1<<i as u32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn equals(b: &small_bitv) -> bool { self.bits == b.bits }
|
fn equals(b: &small_bitv, nbits: uint) -> bool {
|
||||||
|
let mask = small_mask(nbits);
|
||||||
|
mask & self.bits == mask & b.bits
|
||||||
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn clear() { self.bits = 0; }
|
fn clear() { self.bits = 0; }
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn set_all() { self.bits = !0; }
|
fn set_all() { self.bits = !0; }
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn is_true() -> bool { self.bits == !0 }
|
fn is_true(nbits: uint) -> bool {
|
||||||
|
small_mask(nbits) & !self.bits == 0
|
||||||
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn is_false() -> bool { self.bits == 0 }
|
fn is_false(nbits: uint) -> bool {
|
||||||
|
small_mask(nbits) & self.bits == 0
|
||||||
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn invert() { self.bits = !self.bits; }
|
fn invert() { self.bits = !self.bits; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a mask that has a 1 for each defined bit in the nth element of a big_bitv,
|
||||||
|
* assuming n bits.
|
||||||
|
*/
|
||||||
|
#[inline(always)]
|
||||||
|
fn big_mask(nbits: uint, elem: uint) -> uint {
|
||||||
|
let rmd = nbits % uint_bits;
|
||||||
|
let nelems = nbits/uint_bits + if rmd == 0 {0} else {1};
|
||||||
|
|
||||||
|
if elem < nelems - 1 || rmd == 0 {
|
||||||
|
!0
|
||||||
|
} else {
|
||||||
|
(1 << rmd) - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct big_bitv {
|
struct big_bitv {
|
||||||
// only mut b/c of clone and lack of other constructor
|
// only mut b/c of clone and lack of other constructor
|
||||||
let mut storage: ~[mut uint];
|
let mut storage: ~[mut uint];
|
||||||
new(-storage: ~[mut uint]) {
|
new(-storage: ~[mut uint]) {
|
||||||
self.storage <- storage;
|
self.storage <- storage;
|
||||||
}
|
}
|
||||||
priv {
|
priv {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn process(b: &big_bitv, op: fn(uint, uint) -> uint) -> bool {
|
fn process(b: &big_bitv, nbits: uint, op: fn(uint, uint) -> uint)
|
||||||
|
-> bool {
|
||||||
let len = b.storage.len();
|
let len = b.storage.len();
|
||||||
assert (self.storage.len() == len);
|
assert (self.storage.len() == len);
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
do uint::range(0, len) |i| {
|
do uint::range(0, len) |i| {
|
||||||
let w0 = self.storage[i];
|
let mask = big_mask(nbits, i);
|
||||||
let w1 = b.storage[i];
|
let w0 = self.storage[i] & mask;
|
||||||
let w = op(w0, w1);
|
let w1 = b.storage[i] & mask;
|
||||||
if w0 != w unchecked { changed = true; self.storage[i] = w; };
|
let w = op(w0, w1) & mask;
|
||||||
|
if w0 != w unchecked {
|
||||||
|
changed = true;
|
||||||
|
self.storage[i] = w;
|
||||||
|
}
|
||||||
true
|
true
|
||||||
};
|
}
|
||||||
changed
|
changed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,15 +145,21 @@ struct big_bitv {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn invert() { for self.each_storage() |w| { w = !w } }
|
fn invert() { for self.each_storage() |w| { w = !w } }
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn union(b: &big_bitv) -> bool { self.process(b, lor) }
|
fn union(b: &big_bitv, nbits: uint) -> bool {
|
||||||
|
self.process(b, nbits, lor)
|
||||||
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn intersect(b: &big_bitv) -> bool { self.process(b, land) }
|
fn intersect(b: &big_bitv, nbits: uint) -> bool {
|
||||||
|
self.process(b, nbits, land)
|
||||||
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn become(b: &big_bitv) -> bool { self.process(b, right) }
|
fn become(b: &big_bitv, nbits: uint) -> bool {
|
||||||
|
self.process(b, nbits, right)
|
||||||
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn difference(b: &big_bitv) -> bool {
|
fn difference(b: &big_bitv, nbits: uint) -> bool {
|
||||||
self.invert();
|
self.invert();
|
||||||
let b = self.intersect(b);
|
let b = self.intersect(b, nbits);
|
||||||
self.invert();
|
self.invert();
|
||||||
b
|
b
|
||||||
}
|
}
|
||||||
|
@ -140,10 +179,13 @@ struct big_bitv {
|
||||||
else { self.storage[w] & !flag };
|
else { self.storage[w] & !flag };
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn equals(b: &big_bitv) -> bool {
|
fn equals(b: &big_bitv, nbits: uint) -> bool {
|
||||||
let len = b.storage.len();
|
let len = b.storage.len();
|
||||||
for uint::iterate(0, len) |i| {
|
for uint::iterate(0, len) |i| {
|
||||||
if self.storage[i] != b.storage[i] { return false; }
|
let mask = big_mask(nbits, i);
|
||||||
|
if mask & self.storage[i] != mask & b.storage[i] {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,8 +205,10 @@ struct bitv {
|
||||||
self.rep = small(~small_bitv(if init {!0} else {0}));
|
self.rep = small(~small_bitv(if init {!0} else {0}));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let s = to_mut(from_elem(nbits / uint_bits + 1,
|
let nelems = nbits/uint_bits +
|
||||||
if init {!0} else {0}));
|
if nbits % uint_bits == 0 {0} else {1};
|
||||||
|
let elem = if init {!0} else {0};
|
||||||
|
let s = to_mut(from_elem(nelems, elem));
|
||||||
self.rep = big(~big_bitv(s));
|
self.rep = big(~big_bitv(s));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -182,20 +226,20 @@ struct bitv {
|
||||||
match self.rep {
|
match self.rep {
|
||||||
small(s) => match other.rep {
|
small(s) => match other.rep {
|
||||||
small(s1) => match op {
|
small(s1) => match op {
|
||||||
union => s.union(s1),
|
union => s.union(s1, self.nbits),
|
||||||
intersect => s.intersect(s1),
|
intersect => s.intersect(s1, self.nbits),
|
||||||
assign => s.become(s1),
|
assign => s.become(s1, self.nbits),
|
||||||
difference => s.difference(s1)
|
difference => s.difference(s1, self.nbits)
|
||||||
},
|
},
|
||||||
big(s1) => self.die()
|
big(s1) => self.die()
|
||||||
},
|
},
|
||||||
big(s) => match other.rep {
|
big(s) => match other.rep {
|
||||||
small(_) => self.die(),
|
small(_) => self.die(),
|
||||||
big(s1) => match op {
|
big(s1) => match op {
|
||||||
union => s.union(s1),
|
union => s.union(s1, self.nbits),
|
||||||
intersect => s.intersect(s1),
|
intersect => s.intersect(s1, self.nbits),
|
||||||
assign => s.become(s1),
|
assign => s.become(s1, self.nbits),
|
||||||
difference => s.difference(s1)
|
difference => s.difference(s1, self.nbits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,11 +324,11 @@ struct bitv {
|
||||||
if self.nbits != v1.nbits { return false; }
|
if self.nbits != v1.nbits { return false; }
|
||||||
match self.rep {
|
match self.rep {
|
||||||
small(b) => match v1.rep {
|
small(b) => match v1.rep {
|
||||||
small(b1) => b.equals(b1),
|
small(b1) => b.equals(b1, self.nbits),
|
||||||
_ => false
|
_ => false
|
||||||
},
|
},
|
||||||
big(s) => match v1.rep {
|
big(s) => match v1.rep {
|
||||||
big(s1) => s.equals(s1),
|
big(s1) => s.equals(s1, self.nbits),
|
||||||
small(_) => return false
|
small(_) => return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +374,7 @@ struct bitv {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn is_true() -> bool {
|
fn is_true() -> bool {
|
||||||
match self.rep {
|
match self.rep {
|
||||||
small(b) => b.is_true(),
|
small(b) => b.is_true(self.nbits),
|
||||||
_ => {
|
_ => {
|
||||||
for self.each() |i| { if !i { return false; } }
|
for self.each() |i| { if !i { return false; } }
|
||||||
true
|
true
|
||||||
|
@ -351,7 +395,7 @@ struct bitv {
|
||||||
|
|
||||||
fn is_false() -> bool {
|
fn is_false() -> bool {
|
||||||
match self.rep {
|
match self.rep {
|
||||||
small(b) => b.is_false(),
|
small(b) => b.is_false(self.nbits),
|
||||||
big(_) => {
|
big(_) => {
|
||||||
for self.each() |i| { if i { return false; } }
|
for self.each() |i| { if i { return false; } }
|
||||||
true
|
true
|
||||||
|
@ -456,6 +500,14 @@ mod tests {
|
||||||
assert act.eq_vec(~[1u]);
|
assert act.eq_vec(~[1u]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_2_elements() {
|
||||||
|
let b = bitv::bitv(2, false);
|
||||||
|
b.set(0, true);
|
||||||
|
b.set(1, false);
|
||||||
|
assert b.to_str() == ~"10";
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_10_elements() {
|
fn test_10_elements() {
|
||||||
let mut act;
|
let mut act;
|
||||||
|
@ -732,6 +784,33 @@ mod tests {
|
||||||
let v1 = bitv(110u, false);
|
let v1 = bitv(110u, false);
|
||||||
assert !v0.equal(v1);
|
assert !v0.equal(v1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_equal_sneaky_small() {
|
||||||
|
let a = bitv::bitv(1, false);
|
||||||
|
a.set(0, true);
|
||||||
|
|
||||||
|
let b = bitv::bitv(1, true);
|
||||||
|
b.set(0, true);
|
||||||
|
|
||||||
|
assert a.equal(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_equal_sneaky_big() {
|
||||||
|
let a = bitv::bitv(100, false);
|
||||||
|
for uint::range(0, 100) |i| {
|
||||||
|
a.set(i, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let b = bitv::bitv(100, true);
|
||||||
|
for uint::range(0, 100) |i| {
|
||||||
|
b.set(i, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert a.equal(b);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue