From 082d8314da6b6b99854f0a70f5ea8e27f2602f79 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Sun, 29 Jul 2012 16:00:55 -0700 Subject: [PATCH] Rewrite bitv to use classes and optimize its representation Rewrote bitv as a class that uses a 32-bit int as its representation for bit vectors of 32 bits or less, and a vector (the old representation) otherwise. I didn't benchmark very much, but a bit of informal benchmarking suggested this is a win. Closes #2341 --- src/libstd/bitv.rs | 814 +++++++++++------- src/libsyntax/ext/pipes/liveness.rs | 4 +- src/rustc/middle/tstate/ann.rs | 68 +- src/rustc/middle/tstate/auxiliary.rs | 24 +- .../middle/tstate/pre_post_conditions.rs | 4 +- src/rustc/middle/tstate/states.rs | 36 +- src/rustc/middle/tstate/tritv.rs | 326 ++++--- src/test/bench/sudoku.rs | 6 +- src/test/compile-fail/for-loop-decl.rs | 4 +- src/test/run-pass/bitv-perf-test.rs | 13 + 10 files changed, 721 insertions(+), 578 deletions(-) create mode 100644 src/test/run-pass/bitv-perf-test.rs diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index 145ceba4ae5..a9b3910ec19 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -1,3 +1,5 @@ +import vec::{to_mut, from_elem}; + export bitv; export union; export intersect; @@ -17,94 +19,265 @@ export eq_vec; export methods; -// FIXME (#2341): With recursive object types, we could implement binary -// methods like union, intersection, and difference. At that point, we could -// write an optimizing version of this module that produces a different obj -// for the case where nbits <= 32. +class small_bitv { + let mut bits: u32; + new(bits: u32) { self.bits = bits; } + priv { + #[inline(always)] + fn bits_op(right_bits: u32, f: fn(u32, u32) -> u32) -> bool { + let old_b: u32 = self.bits; + let new_b = f(old_b, right_bits); + self.bits = new_b; + old_b != new_b + } + } + #[inline(always)] + fn union(s: &small_bitv) -> bool { + self.bits_op(s.bits, |u1, u2| { u1 | u2 }) + } + #[inline(always)] + fn intersect(s: &small_bitv) -> bool { + self.bits_op(s.bits, |u1, u2| { u1 & u2 }) + } + #[inline(always)] + fn become(s: &small_bitv) -> bool { + let old = self.bits; + self.bits = s.bits; + old != self.bits + } + #[inline(always)] + fn difference(s: &small_bitv) -> bool { + let old = self.bits; + self.bits &= !s.bits; + old != self.bits + } + #[inline(always)] + pure fn get(i: uint) -> bool { + (self.bits & (1 << i)) != 0 + } + #[inline(always)] + fn set(i: uint, x: bool) { + if x { + self.bits |= 1< bool { self.bits == b.bits } + #[inline(always)] + fn clear() { self.bits = 0; } + #[inline(always)] + fn set_all() { self.bits = !0; } + #[inline(always)] + fn is_true() -> bool { self.bits == !0 } + #[inline(always)] + fn is_false() -> bool { self.bits == 0 } + #[inline(always)] + fn invert() { self.bits = !self.bits; } +} -/// The bitvector type -type bitv = {storage: ~[mut uint], nbits: uint}; +class big_bitv { +// only mut b/c of clone and lack of other constructor + let mut storage: ~[mut uint]; + new(-storage: ~[mut uint]) { + self.storage <- storage; + } + priv { + #[inline(always)] + fn process(b: &big_bitv, op: fn(uint, uint) -> uint) -> bool { + let len = b.storage.len(); + assert (self.storage.len() == len); + let mut changed = false; + do uint::range(0, len) |i| { + let w0 = self.storage[i]; + let w1 = b.storage[i]; + let w = op(w0, w1); + if w0 != w unchecked { changed = true; self.storage[i] = w; }; + true + }; + changed + } + } + #[inline(always)] + fn each_storage(op: fn(&uint) -> bool) { + for uint::range(0, self.storage.len()) |i| { + let mut w = self.storage[i]; + let b = !op(w); + self.storage[i] = w; + if !b { break; } + } + } + #[inline(always)] + fn invert() { for self.each_storage() |w| { w = !w } } + #[inline(always)] + fn union(b: &big_bitv) -> bool { self.process(b, lor) } + #[inline(always)] + fn intersect(b: &big_bitv) -> bool { self.process(b, land) } + #[inline(always)] + fn become(b: &big_bitv) -> bool { self.process(b, right) } + #[inline(always)] + fn difference(b: &big_bitv) -> bool { + self.invert(); + let b = self.intersect(b); + self.invert(); + b + } + #[inline(always)] + pure fn get(i: uint) -> bool { + let w = i / uint_bits; + let b = i % uint_bits; + let x = 1 & self.storage[w] >> b; + x == 1 + } + #[inline(always)] + fn set(i: uint, x: bool) { + let w = i / uint_bits; + let b = i % uint_bits; + let flag = 1 << b; + self.storage[w] = if x { self.storage[w] | flag } + else { self.storage[w] & !flag }; + } + #[inline(always)] + fn equals(b: &big_bitv) -> bool { + let len = b.storage.len(); + for uint::iterate(0, len) |i| { + if self.storage[i] != b.storage[i] { ret false; } + } + } +} -#[cfg(target_arch="x86")] -const uint_bits: uint = 32; -#[cfg(target_arch="x86_64")] -const uint_bits: uint = 64; +enum a_bitv { big(~big_bitv), small(~small_bitv) } -/** - * Constructs a bitvector - * - * # Arguments - * - * * nbits - The number of bits in the bitvector - * * init - If true then the bits are initialized to 1, otherwise 0 - */ -fn bitv(nbits: uint, init: bool) -> bitv { - let elt = if init { !0u } else { 0u }; - let storage = vec::to_mut(vec::from_elem(nbits / uint_bits + 1u, elt)); - ret {storage: storage, nbits: nbits}; -} +enum op {union, intersect, assign, difference} -fn process(v0: bitv, v1: bitv, op: fn(uint, uint) -> uint) -> bool { - let len = vec::len(v1.storage); - assert (vec::len(v0.storage) == len); - assert (v0.nbits == v1.nbits); - let mut changed = false; - for uint::range(0u, len) |i| { - let w0 = v0.storage[i]; - let w1 = v1.storage[i]; - let w = op(w0, w1); - if w0 != w { changed = true; v0.storage[i] = w; } - }; - ret changed; -} +// The bitvector type +class bitv { + let rep: a_bitv; + let nbits: uint; + new(nbits: uint, init: bool) { + self.nbits = nbits; + if nbits <= 32 { + self.rep = small(~small_bitv(if init {!0} else {0})); + } + else { + let s = to_mut(from_elem(nbits / uint_bits + 1, + if init {!0} else {0})); + self.rep = big(~big_bitv(s)); + }; + } + + priv { + fn die() -> ! { + fail ~"Tried to do operation on bit vectors with \ + different sizes"; + } + #[inline(always)] + fn do_op(op: op, other: &bitv) -> bool { + if self.nbits != other.nbits { + self.die(); + } + alt self.rep { + small(s) { + alt other.rep { + small(s1) { + alt op { + union { s.union(s1) } + intersect { s.intersect(s1) } + assign { s.become(s1) } + difference { s.difference(s1) } + } + } + big(s1) { + self.die(); + } + } + } + big(s) { + alt other.rep { + small(_) { self.die(); } + big(s1) { + alt op { + union { s.union(s1) } + intersect { s.intersect(s1) } + assign { s.become(s1) } + difference { s.difference(s1) } + } + } + } + } + } + } + } /** * Calculates the union of two bitvectors * - * Sets `v0` to the union of `v0` and `v1`. Both bitvectors must be the - * same length. Returns 'true' if `v0` was changed. - */ -fn union(v0: bitv, v1: bitv) -> bool { - process(v0, v1, |a, b| a | b) -} + * Sets `self` to the union of `self` and `v1`. Both bitvectors must be + * the same length. Returns 'true' if `self` changed. +*/ + #[inline(always)] + fn union(v1: &bitv) -> bool { self.do_op(union, v1) } /** * Calculates the intersection of two bitvectors * - * Sets `v0` to the intersection of `v0` and `v1`. Both bitvectors must be the - * same length. Returns 'true' if `v0` was changed. - */ -fn intersect(v0: bitv, v1: bitv) -> bool { - process(v0, v1, |a, b| a & b) -} - -fn right(_w0: uint, w1: uint) -> uint { ret w1; } + * Sets `self` to the intersection of `self` and `v1`. Both bitvectors must be + * the same length. Returns 'true' if `self` changed. +*/ + #[inline(always)] + fn intersect(v1: &bitv) -> bool { self.do_op(intersect, v1) } /** - * Assigns the value of `v1` to `v0` + * Assigns the value of `v1` to `self` * - * Both bitvectors must be the same length. Returns `true` if `v0` was changed + * Both bitvectors must be the same length. Returns `true` if `self` was + * changed */ -fn assign(v0: bitv, v1: bitv) -> bool { - let sub = right; ret process(v0, v1, sub); -} + #[inline(always)] + fn assign(v: &bitv) -> bool { self.do_op(assign, v) } + + /// Makes a copy of a bitvector + #[inline(always)] + fn clone() -> ~bitv { + ~alt self.rep { + small(b) { + bitv{nbits: self.nbits, rep: small(~small_bitv{bits: b.bits})} + } + big(b) { + let st = to_mut(from_elem(self.nbits / uint_bits + 1, 0)); + let len = st.len(); + for uint::range(0, len) |i| { st[i] = b.storage[i]; }; + bitv{nbits: self.nbits, rep: big(~big_bitv{storage: st})} + } + } + } -/// Makes a copy of a bitvector -fn clone(v: bitv) -> bitv { - copy v -} + /// Retrieve the value at index `i` + #[inline(always)] + pure fn get(i: uint) -> bool { + assert (i < self.nbits); + alt self.rep { + big(b) { b.get(i) } + small(s) { s.get(i) } + } + } -/// Retrieve the value at index `i` -#[inline(always)] -pure fn get(v: bitv, i: uint) -> bool { - assert (i < v.nbits); - let bits = uint_bits; - let w = i / bits; - let b = i % bits; - let x = 1u & v.storage[w] >> b; - ret x == 1u; -} +/** + * Set the value of a bit at a given index + * + * `i` must be less than the length of the bitvector. + */ + #[inline(always)] + fn set(i: uint, x: bool) { + assert (i < self.nbits); + alt self.rep { + big(b) { b.set(i, x); } + small(s) { s.set(i, x); } + } + } /** * Compares two bitvectors @@ -112,25 +285,57 @@ fn clone(v: bitv) -> bitv { * Both bitvectors must be the same length. Returns `true` if both bitvectors * contain identical elements. */ -fn equal(v0: bitv, v1: bitv) -> bool { - if v0.nbits != v1.nbits { ret false; } - let len = vec::len(v1.storage); - for uint::iterate(0u, len) |i| { - if v0.storage[i] != v1.storage[i] { ret false; } + #[inline(always)] + fn equal(v1: bitv) -> bool { + if self.nbits != v1.nbits { ret false; } + alt self.rep { + small(b) { + alt v1.rep { + small(b1) { b.equals(b1) } + _ { false } + } + } + big(s) { + alt v1.rep { + big(s1) { + s.equals(s1) + } + small(_) { ret false; } + } + } + } } -} -/// Set all bits to 0 -#[inline(always)] -fn clear(v: bitv) { for each_storage(v) |w| { w = 0u } } + /// Set all bits to 0 + #[inline(always)] + fn clear() { + alt self.rep { + small(b) { b.clear(); } + big(s) { + for s.each_storage() |w| { w = 0u } + } + } + } -/// Set all bits to 1 -#[inline(always)] -fn set_all(v: bitv) { for each_storage(v) |w| { w = !0u } } + /// Set all bits to 1 + #[inline(always)] + fn set_all() { + alt self.rep { + small(b) { b.set_all(); } + big(s) { + for s.each_storage() |w| { w = !0u } } + } + } -/// Invert all bits -#[inline(always)] -fn invert(v: bitv) { for each_storage(v) |w| { w = !w } } + /// Invert all bits + #[inline(always)] + fn invert() { + alt self.rep { + small(b) { b.invert(); } + big(s) { + for s.each_storage() |w| { w = !w } } + } + } /** * Calculate the difference between two bitvectors @@ -140,81 +345,68 @@ fn invert(v: bitv) { for each_storage(v) |w| { w = !w } } * * Returns `true` if `v0` was changed. */ -fn difference(v0: bitv, v1: bitv) -> bool { - invert(v1); - let b = intersect(v0, v1); - invert(v1); - ret b; -} - -/** - * Set the value of a bit at a given index - * - * `i` must be less than the length of the bitvector. - */ -#[inline(always)] -fn set(v: bitv, i: uint, x: bool) { - assert (i < v.nbits); - let bits = uint_bits; - let w = i / bits; - let b = i % bits; - let flag = 1u << b; - v.storage[w] = if x { v.storage[w] | flag } else { v.storage[w] & !flag }; -} + #[inline(always)] + fn difference(v: ~bitv) -> bool { self.do_op(difference, v) } + + /// Returns true if all bits are 1 + #[inline(always)] + fn is_true() -> bool { + alt self.rep { + small(b) { b.is_true() } + _ { + for self.each() |i| { if !i { ret false; } } + true + } + } + } + #[inline(always)] + fn each(f: fn(bool) -> bool) { + let mut i = 0; + while i < self.nbits { + if !f(self.get(i)) { break; } + i += 1; + } + } -/// Returns true if all bits are 1 -fn is_true(v: bitv) -> bool { - for each(v) |i| { if !i { ret false; } } - ret true; -} + /// Returns true if all bits are 0 + fn is_false() -> bool { + alt self.rep { + small(b) { b.is_false() } + big(_) { + for self.each() |i| { if i { ret false; } } + true + } + } + } -/// Returns true if all bits are 0 -fn is_false(v: bitv) -> bool { - for each(v) |i| { if i { ret false; } } - ret true; -} + fn init_to_vec(i: uint) -> uint { + ret if self.get(i) { 1 } else { 0 }; + } /** - * Converts the bitvector to a vector of uint with the same length. + * Converts `self` to a vector of uint with the same length. * * Each uint in the resulting vector has either value 0u or 1u. */ -fn to_vec(v: bitv) -> ~[uint] { - vec::from_fn::(v.nbits, |i| if get(v, i) { 1 } else { 0 }) -} - -#[inline(always)] -fn each(v: bitv, f: fn(bool) -> bool) { - let mut i = 0u; - while i < v.nbits { - if !f(get(v, i)) { break; } - i = i + 1u; + fn to_vec() -> ~[uint] { + let sub = |x| self.init_to_vec(x); + ret vec::from_fn::(self.nbits, sub); } -} - -#[inline(always)] -fn each_storage(v: bitv, op: fn(&uint) -> bool) { - for uint::range(0u, vec::len(v.storage)) |i| { - let mut w = v.storage[i]; - let b = !op(w); - v.storage[i] = w; - if !b { break; } - } -} /** - * Converts the bitvector to a string. + * Converts `self` to a string. * - * The resulting string has the same length as the bitvector, and each + * The resulting string has the same length as `self`, and each * character is either '0' or '1'. */ -fn to_str(v: bitv) -> ~str { - let mut rs = ~""; - for each(v) |i| { if i { rs += ~"1"; } else { rs += ~"0"; } } - ret rs; -} + fn to_str() -> ~str { + let mut rs = ~""; + for self.each() |i| { if i { rs += "1"; } else { rs += "0"; } }; + rs + } + /** * Compare a bitvector to a vector of uint @@ -222,59 +414,17 @@ fn to_str(v: bitv) -> ~str { * The uint vector is expected to only contain the values 0u and 1u. Both the * bitvector and vector must have the same length */ -fn eq_vec(v0: bitv, v1: ~[uint]) -> bool { - assert (v0.nbits == vec::len::(v1)); - let len = v0.nbits; - let mut i = 0u; - while i < len { - let w0 = get(v0, i); - let w1 = v1[i]; - if !w0 && w1 != 0u || w0 && w1 == 0u { ret false; } - i = i + 1u; - } - ret true; -} - -trait methods { - fn union(rhs: bitv) -> bool; - fn intersect(rhs: bitv) -> bool; - fn assign(rhs: bitv) -> bool; - pure fn get(i: uint) -> bool; - fn [](i: uint) -> bool; - fn eq(rhs: bitv) -> bool; - fn clear(); - fn set_all(); - fn invert(); - fn difference(rhs: bitv) -> bool; - fn set(i: uint, x: bool); - fn is_true() -> bool; - fn is_false() -> bool; - fn to_vec() -> ~[uint]; - fn each(f: fn(bool) -> bool); - fn each_storage(f: fn(&uint) -> bool); - fn eq_vec(v: ~[uint]) -> bool; - - fn ones(f: fn(uint) -> bool); -} - -impl of methods for bitv { - fn union(rhs: bitv) -> bool { union(self, rhs) } - fn intersect(rhs: bitv) -> bool { intersect(self, rhs) } - fn assign(rhs: bitv) -> bool { assign(self, rhs) } - pure fn get(i: uint) -> bool { get(self, i) } - fn [](i: uint) -> bool { self.get(i) } - fn eq(rhs: bitv) -> bool { equal(self, rhs) } - fn clear() { clear(self) } - fn set_all() { set_all(self) } - fn invert() { invert(self) } - fn difference(rhs: bitv) -> bool { difference(self, rhs) } - fn set(i: uint, x: bool) { set(self, i, x) } - fn is_true() -> bool { is_true(self) } - fn is_false() -> bool { is_false(self) } - fn to_vec() -> ~[uint] { to_vec(self) } - fn each(f: fn(bool) -> bool) { each(self, f) } - fn each_storage(f: fn(&uint) -> bool) { each_storage(self, f) } - fn eq_vec(v: ~[uint]) -> bool { eq_vec(self, v) } + fn eq_vec(v: ~[uint]) -> bool { + assert self.nbits == v.len(); + let mut i = 0; + while i < self.nbits { + let w0 = self.get(i); + let w1 = v[i]; + if !w0 && w1 != 0u || w0 && w1 == 0u { ret false; } + i = i + 1; + } + true + } fn ones(f: fn(uint) -> bool) { for uint::range(0, self.nbits) |i| { @@ -283,7 +433,16 @@ fn ones(f: fn(uint) -> bool) { } } } -} + +} // end of bitv class + +const uint_bits: uint = 32u + (1u << 32u >> 27u); + +pure fn lor(w0: uint, w1: uint) -> uint { ret w0 | w1; } + +pure fn land(w0: uint, w1: uint) -> uint { ret w0 & w1; } + +pure fn right(_w0: uint, w1: uint) -> uint { ret w1; } impl extensions of ops::index for bitv { pure fn index(&&i: uint) -> bool { @@ -291,19 +450,15 @@ impl extensions of ops::index for bitv { } } -impl of to_str::to_str for bitv { - fn to_str() -> ~str { to_str(self) } -} - #[cfg(test)] mod tests { #[test] fn test_to_str() { let zerolen = bitv(0u, false); - assert to_str(zerolen) == ~""; + assert zerolen.to_str() == ~""; let eightbits = bitv(8u, false); - assert to_str(eightbits) == ~"00000000"; + assert eightbits.to_str() == ~"00000000"; } #[test] @@ -312,16 +467,16 @@ fn test_0_elements() { let mut exp; act = bitv(0u, false); exp = vec::from_elem::(0u, 0u); - assert (eq_vec(act, exp)); + assert act.eq_vec(exp); } #[test] fn test_1_element() { let mut act; act = bitv(1u, false); - assert (eq_vec(act, ~[0u])); + assert act.eq_vec(~[0u]); act = bitv(1u, true); - assert (eq_vec(act, ~[1u])); + assert act.eq_vec(~[1u]); } #[test] @@ -330,37 +485,37 @@ fn test_10_elements() { // all 0 act = bitv(10u, false); - assert (eq_vec(act, ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); + assert (act.eq_vec(~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); // all 1 act = bitv(10u, true); - assert (eq_vec(act, ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u])); + assert (act.eq_vec(~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u])); // mixed act = bitv(10u, false); - set(act, 0u, true); - set(act, 1u, true); - set(act, 2u, true); - set(act, 3u, true); - set(act, 4u, true); - assert (eq_vec(act, ~[1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u])); + act.set(0u, true); + act.set(1u, true); + act.set(2u, true); + act.set(3u, true); + act.set(4u, true); + assert (act.eq_vec(~[1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u])); // mixed act = bitv(10u, false); - set(act, 5u, true); - set(act, 6u, true); - set(act, 7u, true); - set(act, 8u, true); - set(act, 9u, true); - assert (eq_vec(act, ~[0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u])); + act.set(5u, true); + act.set(6u, true); + act.set(7u, true); + act.set(8u, true); + act.set(9u, true); + assert (act.eq_vec(~[0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u])); // mixed act = bitv(10u, false); - set(act, 0u, true); - set(act, 3u, true); - set(act, 6u, true); - set(act, 9u, true); - assert (eq_vec(act, ~[1u, 0u, 0u, 1u, 0u, 0u, 1u, 0u, 0u, 1u])); + act.set(0u, true); + act.set(3u, true); + act.set(6u, true); + act.set(9u, true); + assert (act.eq_vec(~[1u, 0u, 0u, 1u, 0u, 0u, 1u, 0u, 0u, 1u])); } #[test] @@ -369,68 +524,68 @@ fn test_31_elements() { // all 0 act = bitv(31u, false); - assert (eq_vec(act, + assert (act.eq_vec( ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); // all 1 act = bitv(31u, true); - assert (eq_vec(act, + assert (act.eq_vec( ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u])); // mixed act = bitv(31u, false); - set(act, 0u, true); - set(act, 1u, true); - set(act, 2u, true); - set(act, 3u, true); - set(act, 4u, true); - set(act, 5u, true); - set(act, 6u, true); - set(act, 7u, true); - assert (eq_vec(act, + act.set(0u, true); + act.set(1u, true); + act.set(2u, true); + act.set(3u, true); + act.set(4u, true); + act.set(5u, true); + act.set(6u, true); + act.set(7u, true); + assert (act.eq_vec( ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); // mixed act = bitv(31u, false); - set(act, 16u, true); - set(act, 17u, true); - set(act, 18u, true); - set(act, 19u, true); - set(act, 20u, true); - set(act, 21u, true); - set(act, 22u, true); - set(act, 23u, true); - assert (eq_vec(act, + act.set(16u, true); + act.set(17u, true); + act.set(18u, true); + act.set(19u, true); + act.set(20u, true); + act.set(21u, true); + act.set(22u, true); + act.set(23u, true); + assert (act.eq_vec( ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); // mixed act = bitv(31u, false); - set(act, 24u, true); - set(act, 25u, true); - set(act, 26u, true); - set(act, 27u, true); - set(act, 28u, true); - set(act, 29u, true); - set(act, 30u, true); - assert (eq_vec(act, + act.set(24u, true); + act.set(25u, true); + act.set(26u, true); + act.set(27u, true); + act.set(28u, true); + act.set(29u, true); + act.set(30u, true); + assert (act.eq_vec( ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u])); // mixed act = bitv(31u, false); - set(act, 3u, true); - set(act, 17u, true); - set(act, 30u, true); - assert (eq_vec(act, + act.set(3u, true); + act.set(17u, true); + act.set(30u, true); + assert (act.eq_vec( ~[0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u])); @@ -442,70 +597,70 @@ fn test_32_elements() { // all 0 act = bitv(32u, false); - assert (eq_vec(act, + assert (act.eq_vec( ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); // all 1 act = bitv(32u, true); - assert (eq_vec(act, + assert (act.eq_vec( ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u])); // mixed act = bitv(32u, false); - set(act, 0u, true); - set(act, 1u, true); - set(act, 2u, true); - set(act, 3u, true); - set(act, 4u, true); - set(act, 5u, true); - set(act, 6u, true); - set(act, 7u, true); - assert (eq_vec(act, + act.set(0u, true); + act.set(1u, true); + act.set(2u, true); + act.set(3u, true); + act.set(4u, true); + act.set(5u, true); + act.set(6u, true); + act.set(7u, true); + assert (act.eq_vec( ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); // mixed act = bitv(32u, false); - set(act, 16u, true); - set(act, 17u, true); - set(act, 18u, true); - set(act, 19u, true); - set(act, 20u, true); - set(act, 21u, true); - set(act, 22u, true); - set(act, 23u, true); - assert (eq_vec(act, + act.set(16u, true); + act.set(17u, true); + act.set(18u, true); + act.set(19u, true); + act.set(20u, true); + act.set(21u, true); + act.set(22u, true); + act.set(23u, true); + assert (act.eq_vec( ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); // mixed act = bitv(32u, false); - set(act, 24u, true); - set(act, 25u, true); - set(act, 26u, true); - set(act, 27u, true); - set(act, 28u, true); - set(act, 29u, true); - set(act, 30u, true); - set(act, 31u, true); - assert (eq_vec(act, + act.set(24u, true); + act.set(25u, true); + act.set(26u, true); + act.set(27u, true); + act.set(28u, true); + act.set(29u, true); + act.set(30u, true); + act.set(31u, true); + assert (act.eq_vec( ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u])); // mixed act = bitv(32u, false); - set(act, 3u, true); - set(act, 17u, true); - set(act, 30u, true); - set(act, 31u, true); - assert (eq_vec(act, + act.set(3u, true); + act.set(17u, true); + act.set(30u, true); + act.set(31u, true); + assert (act.eq_vec( ~[0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u])); @@ -517,71 +672,71 @@ fn test_33_elements() { // all 0 act = bitv(33u, false); - assert (eq_vec(act, + assert (act.eq_vec( ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); // all 1 act = bitv(33u, true); - assert (eq_vec(act, + assert (act.eq_vec( ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u])); // mixed act = bitv(33u, false); - set(act, 0u, true); - set(act, 1u, true); - set(act, 2u, true); - set(act, 3u, true); - set(act, 4u, true); - set(act, 5u, true); - set(act, 6u, true); - set(act, 7u, true); - assert (eq_vec(act, + act.set(0u, true); + act.set(1u, true); + act.set(2u, true); + act.set(3u, true); + act.set(4u, true); + act.set(5u, true); + act.set(6u, true); + act.set(7u, true); + assert (act.eq_vec( ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); // mixed act = bitv(33u, false); - set(act, 16u, true); - set(act, 17u, true); - set(act, 18u, true); - set(act, 19u, true); - set(act, 20u, true); - set(act, 21u, true); - set(act, 22u, true); - set(act, 23u, true); - assert (eq_vec(act, + act.set(16u, true); + act.set(17u, true); + act.set(18u, true); + act.set(19u, true); + act.set(20u, true); + act.set(21u, true); + act.set(22u, true); + act.set(23u, true); + assert (act.eq_vec( ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])); // mixed act = bitv(33u, false); - set(act, 24u, true); - set(act, 25u, true); - set(act, 26u, true); - set(act, 27u, true); - set(act, 28u, true); - set(act, 29u, true); - set(act, 30u, true); - set(act, 31u, true); - assert (eq_vec(act, + act.set(24u, true); + act.set(25u, true); + act.set(26u, true); + act.set(27u, true); + act.set(28u, true); + act.set(29u, true); + act.set(30u, true); + act.set(31u, true); + assert (act.eq_vec( ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u])); // mixed act = bitv(33u, false); - set(act, 3u, true); - set(act, 17u, true); - set(act, 30u, true); - set(act, 31u, true); - set(act, 32u, true); - assert (eq_vec(act, + act.set(3u, true); + act.set(17u, true); + act.set(30u, true); + act.set(31u, true); + act.set(32u, true); + assert (act.eq_vec( ~[0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u])); @@ -591,16 +746,15 @@ fn test_33_elements() { fn test_equal_differing_sizes() { let v0 = bitv(10u, false); let v1 = bitv(11u, false); - assert !equal(v0, v1); + assert !v0.equal(v1); } #[test] fn test_equal_greatly_differing_sizes() { let v0 = bitv(10u, false); let v1 = bitv(110u, false); - assert !equal(v0, v1); + assert !v0.equal(v1); } - } // diff --git a/src/libsyntax/ext/pipes/liveness.rs b/src/libsyntax/ext/pipes/liveness.rs index d8467e36c84..c3ae0fb80fd 100644 --- a/src/libsyntax/ext/pipes/liveness.rs +++ b/src/libsyntax/ext/pipes/liveness.rs @@ -29,7 +29,7 @@ import dvec::extensions; -import std::bitv::{bitv, methods}; +import std::bitv::{bitv}; import proto::methods; import ast_builder::empty_span; @@ -38,7 +38,7 @@ fn analyze(proto: protocol, _cx: ext_ctxt) { #debug("initializing colive analysis"); let num_states = proto.num_states(); let colive = do (copy proto.states).map_to_vec |state| { - let bv = bitv(num_states, false); + let bv = ~bitv(num_states, false); for state.reachable |s| { bv.set(s.id, true); } diff --git a/src/rustc/middle/tstate/ann.rs b/src/rustc/middle/tstate/ann.rs index d1f19ba6e1f..7729c3ffc1d 100644 --- a/src/rustc/middle/tstate/ann.rs +++ b/src/rustc/middle/tstate/ann.rs @@ -53,8 +53,8 @@ fn empty_poststate(num_vars: uint) -> poststate { fn false_postcond(num_vars: uint) -> postcond { let rslt = create_tritv(num_vars); - tritv_set_all(rslt); - ret rslt; + rslt.set_all(); + rslt } fn empty_pre_post(num_vars: uint) -> pre_and_post { @@ -76,15 +76,11 @@ fn empty_ann(num_vars: uint) -> ts_ann { fn get_post(&&p: pre_and_post) -> postcond { ret p.postcondition; } -fn difference(p1: precond, p2: precond) -> bool { - ret tritv_difference(p1, p2); -} +fn difference(p1: precond, p2: precond) -> bool { p1.difference(p2) } -fn union(p1: precond, p2: precond) -> bool { ret tritv_union(p1, p2); } +fn union(p1: precond, p2: precond) -> bool { p1.union(p2) } -fn intersect(p1: precond, p2: precond) -> bool { - ret tritv_intersect(p1, p2); -} +fn intersect(p1: precond, p2: precond) -> bool { p1.intersect(p2) } fn pps_len(p: pre_and_post) -> uint { // gratuitous check @@ -95,13 +91,13 @@ fn pps_len(p: pre_and_post) -> uint { fn require(i: uint, p: pre_and_post) { // sets the ith bit in p's pre - tritv_set(i, p.precondition, ttrue); + p.precondition.set(i, ttrue); } fn require_and_preserve(i: uint, p: pre_and_post) { // sets the ith bit in p's pre and post - tritv_set(i, p.precondition, ttrue); - tritv_set(i, p.postcondition, ttrue); + p.precondition.set(i, ttrue); + p.postcondition.set(i, ttrue); } fn set_in_postcond(i: uint, p: pre_and_post) -> bool { @@ -110,8 +106,8 @@ fn set_in_postcond(i: uint, p: pre_and_post) -> bool { } fn set_in_postcond_(i: uint, p: postcond) -> bool { - let was_set = tritv_get(p, i); - tritv_set(i, p, ttrue); + let was_set = p.get(i); + p.set(i, ttrue); ret was_set != ttrue; } @@ -121,8 +117,8 @@ fn set_in_poststate(i: uint, s: pre_and_post_state) -> bool { } fn set_in_poststate_(i: uint, p: poststate) -> bool { - let was_set = tritv_get(p, i); - tritv_set(i, p, ttrue); + let was_set = p.get(i); + p.set(i, ttrue); ret was_set != ttrue; } @@ -133,8 +129,8 @@ fn clear_in_poststate(i: uint, s: pre_and_post_state) -> bool { } fn clear_in_poststate_(i: uint, s: poststate) -> bool { - let was_set = tritv_get(s, i); - tritv_set(i, s, tfalse); + let was_set = s.get(i); + s.set(i, tfalse); ret was_set != tfalse; } @@ -144,61 +140,61 @@ fn clear_in_prestate(i: uint, s: pre_and_post_state) -> bool { } fn clear_in_prestate_(i: uint, s: prestate) -> bool { - let was_set = tritv_get(s, i); - tritv_set(i, s, tfalse); + let was_set = s.get(i); + s.set(i, tfalse); ret was_set != tfalse; } fn clear_in_postcond(i: uint, s: pre_and_post) -> bool { // sets the ith bit in p's post - let was_set = tritv_get(s.postcondition, i); - tritv_set(i, s.postcondition, tfalse); + let was_set = s.postcondition.get(i); + s.postcondition.set(i, tfalse); ret was_set != tfalse; } // Sets all the bits in a's precondition to equal the // corresponding bit in p's precondition. fn set_precondition(a: ts_ann, p: precond) { - tritv_copy(a.conditions.precondition, p); + a.conditions.precondition.become(p); } // Sets all the bits in a's postcondition to equal the // corresponding bit in p's postcondition. fn set_postcondition(a: ts_ann, p: postcond) { - tritv_copy(a.conditions.postcondition, p); + a.conditions.postcondition.become(p); } // Sets all the bits in a's prestate to equal the // corresponding bit in p's prestate. fn set_prestate(a: ts_ann, p: prestate) -> bool { - ret tritv_copy(a.states.prestate, p); + a.states.prestate.become(p) } // Sets all the bits in a's postcondition to equal the // corresponding bit in p's postcondition. fn set_poststate(a: ts_ann, p: poststate) -> bool { - ret tritv_copy(a.states.poststate, p); + a.states.poststate.become(p) } // Set all the bits in p that are set in new fn extend_prestate(p: prestate, newv: poststate) -> bool { - ret tritv_union(p, newv); + p.union(newv) } // Set all the bits in p that are set in new fn extend_poststate(p: poststate, newv: poststate) -> bool { - ret tritv_union(p, newv); + p.union(newv) } // Sets the given bit in p to "don't care" fn relax_prestate(i: uint, p: prestate) -> bool { - let was_set = tritv_get(p, i); - tritv_set(i, p, dont_care); + let was_set = p.get(i); + p.set(i, dont_care); ret was_set != dont_care; } @@ -211,10 +207,10 @@ fn relax_poststate(i: uint, p: poststate) -> bool { fn relax_precond(i: uint, p: precond) { relax_prestate(i, p); } // Sets all the bits in p to "don't care" -fn clear(p: precond) { tritv_clear(p); } +fn clear(p: precond) { p.clear(); } // Sets all the bits in p to true -fn set(p: precond) { tritv_set_all(p); } +fn set(p: precond) { p.set_all(); } fn ann_precond(a: ts_ann) -> precond { ret a.conditions.precondition; } @@ -227,16 +223,16 @@ fn pp_clone(p: pre_and_post) -> pre_and_post { postcondition: clone(p.postcondition)}; } -fn clone(p: prestate) -> prestate { ret tritv_clone(p); } +fn clone(p: prestate) -> prestate { p.clone() } // returns true if a implies b // that is, returns true except if for some bits c and d, // c = 1 and d = either 0 or "don't know" fn implies(a: t, b: t) -> bool { - let tmp = tritv_clone(b); - tritv_difference(tmp, a); - ret tritv_doesntcare(tmp); + let tmp = b.clone(); + tmp.difference(a); + tmp.doesntcare() } fn trit_str(t: trit) -> ~str { diff --git a/src/rustc/middle/tstate/auxiliary.rs b/src/rustc/middle/tstate/auxiliary.rs index a098757175c..1e6bcd52ede 100644 --- a/src/rustc/middle/tstate/auxiliary.rs +++ b/src/rustc/middle/tstate/auxiliary.rs @@ -15,7 +15,7 @@ clear_in_poststate_}; import driver::session::session; import dvec::{dvec, extensions}; -import tritv::{dont_care, tfalse, tritv_get, ttrue}; +import tritv::{trit, tfalse, ttrue, dont_care, t}; import syntax::print::pprust::{constr_args_to_str, lit_to_str}; @@ -59,7 +59,7 @@ fn tritv_to_str(fcx: fn_ctxt, v: tritv::t) -> ~str { let mut s = ~""; let mut comma = false; for constraints(fcx).each |p| { - alt tritv_get(v, p.bit_num) { + alt v.get(p.bit_num) { dont_care { } tt { s += @@ -80,8 +80,8 @@ fn first_difference_string(fcx: fn_ctxt, expected: tritv::t, actual: tritv::t) -> ~str { let mut s = ~""; for constraints(fcx).each |c| { - if tritv_get(expected, c.bit_num) == ttrue && - tritv_get(actual, c.bit_num) != ttrue { + if expected.get(c.bit_num) == ttrue && + actual.get(c.bit_num) != ttrue { s = constraint_to_str(fcx.ccx.tcx, c.c); break; } @@ -108,8 +108,8 @@ fn tos(v: ~[uint]) -> ~str { fn log_cond_err(v: ~[uint]) { log(error, tos(v)); } fn log_pp(pp: pre_and_post) { - let p1 = tritv::to_vec(pp.precondition); - let p2 = tritv::to_vec(pp.postcondition); + let p1 = pp.precondition.to_vec(); + let p2 = pp.postcondition.to_vec(); #debug("pre:"); log_cond(p1); #debug("post:"); @@ -117,8 +117,8 @@ fn log_pp(pp: pre_and_post) { } fn log_pp_err(pp: pre_and_post) { - let p1 = tritv::to_vec(pp.precondition); - let p2 = tritv::to_vec(pp.postcondition); + let p1 = pp.precondition.to_vec(); + let p2 = pp.postcondition.to_vec(); #error("pre:"); log_cond_err(p1); #error("post:"); @@ -126,8 +126,8 @@ fn log_pp_err(pp: pre_and_post) { } fn log_states(pp: pre_and_post_state) { - let p1 = tritv::to_vec(pp.prestate); - let p2 = tritv::to_vec(pp.poststate); + let p1 = pp.prestate.to_vec(); + let p2 = pp.poststate.to_vec(); #debug("prestate:"); log_cond(p1); #debug("poststate:"); @@ -135,8 +135,8 @@ fn log_states(pp: pre_and_post_state) { } fn log_states_err(pp: pre_and_post_state) { - let p1 = tritv::to_vec(pp.prestate); - let p2 = tritv::to_vec(pp.poststate); + let p1 = pp.prestate.to_vec(); + let p2 = pp.poststate.to_vec(); #error("prestate:"); log_cond_err(p1); #error("poststate:"); diff --git a/src/rustc/middle/tstate/pre_post_conditions.rs b/src/rustc/middle/tstate/pre_post_conditions.rs index 591f152acb3..36b7d9c7308 100644 --- a/src/rustc/middle/tstate/pre_post_conditions.rs +++ b/src/rustc/middle/tstate/pre_post_conditions.rs @@ -184,7 +184,7 @@ fn handle_update(fcx: fn_ctxt, parent: @expr, lhs: @expr, rhs: @expr, alt lhs.node { expr_path(p) { let post = expr_postcond(fcx.ccx, parent); - let tmp = tritv_clone(post); + let tmp = post.clone(); alt ty { oper_move { @@ -497,7 +497,7 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) { /* Clear out anything that the previous initializer guaranteed */ let e_pp = expr_pp(fcx.ccx, an_init.expr); - tritv_copy(prev_pp.precondition, + prev_pp.precondition.become( seq_preconds(fcx, ~[prev_pp, e_pp])); /* Include the LHSs too, since those aren't in the diff --git a/src/rustc/middle/tstate/states.rs b/src/rustc/middle/tstate/states.rs index ebe476b3d7f..e427841103f 100644 --- a/src/rustc/middle/tstate/states.rs +++ b/src/rustc/middle/tstate/states.rs @@ -1,6 +1,6 @@ import ann::*; import aux::*; -import tritv::{tritv_clone, tritv_set, ttrue}; +import tritv::*; import syntax::print::pprust::block_to_str; import bitvectors::*; @@ -57,14 +57,14 @@ fn handle_move_or_copy(fcx: fn_ctxt, post: poststate, rhs_path: @path, fn seq_states(fcx: fn_ctxt, pres: prestate, bindings: ~[binding]) -> {changed: bool, post: poststate} { let mut changed = false; - let mut post = tritv_clone(pres); + let mut post = pres.clone(); for bindings.each |b| { alt b.rhs { some(an_init) { // an expression, with or without a destination changed |= find_pre_post_state_expr(fcx, post, an_init.expr) || changed; - post = tritv_clone(expr_poststate(fcx.ccx, an_init.expr)); + post = expr_poststate(fcx.ccx, an_init.expr).clone(); for b.lhs.each |d| { alt an_init.expr.node { expr_path(p) { @@ -93,7 +93,7 @@ fn find_pre_post_state_sub(fcx: fn_ctxt, pres: prestate, e: @expr, changed = set_prestate_ann(fcx.ccx, parent, pres) || changed; - let post = tritv_clone(expr_poststate(fcx.ccx, e)); + let post = expr_poststate(fcx.ccx, e).clone(); alt c { none { } some(c1) { set_in_poststate_(bit_num(fcx, c1), post); } @@ -113,7 +113,7 @@ fn find_pre_post_state_two(fcx: fn_ctxt, pres: prestate, lhs: @expr, changed; forbid_upvar(fcx, rhs.id, rhs.span, ty); - let post = tritv_clone(expr_poststate(fcx.ccx, rhs)); + let post = expr_poststate(fcx.ccx, rhs).clone(); alt lhs.node { expr_path(p) { @@ -121,7 +121,7 @@ fn find_pre_post_state_two(fcx: fn_ctxt, pres: prestate, lhs: @expr, // changed flag // tmp remembers "old" constraints we'd otherwise forget, // for substitution purposes - let tmp = tritv_clone(post); + let tmp = post.clone(); alt ty { oper_move { @@ -210,8 +210,8 @@ fn join_then_else(fcx: fn_ctxt, antec: @expr, conseq: blk, alt chk { if_check { let c: sp_constr = expr_to_constr(fcx.ccx.tcx, antec); - let conseq_prestate = tritv_clone(expr_poststate(fcx.ccx, antec)); - tritv_set(bit_num(fcx, c.node), conseq_prestate, ttrue); + let conseq_prestate = expr_poststate(fcx.ccx, antec).clone(); + conseq_prestate.set(bit_num(fcx, c.node), ttrue); changed |= find_pre_post_state_block(fcx, conseq_prestate, conseq) | set_poststate_ann(fcx.ccx, id, @@ -235,8 +235,8 @@ fn join_then_else(fcx: fn_ctxt, antec: @expr, conseq: blk, alt chk { if_check { let c: sp_constr = expr_to_constr(fcx.ccx.tcx, antec); - conseq_prestate = tritv_clone(conseq_prestate); - tritv_set(bit_num(fcx, c.node), conseq_prestate, ttrue); + conseq_prestate = conseq_prestate.clone(); + conseq_prestate.set(bit_num(fcx, c.node), ttrue); } _ { } } @@ -270,7 +270,7 @@ fn find_pre_post_state_cap_clause(fcx: fn_ctxt, e_id: node_id, { let ccx = fcx.ccx; let pres_changed = set_prestate_ann(ccx, e_id, pres); - let post = tritv_clone(pres); + let post = pres.clone(); for (*cap_clause).each |cap_item| { if cap_item.is_move { forget_in_poststate(fcx, post, cap_item.id); @@ -432,7 +432,7 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool { worst case, the body could invalidate all preds and deinitialize everything before breaking */ let post = empty_poststate(num_constrs); - tritv::tritv_kill(post); + post.kill(); ret changed | set_poststate_ann(fcx.ccx, e.id, post); } else { ret changed | set_poststate_ann(fcx.ccx, e.id, @@ -507,8 +507,8 @@ fn find_pre_post_state_stmt(fcx: fn_ctxt, pres: prestate, s: @stmt) -> bool { #debug["[ %s ]", *fcx.name]; #debug["*At beginning: stmt = %s", stmt_to_str(*s)]; - #debug["*prestate = %s", tritv::to_str(stmt_ann.states.prestate)]; - #debug["*poststate = %s", tritv::to_str(stmt_ann.states.prestate)]; + #debug["*prestate = %s", stmt_ann.states.prestate.to_str()]; + #debug["*poststate = %s", stmt_ann.states.prestate.to_str()]; alt s.node { stmt_decl(adecl, id) { @@ -525,8 +525,8 @@ fn find_pre_post_state_stmt(fcx: fn_ctxt, pres: prestate, s: @stmt) -> bool { set_poststate(stmt_ann, c_and_p.post) | c_and_p.changed; #debug["Summary: stmt = %s", stmt_to_str(*s)]; - #debug["prestate = %s", tritv::to_str(stmt_ann.states.prestate)]; - #debug["poststate = %s",tritv::to_str(stmt_ann.states.poststate)]; + #debug["prestate = %s", stmt_ann.states.prestate.to_str()]; + #debug["poststate = %s", stmt_ann.states.poststate.to_str()]; #debug["changed = %s", bool::to_str(changed)]; ret changed; @@ -545,8 +545,8 @@ fn find_pre_post_state_stmt(fcx: fn_ctxt, pres: prestate, s: @stmt) -> bool { #debug["Finally: %s", stmt_to_str(*s)]; - #debug["prestate = %s", tritv::to_str(stmt_ann.states.prestate)]; - #debug["poststate = %s", tritv::to_str(stmt_ann.states.poststate)]; + #debug["prestate = %s", stmt_ann.states.prestate.to_str()]; + #debug["poststate = %s", stmt_ann.states.poststate.to_str()]; #debug["changed = %s", bool::to_str(changed)]; ret changed; diff --git a/src/rustc/middle/tstate/tritv.rs b/src/rustc/middle/tstate/tritv.rs index fc158262cb6..1e78b82fba8 100644 --- a/src/rustc/middle/tstate/tritv.rs +++ b/src/rustc/middle/tstate/tritv.rs @@ -1,24 +1,8 @@ -import std::bitv; +import std::bitv::*; export t; export create_tritv; -export tritv_clone; -export tritv_set; -export to_vec; -export trit; -export dont_care; -export ttrue; -export tfalse; -export tritv_get; -export tritv_set_all; -export tritv_difference; -export tritv_union; -export tritv_intersect; -export tritv_copy; -export tritv_clear; -export tritv_kill; -export tritv_doesntcare; -export to_str; +export trit, tfalse, ttrue, dont_care; /* for a fixed index: 10 = "this constraint may or may not be true after execution" @@ -31,17 +15,160 @@ per discussion at). */ -type t = {uncertain: bitv::bitv, val: bitv::bitv, nbits: uint}; enum trit { ttrue, tfalse, dont_care, } -fn create_tritv(len: uint) -> t { - ret {uncertain: bitv::bitv(len, true), - val: bitv::bitv(len, false), - nbits: len}; +class t { + // Shouldn't be mut; instead we should have a different + // constructor that takes two bitvs + let mut uncertain: bitv; + let mut val: bitv; + let nbits: uint; + // next two should be private (#2297) + fn set_uncertain(-b: bitv) { + self.uncertain <- b; + } + fn set_val(-b: bitv) { + self.val <- b; + } + fn clone() -> t { + let rs = t(self.nbits); + let r = self.uncertain.clone(); + rs.set_uncertain(r); + let r1 = self.val.clone(); + rs.set_val(r1); + rs + } + fn difference(p: t) -> bool { + assert (self.nbits == p.nbits); + let mut changed = false; + for uint::range(0, p.nbits) |i| { + let old = p.get(i); + let newv = minus(old, p.get(i)); + changed = change(changed, old, newv); + self.set(i, newv); + }; + changed + } + pure fn get(i: uint) -> trit { + let b1 = self.uncertain.get(i); + let b2 = self.val.get(i); + assert (!(b1 && b2)); + if b1 { dont_care } else if b2 { ttrue } else { tfalse } + } + pure fn set(i: uint, t: trit) -> bool { + let old = self.get(i); + alt t { + dont_care { + self.uncertain.set(i, true); + self.val.set(i, false); + } + ttrue { + self.uncertain.set(i, false); + self.val.set(i, true); + } + tfalse { + self.uncertain.set(i, false); + self.val.set(i, false); + } + } + change(false, old, t) + } + + fn set_all() { + for uint::range(0u, self.nbits) |i| { + self.set(i, ttrue); + } + } + + fn clear() { + for uint::range(0, self.nbits) |i| { + self.set(i, dont_care); + } + } + + fn kill() { + for uint::range(0, self.nbits) |i| { + self.set(i, dont_care); + } + } + + fn doesntcare() -> bool { + for uint::range(0, self.nbits) |i| { + if self.get(i) != dont_care { ret false; } + } + true + } + + fn to_vec() -> ~[uint] { + let mut rslt: ~[uint] = ~[]; + for uint::range(0, self.nbits) |i| { + vec::push(rslt, + alt self.get(i) { + dont_care { 2 } + ttrue { 1 } + tfalse { 0 } + }); + }; + rslt + } + + fn to_str() -> str { + let mut rs: str = ""; + for uint::range(0, self.nbits) |i| { + rs += + alt self.get(i) { + dont_care { "?" } + ttrue { "1" } + tfalse { "0" } + }; + }; + rs + } + + fn intersect(p: t) -> bool { + assert (self.nbits == p.nbits); + let mut changed = false; + for uint::range(0, self.nbits) |i| { + let old = self.get(i); + let newv = trit_and(old, p.get(i)); + changed = change(changed, old, newv); + self.set(i, newv); + } + ret changed; + } + + fn become(source: t) -> bool { + assert (self.nbits == source.nbits); + let changed = !self.uncertain.equal(source.uncertain) || + !self.val.equal(source.val); + self.uncertain.assign(source.uncertain); + self.val.assign(source.val); + changed + } + + fn union(p: t) -> bool { + assert (self.nbits == p.nbits); + let mut changed = false; + for uint::range(0, self.nbits) |i| { + let old = self.get(i); + let newv = trit_or(old, p.get(i)); + changed = change(changed, old, newv); + self.set(i, newv); + } + ret changed; + } + + new(len: uint) { + self.uncertain = mk_bitv(len, true); + self.val = mk_bitv(len, false); + self.nbits = len; + } } +fn create_tritv(len: uint) -> t { t(len) } -fn trit_minus(a: trit, b: trit) -> trit { + +fn minus(a: trit, b: trit) -> trit { /* 2 - anything = 2 1 - 1 = 2 @@ -56,10 +183,6 @@ fn trit_minus(a: trit, b: trit) -> trit { alt b { ttrue { dont_care } tfalse { ttrue } - - - - /* internally contradictory, but I guess it'll get flagged? */ dont_care { @@ -70,18 +193,14 @@ fn trit_minus(a: trit, b: trit) -> trit { tfalse { alt b { ttrue { tfalse } - - - - /* see above comment */ _ { tfalse } } } + } } -} fn trit_or(a: trit, b: trit) -> trit { alt a { @@ -137,148 +256,9 @@ fn trit_and(a: trit, b: trit) -> trit { // a and b were both dont_care } -fn change(changed: bool, old: trit, newv: trit) -> bool { +pure fn change(changed: bool, old: trit, newv: trit) -> bool { changed || newv != old } - -fn tritv_difference(p1: t, p2: t) -> bool { - let mut i: uint = 0u; - assert (p1.nbits == p2.nbits); - let sz: uint = p1.nbits; - let mut changed = false; - while i < sz { - let old = tritv_get(p1, i); - let newv = trit_minus(old, tritv_get(p2, i)); - changed = change(changed, old, newv); - tritv_set(i, p1, newv); - i += 1u; - } - ret changed; -} - -fn tritv_union(p1: t, p2: t) -> bool { - let mut i: uint = 0u; - assert (p1.nbits == p2.nbits); - let sz: uint = p1.nbits; - let mut changed = false; - while i < sz { - let old = tritv_get(p1, i); - let newv = trit_or(old, tritv_get(p2, i)); - changed = change(changed, old, newv); - tritv_set(i, p1, newv); - i += 1u; - } - ret changed; -} - -fn tritv_intersect(p1: t, p2: t) -> bool { - let mut i: uint = 0u; - assert (p1.nbits == p2.nbits); - let sz: uint = p1.nbits; - let mut changed = false; - while i < sz { - let old = tritv_get(p1, i); - let newv = trit_and(old, tritv_get(p2, i)); - changed = change(changed, old, newv); - tritv_set(i, p1, newv); - i += 1u; - } - ret changed; -} - -fn tritv_get(v: t, i: uint) -> trit { - let b1 = bitv::get(v.uncertain, i); - let b2 = bitv::get(v.val, i); - assert (!(b1 && b2)); - if b1 { dont_care } else if b2 { ttrue } else { tfalse } -} - -fn tritv_set(i: uint, v: t, t: trit) -> bool { - let old = tritv_get(v, i); - alt t { - dont_care { - bitv::set(v.uncertain, i, true); - bitv::set(v.val, i, false); - } - ttrue { bitv::set(v.uncertain, i, false); bitv::set(v.val, i, true); } - tfalse { - bitv::set(v.uncertain, i, false); - bitv::set(v.val, i, false); - } - } - ret change(false, old, t); -} - -fn tritv_copy(target: t, source: t) -> bool { - assert (target.nbits == source.nbits); - let changed = - !bitv::equal(target.uncertain, source.uncertain) || - !bitv::equal(target.val, source.val); - bitv::assign(target.uncertain, source.uncertain); - bitv::assign(target.val, source.val); - ret changed; -} - -fn tritv_set_all(v: t) { - let mut i: uint = 0u; - while i < v.nbits { tritv_set(i, v, ttrue); i += 1u; } -} - -fn tritv_clear(v: t) { - let mut i: uint = 0u; - while i < v.nbits { tritv_set(i, v, dont_care); i += 1u; } -} - -fn tritv_kill(v: t) { - let mut i: uint = 0u; - while i < v.nbits { tritv_set(i, v, tfalse); i += 1u; } -} - -fn tritv_clone(v: t) -> t { - ret {uncertain: bitv::clone(v.uncertain), - val: bitv::clone(v.val), - nbits: v.nbits}; -} - -fn tritv_doesntcare(v: t) -> bool { - let mut i: uint = 0u; - while i < v.nbits { - if tritv_get(v, i) != dont_care { ret false; } - i += 1u; - } - ret true; -} - -fn to_vec(v: t) -> ~[uint] { - let mut i: uint = 0u; - let mut rslt: ~[uint] = ~[]; - while i < v.nbits { - vec::push(rslt, - alt tritv_get(v, i) { - dont_care { 2u } - ttrue { 1u } - tfalse { 0u } - }); - i += 1u; - } - ret rslt; -} - -fn to_str(v: t) -> ~str { - let mut i: uint = 0u; - let mut rs: ~str = ~""; - while i < v.nbits { - rs += - alt tritv_get(v, i) { - dont_care { ~"?" } - ttrue { ~"1" } - tfalse { ~"0" } - }; - i += 1u; - } - ret rs; -} - // // Local Variables: // mode: rust diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index 3eeb16f9379..f1bf1ec8d0a 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -52,7 +52,7 @@ fn next_color(g: grid, row: u8, col: u8, start_color: u8) -> bool { // colors not yet used let avail = bitv::bitv(10u, false); for u8::range(start_color, 10u8) |color| { - bitv::set(avail, color as uint, true); + avail.set(color as uint, true); } // drop colors already in use in neighbourhood @@ -60,7 +60,7 @@ fn next_color(g: grid, row: u8, col: u8, start_color: u8) -> bool { // find first remaining color that is available for uint::range(1u, 10u) |i| { - if bitv::get(avail, i) { + if avail.get(i) { g[row][col] = i as u8; ret true; } @@ -74,7 +74,7 @@ fn next_color(g: grid, row: u8, col: u8, start_color: u8) -> bool { fn drop_colors(g: grid, avail: bitv::bitv, row: u8, col: u8) { fn drop_color(g: grid, colors: bitv::bitv, row: u8, col: u8) { let color = g[row][col]; - if color != 0u8 { bitv::set(colors, color as uint, false); } + if color != 0u8 { colors.set(color as uint, false); } } let it = |a,b| drop_color(g, avail, a, b); diff --git a/src/test/compile-fail/for-loop-decl.rs b/src/test/compile-fail/for-loop-decl.rs index 00f9433eef0..2252672f1b5 100644 --- a/src/test/compile-fail/for-loop-decl.rs +++ b/src/test/compile-fail/for-loop-decl.rs @@ -6,12 +6,12 @@ type fn_info = {vars: hashmap}; type var_info = {a: uint, b: uint}; -fn bitv_to_str(enclosing: fn_info, v: bitv::bitv) -> str { +fn bitv_to_str(enclosing: fn_info, v: ~bitv::bitv) -> str { let s = ""; // error is that the value type in the hash map is var_info, not a box for enclosing.vars.each_value |val| { - if bitv::get(v, val) { s += "foo"; } + if v.get(val) { s += "foo"; } } ret s; } diff --git a/src/test/run-pass/bitv-perf-test.rs b/src/test/run-pass/bitv-perf-test.rs new file mode 100644 index 00000000000..2e4b567e619 --- /dev/null +++ b/src/test/run-pass/bitv-perf-test.rs @@ -0,0 +1,13 @@ +use std; +import std::bitv::*; + +fn bitv_test() -> bool { + let v1 = ~bitv(31, false); + let v2 = ~bitv(31, true); + v1.union(v2); + true +} + +fn main() { + do iter::repeat(1000000) || {bitv_test()}; +} \ No newline at end of file -- GitLab