Skip to content
70 changes: 22 additions & 48 deletions src/libextra/bitv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

use std::cmp;
use std::iterator::RandomAccessIterator;
use std::iterator::{Invert, Enumerate};
use std::iterator::{Invert, Enumerate, Repeat, Map, Zip};
use std::num;
use std::ops;
use std::uint;
Expand Down Expand Up @@ -206,14 +206,13 @@ impl BigBitv {
#[inline]
pub fn equals(&self, b: &BigBitv, nbits: uint) -> bool {
let len = b.storage.len();
do uint::iterate(0, len) |i| {
for i in range(0, len) {
let mask = big_mask(nbits, i);
if mask & self.storage[i] != mask & b.storage[i] {
false
} else {
true
return false;
}
}
true
}
}

Expand Down Expand Up @@ -864,13 +863,12 @@ impl BitvSet {
/// 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 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());
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])
}
-> Map<'static, ((uint, &'a uint), &'a ~[uint]), (uint, uint, uint),
Zip<Enumerate<vec::VecIterator<'a, uint>>, Repeat<&'a ~[uint]>>> {
let min = num::min(self.bitv.storage.len(), other.bitv.storage.len());
self.bitv.storage.slice(0, min).iter().enumerate()
.zip(Repeat::new(&other.bitv.storage))
.transform(|((i, &w), o_store)| (i * uint::bits, w, o_store[i]))
}

/// Visits each word in self or other that extends beyond the other. This
Expand All @@ -881,45 +879,21 @@ impl BitvSet {
/// is true if the word comes from 'self', and false if it comes from
/// 'other'.
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);

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)
}
-> Map<'static, ((uint, &'a uint), uint), (bool, uint, uint),
Zip<Enumerate<vec::VecIterator<'a, uint>>, Repeat<uint>>> {
let slen = self.bitv.storage.len();
let olen = other.bitv.storage.len();

if olen < slen {
self.bitv.storage.slice_from(olen).iter().enumerate()
.zip(Repeat::new(olen))
.transform(|((i, &w), 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)
}
}
}
}

/// 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
other.bitv.storage.slice_from(slen).iter().enumerate()
.zip(Repeat::new(slen))
.transform(|((i, &w), min)| (false, (i + min) * uint::bits, w))
}
}

#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.iter.size_hint()
}
}

pub struct BitvSetIterator<'self> {
Expand Down
54 changes: 17 additions & 37 deletions src/libstd/hashmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
use clone::Clone;
use cmp::{Eq, Equiv};
use hash::Hash;
use iterator::{Iterator, IteratorUtil, FromIterator, Extendable, Chain, range};
use iterator::{Iterator, IteratorUtil, FromIterator, Extendable, range};
use iterator::{FilterMap, Chain, Repeat, Zip};
use num;
use option::{None, Option, Some};
use rand::RngUtil;
Expand Down Expand Up @@ -712,10 +713,12 @@ impl<T:Hash + Eq> HashSet<T> {
}

/// Visit the values representing the difference
pub fn difference_iter<'a>(&'a self, other: &'a HashSet<T>)
-> SetAlgebraIter<'a, T> {
EnvFilterIterator{iter: self.iter(), env: other,
filter: |elt, other| !other.contains(elt) }
pub fn difference_iter<'a>(&'a self, other: &'a HashSet<T>) -> SetAlgebraIter<'a, T> {
Repeat::new(other)
.zip(self.iter())
.filter_map(|(other, elt)| {
if !other.contains(elt) { Some(elt) } else { None }
})
}

/// Visit the values representing the symmetric difference
Expand All @@ -727,8 +730,11 @@ impl<T:Hash + Eq> HashSet<T> {
/// Visit the values representing the intersection
pub fn intersection_iter<'a>(&'a self, other: &'a HashSet<T>)
-> SetAlgebraIter<'a, T> {
EnvFilterIterator{iter: self.iter(), env: other,
filter: |elt, other| other.contains(elt) }
Repeat::new(other)
.zip(self.iter())
.filter_map(|(other, elt)| {
if other.contains(elt) { Some(elt) } else { None }
})
}

