From 8ac8ac8f6c55bd50e74d5dc618e24c050b800c61 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Fri, 23 Mar 2018 15:37:31 +0000 Subject: [PATCH 1/8] Update READMEs. Better doc of features in both crates. Update version req to 0.5.0-pre.0. More updates are needed for final 0.5. --- README.md | 49 +++++++++++++++++++++++---------------------- rand_core/README.md | 24 +++++++++++++++++++++- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 28b3fb1c6c5..d98607b7a68 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,10 @@ Rand A Rust library for random number generators and other randomness functionality. +See also: + +* [rand_core](https://crates.io/crates/rand_core) + [![Build Status](https://travis-ci.org/rust-lang-nursery/rand.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rand) [![Build status](https://ci.appveyor.com/api/projects/status/rm5c9o33k3jhchbw?svg=true)](https://ci.appveyor.com/project/alexcrichton/rand) @@ -14,7 +18,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -rand = "0.4" +rand = "0.5.0-pre.0" ``` and this to your crate root: @@ -44,34 +48,31 @@ Travis CI always has a build with a pinned version of Rustc matching the oldest supported Rust release. The current policy is that this can be updated in any Rand release if required, but the change must be noted in the changelog. -## Examples +## Functionality -There is built-in support for a random number generator (RNG) associated with each thread stored in thread-local storage. This RNG can be accessed via thread_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. +The `rand_core` crate provides: -```rust -let tuple = rand::random::<(f64, char)>(); -println!("{:?}", tuple) -``` +- base random number generator traits +- error-reporting types +- functionality to aid implementation of RNGs -```rust -use rand::Rng; +The `rand` crate provides: -let mut rng = rand::thread_rng(); -if rng.gen() { // random bool - println!("i32: {}, u32: {}", rng.gen::(), rng.gen::()) -} -``` - -It is also possible to use other RNG types, which have a similar interface. The following uses the "ChaCha" algorithm instead of the default. - -```rust -use rand::{Rng, ChaChaRng}; - -let mut rng = rand::ChaChaRng::new_unseeded(); -println!("i32: {}, u32: {}", rng.gen::(), rng.gen::()) -``` +- most content from `rand_core` (re-exported) +- fresh entropy: `EntropyRng`, `OsRng`, `JitterRng` +- pseudo-random number generators: `StdRng`, `SmallRng`, `prng` module +- convenient, auto-seeded crypto-grade thread-local generator: `thread_rng` +- `distributions` producing many different types of random values: + - `Uniform`-ly distributed integers and floats of many types + - unbiased sampling from specified `Range`s + - sampling from exponential/normal/gamma distributions + - sampling from binomial/poisson distributions + - `gen_bool` aka Bernoulli distribution +- `seq`-uence related functionality: + - sampling a subset of elements + - randomly shuffling a list -## Features +## Crate Features By default, Rand is built with all stable features available. The following optional features are available: diff --git a/rand_core/README.md b/rand_core/README.md index 34c92b65684..1f355145084 100644 --- a/rand_core/README.md +++ b/rand_core/README.md @@ -16,7 +16,29 @@ prefer to use the main [rand] crate. [Documentation](https://docs.rs/rand_core) -[rand]: ../README.md +[rand]: https://crates.io/crates/rand + + +## Functionality + +The `rand_core` crate provides: + +- base random number generator traits +- error-reporting types +- functionality to aid implementation of RNGs + +The traits and error types are also available via `rand`. + +## Crate Features + +`rand_core` supports `no_std` and `alloc`-only configurations, as well as full +`std` functionality. The differences between `no_std` and full `std` are small, +comprising `RngCore` support for `Box` types where `R: RngCore`, as well as +extensions to the `Error` type's functionality. + +Due to a bug in Cargo, `rand_core` is built without `std` support by default. +Since features are unioned across the whole dependency tree, any crate using +`rand` with its default features will also enable `std` support in `rand_core`. # License From d5d5ba66cd28f3173aa497003125a037e72a771c Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sat, 24 Mar 2018 12:13:27 +0000 Subject: [PATCH 2/8] Doc: big update to library doc --- README.md | 4 + src/entropy_rng.rs | 6 +- src/lib.rs | 183 ++++++++++++++++++++++++++++----------------- src/os.rs | 24 ++++++ 4 files changed, 147 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index d98607b7a68..04893783162 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,10 @@ and this to your crate root: ```rust extern crate rand; + +// example usage: +use rand::{Rng, thread_rng}; +let x: f64 = thread_rng().gen(); ``` ## Versions diff --git a/src/entropy_rng.rs b/src/entropy_rng.rs index 67a033a9c8a..f5942b39f15 100644 --- a/src/entropy_rng.rs +++ b/src/entropy_rng.rs @@ -13,13 +13,17 @@ use rand_core::{RngCore, CryptoRng, Error, impls}; use {OsRng, JitterRng}; -/// An RNG provided specifically for seeding PRNGs. +/// A generator provided specifically for securely seeding algorithmic +/// generators (PRNGs). /// /// Where possible, `EntropyRng` retrieves random data from the operating /// system's interface for random numbers ([`OsRng`]); if that fails it will /// fall back to the [`JitterRng`] entropy collector. In the latter case it will /// still try to use [`OsRng`] on the next usage. /// +/// If no secure source of entropy is available `EntropyRng` will panic on use; +/// i.e. it should never output predictable data. +/// /// This is either a little slow ([`OsRng`] requires a system call) or extremely /// slow ([`JitterRng`] must use significant CPU time to generate sufficient /// jitter). It is recommended to only use `EntropyRng` to seed a PRNG (as in diff --git a/src/lib.rs b/src/lib.rs index 08ea352f656..11ee0cb0dd8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,84 +9,129 @@ // except according to those terms. //! Utilities for random number generation +//! +//! ## Example +//! +//! ```rust +//! // Rng is the main trait and needs to be imported: +//! use rand::{Rng, thread_rng}; +//! +//! // thread_rng is often the most convenient source of randomness: +//! let mut rng = rand::thread_rng(); +//! if rng.gen() { // random bool +//! let x: f64 = rng.gen(); // random number in range (0, 1) +//! println!("x is: {}"); +//! println!("Number from 0 to 9: {}", rng.gen_range(0, 10)); +//! } +//! ``` //! //! The key function is `Rng::gen()`. It is polymorphic and so can be used to -//! generate any type supporting the [`Uniform`] distribution (i.e. `T` where -//! `Uniform`: `Distribution`). Type inference means that often a simple call -//! to `rng.gen()` will suffice, but sometimes an annotation is required, e.g. +//! generate many types; the [`Uniform`] distribution carries the +//! implementations. In some cases type annotation is required, e.g. //! `rng.gen::()`. //! -//! See the `distributions` submodule for sampling random numbers from -//! distributions like normal and exponential. -//! -//! # Usage +//! # Getting random values //! -//! This crate is [on crates.io](https://crates.io/crates/rand) and can be -//! used by adding `rand` to the dependencies in your project's `Cargo.toml`. -//! -//! ```toml -//! [dependencies] -//! rand = "0.4" +//! The most convenient source of randomness is likely `thread_rng()`, which +//! automatically initialises a fast algorithmic generator on first use per +//! thread with thread-local storage. +//! +//! If one wants to obtain random data directly from an external source it is +//! recommended to use `EntropyRng` which manages multiple available sources +//! or `OsRng` which retrieves random data directly from the OS. It should be +//! noted that this is significantly slower than using a local generator like +//! `thread_rng` and potentially much slower if `EntropyRng` must fall back to +//! `JitterRng` as a source. +//! +//! It is also common to use an algorithmic generator in local memory; for +//! example `StdRng` or `SmallRng` (the main advantages of the latter are +//! much smaller state and faster initialisation while its disadvantage is +//! that it may be easy for an attacker to predict; actual performance varies). +//! These can be seeded from a parent generator (`SeedableRng::thread_rng`) or +//! with fresh entropy using `NewRng`: +//! //! ``` -//! -//! and this to your crate root: -//! -//! ```rust -//! extern crate rand; +//! use rand::{SmallRng, NewRng}; +//! let mut rng = SmallRng::new(); //! ``` -//! -//! # Thread-local RNG -//! -//! There is built-in support for a RNG associated with each thread stored -//! in thread-local storage. This RNG can be accessed via `thread_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. -//! +//! +//! In case one wants specifically to have a reproducible stream of "random" +//! data (e.g. to procedurally generate a game world), select a named algorithm +//! (i.e. not `StdRng`/`SmallRng` which may be adjusted in the future), and +//! use `SeedableRng::from_seed`. Some generators provide additional +//! constructors suitable for some applications, e.g. `IsaacRng::new_from_u64`. +//! +//! # Applying / converting random data +//! +//! The `RngCore` trait allows generators to implement a common interface for +//! retrieving random data, but how should you use this? Typically users should +//! use the `Rng` trait not `RngCore`; this provides more flexible ways to +//! access the same data (e.g. `gen()` can output many more types than +//! `next_u32()` and `next_u64()`; Rust's optimiser should eliminate any +//! overhead). It also provides several useful algorithms, +//! e.g. `gen_bool(p)` to generate events with weighted probability and +//! `shuffle(&mut v[..])` to randomly-order a vector. +//! +//! The `distributions` module provides several more ways to convert random +//! data to useful values, e.g. time of decay is often modelled with an +//! exponential distribution, and the log-normal distribution provides a good +//! model of many natural phenomona. +//! +//! The `seq` module has a few tools applicable to sliceable or iterable 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. Linux 3.17 added the `getrandom(2)` system call which solves -//! the issue: it blocks if entropy pool is not initialized yet, but it does -//! not block once initialized. `OsRng` tries to use `getrandom(2)` if -//! available, and use `/dev/urandom` fallback if not. If an application -//! does not have `getrandom` and likely to be run soon after first booting, -//! or on a system with very few entropy sources, one should consider using -//! `/dev/random` via `ReadRng`. -//! - 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.) -//! +//! Security analysis requires a threat model and expert review; we can provide +//! neither, but can provide some guidance. We assume that the goal is to +//! obtain secret random data and that some source of secrets ("entropy") is +//! available; that is, `EntropyRng` is functional. +//! +//! Potential threat: is the entropy source secure? The primary entropy source +//! is `OsRng` which is simply a wrapper around the platform's native "secure +//! entropy source"; usually this is available (outside of embedded platforms) +//! and usually you can trust this (some caveats may apply; see `OsRng` doc). +//! The fallback source used by `EntropyRng` is `JitterRng` which runs extensive +//! tests on the quality of the CPU timer and is conservative in its estimates +//! of the entropy harvested from each time sample; this makes it slow but very +//! strong. Using `EntropyRng` directly should therefore be secure; the main +//! reason not to is performance, which is why many applications use local +//! algorithmic generators. +//! +//! Potential threat: are algorithmic generators predictable? Certainly some +//! are; algorithmic generators fall broadly into two categories: those using a +//! small amount of state (e.g. one to four 32- or 64-bit words) designed for +//! non-security applications and those designed to be secure, typically with +//! much larger state space and complex initialisation. The former should not be +//! trusted to be secure, the latter may or may not have known weaknesses or +//! may even have been proven secure under a specified adversarial model. We +//! provide some notes on the security of the cryptographic algorithmic +//! generators provided by this crate, `Hc128Rng` and `ChaChaRng`. Note that +//! previously `IsaacRng` and `Isaac64Rng` were used as "reasonably strong +//! generators"; these have no known weaknesses but also have no proofs of +//! security, thus are not recommended for cryptographic uses. +//! +//! Potential threat: could the internal state of a cryptographic generator be +//! leaked? This falls under the topic of "side channel attacks", and multiple +//! variants are possible: the state of the generators being accidentally +//! printed in log files or some other application output, the process's memory +//! being copied somehow, the process being forked and both sub-processes +//! outputting the same random sequence but such that one of those can be read; +//! likely some other side-channel attacks are possible in some circumstances. +//! It is typically impossible to prove immunity to all side-channel attacks, +//! however some mitigation of known threats is usually possible, for example +//! all generators implemented in this crate have a custom `Debug` +//! implementation omitting all internal state, and `ReseedingRng` allows +//! periodic reseeding such that a long-running process with leaked generator +//! state should eventually recover to an unknown state. In the future we plan +//! to add further mitigations; see issue #314. +//! +//! We provide the `CryptoRng` marker trait as an indication of which random +//! generators/sources may be used for cryptographic applications; this should +//! be considered advisory only does not imply any protection against +//! side-channel attacks. +//! //! # Examples //! -//! ```rust -//! use rand::Rng; -//! -//! let mut rng = rand::thread_rng(); -//! if rng.gen() { // random bool -//! println!("i32: {}, u32: {}", rng.gen::(), rng.gen::()) -//! } -//! ``` -//! //! ## Monte Carlo estimation of π //! //! For this example, imagine we have a square with sides of length 2 and a unit @@ -785,8 +830,8 @@ impl Iterator for AsciiGenerator { } -/// A convenient way to seed new algorithmic generators, otherwise known as -/// pseudo-random number generators (PRNGs). +/// A convenient way to seed new algorithmic generators with fresh entropy from +/// `EntropyRng`. /// /// This is the recommended way to create PRNGs, unless a deterministic seed is /// desired (in which case [`SeedableRng::from_seed`] should be used). diff --git a/src/os.rs b/src/os.rs index 39958c9e29d..55269862341 100644 --- a/src/os.rs +++ b/src/os.rs @@ -42,6 +42,30 @@ use rand_core::{RngCore, Error, ErrorKind, impls}; /// Max OS X, and modern Linux) this may block very early in the init /// process, if the CSPRNG has not been seeded yet.[1] /// +/// *Note*: many Unix systems provide `/dev/random` as well as `/dev/urandom`. +/// This module uses `getrandom` if available, otherwise `/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. Linux 3.17 added the `getrandom(2)` system call which solves +/// the issue: it blocks if entropy pool is not initialized yet, but it does +/// not block once initialized. `OsRng` tries to use `getrandom(2)` if +/// available, and use `/dev/urandom` fallback if not. If an application +/// does not have `getrandom` and likely to be run soon after first booting, +/// or on a system with very few entropy sources, one should consider using +/// `/dev/random` via `ReadRng`. +/// - 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.) +/// /// [1] See for a more /// in-depth discussion. From eccc5c95ace240ab8d2153440576ebdfa7453442 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sat, 24 Mar 2018 16:36:21 +0000 Subject: [PATCH 3/8] Lib doc: update in response to review --- src/lib.rs | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 11ee0cb0dd8..9e935fe0ff8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,46 +20,54 @@ //! let mut rng = rand::thread_rng(); //! if rng.gen() { // random bool //! let x: f64 = rng.gen(); // random number in range (0, 1) -//! println!("x is: {}"); +//! println!("x is: {}", x); //! println!("Number from 0 to 9: {}", rng.gen_range(0, 10)); //! } //! ``` //! -//! The key function is `Rng::gen()`. It is polymorphic and so can be used to +//! The key function is [`Rng::gen()`]. It is polymorphic and so can be used to //! generate many types; the [`Uniform`] distribution carries the //! implementations. In some cases type annotation is required, e.g. //! `rng.gen::()`. //! //! # Getting random values //! -//! The most convenient source of randomness is likely `thread_rng()`, which +//! The most convenient source of randomness is likely [`thread_rng`], which //! automatically initialises a fast algorithmic generator on first use per //! thread with thread-local storage. //! //! If one wants to obtain random data directly from an external source it is -//! recommended to use `EntropyRng` which manages multiple available sources -//! or `OsRng` which retrieves random data directly from the OS. It should be +//! recommended to use [`EntropyRng`] which manages multiple available sources +//! or [`OsRng`] which retrieves random data directly from the OS. It should be //! noted that this is significantly slower than using a local generator like -//! `thread_rng` and potentially much slower if `EntropyRng` must fall back to -//! `JitterRng` as a source. +//! [`thread_rng`] and potentially much slower if [`EntropyRng`] must fall back to +//! [`JitterRng`] as a source. //! -//! It is also common to use an algorithmic generator in local memory; for -//! example `StdRng` or `SmallRng` (the main advantages of the latter are -//! much smaller state and faster initialisation while its disadvantage is -//! that it may be easy for an attacker to predict; actual performance varies). -//! These can be seeded from a parent generator (`SeedableRng::thread_rng`) or -//! with fresh entropy using `NewRng`: +//! It is also common to use an algorithmic generator in local memory; this may +//! be faster than `thread_rng` and provides more control. In this case +//! [`StdRng`] (the generator behind `thread_rng`) or [`SmallRng`] (a fast +//! generator with much smaller state and faster initialisation, but not +//! suitable for cryptography) are good choices; more are found in the [`prng`] +//! module or other crates. +//! +//! Local generators need to be seeded. It is recommended to use [`NewRng`] or +//! to seed from a strong parent generator with [`from_rng`]: //! //! ``` +//! // seed with fresh entropy: //! use rand::{SmallRng, NewRng}; //! let mut rng = SmallRng::new(); +//! +//! // seed from thread_rng: +//! use rand::{SeedableRng, thread_rng}; +//! let mut rng = SmallRng::from_rng(thread_rng()); //! ``` //! -//! In case one wants specifically to have a reproducible stream of "random" +//! In case you specifically want to have a reproducible stream of "random" //! data (e.g. to procedurally generate a game world), select a named algorithm -//! (i.e. not `StdRng`/`SmallRng` which may be adjusted in the future), and -//! use `SeedableRng::from_seed`. Some generators provide additional -//! constructors suitable for some applications, e.g. `IsaacRng::new_from_u64`. +//! (i.e. not [`StdRng`]/[`SmallRng`] which may be adjusted in the future), and +//! use `SeedableRng::from_seed` or a constructor specific to the generator +//! (e.g. [`IsaacRng::new_from_u64`]). //! //! # Applying / converting random data //! From 57905a341efc487541f3e08305173eef960b0a24 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sat, 24 Mar 2018 16:57:37 +0000 Subject: [PATCH 4/8] Travis: build doc for all sub-crates --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 61ca13335c0..ff4eca5336f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ matrix: - cargo test --all --features=alloc - cargo test --features serde-1,log,nightly - cargo test --benches - - cargo doc --no-deps --all-features + - cargo doc --no-deps --all --all-features after_success: - travis-cargo --only nightly doc-upload From 8b65ebec407c4ea25293ee57e010c8d64fc27898 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sat, 24 Mar 2018 17:00:41 +0000 Subject: [PATCH 5/8] Extract examples from lib doc Note: links are predictive. Unfortunately example code is not included in generated documentation, so we must link to the repo. --- examples/monte-carlo.rs | 49 +++++++++++++ examples/monty-hall.rs | 115 ++++++++++++++++++++++++++++++ src/lib.rs | 151 ++-------------------------------------- 3 files changed, 170 insertions(+), 145 deletions(-) create mode 100644 examples/monte-carlo.rs create mode 100644 examples/monty-hall.rs diff --git a/examples/monte-carlo.rs b/examples/monte-carlo.rs new file mode 100644 index 00000000000..3d2699698bc --- /dev/null +++ b/examples/monte-carlo.rs @@ -0,0 +1,49 @@ +// Copyright 2013-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! # Monte Carlo estimation of π +//! +//! Imagine that we have a square with sides of length 2 and a unit circle +//! (radius = 1), both centered at the origin. The areas are: +//! +//! ```text +//! area of circle = πr² = π * r * r = π +//! area of square = 2² = 4 +//! ``` +//! +//! The circle is entirely within the square, so if we sample many points +//! randomly from the square, roughly π / 4 of them should be inside the circle. +//! +//! We can use the above fact to estimate the value of π: pick many points in +//! the square at random, calculate the fraction that fall within the circle, +//! and multiply this fraction by 4. + +extern crate rand; + +use rand::distributions::{Distribution, Range}; + +fn main() { + let range = Range::new(-1.0f64, 1.0); + let mut rng = rand::thread_rng(); + + let total = 1_000_000; + let mut in_circle = 0; + + for _ in 0..total { + let a = range.sample(&mut rng); + let b = range.sample(&mut rng); + if a*a + b*b <= 1.0 { + in_circle += 1; + } + } + + // prints something close to 3.14159... + println!("π is approximately {}", 4. * (in_circle as f64) / (total as f64)); +} diff --git a/examples/monty-hall.rs b/examples/monty-hall.rs new file mode 100644 index 00000000000..b8ff1ff4c32 --- /dev/null +++ b/examples/monty-hall.rs @@ -0,0 +1,115 @@ +// Copyright 2013-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! ## Monty Hall Problem +//! +//! This is a simulation of the [Monty Hall Problem][]: +//! +//! > Suppose you're on a game show, and you're given the choice of three doors: +//! > Behind one door is a car; behind the others, goats. You pick a door, say +//! > No. 1, and the host, who knows what's behind the doors, opens another +//! > door, say No. 3, which has a goat. He then says to you, "Do you want to +//! > pick door No. 2?" Is it to your advantage to switch your choice? +//! +//! The rather unintuitive answer is that you will have a 2/3 chance of winning +//! if you switch and a 1/3 chance of winning if you don't, so it's better to +//! switch. +//! +//! This program will simulate the game show and with large enough simulation +//! steps it will indeed confirm that it is better to switch. +//! +//! [Monty Hall Problem]: https://en.wikipedia.org/wiki/Monty_Hall_problem + +extern crate rand; + +use rand::Rng; +use rand::distributions::{Distribution, Range}; +use rand::distributions::range::RangeInt; + +struct SimulationResult { + win: bool, + switch: bool, +} + +// Run a single simulation of the Monty Hall problem. +fn simulate(random_door: &Range>, rng: &mut R) + -> SimulationResult { + let car = random_door.sample(rng); + + // This is our initial choice + let mut choice = random_door.sample(rng); + + // The game host opens a door + let open = game_host_open(car, choice, rng); + + // Shall we switch? + let switch = rng.gen(); + if switch { + choice = switch_door(choice, open); + } + + SimulationResult { win: choice == car, switch: switch } +} + +// Returns the door the game host opens given our choice and knowledge of +// where the car is. The game host will never open the door with the car. +fn game_host_open(car: u32, choice: u32, rng: &mut R) -> u32 { + let choices = free_doors(&[car, choice]); + rand::seq::sample_slice(rng, &choices, 1)[0] +} + +// Returns the door we switch to, given our current choice and +// the open door. There will only be one valid door. +fn switch_door(choice: u32, open: u32) -> u32 { + free_doors(&[choice, open])[0] +} + +fn free_doors(blocked: &[u32]) -> Vec { + (0..3).filter(|x| !blocked.contains(x)).collect() +} + +fn main() { + // The estimation will be more accurate with more simulations + let num_simulations = 10000; + + let mut rng = rand::thread_rng(); + let random_door = Range::new(0u32, 3); + + let (mut switch_wins, mut switch_losses) = (0, 0); + let (mut keep_wins, mut keep_losses) = (0, 0); + + println!("Running {} simulations...", num_simulations); + for _ in 0..num_simulations { + let result = simulate(&random_door, &mut rng); + + match (result.win, result.switch) { + (true, true) => switch_wins += 1, + (true, false) => keep_wins += 1, + (false, true) => switch_losses += 1, + (false, false) => keep_losses += 1, + } + } + + let total_switches = switch_wins + switch_losses; + let total_keeps = keep_wins + keep_losses; + + println!("Switched door {} times with {} wins and {} losses", + total_switches, switch_wins, switch_losses); + + println!("Kept our choice {} times with {} wins and {} losses", + total_keeps, keep_wins, keep_losses); + + // With a large number of simulations, the values should converge to + // 0.667 and 0.333 respectively. + println!("Estimated chance to win if we switch: {}", + switch_wins as f32 / total_switches as f32); + println!("Estimated chance to win if we don't: {}", + keep_wins as f32 / total_keeps as f32); +} diff --git a/src/lib.rs b/src/lib.rs index 9e935fe0ff8..57fae878eb1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -140,151 +140,12 @@ //! //! # Examples //! -//! ## Monte Carlo estimation of π -//! -//! For this example, imagine we have a square with sides of length 2 and a unit -//! circle, both centered at the origin. Since the area of a unit circle is π, -//! we have: -//! -//! ```text -//! (area of unit circle) / (area of square) = π / 4 -//! ``` -//! -//! So if we sample many points randomly from the square, roughly π / 4 of them -//! should be inside the circle. -//! -//! We can use the above fact to estimate the value of π: pick many points in -//! the square at random, calculate the fraction that fall within the circle, -//! and multiply this fraction by 4. -//! -//! ``` -//! use rand::distributions::{Distribution, Range}; -//! -//! fn main() { -//! let between = Range::new(-1f64, 1.); -//! let mut rng = rand::thread_rng(); -//! -//! let total = 1_000_000; -//! let mut in_circle = 0; -//! -//! for _ in 0..total { -//! let a = between.sample(&mut rng); -//! let b = between.sample(&mut rng); -//! if a*a + b*b <= 1. { -//! in_circle += 1; -//! } -//! } -//! -//! // prints something close to 3.14159... -//! println!("{}", 4. * (in_circle as f64) / (total as f64)); -//! } -//! ``` -//! -//! ## Monty Hall Problem -//! -//! This is a simulation of the [Monty Hall Problem][]: -//! -//! > Suppose you're on a game show, and you're given the choice of three doors: -//! > Behind one door is a car; behind the others, goats. You pick a door, say -//! > No. 1, and the host, who knows what's behind the doors, opens another -//! > door, say No. 3, which has a goat. He then says to you, "Do you want to -//! > pick door No. 2?" Is it to your advantage to switch your choice? -//! -//! The rather unintuitive answer is that you will have a 2/3 chance of winning -//! if you switch and a 1/3 chance of winning if you don't, so it's better to -//! switch. -//! -//! This program will simulate the game show and with large enough simulation -//! steps it will indeed confirm that it is better to switch. -//! -//! [Monty Hall Problem]: https://en.wikipedia.org/wiki/Monty_Hall_problem -//! -//! ``` -//! use rand::Rng; -//! use rand::distributions::{Distribution, Range}; -//! use rand::distributions::range::RangeInt; -//! -//! struct SimulationResult { -//! win: bool, -//! switch: bool, -//! } -//! -//! // Run a single simulation of the Monty Hall problem. -//! fn simulate(random_door: &Range>, rng: &mut R) -//! -> SimulationResult { -//! let car = random_door.sample(rng); -//! -//! // This is our initial choice -//! let mut choice = random_door.sample(rng); -//! -//! // The game host opens a door -//! let open = game_host_open(car, choice, rng); -//! -//! // Shall we switch? -//! let switch = rng.gen(); -//! if switch { -//! choice = switch_door(choice, open); -//! } -//! -//! SimulationResult { win: choice == car, switch: switch } -//! } -//! -//! // Returns the door the game host opens given our choice and knowledge of -//! // where the car is. The game host will never open the door with the car. -//! fn game_host_open(car: u32, choice: u32, rng: &mut R) -> u32 { -//! let choices = free_doors(&[car, choice]); -//! rand::seq::sample_slice(rng, &choices, 1)[0] -//! } -//! -//! // Returns the door we switch to, given our current choice and -//! // the open door. There will only be one valid door. -//! fn switch_door(choice: u32, open: u32) -> u32 { -//! free_doors(&[choice, open])[0] -//! } -//! -//! fn free_doors(blocked: &[u32]) -> Vec { -//! (0..3).filter(|x| !blocked.contains(x)).collect() -//! } -//! -//! fn main() { -//! // The estimation will be more accurate with more simulations -//! let num_simulations = 10000; -//! -//! let mut rng = rand::thread_rng(); -//! let random_door = Range::new(0u32, 3); -//! -//! let (mut switch_wins, mut switch_losses) = (0, 0); -//! let (mut keep_wins, mut keep_losses) = (0, 0); -//! -//! println!("Running {} simulations...", num_simulations); -//! for _ in 0..num_simulations { -//! let result = simulate(&random_door, &mut rng); -//! -//! match (result.win, result.switch) { -//! (true, true) => switch_wins += 1, -//! (true, false) => keep_wins += 1, -//! (false, true) => switch_losses += 1, -//! (false, false) => keep_losses += 1, -//! } -//! } -//! -//! let total_switches = switch_wins + switch_losses; -//! let total_keeps = keep_wins + keep_losses; -//! -//! println!("Switched door {} times with {} wins and {} losses", -//! total_switches, switch_wins, switch_losses); -//! -//! println!("Kept our choice {} times with {} wins and {} losses", -//! total_keeps, keep_wins, keep_losses); -//! -//! // With a large number of simulations, the values should converge to -//! // 0.667 and 0.333 respectively. -//! println!("Estimated chance to win if we switch: {}", -//! switch_wins as f32 / total_switches as f32); -//! println!("Estimated chance to win if we don't: {}", -//! keep_wins as f32 / total_keeps as f32); -//! } -//! ``` +//! For some inspiration, see the examples: +//! +//! * [Monte Carlo estimation of π]( +//! https://github.com/rust-lang-nursery/rand/blob/master/examples/monte-carlo.rs) +//! * [Monty Hall Problem]( +//! https://github.com/rust-lang-nursery/rand/blob/master/examples/monty-hall.rs) //! //! [`Uniform`]: distributions/struct.Uniform.html From be98c6432ac6994163563804c9a6b3509acfc4ff Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sat, 24 Mar 2018 17:36:23 +0000 Subject: [PATCH 6/8] Doc: fix lots of links This uses relative paths between crates which works fine with locally-generated documentation and should also with this: https://rust-lang-nursery.github.io/rand/rand/index.html --- rand_core/src/lib.rs | 56 ++++++++++++++++++++++++-------------- src/lib.rs | 65 +++++++++++++++++++++++++++++--------------- 2 files changed, 79 insertions(+), 42 deletions(-) diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 2dd200f2f1a..617a681a265 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -11,22 +11,27 @@ //! Random number generation traits //! //! This crate is mainly of interest to crates publishing implementations of -//! `RngCore`. Other users are encouraged to use the [rand] crate instead +//! [`RngCore`]. Other users are encouraged to use the [rand] crate instead //! which re-exports the main traits and error types. //! -//! `RngCore` is the core trait implemented by algorithmic pseudo-random number +//! [`RngCore`] is the core trait implemented by algorithmic pseudo-random number //! generators and external random-number sources. //! -//! `SeedableRng` is an extension trait for construction from fixed seeds and +//! [`SeedableRng`] is an extension trait for construction from fixed seeds and //! other random number generators. //! -//! `Error` is provided for error-handling. It is safe to use in `no_std` +//! [`Error`] is provided for error-handling. It is safe to use in `no_std` //! environments. //! -//! The `impls` and `le` sub-modules include a few small functions to assist -//! implementation of `RngCore`. +//! The [`impls`] and [`le`] sub-modules include a few small functions to assist +//! implementation of [`RngCore`]. //! //! [rand]: https://crates.io/crates/rand +//! [`RngCore`]: trait.RngCore.html +//! [`SeedableRng`]: trait.SeedableRng.html +//! [`Error`]: struct.Error.html +//! [`impls`]: impls/index.html +//! [`le`]: le/index.html #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", @@ -64,15 +69,15 @@ pub mod le; /// Three different methods for generating random data are provided since the /// optimal implementation of each is dependent on the type of generator. There /// is no required relationship between the output of each; e.g. many -/// implementations of `fill_bytes` consume a whole number of `u32` or `u64` +/// implementations of [`fill_bytes`] consume a whole number of `u32` or `u64` /// values and drop any remaining unused bytes. /// -/// The `try_fill_bytes` method is a variant of `fill_bytes` allowing error +/// The [`try_fill_bytes`] method is a variant of [`fill_bytes`] allowing error /// handling; it is not deemed sufficiently useful to add equivalents for -/// `next_u32` or `next_u64` since the latter methods are almost always used +/// [`next_u32`] or [`next_u64`] since the latter methods are almost always used /// with algorithmic generators (PRNGs), which are normally infallible. /// -/// Algorithmic generators implementing `SeedableRng` should normally have +/// Algorithmic generators implementing [`SeedableRng`] should normally have /// *portable, reproducible* output, i.e. fix Endianness when converting values /// to avoid platform differences, and avoid making any changes which affect /// output (except by communicating that the release has breaking changes). @@ -84,7 +89,7 @@ pub mod le; /// It is recommended that implementations also implement: /// /// - `Debug` with a custom implementation which *does not* print any internal -/// state (at least, `CryptoRng`s should not risk leaking state through Debug) +/// state (at least, [`CryptoRng`]s should not risk leaking state through Debug) /// - `Serialize` and `Deserialize` (from Serde), preferably making Serde /// support optional at the crate level in PRNG libs /// - `Clone` if, and only if, the clone will have identical output to the @@ -124,8 +129,14 @@ pub mod le; /// ``` /// /// [rand]: https://crates.io/crates/rand -/// [`Rng`]: https://docs.rs/rand/0.5/rand/trait.Rng.html +/// [`Rng`]: ../rand/trait.Rng.html +/// [`SeedableRng`]: trait.SeedableRng.html /// [`impls`]: impls/index.html +/// [`try_fill_bytes`]: trait.RngCore.html#tymethod.try_fill_bytes +/// [`fill_bytes`]: trait.RngCore.html#tymethod.fill_bytes +/// [`next_u32`]: trait.RngCore.html#tymethod.next_u32 +/// [`next_u64`]: trait.RngCore.html#tymethod.next_u64 +/// [`CryptoRng`]: trait.CryptoRng.html pub trait RngCore { /// Return the next random `u32`. /// @@ -181,7 +192,7 @@ pub trait RngCore { /// /// Usage of this trait is optional, but provides two advantages: /// implementations only need to concern themselves with generation of the -/// block, not the various `RngCore` methods (especially `fill_bytes`, where the +/// block, not the various [`RngCore`] methods (especially [`fill_bytes`], where the /// optimal implementations are not trivial), and this allows `ReseedingRng` to /// perform periodic reseeding with very low overhead. /// @@ -213,6 +224,9 @@ pub trait RngCore { /// // Final RNG. /// type MyRng = BlockRng; /// ``` +/// +/// [`RngCore`]: trait.RngCore.html +/// [`fill_bytes`]: trait.RngCore.html#tymethod.fill_bytes pub trait BlockRngCore { /// Results element type, e.g. `u32`. type Item; @@ -225,7 +239,7 @@ pub trait BlockRngCore { fn generate(&mut self, results: &mut Self::Results); } -/// A marker trait used to indicate that an `RngCore` or `BlockRngCore` +/// A marker trait used to indicate that an [`RngCore`] or [`BlockRngCore`] /// implementation is supposed to be cryptographically secure. /// /// *Cryptographically secure generators*, also known as *CSPRNGs*, should @@ -245,6 +259,9 @@ pub trait BlockRngCore { /// /// Note also that use of a `CryptoRng` does not protect against other /// weaknesses such as seeding from a weak entropy source or leaking state. +/// +/// [`RngCore`]: trait.RngCore.html +/// [`BlockRngCore`]: trait.BlockRngCore.html pub trait CryptoRng {} /// A random number generator that can be explicitly seeded. @@ -252,11 +269,10 @@ pub trait CryptoRng {} /// This trait encapsulates the low-level functionality common to all /// pseudo-random number generators (PRNGs, or algorithmic generators). /// -/// [rand]'s [`NewRng`] trait is automatically implemented for every type +/// The [`rand::NewRng`] trait is automatically implemented for every type /// implementing `SeedableRng`, providing a convenient `new()` method. /// -/// [rand]: https://crates.io/crates/rand -/// [`NewRng`]: https://docs.rs/rand/0.5/rand/trait.NewRng.html +/// [`rand::NewRng`]: ../rand/trait.NewRng.html pub trait SeedableRng: Sized { /// Seed type, which is restricted to types mutably-dereferencable as `u8` /// arrays (we recommend `[u8; N]` for some `N`). @@ -314,9 +330,9 @@ pub trait SeedableRng: Sized { /// PRNG implementations are allowed to assume that a good RNG is provided /// for seeding, and that it is cryptographically secure when appropriate. /// - /// [`NewRng`]: https://docs.rs/rand/0.5/rand/trait.NewRng.html - /// [`OsRng`]: https://docs.rs/rand/0.5/rand/os/struct.OsRng.html - /// [`XorShiftRng`]: https://docs.rs/rand/0.5/rand/prng/xorshift/struct.XorShiftRng.html + /// [`NewRng`]: ../rand/trait.NewRng.html + /// [`OsRng`]: ../rand/os/struct.OsRng.html + /// [`XorShiftRng`]: ../rand/struct.XorShiftRng.html fn from_rng(mut rng: R) -> Result { let mut seed = Self::Seed::default(); rng.try_fill_bytes(seed.as_mut())?; diff --git a/src/lib.rs b/src/lib.rs index 57fae878eb1..88169a2674e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,63 +45,62 @@ //! //! It is also common to use an algorithmic generator in local memory; this may //! be faster than `thread_rng` and provides more control. In this case -//! [`StdRng`] (the generator behind `thread_rng`) or [`SmallRng`] (a fast -//! generator with much smaller state and faster initialisation, but not -//! suitable for cryptography) are good choices; more are found in the [`prng`] -//! module or other crates. +//! [`StdRng`] — the generator behind [`thread_rng`] — and [`SmallRng`] — a +//! small, fast, weak generator — are good choices; more options can be found in +//! the [`prng`] module as well as in other crates. //! //! Local generators need to be seeded. It is recommended to use [`NewRng`] or //! to seed from a strong parent generator with [`from_rng`]: //! //! ``` //! // seed with fresh entropy: -//! use rand::{SmallRng, NewRng}; -//! let mut rng = SmallRng::new(); +//! use rand::{StdRng, NewRng}; +//! let mut rng = StdRng::new(); //! //! // seed from thread_rng: -//! use rand::{SeedableRng, thread_rng}; +//! use rand::{SmallRng, SeedableRng, thread_rng}; //! let mut rng = SmallRng::from_rng(thread_rng()); //! ``` //! //! In case you specifically want to have a reproducible stream of "random" //! data (e.g. to procedurally generate a game world), select a named algorithm //! (i.e. not [`StdRng`]/[`SmallRng`] which may be adjusted in the future), and -//! use `SeedableRng::from_seed` or a constructor specific to the generator +//! use [`SeedableRng::from_seed`] or a constructor specific to the generator //! (e.g. [`IsaacRng::new_from_u64`]). //! //! # Applying / converting random data //! -//! The `RngCore` trait allows generators to implement a common interface for +//! The [`RngCore`] trait allows generators to implement a common interface for //! retrieving random data, but how should you use this? Typically users should -//! use the `Rng` trait not `RngCore`; this provides more flexible ways to +//! use the [`Rng`] trait not [`RngCore`]; this provides more flexible ways to //! access the same data (e.g. `gen()` can output many more types than //! `next_u32()` and `next_u64()`; Rust's optimiser should eliminate any //! overhead). It also provides several useful algorithms, //! e.g. `gen_bool(p)` to generate events with weighted probability and //! `shuffle(&mut v[..])` to randomly-order a vector. //! -//! The `distributions` module provides several more ways to convert random +//! The [`distributions`] module provides several more ways to convert random //! data to useful values, e.g. time of decay is often modelled with an //! exponential distribution, and the log-normal distribution provides a good //! model of many natural phenomona. //! -//! The `seq` module has a few tools applicable to sliceable or iterable data. +//! The [`seq`] module has a few tools applicable to sliceable or iterable data. //! //! # Cryptographic security //! //! Security analysis requires a threat model and expert review; we can provide //! neither, but can provide some guidance. We assume that the goal is to //! obtain secret random data and that some source of secrets ("entropy") is -//! available; that is, `EntropyRng` is functional. +//! available; that is, [`EntropyRng`] is functional. //! //! Potential threat: is the entropy source secure? The primary entropy source -//! is `OsRng` which is simply a wrapper around the platform's native "secure +//! is [`OsRng`] which is simply a wrapper around the platform's native "secure //! entropy source"; usually this is available (outside of embedded platforms) -//! and usually you can trust this (some caveats may apply; see `OsRng` doc). -//! The fallback source used by `EntropyRng` is `JitterRng` which runs extensive +//! and usually you can trust this (some caveats may apply; see [`OsRng`] doc). +//! The fallback source used by [`EntropyRng`] is [`JitterRng`] which runs extensive //! tests on the quality of the CPU timer and is conservative in its estimates //! of the entropy harvested from each time sample; this makes it slow but very -//! strong. Using `EntropyRng` directly should therefore be secure; the main +//! strong. Using [`EntropyRng`] directly should therefore be secure; the main //! reason not to is performance, which is why many applications use local //! algorithmic generators. //! @@ -113,8 +112,8 @@ //! trusted to be secure, the latter may or may not have known weaknesses or //! may even have been proven secure under a specified adversarial model. We //! provide some notes on the security of the cryptographic algorithmic -//! generators provided by this crate, `Hc128Rng` and `ChaChaRng`. Note that -//! previously `IsaacRng` and `Isaac64Rng` were used as "reasonably strong +//! generators provided by this crate, [`Hc128Rng`] and [`ChaChaRng`]. Note that +//! previously [`IsaacRng`] and [`Isaac64Rng`] were used as "reasonably strong //! generators"; these have no known weaknesses but also have no proofs of //! security, thus are not recommended for cryptographic uses. //! @@ -128,12 +127,12 @@ //! It is typically impossible to prove immunity to all side-channel attacks, //! however some mitigation of known threats is usually possible, for example //! all generators implemented in this crate have a custom `Debug` -//! implementation omitting all internal state, and `ReseedingRng` allows +//! implementation omitting all internal state, and [`ReseedingRng`] allows //! periodic reseeding such that a long-running process with leaked generator //! state should eventually recover to an unknown state. In the future we plan //! to add further mitigations; see issue #314. //! -//! We provide the `CryptoRng` marker trait as an indication of which random +//! We provide the [`CryptoRng`] marker trait as an indication of which random //! generators/sources may be used for cryptographic applications; this should //! be considered advisory only does not imply any protection against //! side-channel attacks. @@ -147,6 +146,28 @@ //! * [Monty Hall Problem]( //! https://github.com/rust-lang-nursery/rand/blob/master/examples/monty-hall.rs) //! +//! [`Rng`]: trait.Rng.html +//! [`Rng::gen()`]: trait.Rng.html#method.gen +//! [`RngCore`]: trait.RngCore.html +//! [`NewRng`]: trait.NewRng.html +//! [`SeedableRng::from_seed`]: trait.SeedableRng.html#tymethod.from_seed +//! [`from_rng`]: trait.SeedableRng.html#method.from_rng +//! [`CryptoRng`]: trait.CryptoRng.html +//! [`thread_rng`]: fn.thread_rng.html +//! [`EntropyRng`]: struct.EntropyRng.html +//! [`OsRng`]: os/struct.OsRng.html +//! [`JitterRng`]: jitter/struct.JitterRng.html +//! [`StdRng`]: struct.StdRng.html +//! [`SmallRng`]: struct.SmallRng.html +//! [`ReseedingRng`]: reseeding/struct.ReseedingRng.html +//! [`prng`]: prng/index.html +//! [`IsaacRng::new_from_u64`]: struct.IsaacRng.html#method.new_from_u64 +//! [`Hc128Rng`]: prng/hc128/struct.Hc128Rng.html +//! [`ChaChaRng`]: prng/chacha/struct.ChaChaRng.html +//! [`IsaacRng`]: prng/struct.IsaacRng.html +//! [`Isaac64Rng`]: prng/struct.Isaac64Rng.html +//! [`seq`]: seq/index.html +//! [`distributions`]: distributions/index.html //! [`Uniform`]: distributions/struct.Uniform.html #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", @@ -767,7 +788,7 @@ impl NewRng for R { /// produce different output depending on the architecture. If you require /// reproducible output, use a named RNG, for example `ChaChaRng`. /// -/// [HC-128]: struct.Hc128Rng.html +/// [HC-128]: prng/hc128/struct.Hc128Rng.html #[derive(Clone, Debug)] pub struct StdRng(Hc128Rng); From 4650ed877e83be39aac91f0ef00f19f96099723e Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sat, 24 Mar 2018 17:40:58 +0000 Subject: [PATCH 7/8] Readme: link both generated doc sites --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 04893783162..bdd8a6c89f5 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,9 @@ See also: [![Build Status](https://travis-ci.org/rust-lang-nursery/rand.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rand) [![Build status](https://ci.appveyor.com/api/projects/status/rm5c9o33k3jhchbw?svg=true)](https://ci.appveyor.com/project/alexcrichton/rand) -[Documentation](https://docs.rs/rand) +Documentation: +[master branch](https://rust-lang-nursery.github.io/rand/rand/index.html), +[by release](https://docs.rs/rand) ## Usage From 5271ffb9e36eebcf240d41f565f71f35b68c75df Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sat, 24 Mar 2018 22:52:20 +0000 Subject: [PATCH 8/8] Disable examples on no-std --- examples/monte-carlo.rs | 3 +++ examples/monty-hall.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/examples/monte-carlo.rs b/examples/monte-carlo.rs index 3d2699698bc..f4ed742cd2c 100644 --- a/examples/monte-carlo.rs +++ b/examples/monte-carlo.rs @@ -25,6 +25,9 @@ //! the square at random, calculate the fraction that fall within the circle, //! and multiply this fraction by 4. +#![cfg(feature="std")] + + extern crate rand; use rand::distributions::{Distribution, Range}; diff --git a/examples/monty-hall.rs b/examples/monty-hall.rs index b8ff1ff4c32..df24ff61c9f 100644 --- a/examples/monty-hall.rs +++ b/examples/monty-hall.rs @@ -27,6 +27,9 @@ //! //! [Monty Hall Problem]: https://en.wikipedia.org/wiki/Monty_Hall_problem +#![cfg(feature="std")] + + extern crate rand; use rand::Rng;