std: add reverse vec iterators, replace vec::each*_reverse.
This commit is contained in:
@@ -19,7 +19,7 @@ A BigInt is a combination of BigUint and Sign.
|
|||||||
#[allow(missing_doc)];
|
#[allow(missing_doc)];
|
||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
use core::iterator::IteratorUtil;
|
||||||
use core::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
|
use core::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
|
||||||
use core::int;
|
use core::int;
|
||||||
use core::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix, Orderable};
|
use core::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix, Orderable};
|
||||||
@@ -129,12 +129,9 @@ impl TotalOrd for BigUint {
|
|||||||
if s_len < o_len { return Less; }
|
if s_len < o_len { return Less; }
|
||||||
if s_len > o_len { return Greater; }
|
if s_len > o_len { return Greater; }
|
||||||
|
|
||||||
for self.data.eachi_reverse |i, elm| {
|
for self.data.rev_iter().zip(other.data.rev_iter()).advance |(&self_i, &other_i)| {
|
||||||
match (*elm, other.data[i]) {
|
cond!((self_i < other_i) { return Less; }
|
||||||
(l, r) if l < r => return Less,
|
(self_i > other_i) { return Greater; })
|
||||||
(l, r) if l > r => return Greater,
|
|
||||||
_ => loop
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return Equal;
|
return Equal;
|
||||||
}
|
}
|
||||||
@@ -421,7 +418,7 @@ impl Integer for BigUint {
|
|||||||
let bn = *b.data.last();
|
let bn = *b.data.last();
|
||||||
let mut d = ~[];
|
let mut d = ~[];
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
for an.each_reverse |elt| {
|
for an.rev_iter().advance |elt| {
|
||||||
let ai = BigDigit::to_uint(carry, *elt);
|
let ai = BigDigit::to_uint(carry, *elt);
|
||||||
let di = ai / (bn as uint);
|
let di = ai / (bn as uint);
|
||||||
assert!(di < BigDigit::base);
|
assert!(di < BigDigit::base);
|
||||||
@@ -648,7 +645,7 @@ impl BigUint {
|
|||||||
|
|
||||||
let mut borrow = 0;
|
let mut borrow = 0;
|
||||||
let mut shifted = ~[];
|
let mut shifted = ~[];
|
||||||
for self.data.each_reverse |elem| {
|
for self.data.rev_iter().advance |elem| {
|
||||||
shifted = ~[(*elem >> n_bits) | borrow] + shifted;
|
shifted = ~[(*elem >> n_bits) | borrow] + shifted;
|
||||||
borrow = *elem << (BigDigit::bits - n_bits);
|
borrow = *elem << (BigDigit::bits - n_bits);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ use middle::ty;
|
|||||||
use util::common::indenter;
|
use util::common::indenter;
|
||||||
use util::ppaux::{Repr, ty_to_str};
|
use util::ppaux::{Repr, ty_to_str};
|
||||||
|
|
||||||
|
use core::iterator::IteratorUtil;
|
||||||
use core::hash;
|
use core::hash;
|
||||||
use core::hashmap::{HashMap, HashSet};
|
use core::hashmap::{HashMap, HashSet};
|
||||||
use core::int;
|
use core::int;
|
||||||
@@ -1275,7 +1276,7 @@ pub fn trans_block_cleanups_(bcx: block,
|
|||||||
bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0;
|
bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0;
|
||||||
if bcx.unreachable && !no_lpads { return bcx; }
|
if bcx.unreachable && !no_lpads { return bcx; }
|
||||||
let mut bcx = bcx;
|
let mut bcx = bcx;
|
||||||
for cleanups.each_reverse |cu| {
|
for cleanups.rev_iter().advance |cu| {
|
||||||
match *cu {
|
match *cu {
|
||||||
clean(cfn, cleanup_type) | clean_temp(_, cfn, cleanup_type) => {
|
clean(cfn, cleanup_type) | clean_temp(_, cfn, cleanup_type) => {
|
||||||
// Some types don't need to be cleaned up during
|
// Some types don't need to be cleaned up during
|
||||||
|
|||||||
@@ -3964,7 +3964,7 @@ mod tests {
|
|||||||
let s = ~"ศไทย中华Việt Nam";
|
let s = ~"ศไทย中华Việt Nam";
|
||||||
let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
|
let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
|
||||||
let mut pos = s.len();
|
let mut pos = s.len();
|
||||||
for v.each_reverse |ch| {
|
for v.rev_iter().advance |ch| {
|
||||||
assert!(s.char_at_reverse(pos) == *ch);
|
assert!(s.char_at_reverse(pos) == *ch);
|
||||||
pos -= from_char(*ch).len();
|
pos -= from_char(*ch).len();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
//! Runtime calls emitted by the compiler.
|
//! Runtime calls emitted by the compiler.
|
||||||
|
|
||||||
|
use iterator::IteratorUtil;
|
||||||
use uint;
|
use uint;
|
||||||
use cast::transmute;
|
use cast::transmute;
|
||||||
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int, STDERR_FILENO};
|
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int, STDERR_FILENO};
|
||||||
@@ -133,7 +134,7 @@ unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) {
|
|||||||
Some(borrow_list) => { // recording borrows
|
Some(borrow_list) => { // recording borrows
|
||||||
let mut msg = ~"borrowed";
|
let mut msg = ~"borrowed";
|
||||||
let mut sep = " at ";
|
let mut sep = " at ";
|
||||||
for borrow_list.each_reverse |entry| {
|
for borrow_list.rev_iter().advance |entry| {
|
||||||
if entry.box == box {
|
if entry.box == box {
|
||||||
str::push_str(&mut msg, sep);
|
str::push_str(&mut msg, sep);
|
||||||
let filename = str::raw::from_c_str(entry.file);
|
let filename = str::raw::from_c_str(entry.file);
|
||||||
|
|||||||
@@ -1598,34 +1598,6 @@ pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterates over a vector's elements in reverse
|
|
||||||
*
|
|
||||||
* Return true to continue, false to break.
|
|
||||||
*/
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn each_reverse<'r,T>(v: &'r [T], blk: &fn(v: &'r T) -> bool) -> bool {
|
|
||||||
eachi_reverse(v, |_i, v| blk(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterates over a vector's elements and indices in reverse
|
|
||||||
*
|
|
||||||
* Return true to continue, false to break.
|
|
||||||
*/
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn eachi_reverse<'r,T>(v: &'r [T],
|
|
||||||
blk: &fn(i: uint, v: &'r T) -> bool) -> bool {
|
|
||||||
let mut i = v.len();
|
|
||||||
while i > 0 {
|
|
||||||
i -= 1;
|
|
||||||
if !blk(i, &v[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate over all permutations of vector `v`.
|
* Iterate over all permutations of vector `v`.
|
||||||
*
|
*
|
||||||
@@ -1964,6 +1936,7 @@ impl<'self,T:Copy> CopyableVector<T> for &'self [T] {
|
|||||||
pub trait ImmutableVector<'self, T> {
|
pub trait ImmutableVector<'self, T> {
|
||||||
fn slice(&self, start: uint, end: uint) -> &'self [T];
|
fn slice(&self, start: uint, end: uint) -> &'self [T];
|
||||||
fn iter(self) -> VecIterator<'self, T>;
|
fn iter(self) -> VecIterator<'self, T>;
|
||||||
|
fn rev_iter(self) -> VecRevIterator<'self, T>;
|
||||||
fn head(&self) -> &'self T;
|
fn head(&self) -> &'self T;
|
||||||
fn head_opt(&self) -> Option<&'self T>;
|
fn head_opt(&self) -> Option<&'self T>;
|
||||||
fn tail(&self) -> &'self [T];
|
fn tail(&self) -> &'self [T];
|
||||||
@@ -1974,8 +1947,6 @@ pub trait ImmutableVector<'self, T> {
|
|||||||
fn last_opt(&self) -> Option<&'self T>;
|
fn last_opt(&self) -> Option<&'self T>;
|
||||||
fn position(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
|
fn position(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
|
||||||
fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
|
fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
|
||||||
fn each_reverse(&self, blk: &fn(&T) -> bool) -> bool;
|
|
||||||
fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool) -> bool;
|
|
||||||
fn foldr<'a, U>(&'a self, z: U, p: &fn(t: &'a T, u: U) -> U) -> U;
|
fn foldr<'a, U>(&'a self, z: U, p: &fn(t: &'a T, u: U) -> U) -> U;
|
||||||
fn map<U>(&self, f: &fn(t: &T) -> U) -> ~[U];
|
fn map<U>(&self, f: &fn(t: &T) -> U) -> ~[U];
|
||||||
fn mapi<U>(&self, f: &fn(uint, t: &T) -> U) -> ~[U];
|
fn mapi<U>(&self, f: &fn(uint, t: &T) -> U) -> ~[U];
|
||||||
@@ -2002,6 +1973,15 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
|
|||||||
lifetime: cast::transmute(p)}
|
lifetime: cast::transmute(p)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
|
fn rev_iter(self) -> VecRevIterator<'self, T> {
|
||||||
|
unsafe {
|
||||||
|
let p = vec::raw::to_ptr(self);
|
||||||
|
VecRevIterator{ptr: p.offset(self.len() - 1),
|
||||||
|
end: p.offset(-1),
|
||||||
|
lifetime: cast::transmute(p)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the first element of a vector, failing if the vector is empty.
|
/// Returns the first element of a vector, failing if the vector is empty.
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -2059,18 +2039,6 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
|
|||||||
rposition(*self, f)
|
rposition(*self, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over a vector's elements in reverse.
|
|
||||||
#[inline]
|
|
||||||
fn each_reverse(&self, blk: &fn(&T) -> bool) -> bool {
|
|
||||||
each_reverse(*self, blk)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterates over a vector's elements and indices in reverse.
|
|
||||||
#[inline]
|
|
||||||
fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool) -> bool {
|
|
||||||
eachi_reverse(*self, blk)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reduce a vector from right to left
|
/// Reduce a vector from right to left
|
||||||
#[inline]
|
#[inline]
|
||||||
fn foldr<'a, U>(&'a self, z: U, p: &fn(t: &'a T, u: U) -> U) -> U {
|
fn foldr<'a, U>(&'a self, z: U, p: &fn(t: &'a T, u: U) -> U) -> U {
|
||||||
@@ -2350,7 +2318,8 @@ impl<T:Eq> OwnedEqVector<T> for ~[T] {
|
|||||||
#[allow(missing_doc)]
|
#[allow(missing_doc)]
|
||||||
pub trait MutableVector<'self, T> {
|
pub trait MutableVector<'self, T> {
|
||||||
fn mut_slice(self, start: uint, end: uint) -> &'self mut [T];
|
fn mut_slice(self, start: uint, end: uint) -> &'self mut [T];
|
||||||
fn mut_iter(self) -> MutVecIterator<'self, T>;
|
fn mut_iter(self) -> VecMutIterator<'self, T>;
|
||||||
|
fn mut_rev_iter(self) -> VecMutRevIterator<'self, T>;
|
||||||
|
|
||||||
unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T;
|
unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T;
|
||||||
unsafe fn unsafe_set(&self, index: uint, val: T);
|
unsafe fn unsafe_set(&self, index: uint, val: T);
|
||||||
@@ -2363,10 +2332,19 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mut_iter(self) -> MutVecIterator<'self, T> {
|
fn mut_iter(self) -> VecMutIterator<'self, T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let p = vec::raw::to_mut_ptr(self);
|
let p = vec::raw::to_mut_ptr(self);
|
||||||
MutVecIterator{ptr: p, end: p.offset(self.len()),
|
VecMutIterator{ptr: p, end: p.offset(self.len()),
|
||||||
|
lifetime: cast::transmute(p)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mut_rev_iter(self) -> VecMutRevIterator<'self, T> {
|
||||||
|
unsafe {
|
||||||
|
let p = vec::raw::to_mut_ptr(self);
|
||||||
|
VecMutRevIterator{ptr: p.offset(self.len() - 1),
|
||||||
|
end: p.offset(-1),
|
||||||
lifetime: cast::transmute(p)}
|
lifetime: cast::transmute(p)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2872,52 +2850,69 @@ impl<A:Clone> Clone for ~[A] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An external iterator for vectors (use with the std::iterator module)
|
macro_rules! iterator {
|
||||||
|
/* FIXME: #4375 Cannot attach documentation/attributes to a macro generated struct.
|
||||||
|
(struct $name:ident -> $ptr:ty, $elem:ty) => {
|
||||||
|
pub struct $name<'self, T> {
|
||||||
|
priv ptr: $ptr,
|
||||||
|
priv end: $ptr,
|
||||||
|
priv lifetime: $elem // FIXME: #5922
|
||||||
|
}
|
||||||
|
};*/
|
||||||
|
(impl $name:ident -> $elem:ty, $step:expr) => {
|
||||||
|
// could be implemented with &[T] with .slice(), but this avoids bounds checks
|
||||||
|
impl<'self, T> Iterator<$elem> for $name<'self, T> {
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<$elem> {
|
||||||
|
unsafe {
|
||||||
|
if self.ptr == self.end {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let old = self.ptr;
|
||||||
|
self.ptr = self.ptr.offset($step);
|
||||||
|
Some(cast::transmute(old))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//iterator!{struct VecIterator -> *T, &'self T}
|
||||||
|
/// An iterator for iterating over a vector
|
||||||
pub struct VecIterator<'self, T> {
|
pub struct VecIterator<'self, T> {
|
||||||
priv ptr: *T,
|
priv ptr: *T,
|
||||||
priv end: *T,
|
priv end: *T,
|
||||||
priv lifetime: &'self T // FIXME: #5922
|
priv lifetime: &'self T // FIXME: #5922
|
||||||
}
|
}
|
||||||
|
iterator!{impl VecIterator -> &'self T, 1}
|
||||||
|
|
||||||
// could be implemented with &[T] with .slice(), but this avoids bounds checks
|
//iterator!{struct VecRevIterator -> *T, &'self T}
|
||||||
impl<'self, T> Iterator<&'self T> for VecIterator<'self, T> {
|
/// An iterator for iterating over a vector in reverse
|
||||||
#[inline]
|
pub struct VecRevIterator<'self, T> {
|
||||||
fn next(&mut self) -> Option<&'self T> {
|
priv ptr: *T,
|
||||||
unsafe {
|
priv end: *T,
|
||||||
if self.ptr == self.end {
|
priv lifetime: &'self T // FIXME: #5922
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let old = self.ptr;
|
|
||||||
self.ptr = self.ptr.offset(1);
|
|
||||||
Some(cast::transmute(old))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
iterator!{impl VecRevIterator -> &'self T, -1}
|
||||||
|
|
||||||
/// An external iterator for vectors with the possibility of mutating
|
//iterator!{struct VecMutIterator -> *mut T, &'self mut T}
|
||||||
/// elements. (use with the std::iterator module)
|
/// An iterator for mutating the elements of a vector
|
||||||
pub struct MutVecIterator<'self, T> {
|
pub struct VecMutIterator<'self, T> {
|
||||||
priv ptr: *mut T,
|
priv ptr: *mut T,
|
||||||
priv end: *mut T,
|
priv end: *mut T,
|
||||||
priv lifetime: &'self mut T // FIXME: #5922
|
priv lifetime: &'self mut T // FIXME: #5922
|
||||||
}
|
}
|
||||||
|
iterator!{impl VecMutIterator -> &'self mut T, 1}
|
||||||
|
|
||||||
// could be implemented with &[T] with .slice(), but this avoids bounds checks
|
//iterator!{struct VecMutRevIterator -> *mut T, &'self mut T}
|
||||||
impl<'self, T> Iterator<&'self mut T> for MutVecIterator<'self, T> {
|
/// An iterator for mutating the elements of a vector in reverse
|
||||||
#[inline]
|
pub struct VecMutRevIterator<'self, T> {
|
||||||
fn next(&mut self) -> Option<&'self mut T> {
|
priv ptr: *mut T,
|
||||||
unsafe {
|
priv end: *mut T,
|
||||||
if self.ptr == self.end {
|
priv lifetime: &'self mut T // FIXME: #5922
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let old = self.ptr;
|
|
||||||
self.ptr = self.ptr.offset(1);
|
|
||||||
Some(cast::transmute(old))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
iterator!{impl VecMutRevIterator -> &'self mut T, -1}
|
||||||
|
|
||||||
impl<T> FromIter<T> for ~[T]{
|
impl<T> FromIter<T> for ~[T]{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -3527,43 +3522,6 @@ mod tests {
|
|||||||
assert_eq!(i, 6);
|
assert_eq!(i, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_each_reverse_empty() {
|
|
||||||
let v: ~[int] = ~[];
|
|
||||||
for v.each_reverse |_v| {
|
|
||||||
fail!(); // should never execute
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_each_reverse_nonempty() {
|
|
||||||
let mut i = 0;
|
|
||||||
for each_reverse([1, 2, 3]) |v| {
|
|
||||||
if i == 0 { assert!(*v == 3); }
|
|
||||||
i += *v
|
|
||||||
}
|
|
||||||
assert_eq!(i, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_eachi_reverse() {
|
|
||||||
let mut i = 0;
|
|
||||||
for eachi_reverse([0, 1, 2]) |j, v| {
|
|
||||||
if i == 0 { assert!(*v == 2); }
|
|
||||||
assert_eq!(j, *v as uint);
|
|
||||||
i += *v;
|
|
||||||
}
|
|
||||||
assert_eq!(i, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_eachi_reverse_empty() {
|
|
||||||
let v: ~[int] = ~[];
|
|
||||||
for v.eachi_reverse |_i, _v| {
|
|
||||||
fail!(); // should never execute
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_each_ret_len0() {
|
fn test_each_ret_len0() {
|
||||||
let mut a0 : [int, .. 0] = [];
|
let mut a0 : [int, .. 0] = [];
|
||||||
@@ -4642,6 +4600,30 @@ mod tests {
|
|||||||
assert_eq!(xs, [2, 3, 4, 5, 6])
|
assert_eq!(xs, [2, 3, 4, 5, 6])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rev_iterator() {
|
||||||
|
use iterator::*;
|
||||||
|
|
||||||
|
let xs = [1, 2, 5, 10, 11];
|
||||||
|
let ys = [11, 10, 5, 2, 1];
|
||||||
|
let mut i = 0;
|
||||||
|
for xs.rev_iter().advance |&x| {
|
||||||
|
assert_eq!(x, ys[i]);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
assert_eq!(i, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mut_rev_iterator() {
|
||||||
|
use iterator::*;
|
||||||
|
let mut xs = [1, 2, 3, 4, 5];
|
||||||
|
for xs.mut_rev_iter().enumerate().advance |(i,x)| {
|
||||||
|
*x += i;
|
||||||
|
}
|
||||||
|
assert_eq!(xs, [5, 5, 5, 5, 5])
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reverse_part() {
|
fn test_reverse_part() {
|
||||||
let mut values = [1,2,3,4,5];
|
let mut values = [1,2,3,4,5];
|
||||||
|
|||||||
Reference in New Issue
Block a user