/// Visit the values representing the union
Expand Down Expand Up @@ -756,38 +762,12 @@ impl<K: Eq + Hash, T: Iterator<K>> Extendable<K, T> for HashSet<K> {
}
}

// FIXME #7814: use std::iterator::FilterIterator
/// Building block for Set operation iterators
pub struct EnvFilterIterator<A, Env, I> {
priv env: Env,
priv filter: &'static fn(&A, Env) -> bool,
priv iter: I,
}

impl<'self, A, Env: Clone, I: Iterator<&'self A>> Iterator<&'self A>
for EnvFilterIterator<A, Env, I> {
#[inline]
fn next(&mut self) -> Option<&'self A> {
loop {
match self.iter.next() {
Some(elt) => if (self.filter)(elt, self.env.clone()) {
return Some(elt)
},
None => return None,
}
}
}

#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}

// `Repeat` is used to feed the filter closure an explicit capture
// of a reference to the other set
/// Set operations iterator
pub type SetAlgebraIter<'self, T> =
EnvFilterIterator<T, &'self HashSet<T>, HashSetIterator<'self, T>>;
FilterMap<'static,(&'self HashSet<T>, &'self T), &'self T,
Zip<Repeat<&'self HashSet<T>>,HashSetIterator<'self,T>>>;


