about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-04-24 06:48:50 -0700
committerbors <bors@rust-lang.org>2013-04-24 06:48:50 -0700
commite26f992d5e199a1ff8c26733650d254d63be066a (patch)
treec1aa3ef0f5e49f777912683ae95144541dd07cd1 /src/libcore
parentc8ac057545f7b2edf1e488aa4562138a6ed7a096 (diff)
parent9860fe10a19cc4997e58861df905f8dbe4de3c5b (diff)
downloadrust-e26f992d5e199a1ff8c26733650d254d63be066a.tar.gz
rust-e26f992d5e199a1ff8c26733650d254d63be066a.zip
auto merge of #6036 : huonw/rust/core-less-at, r=nikomatsakis
From a cursory `git grep` this removes the last part of `core` that requires on `@` (other than `io` and the task local data section).

It renames `RandRes` to ~~StdRng~~ `IsaacRng` and `XorShiftState` to `XorShiftRng` as well as moving their constructors to static methods. To go with this, it adds `rng()` which is designed to be used when the programmer just wants a random number generator, without caring about which exact algorithm is being used.

It also removes all the `gen_int`, `gen_uint`, `gen_char` (etc) methods on `RngUtil` (by moving the defintions to the actual `Rand` instances). The replacement is using `RngUtil::gen`, either type-inferred or with an annotation (`rng.gen::<uint>()`).

