Skip to content

Commit 310e0b6

Browse files
author
blake2-ppc
committed
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
1 parent dbcb74e commit 310e0b6

File tree

1 file changed

+55
-33
lines changed

1 file changed

+55
-33
lines changed

src/libextra/bitv.rs

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313

1414
use std::cmp;
15-
use std::iterator::{DoubleEndedIterator, RandomAccessIterator, Invert};
15+
use std::iterator::RandomAccessIterator;
16+
use std::iterator::{Invert, Enumerate};
1617
use std::num;
1718
use std::ops;
1819
use std::uint;
@@ -164,7 +165,7 @@ impl BigBitv {
164165
}
165166

166167
#[inline]
167-
pub fn negate(&mut self) { for self.each_storage |w| { *w = !*w } }
168+
pub fn negate(&mut self) { do self.each_storage |w| { *w = !*w; true }; }
168169

169170
#[inline]
170171
pub fn union(&mut self, b: &BigBitv, nbits: uint) -> bool {
@@ -723,12 +724,12 @@ impl cmp::Eq for BitvSet {
723724
if self.size != other.size {
724725
return false;
725726
}
726-
for self.each_common(other) |_, w1, w2| {
727+
for self.common_iter(other).advance |(_, w1, w2)| {
727728
if w1 != w2 {
728729
return false;
729730
}
730731
}
731-
for self.each_outlier(other) |_, _, w| {
732+
for self.outlier_iter(other).advance |(_, _, w)| {
732733
if w != 0 {
733734
return false;
734735
}
@@ -746,7 +747,7 @@ impl Container for BitvSet {
746747

747748
impl Mutable for BitvSet {
748749
fn clear(&mut self) {
749-
for self.bitv.each_storage |w| { *w = 0; }
750+
do self.bitv.each_storage |w| { *w = 0; true };
750751
self.size = 0;
751752
}
752753
}
@@ -757,22 +758,21 @@ impl Set<uint> for BitvSet {
757758
}
758759

759760
fn is_disjoint(&self, other: &BitvSet) -> bool {
760-
for self.intersection(other) |_| {
761-
return false;
761+
do self.intersection(other) |_| {
762+
false
762763
}
763-
return true;
764764
}
765765

766766
fn is_subset(&self, other: &BitvSet) -> bool {
767-
for self.each_common(other) |_, w1, w2| {
767+
for self.common_iter(other).advance |(_, w1, w2)| {
768768
if w1 & w2 != w1 {
769769
return false;
770770
}
771771
}
772772
/* If anything is not ours, then everything is not ours so we're
773773
definitely a subset in that case. Otherwise if there's any stray
774774
ones that 'other' doesn't have, we're not a subset. */
775-
for self.each_outlier(other) |mine, _, w| {
775+
for self.outlier_iter(other).advance |(mine, _, w)| {
776776
if !mine {
777777
return true;
778778
} else if w != 0 {
@@ -787,38 +787,38 @@ impl Set<uint> for BitvSet {
787787
}
788788

789789
fn difference(&self, other: &BitvSet, f: &fn(&uint) -> bool) -> bool {
790-
for self.each_common(other) |i, w1, w2| {
790+
for self.common_iter(other).advance |(i, w1, w2)| {
791791
if !iterate_bits(i, w1 & !w2, |b| f(&b)) {
792792
return false;
793793
}
794794
}
795795
/* everything we have that they don't also shows up */
796-
self.each_outlier(other, |mine, i, w|
796+
self.outlier_iter(other).advance(|(mine, i, w)|
797797
!mine || iterate_bits(i, w, |b| f(&b))
798798
)
799799
}
800800

801801
fn symmetric_difference(&self, other: &BitvSet,
802802
f: &fn(&uint) -> bool) -> bool {
803-
for self.each_common(other) |i, w1, w2| {
803+
for self.common_iter(other).advance |(i, w1, w2)| {
804804
if !iterate_bits(i, w1 ^ w2, |b| f(&b)) {
805805
return false;
806806
}
807807
}
808-
self.each_outlier(other, |_, i, w| iterate_bits(i, w, |b| f(&b)))
808+
self.outlier_iter(other).advance(|(_, i, w)| iterate_bits(i, w, |b| f(&b)))
809809
}
810810

811811
fn intersection(&self, other: &BitvSet, f: &fn(&uint) -> bool) -> bool {
812-
self.each_common(other, |i, w1, w2| iterate_bits(i, w1 & w2, |b| f(&b)))
812+
self.common_iter(other).advance(|(i, w1, w2)| iterate_bits(i, w1 & w2, |b| f(&b)))
813813
}
814814

815815
fn union(&self, other: &BitvSet, f: &fn(&uint) -> bool) -> bool {
816-
for self.each_common(other) |i, w1, w2| {
816+
for self.common_iter(other).advance |(i, w1, w2)| {
817817
if !iterate_bits(i, w1 | w2, |b| f(&b)) {
818818
return false;
819819
}
820820
}
821-
self.each_outlier(other, |_, i, w| iterate_bits(i, w, |b| f(&b)))
821+
self.outlier_iter(other).advance(|(_, i, w)| iterate_bits(i, w, |b| f(&b)))
822822
}
823823
}
824824

@@ -861,13 +861,14 @@ impl BitvSet {
861861
/// both have in common. The three yielded arguments are (bit location,
862862
/// w1, w2) where the bit location is the number of bits offset so far,
863863
/// and w1/w2 are the words coming from the two vectors self, other.
864-
fn each_common(&self, other: &BitvSet,
865-
f: &fn(uint, uint, uint) -> bool) -> bool {
864+
fn common_iter<'a>(&'a self, other: &'a BitvSet)
865+
-> MapE<(uint,&uint),(uint,uint,uint), &'a ~[uint],Enumerate<vec::VecIterator<'a,uint>>> {
866866
let min = num::min(self.bitv.storage.len(),
867867
other.bitv.storage.len());
868-
self.bitv.storage.slice(0, min).iter().enumerate().advance(|(i, &w)| {
869-
f(i * uint::bits, w, other.bitv.storage[i])
870-
})
868+
MapE{iter: self.bitv.storage.slice(0, min).iter().enumerate(),
869+
env: &other.bitv.storage,
870+
f: |(i, &w): (uint, &uint), o_store| (i * uint::bits, w, o_store[i])
871+
}
871872
}
872873

873874
/// Visits each word in self or other that extends beyond the other. This
@@ -877,24 +878,45 @@ impl BitvSet {
877878
/// The yielded arguments are a bool, the bit offset, and a word. The bool
878879
/// is true if the word comes from 'self', and false if it comes from
879880
/// 'other'.
880-
fn each_outlier(&self, other: &BitvSet,
881-
f: &fn(bool, uint, uint) -> bool) -> bool {
881+
fn outlier_iter<'a>(&'a self, other: &'a BitvSet)
882+
-> MapE<(uint, &uint),(bool, uint, uint), uint, Enumerate<vec::VecIterator<'a, uint>>> {
882883
let len1 = self.bitv.storage.len();
883884
let len2 = other.bitv.storage.len();
884885
let min = num::min(len1, len2);
885886

886-
/* only one of these loops will execute and that's the point */
887-
foreach (i, &w) in self.bitv.storage.slice(min, len1).iter().enumerate() {
888-
if !f(true, (i + min) * uint::bits, w) {
889-
return false;
887+
if min < len1 {
888+
MapE{iter: self.bitv.storage.slice(min, len1).iter().enumerate(),
889+
env: min,
890+
f: |(i, &w): (uint, &uint), min| (true, (i + min) * uint::bits, w)
890891
}
891-
}
892-
foreach (i, &w) in other.bitv.storage.slice(min, len2).iter().enumerate() {
893-
if !f(false, (i + min) * uint::bits, w) {
894-
return false;
892+
} else {
893+
MapE{iter: other.bitv.storage.slice(min, len2).iter().enumerate(),
894+
env: min,
895+
f: |(i, &w): (uint, &uint), min| (false, (i + min) * uint::bits, w)
895896
}
896897
}
897-
return true;
898+
}
899+
}
900+
901+
/// Like iterator::Map with explicit env capture
902+
struct MapE<A, B, Env, I> {
903+
priv env: Env,
904+
priv f: &'static fn(A, Env) -> B,
905+
priv iter: I,
906+
}
907+
908+
impl<'self, A, B, Env: Clone, I: Iterator<A>> Iterator<B> for MapE<A, B, Env, I> {
909+
#[inline]
910+
fn next(&mut self) -> Option<B> {
911+
match self.iter.next() {
912+
Some(elt) => Some((self.f)(elt, self.env.clone())),
913+
None => None
914+
}
915+
}
916+
917+
#[inline]
918+
fn size_hint(&self) -> (uint, Option<uint>) {
919+
self.iter.size_hint()
898920
}
899921
}
900922

0 commit comments

Comments
 (0)