diff --git a/src/distributions/exponential.rs b/src/distributions/exponential.rs index 5b737755..a7d05005 100644 --- a/src/distributions/exponential.rs +++ b/src/distributions/exponential.rs @@ -63,6 +63,8 @@ impl Distribution for Exp1 { /// /// This distribution has density function: `f(x) = lambda * exp(-lambda * x)` /// for `x > 0`. +/// +/// Note that [`Exp1`](struct.Exp1.html) is an optimised implementation for `lambda = 1`. /// /// # Example /// diff --git a/src/distributions/normal.rs b/src/distributions/normal.rs index 06a995d8..b8d632e6 100644 --- a/src/distributions/normal.rs +++ b/src/distributions/normal.rs @@ -74,8 +74,11 @@ impl Distribution for StandardNormal { /// The normal distribution `N(mean, std_dev**2)`. /// -/// This uses the ZIGNOR variant of the Ziggurat method, see `StandardNormal` +/// This uses the ZIGNOR variant of the Ziggurat method, see [`StandardNormal`] /// for more details. +/// +/// Note that [`StandardNormal`] is an optimised implementation for mean 0, and +/// standard deviation 1. /// /// # Example /// @@ -87,6 +90,8 @@ impl Distribution for StandardNormal { /// let v = normal.sample(&mut rand::thread_rng()); /// println!("{} is from a N(2, 9) distribution", v) /// ``` +/// +/// [`StandardNormal`]: struct.StandardNormal.html #[derive(Clone, Copy, Debug)] pub struct Normal { mean: f64, diff --git a/src/lib.rs b/src/lib.rs index 1cac38fb..6b59ff98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,208 +12,39 @@ //! Rand provides utilities to generate random numbers, to convert them to //! useful types and distributions, and some randomness-related algorithms. //! -//! # Basic usage -//! +//! # Quick Start +//! //! To get you started quickly, the easiest and highest-level way to get -//! a random value is to use [`random()`]. -//! -//! ``` -//! let x: u8 = rand::random(); // generates an integer within u8 bounds -//! println!("{}", x); -//! -//! let y = rand::random::(); // generates a float between 0 and 1 -//! println!("{}", y); -//! -//! if rand::random() { // generates a boolean -//! println!("Heads!"); -//! } -//! ``` -//! -//! This supports generating most common types but is not very flexible, thus -//! you probably want to learn a bit more about the Rand library. -//! -//! -//! # The two-step process to get a random value -//! -//! Generating random values is typically a two-step process: -//! -//! - get some *random data* (an integer or bit/byte sequence) from a random -//! number generator (RNG); -//! - use some function to transform that *data* into the type of value you want -//! (this function is an implementation of some *distribution* describing the -//! kind of value produced). -//! -//! Rand represents the first step with the [`RngCore`] trait and the second -//! step via a combination of the [`Rng`] extension trait and the -//! [`distributions` module]. -//! In practice you probably won't use [`RngCore`] directly unless you are -//! implementing a random number generator (RNG). -//! -//! There are many kinds of RNGs, with different trade-offs. You can read more -//! about them in the [`rngs` module] and even more in the [`prng` module], -//! however, often you can just use [`thread_rng()`]. This function -//! automatically initializes an RNG in thread-local memory, then returns a -//! reference to it. It is fast, good quality, and secure (unpredictable). -//! -//! To turn the output of the RNG into something usable, you usually want to use -//! the methods from the [`Rng`] trait. Some of the most useful methods are: -//! -//! - [`gen`] generates a random value appropriate for the type (just like -//! [`random()`]). For integers this is normally the full representable range -//! (e.g. from `0u32` to `std::u32::MAX`), for floats this is between 0 and 1, -//! and some other types are supported, including arrays and tuples. See the -//! [`Standard`] distribution which provides the implementations. -//! - [`gen_range`] samples from a specific range of values; this is like -//! [`gen`] but with specific upper and lower bounds. -//! - [`sample`] samples directly from some distribution. -//! -//! [`random()`] is defined using just the above: `thread_rng().gen()`. -//! -//! ## Distributions -//! -//! What are distributions, you ask? Specifying only the type and range of -//! values (known as the *sample space*) is not enough; samples must also have -//! a *probability distribution*, describing the relative probability of -//! sampling each value in that space. -//! -//! In many cases a *uniform* distribution is used, meaning roughly that each -//! value is equally likely (or for "continuous" types like floats, that each -//! equal-sized sub-range has the same probability of containing a sample). -//! [`gen`] and [`gen_range`] both use statistically uniform distributions. -//! -//! The [`distributions` module] provides implementations -//! of some other distributions, including Normal, Log-Normal and Exponential. -//! -//! It is worth noting that the functionality already mentioned is implemented -//! with distributions: [`gen`] samples values using the [`Standard`] -//! distribution, while [`gen_range`] uses [`Uniform`]. -//! -//! ## Importing (prelude) -//! -//! The most convenient way to import items from Rand is to use the [prelude]. -//! This includes the most important parts of Rand, but only those unlikely to -//! cause name conflicts. -//! -//! Note that Rand 0.5 has significantly changed the module organization and -//! contents relative to previous versions. Where possible old names have been -//! kept (but are hidden in the documentation), however these will be removed -//! in the future. We therefore recommend migrating to use the prelude or the -//! new module organization in your imports. -//! -//! -//! ## Examples +//! a random value is to use [`random()`]; alternatively you can use +//! [`thread_rng()`]. The [`Rng`] trait provides a useful API on all RNGs, while +//! the [`distributions` module] and [`seq` module] provide further +//! functionality on top of RNGs. //! //! ``` //! use rand::prelude::*; -//! -//! // thread_rng is often the most convenient source of randomness: -//! let mut rng = thread_rng(); -//! -//! if rng.gen() { // random bool -//! let x: f64 = rng.gen(); // random number in range [0, 1) -//! println!("x is: {}", x); -//! let ch = rng.gen::(); // using type annotation -//! println!("char is: {}", ch); -//! println!("Number from 0 to 9: {}", rng.gen_range(0, 10)); +//! +//! if rand::random() { // generates a boolean +//! // Try printing a random unicode code point (probably a bad idea)! +//! println!("char: {}", rand::random::()); //! } +//! +//! let mut rng = rand::thread_rng(); +//! let y: f64 = rng.gen(); // generates a float between 0 and 1 +//! +//! let nums: Vec = (1..100).collect(); +//! nums.shuffle(&mut rng); //! ``` //! -//! -//! # More functionality -//! -//! The [`Rng`] trait includes a few more methods not mentioned above: -//! -//! - [`Rng::sample_iter`] allows iterating over values from a chosen -//! distribution. -//! - [`Rng::gen_bool`] generates boolean "events" with a given probability. -//! - [`Rng::fill`] and [`Rng::try_fill`] are fast alternatives to fill a slice -//! of integers. -//! - [`Rng::shuffle`] randomly shuffles elements in a slice. -//! - [`Rng::choose`] picks one element at random from a slice. -//! -//! For more slice/sequence related functionality, look in the [`seq` module]. -//! -//! -//! # Error handling -//! -//! Error handling in Rand is a compromise between simplicity and necessity. -//! Most RNGs and sampling functions will never produce errors, and making these -//! able to handle errors would add significant overhead (to code complexity -//! and ergonomics of usage at least, and potentially also performance, -//! depending on the approach). -//! However, external RNGs can fail, and being able to handle this is important. -//! -//! It has therefore been decided that *most* methods should not return a -//! `Result` type, with as exceptions [`Rng::try_fill`], -//! [`RngCore::try_fill_bytes`], and [`SeedableRng::from_rng`]. -//! -//! Note that it is the RNG that panics when it fails but is not used through a -//! method that can report errors. Currently Rand contains only three RNGs that -//! can return an error (and thus may panic), and documents this property: -//! [`OsRng`], [`EntropyRng`] and [`ReadRng`]. Other RNGs, like [`ThreadRng`] -//! and [`StdRng`], can be used with all methods without concern. -//! -//! One further problem is that if Rand is unable to get any external randomness -//! when initializing an RNG with [`EntropyRng`], it will panic in -//! [`FromEntropy::from_entropy`], and notably in [`thread_rng()`]. Except by -//! compromising security, this problem is as unsolvable as running out of -//! memory. -//! -//! -//! # Distinction between Rand and `rand_core` -//! -//! The [`rand_core`] crate provides the necessary traits and functionality for -//! implementing RNGs; this includes the [`RngCore`] and [`SeedableRng`] traits -//! and the [`Error`] type. -//! Crates implementing RNGs should depend on [`rand_core`]. -//! -//! Applications and libraries consuming random values are encouraged to use the -//! Rand crate, which re-exports the common parts of [`rand_core`]. -//! -//! -//! # More examples -//! -//! For some inspiration, see the examples: -//! -//! - [Monte Carlo estimation of π]( -//! https://github.com/rust-random/rand/blob/master/examples/monte-carlo.rs) -//! - [Monty Hall Problem]( -//! https://github.com/rust-random/rand/blob/master/examples/monty-hall.rs) -//! +//! # The Book +//! +//! For the user guide and futher documentation, please read +//! [The Rust Rand Book](https://rust-random.github.io/book). //! //! [`distributions` module]: distributions/index.html -//! [`FromEntropy::from_entropy`]: trait.FromEntropy.html#tymethod.from_entropy -//! [`EntropyRng`]: rngs/struct.EntropyRng.html -//! [`Error`]: struct.Error.html -//! [`gen_range`]: trait.Rng.html#method.gen_range -//! [`gen`]: trait.Rng.html#method.gen -//! [`OsRng`]: rngs/struct.OsRng.html -//! [prelude]: prelude/index.html -//! [`rand_core`]: https://crates.io/crates/rand_core //! [`random()`]: fn.random.html -//! [`ReadRng`]: rngs/adapter/struct.ReadRng.html -//! [`Rng::choose`]: trait.Rng.html#method.choose -//! [`Rng::fill`]: trait.Rng.html#method.fill -//! [`Rng::gen_bool`]: trait.Rng.html#method.gen_bool -//! [`Rng::gen`]: trait.Rng.html#method.gen -//! [`Rng::sample_iter`]: trait.Rng.html#method.sample_iter -//! [`Rng::shuffle`]: trait.Rng.html#method.shuffle -//! [`RngCore`]: trait.RngCore.html -//! [`RngCore::try_fill_bytes`]: trait.RngCore.html#method.try_fill_bytes -//! [`rngs` module]: rngs/index.html -//! [`prng` module]: prng/index.html //! [`Rng`]: trait.Rng.html -//! [`Rng::try_fill`]: trait.Rng.html#method.try_fill -//! [`sample`]: trait.Rng.html#method.sample -//! [`SeedableRng`]: trait.SeedableRng.html -//! [`SeedableRng::from_rng`]: trait.SeedableRng.html#method.from_rng //! [`seq` module]: seq/index.html -//! [`SmallRng`]: rngs/struct.SmallRng.html -//! [`StdRng`]: rngs/struct.StdRng.html //! [`thread_rng()`]: fn.thread_rng.html -//! [`ThreadRng`]: rngs/struct.ThreadRng.html -//! [`Standard`]: distributions/struct.Standard.html -//! [`Uniform`]: distributions/struct.Uniform.html #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", diff --git a/src/prng/mod.rs b/src/prng/mod.rs index 238c25ef..3c0d27b2 100644 --- a/src/prng/mod.rs +++ b/src/prng/mod.rs @@ -8,312 +8,11 @@ //! Pseudo-random number generators. //! -//! Pseudo-random number generators are algorithms to produce apparently random -//! numbers deterministically, and usually fairly quickly. See the documentation -//! of the [`rngs` module] for some introduction to PRNGs. -//! -//! As mentioned there, PRNGs fall in two broad categories: -//! -//! - [basic PRNGs], primarily designed for simulations -//! - [CSPRNGs], primarily designed for cryptography -//! -//! In simple terms, the basic PRNGs are often predictable; CSPRNGs should not -//! be predictable *when used correctly*. +//! This module is deprecated: //! -//! Contents of this documentation: -//! -//! 1. [The generators](#the-generators) -//! 1. [Performance and size](#performance) -//! 1. [Quality and cycle length](#quality) -//! 1. [Security](#security) -//! 1. [Extra features](#extra-features) -//! 1. [Further reading](#further-reading) -//! -//! -//! # The generators -//! -//! ## Basic pseudo-random number generators (PRNGs) -//! -//! The goal of regular, non-cryptographic PRNGs is usually to find a good -//! balance between simplicity, quality, memory usage and performance. These -//! algorithms are very important to Monte Carlo simulations, and also suitable -//! for several other problems such as randomized algorithms and games (except -//! where there is a risk of players predicting the next output value from -//! previous values, in which case a CSPRNG should be used). -//! -//! Currently Rand provides only one PRNG, and not a very good one at that: -//! -//! | name | full name | performance | memory | quality | period | features | -//! |------|-----------|-------------|--------|---------|--------|----------| -//! | [`Pcg32`] | PCG XSH RR 64/32 (LCG) | ★★★☆☆ | 16 bytes | ★★★☆☆ | `u32` * 264 | — | -//! | [`Pcg64Mcg`] | PCG XSL 128/64 (MCG) | ★★★★☆ | 16 bytes | ★★★☆☆ | `u64` * 2126 | — | -//! | [`XorShiftRng`] | Xorshift 32/128 | ★★★★☆ | 16 bytes | ★☆☆☆☆ | `u32` * 2128 - 1 | — | -//! -// Quality stars [not rendered in documentation]: -// 5. proven cryptographic quality (e.g. ChaCha20) -// 4. potentially cryptographic, but low margin or lack of theory (e.g. ChaCha8, ISAAC) -// 3. good performance on TestU01 and PractRand, good theory -// 2. imperfect performance on tests or other limiting properties, or -// insufficient theory, but not terrible -// 1. clear deficiencies in test results, cycle length, theory, or other -// properties -// -// Performance stars [not rendered in documentation]: -// Meant to give an indication of relative performance. Roughly follows a log -// scale, based on the performance of `next_u64` on a current i5/i7: -// - 5. 8000 MB/s+ -// - 4. 4000 MB/s+ -// - 3. 2000 MB/s+ -// - 2. 1000 MB/s+ -// - 1. < 1000 MB/s -// -//! ## Cryptographically secure pseudo-random number generators (CSPRNGs) -//! -//! CSPRNGs have much higher requirements than basic PRNGs. The primary -//! consideration is security. Performance and simplicity are also important, -//! but in general CSPRNGs are more complex and slower than regular PRNGs. -//! Quality is no longer a concern, as it is a requirement for a -//! CSPRNG that the output is basically indistinguishable from true randomness -//! since any bias or correlation makes the output more predictable. -//! -//! There is a close relationship between CSPRNGs and cryptographic ciphers. -//! Any block cipher can be turned into a CSPRNG by encrypting a counter. Stream -//! ciphers are basically a CSPRNG and a combining operation, usually XOR. This -//! means that we can easily use any stream cipher as a CSPRNG. -//! -//! This crate currently provides two CSPRNGs. The sub-crate `rand_isaac` -//! provides two CSPRNG-like PRNGs: -//! -//! | name | full name | performance | initialization | memory | predictability | forward secrecy | -//! |------|-----------|--------------|--------------|----------|----------------|-------------------------| -//! | [`ChaChaRng`] | ChaCha20 | ★☆☆☆☆ | fast | 136 bytes | secure | no | -//! | [`Hc128Rng`] | HC-128 | ★★☆☆☆ | slow | 4176 bytes | secure | no | -//! | [`IsaacRng`] | ISAAC | ★★☆☆☆ | slow | 2072 bytes | unknown | unknown | -//! | [`Isaac64Rng`] | ISAAC-64 | ★★☆☆☆ | slow | 4136 bytes| unknown | unknown | -//! -//! It should be noted that the ISAAC generators are only included for -//! historical reasons, they have been with the Rust language since the very -//! beginning. They have good quality output and no attacks are known, but have -//! received little attention from cryptography experts. -//! -//! -//! # Performance -//! -//! First it has to be said most PRNGs are very fast, and will rarely be a -//! performance bottleneck. -//! -//! Performance of basic PRNGs is a bit of a subtle thing. It depends a lot on -//! the CPU architecture (32 vs. 64 bits), inlining, and also on the number of -//! available registers. This often causes the performance to be affected by -//! surrounding code due to inlining and other usage of registers. -//! -//! When choosing a PRNG for performance it is important to benchmark your own -//! application due to interactions between PRNGs and surrounding code and -//! dependence on the CPU architecture as well as the impact of the size of -//! data requested. Because of all this, we do not include performance numbers -//! here but merely a qualitative rating. -//! -//! CSPRNGs are a little different in that they typically generate a block of -//! output in a cache, and pull outputs from the cache. This allows them to have -//! good amortised performance, and reduces or completely removes the influence -//! of surrounding code on the CSPRNG performance. -//! -//! ### Worst-case performance -//! Because CSPRNGs usually produce a block of values into a cache, they have -//! poor worst case performance (in contrast to basic PRNGs, where the -//! performance is usually quite regular). -//! -//! ## State size -//! -//! Simple PRNGs often use very little memory, commonly only a few words, where -//! a *word* is usually either `u32` or `u64`. This is not true for all -//! non-cryptographic PRNGs however, for example the historically popular -//! Mersenne Twister MT19937 algorithm requires 2.5 kB of state. -//! -//! CSPRNGs typically require more memory; since the seed size is recommended -//! to be at least 192 bits and some more may be required for the algorithm, -//! 256 bits would be approximately the minimum secure size. In practice, -//! CSPRNGs tend to use quite a bit more, [`ChaChaRng`] is relatively small with -//! 136 bytes of state. -//! -//! ## Initialization time -//! -//! The time required to initialize new generators varies significantly. Many -//! simple PRNGs and even some cryptographic ones (including [`ChaChaRng`]) -//! only need to copy the seed value and some constants into their state, and -//! thus can be constructed very quickly. In contrast, CSPRNGs with large state -//! require an expensive key-expansion. -//! -//! # Quality -//! -//! Many basic PRNGs are not much more than a couple of bitwise and arithmetic -//! operations. Their simplicity gives good performance, but also means there -//! are small regularities hidden in the generated random number stream. -//! -//! How much do those hidden regularities matter? That is hard to say, and -//! depends on how the RNG gets used. If there happen to be correlations between -//! the random numbers and the algorithm they are used in, the results can be -//! wrong or misleading. -//! -//! A random number generator can be considered good if it gives the correct -//! results in as many applications as possible. The quality of PRNG -//! algorithms can be evaluated to some extend analytically, to determine the -//! cycle length and to rule out some correlations. Then there are empirical -//! test suites designed to test how well a PRNG performs on a wide range of -//! possible uses, the latest and most complete of which are [TestU01] and -//! [PractRand]. -//! -//! CSPRNGs tend to be more complex, and have an explicit requirement to be -//! unpredictable. This implies there must be no obvious correlations between -//! output values. -//! -//! ### Quality stars: -//! PRNGs with 3 stars or more should be good enough for any purpose. -//! 1 or 2 stars may be good enough for typical apps and games, but do not work -//! well with all algorithms. -//! -//! ## Period -//! -//! The *period* or *cycle length* of a PRNG is the number of values that can be -//! generated after which it starts repeating the same random number stream. -//! Many PRNGs have a fixed-size period, but for some only an expected average -//! cycle length can be given, where the exact length depends on the seed. -//! -//! On today's hardware, even a fast RNG with a cycle length of *only* -//! 264 can be used for centuries before cycling. Yet we recommend a -//! period of 2128 or more, which most modern PRNGs satisfy. -//! Alternatively a PRNG with shorter period but support for multiple streams -//! may be chosen. There are two reasons for this, as follows. -//! -//! If we see the entire period of an RNG as one long random number stream, -//! every independently seeded RNG returns a slice of that stream. When multiple -//! RNG are seeded randomly, there is an increasingly large chance to end up -//! with a partially overlapping slice of the stream. -//! -//! If the period of the RNG is 2128, and an application consumes -//! 248 values, it then takes about 232 random -//! initializations to have a chance of 1 in a million to repeat part of an -//! already used stream. This seems good enough for common usage of -//! non-cryptographic generators, hence the recommendation of at least -//! 2128. As an estimate, the chance of any overlap in a period of -//! size `p` with `n` independent seeds and `u` values used per seed is -//! approximately `1 - e^(-u * n^2 / (2 * p))`. -//! -//! Further, it is not recommended to use the full period of an RNG. Many -//! PRNGs have a property called *k-dimensional equidistribution*, meaning that -//! for values of some size (potentially larger than the output size), all -//! possible values are produced the same number of times over the generator's -//! period. This is not a property of true randomness. This is known as the -//! generalized birthday problem, see the [PCG paper] for a good explanation. -//! This results in a noticable bias on output after generating more values -//! than the square root of the period (after 264 values for a -//! period of 2128). -//! -//! -//! # Security -//! -//! ## Predictability -//! -//! From the context of any PRNG, one can ask the question *given some previous -//! output from the PRNG, is it possible to predict the next output value?* -//! This is an important property in any situation where there might be an -//! adversary. -//! -//! Regular PRNGs tend to be predictable, although with varying difficulty. In -//! some cases prediction is trivial, for example plain Xorshift outputs part of -//! its state without mutation, and prediction is as simple as seeding a new -//! Xorshift generator from four `u32` outputs. Other generators, like -//! [PCG](http://www.pcg-random.org/predictability.html) and truncated Xorshift* -//! are harder to predict, but not outside the realm of common mathematics and a -//! desktop PC. -//! -//! The basic security that CSPRNGs must provide is the infeasibility to predict -//! output. This requirement is formalized as the [next-bit test]; this is -//! roughly stated as: given the first *k* bits of a random sequence, the -//! sequence satisfies the next-bit test if there is no algorithm able to -//! predict the next bit using reasonable computing power. -//! -//! A further security that *some* CSPRNGs provide is forward secrecy: -//! in the event that the CSPRNGs state is revealed at some point, it must be -//! infeasible to reconstruct previous states or output. Note that many CSPRNGs -//! *do not* have forward secrecy in their usual formulations. -//! -//! As an outsider it is hard to get a good idea about the security of an -//! algorithm. People in the field of cryptography spend a lot of effort -//! analyzing existing designs, and what was once considered good may now turn -//! out to be weaker. Generally it is best to use algorithms well-analyzed by -//! experts, such as those recommended by NIST or ECRYPT. -//! -//! ## State and seeding -//! -//! It is worth noting that a CSPRNG's security relies absolutely on being -//! seeded with a secure random key. Should the key be known or guessable, all -//! output of the CSPRNG is easy to guess. This implies that the seed should -//! come from a trusted source; usually either the OS or another CSPRNG. Our -//! seeding helper trait, [`FromEntropy`], and the source it uses -//! ([`EntropyRng`]), should be secure. Additionally, [`ThreadRng`] is a CSPRNG, -//! thus it is acceptable to seed from this (although for security applications -//! fresh/external entropy should be preferred). -//! -//! Further, it should be obvious that the internal state of a CSPRNG must be -//! kept secret. With that in mind, our implementations do not provide direct -//! access to most of their internal state, and `Debug` implementations do not -//! print any internal state. This does not fully protect CSPRNG state; code -//! within the same process may read this memory (and we allow cloning and -//! serialisation of CSPRNGs for convenience). Further, a running process may be -//! forked by the operating system, which may leave both processes with a copy -//! of the same generator. -//! -//! ## Not a crypto library -//! -//! It should be emphasised that this is not a cryptography library; although -//! Rand does take some measures to provide secure random numbers, it does not -//! necessarily take all recommended measures. Further, cryptographic processes -//! such as encryption and authentication are complex and must be implemented -//! very carefully to avoid flaws and resist known attacks. It is therefore -//! recommended to use specialized libraries where possible, for example -//! [openssl], [ring] and the [RustCrypto libraries]. -//! -//! -//! # Extra features -//! -//! Some PRNGs may provide extra features, like: -//! -//! - Support for multiple streams, which can help with parallel tasks. -//! - The ability to jump or seek around in the random number stream; -//! with large periood this can be used as an alternative to streams. -//! -//! -//! # Further reading -//! -//! There is quite a lot that can be said about PRNGs. The [PCG paper] is a -//! very approachable explaining more concepts. -//! -//! A good paper about RNG quality is -//! ["Good random number generators are (not so) easy to find"]( -//! http://random.mat.sbg.ac.at/results/peter/A19final.pdf) by P. Hellekalek. -//! -//! -//! [`rngs` module]: ../rngs/index.html -//! [basic PRNGs]: #basic-pseudo-random-number-generators-prngs -//! [CSPRNGs]: #cryptographically-secure-pseudo-random-number-generators-csprngs -//! [`Pcg32`]: ../../rand_pcg/type.Pcg32.html -//! [`Pcg64Mcg`]: ../../rand_pcg/type.Pcg64Mcg.html -//! [`XorShiftRng`]: ../../rand_xorshift/struct.XorShiftRng.html -//! [`ChaChaRng`]: ../../rand_chacha/struct.ChaChaRng.html -//! [`Hc128Rng`]: ../../rand_hc/struct.Hc128Rng.html -//! [`IsaacRng`]: ../../rand_isaac/isaac/struct.IsaacRng.html -//! [`Isaac64Rng`]: ../../rand_isaac/isaac64/struct.Isaac64Rng.html -//! [`ThreadRng`]: ../rngs/struct.ThreadRng.html -//! [`FromEntropy`]: ../trait.FromEntropy.html -//! [`EntropyRng`]: ../rngs/struct.EntropyRng.html -//! [TestU01]: http://simul.iro.umontreal.ca/testu01/tu01.html -//! [PractRand]: http://pracrand.sourceforge.net/ -//! [PCG paper]: http://www.pcg-random.org/pdf/hmc-cs-2014-0905.pdf -//! [openssl]: https://crates.io/crates/openssl -//! [ring]: https://crates.io/crates/ring -//! [RustCrypto libraries]: https://github.com/RustCrypto -//! [next-bit test]: https://en.wikipedia.org/wiki/Next-bit_test +//! - documentation has moved to +//! [The Book](https://rust-random.github.io/book/guide-rngs.html), +//! - PRNGs have moved to other `rand_*` crates. // Deprecations (to be removed in 0.7) #[doc(hidden)] #[allow(deprecated)]