I tried to have the `Rng` and `RngUtil` traits exported by `core::prelude` (since `core::rand` (except for `random()`) is useless without them), but this caused [an explosion of (seemingly unrelated) `error: unresolved import`'s](https://gist.github.com/5451839).
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/flate.rs2
-rw-r--r--src/libcore/hashmap.rs2
-rw-r--r--src/libcore/os.rs2
-rw-r--r--src/libcore/rand.rs551
-rw-r--r--src/libcore/run.rs218
-rw-r--r--src/libcore/unstable/at_exit.rs2
6 files changed, 336 insertions, 441 deletions
diff --git a/src/libcore/flate.rs b/src/libcore/flate.rs
index 70c96c9c806..5c4181c10cf 100644
--- a/src/libcore/flate.rs
+++ b/src/libcore/flate.rs
@@ -85,7 +85,7 @@ pub fn inflate_bytes(bytes: &const [u8]) -> ~[u8] {
 #[test]
 #[allow(non_implicitly_copyable_typarams)]
 fn test_flate_round_trip() {
-    let r = rand::Rng();
+    let r = rand::rng();
     let mut words = ~[];
     for 20.times {
         words.push(r.gen_bytes(r.gen_uint_range(1, 10)));
diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs
index 1d7cc8515a6..d2be0416371 100644
--- a/src/libcore/hashmap.rs
+++ b/src/libcore/hashmap.rs
@@ -56,7 +56,7 @@ fn resize_at(capacity: uint) -> uint {
 pub fn linear_map_with_capacity<K:Eq + Hash,V>(
     initial_capacity: uint) -> HashMap<K, V> {
     let r = rand::task_rng();
-    linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(),
+    linear_map_with_capacity_and_keys(r.gen(), r.gen(),
                                       initial_capacity)
 }
 
diff --git a/src/libcore/os.rs b/src/libcore/os.rs
index fa3ca4577c6..1000fd88b52 100644
--- a/src/libcore/os.rs
+++ b/src/libcore/os.rs
@@ -1259,7 +1259,7 @@ mod tests {
     }
 
     fn make_rand_name() -> ~str {
-        let rng: @rand::Rng = rand::Rng();
+        let rng = rand::rng();
         let n = ~"TEST" + rng.gen_str(10u);
         assert!(getenv(n).is_none());
         n
diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs
index 919c7bbb036..cdf6a5bb63d 100644
--- a/src/libcore/rand.rs
+++ b/src/libcore/rand.rs
@@ -8,7 +8,34 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Random number generation
+/*!
+Random number generation.
+
+The key functions are `random()` and `RngUtil::gen()`. These are polymorphic
+and so can be used to generate any type that implements `Rand`. Type inference
+means that often a simple call to `rand::random()` or `rng.gen()` will
+suffice, but sometimes an annotation is required, e.g. `rand::random::<float>()`.
+
+# Examples
+~~~
+use core::rand::RngUtil;
+
+fn main() {
+    let rng = rand::rng();
+    if rng.gen() { // bool
+        println(fmt!("int: %d, uint: %u", rng.gen(), rng.gen()))
+    }
+}
+~~~
+
+~~~
+fn main () {
+    let tuple_ptr = rand::random::<~(f64, char)>();
+    println(fmt!("%?", tuple_ptr))
+}
+~~~
+*/
+
 
 use int;
 use prelude::*;
@@ -20,98 +47,111 @@ use util;
 use vec;
 use libc::size_t;
 
-/// A type that can be randomly generated using an RNG
+/// A type that can be randomly generated using an Rng
 pub trait Rand {
-    fn rand(rng: @rand::Rng) -> Self;
+    fn rand<R: Rng>(rng: &R) -> Self;
 }
 
 impl Rand for int {
-    fn rand(rng: @rand::Rng) -> int {
-        rng.gen_int()
+    fn rand<R: Rng>(rng: &R) -> int {
+        if int::bits == 32 {
+            rng.next() as int
+        } else {
+            rng.gen::<i64>() as int
+        }
     }
 }
 
 impl Rand for i8 {
-    fn rand(rng: @rand::Rng) -> i8 {
-        rng.gen_i8()
+    fn rand<R: Rng>(rng: &R) -> i8 {
+        rng.next() as i8
     }
 }
 
 impl Rand for i16 {
-    fn rand(rng: @rand::Rng) -> i16 {
-        rng.gen_i16()
+    fn rand<R: Rng>(rng: &R) -> i16 {
+        rng.next() as i16
     }
 }
 
 impl Rand for i32 {
-    fn rand(rng: @rand::Rng) -> i32 {
-        rng.gen_i32()
+    fn rand<R: Rng>(rng: &R) -> i32 {
+        rng.next() as i32
     }
 }
 
 impl Rand for i64 {
-    fn rand(rng: @rand::Rng) -> i64 {
-        rng.gen_i64()
+    fn rand<R: Rng>(rng: &R) -> i64 {
+        (rng.next() as i64 << 32) | rng.next() as i64
     }
 }
 
 impl Rand for uint {
-    fn rand(rng: @rand::Rng) -> uint {
-        rng.gen_uint()
+    fn rand<R: Rng>(rng: &R) -> uint {
+        if uint::bits == 32 {
+            rng.next() as uint
+        } else {
+            rng.gen::<u64>() as uint
+        }
     }
 }
 
 impl Rand for u8 {
-    fn rand(rng: @rand::Rng) -> u8 {
-        rng.gen_u8()
+    fn rand<R: Rng>(rng: &R) -> u8 {
+        rng.next() as u8
     }
 }
 
 impl Rand for u16 {
-    fn rand(rng: @rand::Rng) -> u16 {
-        rng.gen_u16()
+    fn rand<R: Rng>(rng: &R) -> u16 {
+        rng.next() as u16
     }
 }
 
 impl Rand for u32 {
-    fn rand(rng: @rand::Rng) -> u32 {
-        rng.gen_u32()
+    fn rand<R: Rng>(rng: &R) -> u32 {
+        rng.next()
     }
 }
 
 impl Rand for u64 {
-    fn rand(rng: @rand::Rng) -> u64 {
-        rng.gen_u64()
+    fn rand<R: Rng>(rng: &R) -> u64 {
+        (rng.next() as u64 << 32) | rng.next() as u64
     }
 }
 
 impl Rand for float {
-    fn rand(rng: @rand::Rng) -> float {
-        rng.gen_float()
+    fn rand<R: Rng>(rng: &R) -> float {
+        rng.gen::<f64>() as float
     }
 }
 
 impl Rand for f32 {
-    fn rand(rng: @rand::Rng) -> f32 {
-        rng.gen_f32()
+    fn rand<R: Rng>(rng: &R) -> f32 {
+        rng.gen::<f64>() as f32
     }
 }
 
+static scale : f64 = (u32::max_value as f64) + 1.0f64;
 impl Rand for f64 {
-    fn rand(rng: @rand::Rng) -> f64 {
-        rng.gen_f64()
+    fn rand<R: Rng>(rng: &R) -> f64 {
+        let u1 = rng.next() as f64;
+        let u2 = rng.next() as f64;
+        let u3 = rng.next() as f64;
+
+        ((u1 / scale + u2) / scale + u3) / scale
     }
 }
 
 impl Rand for char {
-    fn rand(rng: @rand::Rng) -> char {
-        rng.gen_char()
+    fn rand<R: Rng>(rng: &R) -> char {
+        rng.next() as char
     }
 }
 
 impl Rand for bool {
-    fn rand(rng: @rand::Rng) -> bool {
-        rng.gen_bool()
+    fn rand<R: Rng>(rng: &R) -> bool {
+        rng.next() & 1u32 == 1u32
     }
 }
 
@@ -123,10 +163,10 @@ macro_rules! tuple_impl {
             $( $tyvar : Rand ),*
             > Rand for ( $( $tyvar ),* , ) {
 
-            fn rand (_rng: @Rng) -> ( $( $tyvar ),* , ) {
+            fn rand<R: Rng>(_rng: &R) -> ( $( $tyvar ),* , ) {
                 (
-                    // use the $var's to get the appropriate number of repeats
-                    // (they're not actually needed)
+                    // use the $tyvar's to get the appropriate number of
+                    // repeats (they're not actually needed)
                     $(
                         _rng.gen::<$tyvar>()
                     ),*
@@ -137,7 +177,7 @@ macro_rules! tuple_impl {
     }
 }
 
-impl Rand for () { fn rand(_: @Rng) -> () { () } }
+impl Rand for () { fn rand<R: Rng>(_: &R) -> () { () } }
 tuple_impl!{A}
 tuple_impl!{A, B}
 tuple_impl!{A, B, C}
@@ -150,9 +190,9 @@ tuple_impl!{A, B, C, D, E, F, G, H, I}
 tuple_impl!{A, B, C, D, E, F, G, H, I, J}
 
 impl<T:Rand> Rand for Option<T> {
-    fn rand(rng: @rand::Rng) -> Option<T> {
-        if rng.gen_bool() {
-            Some(Rand::rand(rng))
+    fn rand<R: Rng>(rng: &R) -> Option<T> {
+        if rng.gen() {
+            Some(rng.gen())
         } else {
             None
         }
@@ -160,11 +200,11 @@ impl<T:Rand> Rand for Option<T> {
 }
 
 impl<T: Rand> Rand for ~T {
-    fn rand(rng: @Rng) -> ~T { ~rng.gen() }
+    fn rand<R: Rng>(rng: &R) -> ~T { ~rng.gen() }
 }
 
 impl<T: Rand> Rand for @T {
-    fn rand(rng: @Rng) -> @T { @rng.gen() }
+    fn rand<R: Rng>(rng: &R) -> @T { @rng.gen() }
 }
 
 #[allow(non_camel_case_types)] // runtime type
@@ -173,7 +213,7 @@ pub enum rust_rng {}
 #[abi = "cdecl"]
 pub mod rustrt {
     use libc::size_t;
-    use rand::rust_rng;
+    use super::rust_rng;
 
     pub extern {
         unsafe fn rand_seed_size() -> size_t;
@@ -187,7 +227,7 @@ pub mod rustrt {
 /// A random number generator
 pub trait Rng {
     /// Return the next random integer
-    fn next(&self) -> u32;
+    pub fn next(&self) -> u32;
 }
 
 /// A value with a particular weight compared to other values
@@ -197,91 +237,23 @@ pub struct Weighted<T> {
 }
 
 pub trait RngUtil {
-    /// Return a random value for a Rand type
+    /// Return a random value of a Rand type
     fn gen<T:Rand>(&self) -> T;
     /**
-     * Return a random int
-     *
-     * *Example*
-     *
-     * ~~~
-     *
-     * use core::rand::RngUtil;
-     *
-     * fn main() {
-     *     rng = rand::Rng();
-     *     println(fmt!("%d",rng.gen_int()));
-     * }
-     * ~~~
+     * Return a int randomly chosen from the range [start, end),
+     * failing if start >= end
      */
-    fn gen_int(&self) -> int;
     fn gen_int_range(&self, start: int, end: int) -> int;
-    /// Return a random i8
-    fn gen_i8(&self) -> i8;
-    /// Return a random i16
-    fn gen_i16(&self) -> i16;
-    /// Return a random i32
-    fn gen_i32(&self) -> i32;
-    /// Return a random i64
-    fn gen_i64(&self) -> i64;
-    /// Return a random uint
-    fn gen_uint(&self) -> uint;
     /**
      * Return a uint randomly chosen from the range [start, end),
      * failing if start >= end
      */
     fn gen_uint_range(&self, start: uint, end: uint) -> uint;
-    /// Return a random u8
-    fn gen_u8(&self) -> u8;
-    /// Return a random u16
-    fn gen_u16(&self) -> u16;
-    /// Return a random u32
-    fn gen_u32(&self) -> u32;
-    /// Return a random u64
-    fn gen_u64(&self) -> u64;
-    /**
-     * Return random float in the interval [0,1]
-     *
-     * *Example*
-     *
-     * ~~~
-     *
-     * use core::rand::RngUtil;
-     *
-     * fn main() {
-     *     rng = rand::Rng();
-     *     println(fmt!("%f",rng.gen_float()));
-     * }
-     * ~~~
-     */
-    fn gen_float(&self) -> float;
-    /// Return a random f32 in the interval [0,1]
-    fn gen_f32(&self) -> f32;
-    /// Return a random f64 in the interval [0,1]
-    fn gen_f64(&self) -> f64;
-    /// Return a random char
-    fn gen_char(&self) -> char;
     /**
      * Return a char randomly chosen from chars, failing if chars is empty
      */
     fn gen_char_from(&self, chars: &str) -> char;
     /**
-     * Return a random bool
-     *
-     * *Example*
-     *
-     * ~~~
-     *
-     * use core::rand::RngUtil;
-     *
-     * fn main() {
-     *     rng = rand::Rng();
-     *     println(fmt!("%b",rng.gen_bool()));
-     * }
-     * ~~~
-     */
-    fn gen_bool(&self) -> bool;
-    /**
      * Return a bool with a 1 in n chance of true
      *
      * *Example*
@@ -291,7 +263,7 @@ pub trait RngUtil {
      * use core::rand::RngUtil;
      *
      * fn main() {
-     *     rng = rand::Rng();
+     *     rng = rand::rng();
      *     println(fmt!("%b",rng.gen_weighted_bool(3)));
      * }
      * ~~~
@@ -307,7 +279,7 @@ pub trait RngUtil {
      * use core::rand::RngUtil;
      *
      * fn main() {
-     *     rng = rand::Rng();
+     *     rng = rand::rng();
      *     println(rng.gen_str(8));
      * }
      * ~~~
@@ -323,13 +295,12 @@ pub trait RngUtil {
      * use core::rand::RngUtil;
      *
      * fn main() {
-     *     rng = rand::Rng();
+     *     rng = rand::rng();
      *     println(fmt!("%?",rng.gen_bytes(8)));
      * }
      * ~~~
      */
     fn gen_bytes(&self, len: uint) -> ~[u8];
-    ///
     /**
      * Choose an item randomly, failing if values is empty
      *
@@ -340,7 +311,7 @@ pub trait RngUtil {
      * use core::rand::RngUtil;
      *
      * fn main() {
-     *     rng = rand::Rng();
+     *     rng = rand::rng();
      *     println(fmt!("%d",rng.choose([1,2,4,8,16,32])));
      * }
      * ~~~
@@ -359,7 +330,7 @@ pub trait RngUtil {
      * use core::rand::RngUtil;
      *
      * fn main() {
-     *     rng = rand::Rng();
+     *     rng = rand::rng();
      *     let x = [rand::Weighted {weight: 4, item: 'a'},
      *              rand::Weighted {weight: 2, item: 'b'},
      *              rand::Weighted {weight: 2, item: 'c'}];
@@ -379,7 +350,7 @@ pub trait RngUtil {
      * use core::rand::RngUtil;
      *
      * fn main() {
-     *     rng = rand::Rng();
+     *     rng = rand::rng();
      *     let x = [rand::Weighted {weight: 4, item: 'a'},
      *              rand::Weighted {weight: 2, item: 'b'},
      *              rand::Weighted {weight: 2, item: 'c'}];
@@ -399,7 +370,7 @@ pub trait RngUtil {
      * use core::rand::RngUtil;
      *
      * fn main() {
-     *     rng = rand::Rng();
+     *     rng = rand::rng();
      *     let x = [rand::Weighted {weight: 4, item: 'a'},
      *              rand::Weighted {weight: 2, item: 'b'},
      *              rand::Weighted {weight: 2, item: 'c'}];
@@ -418,7 +389,7 @@ pub trait RngUtil {
      * use core::rand::RngUtil;
      *
      * fn main() {
-     *     rng = rand::Rng();
+     *     rng = rand::rng();
      *     println(fmt!("%?",rng.shuffle([1,2,3])));
      * }
      * ~~~
@@ -434,7 +405,7 @@ pub trait RngUtil {
      * use core::rand::RngUtil;
      *
      * fn main() {
-     *     rng = rand::Rng();
+     *     rng = rand::rng();
      *     let mut y = [1,2,3];
      *     rng.shuffle_mut(y);
      *     println(fmt!("%?",y));
@@ -447,15 +418,10 @@ pub trait RngUtil {
 }
 
 /// Extension methods for random number generators
-impl RngUtil for @Rng {
+impl<R: Rng> RngUtil for R {
     /// Return a random value for a Rand type
-    fn gen<T:Rand>(&self) -> T {
-        Rand::rand(*self)
-    }
-
-    /// Return a random int
-    fn gen_int(&self) -> int {
-        self.gen_i64() as int
+    fn gen<T: Rand>(&self) -> T {
+        Rand::rand(self)
     }
 
     /**
@@ -464,32 +430,7 @@ impl RngUtil for @Rng {
      */
     fn gen_int_range(&self, start: int, end: int) -> int {
         assert!(start < end);
-        start + int::abs(self.gen_int() % (end - start))
-    }
-
-    /// Return a random i8
-    fn gen_i8(&self) -> i8 {
-        self.next() as i8
-    }
-
-    /// Return a random i16
-    fn gen_i16(&self) -> i16 {
-        self.next() as i16
-    }
-
-    /// Return a random i32
-    fn gen_i32(&self) -> i32 {
-        self.next() as i32
-    }
-
-    /// Return a random i64
-    fn gen_i64(&self) -> i64 {
-        (self.next() as i64 << 32) | self.next() as i64
-    }
-
-    /// Return a random uint
-    fn gen_uint(&self) -> uint {
-        self.gen_u64() as uint
+        start + int::abs(self.gen::<int>() % (end - start))
     }
 
     /**
@@ -498,51 +439,7 @@ impl RngUtil for @Rng {
      */
     fn gen_uint_range(&self, start: uint, end: uint) -> uint {
         assert!(start < end);
-        start + (self.gen_uint() % (end - start))
-    }
-
-    /// Return a random u8
-    fn gen_u8(&self) -> u8 {
-        self.next() as u8
-    }
-
-    /// Return a random u16
-    fn gen_u16(&self) -> u16 {
-        self.next() as u16
-    }
-
-    /// Return a random u32
-    fn gen_u32(&self) -> u32 {
-        self.next()
-    }
-
-    /// Return a random u64
-    fn gen_u64(&self) -> u64 {
-        (self.next() as u64 << 32) | self.next() as u64
-    }
-
-    /// Return a random float in the interval [0,1]
-    fn gen_float(&self) -> float {
-        self.gen_f64() as float
-    }
-
-    /// Return a random f32 in the interval [0,1]
-    fn gen_f32(&self) -> f32 {
-        self.gen_f64() as f32
-    }
-
-    /// Return a random f64 in the interval [0,1]
-    fn gen_f64(&self) -> f64 {
-        let u1 = self.next() as f64;
-        let u2 = self.next() as f64;
-        let u3 = self.next() as f64;
-        static scale : f64 = (u32::max_value as f64) + 1.0f64;
-        return ((u1 / scale + u2) / scale + u3) / scale;
-    }
-
-    /// Return a random char
-    fn gen_char(&self) -> char {
-        self.next() as char
+        start + (self.gen::<uint>() % (end - start))
     }
 
     /**
@@ -555,11 +452,6 @@ impl RngUtil for @Rng {
         self.choose(cs)
     }
 
-    /// Return a random bool
-    fn gen_bool(&self) -> bool {
-        self.next() & 1u32 == 1u32
-    }
-
     /// Return a bool with a 1-in-n chance of true
     fn gen_weighted_bool(&self, n: uint) -> bool {
         if n == 0u {
@@ -588,7 +480,7 @@ impl RngUtil for @Rng {
     /// Return a random byte string of the specified length
     fn gen_bytes(&self, len: uint) -> ~[u8] {
         do vec::from_fn(len) |_i| {
-            self.gen_u8()
+            self.gen()
         }
     }
 
@@ -605,7 +497,6 @@ impl RngUtil for @Rng {
             Some(values[self.gen_uint_range(0u, values.len())])
         }
     }
-
     /**
      * Choose an item respecting the relative weights, failing if the sum of
      * the weights is 0
@@ -668,14 +559,18 @@ impl RngUtil for @Rng {
             vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
         }
     }
+}
 
+/// Create a random number generator with a default algorithm and seed.
+pub fn rng() -> IsaacRng {
+    IsaacRng::new()
 }
 
-struct RandRes {
-    rng: *rust_rng,
+pub struct IsaacRng {
+    priv rng: *rust_rng,
 }
 
-impl Drop for RandRes {
+impl Drop for IsaacRng {
     fn finalize(&self) {
         unsafe {
             rustrt::rand_free(self.rng);
@@ -683,21 +578,42 @@ impl Drop for RandRes {
     }
 }
 
-fn RandRes(rng: *rust_rng) -> RandRes {
-    RandRes {
-        rng: rng
+pub impl IsaacRng {
+    priv fn from_rust_rng(rng: *rust_rng) -> IsaacRng {
+        IsaacRng {
+            rng: rng
+        }
+    }
+
+    /// Create an ISAAC random number generator with a system specified seed
+    fn new() -> IsaacRng {
+        IsaacRng::new_seeded(seed())
+    }
+
+    /**
+     * Create a random number generator using the specified seed. A generator
+     * constructed with a given seed will generate the same sequence of values as
+     * all other generators constructed with the same seed. The seed may be any
+     * length.
+     */
+    fn new_seeded(seed: &[u8]) -> IsaacRng {
+        unsafe {
+            do vec::as_imm_buf(seed) |p, sz| {
+                IsaacRng::from_rust_rng(rustrt::rand_new_seeded(p, sz as size_t))
+            }
+        }
     }
 }
 
-impl Rng for @RandRes {
-    fn next(&self) -> u32 {
+impl Rng for IsaacRng {
+    pub fn next(&self) -> u32 {
         unsafe {
-            return rustrt::rand_next((*self).rng);
+            return rustrt::rand_next(self.rng);
         }
     }
 }
 
-/// Create a new random seed for seeded_rng
+/// Create a new random seed for IsaacRng::new_seeded
 pub fn seed() -> ~[u8] {
     unsafe {
         let n = rustrt::rand_seed_size() as uint;
@@ -709,38 +625,15 @@ pub fn seed() -> ~[u8] {
     }
 }
 
-/// Create a random number generator with a system specified seed
-pub fn Rng() -> @Rng {
-    seeded_rng(seed())
-}
-
-/**
- * Create a random number generator using the specified seed. A generator
- * constructed with a given seed will generate the same sequence of values as
- * all other generators constructed with the same seed. The seed may be any
- * length.
- */
-pub fn seeded_rng(seed: &[u8]) -> @Rng {
-    @seeded_randres(seed) as @Rng
-}
-
-fn seeded_randres(seed: &[u8]) -> @RandRes {
-    unsafe {
-        do vec::as_imm_buf(seed) |p, sz| {
-            @RandRes(rustrt::rand_new_seeded(p, sz as size_t))
-        }
-    }
-}
-
-struct XorShiftState {
-    mut x: u32,
-    mut y: u32,
-    mut z: u32,
-    mut w: u32,
+struct XorShiftRng {
+    priv mut x: u32,
+    priv mut y: u32,
+    priv mut z: u32,
+    priv mut w: u32,
 }
 
-impl Rng for XorShiftState {
-    fn next(&self) -> u32 {
+impl Rng for XorShiftRng {
+    pub fn next(&self) -> u32 {
         let x = self.x;
         let t = x ^ (x << 11);
         self.x = self.y;
@@ -752,41 +645,54 @@ impl Rng for XorShiftState {
     }
 }
 
-pub fn xorshift() -> @Rng {
-    // constants taken from http://en.wikipedia.org/wiki/Xorshift
-    seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
-}
+pub impl XorShiftRng {
+    /// Create an xor shift random number generator with a default seed.
+    fn new() -> XorShiftRng {
+        // constants taken from http://en.wikipedia.org/wiki/Xorshift
+        XorShiftRng::new_seeded(123456789u32, 362436069u32, 521288629u32, 88675123u32)
+    }
 
-pub fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> @Rng {
-    @XorShiftState { x: x, y: y, z: z, w: w } as @Rng
-}
+    /**
+     * Create a random number generator using the specified seed. A generator
+     * constructed with a given seed will generate the same sequence of values as
+     * all other generators constructed with the same seed.
+     */
+    fn new_seeded(x: u32, y: u32, z: u32, w: u32) -> XorShiftRng {
+        XorShiftRng { x: x, y: y, z: z, w: w }
+    }
 
+}
 
 // used to make space in TLS for a random number generator
-fn tls_rng_state(_v: @RandRes) {}
+fn tls_rng_state(_v: @IsaacRng) {}
 
 /**
  * Gives back a lazily initialized task-local random number generator,
  * seeded by the system. Intended to be used in method chaining style, ie
- * task_rng().gen_int().
+ * `task_rng().gen::<int>()`.
  */
-pub fn task_rng() -> @Rng {
-    let r : Option<@RandRes>;
+pub fn task_rng() -> @IsaacRng {
+    let r : Option<@IsaacRng>;
     unsafe {
         r = task::local_data::local_data_get(tls_rng_state);
     }
     match r {
         None => {
             unsafe {
-                let rng = seeded_randres(seed());
+                let rng = @IsaacRng::new_seeded(seed());
                 task::local_data::local_data_set(tls_rng_state, rng);
-                @rng as @Rng
+                rng
             }
         }
-        Some(rng) => @rng as @Rng
+        Some(rng) => rng
     }
 }
 
+// Allow direct chaining with `task_rng`
+impl<R: Rng> Rng for @R {
+    fn next(&self) -> u32 { (*self).next() }
+}
+
 /**
  * Returns a random value of a Rand type, using the task's random number
  * generator.
@@ -795,33 +701,32 @@ pub fn random<T: Rand>() -> T {
     task_rng().gen()
 }
 
-
 #[cfg(test)]
 mod tests {
     use option::{Option, Some};
-    use rand;
+    use super::*;
 
     #[test]
-    fn rng_seeded() {
-        let seed = rand::seed();
-        let ra = rand::seeded_rng(seed);
-        let rb = rand::seeded_rng(seed);
+    fn test_rng_seeded() {
+        let seed = seed();
+        let ra = IsaacRng::new_seeded(seed);
+        let rb = IsaacRng::new_seeded(seed);
         assert!(ra.gen_str(100u) == rb.gen_str(100u));
     }
 
     #[test]
-    fn rng_seeded_custom_seed() {
+    fn test_rng_seeded_custom_seed() {
         // much shorter than generated seeds which are 1024 bytes
         let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
-        let ra = rand::seeded_rng(seed);
-        let rb = rand::seeded_rng(seed);
+        let ra = IsaacRng::new_seeded(seed);
+        let rb = IsaacRng::new_seeded(seed);
         assert!(ra.gen_str(100u) == rb.gen_str(100u));
     }
 
     #[test]
-    fn rng_seeded_custom_seed2() {
+    fn test_rng_seeded_custom_seed2() {
         let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
-        let ra = rand::seeded_rng(seed);
+        let ra = IsaacRng::new_seeded(seed);
         // Regression test that isaac is actually using the above vector
         let r = ra.next();
         error!("%?", r);
@@ -830,8 +735,8 @@ mod tests {
     }
 
     #[test]
-    fn gen_int_range() {
-        let r = rand::Rng();
+    fn test_gen_int_range() {
+        let r = rng();
         let a = r.gen_int_range(-3, 42);
         assert!(a >= -3 && a < 42);
         assert!(r.gen_int_range(0, 1) == 0);
@@ -841,13 +746,13 @@ mod tests {
     #[test]
     #[should_fail]
     #[ignore(cfg(windows))]
-    fn gen_int_from_fail() {
-        rand::Rng().gen_int_range(5, -2);
+    fn test_gen_int_from_fail() {
+        rng().gen_int_range(5, -2);
     }
 
     #[test]
-    fn gen_uint_range() {
-        let r = rand::Rng();
+    fn test_gen_uint_range() {
+        let r = rng();
         let a = r.gen_uint_range(3u, 42u);
         assert!(a >= 3u && a < 42u);
         assert!(r.gen_uint_range(0u, 1u) == 0u);
@@ -857,28 +762,28 @@ mod tests {
     #[test]
     #[should_fail]
     #[ignore(cfg(windows))]
-    fn gen_uint_range_fail() {
-        rand::Rng().gen_uint_range(5u, 2u);
+    fn test_gen_uint_range_fail() {
+        rng().gen_uint_range(5u, 2u);
     }
 
     #[test]
-    fn gen_float() {
-        let r = rand::Rng();
-        let a = r.gen_float();
-        let b = r.gen_float();
+    fn test_gen_float() {
+        let r = rng();
+        let a = r.gen::<float>();
+        let b = r.gen::<float>();
         debug!((a, b));
     }
 
     #[test]
-    fn gen_weighted_bool() {
-        let r = rand::Rng();
+    fn test_gen_weighted_bool() {
+        let r = rng();
         assert!(r.gen_weighted_bool(0u) == true);
         assert!(r.gen_weighted_bool(1u) == true);
     }
 
     #[test]
-    fn gen_str() {
-        let r = rand::Rng();
+    fn test_gen_str() {
+        let r = rng();
         debug!(r.gen_str(10u));
         debug!(r.gen_str(10u));
         debug!(r.gen_str(10u));
@@ -888,91 +793,91 @@ mod tests {
     }
 
     #[test]
-    fn gen_bytes() {
-        let r = rand::Rng();
+    fn test_gen_bytes() {
+        let r = rng();
         assert!(r.gen_bytes(0u).len() == 0u);
         assert!(r.gen_bytes(10u).len() == 10u);
         assert!(r.gen_bytes(16u).len() == 16u);
     }
 
     #[test]
-    fn choose() {
-        let r = rand::Rng();
+    fn test_choose() {
+        let r = rng();
         assert!(r.choose([1, 1, 1]) == 1);
     }
 
     #[test]
-    fn choose_option() {
-        let r = rand::Rng();
+    fn test_choose_option() {
+        let r = rng();
         let x: Option<int> = r.choose_option([]);
         assert!(x.is_none());
         assert!(r.choose_option([1, 1, 1]) == Some(1));
     }
 
     #[test]
-    fn choose_weighted() {
-        let r = rand::Rng();
+    fn test_choose_weighted() {
+        let r = rng();
         assert!(r.choose_weighted(~[
-            rand::Weighted { weight: 1u, item: 42 },
+            Weighted { weight: 1u, item: 42 },
         ]) == 42);
         assert!(r.choose_weighted(~[
-            rand::Weighted { weight: 0u, item: 42 },
-            rand::Weighted { weight: 1u, item: 43 },
+            Weighted { weight: 0u, item: 42 },
+            Weighted { weight: 1u, item: 43 },
         ]) == 43);
     }
 
     #[test]
-    fn choose_weighted_option() {
-        let r = rand::Rng();
+    fn test_choose_weighted_option() {
+        let r = rng();
         assert!(r.choose_weighted_option(~[
-            rand::Weighted { weight: 1u, item: 42 },
+            Weighted { weight: 1u, item: 42 },
         ]) == Some(42));
         assert!(r.choose_weighted_option(~[
-            rand::Weighted { weight: 0u, item: 42 },
-            rand::Weighted { weight: 1u, item: 43 },
+            Weighted { weight: 0u, item: 42 },
+            Weighted { weight: 1u, item: 43 },
         ]) == Some(43));
         let v: Option<int> = r.choose_weighted_option([]);
         assert!(v.is_none());
     }
 
     #[test]
-    fn weighted_vec() {
-        let r = rand::Rng();
+    fn test_weighted_vec() {
+        let r = rng();
         let empty: ~[int] = ~[];
         assert!(r.weighted_vec(~[]) == empty);
         assert!(r.weighted_vec(~[
-            rand::Weighted { weight: 0u, item: 3u },
-            rand::Weighted { weight: 1u, item: 2u },
-            rand::Weighted { weight: 2u, item: 1u },
+            Weighted { weight: 0u, item: 3u },
+            Weighted { weight: 1u, item: 2u },
+            Weighted { weight: 2u, item: 1u },
         ]) == ~[2u, 1u, 1u]);
     }
 
     #[test]
-    fn shuffle() {
-        let r = rand::Rng();
+    fn test_shuffle() {
+        let r = rng();
         let empty: ~[int] = ~[];
         assert!(r.shuffle(~[]) == empty);
         assert!(r.shuffle(~[1, 1, 1]) == ~[1, 1, 1]);
     }
 
     #[test]
-    fn task_rng() {
-        let r = rand::task_rng();
-        r.gen_int();
+    fn test_task_rng() {
+        let r = task_rng();
+        r.gen::<int>();
         assert!(r.shuffle(~[1, 1, 1]) == ~[1, 1, 1]);
         assert!(r.gen_uint_range(0u, 1u) == 0u);
     }
 
     #[test]
-    fn random() {
+    fn test_random() {
         // not sure how to test this aside from just getting some values
-        let _n : uint = rand::random();
-        let _f : f32 = rand::random();
-        let _o : Option<Option<i8>> = rand::random();
+        let _n : uint = random();
+        let _f : f32 = random();
+        let _o : Option<Option<i8>> = random();
         let _many : ((),
                      (~uint, @int, ~Option<~(@char, ~(@bool,))>),
                      (u8, i8, u16, i16, u32, i32, u64, i64),
-                     (f32, (f64, (float,)))) = rand::random();
+                     (f32, (f64, (float,)))) = random();
     }
 }
 
diff --git a/src/libcore/run.rs b/src/libcore/run.rs
index 2455954ebe1..e7df95e20c8 100644
--- a/src/libcore/run.rs
+++ b/src/libcore/run.rs
@@ -47,28 +47,117 @@ pub struct RunProgramResult {
     handle: *(),
 }
 
+struct ProgRepr {
+    pid: pid_t,
+    handle: *(),
+    in_fd: c_int,
+    out_file: *libc::FILE,
+    err_file: *libc::FILE,
+    finished: bool,
+}
+
+impl ProgRepr {
+    fn close_input(&mut self) {
+        let invalid_fd = -1i32;
+        if self.in_fd != invalid_fd {
+            unsafe {
+                libc::close(self.in_fd);
+            }
+            self.in_fd = invalid_fd;
+        }
+    }
+
+    fn close_outputs(&mut self) {
+        unsafe {
+            fclose_and_null(&mut self.out_file);
+            fclose_and_null(&mut self.err_file);
+        }
+    }
+
+    fn finish(&mut self) -> int {
+        if self.finished { return 0; }
+        self.finished = true;
+        self.close_input();
+        return waitpid(self.pid);
+    }
+
+    fn destroy(&mut self, force: bool) {
+        killpid(self.pid, force);
+        self.finish();
+        self.close_outputs();
+
+        #[cfg(windows)]
+        fn killpid(pid: pid_t, _force: bool) {
+            unsafe {
+                libc::funcs::extra::kernel32::TerminateProcess(
+                    cast::transmute(pid), 1);
+            }
+        }
+
+        #[cfg(unix)]
+        fn killpid(pid: pid_t, force: bool) {
+            let signal = if force {
+                libc::consts::os::posix88::SIGKILL
+            } else {
+                libc::consts::os::posix88::SIGTERM
+            };
+
+            unsafe {
+                libc::funcs::posix88::signal::kill(pid, signal as c_int);
+            }
+        }
+    }
+}
+
 /// A value representing a child process
-pub trait Program {
+pub struct Program {
+    priv r: ProgRepr,
+}
+
+impl Drop for Program {
+    fn finalize(&self) {
+        // FIXME #4943: transmute is bad.
+        let selfr: &mut ProgRepr = unsafe { cast::transmute(&self.r) };
+
+        selfr.finish();
+        selfr.close_outputs();
+        free_handle(self.r.handle);
+    }
+}
+
+pub impl Program {
+    priv fn new(r: ProgRepr) -> Program {
+        Program {
+            r: r
+        }
+    }
+
     /// Returns the process id of the program
-    fn get_id(&mut self) -> pid_t;
+    fn get_id(&mut self) -> pid_t { self.r.pid }
 
     /// Returns an io::Writer that can be used to write to stdin
-    fn input(&mut self) -> @io::Writer;
+    fn input(&mut self) -> @io::Writer {
+        io::fd_writer(self.r.in_fd, false)
+    }
 
     /// Returns an io::Reader that can be used to read from stdout
-    fn output(&mut self) -> @io::Reader;
+    fn output(&mut self) -> @io::Reader {
+        io::FILE_reader(self.r.out_file, false)
+    }
 
     /// Returns an io::Reader that can be used to read from stderr
-    fn err(&mut self) -> @io::Reader;
+    fn err(&mut self) -> @io::Reader {
+        io::FILE_reader(self.r.err_file, false)
+    }
 
     /// Closes the handle to the child processes standard input
-    fn close_input(&mut self);
+    fn close_input(&mut self) { self.r.close_input(); }
 
     /**
      * Waits for the child process to terminate. Closes the handle
      * to stdin if necessary.
      */
-    fn finish(&mut self) -> int;
+    fn finish(&mut self) -> int { self.r.finish() }
 
     /**
      * Terminate the program, giving it a chance to clean itself up if
@@ -77,7 +166,7 @@ pub trait Program {
      * On Posix OSs SIGTERM will be sent to the process. On Win32
      * TerminateProcess(..) will be called.
      */
-    fn destroy(&mut self);
+    fn destroy(&mut self) { self.r.destroy(false); }
 
     /**
      * Terminate the program as soon as possible without giving it a
@@ -86,7 +175,7 @@ pub trait Program {
      * On Posix OSs SIGKILL will be sent to the process. On Win32
      * TerminateProcess(..) will be called.
      */
-    fn force_destroy(&mut self);
+    fn force_destroy(&mut self) { self.r.destroy(true); }
 }
 
 
@@ -248,9 +337,9 @@ pub fn run_program(prog: &str, args: &[~str]) -> int {
 /**
  * Spawns a process and returns a Program
  *
- * The returned value is a boxed class containing a <Program> object that can
- * be used for sending and receiving data over the standard file descriptors.
- * The class will ensure that file descriptors are closed properly.
+ * The returned value is a <Program> object that can be used for sending and
+ * receiving data over the standard file descriptors.  The class will ensure
+ * that file descriptors are closed properly.
  *
  * # Arguments
  *
@@ -259,9 +348,9 @@ pub fn run_program(prog: &str, args: &[~str]) -> int {
  *
  * # Return value
  *
- * A class with a <program> field
+ * A <Program> object
  */
-pub fn start_program(prog: &str, args: &[~str]) -> @Program {
+pub fn start_program(prog: &str, args: &[~str]) -> Program {
     let pipe_input = os::pipe();
     let pipe_output = os::pipe();
     let pipe_err = os::pipe();
@@ -277,105 +366,6 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
         libc::close(pipe_err.out);
     }
 
-    struct ProgRepr {
-        pid: pid_t,
-        handle: *(),
-        in_fd: c_int,
-        out_file: *libc::FILE,
-        err_file: *libc::FILE,
-        finished: bool,
-    }
-
-    fn close_repr_input(r: &mut ProgRepr) {
-        let invalid_fd = -1i32;
-        if r.in_fd != invalid_fd {
-            unsafe {
-                libc::close(r.in_fd);
-            }
-            r.in_fd = invalid_fd;
-        }
-    }
-
-    fn close_repr_outputs(r: &mut ProgRepr) {
-        unsafe {
-            fclose_and_null(&mut r.out_file);
-            fclose_and_null(&mut r.err_file);
-        }
-    }
-
-    fn finish_repr(r: &mut ProgRepr) -> int {
-        if r.finished { return 0; }
-        r.finished = true;
-        close_repr_input(&mut *r);
-        return waitpid(r.pid);
-    }
-
-    fn destroy_repr(r: &mut ProgRepr, force: bool) {
-        killpid(r.pid, force);
-        finish_repr(&mut *r);
-        close_repr_outputs(&mut *r);
-
-        #[cfg(windows)]
-        fn killpid(pid: pid_t, _force: bool) {
-            unsafe {
-                libc::funcs::extra::kernel32::TerminateProcess(
-                    cast::transmute(pid), 1);
-            }
-        }
-
-        #[cfg(unix)]
-        fn killpid(pid: pid_t, force: bool) {
-
-            let signal = if force {
-                libc::consts::os::posix88::SIGKILL
-            } else {
-                libc::consts::os::posix88::SIGTERM
-            };
-
-            unsafe {
-                libc::funcs::posix88::signal::kill(pid, signal as c_int);
-            }
-        }
-    }
-
-    struct ProgRes {
-        r: ProgRepr,
-    }
-
-    impl Drop for ProgRes {
-        fn finalize(&self) {
-            unsafe {
-                // FIXME #4943: transmute is bad.
-                finish_repr(cast::transmute(&self.r));
-                close_repr_outputs(cast::transmute(&self.r));
-            }
-            free_handle(self.r.handle);
-        }
-    }
-
-    fn ProgRes(r: ProgRepr) -> ProgRes {
-        ProgRes {
-            r: r
-        }
-    }
-
-    impl Program for ProgRes {
-        fn get_id(&mut self) -> pid_t { return self.r.pid; }
-        fn input(&mut self) -> @io::Writer {
-            io::fd_writer(self.r.in_fd, false)
-        }
-        fn output(&mut self) -> @io::Reader {
-            io::FILE_reader(self.r.out_file, false)
-        }
-        fn err(&mut self) -> @io::Reader {
-            io::FILE_reader(self.r.err_file, false)
-        }
-        fn close_input(&mut self) { close_repr_input(&mut self.r); }
-        fn finish(&mut self) -> int { finish_repr(&mut self.r) }
-        fn destroy(&mut self) { destroy_repr(&mut self.r, false); }
-        fn force_destroy(&mut self) { destroy_repr(&mut self.r, true); }
-    }
-
     let repr = ProgRepr {
         pid: res.pid,
         handle: res.handle,
@@ -385,7 +375,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
         finished: false,
     };
 
-    @ProgRes(repr) as @Program
+    Program::new(repr)
 }
 
 fn read_all(rd: @io::Reader) -> ~str {
diff --git a/src/libcore/unstable/at_exit.rs b/src/libcore/unstable/at_exit.rs
index 83f0c3695e8..bc4ec620aa8 100644
--- a/src/libcore/unstable/at_exit.rs
+++ b/src/libcore/unstable/at_exit.rs
@@ -62,7 +62,7 @@ fn exit_runner(exit_fns: *ExitFunctions) {
     // give us ownership of the array of functions
     let mut exit_fns_vec = unsafe { vec::from_buf(start, count as uint) };
     // Let's not make any promises about execution order
-    rand::Rng().shuffle_mut(exit_fns_vec);
+    rand::rng().shuffle_mut(exit_fns_vec);
 
     debug!("running %u exit functions", exit_fns_vec.len());