diff --git a/src/libextra/smallintmap.rs b/src/libextra/smallintmap.rs
index d952374ee5ccc..329d3a454b45a 100644
--- a/src/libextra/smallintmap.rs
+++ b/src/libextra/smallintmap.rs
@@ -159,8 +159,8 @@ impl<V> SmallIntMap<V> {
     /// Visit all key-value pairs in reverse order
     pub fn each_reverse<'a>(&'a self, it: &fn(uint, &'a V) -> bool) -> bool {
         for uint::range_rev(self.v.len(), 0) |i| {
-            match self.v[i - 1] {
-              Some(ref elt) => if !it(i - 1, elt) { return false; },
+            match self.v[i] {
+              Some(ref elt) => if !it(i, elt) { return false; },
               None => ()
             }
         }
diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs
index 75e0bbcb71b04..cef32b5c7e445 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 {
@@ -76,9 +132,10 @@ pub fn range(lo: $T, hi: $T, it: &fn($T) -> bool) -> bool {
 }
 
 #[inline]
-/// Iterate over the range [`hi`..`lo`)
+/// Iterate over the range (`hi`..`lo`]
 pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool {
-    range_step(hi, lo, -1 as $T, it)
+    if hi == min_value { return true; }
+    range_step_inclusive(hi-1, lo, -1 as $T, it)
 }
 
 impl Num for $T {}
@@ -841,7 +898,7 @@ mod tests {
         for range(0,3) |i| {
             l.push(i);
         }
-        for range_rev(13,10) |i| {
+        for range_rev(14,11) |i| {
             l.push(i);
         }
         for range_step(20,26,2) |i| {
diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs
index de1b997b14b52..54c1327fa9303 100644
--- a/src/libstd/num/uint_macros.rs
+++ b/src/libstd/num/uint_macros.rs
@@ -30,32 +30,46 @@ pub static bytes : uint = ($bits / 8);
 pub static min_value: $T = 0 as $T;
 pub static max_value: $T = 0 as $T - 1 as $T;
 
+enum Range { Closed, HalfOpen }
+
 #[inline]
-/**
- * Iterate through a range with a given step value.
- *
- * # Examples
- * ~~~ {.rust}
- * let nums = [1,2,3,4,5,6,7];
- *
- * for uint::range_step(0, nums.len() - 1, 2) |i| {
- *     println(fmt!("%d & %d", nums[i], nums[i+1]));
- * }
- * ~~~
- */
-pub fn range_step(start: $T, stop: $T, step: $T_SIGNED, it: &fn($T) -> bool) -> bool {
+///
+/// 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");
-    }
-    if 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 {
+    } else { // descending
         while i > stop {
             if !it(i) { return false; }
             // avoiding underflow. break if i + step < min_value
@@ -63,7 +77,52 @@ pub fn range_step(start: $T, stop: $T, step: $T_SIGNED, it: &fn($T) -> bool) ->
             i -= -step as $T;
         }
     }
-    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
+/// ~~~ {.rust}
+/// let nums = [1,2,3,4,5,6,7];
+///
+/// for uint::range_step(0, nums.len() - 1, 2) |i| {
+///     println(fmt!("%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)
 }
 
 #[inline]
@@ -73,9 +132,10 @@ pub fn range(lo: $T, hi: $T, it: &fn($T) -> bool) -> bool {
 }
 
 #[inline]
-/// Iterate over the range [`hi`..`lo`)
+/// Iterate over the range (`hi`..`lo`]
 pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool {
-    range_step(hi, lo, -1 as $T_SIGNED, it)
+    if hi == min_value { return true; }
+    range_step_inclusive(hi-1, lo, -1 as $T_SIGNED, it)
 }
 
 impl Num for $T {}
@@ -603,7 +663,7 @@ mod tests {
         for range(0,3) |i| {
             l.push(i);
         }
-        for range_rev(13,10) |i| {
+        for range_rev(14,11) |i| {
             l.push(i);
         }
         for range_step(20,26,2) |i| {
diff --git a/src/libstd/run.rs b/src/libstd/run.rs
index 17dc604a17858..883870db1e673 100644
--- a/src/libstd/run.rs
+++ b/src/libstd/run.rs
@@ -669,7 +669,7 @@ fn spawn_process_os(prog: &str, args: &[~str],
             fail!("failure in dup3(err_fd, 2): %s", os::last_os_error());
         }
         // close all other fds
-        for int::range_rev(getdtablesize() as int - 1, 2) |fd| {
+        for int::range_rev(getdtablesize() as int, 3) |fd| {
             close(fd as c_int);
         }
 
diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs
index 8ce02d59ab15c..f4597f4b08e9e 100644
--- a/src/libstd/trie.rs
+++ b/src/libstd/trie.rs
@@ -261,7 +261,7 @@ impl<T> TrieNode<T> {
 
     fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
         for uint::range_rev(self.children.len(), 0) |idx| {
-            match self.children[idx - 1] {
+            match self.children[idx] {
                 Internal(ref x) => if !x.each_reverse(|i,t| f(i,t)) { return false },
                 External(k, ref v) => if !f(&k, v) { return false },
                 Nothing => ()
@@ -462,7 +462,7 @@ mod tests {
             m.insert(x, x / 2);
         }
 
-        let mut n = uint::max_value - 9999;
+        let mut n = uint::max_value - 10000;
         for m.each |k, v| {
             if n == uint::max_value - 5000 { break }
             assert!(n < uint::max_value - 5000);
@@ -499,7 +499,7 @@ mod tests {
             m.insert(x, x / 2);
         }
 
-        let mut n = uint::max_value;
+        let mut n = uint::max_value - 1;
         for m.each_reverse |k, v| {
             if n == uint::max_value - 5000 { break }
             assert!(n > uint::max_value - 5000);
diff --git a/src/test/run-pass/num-range-rev.rs b/src/test/run-pass/num-range-rev.rs
new file mode 100644
index 0000000000000..7262339e431d9
--- /dev/null
+++ b/src/test/run-pass/num-range-rev.rs
@@ -0,0 +1,114 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::int;
+use std::uint;
+
+fn uint_range(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool {
+    uint::range(lo, hi, it)
+}
+
+fn int_range(lo: int,  hi: int, it: &fn(int) -> bool) -> bool {
+    int::range(lo, hi, it)
+}
+
+fn uint_range_rev(hi: uint, lo: uint, it: &fn(uint) -> bool) -> bool {
+    uint::range_rev(hi, lo, it)
+}
+
+fn int_range_rev(hi: int,  lo: int, it: &fn(int) -> bool) -> bool {
+    int::range_rev(hi, lo, it)
+}
+
+fn int_range_step(a: int, b: int, step: int, it: &fn(int) -> bool) -> bool {
+    int::range_step(a, b, step, it)
+}
+
+fn uint_range_step(a: uint, b: uint, step: int, it: &fn(uint) -> bool) -> bool {
+    uint::range_step(a, b, step, it)
+}
+
+
+pub fn main() {
+    // int and uint have same result for
+    //   Sum{100 > i >= 2} == (Sum{1 <= i <= 99} - 1) == n*(n+1)/2 - 1 for n=99
+    let mut sum = 0u;
+    for uint_range_rev(100, 2) |i| {
+        sum += i;
+    }
+    assert_eq!(sum, 4949);
+
+    let mut sum = 0i;
+    for int_range_rev(100, 2) |i| {
+        sum += i;
+    }
+    assert_eq!(sum, 4949);
+
+
+    // elements are visited in correct order
+    let primes = [2,3,5,7,11];
+    let mut prod = 1i;
+    for uint_range_rev(5, 0) |i| {
+        println(fmt!("uint 4 downto 0: %u", i));
+        prod *= int::pow(primes[i], i);
+    }
+    assert_eq!(prod, 11*11*11*11*7*7*7*5*5*3*1);
+    let mut prod = 1i;
+    for int_range_rev(5, 0) |i| {
+        println(fmt!("int 4 downto 0: %d", i));
+        prod *= int::pow(primes[i], i as uint);
+    }
+    assert_eq!(prod, 11*11*11*11*7*7*7*5*5*3*1);
+
+
+    // range and range_rev are symmetric.
+    let mut sum_up = 0u;
+    for uint_range(10, 30) |i| {
+        sum_up += i;
+    }
+    let mut sum_down = 0u;
+    for uint_range_rev(30, 10) |i| {
+        sum_down += i;
+    }
+    assert_eq!(sum_up, sum_down);
+
+    let mut sum_up = 0;
+    for int_range(-20, 10) |i| {
+        sum_up += i;
+    }
+    let mut sum_down = 0;
+    for int_range_rev(10, -20) |i| {
+        sum_down += i;
+    }
+    assert_eq!(sum_up, sum_down);
+
+
+    // empty ranges
+    for int_range_rev(10, 10) |_| {
+        fail!("range should be empty when start == stop");
+    }
+
+    for uint_range_rev(0, 1) |_| {
+        fail!("range should be empty when start-1 underflows");
+    }
+
+    // range iterations do not wrap/underflow
+    let mut uflo_loop_visited = ~[];
+    for int_range_step(int::min_value+15, int::min_value, -4) |x| {
+        uflo_loop_visited.push(x - int::min_value);
+    }
+    assert_eq!(uflo_loop_visited, ~[15, 11, 7, 3]);
+
+    let mut uflo_loop_visited = ~[];
+    for uint_range_step(uint::min_value+15, uint::min_value, -4) |x| {
+        uflo_loop_visited.push(x - uint::min_value);
+    }
+    assert_eq!(uflo_loop_visited, ~[15, 11, 7, 3]);
+}
diff --git a/src/test/run-pass/num-range.rs b/src/test/run-pass/num-range.rs
new file mode 100644
index 0000000000000..7c1f905a049b6
--- /dev/null
+++ b/src/test/run-pass/num-range.rs
@@ -0,0 +1,119 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::int;
+use std::uint;
+
+fn uint_range(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool {
+    uint::range(lo, hi, it)
+}
+
+fn int_range(lo: int, hi: int, it: &fn(int) -> bool) -> bool {
+    int::range(lo, hi, it)
+}
+
+fn int_range_step(a: int, b: int, step: int, it: &fn(int) -> bool) -> bool {
+    int::range_step(a, b, step, it)
+}
+
+fn uint_range_step(a: uint, b: uint, s: int, it: &fn(uint) -> bool) -> bool {
+    uint::range_step(a, b, s, it)
+}
+
+pub fn main() {
+    println(fmt!("num-range start"));
+    // int and uint have same result for
+    //   Sum{2 <= i < 100} == (Sum{1 <= i <= 99} - 1) == n*(n+1)/2 - 1 for n=99
+    let mut sum = 0u;
+    for uint_range(2, 100) |i| {
+        sum += i;
+    }
+    assert_eq!(sum, 4949);
+
+    let mut sum = 0i;
+    for int_range(2, 100) |i| {
+        sum += i;
+    }
+    assert_eq!(sum, 4949);
+
+
+    // elements are visited in correct order
+    let primes = [2,3,5,7];
+    let mut prod = 1i;
+    for uint_range(0, 4) |i| {
+        prod *= int::pow(primes[i], i);
+    }
+    assert_eq!(prod, 1*3*5*5*7*7*7);
+    let mut prod = 1i;
+    for int_range(0, 4) |i| {
+        prod *= int::pow(primes[i], i as uint);
+    }
+    assert_eq!(prod, 1*3*5*5*7*7*7);
+
+
+    // empty ranges
+    for int_range(10, 10) |_| {
+        fail!("range should be empty when start == stop");
+    }
+
+    for uint_range(10, 10) |_| {
+        fail!("range should be empty when start == stop");
+    }
+
+
+    // range iterations do not wrap/overflow
+    let mut oflo_loop_visited = ~[];
+    for uint_range_step(uint::max_value-15, uint::max_value, 4) |x| {
+        oflo_loop_visited.push(uint::max_value - x);
+    }
+    assert_eq!(oflo_loop_visited, ~[15, 11, 7, 3]);
+
+    let mut oflo_loop_visited = ~[];
+    for int_range_step(int::max_value-15, int::max_value, 4) |x| {
+        oflo_loop_visited.push(int::max_value - x);
+    }
+    assert_eq!(oflo_loop_visited, ~[15, 11, 7, 3]);
+
+
+    // range_step never passes nor visits the stop element
+    for int_range_step(0, 21, 3) |x| {
+        assert!(x < 21);
+    }
+
+    // range_step_inclusive will never pass stop element, and may skip it.
+    let mut saw21 = false;
+    for uint::range_step_inclusive(0, 21, 4) |x| {
+        assert!(x <= 21);
+        if x == 21 { saw21 = true; }
+    }
+    assert!(!saw21);
+    let mut saw21 = false;
+    for int::range_step_inclusive(0, 21, 4) |x| {
+        assert!(x <= 21);
+        if x == 21 { saw21 = true; }
+    }
+    assert!(!saw21);
+
+    // range_step_inclusive will never pass stop element, but may visit it.
+    let mut saw21 = false;
+    for uint::range_step_inclusive(0, 21, 3) |x| {
+        assert!(x <= 21);
+        println(fmt!("saw: %u", x));
+        if x == 21 { saw21 = true; }
+    }
+    assert!(saw21);
+    let mut saw21 = false;
+    for int::range_step_inclusive(0, 21, 3) |x| {
+        assert!(x <= 21);
+        if x == 21 { saw21 = true; }
+    }
+    assert!(saw21);
+
+}