#[cfg(test)]
Expand Down
65 changes: 65 additions & 0 deletions src/libstd/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ pub trait DoubleEndedIteratorUtil {
/// In the future these will be default methods instead of a utility trait.
impl<A, T: DoubleEndedIterator<A>> DoubleEndedIteratorUtil for T {
/// Flip the direction of the iterator
///
/// The inverted iterator flips the ends on an iterator that can already
/// be iterated from the front and from the back.
///
///
/// If the iterator also implements RandomAccessIterator, the inverted
/// iterator is also random access, with the indices starting at the back
/// of the original iterator.
///
/// Note: Random access with inverted indices still only applies to the first
/// `uint::max_value` elements of the original iterator.
#[inline]
fn invert(self) -> Invert<T> {
Invert{iter: self}
Expand All @@ -106,6 +117,16 @@ impl<A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Invert<T> {
fn next_back(&mut self) -> Option<A> { self.iter.next() }
}

impl<A, T: DoubleEndedIterator<A> + RandomAccessIterator<A>> RandomAccessIterator<A>
for Invert<T> {
#[inline]
fn indexable(&self) -> uint { self.iter.indexable() }
#[inline]
fn idx(&self, index: uint) -> Option<A> {
self.iter.idx(self.indexable() - index - 1)
}
}

/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
/// implementations of the `Iterator` trait.
///
Expand Down Expand Up @@ -1555,6 +1576,39 @@ impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> {
}
}

/// An iterator that repeats an element endlessly
#[deriving(Clone, DeepClone)]
pub struct Repeat<A> {
priv element: A
}

impl<A: Clone> Repeat<A> {
/// Create a new `Repeat` that enlessly repeats the element `elt`.
#[inline]
pub fn new(elt: A) -> Repeat<A> {
Repeat{element: elt}
}
}

impl<A: Clone> Iterator<A> for Repeat<A> {
#[inline]
fn next(&mut self) -> Option<A> { self.idx(0) }
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) { (uint::max_value, None) }
}

impl<A: Clone> DoubleEndedIterator<A> for Repeat<A> {
#[inline]
fn next_back(&mut self) -> Option<A> { self.idx(0) }
}

impl<A: Clone> RandomAccessIterator<A> for Repeat<A> {
#[inline]
fn indexable(&self) -> uint { uint::max_value }
#[inline]
fn idx(&self, _: uint) -> Option<A> { Some(self.element.clone()) }
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -2017,6 +2071,17 @@ mod tests {
check_randacc_iter(xs.iter().enumerate(), xs.len());
}

#[test]
fn test_random_access_invert() {
let xs = [1, 2, 3, 4, 5];
check_randacc_iter(xs.iter().invert(), xs.len());
let mut it = xs.iter().invert();
it.next();
it.next_back();
it.next();
check_randacc_iter(it, xs.len() - 3);
}

#[test]
fn test_random_access_zip() {
let xs = [1, 2, 3, 4, 5];
Expand Down
24 changes: 0 additions & 24 deletions src/libstd/num/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,30 +70,6 @@ pub fn div_round(x: uint, y: uint) -> uint {
///
pub fn div_floor(x: uint, y: uint) -> uint { return x / y; }

///
/// Iterate over the range [`lo`..`hi`), or stop when requested
///
/// # Arguments
///
/// * lo - The integer at which to start the loop (included)
/// * hi - The integer at which to stop the loop (excluded)
/// * it - A block to execute with each consecutive integer of the range.
/// Return `true` to continue, `false` to stop.
///
/// # Return value
///
/// `true` If execution proceeded correctly, `false` if it was interrupted,
/// that is if `it` returned `false` at any point.
///
pub fn iterate(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool {
let mut i = lo;
while i < hi {
if (!it(i)) { return false; }
i += 1u;
}
return true;
}

impl iter::Times for uint {
#[inline]
///
Expand Down
46 changes: 18 additions & 28 deletions src/libstd/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl<T: ToStr> ToStr for Option<T> {
impl<T> Option<T> {
/// Return an iterator over the possibly contained value
#[inline]
pub fn iter<'r>(&'r self) -> OptionIterator<'r, T> {
pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> {
match *self {
Some(ref x) => OptionIterator{opt: Some(x)},
None => OptionIterator{opt: None}
Expand All @@ -125,13 +125,19 @@ impl<T> Option<T> {

/// Return a mutable iterator over the possibly contained value
#[inline]
pub fn mut_iter<'r>(&'r mut self) -> OptionMutIterator<'r, T> {
pub fn mut_iter<'r>(&'r mut self) -> OptionIterator<&'r mut T> {
match *self {
Some(ref mut x) => OptionMutIterator{opt: Some(x)},
None => OptionMutIterator{opt: None}
Some(ref mut x) => OptionIterator{opt: Some(x)},
None => OptionIterator{opt: None}
}
}

/// Return a consuming iterator over the possibly contained value
#[inline]
pub fn consume(self) -> OptionIterator<T> {
OptionIterator{opt: self}
}

/// Returns true if the option equals `None`
#[inline]
pub fn is_none(&self) -> bool {
Expand Down Expand Up @@ -404,34 +410,18 @@ impl<T> Zero for Option<T> {
fn is_zero(&self) -> bool { self.is_none() }
}

/// Immutable iterator over an `Option<A>`
pub struct OptionIterator<'self, A> {
priv opt: Option<&'self A>
}

impl<'self, A> Iterator<&'self A> for OptionIterator<'self, A> {
fn next(&mut self) -> Option<&'self A> {
util::replace(&mut self.opt, None)
}

fn size_hint(&self) -> (uint, Option<uint>) {
match self.opt {
Some(_) => (1, Some(1)),
None => (0, Some(0)),
}
}
}

/// Mutable iterator over an `Option<A>`
pub struct OptionMutIterator<'self, A> {
priv opt: Option<&'self mut A>
/// An iterator that yields either one or zero elements
pub struct OptionIterator<A> {
priv opt: Option<A>
}

impl<'self, A> Iterator<&'self mut A> for OptionMutIterator<'self, A> {
fn next(&mut self) -> Option<&'self mut A> {
util::replace(&mut self.opt, None)
impl<A> Iterator<A> for OptionIterator<A> {
#[inline]
fn next(&mut self) -> Option<A> {
self.opt.take()
}

#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
match self.opt {
Some(_) => (1, Some(1)),
Expand Down
Loading