extra: Use external iterators in bitv implementation

Convert some internally used functions to use a external iterators.

Change all uses of remaining internal iterators to use `do` expr
This commit is contained in:
blake2-ppc 2013-07-31 21:07:44 +02:00
parent dbcb74e247
commit 310e0b6e92

View File

@ -12,7 +12,8 @@
use std::cmp;
use std::iterator::{DoubleEndedIterator, RandomAccessIterator, Invert};
use std::iterator::RandomAccessIterator;
use std::iterator::{Invert, Enumerate};
use std::num;
use std::ops;
use std::uint;
@ -164,7 +165,7 @@ impl BigBitv {
}
#[inline]
pub fn negate(&mut self) { for self.each_storage |w| { *w = !*w } }
pub fn negate(&mut self) { do self.each_storage |w| { *w = !*w; true }; }
#[inline]
pub fn union(&mut self, b: &BigBitv, nbits: uint) -> bool {
@ -723,12 +724,12 @@ impl cmp::Eq for BitvSet {
if self.size != other.size {
return false;
}
for self.each_common(other) |_, w1, w2| {
for self.common_iter(other).advance |(_, w1, w2)| {
if w1 != w2 {
return false;
}
}
for self.each_outlier(other) |_, _, w| {
for self.outlier_iter(other).advance |(_, _, w)| {
if w != 0 {
return false;
}
@ -746,7 +747,7 @@ impl Container for BitvSet {
impl Mutable for BitvSet {
fn clear(&mut self) {
for self.bitv.each_storage |w| { *w = 0; }
do self.bitv.each_storage |w| { *w = 0; true };
self.size = 0;
}
}
@ -757,14 +758,13 @@ impl Set<uint> for BitvSet {
}
fn is_disjoint(&self, other: &BitvSet) -> bool {
for self.intersection(other) |_| {
return false;
do self.intersection(other) |_| {
false
}
return true;
}
fn is_subset(&self, other: &BitvSet) -> bool {
for self.each_common(other) |_, w1, w2| {
for self.common_iter(other).advance |(_, w1, w2)| {
if w1 & w2 != w1 {
return false;
}
@ -772,7 +772,7 @@ impl Set<uint> for BitvSet {
/* If anything is not ours, then everything is not ours so we're
definitely a subset in that case. Otherwise if there's any stray
ones that 'other' doesn't have, we're not a subset. */
for self.each_outlier(other) |mine, _, w| {
for self.outlier_iter(other).advance |(mine, _, w)| {
if !mine {
return true;
} else if w != 0 {
@ -787,38 +787,38 @@ impl Set<uint> for BitvSet {
}
fn difference(&self, other: &BitvSet, f: &fn(&uint) -> bool) -> bool {
for self.each_common(other) |i, w1, w2| {
for self.common_iter(other).advance |(i, w1, w2)| {
if !iterate_bits(i, w1 & !w2, |b| f(&b)) {
return false;
}
}
/* everything we have that they don't also shows up */
self.each_outlier(other, |mine, i, w|
self.outlier_iter(other).advance(|(mine, i, w)|
!mine || iterate_bits(i, w, |b| f(&b))
)
}
fn symmetric_difference(&self, other: &BitvSet,
f: &fn(&uint) -> bool) -> bool {
for self.each_common(other) |i, w1, w2| {
for self.common_iter(other).advance |(i, w1, w2)| {
if !iterate_bits(i, w1 ^ w2, |b| f(&b)) {
return false;
}
}
self.each_outlier(other, |_, i, w| iterate_bits(i, w, |b| f(&b)))
self.outlier_iter(other).advance(|(_, i, w)| iterate_bits(i, w, |b| f(&b)))
}
fn intersection(&self, other: &BitvSet, f: &fn(&uint) -> bool) -> bool {
self.each_common(other, |i, w1, w2| iterate_bits(i, w1 & w2, |b| f(&b)))
self.common_iter(other).advance(|(i, w1, w2)| iterate_bits(i, w1 & w2, |b| f(&b)))
}
fn union(&self, other: &BitvSet, f: &fn(&uint) -> bool) -> bool {
for self.each_common(other) |i, w1, w2| {
for self.common_iter(other).advance |(i, w1, w2)| {
if !iterate_bits(i, w1 | w2, |b| f(&b)) {
return false;
}
}
self.each_outlier(other, |_, i, w| iterate_bits(i, w, |b| f(&b)))
self.outlier_iter(other).advance(|(_, i, w)| iterate_bits(i, w, |b| f(&b)))
}
}
@ -861,13 +861,14 @@ impl BitvSet {
/// both have in common. The three yielded arguments are (bit location,
/// w1, w2) where the bit location is the number of bits offset so far,
/// and w1/w2 are the words coming from the two vectors self, other.
fn each_common(&self, other: &BitvSet,
f: &fn(uint, uint, uint) -> bool) -> bool {
fn common_iter<'a>(&'a self, other: &'a BitvSet)
-> MapE<(uint,&uint),(uint,uint,uint), &'a ~[uint],Enumerate<vec::VecIterator<'a,uint>>> {
let min = num::min(self.bitv.storage.len(),
other.bitv.storage.len());
self.bitv.storage.slice(0, min).iter().enumerate().advance(|(i, &w)| {
f(i * uint::bits, w, other.bitv.storage[i])
})
MapE{iter: self.bitv.storage.slice(0, min).iter().enumerate(),
env: &other.bitv.storage,
f: |(i, &w): (uint, &uint), o_store| (i * uint::bits, w, o_store[i])
}
}
/// Visits each word in self or other that extends beyond the other. This
@ -877,24 +878,45 @@ impl BitvSet {
/// The yielded arguments are a bool, the bit offset, and a word. The bool
/// is true if the word comes from 'self', and false if it comes from
/// 'other'.
fn each_outlier(&self, other: &BitvSet,
f: &fn(bool, uint, uint) -> bool) -> bool {
fn outlier_iter<'a>(&'a self, other: &'a BitvSet)
-> MapE<(uint, &uint),(bool, uint, uint), uint, Enumerate<vec::VecIterator<'a, uint>>> {
let len1 = self.bitv.storage.len();
let len2 = other.bitv.storage.len();
let min = num::min(len1, len2);
/* only one of these loops will execute and that's the point */
foreach (i, &w) in self.bitv.storage.slice(min, len1).iter().enumerate() {
if !f(true, (i + min) * uint::bits, w) {
return false;
if min < len1 {
MapE{iter: self.bitv.storage.slice(min, len1).iter().enumerate(),
env: min,
f: |(i, &w): (uint, &uint), min| (true, (i + min) * uint::bits, w)
}
} else {
MapE{iter: other.bitv.storage.slice(min, len2).iter().enumerate(),
env: min,
f: |(i, &w): (uint, &uint), min| (false, (i + min) * uint::bits, w)
}
}
foreach (i, &w) in other.bitv.storage.slice(min, len2).iter().enumerate() {
if !f(false, (i + min) * uint::bits, w) {
return false;
}
}
}
/// Like iterator::Map with explicit env capture
struct MapE<A, B, Env, I> {
priv env: Env,
priv f: &'static fn(A, Env) -> B,
priv iter: I,
}
impl<'self, A, B, Env: Clone, I: Iterator<A>> Iterator<B> for MapE<A, B, Env, I> {
#[inline]
fn next(&mut self) -> Option<B> {
match self.iter.next() {
Some(elt) => Some((self.f)(elt, self.env.clone())),
None => None
}
return true;
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.iter.size_hint()
}
}