std::rand: documentation & references.

Most importantly, links to the papers/references for the core
algorithms (the RNG ones & the distribution ones).
This commit is contained in:
Huon Wilson 2013-10-11 17:25:40 +11:00
parent 148f737c19
commit e0eb128086
5 changed files with 102 additions and 44 deletions

View File

@ -8,17 +8,17 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Sampling from random distributions
/*!
Sampling from random distributions.
// Some implementations use the Ziggurat method
// https://en.wikipedia.org/wiki/Ziggurat_algorithm
//
// The version used here is ZIGNOR [Doornik 2005, "An Improved
// Ziggurat Method to Generate Normal Random Samples"] which is slower
// (about double, it generates an extra random number) than the
// canonical version [Marsaglia & Tsang 2000, "The Ziggurat Method for
// Generating Random Variables"], but more robust. If one wanted, one
// could implement VIZIGNOR the ZIGNOR paper for more speed.
This is a generalization of `Rand` to allow parameters to control the
exact properties of the generated values, e.g. the mean and standard
deviation of a normal distribution. The `Sample` trait is the most
general, and allows for generating values that change some state
internally. The `IndependentSample` trait is for generating values
that do not need to record state.
*/
use num;
use rand::{Rng,Rand};
@ -27,16 +27,18 @@ pub use self::range::Range;
pub mod range;
/// Things that can be used to create a random instance of `Support`.
/// Types that can be used to create a random instance of `Support`.
pub trait Sample<Support> {
/// Generate a random value of `Support`, using `rng` as the
/// source of randomness.
fn sample<R: Rng>(&mut self, rng: &mut R) -> Support;
}
/// `Sample`s that do not require keeping track of state, so each
/// sample is (statistically) independent of all others, assuming the
/// `Rng` used has this property.
/// `Sample`s that do not require keeping track of state.
///
/// Since no state is recored, each sample is (statistically)
/// independent of all others, assuming the `Rng` used has this
/// property.
// XXX maybe having this separate is overkill (the only reason is to
// take &self rather than &mut self)? or maybe this should be the
// trait called `Sample` and the other should be `DependentSample`.
@ -91,13 +93,19 @@ fn ziggurat<R:Rng>(rng: &mut R,
}
}
/// A wrapper around an `f64` to generate N(0, 1) random numbers (a.k.a. a
/// standard normal, or Gaussian). Multiplying the generated values by the
/// desired standard deviation `sigma` then adding the desired mean `mu` will
/// give N(mu, sigma^2) distributed random numbers.
/// A wrapper around an `f64` to generate N(0, 1) random numbers
/// (a.k.a. a standard normal, or Gaussian).
///
/// Note that this has to be unwrapped before use as an `f64` (using either
/// `*` or `cast::transmute` is safe).
/// See `Normal` for the general normal distribution. That this has to
/// be unwrapped before use as an `f64` (using either `*` or
/// `cast::transmute` is safe).
///
/// Implemented via the ZIGNOR variant[1] of the Ziggurat method.
///
/// [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
/// Generate Normal Random
/// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield
/// College, Oxford
pub struct StandardNormal(f64);
impl Rand for StandardNormal {
@ -135,8 +143,10 @@ impl Rand for StandardNormal {
}
}
/// The `N(mean, std_dev**2)` distribution, i.e. samples from a normal
/// distribution with mean `mean` and standard deviation `std_dev`.
/// The normal distribution `N(mean, std_dev**2)`.
///
/// This uses the ZIGNOR variant of the Ziggurat method, see
/// `StandardNormal` for more details.
///
/// # Example
///
@ -175,12 +185,20 @@ impl IndependentSample<f64> for Normal {
}
}
/// A wrapper around an `f64` to generate Exp(1) random numbers. Dividing by
/// the desired rate `lambda` will give Exp(lambda) distributed random
/// numbers.
/// A wrapper around an `f64` to generate Exp(1) random numbers.
///
/// Note that this has to be unwrapped before use as an `f64` (using either
/// See `Exp` for the general exponential distribution.Note that this
// has to be unwrapped before use as an `f64` (using either
/// `*` or `cast::transmute` is safe).
///
/// Implemented via the ZIGNOR variant[1] of the Ziggurat method. The
/// exact description in the paper was adjusted to use tables for the
/// exponential distribution rather than normal.
///
/// [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to
/// Generate Normal Random
/// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield
/// College, Oxford
pub struct Exp1(f64);
// This could be done via `-rng.gen::<f64>().ln()` but that is slower.
@ -203,8 +221,7 @@ impl Rand for Exp1 {
}
}
/// The `Exp(lambda)` distribution; i.e. samples from the exponential
/// distribution with rate parameter `lambda`.
/// The exponential distribution `Exp(lambda)`.
///
/// This distribution has density function: `f(x) = lambda *
/// exp(-lambda * x)` for `x > 0`.

