DEPS_rlibc :=
DEPS_alloc := core libc native:jemalloc
DEPS_debug := std
-DEPS_std := core libc alloc native:rustrt native:backtrace
+DEPS_std := core rand libc alloc native:rustrt native:backtrace
DEPS_graphviz := std
-DEPS_green := std rand native:context_switch
+DEPS_green := std native:context_switch
DEPS_rustuv := std native:uv native:uv_support
DEPS_native := std
DEPS_syntax := std term serialize collections log fmt_macros debug
DEPS_serialize := std collections log
DEPS_term := std collections log
DEPS_semver := std
-DEPS_uuid := std serialize rand
+DEPS_uuid := std serialize
DEPS_sync := std alloc
DEPS_getopts := std
-DEPS_collections := std rand debug
+DEPS_collections := std debug
DEPS_fourcc := syntax std
DEPS_hexfloat := syntax std
-DEPS_num := std rand
+DEPS_num := std
DEPS_test := std collections getopts serialize term time regex
DEPS_time := std serialize sync
-DEPS_rand := std
+DEPS_rand := core
DEPS_url := std collections
DEPS_workcache := std serialize collections log
DEPS_log := std sync
ONLY_RLIB_core := 1
ONLY_RLIB_rlibc := 1
ONLY_RLIB_alloc := 1
+ONLY_RLIB_rand := 1
################################################################################
# You should not need to edit below this line
a single large vector of floats. Each task needs the full vector to perform its duty.
~~~
-extern crate rand;
extern crate sync;
use sync::Arc;
+use std::rand;
fn pnorm(nums: &[f64], p: uint) -> f64 {
nums.iter().fold(0.0, |a, b| a + b.powf(p as f64)).powf(1.0 / (p as f64))
~~~
# extern crate sync;
-# extern crate rand;
+# use std::rand;
# use sync::Arc;
# fn main() {
# let numbers = Vec::from_fn(1000000, |_| rand::random::<f64>());
~~~
# extern crate sync;
-# extern crate rand;
+# use std::rand;
# use sync::Arc;
# fn pnorm(nums: &[f64], p: uint) -> f64 { 4.0 }
# fn main() {
use bitv;
use std::uint;
- use rand;
- use rand::Rng;
+ use std::rand;
+ use std::rand::Rng;
static BENCH_BITS : uint = 1 << 14;
extern crate test;
use self::test::Bencher;
use std::container::MutableMap;
- use rand;
- use rand::Rng;
+ use std::rand;
+ use std::rand::Rng;
pub fn insert_rand_n<M:MutableMap<uint,uint>>(n: uint,
map: &mut M,
extern crate test;
use self::test::Bencher;
use deque::Deque;
- use rand;
+ use std::rand;
use super::{DList, Node, ListInsertion};
pub fn check_links<T>(list: &DList<T>) {
use std::mem::replace;
use std::num;
use std::option::{Option, Some, None};
-use rand;
-use rand::Rng;
+use std::rand;
+use std::rand::Rng;
use std::result::{Ok, Err};
use std::slice::ImmutableVector;
#![deny(deprecated_owned_vector)]
-extern crate rand;
extern crate debug;
#[cfg(test)] extern crate test;
mod test_treemap {
use super::{TreeMap, TreeNode};
- use rand::Rng;
- use rand;
+ use std::rand::Rng;
+ use std::rand;
#[test]
fn find_empty() {
mod bench_map {
extern crate test;
use super::TrieMap;
- use rand::{weak_rng, Rng};
+ use std::rand::{weak_rng, Rng};
use self::test::Bencher;
#[bench]
use prelude::*;
use super::*;
use realstd::owned::{Box, AnyOwnExt};
- use realstd::str::{Str, StrAllocating};
+ use realstd::str::Str;
#[deriving(Eq, Show)]
struct Test;
use slice::ImmutableVector;
use option::{Some, None};
use realstd::string::String;
- use realstd::str::{Str, StrAllocating};
+ use realstd::str::Str;
#[test]
fn test_is_lowercase() {
#[cfg(test)]
pub fn format(args: &Arguments) -> ::realstd::string::String {
use str;
- use realstd::str::StrAllocating;
use realstd::io::MemWriter;
fn mywrite<T: ::realstd::io::Writer>(t: &mut T, b: &[u8]) {
use fmt::radix;
use super::{Binary, Octal, Decimal, LowerHex, UpperHex};
use super::{GenericRadix, Radix};
- use realstd::str::{Str, StrAllocating};
+ use realstd::str::Str;
#[test]
fn test_radix_base() {
mod uint {
use super::test::Bencher;
use fmt::radix;
- use rand::{XorShiftRng, Rng};
+ use realstd::rand::{weak_rng, Rng};
#[bench]
fn format_bin(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { format!("{:t}", rng.gen::<uint>()); })
}
#[bench]
fn format_oct(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { format!("{:o}", rng.gen::<uint>()); })
}
#[bench]
fn format_dec(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { format!("{:u}", rng.gen::<uint>()); })
}
#[bench]
fn format_hex(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { format!("{:x}", rng.gen::<uint>()); })
}
#[bench]
fn format_base_36(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { format!("{}", radix(rng.gen::<uint>(), 36)); })
}
}
mod int {
use super::test::Bencher;
use fmt::radix;
- use rand::{XorShiftRng, Rng};
+ use realstd::rand::{weak_rng, Rng};
#[bench]
fn format_bin(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { format!("{:t}", rng.gen::<int>()); })
}
#[bench]
fn format_oct(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { format!("{:o}", rng.gen::<int>()); })
}
#[bench]
fn format_dec(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { format!("{:d}", rng.gen::<int>()); })
}
#[bench]
fn format_hex(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { format!("{:x}", rng.gen::<int>()); })
}
#[bench]
fn format_base_36(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { format!("{}", radix(rng.gen::<int>(), 36)); })
}
}
#[cfg(test)] extern crate realcore = "core";
#[cfg(test)] extern crate libc;
#[cfg(test)] extern crate native;
-#[cfg(test)] extern crate rand;
#[cfg(test)] extern crate realstd = "std";
#[cfg(test)] pub use cmp = realcore::cmp;
#[cfg(test)]
mod tests {
use realstd::vec::Vec;
- use realstd::string::String;
use result::{collect, fold, fold_};
use prelude::*;
- use realstd::str::{Str, StrAllocating};
+ use realstd::str::Str;
use iter::range;
pub fn op1() -> Result<int, &'static str> { Ok(666) }
use super::*;
use clone::Clone;
use cmp::*;
- use realstd::str::{Str, StrAllocating};
+ use realstd::str::Str;
#[test]
fn test_clone() {
#[cfg(test)]
mod tests {
- extern crate rand;
-
use super::{inflate_bytes, deflate_bytes};
- use self::rand::Rng;
+ use std::rand;
+ use std::rand::Rng;
#[test]
#[allow(deprecated_owned_vector)]
let mut words = vec!();
for _ in range(0, 20) {
let range = r.gen_range(1u, 10);
- words.push(r.gen_vec::<u8>(range));
+ let v = r.gen_iter::<u8>().take(range).collect::<Vec<u8>>();
+ words.push(v);
}
for _ in range(0, 20) {
let mut input = vec![];
#[cfg(test)] #[phase(syntax, link)] extern crate log;
#[cfg(test)] extern crate rustuv;
-extern crate rand;
extern crate libc;
extern crate alloc;
use std::unstable::mutex::NativeMutex;
use std::raw;
-use rand::{XorShiftRng, Rng, Rand};
+use std::rand::{XorShiftRng, Rng, Rand};
use TaskState;
use context::Context;
// worry there.
#[cfg(windows)]
fn new_sched_rng() -> XorShiftRng {
- match XorShiftRng::new() {
- Ok(r) => r,
+ use std::rand::OSRng;
+ match OSRng::new() {
+ Ok(mut r) => r.gen(),
Err(e) => {
rtabort!("sched: failed to create seeded RNG: {}", e)
}
fn new_sched_rng() -> XorShiftRng {
use libc;
use std::mem;
- use rand::SeedableRng;
+ use std::rand::SeedableRng;
let fd = "/dev/urandom".with_c_str(|name| {
unsafe { libc::open(name, libc::O_RDONLY, 0) }
use std::num::{Zero, One, FromStrRadix, ToStrRadix};
use std::num::{ToPrimitive, FromPrimitive};
use std::num::CheckedDiv;
- use rand::{task_rng};
+ use std::rand::task_rng;
use std::u64;
#[test]
use std::num::CheckedDiv;
use std::num::{Zero, One, FromStrRadix, ToStrRadix};
use std::num::{ToPrimitive, FromPrimitive};
- use rand::{task_rng};
+ use std::rand::task_rng;
use std::u64;
#[test]
//! The exponential distribution.
-use std::num::Float;
+use core::num::Float;
+
use {Rng, Rand};
use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};
/// # Example
///
/// ```rust
-/// use rand::distributions::{Exp, IndependentSample};
+/// use std::rand;
+/// use std::rand::distributions::{Exp, IndependentSample};
///
/// let exp = Exp::new(2.0);
/// let v = exp.ind_sample(&mut rand::task_rng());
#[cfg(test)]
mod test {
+ use std::prelude::*;
+
use distributions::{Sample, IndependentSample};
- use {Rng, task_rng};
use super::Exp;
#[test]
fn test_exp() {
let mut exp = Exp::new(10.0);
- let mut rng = task_rng();
+ let mut rng = ::test::rng();
for _ in range(0, 1000) {
assert!(exp.sample(&mut rng) >= 0.0);
assert!(exp.ind_sample(&mut rng) >= 0.0);
#[cfg(test)]
mod bench {
extern crate test;
+
+ use std::prelude::*;
+
use self::test::Bencher;
use std::mem::size_of;
- use {XorShiftRng, RAND_BENCH_N};
use super::Exp;
use distributions::Sample;
#[bench]
fn rand_exp(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = ::test::weak_rng();
let mut exp = Exp::new(2.71828 * 3.14159);
b.iter(|| {
- for _ in range(0, RAND_BENCH_N) {
+ for _ in range(0, ::RAND_BENCH_N) {
exp.sample(&mut rng);
}
});
- b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
+ b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
}
}
//! The Gamma and derived distributions.
-use std::num::Float;
+use core::num::Float;
+
use {Rng, Open01};
use super::normal::StandardNormal;
use super::{IndependentSample, Sample, Exp};
/// # Example
///
/// ```rust
-/// use rand::distributions::{IndependentSample, Gamma};
+/// use std::rand;
+/// use std::rand::distributions::{IndependentSample, Gamma};
///
/// let gamma = Gamma::new(2.0, 5.0);
/// let v = gamma.ind_sample(&mut rand::task_rng());
/// # Example
///
/// ```rust
-/// use rand::distributions::{ChiSquared, IndependentSample};
+/// use std::rand;
+/// use std::rand::distributions::{ChiSquared, IndependentSample};
///
/// let chi = ChiSquared::new(11.0);
/// let v = chi.ind_sample(&mut rand::task_rng());
/// # Example
///
/// ```rust
-/// use rand::distributions::{FisherF, IndependentSample};
+/// use std::rand;
+/// use std::rand::distributions::{FisherF, IndependentSample};
///
/// let f = FisherF::new(2.0, 32.0);
/// let v = f.ind_sample(&mut rand::task_rng());
/// # Example
///
/// ```rust
-/// use rand::distributions::{StudentT, IndependentSample};
+/// use std::rand;
+/// use std::rand::distributions::{StudentT, IndependentSample};
///
/// let t = StudentT::new(11.0);
/// let v = t.ind_sample(&mut rand::task_rng());
#[cfg(test)]
mod test {
+ use std::prelude::*;
+
use distributions::{Sample, IndependentSample};
- use {Rng, task_rng};
use super::{ChiSquared, StudentT, FisherF};
#[test]
fn test_chi_squared_one() {
let mut chi = ChiSquared::new(1.0);
- let mut rng = task_rng();
+ let mut rng = ::test::rng();
for _ in range(0, 1000) {
chi.sample(&mut rng);
chi.ind_sample(&mut rng);
#[test]
fn test_chi_squared_small() {
let mut chi = ChiSquared::new(0.5);
- let mut rng = task_rng();
+ let mut rng = ::test::rng();
for _ in range(0, 1000) {
chi.sample(&mut rng);
chi.ind_sample(&mut rng);
#[test]
fn test_chi_squared_large() {
let mut chi = ChiSquared::new(30.0);
- let mut rng = task_rng();
+ let mut rng = ::test::rng();
for _ in range(0, 1000) {
chi.sample(&mut rng);
chi.ind_sample(&mut rng);
#[test]
fn test_f() {
let mut f = FisherF::new(2.0, 32.0);
- let mut rng = task_rng();
+ let mut rng = ::test::rng();
for _ in range(0, 1000) {
f.sample(&mut rng);
f.ind_sample(&mut rng);
#[test]
fn test_t() {
let mut t = StudentT::new(11.0);
- let mut rng = task_rng();
+ let mut rng = ::test::rng();
for _ in range(0, 1000) {
t.sample(&mut rng);
t.ind_sample(&mut rng);
#[cfg(test)]
mod bench {
extern crate test;
+ use std::prelude::*;
use self::test::Bencher;
use std::mem::size_of;
use distributions::IndependentSample;
- use {XorShiftRng, RAND_BENCH_N};
use super::Gamma;
#[bench]
fn bench_gamma_large_shape(b: &mut Bencher) {
let gamma = Gamma::new(10., 1.0);
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = ::test::weak_rng();
b.iter(|| {
- for _ in range(0, RAND_BENCH_N) {
+ for _ in range(0, ::RAND_BENCH_N) {
gamma.ind_sample(&mut rng);
}
});
- b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
+ b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
}
#[bench]
fn bench_gamma_small_shape(b: &mut Bencher) {
let gamma = Gamma::new(0.1, 1.0);
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = ::test::weak_rng();
b.iter(|| {
- for _ in range(0, RAND_BENCH_N) {
+ for _ in range(0, ::RAND_BENCH_N) {
gamma.ind_sample(&mut rng);
}
});
- b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
+ b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
}
}
*/
-use std::num;
-use std::num::CheckedAdd;
+#![experimental]
+
+use core::prelude::*;
+use core::num;
+use core::num::CheckedAdd;
+
use {Rng, Rand};
pub use self::range::Range;
/// # Example
///
/// ```rust
-/// use rand::distributions::{Weighted, WeightedChoice, IndependentSample};
+/// use std::rand;
+/// use std::rand::distributions::{Weighted, WeightedChoice, IndependentSample};
///
-/// let wc = WeightedChoice::new(vec!(Weighted { weight: 2, item: 'a' },
-/// Weighted { weight: 4, item: 'b' },
-/// Weighted { weight: 1, item: 'c' }));
+/// let mut items = vec!(Weighted { weight: 2, item: 'a' },
+/// Weighted { weight: 4, item: 'b' },
+/// Weighted { weight: 1, item: 'c' });
+/// let wc = WeightedChoice::new(items.as_mut_slice());
/// let mut rng = rand::task_rng();
/// for _ in range(0, 16) {
/// // on average prints 'a' 4 times, 'b' 8 and 'c' twice.
/// println!("{}", wc.ind_sample(&mut rng));
/// }
/// ```
-pub struct WeightedChoice<T> {
- items: Vec<Weighted<T>>,
+pub struct WeightedChoice<'a, T> {
+ items: &'a mut [Weighted<T>],
weight_range: Range<uint>
}
-impl<T: Clone> WeightedChoice<T> {
+impl<'a, T: Clone> WeightedChoice<'a, T> {
/// Create a new `WeightedChoice`.
///
/// Fails if:
/// - `v` is empty
/// - the total weight is 0
/// - the total weight is larger than a `uint` can contain.
- pub fn new(mut items: Vec<Weighted<T>>) -> WeightedChoice<T> {
+ pub fn new<'a>(items: &'a mut [Weighted<T>]) -> WeightedChoice<'a, T> {
// strictly speaking, this is subsumed by the total weight == 0 case
assert!(!items.is_empty(), "WeightedChoice::new called with no items");
// weights so we can binary search. This *could* drop elements
// with weight == 0 as an optimisation.
for item in items.mut_iter() {
- running_total = running_total.checked_add(&item.weight)
- .expect("WeightedChoice::new called with a total weight larger \
- than a uint can contain");
+ running_total = match running_total.checked_add(&item.weight) {
+ Some(n) => n,
+ None => fail!("WeightedChoice::new called with a total weight \
+ larger than a uint can contain")
+ };
item.weight = running_total;
}
}
}
-impl<T: Clone> Sample<T> for WeightedChoice<T> {
+impl<'a, T: Clone> Sample<T> for WeightedChoice<'a, T> {
fn sample<R: Rng>(&mut self, rng: &mut R) -> T { self.ind_sample(rng) }
}
-impl<T: Clone> IndependentSample<T> for WeightedChoice<T> {
+impl<'a, T: Clone> IndependentSample<T> for WeightedChoice<'a, T> {
fn ind_sample<R: Rng>(&self, rng: &mut R) -> T {
// we want to find the first element that has cumulative
// weight > sample_weight, which we do by binary since the
let sample_weight = self.weight_range.ind_sample(rng);
// short circuit when it's the first item
- if sample_weight < self.items.get(0).weight {
- return self.items.get(0).item.clone();
+ if sample_weight < self.items[0].weight {
+ return self.items[0].item.clone();
}
let mut idx = 0;
// one is exactly the total weight.)
while modifier > 1 {
let i = idx + modifier / 2;
- if self.items.get(i).weight <= sample_weight {
+ if self.items[i].weight <= sample_weight {
// we're small, so look to the right, but allow this
// exact element still.
idx = i;
}
modifier /= 2;
}
- return self.items.get(idx + 1).item.clone();
+ return self.items[idx + 1].item.clone();
}
}
#[cfg(test)]
mod tests {
- use {task_rng, Rng, Rand};
+ use std::prelude::*;
+
+ use {Rng, Rand};
use super::{RandSample, WeightedChoice, Weighted, Sample, IndependentSample};
#[deriving(Eq, Show)]
fn test_rand_sample() {
let mut rand_sample = RandSample::<ConstRand>;
- assert_eq!(rand_sample.sample(&mut task_rng()), ConstRand(0));
- assert_eq!(rand_sample.ind_sample(&mut task_rng()), ConstRand(0));
+ assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0));
+ assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0));
}
#[test]
fn test_weighted_choice() {
macro_rules! t (
($items:expr, $expected:expr) => {{
- let wc = WeightedChoice::new($items);
+ let mut items = $items;
+ let wc = WeightedChoice::new(items.as_mut_slice());
let expected = $expected;
let mut rng = CountingRng { i: 0 };
#[test] #[should_fail]
fn test_weighted_choice_no_items() {
- WeightedChoice::<int>::new(vec!());
+ WeightedChoice::<int>::new([]);
}
#[test] #[should_fail]
fn test_weighted_choice_zero_weight() {
- WeightedChoice::new(vec!(Weighted { weight: 0, item: 0},
- Weighted { weight: 0, item: 1}));
+ WeightedChoice::new(&mut [Weighted { weight: 0, item: 0},
+ Weighted { weight: 0, item: 1}]);
}
#[test] #[should_fail]
fn test_weighted_choice_weight_overflows() {
let x = (-1) as uint / 2; // x + x + 2 is the overflow
- WeightedChoice::new(vec!(Weighted { weight: x, item: 0 },
- Weighted { weight: 1, item: 1 },
- Weighted { weight: x, item: 2 },
- Weighted { weight: 1, item: 3 }));
+ WeightedChoice::new(&mut [Weighted { weight: x, item: 0 },
+ Weighted { weight: 1, item: 1 },
+ Weighted { weight: x, item: 2 },
+ Weighted { weight: 1, item: 3 }]);
}
}
//! The normal and derived distributions.
-use std::num::Float;
+use core::num::Float;
+
use {Rng, Rand, Open01};
use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};
/// # Example
///
/// ```rust
-/// use rand::distributions::{Normal, IndependentSample};
+/// use std::rand;
+/// use std::rand::distributions::{Normal, IndependentSample};
///
/// // mean 2, standard deviation 3
/// let normal = Normal::new(2.0, 3.0);
/// # Example
///
/// ```rust
-/// use rand::distributions::{LogNormal, IndependentSample};
+/// use std::rand;
+/// use std::rand::distributions::{LogNormal, IndependentSample};
///
/// // mean 2, standard deviation 3
/// let log_normal = LogNormal::new(2.0, 3.0);
#[cfg(test)]
mod tests {
+ use std::prelude::*;
+
use distributions::{Sample, IndependentSample};
- use {Rng, task_rng};
use super::{Normal, LogNormal};
#[test]
fn test_normal() {
let mut norm = Normal::new(10.0, 10.0);
- let mut rng = task_rng();
+ let mut rng = ::test::rng();
for _ in range(0, 1000) {
norm.sample(&mut rng);
norm.ind_sample(&mut rng);
#[test]
fn test_log_normal() {
let mut lnorm = LogNormal::new(10.0, 10.0);
- let mut rng = task_rng();
+ let mut rng = ::test::rng();
for _ in range(0, 1000) {
lnorm.sample(&mut rng);
lnorm.ind_sample(&mut rng);
#[cfg(test)]
mod bench {
extern crate test;
+ use std::prelude::*;
use self::test::Bencher;
use std::mem::size_of;
- use {XorShiftRng, RAND_BENCH_N};
use distributions::{Sample};
use super::Normal;
#[bench]
fn rand_normal(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = ::test::weak_rng();
let mut normal = Normal::new(-2.71828, 3.14159);
b.iter(|| {
- for _ in range(0, RAND_BENCH_N) {
+ for _ in range(0, ::RAND_BENCH_N) {
normal.sample(&mut rng);
}
});
- b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
+ b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
}
}
// this is surprisingly complicated to be both generic & correct
-use std::num::Bounded;
+use core::prelude::*;
+use core::num::Bounded;
+
use Rng;
use distributions::{Sample, IndependentSample};
/// # Example
///
/// ```rust
-/// use rand::distributions::{IndependentSample, Range};
+/// use std::rand;
+/// use std::rand::distributions::{IndependentSample, Range};
///
/// fn main() {
/// let between = Range::new(10u, 10000u);
#[cfg(test)]
mod tests {
+ use std::prelude::*;
use distributions::{Sample, IndependentSample};
- use {Rng, task_rng};
use super::Range;
use std::num::Bounded;
#[test]
fn test_integers() {
- let mut rng = task_rng();
+ let mut rng = ::test::rng();
macro_rules! t (
($($ty:ty),*) => {{
$(
#[test]
fn test_floats() {
- let mut rng = task_rng();
+ let mut rng = ::test::rng();
macro_rules! t (
($($ty:ty),*) => {{
$(
//! The ISAAC random number generator.
-use {Rng, SeedableRng, OSRng};
-use std::io::IoResult;
-use std::iter::{range_step, Repeat};
-use std::slice::raw;
-use std::mem;
+use core::prelude::*;
+use core::iter::{range_step, Repeat};
+use core::slice::raw;
+use core::mem;
+
+use {Rng, SeedableRng, Rand};
static RAND_SIZE_LEN: u32 = 8;
static RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
};
impl IsaacRng {
- /// Create an ISAAC random number generator with a random seed.
- ///
- /// This reads randomness from the operating system (via `OSRng`)
- /// which may fail, any error is propagated via the `IoResult`
- /// return value.
- pub fn new() -> IoResult<IsaacRng> {
- let mut rng = EMPTY;
- let mut os_rng = try!(OSRng::new());
- unsafe {
- let ptr = rng.rsl.as_mut_ptr();
-
- raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl), |slice| {
- os_rng.fill_bytes(slice);
- })
- }
-
- rng.init(true);
- Ok(rng)
- }
-
/// Create an ISAAC random number generator using the default
/// fixed seed.
pub fn new_unseeded() -> IsaacRng {
}
}
+impl Rand for IsaacRng {
+ fn rand<R: Rng>(other: &mut R) -> IsaacRng {
+ let mut ret = EMPTY;
+ unsafe {
+ let ptr = ret.rsl.as_mut_ptr();
+
+ raw::mut_buf_as_slice(ptr as *mut u8,
+ mem::size_of_val(&ret.rsl), |slice| {
+ other.fill_bytes(slice);
+ })
+ }
+ ret.cnt = 0;
+ ret.a = 0;
+ ret.b = 0;
+ ret.c = 0;
+
+ ret.init(true);
+ return ret;
+ }
+}
static RAND_SIZE_64_LEN: uint = 8;
static RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN;
};
impl Isaac64Rng {
- /// Create a 64-bit ISAAC random number generator with a random
- /// seed.
- ///
- /// This reads randomness from the operating system (via `OSRng`)
- /// which may fail, any error is propagated via the `IoResult`
- /// return value.
- pub fn new() -> IoResult<Isaac64Rng> {
- let mut rng = EMPTY_64;
- let mut os_rng = try!(OSRng::new());
-
- unsafe {
- let ptr = rng.rsl.as_mut_ptr();
-
- raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl), |slice| {
- os_rng.fill_bytes(slice);
- })
- }
-
- rng.init(true);
- Ok(rng)
- }
-
/// Create a 64-bit ISAAC random number generator using the
/// default fixed seed.
pub fn new_unseeded() -> Isaac64Rng {
}
}
+impl Rand for Isaac64Rng {
+ fn rand<R: Rng>(other: &mut R) -> Isaac64Rng {
+ let mut ret = EMPTY_64;
+ unsafe {
+ let ptr = ret.rsl.as_mut_ptr();
+
+ raw::mut_buf_as_slice(ptr as *mut u8,
+ mem::size_of_val(&ret.rsl), |slice| {
+ other.fill_bytes(slice);
+ })
+ }
+ ret.cnt = 0;
+ ret.a = 0;
+ ret.b = 0;
+ ret.c = 0;
+
+ ret.init(true);
+ return ret;
+ }
+}
+
#[cfg(test)]
mod test {
+ use std::prelude::*;
+
+ use core::iter::order;
+ use {Rng, SeedableRng};
use super::{IsaacRng, Isaac64Rng};
- use {Rng, SeedableRng, task_rng};
#[test]
fn test_rng_32_rand_seeded() {
- let s = task_rng().gen_vec::<u32>(256);
+ let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
let mut ra: IsaacRng = SeedableRng::from_seed(s.as_slice());
let mut rb: IsaacRng = SeedableRng::from_seed(s.as_slice());
- assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
+ assert!(order::equals(ra.gen_ascii_chars().take(100),
+ rb.gen_ascii_chars().take(100)));
}
#[test]
fn test_rng_64_rand_seeded() {
- let s = task_rng().gen_vec::<u64>(256);
+ let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
let mut ra: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
let mut rb: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
- assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
+ assert!(order::equals(ra.gen_ascii_chars().take(100),
+ rb.gen_ascii_chars().take(100)));
}
#[test]
let seed = &[1, 23, 456, 7890, 12345];
let mut ra: IsaacRng = SeedableRng::from_seed(seed);
let mut rb: IsaacRng = SeedableRng::from_seed(seed);
- assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
+ assert!(order::equals(ra.gen_ascii_chars().take(100),
+ rb.gen_ascii_chars().take(100)));
}
#[test]
fn test_rng_64_seeded() {
let seed = &[1, 23, 456, 7890, 12345];
let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
- assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
+ assert!(order::equals(ra.gen_ascii_chars().take(100),
+ rb.gen_ascii_chars().take(100)));
}
#[test]
fn test_rng_32_reseed() {
- let s = task_rng().gen_vec::<u32>(256);
+ let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>();
let mut r: IsaacRng = SeedableRng::from_seed(s.as_slice());
- let string1 = r.gen_ascii_str(100);
+ let string1: String = r.gen_ascii_chars().take(100).collect();
r.reseed(s.as_slice());
- let string2 = r.gen_ascii_str(100);
+ let string2: String = r.gen_ascii_chars().take(100).collect();
assert_eq!(string1, string2);
}
#[test]
fn test_rng_64_reseed() {
- let s = task_rng().gen_vec::<u64>(256);
+ let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>();
let mut r: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
- let string1 = r.gen_ascii_str(100);
+ let string1: String = r.gen_ascii_chars().take(100).collect();
r.reseed(s.as_slice());
- let string2 = r.gen_ascii_str(100);
+ let string2: String = r.gen_ascii_chars().take(100).collect();
assert_eq!(string1, string2);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-/*!
-Utilities for random number generation
-
-The key functions are `random()` and `Rng::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::<f64>()`.
-
-See the `distributions` submodule for sampling random numbers from
-distributions like normal and exponential.
-
-# Task-local RNG
-
-There is built-in support for a RNG associated with each task stored
-in task-local storage. This RNG can be accessed via `task_rng`, or
-used implicitly via `random`. This RNG is normally randomly seeded
-from an operating-system source of randomness, e.g. `/dev/urandom` on
-Unix systems, and will automatically reseed itself from this source
-after generating 32 KiB of random data.
-
-# Cryptographic security
-
-An application that requires an entropy source for cryptographic purposes
-must use `OSRng`, which reads randomness from the source that the operating
-system provides (e.g. `/dev/urandom` on Unixes or `CryptGenRandom()` on Windows).
-The other random number generators provided by this module are not suitable
-for such purposes.
-
-*Note*: many Unix systems provide `/dev/random` as well as `/dev/urandom`.
-This module uses `/dev/urandom` for the following reasons:
-
-- On Linux, `/dev/random` may block if entropy pool is empty; `/dev/urandom` will not block.
- This does not mean that `/dev/random` provides better output than
- `/dev/urandom`; the kernel internally runs a cryptographically secure pseudorandom
- number generator (CSPRNG) based on entropy pool for random number generation,
- so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
- However, this means that `/dev/urandom` can yield somewhat predictable randomness
- if the entropy pool is very small, such as immediately after first booting.
- If an application likely to be run soon after first booting, or on a system with very
- few entropy sources, one should consider using `/dev/random` via `ReaderRng`.
-- On some systems (e.g. FreeBSD, OpenBSD and Mac OS X) there is no difference
- between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random`
- and `/dev/urandom` may block once if the CSPRNG has not seeded yet.)
-
-# Examples
-
-```rust
-use rand::Rng;
-
-let mut rng = rand::task_rng();
-if rng.gen() { // bool
- println!("int: {}, uint: {}", rng.gen::<int>(), rng.gen::<uint>())
-}
-```
-
-```rust
-let tuple_ptr = rand::random::<Box<(f64, char)>>();
-println!("{}", tuple_ptr)
-```
-*/
+//! Interface to random number generators in Rust.
+//!
+//! This is an experimental library which lives underneath the standard library
+//! in its dependency chain. This library is intended to define the interface
+//! for random number generation and also provide utilities around doing so. It
+//! is not recommended to use this library directly, but rather the official
+//! interface through `std::rand`.
#![crate_id = "rand#0.11.0-pre"]
#![license = "MIT/ASL2"]
-#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/")]
-#![feature(macro_rules, managed_boxes, phase)]
-#![deny(deprecated_owned_vector)]
+#![feature(macro_rules, phase, globs)]
+#![no_std]
+#![experimental]
+
+#[phase(syntax, link)]
+extern crate core;
+#[cfg(test)] extern crate native;
#[cfg(test)] extern crate debug;
+#[cfg(test)] #[phase(syntax, link)] extern crate std;
#[cfg(test)] #[phase(syntax, link)] extern crate log;
-use std::io::IoResult;
-use std::kinds::marker;
-use std::mem;
-use std::string::String;
+use core::prelude::*;
pub use isaac::{IsaacRng, Isaac64Rng};
-pub use os::OSRng;
use distributions::{Range, IndependentSample};
use distributions::range::SampleRange;
+#[cfg(test)]
+static RAND_BENCH_N: u64 = 100;
+
pub mod distributions;
pub mod isaac;
-pub mod os;
-pub mod reader;
pub mod reseeding;
mod rand_impls;
/// # Example
///
/// ```rust
- /// use rand::{task_rng, Rng};
+ /// use std::rand::{task_rng, Rng};
///
/// let mut v = [0u8, .. 13579];
/// task_rng().fill_bytes(v);
/// # Example
///
/// ```rust
- /// use rand::{task_rng, Rng};
+ /// use std::rand::{task_rng, Rng};
///
/// let mut rng = task_rng();
/// let x: uint = rng.gen();
Rand::rand(self)
}
- /// Return a random vector of the specified length.
+ /// Return an iterator which will yield an infinite number of randomly
+ /// generated items.
///
/// # Example
///
- /// ```rust
- /// use rand::{task_rng, Rng};
+ /// ```
+ /// use std::rand::{task_rng, Rng};
///
/// let mut rng = task_rng();
- /// let x: Vec<uint> = rng.gen_vec(10);
+ /// let x = rng.gen_iter::<uint>().take(10).collect::<Vec<uint>>();
/// println!("{}", x);
- /// println!("{}", rng.gen_vec::<(f64, bool)>(5));
+ /// println!("{}", rng.gen_iter::<(f64, bool)>().take(5)
+ /// .collect::<Vec<(f64, bool)>>());
/// ```
- fn gen_vec<T: Rand>(&mut self, len: uint) -> Vec<T> {
- Vec::from_fn(len, |_| self.gen())
+ fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> {
+ Generator { rng: self }
}
/// Generate a random value in the range [`low`, `high`). Fails if
/// # Example
///
/// ```rust
- /// use rand::{task_rng, Rng};
+ /// use std::rand::{task_rng, Rng};
///
/// let mut rng = task_rng();
/// let n: uint = rng.gen_range(0u, 10);
/// # Example
///
/// ```rust
- /// use rand::{task_rng, Rng};
+ /// use std::rand::{task_rng, Rng};
///
/// let mut rng = task_rng();
/// println!("{:b}", rng.gen_weighted_bool(3));
n == 0 || self.gen_range(0, n) == 0
}
- /// Return a random string of the specified length composed of
- /// A-Z,a-z,0-9.
+ /// Return an iterator of random characters from the set A-Z,a-z,0-9.
///
/// # Example
///
/// ```rust
- /// use rand::{task_rng, Rng};
+ /// use std::rand::{task_rng, Rng};
///
- /// println!("{}", task_rng().gen_ascii_str(10));
+ /// let s: String = task_rng().gen_ascii_chars().take(10).collect();
+ /// println!("{}", s);
/// ```
- fn gen_ascii_str(&mut self, len: uint) -> String {
- static GEN_ASCII_STR_CHARSET: &'static [u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ\
- abcdefghijklmnopqrstuvwxyz\
- 0123456789");
- let mut s = String::with_capacity(len);
- for _ in range(0, len) {
- s.push_char(*self.choose(GEN_ASCII_STR_CHARSET).unwrap() as char)
- }
- s
+ fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> {
+ AsciiGenerator { rng: self }
}
/// Return a random element from `values`.
/// # Example
///
/// ```
- /// use rand::{task_rng, Rng};
+ /// use std::rand::{task_rng, Rng};
///
/// let choices = [1, 2, 4, 8, 16, 32];
/// let mut rng = task_rng();
/// # Example
///
/// ```rust
- /// use rand::{task_rng, Rng};
+ /// use std::rand::{task_rng, Rng};
///
/// let mut rng = task_rng();
/// let mut y = [1,2,3];
values.swap(i, self.gen_range(0u, i + 1u));
}
}
+}
- /// Randomly sample up to `n` elements from an iterator.
- ///
- /// # Example
- ///
- /// ```rust
- /// use rand::{task_rng, Rng};
- ///
- /// let mut rng = task_rng();
- /// let sample = rng.sample(range(1, 100), 5);
- /// println!("{}", sample);
- /// ```
- fn sample<A, T: Iterator<A>>(&mut self, iter: T, n: uint) -> Vec<A> {
- let mut reservoir = Vec::with_capacity(n);
- for (i, elem) in iter.enumerate() {
- if i < n {
- reservoir.push(elem);
- continue
- }
+/// Iterator which will generate a stream of random items.
+///
+/// This iterator is created via the `gen_iter` method on `Rng`.
+pub struct Generator<'a, T, R> {
+ rng: &'a mut R,
+}
- let k = self.gen_range(0, i + 1);
- if k < reservoir.len() {
- *reservoir.get_mut(k) = elem
- }
- }
- reservoir
+impl<'a, T: Rand, R: Rng> Iterator<T> for Generator<'a, T, R> {
+ fn next(&mut self) -> Option<T> {
+ Some(self.rng.gen())
+ }
+}
+
+/// Iterator which will continuously generate random ascii characters.
+///
+/// This iterator is created via the `gen_ascii_chars` method on `Rng`.
+pub struct AsciiGenerator<'a, R> {
+ rng: &'a mut R,
+}
+
+impl<'a, R: Rng> Iterator<char> for AsciiGenerator<'a, R> {
+ fn next(&mut self) -> Option<char> {
+ static GEN_ASCII_STR_CHARSET: &'static [u8] =
+ bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ\
+ abcdefghijklmnopqrstuvwxyz\
+ 0123456789");
+ Some(*self.rng.choose(GEN_ASCII_STR_CHARSET).unwrap() as char)
}
}
/// # Example
///
/// ```rust
- /// use rand::{Rng, SeedableRng, StdRng};
+ /// use std::rand::{Rng, SeedableRng, StdRng};
///
/// let mut rng: StdRng = SeedableRng::from_seed(&[1, 2, 3, 4]);
/// println!("{}", rng.gen::<f64>());
/// # Example
///
/// ```rust
- /// use rand::{Rng, SeedableRng, StdRng};
+ /// use std::rand::{Rng, SeedableRng, StdRng};
///
/// let mut rng: StdRng = SeedableRng::from_seed(&[1, 2, 3, 4]);
/// println!("{}", rng.gen::<f64>());
fn from_seed(seed: Seed) -> Self;
}
-/// The standard RNG. This is designed to be efficient on the current
-/// platform.
-#[cfg(not(target_word_size="64"))]
-pub struct StdRng { rng: IsaacRng }
-
-/// The standard RNG. This is designed to be efficient on the current
-/// platform.
-#[cfg(target_word_size="64")]
-pub struct StdRng { rng: Isaac64Rng }
-
-impl StdRng {
- /// Create a randomly seeded instance of `StdRng`.
- ///
- /// This is a very expensive operation as it has to read
- /// randomness from the operating system and use this in an
- /// expensive seeding operation. If one is only generating a small
- /// number of random numbers, or doesn't need the utmost speed for
- /// generating each number, `task_rng` and/or `random` may be more
- /// appropriate.
- ///
- /// Reading the randomness from the OS may fail, and any error is
- /// propagated via the `IoResult` return value.
- #[cfg(not(target_word_size="64"))]
- pub fn new() -> IoResult<StdRng> {
- IsaacRng::new().map(|r| StdRng { rng: r })
- }
- /// Create a randomly seeded instance of `StdRng`.
- ///
- /// This is a very expensive operation as it has to read
- /// randomness from the operating system and use this in an
- /// expensive seeding operation. If one is only generating a small
- /// number of random numbers, or doesn't need the utmost speed for
- /// generating each number, `task_rng` and/or `random` may be more
- /// appropriate.
- ///
- /// Reading the randomness from the OS may fail, and any error is
- /// propagated via the `IoResult` return value.
- #[cfg(target_word_size="64")]
- pub fn new() -> IoResult<StdRng> {
- Isaac64Rng::new().map(|r| StdRng { rng: r })
- }
-}
-
-impl Rng for StdRng {
- #[inline]
- fn next_u32(&mut self) -> u32 {
- self.rng.next_u32()
- }
-
- #[inline]
- fn next_u64(&mut self) -> u64 {
- self.rng.next_u64()
- }
-}
-
-impl<'a> SeedableRng<&'a [uint]> for StdRng {
- fn reseed(&mut self, seed: &'a [uint]) {
- // the internal RNG can just be seeded from the above
- // randomness.
- self.rng.reseed(unsafe {mem::transmute(seed)})
- }
-
- fn from_seed(seed: &'a [uint]) -> StdRng {
- StdRng { rng: SeedableRng::from_seed(unsafe {mem::transmute(seed)}) }
- }
-}
-
-/// Create a weak random number generator with a default algorithm and seed.
-///
-/// It returns the fastest `Rng` algorithm currently available in Rust without
-/// consideration for cryptography or security. If you require a specifically
-/// seeded `Rng` for consistency over time you should pick one algorithm and
-/// create the `Rng` yourself.
-///
-/// This will read randomness from the operating system to seed the
-/// generator.
-pub fn weak_rng() -> XorShiftRng {
- match XorShiftRng::new() {
- Ok(r) => r,
- Err(e) => fail!("weak_rng: failed to create seeded RNG: {}", e)
- }
-}
-
/// An Xorshift[1] random number
/// generator.
///
w: u32,
}
+impl XorShiftRng {
+ /// Creates a new XorShiftRng instance which is not seeded.
+ ///
+ /// The initial values of this RNG are constants, so all generators created
+ /// by this function will yield the same stream of random numbers. It is
+ /// highly recommended that this is created through `SeedableRng` instead of
+ /// this function
+ pub fn new_unseeded() -> XorShiftRng {
+ XorShiftRng {
+ x: 0x193a6754,
+ y: 0xa8a7d469,
+ z: 0x97830e05,
+ w: 0x113ba7bb,
+ }
+ }
+}
+
impl Rng for XorShiftRng {
#[inline]
fn next_u32(&mut self) -> u32 {
}
}
-impl XorShiftRng {
- /// Create an xor shift random number generator with a random seed.
- pub fn new() -> IoResult<XorShiftRng> {
- let mut s = [0u8, ..16];
- let mut r = try!(OSRng::new());
- loop {
- r.fill_bytes(s);
-
- if !s.iter().all(|x| *x == 0) {
- break;
- }
- }
- let s: [u32, ..4] = unsafe { mem::transmute(s) };
- Ok(SeedableRng::from_seed(s))
- }
-}
-
-/// Controls how the task-local RNG is reseeded.
-struct TaskRngReseeder;
-
-impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
- fn reseed(&mut self, rng: &mut StdRng) {
- *rng = match StdRng::new() {
- Ok(r) => r,
- Err(e) => fail!("could not reseed task_rng: {}", e)
+impl Rand for XorShiftRng {
+ fn rand<R: Rng>(rng: &mut R) -> XorShiftRng {
+ let mut tuple: (u32, u32, u32, u32) = rng.gen();
+ while tuple == (0, 0, 0, 0) {
+ tuple = rng.gen();
}
+ let (x, y, z, w) = tuple;
+ XorShiftRng { x: x, y: y, z: z, w: w }
}
}
-static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
-type TaskRngInner = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
-/// The task-local RNG.
-pub struct TaskRng {
- // This points into TLS (specifically, it points to the endpoint
- // of a Box stored in TLS, to make it robust against TLS moving
- // things internally) and so this struct cannot be legally
- // transferred between tasks *and* it's unsafe to deallocate the
- // RNG other than when a task is finished.
- //
- // The use of unsafe code here is OK if the invariants above are
- // satisfied; and it allows us to avoid (unnecessarily) using a
- // GC'd or RC'd pointer.
- rng: *mut TaskRngInner,
- marker: marker::NoSend,
-}
-
-/// Retrieve the lazily-initialized task-local random number
-/// generator, seeded by the system. Intended to be used in method
-/// chaining style, e.g. `task_rng().gen::<int>()`.
-///
-/// The RNG provided will reseed itself from the operating system
-/// after generating a certain amount of randomness.
-///
-/// The internal RNG used is platform and architecture dependent, even
-/// if the operating system random number generator is rigged to give
-/// the same sequence always. If absolute consistency is required,
-/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
-pub fn task_rng() -> TaskRng {
- // used to make space in TLS for a random number generator
- local_data_key!(TASK_RNG_KEY: Box<TaskRngInner>)
-
- match TASK_RNG_KEY.get() {
- None => {
- let r = match StdRng::new() {
- Ok(r) => r,
- Err(e) => fail!("could not initialize task_rng: {}", e)
- };
- let mut rng = box reseeding::ReseedingRng::new(r,
- TASK_RNG_RESEED_THRESHOLD,
- TaskRngReseeder);
- let ptr = &mut *rng as *mut TaskRngInner;
-
- TASK_RNG_KEY.replace(Some(rng));
-
- TaskRng { rng: ptr, marker: marker::NoSend }
- }
- Some(rng) => TaskRng {
- rng: &**rng as *_ as *mut TaskRngInner,
- marker: marker::NoSend
- }
- }
-}
-
-impl Rng for TaskRng {
- fn next_u32(&mut self) -> u32 {
- unsafe { (*self.rng).next_u32() }
- }
-
- fn next_u64(&mut self) -> u64 {
- unsafe { (*self.rng).next_u64() }
- }
-
- #[inline]
- fn fill_bytes(&mut self, bytes: &mut [u8]) {
- unsafe { (*self.rng).fill_bytes(bytes) }
- }
-}
-
-/// Generate a random value using the task-local random number
-/// generator.
-///
-/// # Example
-///
-/// ```rust
-/// use rand::random;
-///
-/// if random() {
-/// let x = random();
-/// println!("{}", 2u * x);
-/// } else {
-/// println!("{}", random::<f64>());
-/// }
-/// ```
-#[inline]
-pub fn random<T: Rand>() -> T {
- task_rng().gen()
-}
/// A wrapper for generating floating point numbers uniformly in the
/// open interval `(0,1)` (not including either endpoint).
///
/// # Example
/// ```rust
-/// use rand::{random, Open01};
+/// use std::rand::{random, Open01};
///
/// let Open01(val) = random::<Open01<f32>>();
/// println!("f32 from (0,1): {}", val);
/// `[0,1)`.
///
/// # Example
+///
/// ```rust
-/// use rand::{random, Closed01};
+/// use std::rand::{random, Closed01};
///
/// let Closed01(val) = random::<Closed01<f32>>();
/// println!("f32 from [0,1]: {}", val);
/// ```
pub struct Closed01<F>(pub F);
-#[cfg(test)]
-mod test {
- use super::{Rng, task_rng, random, SeedableRng, StdRng};
-
- struct ConstRng { i: u64 }
- impl Rng for ConstRng {
- fn next_u32(&mut self) -> u32 { self.i as u32 }
- fn next_u64(&mut self) -> u64 { self.i }
-
- // no fill_bytes on purpose
- }
-
- #[test]
- fn test_fill_bytes_default() {
- let mut r = ConstRng { i: 0x11_22_33_44_55_66_77_88 };
-
- // check every remainder mod 8, both in small and big vectors.
- let lengths = [0, 1, 2, 3, 4, 5, 6, 7,
- 80, 81, 82, 83, 84, 85, 86, 87];
- for &n in lengths.iter() {
- let mut v = Vec::from_elem(n, 0u8);
- r.fill_bytes(v.as_mut_slice());
-
- // use this to get nicer error messages.
- for (i, &byte) in v.iter().enumerate() {
- if byte == 0 {
- fail!("byte {} of {} is zero", i, n)
- }
- }
- }
- }
-
- #[test]
- fn test_gen_range() {
- let mut r = task_rng();
- for _ in range(0, 1000) {
- let a = r.gen_range(-3i, 42);
- assert!(a >= -3 && a < 42);
- assert_eq!(r.gen_range(0, 1), 0);
- assert_eq!(r.gen_range(-12, -11), -12);
- }
-
- for _ in range(0, 1000) {
- let a = r.gen_range(10, 42);
- assert!(a >= 10 && a < 42);
- assert_eq!(r.gen_range(0, 1), 0);
- assert_eq!(r.gen_range(3_000_000u, 3_000_001), 3_000_000);
- }
-
- }
-
- #[test]
- #[should_fail]
- fn test_gen_range_fail_int() {
- let mut r = task_rng();
- r.gen_range(5i, -2);
- }
-
- #[test]
- #[should_fail]
- fn test_gen_range_fail_uint() {
- let mut r = task_rng();
- r.gen_range(5u, 2u);
- }
-
- #[test]
- fn test_gen_f64() {
- let mut r = task_rng();
- let a = r.gen::<f64>();
- let b = r.gen::<f64>();
- debug!("{:?}", (a, b));
- }
-
- #[test]
- fn test_gen_weighted_bool() {
- let mut r = task_rng();
- assert_eq!(r.gen_weighted_bool(0u), true);
- assert_eq!(r.gen_weighted_bool(1u), true);
- }
-
- #[test]
- fn test_gen_ascii_str() {
- let mut r = task_rng();
- debug!("{}", r.gen_ascii_str(10u));
- debug!("{}", r.gen_ascii_str(10u));
- debug!("{}", r.gen_ascii_str(10u));
- assert_eq!(r.gen_ascii_str(0u).len(), 0u);
- assert_eq!(r.gen_ascii_str(10u).len(), 10u);
- assert_eq!(r.gen_ascii_str(16u).len(), 16u);
- }
-
- #[test]
- fn test_gen_vec() {
- let mut r = task_rng();
- assert_eq!(r.gen_vec::<u8>(0u).len(), 0u);
- assert_eq!(r.gen_vec::<u8>(10u).len(), 10u);
- assert_eq!(r.gen_vec::<f64>(16u).len(), 16u);
- }
-
- #[test]
- fn test_choose() {
- let mut r = task_rng();
- assert_eq!(r.choose([1, 1, 1]).map(|&x|x), Some(1));
-
- let v: &[int] = &[];
- assert_eq!(r.choose(v), None);
- }
-
- #[test]
- fn test_shuffle() {
- let mut r = task_rng();
- let empty: &mut [int] = &mut [];
- r.shuffle(empty);
- let mut one = [1];
- r.shuffle(one);
- assert_eq!(one.as_slice(), &[1]);
-
- let mut two = [1, 2];
- r.shuffle(two);
- assert!(two == [1, 2] || two == [2, 1]);
-
- let mut x = [1, 1, 1];
- r.shuffle(x);
- assert_eq!(x.as_slice(), &[1, 1, 1]);
- }
-
- #[test]
- fn test_task_rng() {
- let mut r = task_rng();
- r.gen::<int>();
- let mut v = [1, 1, 1];
- r.shuffle(v);
- assert_eq!(v.as_slice(), &[1, 1, 1]);
- assert_eq!(r.gen_range(0u, 1u), 0u);
- }
-
- #[test]
- fn test_random() {
- // not sure how to test this aside from just getting some values
- let _n : uint = random();
- let _f : f32 = random();
- let _o : Option<Option<i8>> = random();
- let _many : ((),
- (Box<uint>,
- @int,
- Box<Option<Box<(@u32, Box<(@bool,)>)>>>),
- (u8, i8, u16, i16, u32, i32, u64, i64),
- (f32, (f64, (f64,)))) = random();
- }
-
- #[test]
- fn test_sample() {
- let min_val = 1;
- let max_val = 100;
-
- let mut r = task_rng();
- let vals = range(min_val, max_val).collect::<Vec<int>>();
- let small_sample = r.sample(vals.iter(), 5);
- let large_sample = r.sample(vals.iter(), vals.len() + 5);
-
- assert_eq!(small_sample.len(), 5);
- assert_eq!(large_sample.len(), vals.len());
-
- assert!(small_sample.iter().all(|e| {
- **e >= min_val && **e <= max_val
- }));
- }
-
- #[test]
- fn test_std_rng_seeded() {
- let s = task_rng().gen_vec::<uint>(256);
- let mut ra: StdRng = SeedableRng::from_seed(s.as_slice());
- let mut rb: StdRng = SeedableRng::from_seed(s.as_slice());
- assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
- }
-
- #[test]
- fn test_std_rng_reseed() {
- let s = task_rng().gen_vec::<uint>(256);
- let mut r: StdRng = SeedableRng::from_seed(s.as_slice());
- let string1 = r.gen_ascii_str(100);
-
- r.reseed(s.as_slice());
-
- let string2 = r.gen_ascii_str(100);
- assert_eq!(string1, string2);
- }
+#[cfg(not(test))]
+mod std {
+ pub use core::{option, fmt}; // fail!()
}
#[cfg(test)]
-static RAND_BENCH_N: u64 = 100;
-
-#[cfg(test)]
-mod bench {
- extern crate test;
- use self::test::Bencher;
- use {XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng, RAND_BENCH_N};
- use std::mem::size_of;
-
- #[bench]
- fn rand_xorshift(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
- b.iter(|| {
- for _ in range(0, RAND_BENCH_N) {
- rng.gen::<uint>();
- }
- });
- b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
- }
+mod test {
+ use std::rand;
- #[bench]
- fn rand_isaac(b: &mut Bencher) {
- let mut rng = IsaacRng::new().unwrap();
- b.iter(|| {
- for _ in range(0, RAND_BENCH_N) {
- rng.gen::<uint>();
- }
- });
- b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
- }
+ pub struct MyRng<R> { inner: R }
- #[bench]
- fn rand_isaac64(b: &mut Bencher) {
- let mut rng = Isaac64Rng::new().unwrap();
- b.iter(|| {
- for _ in range(0, RAND_BENCH_N) {
- rng.gen::<uint>();
+ impl<R: rand::Rng> ::Rng for MyRng<R> {
+ fn next_u32(&mut self) -> u32 {
+ fn next<T: rand::Rng>(t: &mut T) -> u32 {
+ use std::rand::Rng;
+ t.next_u32()
}
- });
- b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
+ next(&mut self.inner)
+ }
}
- #[bench]
- fn rand_std(b: &mut Bencher) {
- let mut rng = StdRng::new().unwrap();
- b.iter(|| {
- for _ in range(0, RAND_BENCH_N) {
- rng.gen::<uint>();
- }
- });
- b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
+ pub fn rng() -> MyRng<rand::TaskRng> {
+ MyRng { inner: rand::task_rng() }
}
- #[bench]
- fn rand_shuffle_100(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
- let x : &mut[uint] = [1,..100];
- b.iter(|| {
- rng.shuffle(x);
- })
+ pub fn weak_rng() -> MyRng<rand::XorShiftRng> {
+ MyRng { inner: rand::weak_rng() }
}
}
+++ /dev/null
-// 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.
-
-//! Interfaces to the operating system provided random number
-//! generators.
-
-pub use self::imp::OSRng;
-
-#[cfg(unix)]
-mod imp {
- use Rng;
- use reader::ReaderRng;
- use std::io::{IoResult, File};
-
- /// A random number generator that retrieves randomness straight from
- /// the operating system. Platform sources:
- ///
- /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
- /// `/dev/urandom`.
- /// - Windows: calls `CryptGenRandom`, using the default cryptographic
- /// service provider with the `PROV_RSA_FULL` type.
- ///
- /// This does not block.
- #[cfg(unix)]
- pub struct OSRng {
- inner: ReaderRng<File>
- }
-
- impl OSRng {
- /// Create a new `OSRng`.
- pub fn new() -> IoResult<OSRng> {
- let reader = try!(File::open(&Path::new("/dev/urandom")));
- let reader_rng = ReaderRng::new(reader);
-
- Ok(OSRng { inner: reader_rng })
- }
- }
-
- impl Rng for OSRng {
- fn next_u32(&mut self) -> u32 {
- self.inner.next_u32()
- }
- fn next_u64(&mut self) -> u64 {
- self.inner.next_u64()
- }
- fn fill_bytes(&mut self, v: &mut [u8]) {
- self.inner.fill_bytes(v)
- }
- }
-}
-
-#[cfg(windows)]
-mod imp {
- extern crate libc;
-
- use Rng;
- use std::io::{IoResult, IoError};
- use std::mem;
- use std::os;
- use std::rt::stack;
- use self::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
-
- type HCRYPTPROV = c_ulong;
-
- /// A random number generator that retrieves randomness straight from
- /// the operating system. Platform sources:
- ///
- /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
- /// `/dev/urandom`.
- /// - Windows: calls `CryptGenRandom`, using the default cryptographic
- /// service provider with the `PROV_RSA_FULL` type.
- ///
- /// This does not block.
- pub struct OSRng {
- hcryptprov: HCRYPTPROV
- }
-
- static PROV_RSA_FULL: DWORD = 1;
- static CRYPT_SILENT: DWORD = 64;
- static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
- static NTE_BAD_SIGNATURE: DWORD = 0x80090006;
-
- extern "system" {
- fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
- pszContainer: LPCSTR,
- pszProvider: LPCSTR,
- dwProvType: DWORD,
- dwFlags: DWORD) -> BOOL;
- fn CryptGenRandom(hProv: HCRYPTPROV,
- dwLen: DWORD,
- pbBuffer: *mut BYTE) -> BOOL;
- fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
- }
-
- impl OSRng {
- /// Create a new `OSRng`.
- pub fn new() -> IoResult<OSRng> {
- let mut hcp = 0;
- let mut ret = unsafe {
- CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
- PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
- };
-
- // FIXME #13259:
- // It turns out that if we can't acquire a context with the
- // NTE_BAD_SIGNATURE error code, the documentation states:
- //
- // The provider DLL signature could not be verified. Either the
- // DLL or the digital signature has been tampered with.
- //
- // Sounds fishy, no? As it turns out, our signature can be bad
- // because our Thread Information Block (TIB) isn't exactly what it
- // expects. As to why, I have no idea. The only data we store in the
- // TIB is the stack limit for each thread, but apparently that's
- // enough to make the signature valid.
- //
- // Furthermore, this error only happens the *first* time we call
- // CryptAcquireContext, so we don't have to worry about future
- // calls.
- //
- // Anyway, the fix employed here is that if we see this error, we
- // pray that we're not close to the end of the stack, temporarily
- // set the stack limit to 0 (what the TIB originally was), acquire a
- // context, and then reset the stack limit.
- //
- // Again, I'm not sure why this is the fix, nor why we're getting
- // this error. All I can say is that this seems to allow libnative
- // to progress where it otherwise would be hindered. Who knew?
- if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
- unsafe {
- let limit = stack::get_sp_limit();
- stack::record_sp_limit(0);
- ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
- PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
- stack::record_sp_limit(limit);
- }
- }
-
- if ret == 0 {
- Err(IoError::last_error())
- } else {
- Ok(OSRng { hcryptprov: hcp })
- }
- }
- }
-
- impl Rng for OSRng {
- fn next_u32(&mut self) -> u32 {
- let mut v = [0u8, .. 4];
- self.fill_bytes(v);
- unsafe { mem::transmute(v) }
- }
- fn next_u64(&mut self) -> u64 {
- let mut v = [0u8, .. 8];
- self.fill_bytes(v);
- unsafe { mem::transmute(v) }
- }
- fn fill_bytes(&mut self, v: &mut [u8]) {
- let ret = unsafe {
- CryptGenRandom(self.hcryptprov, v.len() as DWORD,
- v.as_mut_ptr())
- };
- if ret == 0 {
- fail!("couldn't generate random bytes: {}", os::last_os_error());
- }
- }
- }
-
- impl Drop for OSRng {
- fn drop(&mut self) {
- let ret = unsafe {
- CryptReleaseContext(self.hcryptprov, 0)
- };
- if ret == 0 {
- fail!("couldn't release context: {}", os::last_os_error());
- }
- }
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::OSRng;
- use Rng;
- use std::task;
-
- #[test]
- fn test_os_rng() {
- let mut r = OSRng::new().unwrap();
-
- r.next_u32();
- r.next_u64();
-
- let mut v = [0u8, .. 1000];
- r.fill_bytes(v);
- }
-
- #[test]
- fn test_os_rng_tasks() {
-
- let mut txs = vec!();
- for _ in range(0, 20) {
- let (tx, rx) = channel();
- txs.push(tx);
- task::spawn(proc() {
- // wait until all the tasks are ready to go.
- rx.recv();
-
- // deschedule to attempt to interleave things as much
- // as possible (XXX: is this a good test?)
- let mut r = OSRng::new().unwrap();
- task::deschedule();
- let mut v = [0u8, .. 1000];
-
- for _ in range(0, 100) {
- r.next_u32();
- task::deschedule();
- r.next_u64();
- task::deschedule();
- r.fill_bytes(v);
- task::deschedule();
- }
- })
- }
-
- // start all the tasks
- for tx in txs.iter() {
- tx.send(())
- }
- }
-}
//! The implementations of `Rand` for the built-in types.
-use std::char;
-use std::int;
-use std::uint;
+use core::prelude::*;
+use core::char;
+use core::int;
+use core::uint;
use {Rand,Rng};
}
}
-impl<T: Rand> Rand for Box<T> {
- #[inline]
- fn rand<R: Rng>(rng: &mut R) -> Box<T> { box rng.gen() }
-}
-
-impl<T: Rand + 'static> Rand for @T {
- #[inline]
- fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
-}
-
#[cfg(test)]
mod tests {
- use {Rng, task_rng, Open01, Closed01};
+ use std::prelude::*;
+ use std::rand::{Rng, task_rng, Open01, Closed01};
struct ConstantRng(u64);
impl Rng for ConstantRng {
+++ /dev/null
-// 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.
-
-//! A wrapper around any Reader to treat it as an RNG.
-
-use Rng;
-
-/// An RNG that reads random bytes straight from a `Reader`. This will
-/// work best with an infinite reader, but this is not required.
-///
-/// It will fail if it there is insufficient data to fulfill a request.
-///
-/// # Example
-///
-/// ```rust
-/// use rand::{reader, Rng};
-/// use std::io::MemReader;
-///
-/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
-/// println!("{:x}", rng.gen::<uint>());
-/// ```
-pub struct ReaderRng<R> {
- reader: R
-}
-
-impl<R: Reader> ReaderRng<R> {
- /// Create a new `ReaderRng` from a `Reader`.
- pub fn new(r: R) -> ReaderRng<R> {
- ReaderRng {
- reader: r
- }
- }
-}
-
-impl<R: Reader> Rng for ReaderRng<R> {
- fn next_u32(&mut self) -> u32 {
- // This is designed for speed: reading a LE integer on a LE
- // platform just involves blitting the bytes into the memory
- // of the u32, similarly for BE on BE; avoiding byteswapping.
- if cfg!(target_endian="little") {
- self.reader.read_le_u32().unwrap()
- } else {
- self.reader.read_be_u32().unwrap()
- }
- }
- fn next_u64(&mut self) -> u64 {
- // see above for explanation.
- if cfg!(target_endian="little") {
- self.reader.read_le_u64().unwrap()
- } else {
- self.reader.read_be_u64().unwrap()
- }
- }
- fn fill_bytes(&mut self, v: &mut [u8]) {
- if v.len() == 0 { return }
- match self.reader.read_at_least(v.len(), v) {
- Ok(_) => {}
- Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
- }
- }
-}
-
-#[cfg(test)]
-#[allow(deprecated_owned_vector)]
-mod test {
- use super::ReaderRng;
- use std::io::MemReader;
- use std::mem;
- use Rng;
-
- #[test]
- fn test_reader_rng_u64() {
- // transmute from the target to avoid endianness concerns.
- let v = box [1u64, 2u64, 3u64];
- let bytes: ~[u8] = unsafe {mem::transmute(v)};
- let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));
-
- assert_eq!(rng.next_u64(), 1);
- assert_eq!(rng.next_u64(), 2);
- assert_eq!(rng.next_u64(), 3);
- }
- #[test]
- fn test_reader_rng_u32() {
- // transmute from the target to avoid endianness concerns.
- let v = box [1u32, 2u32, 3u32];
- let bytes: ~[u8] = unsafe {mem::transmute(v)};
- let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));
-
- assert_eq!(rng.next_u32(), 1);
- assert_eq!(rng.next_u32(), 2);
- assert_eq!(rng.next_u32(), 3);
- }
- #[test]
- fn test_reader_rng_fill_bytes() {
- let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
- let mut w = [0u8, .. 8];
-
- let mut rng = ReaderRng::new(MemReader::new(Vec::from_slice(v)));
- rng.fill_bytes(w);
-
- assert!(v == w);
- }
-
- #[test]
- #[should_fail]
- fn test_reader_rng_insufficient_bytes() {
- let mut rng = ReaderRng::new(MemReader::new(vec!()));
- let mut v = [0u8, .. 3];
- rng.fill_bytes(v);
- }
-}
//! A wrapper around another RNG that reseeds it after it
//! generates a certain number of random bytes.
-use std::default::Default;
+use core::prelude::*;
+
use {Rng, SeedableRng};
+use core::default::Default;
/// How many bytes of entropy the underling RNG is allowed to generate
/// before it is reseeded.
}
}
-impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R>>
+impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default>
SeedableRng<(Rsdr, S)> for ReseedingRng<R, Rsdr> {
fn reseed(&mut self, (rsdr, seed): (Rsdr, S)) {
self.rng.reseed(seed);
self.reseeder = rsdr;
self.bytes_generated = 0;
}
+
/// Create a new `ReseedingRng` from the given reseeder and
/// seed. This uses a default value for `generation_threshold`.
fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
/// # Example
///
/// ```rust
-/// use rand::{Rng, SeedableRng, StdRng};
-/// use rand::reseeding::{Reseeder, ReseedingRng};
+/// use std::rand::{Rng, SeedableRng, StdRng};
+/// use std::rand::reseeding::{Reseeder, ReseedingRng};
///
/// struct TickTockReseeder { tick: bool }
/// impl Reseeder<StdRng> for TickTockReseeder {
/// let mut rng = ReseedingRng::new(inner, 10, rsdr);
///
/// // this will repeat, because it gets reseeded very regularly.
-/// println!("{}", rng.gen_ascii_str(100));
+/// let s: String = rng.gen_ascii_chars().take(100).collect();
+/// println!("{}", s);
/// }
///
/// ```
#[cfg(test)]
mod test {
+ use std::prelude::*;
+
+ use core::iter::order;
use super::{ReseedingRng, ReseedWithDefault};
use std::default::Default;
use {SeedableRng, Rng};
fn test_rng_seeded() {
let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
- assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
+ assert!(order::equals(ra.gen_ascii_chars().take(100),
+ rb.gen_ascii_chars().take(100)));
}
#[test]
fn test_rng_reseed() {
let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3));
- let string1 = r.gen_ascii_str(100);
+ let string1: String = r.gen_ascii_chars().take(100).collect();
r.reseed((ReseedWithDefault, 3));
- let string2 = r.gen_ascii_str(100);
+ let string2: String = r.gen_ascii_chars().take(100).collect();
assert_eq!(string1, string2);
}
static fill_bytes_v_len: uint = 13579;
#[test]
fn test_rng_fill_bytes() {
- use task_rng;
let mut v = Vec::from_elem(fill_bytes_v_len, 0u8);
- task_rng().fill_bytes(v.as_mut_slice());
+ ::test::rng().fill_bytes(v.as_mut_slice());
// Sanity test: if we've gotten here, `fill_bytes` has not infinitely
// recursed.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use rand::{Rng, task_rng};
-use stdtest::Bencher;
+use std::rand::{Rng, task_rng};
use std::str;
+use stdtest::Bencher;
+
use regex::{Regex, NoExpand};
fn bench_assert_match(b: &mut Bencher, re: Regex, text: &str) {
fn medium() -> Regex { regex!("[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$") }
fn hard() -> Regex { regex!("[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$") }
-#[allow(deprecated_owned_vector)]
fn gen_text(n: uint) -> String {
let mut rng = task_rng();
- let mut bytes = rng.gen_ascii_str(n).into_bytes();
+ let mut bytes = rng.gen_ascii_chars().map(|n| n as u8).take(n)
+ .collect::<Vec<u8>>();
for (i, b) in bytes.mut_iter().enumerate() {
if i % 20 == 0 {
*b = '\n' as u8
#[cfg(test)]
mod tests {
extern crate test;
- extern crate rand;
use self::test::Bencher;
use base64::{Config, FromBase64, ToBase64, STANDARD, URL_SAFE};
#[test]
fn test_base64_random() {
- use self::rand::{task_rng, random, Rng};
+ use std::rand::{task_rng, random, Rng};
for _ in range(0, 1000) {
let times = task_rng().gen_range(1u, 100);
#[cfg(test)] extern crate debug;
#[cfg(test)] #[phase(syntax, link)] extern crate log;
-// Make and rand accessible for benchmarking/testcases
-#[cfg(test)] extern crate rand;
-
extern crate alloc;
extern crate core;
extern crate libc;
+extern crate core_rand = "rand";
// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate realstd = "std";
pub mod vec;
pub mod str;
pub mod string;
+pub mod rand;
pub mod ascii;
mod uint {
use super::test::Bencher;
- use rand::{XorShiftRng, Rng};
+ use rand::{weak_rng, Rng};
use num::ToStrRadix;
#[bench]
fn to_str_bin(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { rng.gen::<uint>().to_str_radix(2); })
}
#[bench]
fn to_str_oct(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { rng.gen::<uint>().to_str_radix(8); })
}
#[bench]
fn to_str_dec(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { rng.gen::<uint>().to_str_radix(10); })
}
#[bench]
fn to_str_hex(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { rng.gen::<uint>().to_str_radix(16); })
}
#[bench]
fn to_str_base_36(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { rng.gen::<uint>().to_str_radix(36); })
}
}
mod int {
use super::test::Bencher;
- use rand::{XorShiftRng, Rng};
+ use rand::{weak_rng, Rng};
use num::ToStrRadix;
#[bench]
fn to_str_bin(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { rng.gen::<int>().to_str_radix(2); })
}
#[bench]
fn to_str_oct(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { rng.gen::<int>().to_str_radix(8); })
}
#[bench]
fn to_str_dec(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { rng.gen::<int>().to_str_radix(10); })
}
#[bench]
fn to_str_hex(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { rng.gen::<int>().to_str_radix(16); })
}
#[bench]
fn to_str_base_36(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { rng.gen::<int>().to_str_radix(36); })
}
}
mod f64 {
use super::test::Bencher;
- use rand::{XorShiftRng, Rng};
+ use rand::{weak_rng, Rng};
use f64;
#[bench]
fn float_to_str(b: &mut Bencher) {
- let mut rng = XorShiftRng::new().unwrap();
+ let mut rng = weak_rng();
b.iter(|| { f64::to_str(rng.gen()); })
}
}
fn make_rand_name() -> String {
let mut rng = rand::task_rng();
- let n = format!("TEST{}", rng.gen_ascii_str(10u).as_slice());
+ let n = format!("TEST{}", rng.gen_ascii_chars().take(10u)
+ .collect::<String>());
assert!(getenv(n.as_slice()).is_none());
n
}
--- /dev/null
+// 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.
+
+/*!
+
+Utilities for random number generation
+
+The key functions are `random()` and `Rng::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::<f64>()`.
+
+See the `distributions` submodule for sampling random numbers from
+distributions like normal and exponential.
+
+# Task-local RNG
+
+There is built-in support for a RNG associated with each task stored
+in task-local storage. This RNG can be accessed via `task_rng`, or
+used implicitly via `random`. This RNG is normally randomly seeded
+from an operating-system source of randomness, e.g. `/dev/urandom` on
+Unix systems, and will automatically reseed itself from this source
+after generating 32 KiB of random data.
+
+# Cryptographic security
+
+An application that requires an entropy source for cryptographic purposes
+must use `OSRng`, which reads randomness from the source that the operating
+system provides (e.g. `/dev/urandom` on Unixes or `CryptGenRandom()` on Windows).
+The other random number generators provided by this module are not suitable
+for such purposes.
+
+*Note*: many Unix systems provide `/dev/random` as well as `/dev/urandom`.
+This module uses `/dev/urandom` for the following reasons:
+
+- On Linux, `/dev/random` may block if entropy pool is empty; `/dev/urandom` will not block.
+ This does not mean that `/dev/random` provides better output than
+ `/dev/urandom`; the kernel internally runs a cryptographically secure pseudorandom
+ number generator (CSPRNG) based on entropy pool for random number generation,
+ so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
+ However, this means that `/dev/urandom` can yield somewhat predictable randomness
+ if the entropy pool is very small, such as immediately after first booting.
+ If an application likely to be run soon after first booting, or on a system with very
+ few entropy sources, one should consider using `/dev/random` via `ReaderRng`.
+- On some systems (e.g. FreeBSD, OpenBSD and Mac OS X) there is no difference
+ between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random`
+ and `/dev/urandom` may block once if the CSPRNG has not seeded yet.)
+
+# Examples
+
+```rust
+use std::rand;
+use std::rand::Rng;
+
+let mut rng = rand::task_rng();
+if rng.gen() { // bool
+ println!("int: {}, uint: {}", rng.gen::<int>(), rng.gen::<uint>())
+}
+```
+
+```rust
+use std::rand;
+
+let tuple = rand::random::<(f64, char)>();
+println!("{}", tuple)
+```
+*/
+
+use cell::RefCell;
+use clone::Clone;
+use io::IoResult;
+use iter::Iterator;
+use mem;
+use option::{Some, None};
+use rc::Rc;
+use result::{Ok, Err};
+use vec::Vec;
+
+#[cfg(not(target_word_size="64"))]
+use IsaacWordRng = core_rand::IsaacRng;
+#[cfg(target_word_size="64")]
+use IsaacWordRng = core_rand::Isaac64Rng;
+
+pub use core_rand::{Rand, Rng, SeedableRng, Open01, Closed01};
+pub use core_rand::{XorShiftRng, IsaacRng, Isaac64Rng};
+pub use core_rand::{distributions, reseeding};
+pub use rand::os::OSRng;
+
+pub mod os;
+pub mod reader;
+
+/// The standard RNG. This is designed to be efficient on the current
+/// platform.
+pub struct StdRng { rng: IsaacWordRng }
+
+impl StdRng {
+ /// Create a randomly seeded instance of `StdRng`.
+ ///
+ /// This is a very expensive operation as it has to read
+ /// randomness from the operating system and use this in an
+ /// expensive seeding operation. If one is only generating a small
+ /// number of random numbers, or doesn't need the utmost speed for
+ /// generating each number, `task_rng` and/or `random` may be more
+ /// appropriate.
+ ///
+ /// Reading the randomness from the OS may fail, and any error is
+ /// propagated via the `IoResult` return value.
+ pub fn new() -> IoResult<StdRng> {
+ OSRng::new().map(|mut r| StdRng { rng: r.gen() })
+ }
+}
+
+impl Rng for StdRng {
+ #[inline]
+ fn next_u32(&mut self) -> u32 {
+ self.rng.next_u32()
+ }
+
+ #[inline]
+ fn next_u64(&mut self) -> u64 {
+ self.rng.next_u64()
+ }
+}
+
+impl<'a> SeedableRng<&'a [uint]> for StdRng {
+ fn reseed(&mut self, seed: &'a [uint]) {
+ // the internal RNG can just be seeded from the above
+ // randomness.
+ self.rng.reseed(unsafe {mem::transmute(seed)})
+ }
+
+ fn from_seed(seed: &'a [uint]) -> StdRng {
+ StdRng { rng: SeedableRng::from_seed(unsafe {mem::transmute(seed)}) }
+ }
+}
+
+/// Create a weak random number generator with a default algorithm and seed.
+///
+/// It returns the fastest `Rng` algorithm currently available in Rust without
+/// consideration for cryptography or security. If you require a specifically
+/// seeded `Rng` for consistency over time you should pick one algorithm and
+/// create the `Rng` yourself.
+///
+/// This will read randomness from the operating system to seed the
+/// generator.
+pub fn weak_rng() -> XorShiftRng {
+ match OSRng::new() {
+ Ok(mut r) => r.gen(),
+ Err(e) => fail!("weak_rng: failed to create seeded RNG: {}", e)
+ }
+}
+
+/// Controls how the task-local RNG is reseeded.
+struct TaskRngReseeder;
+
+impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
+ fn reseed(&mut self, rng: &mut StdRng) {
+ *rng = match StdRng::new() {
+ Ok(r) => r,
+ Err(e) => fail!("could not reseed task_rng: {}", e)
+ }
+ }
+}
+static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
+type TaskRngInner = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
+
+/// The task-local RNG.
+pub struct TaskRng {
+ rng: Rc<RefCell<TaskRngInner>>,
+}
+
+/// Retrieve the lazily-initialized task-local random number
+/// generator, seeded by the system. Intended to be used in method
+/// chaining style, e.g. `task_rng().gen::<int>()`.
+///
+/// The RNG provided will reseed itself from the operating system
+/// after generating a certain amount of randomness.
+///
+/// The internal RNG used is platform and architecture dependent, even
+/// if the operating system random number generator is rigged to give
+/// the same sequence always. If absolute consistency is required,
+/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
+pub fn task_rng() -> TaskRng {
+ // used to make space in TLS for a random number generator
+ local_data_key!(TASK_RNG_KEY: Rc<RefCell<TaskRngInner>>)
+
+ match TASK_RNG_KEY.get() {
+ None => {
+ let r = match StdRng::new() {
+ Ok(r) => r,
+ Err(e) => fail!("could not initialize task_rng: {}", e)
+ };
+ let rng = reseeding::ReseedingRng::new(r,
+ TASK_RNG_RESEED_THRESHOLD,
+ TaskRngReseeder);
+ let rng = Rc::new(RefCell::new(rng));
+ TASK_RNG_KEY.replace(Some(rng.clone()));
+
+ TaskRng { rng: rng }
+ }
+ Some(rng) => TaskRng { rng: rng.clone() }
+ }
+}
+
+impl Rng for TaskRng {
+ fn next_u32(&mut self) -> u32 {
+ self.rng.borrow_mut().next_u32()
+ }
+
+ fn next_u64(&mut self) -> u64 {
+ self.rng.borrow_mut().next_u64()
+ }
+
+ #[inline]
+ fn fill_bytes(&mut self, bytes: &mut [u8]) {
+ self.rng.borrow_mut().fill_bytes(bytes)
+ }
+}
+
+/// Generate a random value using the task-local random number
+/// generator.
+///
+/// # Example
+///
+/// ```rust
+/// use std::rand::random;
+///
+/// if random() {
+/// let x = random();
+/// println!("{}", 2u * x);
+/// } else {
+/// println!("{}", random::<f64>());
+/// }
+/// ```
+#[inline]
+pub fn random<T: Rand>() -> T {
+ task_rng().gen()
+}
+
+/// Randomly sample up to `n` elements from an iterator.
+///
+/// # Example
+///
+/// ```rust
+/// use std::rand::{task_rng, sample};
+///
+/// let mut rng = task_rng();
+/// let sample = sample(&mut rng, range(1, 100), 5);
+/// println!("{}", sample);
+/// ```
+pub fn sample<T, I: Iterator<T>, R: Rng>(rng: &mut R,
+ mut iter: I,
+ amt: uint) -> Vec<T> {
+ let mut reservoir: Vec<T> = iter.by_ref().take(amt).collect();
+ for (i, elem) in iter.enumerate() {
+ let k = rng.gen_range(0, i + 1 + amt);
+ if k < amt {
+ *reservoir.get_mut(k) = elem;
+ }
+ }
+ return reservoir;
+}
+
+#[cfg(test)]
+mod test {
+ use prelude::*;
+ use super::{Rng, task_rng, random, SeedableRng, StdRng, sample};
+ use iter::order;
+
+ struct ConstRng { i: u64 }
+ impl Rng for ConstRng {
+ fn next_u32(&mut self) -> u32 { self.i as u32 }
+ fn next_u64(&mut self) -> u64 { self.i }
+
+ // no fill_bytes on purpose
+ }
+
+ #[test]
+ fn test_fill_bytes_default() {
+ let mut r = ConstRng { i: 0x11_22_33_44_55_66_77_88 };
+
+ // check every remainder mod 8, both in small and big vectors.
+ let lengths = [0, 1, 2, 3, 4, 5, 6, 7,
+ 80, 81, 82, 83, 84, 85, 86, 87];
+ for &n in lengths.iter() {
+ let mut v = Vec::from_elem(n, 0u8);
+ r.fill_bytes(v.as_mut_slice());
+
+ // use this to get nicer error messages.
+ for (i, &byte) in v.iter().enumerate() {
+ if byte == 0 {
+ fail!("byte {} of {} is zero", i, n)
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_gen_range() {
+ let mut r = task_rng();
+ for _ in range(0, 1000) {
+ let a = r.gen_range(-3i, 42);
+ assert!(a >= -3 && a < 42);
+ assert_eq!(r.gen_range(0, 1), 0);
+ assert_eq!(r.gen_range(-12, -11), -12);
+ }
+
+ for _ in range(0, 1000) {
+ let a = r.gen_range(10, 42);
+ assert!(a >= 10 && a < 42);
+ assert_eq!(r.gen_range(0, 1), 0);
+ assert_eq!(r.gen_range(3_000_000u, 3_000_001), 3_000_000);
+ }
+
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_gen_range_fail_int() {
+ let mut r = task_rng();
+ r.gen_range(5i, -2);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_gen_range_fail_uint() {
+ let mut r = task_rng();
+ r.gen_range(5u, 2u);
+ }
+
+ #[test]
+ fn test_gen_f64() {
+ let mut r = task_rng();
+ let a = r.gen::<f64>();
+ let b = r.gen::<f64>();
+ debug!("{}", (a, b));
+ }
+
+ #[test]
+ fn test_gen_weighted_bool() {
+ let mut r = task_rng();
+ assert_eq!(r.gen_weighted_bool(0u), true);
+ assert_eq!(r.gen_weighted_bool(1u), true);
+ }
+
+ #[test]
+ fn test_gen_ascii_str() {
+ let mut r = task_rng();
+ assert_eq!(r.gen_ascii_chars().take(0).len(), 0u);
+ assert_eq!(r.gen_ascii_chars().take(10).len(), 10u);
+ assert_eq!(r.gen_ascii_chars().take(16).len(), 16u);
+ }
+
+ #[test]
+ fn test_gen_vec() {
+ let mut r = task_rng();
+ assert_eq!(r.gen_iter::<u8>().take(0).len(), 0u);
+ assert_eq!(r.gen_iter::<u8>().take(10).len(), 10u);
+ assert_eq!(r.gen_iter::<f64>().take(16).len(), 16u);
+ }
+
+ #[test]
+ fn test_choose() {
+ let mut r = task_rng();
+ assert_eq!(r.choose([1, 1, 1]).map(|&x|x), Some(1));
+
+ let v: &[int] = &[];
+ assert_eq!(r.choose(v), None);
+ }
+
+ #[test]
+ fn test_shuffle() {
+ let mut r = task_rng();
+ let empty: &mut [int] = &mut [];
+ r.shuffle(empty);
+ let mut one = [1];
+ r.shuffle(one);
+ assert_eq!(one.as_slice(), &[1]);
+
+ let mut two = [1, 2];
+ r.shuffle(two);
+ assert!(two == [1, 2] || two == [2, 1]);
+
+ let mut x = [1, 1, 1];
+ r.shuffle(x);
+ assert_eq!(x.as_slice(), &[1, 1, 1]);
+ }
+
+ #[test]
+ fn test_task_rng() {
+ let mut r = task_rng();
+ r.gen::<int>();
+ let mut v = [1, 1, 1];
+ r.shuffle(v);
+ assert_eq!(v.as_slice(), &[1, 1, 1]);
+ assert_eq!(r.gen_range(0u, 1u), 0u);
+ }
+
+ #[test]
+ fn test_random() {
+ // not sure how to test this aside from just getting some values
+ let _n : uint = random();
+ let _f : f32 = random();
+ let _o : Option<Option<i8>> = random();
+ let _many : ((),
+ (uint,
+ int,
+ Option<(u32, (bool,))>),
+ (u8, i8, u16, i16, u32, i32, u64, i64),
+ (f32, (f64, (f64,)))) = random();
+ }
+
+ #[test]
+ fn test_sample() {
+ let min_val = 1;
+ let max_val = 100;
+
+ let mut r = task_rng();
+ let vals = range(min_val, max_val).collect::<Vec<int>>();
+ let small_sample = sample(&mut r, vals.iter(), 5);
+ let large_sample = sample(&mut r, vals.iter(), vals.len() + 5);
+
+ assert_eq!(small_sample.len(), 5);
+ assert_eq!(large_sample.len(), vals.len());
+
+ assert!(small_sample.iter().all(|e| {
+ **e >= min_val && **e <= max_val
+ }));
+ }
+
+ #[test]
+ fn test_std_rng_seeded() {
+ let s = task_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>();
+ let mut ra: StdRng = SeedableRng::from_seed(s.as_slice());
+ let mut rb: StdRng = SeedableRng::from_seed(s.as_slice());
+ assert!(order::equals(ra.gen_ascii_chars().take(100),
+ rb.gen_ascii_chars().take(100)));
+ }
+
+ #[test]
+ fn test_std_rng_reseed() {
+ let s = task_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>();
+ let mut r: StdRng = SeedableRng::from_seed(s.as_slice());
+ let string1 = r.gen_ascii_chars().take(100).collect::<String>();
+
+ r.reseed(s.as_slice());
+
+ let string2 = r.gen_ascii_chars().take(100).collect::<String>();
+ assert_eq!(string1, string2);
+ }
+}
+
+#[cfg(test)]
+static RAND_BENCH_N: u64 = 100;
+
+#[cfg(test)]
+mod bench {
+ extern crate test;
+ use prelude::*;
+
+ use self::test::Bencher;
+ use super::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng, RAND_BENCH_N};
+ use super::{OSRng, weak_rng};
+ use mem::size_of;
+
+ #[bench]
+ fn rand_xorshift(b: &mut Bencher) {
+ let mut rng: XorShiftRng = OSRng::new().unwrap().gen();
+ b.iter(|| {
+ for _ in range(0, RAND_BENCH_N) {
+ rng.gen::<uint>();
+ }
+ });
+ b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
+ }
+
+ #[bench]
+ fn rand_isaac(b: &mut Bencher) {
+ let mut rng: IsaacRng = OSRng::new().unwrap().gen();
+ b.iter(|| {
+ for _ in range(0, RAND_BENCH_N) {
+ rng.gen::<uint>();
+ }
+ });
+ b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
+ }
+
+ #[bench]
+ fn rand_isaac64(b: &mut Bencher) {
+ let mut rng: Isaac64Rng = OSRng::new().unwrap().gen();
+ b.iter(|| {
+ for _ in range(0, RAND_BENCH_N) {
+ rng.gen::<uint>();
+ }
+ });
+ b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
+ }
+
+ #[bench]
+ fn rand_std(b: &mut Bencher) {
+ let mut rng = StdRng::new().unwrap();
+ b.iter(|| {
+ for _ in range(0, RAND_BENCH_N) {
+ rng.gen::<uint>();
+ }
+ });
+ b.bytes = size_of::<uint>() as u64 * RAND_BENCH_N;
+ }
+
+ #[bench]
+ fn rand_shuffle_100(b: &mut Bencher) {
+ let mut rng = weak_rng();
+ let x : &mut[uint] = [1,..100];
+ b.iter(|| {
+ rng.shuffle(x);
+ })
+ }
+}
--- /dev/null
+// 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.
+
+//! Interfaces to the operating system provided random number
+//! generators.
+
+pub use self::imp::OSRng;
+
+#[cfg(unix)]
+mod imp {
+ use io::{IoResult, File};
+ use path::Path;
+ use rand::Rng;
+ use rand::reader::ReaderRng;
+ use result::{Ok, Err};
+
+ /// A random number generator that retrieves randomness straight from
+ /// the operating system. Platform sources:
+ ///
+ /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
+ /// `/dev/urandom`.
+ /// - Windows: calls `CryptGenRandom`, using the default cryptographic
+ /// service provider with the `PROV_RSA_FULL` type.
+ ///
+ /// This does not block.
+ #[cfg(unix)]
+ pub struct OSRng {
+ inner: ReaderRng<File>
+ }
+
+ impl OSRng {
+ /// Create a new `OSRng`.
+ pub fn new() -> IoResult<OSRng> {
+ let reader = try!(File::open(&Path::new("/dev/urandom")));
+ let reader_rng = ReaderRng::new(reader);
+
+ Ok(OSRng { inner: reader_rng })
+ }
+ }
+
+ impl Rng for OSRng {
+ fn next_u32(&mut self) -> u32 {
+ self.inner.next_u32()
+ }
+ fn next_u64(&mut self) -> u64 {
+ self.inner.next_u64()
+ }
+ fn fill_bytes(&mut self, v: &mut [u8]) {
+ self.inner.fill_bytes(v)
+ }
+ }
+}
+
+#[cfg(windows)]
+mod imp {
+ extern crate libc;
+
+ use container::Container;
+ use io::{IoResult, IoError};
+ use mem;
+ use ops::Drop;
+ use os;
+ use rand::Rng;
+ use result::{Ok, Err};
+ use rt::stack;
+ use self::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
+ use slice::MutableVector;
+
+ type HCRYPTPROV = c_ulong;
+
+ /// A random number generator that retrieves randomness straight from
+ /// the operating system. Platform sources:
+ ///
+ /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
+ /// `/dev/urandom`.
+ /// - Windows: calls `CryptGenRandom`, using the default cryptographic
+ /// service provider with the `PROV_RSA_FULL` type.
+ ///
+ /// This does not block.
+ pub struct OSRng {
+ hcryptprov: HCRYPTPROV
+ }
+
+ static PROV_RSA_FULL: DWORD = 1;
+ static CRYPT_SILENT: DWORD = 64;
+ static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
+ static NTE_BAD_SIGNATURE: DWORD = 0x80090006;
+
+ extern "system" {
+ fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
+ pszContainer: LPCSTR,
+ pszProvider: LPCSTR,
+ dwProvType: DWORD,
+ dwFlags: DWORD) -> BOOL;
+ fn CryptGenRandom(hProv: HCRYPTPROV,
+ dwLen: DWORD,
+ pbBuffer: *mut BYTE) -> BOOL;
+ fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
+ }
+
+ impl OSRng {
+ /// Create a new `OSRng`.
+ pub fn new() -> IoResult<OSRng> {
+ let mut hcp = 0;
+ let mut ret = unsafe {
+ CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
+ PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
+ };
+
+ // FIXME #13259:
+ // It turns out that if we can't acquire a context with the
+ // NTE_BAD_SIGNATURE error code, the documentation states:
+ //
+ // The provider DLL signature could not be verified. Either the
+ // DLL or the digital signature has been tampered with.
+ //
+ // Sounds fishy, no? As it turns out, our signature can be bad
+ // because our Thread Information Block (TIB) isn't exactly what it
+ // expects. As to why, I have no idea. The only data we store in the
+ // TIB is the stack limit for each thread, but apparently that's
+ // enough to make the signature valid.
+ //
+ // Furthermore, this error only happens the *first* time we call
+ // CryptAcquireContext, so we don't have to worry about future
+ // calls.
+ //
+ // Anyway, the fix employed here is that if we see this error, we
+ // pray that we're not close to the end of the stack, temporarily
+ // set the stack limit to 0 (what the TIB originally was), acquire a
+ // context, and then reset the stack limit.
+ //
+ // Again, I'm not sure why this is the fix, nor why we're getting
+ // this error. All I can say is that this seems to allow libnative
+ // to progress where it otherwise would be hindered. Who knew?
+ if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
+ unsafe {
+ let limit = stack::get_sp_limit();
+ stack::record_sp_limit(0);
+ ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
+ PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
+ stack::record_sp_limit(limit);
+ }
+ }
+
+ if ret == 0 {
+ Err(IoError::last_error())
+ } else {
+ Ok(OSRng { hcryptprov: hcp })
+ }
+ }
+ }
+
+ impl Rng for OSRng {
+ fn next_u32(&mut self) -> u32 {
+ let mut v = [0u8, .. 4];
+ self.fill_bytes(v);
+ unsafe { mem::transmute(v) }
+ }
+ fn next_u64(&mut self) -> u64 {
+ let mut v = [0u8, .. 8];
+ self.fill_bytes(v);
+ unsafe { mem::transmute(v) }
+ }
+ fn fill_bytes(&mut self, v: &mut [u8]) {
+ let ret = unsafe {
+ CryptGenRandom(self.hcryptprov, v.len() as DWORD,
+ v.as_mut_ptr())
+ };
+ if ret == 0 {
+ fail!("couldn't generate random bytes: {}", os::last_os_error());
+ }
+ }
+ }
+
+ impl Drop for OSRng {
+ fn drop(&mut self) {
+ let ret = unsafe {
+ CryptReleaseContext(self.hcryptprov, 0)
+ };
+ if ret == 0 {
+ fail!("couldn't release context: {}", os::last_os_error());
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use prelude::*;
+
+ use super::OSRng;
+ use rand::Rng;
+ use task;
+
+ #[test]
+ fn test_os_rng() {
+ let mut r = OSRng::new().unwrap();
+
+ r.next_u32();
+ r.next_u64();
+
+ let mut v = [0u8, .. 1000];
+ r.fill_bytes(v);
+ }
+
+ #[test]
+ fn test_os_rng_tasks() {
+
+ let mut txs = vec!();
+ for _ in range(0, 20) {
+ let (tx, rx) = channel();
+ txs.push(tx);
+ task::spawn(proc() {
+ // wait until all the tasks are ready to go.
+ rx.recv();
+
+ // deschedule to attempt to interleave things as much
+ // as possible (XXX: is this a good test?)
+ let mut r = OSRng::new().unwrap();
+ task::deschedule();
+ let mut v = [0u8, .. 1000];
+
+ for _ in range(0, 100) {
+ r.next_u32();
+ task::deschedule();
+ r.next_u64();
+ task::deschedule();
+ r.fill_bytes(v);
+ task::deschedule();
+ }
+ })
+ }
+
+ // start all the tasks
+ for tx in txs.iter() {
+ tx.send(())
+ }
+ }
+}
--- /dev/null
+// 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.
+
+//! A wrapper around any Reader to treat it as an RNG.
+
+use container::Container;
+use io::Reader;
+use rand::Rng;
+use result::{Ok, Err};
+
+/// An RNG that reads random bytes straight from a `Reader`. This will
+/// work best with an infinite reader, but this is not required.
+///
+/// It will fail if it there is insufficient data to fulfill a request.
+///
+/// # Example
+///
+/// ```rust
+/// use std::rand::{reader, Rng};
+/// use std::io::MemReader;
+///
+/// let mut rng = reader::ReaderRng::new(MemReader::new(vec!(1,2,3,4,5,6,7,8)));
+/// println!("{:x}", rng.gen::<uint>());
+/// ```
+pub struct ReaderRng<R> {
+ reader: R
+}
+
+impl<R: Reader> ReaderRng<R> {
+ /// Create a new `ReaderRng` from a `Reader`.
+ pub fn new(r: R) -> ReaderRng<R> {
+ ReaderRng {
+ reader: r
+ }
+ }
+}
+
+impl<R: Reader> Rng for ReaderRng<R> {
+ fn next_u32(&mut self) -> u32 {
+ // This is designed for speed: reading a LE integer on a LE
+ // platform just involves blitting the bytes into the memory
+ // of the u32, similarly for BE on BE; avoiding byteswapping.
+ if cfg!(target_endian="little") {
+ self.reader.read_le_u32().unwrap()
+ } else {
+ self.reader.read_be_u32().unwrap()
+ }
+ }
+ fn next_u64(&mut self) -> u64 {
+ // see above for explanation.
+ if cfg!(target_endian="little") {
+ self.reader.read_le_u64().unwrap()
+ } else {
+ self.reader.read_be_u64().unwrap()
+ }
+ }
+ fn fill_bytes(&mut self, v: &mut [u8]) {
+ if v.len() == 0 { return }
+ match self.reader.read_at_least(v.len(), v) {
+ Ok(_) => {}
+ Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
+ }
+ }
+}
+
+#[cfg(test)]
+#[allow(deprecated_owned_vector)]
+mod test {
+ use prelude::*;
+
+ use super::ReaderRng;
+ use io::MemReader;
+ use mem;
+ use rand::Rng;
+
+ #[test]
+ fn test_reader_rng_u64() {
+ // transmute from the target to avoid endianness concerns.
+ let v = box [1u64, 2u64, 3u64];
+ let bytes: ~[u8] = unsafe {mem::transmute(v)};
+ let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));
+
+ assert_eq!(rng.next_u64(), 1);
+ assert_eq!(rng.next_u64(), 2);
+ assert_eq!(rng.next_u64(), 3);
+ }
+ #[test]
+ fn test_reader_rng_u32() {
+ // transmute from the target to avoid endianness concerns.
+ let v = box [1u32, 2u32, 3u32];
+ let bytes: ~[u8] = unsafe {mem::transmute(v)};
+ let mut rng = ReaderRng::new(MemReader::new(bytes.move_iter().collect()));
+
+ assert_eq!(rng.next_u32(), 1);
+ assert_eq!(rng.next_u32(), 2);
+ assert_eq!(rng.next_u32(), 3);
+ }
+ #[test]
+ fn test_reader_rng_fill_bytes() {
+ let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
+ let mut w = [0u8, .. 8];
+
+ let mut rng = ReaderRng::new(MemReader::new(Vec::from_slice(v)));
+ rng.fill_bytes(w);
+
+ assert!(v == w);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_reader_rng_insufficient_bytes() {
+ let mut rng = ReaderRng::new(MemReader::new(vec!()));
+ let mut v = [0u8, .. 3];
+ rng.fill_bytes(v);
+ }
+}
use realstd::clone::Clone;
for len in range(4u, 25) {
for _ in range(0, 100) {
- let mut v = task_rng().gen_vec::<uint>(len);
+ let mut v = task_rng().gen_iter::<uint>().take(len)
+ .collect::<Vec<uint>>();
let mut v1 = v.clone();
v.as_mut_slice().sort();
fn sort_random_small(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
- let mut v = rng.gen_vec::<u64>(5);
+ let mut v = rng.gen_iter::<u64>().take(5).collect::<Vec<u64>>();
v.as_mut_slice().sort();
});
b.bytes = 5 * mem::size_of::<u64>() as u64;
fn sort_random_medium(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
- let mut v = rng.gen_vec::<u64>(100);
+ let mut v = rng.gen_iter::<u64>().take(100).collect::<Vec<u64>>();
v.as_mut_slice().sort();
});
b.bytes = 100 * mem::size_of::<u64>() as u64;
fn sort_random_large(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
- let mut v = rng.gen_vec::<u64>(10000);
+ let mut v = rng.gen_iter::<u64>().take(10000).collect::<Vec<u64>>();
v.as_mut_slice().sort();
});
b.bytes = 10000 * mem::size_of::<u64>() as u64;
fn sort_big_random_small(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
- let mut v = rng.gen_vec::<BigSortable>(5);
+ let mut v = rng.gen_iter::<BigSortable>().take(5)
+ .collect::<Vec<BigSortable>>();
v.sort();
});
b.bytes = 5 * mem::size_of::<BigSortable>() as u64;
fn sort_big_random_medium(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
- let mut v = rng.gen_vec::<BigSortable>(100);
+ let mut v = rng.gen_iter::<BigSortable>().take(100)
+ .collect::<Vec<BigSortable>>();
v.sort();
});
b.bytes = 100 * mem::size_of::<BigSortable>() as u64;
fn sort_big_random_large(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
- let mut v = rng.gen_vec::<BigSortable>(10000);
+ let mut v = rng.gen_iter::<BigSortable>().take(10000)
+ .collect::<Vec<BigSortable>>();
v.sort();
});
b.bytes = 10000 * mem::size_of::<BigSortable>() as u64;
let trait_def = TraitDef {
span: span,
attributes: Vec::new(),
- path: Path::new(vec!("rand", "Rand")),
+ path: Path::new(vec!("std", "rand", "Rand")),
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
methods: vec!(
lifetimes: Vec::new(),
bounds: vec!(("R",
ast::StaticSize,
- vec!( Path::new(vec!("rand", "Rng")) )))
+ vec!( Path::new(vec!("std", "rand", "Rng")) )))
},
explicit_self: None,
args: vec!(
_ => cx.bug("Incorrect number of arguments to `rand` in `deriving(Rand)`")
};
let rand_ident = vec!(
+ cx.ident_of("std"),
cx.ident_of("rand"),
cx.ident_of("Rand"),
cx.ident_of("rand")
// test harness access
#[cfg(test)]
extern crate test;
-
-extern crate rand;
extern crate serialize;
-use std::mem::{transmute,transmute_copy};
use std::char::Char;
use std::default::Default;
use std::fmt;
use std::from_str::FromStr;
use std::hash::Hash;
+use std::mem::{transmute,transmute_copy};
use std::num::FromStrRadix;
-use std::str;
+use std::rand;
+use std::rand::Rng;
use std::slice;
-
-use rand::Rng;
+use std::str;
use serialize::{Encoder, Encodable, Decoder, Decodable};
/// of random numbers. Use the rand::Rand trait to supply
/// a custom generator if required.
pub fn new_v4() -> Uuid {
- let ub = rand::task_rng().gen_vec(16);
+ let ub = rand::task_rng().gen_iter::<u8>().take(16).collect::<Vec<_>>();
let mut uuid = Uuid{ bytes: [0, .. 16] };
slice::bytes::copy_memory(uuid.bytes, ub.as_slice());
uuid.set_variant(VariantRFC4122);
impl rand::Rand for Uuid {
#[inline]
fn rand<R: rand::Rng>(rng: &mut R) -> Uuid {
- let ub = rng.gen_vec(16);
+ let ub = rng.gen_iter::<u8>().take(16).collect::<Vec<_>>();
let mut uuid = Uuid{ bytes: [0, .. 16] };
slice::bytes::copy_memory(uuid.bytes, ub.as_slice());
uuid.set_variant(VariantRFC4122);
#[cfg(test)]
mod test {
extern crate collections;
- extern crate rand;
use super::{Uuid, VariantMicrosoft, VariantNCS, VariantRFC4122,
Version1Mac, Version2Dce, Version3Md5, Version4Random,
Version5Sha1};
use std::str;
use std::io::MemWriter;
+ use std::rand;
#[test]
fn test_nil() {
#[test]
fn test_rand_rand() {
let mut rng = rand::task_rng();
- let u: Box<Uuid> = rand::Rand::rand(&mut rng);
+ let u: Uuid = rand::Rand::rand(&mut rng);
let ub = u.as_bytes();
assert!(ub.len() == 16);
#![feature(macro_rules)]
-extern crate rand;
extern crate time;
use time::precise_time_s;
-use rand::Rng;
+use std::rand;
+use std::rand::Rng;
use std::mem::swap;
use std::os;
use std::str;
// Multi-language Perlin noise benchmark.
// See https://github.com/nsf/pnoise for timings and alternative implementations.
-extern crate rand;
-
use std::f32::consts::PI;
-use rand::{Rng, StdRng};
+use std::rand::{Rng, StdRng};
struct Vec2 {
x: f32,
// ensure that the TaskRng isn't/doesn't become accidentally sendable.
-extern crate rand;
+use std::rand;
fn test_send<S: Send>() {}
pub fn main() {
- test_send::<::rand::TaskRng>();
- //~^ ERROR: incompatible type `rand::TaskRng`, which does not fulfill `Send`
+ test_send::<rand::TaskRng>();
+ //~^ ERROR: incompatible type `std::rand::TaskRng`, which does not fulfill `Send`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate rand;
-use rand::{task_rng, Rng};
-
use std::{char, os, str};
use std::io::{File, Command};
+use std::rand::{task_rng, Rng};
// creates unicode_input_multiple_files_{main,chars}.rs, where the
// former imports the latter. `_chars` just contains an indentifier
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate rand;
-use rand::{task_rng, Rng};
-
use std::{char, os, str};
use std::io::{File, Command};
+use std::rand::{task_rng, Rng};
// creates a file with `fn main() { <random ident> }` and checks the
// compiler emits a span of the appropriate length (for the
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
#![feature(struct_variant)]
-extern crate rand;
+use std::rand;
#[deriving(Rand)]
struct A;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate rand;
-
use std::task;
-use rand::{task_rng, Rng};
+use std::rand::{task_rng, Rng};
static MAX_LEN: uint = 20;
static mut drop_counts: [uint, .. MAX_LEN] = [0, .. MAX_LEN];
// len can't go above 64.
for len in range(2u, MAX_LEN) {
for _ in range(0, 10) {
- let main = task_rng().gen_vec::<DropCounter>(len);
+ let main = task_rng().gen_iter::<DropCounter>()
+ .take(len)
+ .collect::<Vec<DropCounter>>();
// work out the total number of comparisons required to sort
// this array...