diff options
| author | Felix S. Klock II <pnkfelix@pnkfx.org> | 2013-06-27 14:20:42 +0200 |
|---|---|---|
| committer | Felix S. Klock II <pnkfelix@pnkfx.org> | 2013-07-10 09:35:35 +0200 |
| commit | 3c19f1bca83be3f4abef378d0a4cd852c8615164 (patch) | |
| tree | 02e3a0567d5295474bb41f278ddb7509138d91f9 /src/libstd/num/int_macros.rs | |
| parent | 41dcec2fe16e272016ae77d10a6a5ff3a737f192 (diff) | |
Refactored int/uint range code in preparation for change to range_rev semantics.
Also added unit tests of range code to test refactoring. The num-range-rev.rs test will need to be updated when the range_rev semantics change.
Diffstat (limited to 'src/libstd/num/int_macros.rs')
| -rw-r--r-- | src/libstd/num/int_macros.rs | 88 |
1 files changed, 72 insertions, 16 deletions
diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 75e0bbcb71b..4fd30be80e6 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -29,28 +29,38 @@ pub static bytes : uint = ($bits / 8); pub static min_value: $T = (-1 as $T) << (bits - 1); pub static max_value: $T = min_value - 1 as $T; +enum Range { Closed, HalfOpen } + +#[inline] /// -/// Iterate over the range [`lo`..`hi`) +/// Iterate through a range with a given step value. /// -/// # Arguments +/// 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`. /// -/// * `lo` - lower bound, inclusive -/// * `hi` - higher bound, exclusive -/// -/// # Examples -/// ~~~ -/// let mut sum = 0; -/// for int::range(1, 5) |i| { -/// sum += i; -/// } -/// assert!(sum == 10); -/// ~~~ +/// If no such nonnegative integer `n` exists, then the iteration range +/// is empty. /// -#[inline] -pub fn range_step(start: $T, stop: $T, step: $T, it: &fn($T) -> bool) -> bool { +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; } @@ -66,9 +76,55 @@ pub fn range_step(start: $T, stop: $T, step: $T, it: &fn($T) -> bool) -> bool { i += step; } } - return true; + 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) } + #[inline] /// Iterate over the range [`lo`..`hi`) pub fn range(lo: $T, hi: $T, it: &fn($T) -> bool) -> bool { |