View File

@ -18,10 +18,15 @@ use option::{None, Some};
static RAND_SIZE_LEN: u32 = 8;
static RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
/// A random number generator that uses the [ISAAC
/// algorithm](http://en.wikipedia.org/wiki/ISAAC_%28cipher%29).
/// A random number generator that uses the ISAAC algorithm[1].
///
/// The ISAAC algorithm is suitable for cryptographic purposes.
/// The ISAAC algorithm is generally accepted as suitable for
/// cryptographic purposes, but this implementation has not be
/// verified as such. Prefer a generator like `OSRng` that defers to
/// the operating system for cases that need high security.
///
/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
pub struct IsaacRng {
priv cnt: u32,
priv rsl: [u32, .. RAND_SIZE],
@ -212,11 +217,16 @@ impl<'self> SeedableRng<&'self [u32]> for IsaacRng {
static RAND_SIZE_64_LEN: uint = 8;
static RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN;
/// A random number generator that uses the 64-bit variant of the
/// [ISAAC
/// algorithm](http://en.wikipedia.org/wiki/ISAAC_%28cipher%29).
/// A random number generator that uses ISAAC-64[1], the 64-bit
/// variant of the ISAAC algorithm.
///
/// The ISAAC algorithm is suitable for cryptographic purposes.
/// The ISAAC algorithm is generally accepted as suitable for
/// cryptographic purposes, but this implementation has not be
/// verified as such. Prefer a generator like `OSRng` that defers to
/// the operating system for cases that need high security.
///
/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number
/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html)
pub struct Isaac64Rng {
priv cnt: uint,
priv rsl: [u64, .. RAND_SIZE_64],

View File

@ -28,6 +28,23 @@ 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 random numbers for cryptographic purposes
should prefer `OSRng`, which reads randomness from one of the source
that the operating system provides (e.g. `/dev/urandom` on
Unixes). The other random number generators provided by this module
are either known to be insecure (`XorShiftRng`), or are not verified
to be secure (`IsaacRng`, `Isaac64Rng` and `StdRng`).
*Note*: on Linux, `/dev/random` is more secure than `/dev/urandom`,
but it is a blocking RNG, and will wait until it has determined that
it has collected enough entropy to fulfill a request for random
data. It can be used with the `Rng` trait provided by this module by
opening the file and passing it to `reader::ReaderRng`. Since it
blocks, `/dev/random` should only be used to retrieve small amounts of
randomness.
# Examples
```rust
@ -516,8 +533,8 @@ pub trait SeedableRng<Seed>: Rng {
/// Create a random number generator with a default algorithm and seed.
///
/// It returns the cryptographically-safest `Rng` algorithm currently
/// available in Rust. If you require a specifically seeded `Rng` for
/// It returns the strongest `Rng` algorithm currently implemented in
/// pure Rust. If you require a specifically seeded `Rng` for
/// consistency over time you should pick one algorithm and create the
/// `Rng` yourself.
///
@ -592,12 +609,16 @@ pub fn weak_rng() -> XorShiftRng {
XorShiftRng::new()
}
/// An [Xorshift random number
/// generator](http://en.wikipedia.org/wiki/Xorshift).
/// An Xorshift[1] random number
/// generator.
///
/// The Xorshift algorithm is not suitable for cryptographic purposes
/// but is very fast. If you do not know for sure that it fits your
/// requirements, use a more secure one such as `IsaacRng`.
/// requirements, use a more secure one such as `IsaacRng` or `OSRng`.
///
/// [1]: Marsaglia, George (July 2003). ["Xorshift
/// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of
/// Statistical Software*. Vol. 8 (Issue 14).
pub struct XorShiftRng {
priv x: u32,
priv y: u32,

View File

@ -30,8 +30,12 @@ type HCRYPTPROV = c_long;
// assume they work when we call them.
/// A random number generator that retrieves randomness straight from
/// the operating system. On Unix-like systems this reads from
/// `/dev/urandom`, on Windows this uses `CryptGenRandom`.
/// 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)]
@ -39,8 +43,12 @@ pub struct OSRng {
priv inner: ReaderRng<file::FileStream>
}
/// A random number generator that retrieves randomness straight from
/// the operating system. On Unix-like systems this reads from
/// `/dev/urandom`, on Windows this uses `CryptGenRandom`.
/// 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(windows)]

View File

@ -672,6 +672,8 @@ extern "C" CDECL void
rust_win32_rand_acquire(HCRYPTPROV* phProv) {
win32_require
(_T("CryptAcquireContext"),
// changes to the parameters here should be reflected in the docs of
// std::rand::os::OSRng
CryptAcquireContext(phProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT|CRYPT_SILENT));