From 910717e603e1a057de3da87a13cb6188d0959d49 Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Sun, 15 Sep 2013 05:25:30 +0200 Subject: [PATCH 1/3] std::iter: Make sure RangeStep[Inclusive] terminates properly Loops with negative step that didn't terminate evenly, i.e. overshot the stop value, didn't terminate at all. For example `range_step(28, -1, -4)` --- src/libstd/iter.rs | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index 22e8a1defbda9..21a99bf083e0c 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -1857,7 +1857,8 @@ pub fn range_step<A: CheckedAdd + Ord + Clone + Zero>(start: A, stop: A, step: A impl<A: CheckedAdd + Ord + Clone> Iterator<A> for RangeStep<A> { #[inline] fn next(&mut self) -> Option<A> { - if (self.rev && self.state > self.stop) || self.state < self.stop { + if (!self.rev && self.state < self.stop) || + (self.rev && self.state > self.stop) { let result = self.state.clone(); match self.state.checked_add(&self.step) { Some(x) => self.state = x, @@ -1891,22 +1892,15 @@ pub fn range_step_inclusive<A: CheckedAdd + Ord + Clone + Zero>(start: A, stop: impl<A: CheckedAdd + Ord + Clone + Eq> Iterator<A> for RangeStepInclusive<A> { #[inline] fn next(&mut self) -> Option<A> { - if !self.done { - if (self.rev && self.state > self.stop) || self.state < self.stop { - let result = self.state.clone(); - match self.state.checked_add(&self.step) { - Some(x) => self.state = x, - None => self.done = true - } - Some(result) - } else { - if self.state == self.stop { - self.done = true; - Some(self.state.clone()) - } else { - None - } + if !self.done && + ((!self.rev && self.state <= self.stop) || + (self.rev && self.state >= self.stop)) { + let result = self.state.clone(); + match self.state.checked_add(&self.step) { + Some(x) => self.state = x, + None => self.done = true } + Some(result) } else { None } @@ -2727,6 +2721,7 @@ mod tests { assert_eq!(range_step(0i, 20, 5).collect::<~[int]>(), ~[0, 5, 10, 15]); assert_eq!(range_step(20i, 0, -5).collect::<~[int]>(), ~[20, 15, 10, 5]); assert_eq!(range_step(200u8, 255, 50).collect::<~[u8]>(), ~[200u8, 250]); + assert_eq!(range_step(20i, -1, -5).collect::<~[int]>(), ~[20, 15, 10, 5, 0]); } #[test] @@ -2734,6 +2729,7 @@ mod tests { assert_eq!(range_step_inclusive(0i, 20, 5).collect::<~[int]>(), ~[0, 5, 10, 15, 20]); assert_eq!(range_step_inclusive(20i, 0, -5).collect::<~[int]>(), ~[20, 15, 10, 5, 0]); assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<~[u8]>(), ~[200u8, 250]); + assert_eq!(range_step_inclusive(20i, -1, -5).collect::<~[int]>(), ~[20, 15, 10, 5, 0]); } #[test] From 82f832f43056fc4f61eb938fd7b183dd321c6c23 Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Sun, 15 Sep 2013 02:46:51 +0200 Subject: [PATCH 2/3] Use std::iter::range_step Use the iterator version instead of the old uint::/int::range_step functions. --- src/libextra/crypto/md5.rs | 22 +++++++++------------- src/libextra/crypto/sha2.rs | 22 +++++++++------------- src/libstd/char.rs | 7 +++---- src/libstd/rand.rs | 27 ++++++++++++--------------- src/libstd/trie.rs | 28 ++++++++++++---------------- src/test/run-pass/num-range-rev.rs | 4 ++-- src/test/run-pass/num-range.rs | 24 ++++++++++-------------- 7 files changed, 57 insertions(+), 77 deletions(-) diff --git a/src/libextra/crypto/md5.rs b/src/libextra/crypto/md5.rs index 8e8b752da8075..8e07c7ee1c7ca 100644 --- a/src/libextra/crypto/md5.rs +++ b/src/libextra/crypto/md5.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::uint; +use std::iter::range_step; use cryptoutil::{write_u32_le, read_u32v_le, FixedBuffer, FixedBuffer64, StandardPadding}; use digest::Digest; @@ -86,46 +86,42 @@ impl Md5State { read_u32v_le(data, input); // round 1 - do uint::range_step(0, 16, 4) |i| { + for i in range_step(0u, 16, 4) { a = op_f(a, b, c, d, data[i] + C1[i], 7); d = op_f(d, a, b, c, data[i + 1] + C1[i + 1], 12); c = op_f(c, d, a, b, data[i + 2] + C1[i + 2], 17); b = op_f(b, c, d, a, data[i + 3] + C1[i + 3], 22); - true - }; + } // round 2 let mut t = 1; - do uint::range_step(0, 16, 4) |i| { + for i in range_step(0u, 16, 4) { a = op_g(a, b, c, d, data[t & 0x0f] + C2[i], 5); d = op_g(d, a, b, c, data[(t + 5) & 0x0f] + C2[i + 1], 9); c = op_g(c, d, a, b, data[(t + 10) & 0x0f] + C2[i + 2], 14); b = op_g(b, c, d, a, data[(t + 15) & 0x0f] + C2[i + 3], 20); t += 20; - true - }; + } // round 3 t = 5; - do uint::range_step(0, 16, 4) |i| { + for i in range_step(0u, 16, 4) { a = op_h(a, b, c, d, data[t & 0x0f] + C3[i], 4); d = op_h(d, a, b, c, data[(t + 3) & 0x0f] + C3[i + 1], 11); c = op_h(c, d, a, b, data[(t + 6) & 0x0f] + C3[i + 2], 16); b = op_h(b, c, d, a, data[(t + 9) & 0x0f] + C3[i + 3], 23); t += 12; - true - }; + } // round 4 t = 0; - do uint::range_step(0, 16, 4) |i| { + for i in range_step(0u, 16, 4) { a = op_i(a, b, c, d, data[t & 0x0f] + C4[i], 6); d = op_i(d, a, b, c, data[(t + 7) & 0x0f] + C4[i + 1], 10); c = op_i(c, d, a, b, data[(t + 14) & 0x0f] + C4[i + 2], 15); b = op_i(b, c, d, a, data[(t + 21) & 0x0f] + C4[i + 3], 21); t += 28; - true - }; + } self.s0 += a; self.s1 += b; diff --git a/src/libextra/crypto/sha2.rs b/src/libextra/crypto/sha2.rs index 49bbddca1dbb7..10289fb8b9764 100644 --- a/src/libextra/crypto/sha2.rs +++ b/src/libextra/crypto/sha2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::uint; +use std::iter::range_step; use cryptoutil::{write_u64_be, write_u32_be, read_u64v_be, read_u32v_be, add_bytes_to_bits, add_bytes_to_bits_tuple, FixedBuffer, FixedBuffer128, FixedBuffer64, StandardPadding}; @@ -111,7 +111,7 @@ impl Engine512State { // Putting the message schedule inside the same loop as the round calculations allows for // the compiler to generate better code. - do uint::range_step(0, 64, 8) |t| { + for t in range_step(0u, 64, 8) { schedule_round!(t + 16); schedule_round!(t + 17); schedule_round!(t + 18); @@ -129,10 +129,9 @@ impl Engine512State { sha2_round!(d, e, f, g, h, a, b, c, K64, t + 5); sha2_round!(c, d, e, f, g, h, a, b, K64, t + 6); sha2_round!(b, c, d, e, f, g, h, a, K64, t + 7); - true - }; + } - do uint::range_step(64, 80, 8) |t| { + for t in range_step(64u, 80, 8) { sha2_round!(a, b, c, d, e, f, g, h, K64, t); sha2_round!(h, a, b, c, d, e, f, g, K64, t + 1); sha2_round!(g, h, a, b, c, d, e, f, K64, t + 2); @@ -141,8 +140,7 @@ impl Engine512State { sha2_round!(d, e, f, g, h, a, b, c, K64, t + 5); sha2_round!(c, d, e, f, g, h, a, b, K64, t + 6); sha2_round!(b, c, d, e, f, g, h, a, K64, t + 7); - true - }; + } self.H0 += a; self.H1 += b; @@ -527,7 +525,7 @@ impl Engine256State { // Putting the message schedule inside the same loop as the round calculations allows for // the compiler to generate better code. - do uint::range_step(0, 48, 8) |t| { + for t in range_step(0u, 48, 8) { schedule_round!(t + 16); schedule_round!(t + 17); schedule_round!(t + 18); @@ -545,10 +543,9 @@ impl Engine256State { sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5); sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6); sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7); - true - }; + } - do uint::range_step(48, 64, 8) |t| { + for t in range_step(48u, 64, 8) { sha2_round!(a, b, c, d, e, f, g, h, K32, t); sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1); sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2); @@ -557,8 +554,7 @@ impl Engine256State { sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5); sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6); sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7); - true - }; + } self.H0 += a; self.H1 += b; diff --git a/src/libstd/char.rs b/src/libstd/char.rs index 3a01e5908d9db..911d883f88ac9 100644 --- a/src/libstd/char.rs +++ b/src/libstd/char.rs @@ -12,7 +12,7 @@ use cast::transmute; use option::{None, Option, Some}; -use i32; +use iter::{Iterator, range_step}; use str::StrSlice; use unicode::{derived_property, general_category, decompose}; use to_str::ToStr; @@ -286,15 +286,14 @@ pub fn escape_unicode(c: char, f: &fn(char)) { (c <= '\uffff') { f('u'); 4 } _ { f('U'); 8 } ); - do i32::range_step(4 * (pad - 1), -1, -4) |offset| { + for offset in range_step::<i32>(4 * (pad - 1), -1, -4) { unsafe { match ((c as i32) >> offset) & 0xf { i @ 0 .. 9 => { f(transmute('0' as i32 + i)); } i => { f(transmute('a' as i32 + (i - 10))); } } } - true - }; + } } /// diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs index 813901207bb2d..1330096ee36a6 100644 --- a/src/libstd/rand.rs +++ b/src/libstd/rand.rs @@ -48,7 +48,7 @@ use clone::Clone; use cmp; use container::Container; use int; -use iter::{Iterator, range}; +use iter::{Iterator, range, range_step}; use local_data; use num; use prelude::*; @@ -748,7 +748,7 @@ impl IsaacRng { if use_rsl { macro_rules! memloop ( ($arr:expr) => {{ - do u32::range_step(0, RAND_SIZE, 8) |i| { + for i in range_step(0u32, RAND_SIZE, 8) { a+=$arr[i ]; b+=$arr[i+1]; c+=$arr[i+2]; d+=$arr[i+3]; e+=$arr[i+4]; f+=$arr[i+5]; @@ -758,22 +758,20 @@ impl IsaacRng { self.mem[i+2]=c; self.mem[i+3]=d; self.mem[i+4]=e; self.mem[i+5]=f; self.mem[i+6]=g; self.mem[i+7]=h; - true - }; + } }} ); memloop!(self.rsl); memloop!(self.mem); } else { - do u32::range_step(0, RAND_SIZE, 8) |i| { + for i in range_step(0u32, RAND_SIZE, 8) { mix!(); self.mem[i ]=a; self.mem[i+1]=b; self.mem[i+2]=c; self.mem[i+3]=d; self.mem[i+4]=e; self.mem[i+5]=f; self.mem[i+6]=g; self.mem[i+7]=h; - true - }; + } } self.isaac(); @@ -794,7 +792,7 @@ impl IsaacRng { }); macro_rules! rngstep( ($j:expr, $shift:expr) => {{ - let base = base + $j; + let base = $j; let mix = if $shift < 0 { a >> -$shift as uint } else { @@ -813,13 +811,12 @@ impl IsaacRng { let r = [(0, MIDPOINT), (MIDPOINT, 0)]; for &(mr_offset, m2_offset) in r.iter() { - do uint::range_step(0, MIDPOINT, 4) |base| { - rngstep!(0, 13); - rngstep!(1, -6); - rngstep!(2, 2); - rngstep!(3, -16); - true - }; + for i in range_step(0u, MIDPOINT, 4) { + rngstep!(i + 0, 13); + rngstep!(i + 1, -6); + rngstep!(i + 2, 2); + rngstep!(i + 3, -16); + } } self.a = a; diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs index 32797216376be..88a953a1601e9 100644 --- a/src/libstd/trie.rs +++ b/src/libstd/trie.rs @@ -520,6 +520,7 @@ pub fn check_integrity<T>(trie: &TrieNode<T>) { mod test_map { use super::*; use prelude::*; + use iter::range_step; use uint; #[test] @@ -538,21 +539,19 @@ mod test_map { #[test] fn test_step() { let mut trie = TrieMap::new(); - let n = 300; + let n = 300u; - do uint::range_step(1, n, 2) |x| { + for x in range_step(1u, n, 2) { assert!(trie.insert(x, x + 1)); assert!(trie.contains_key(&x)); check_integrity(&trie.root); - true - }; + } - do uint::range_step(0, n, 2) |x| { + for x in range_step(0u, n, 2) { assert!(!trie.contains_key(&x)); assert!(trie.insert(x, x + 1)); check_integrity(&trie.root); - true - }; + } for x in range(0u, n) { assert!(trie.contains_key(&x)); @@ -560,19 +559,17 @@ mod test_map { check_integrity(&trie.root); } - do uint::range_step(1, n, 2) |x| { + for x in range_step(1u, n, 2) { assert!(trie.remove(&x)); assert!(!trie.contains_key(&x)); check_integrity(&trie.root); - true - }; + } - do uint::range_step(0, n, 2) |x| { + for x in range_step(0u, n, 2) { assert!(trie.contains_key(&x)); assert!(!trie.insert(x, x + 1)); check_integrity(&trie.root); - true - }; + } } #[test] @@ -715,11 +712,10 @@ mod test_map { let value = 42u; let mut map : TrieMap<uint> = TrieMap::new(); - do uint::range_step(0u, last, step as int) |x| { + for x in range_step(0u, last, step) { assert!(x % step == 0); map.insert(x, value); - true - }; + } for i in range(0u, last - step) { let mut lb = map.lower_bound_iter(i); diff --git a/src/test/run-pass/num-range-rev.rs b/src/test/run-pass/num-range-rev.rs index ea7d4a651f75d..05b84c059c4b3 100644 --- a/src/test/run-pass/num-range-rev.rs +++ b/src/test/run-pass/num-range-rev.rs @@ -28,11 +28,11 @@ fn int_range_rev(hi: int, lo: int, it: &fn(int) -> bool) -> bool { } fn int_range_step(a: int, b: int, step: int, it: &fn(int) -> bool) -> bool { - int::range_step(a, b, step, it) + std::iter::range_step(a, b, step).advance(it) } fn uint_range_step(a: uint, b: uint, step: int, it: &fn(uint) -> bool) -> bool { - uint::range_step(a, b, step, it) + std::iter::range_step(a, b, step).advance(it) } diff --git a/src/test/run-pass/num-range.rs b/src/test/run-pass/num-range.rs index 7376edef8a8f6..5f87d01719ec0 100644 --- a/src/test/run-pass/num-range.rs +++ b/src/test/run-pass/num-range.rs @@ -20,11 +20,11 @@ fn int_range(lo: int, hi: int, it: &fn(int) -> bool) -> bool { } fn int_range_step(a: int, b: int, step: int, it: &fn(int) -> bool) -> bool { - int::range_step(a, b, step, it) + std::iter::range_step(a, b, step).advance(it) } fn uint_range_step(a: uint, b: uint, s: int, it: &fn(uint) -> bool) -> bool { - uint::range_step(a, b, s, it) + std::iter::range_step(a, b, s).advance(it) } pub fn main() { @@ -98,35 +98,31 @@ pub fn main() { // range_step_inclusive will never pass stop element, and may skip it. let mut saw21 = false; - do uint::range_step_inclusive(0, 21, 4) |x| { + for x in std::iter::range_step_inclusive(0, 21, 4) { assert!(x <= 21); if x == 21 { saw21 = true; } - true - }; + } assert!(!saw21); let mut saw21 = false; - do int::range_step_inclusive(0, 21, 4) |x| { + for x in std::iter::range_step_inclusive(0, 21, 4) { assert!(x <= 21); if x == 21 { saw21 = true; } - true - }; + } assert!(!saw21); // range_step_inclusive will never pass stop element, but may visit it. let mut saw21 = false; - do uint::range_step_inclusive(0, 21, 3) |x| { + for x in std::iter::range_step_inclusive(0, 21, 3) { assert!(x <= 21); printfln!("saw: %u", x); if x == 21 { saw21 = true; } - true - }; + } assert!(saw21); let mut saw21 = false; - do int::range_step_inclusive(0, 21, 3) |x| { + for x in std::iter::range_step_inclusive(0, 21, 3) { assert!(x <= 21); if x == 21 { saw21 = true; } - true - }; + } assert!(saw21); } From 2e664c3ba3f0e402e96d4b1a23cdb163ecd679ff Mon Sep 17 00:00:00 2001 From: blake2-ppc <blake2-ppc> Date: Sun, 15 Sep 2013 02:47:20 +0200 Subject: [PATCH 3/3] std::num: Remove `range_step` for each numeric type Replaced by `std::iter::range_step` --- src/libstd/num/int_macros.rs | 145 -------------------------------- src/libstd/num/uint_macros.rs | 151 ---------------------------------- 2 files changed, 296 deletions(-) diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index ae2a56b835dd2..39f32c5ff426e 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -41,101 +41,6 @@ impl CheckedDiv for $T { } } -enum Range { Closed, HalfOpen } - -#[inline] -/// -/// Iterate through a range with a given step value. -/// -/// Let `term` denote the closed interval `[stop-step,stop]` if `r` is Closed; -/// otherwise `term` denotes the half-open interval `[stop-step,stop)`. -/// Iterates through the range `[x_0, x_1, ..., x_n]` where -/// `x_j == start + step*j`, and `x_n` lies in the interval `term`. -/// -/// If no such nonnegative integer `n` exists, then the iteration range -/// is empty. -/// -fn range_step_core(start: $T, stop: $T, step: $T, r: Range, it: &fn($T) -> bool) -> bool { - let mut i = start; - if step == 0 { - fail!(~"range_step called with step == 0"); - } else if step == (1 as $T) { // elide bounds check to tighten loop - while i < stop { - if !it(i) { return false; } - // no need for overflow check; - // cannot have i + 1 > max_value because i < stop <= max_value - i += (1 as $T); - } - } else if step == (-1 as $T) { // elide bounds check to tighten loop - while i > stop { - if !it(i) { return false; } - // no need for underflow check; - // cannot have i - 1 < min_value because i > stop >= min_value - i -= (1 as $T); - } - } else if step > 0 { // ascending - while i < stop { - if !it(i) { return false; } - // avoiding overflow. break if i + step > max_value - if i > max_value - step { return true; } - i += step; - } - } else { // descending - while i > stop { - if !it(i) { return false; } - // avoiding underflow. break if i + step < min_value - if i < min_value - step { return true; } - i += step; - } - } - match r { - HalfOpen => return true, - Closed => return (i != stop || it(i)) - } -} - -#[inline] -/// -/// Iterate through the range [`start`..`stop`) with a given step value. -/// -/// Iterates through the range `[x_0, x_1, ..., x_n]` where -/// * `x_i == start + step*i`, and -/// * `n` is the greatest nonnegative integer such that `x_n < stop` -/// -/// (If no such `n` exists, then the iteration range is empty.) -/// -/// # Arguments -/// -/// * `start` - lower bound, inclusive -/// * `stop` - higher bound, exclusive -/// -/// # Examples -/// ~~~ -/// let mut sum = 0; -/// for int::range(1, 5) |i| { -/// sum += i; -/// } -/// assert!(sum == 10); -/// ~~~ -/// -pub fn range_step(start: $T, stop: $T, step: $T, it: &fn($T) -> bool) -> bool { - range_step_core(start, stop, step, HalfOpen, it) -} - -#[inline] -/// -/// Iterate through a range with a given step value. -/// -/// Iterates through the range `[x_0, x_1, ..., x_n]` where -/// `x_i == start + step*i` and `x_n <= last < step + x_n`. -/// -/// (If no such nonnegative integer `n` exists, then the iteration -/// range is empty.) -/// -pub fn range_step_inclusive(start: $T, last: $T, step: $T, it: &fn($T) -> bool) -> bool { - range_step_core(start, last, step, Closed, it) -} - impl Num for $T {} #[cfg(not(test))] @@ -878,56 +783,6 @@ mod tests { assert!(i64::from_str("-9223372036854775809").is_none()); } - #[test] - fn test_ranges() { - let mut l = ~[]; - - do range_step(20,26,2) |i| { - l.push(i); - true - }; - do range_step(36,30,-2) |i| { - l.push(i); - true - }; - do range_step(max_value - 2, max_value, 2) |i| { - l.push(i); - true - }; - do range_step(max_value - 3, max_value, 2) |i| { - l.push(i); - true - }; - do range_step(min_value + 2, min_value, -2) |i| { - l.push(i); - true - }; - do range_step(min_value + 3, min_value, -2) |i| { - l.push(i); - true - }; - assert_eq!(l, ~[20,22,24, - 36,34,32, - max_value-2, - max_value-3,max_value-1, - min_value+2, - min_value+3,min_value+1]); - - // None of the `fail`s should execute. - do range_step(10,0,1) |_i| { - fail!(~"unreachable"); - }; - do range_step(0,10,-1) |_i| { - fail!(~"unreachable"); - }; - } - - #[test] - #[should_fail] - fn test_range_step_zero_step() { - do range_step(0,10,0) |_i| { true }; - } - #[test] fn test_signed_checked_div() { assert_eq!(10i.checked_div(&2), Some(5)); diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 3deb7312b04f1..4c64efb9114aa 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -42,101 +42,6 @@ impl CheckedDiv for $T { } } -enum Range { Closed, HalfOpen } - -#[inline] -/// -/// Iterate through a range with a given step value. -/// -/// Let `term` denote the closed interval `[stop-step,stop]` if `r` is Closed; -/// otherwise `term` denotes the half-open interval `[stop-step,stop)`. -/// Iterates through the range `[x_0, x_1, ..., x_n]` where -/// `x_j == start + step*j`, and `x_n` lies in the interval `term`. -/// -/// If no such nonnegative integer `n` exists, then the iteration range -/// is empty. -/// -fn range_step_core(start: $T, stop: $T, step: $T_SIGNED, r: Range, it: &fn($T) -> bool) -> bool { - let mut i = start; - if step == 0 { - fail!("range_step called with step == 0"); - } else if step == (1 as $T_SIGNED) { // elide bounds check to tighten loop - while i < stop { - if !it(i) { return false; } - // no need for overflow check; - // cannot have i + 1 > max_value because i < stop <= max_value - i += (1 as $T); - } - } else if step == (-1 as $T_SIGNED) { // elide bounds check to tighten loop - while i > stop { - if !it(i) { return false; } - // no need for underflow check; - // cannot have i - 1 < min_value because i > stop >= min_value - i -= (1 as $T); - } - } else if step > 0 { // ascending - while i < stop { - if !it(i) { return false; } - // avoiding overflow. break if i + step > max_value - if i > max_value - (step as $T) { return true; } - i += step as $T; - } - } else { // descending - while i > stop { - if !it(i) { return false; } - // avoiding underflow. break if i + step < min_value - if i < min_value + ((-step) as $T) { return true; } - i -= -step as $T; - } - } - match r { - HalfOpen => return true, - Closed => return (i != stop || it(i)) - } -} - -#[inline] -/// -/// Iterate through the range [`start`..`stop`) with a given step value. -/// -/// Iterates through the range `[x_0, x_1, ..., x_n]` where -/// - `x_i == start + step*i`, and -/// - `n` is the greatest nonnegative integer such that `x_n < stop` -/// -/// (If no such `n` exists, then the iteration range is empty.) -/// -/// # Arguments -/// -/// * `start` - lower bound, inclusive -/// * `stop` - higher bound, exclusive -/// -/// # Examples -/// ~~~ {.rust} -/// let nums = [1,2,3,4,5,6,7]; -/// -/// for uint::range_step(0, nums.len() - 1, 2) |i| { -/// printfln!("%d & %d", nums[i], nums[i+1]); -/// } -/// ~~~ -/// -pub fn range_step(start: $T, stop: $T, step: $T_SIGNED, it: &fn($T) -> bool) -> bool { - range_step_core(start, stop, step, HalfOpen, it) -} - -#[inline] -/// -/// Iterate through a range with a given step value. -/// -/// Iterates through the range `[x_0, x_1, ..., x_n]` where -/// `x_i == start + step*i` and `x_n <= last < step + x_n`. -/// -/// (If no such nonnegative integer `n` exists, then the iteration -/// range is empty.) -/// -pub fn range_step_inclusive(start: $T, last: $T, step: $T_SIGNED, it: &fn($T) -> bool) -> bool { - range_step_core(start, last, step, Closed, it) -} - impl Num for $T {} #[cfg(not(test))] @@ -653,62 +558,6 @@ mod tests { 100u.to_str_radix(37u); } - #[test] - pub fn test_ranges() { - let mut l = ~[]; - - do range_step(20,26,2) |i| { - l.push(i); - true - }; - do range_step(36,30,-2) |i| { - l.push(i); - true - }; - do range_step(max_value - 2, max_value, 2) |i| { - l.push(i); - true - }; - do range_step(max_value - 3, max_value, 2) |i| { - l.push(i); - true - }; - do range_step(min_value + 2, min_value, -2) |i| { - l.push(i); - true - }; - do range_step(min_value + 3, min_value, -2) |i| { - l.push(i); - true - }; - - assert_eq!(l, ~[20,22,24, - 36,34,32, - max_value-2, - max_value-3,max_value-1, - min_value+2, - min_value+3,min_value+1]); - - // None of the `fail`s should execute. - do range_step(10,0,1) |_i| { - fail!("unreachable"); - }; - do range_step(0,1,-10) |_i| { - fail!("unreachable"); - }; - } - - #[test] - #[should_fail] - fn test_range_step_zero_step_up() { - do range_step(0,10,0) |_i| { true }; - } - #[test] - #[should_fail] - fn test_range_step_zero_step_down() { - do range_step(0,-10,0) |_i| { true }; - } - #[test] fn test_unsigned_checked_div() { assert_eq!(10u.checked_div(&2), Some(5));