# The Rust Rand Book

This is the extended documentation for Rust's **Rand**om number library.

This book contains:

- An overview of crates and functionality
- Documentation of crate feature flags
- The Users' Guide
- Notes on Portability and Reproducibility. (Read this if you want reproducibility across builds.)
- Updating guides
- Contributor's guide

Outside this book, you may want:

- API reference for the latest release
- API reference for the master branch
- The Rand repository
- The Book source

# Crates

The Rand library consists of a family of crates. For common usage, the `rand`

crate alone will often suffice. Other crates serve as building-blocks and/or
provide additional functionality.

### rand_core

The `rand_core`

crate defines the core traits implemented by RNGs. This exists
as a separate crate with two purposes:

- to provide a minimal API for defining and using RNGs
- to provide tools to aid implementation of RNGs

The `RngCore`

, `SeedableRng`

, `CryptoRng`

traits and `Error`

type are
all defined by this crate and re-exported by the `rand`

crate.

### rand

The `rand`

crate is optimised for easy usage of common random-number
functionality. This has several aspects:

- the
`rngs`

module provides a few convenient generators - the
`distributions`

module concerns sampling of random values - the
`seq`

module concerns sampling from and shuffling sequences - the
`Rng`

trait provides a few convenience methods for generating random values - the
`random`

function provides convenient generation in a single call

## Distributions

The `rand`

crate only implements sampling from the most common random
number distributions: uniform and weighted sampling. For everything else,

`rand_distr`

provides fast sampling from a variety of other distributions, including Normal (Gauss), Binomial, Poisson, UnitCircle, and many more`statrs`

is a port of the C# Math.NET library, implementing many of the same distributions (plus/minus a few), along with PDF and CDF functions, the*error*,*beta*,*gamma*and*logistic*special functions, plus a few utilities. (For clarity,`statrs`

is not part of the Rand library.)

## Generators

### Deterministic generators

The following crates implement [PRNGs]:

`rand_chacha`

provides generators using the ChaCha cipher`rand_hc`

implements a generator using the HC-128 cipher`rand_isaac`

implements the ISAAC generators`rand_pcg`

implements a small selection of PCG generators`rand_xoshiro`

implements the SplitMix and Xoshiro generators`rand_xorshift`

implements the basic Xorshift generator

### Non-deterministic generators

The following crates provide non-deterministic random data:

`getrandom`

provides an interface to system-specific random data sources`rand_os`

provides a simple RNG wrapping`getrandom`

functionality (this wrapper is duplicated by the`rand`

crate)`rand_jitter`

implements a CPU-jitter-based entropy harvestor

# Feature flags

Some functionality is gated behind Cargo features, which must be enabled as required, e.g.

```
rand = { version = "0.7", features = ["log", "serde1"] }
```

### Small RNG

From Rand version 0.7, the `SmallRng`

type is gated behind the `small_rng`

feature flag (this reduces `rand`

's depnedency count by one if not used).

### Logging

Rand can optionally log a few events (mostly related to reseeding of
`ThreadRng`

and to `rand_jitter`

).

### Serde

Some parts of the Rand lib support serialisation via Serde.
To enable this, use the `serde1`

feature.

Note that cryptographic RNGs *do not* support serialisation since this could be
a security risk. If you need state-restore functionality on a cryptographic RNG,
the ChaCha generator supports getting and setting the stream position,
which, together with the seed, can be used to reconstruct the generator's state.

### SIMD support

Experimental support for generating SIMD values is available under the
`simd_support`

feature gate. This requires nightly Rust.

The ChaCha implementations provided by `rand_chacha`

use SIMD operations
internally even on stable Rust. This is enabled by default.

### No-std mode

Almost all Rand libraries can be used without Rust's standard library:

- For the
`rand`

and`rand_chacha`

crates, one must disable default features (`default-features = false`

) and some functionality is lost. - The
`rand_core`

and`rand_jitter`

crates assume`no_std`

by default, but support some additional functionality when the`std`

feature is enabled. `getrandom`

(and by extension`rand_os`

) has limited support for`no_std`

. It does not use feature flags, instead detecting requirements based on the target platform.- The
`rand_distr`

crate does not support`no_std`

mode. - All PRNG crates other than
`rand_chacha`

do not require`std`

.

If an allocator is available, some functionality can be recovered by use of the
`alloc`

feature. On:

`rand_core`

, the`alloc`

feature enables blanket trait impls for`Box<T>`

`rand`

, the`alloc`

feature enables sequence-related functionality

# Guide

This section attempts to explain some of the concepts used in this library.

- Intro: Hello Random example
- What is random data and what is randomness anyway?
- What kind of random generators are there?
- What random number generators does Rand provide?
- Turning random data into useful values
- Distributions: more control over random values
- Sequences
- Error handling

## Importing items (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.

## Further examples

For some inspiration, see the example applications:

# Getting Started

Lets kick things off with an example (playground link):

`# extern crate rand; // import commonly used items from the prelude: use rand::prelude::*; fn main() { // We can use random() immediately. It can produce values of many common types: let x: u8 = random(); println!("{}", x); if random() { // generates a boolean println!("Heads!"); } // If we want to be a bit more explicit (and a little more efficient) we can // make a handle to the thread-local generator: let mut rng = thread_rng(); if rng.gen() { // random bool let x: f64 = rng.gen(); // random number in range [0, 1) let y = rng.gen_range(-10.0, 10.0); println!("x is: {}", x); println!("y is: {}", y); println!("Number from 0 to 9: {}", rng.gen_range(0, 10)); } // Sometimes it's useful to use distributions directly: let distr = rand::distributions::Uniform::new_inclusive(1, 100); let mut nums = [0i32; 3]; for x in &mut nums { *x = rng.sample(distr); } println!("Some numbers: {:?}", nums); // We can also interact with iterators and slices: let arrows_iter = "➡⬈⬆⬉⬅⬋⬇⬊".chars(); println!("Lets go in this direction: {}", arrows_iter.choose(&mut rng).unwrap()); let mut nums = [1, 2, 3, 4, 5]; nums.shuffle(&mut rng); println!("I shuffled my {:?}", nums); }`

The first thing you may have noticed is that we imported everything from the
prelude. This is the lazy way to `use`

rand, and like the
standard library's prelude,
only imports the most common items. If you don't wish to use the prelude,
remember to import the `Rng`

trait!

The Rand library automatically initialises a secure, thread-local generator
on demand. This can be accessed via the `thread_rng`

and `random`

functions.
For more on this topic, see Random generators.

While the `random`

function can only sample values in a `Standard`

(type-dependent) manner, `thread_rng`

gives you a handle to a generator.
All generators implement the `Rng`

trait, which provides the `gen`

,
`gen_range`

and `sample`

methods used above.

Rand provides functionality on iterators and slices via two more traits,
`IteratorRandom`

and `SliceRandom`

.

# Random data

`# #![allow(unused_variables)] #fn main() { # extern crate rand; # use rand::RngCore; // get some random data: let mut data = [0u8; 32]; rand::thread_rng().fill_bytes(&mut data); #}`

## What is randomness?

What does **random** mean? Colloquially the word can mean simply *unexpected*
or *unknown*, but we need to be a bit more precise than that. Wikipedia gives us
a more specific definition:

Randomnessis the lack of pattern or predictability in events.

We can take this further: *lack of pattern* implies there is no *bias*; in
other words, all possible values are equally likely.

To understand what a *random value* is, we still need a context: what pool of
numbers can our random value come from?

- To give a simple example, consider dice: they have values 1, 2, 3, 4, 5 and 6, and an unbiased (fair) die will make each number equally likely, with probability ⅙th.
- Now lets take a silly example: the natural numbers (1, 2, 3, etc.). These
numbers have no limit. So if you were to ask for an unbiased random
natural number, 1, 5, 1000, 1 million, 1 trillion — all would be equally
likely. In fact, for
*any*natural number`k`

, the numbers`1, 2, ..., k`

are an infinitely small fraction of all the natural numbers, which means the chance of picking a unbiased number from this range is effectively`1/∞ = 0`

. Put another way: for*any*natural number, we expect an unbiased random value to be bigger. This is impossible, so there cannot be any such thing as an unbiased random natural number. - Another example: real numbers between 0 and 1. Real numbers include all the
fractions, irrational numbers like π and √2, and all multiples of those...
there are infinitely many possibilities, even in a small range like
`(0, 1)`

, so simply saying "all possibilities are equally likely" is not enough. Instead we interpret*lack of pattern*in a different way: every interval of equal size is equally likely; for example we could subdivide the interval`0,1`

into`0,½`

and`½,1`

and toss a coin to decide which interval our random sample comes from. Say we pick`½,1`

we can then toss another coin to decide between`½,¾`

and`¾,1`

, restricting our random value to an interval of size`¼`

. We can repeat this as many times as necessary to pick a random value between`0`

and`1`

with as much precision as we want — although we should realise that we are not choosing an*exact*value but rather just a small interval.

What we have defined (or failed to define) above are uniform random number
distributions, or simply **uniform distributions**. There are also non-uniform
distributions, as we shall see later. It's also worth noting here that a
uniform distribution does not imply that its samples will be *evenly* spread
(try rolling six dice: you probably won't get 1, 2, 3, 4, 5, 6).

To bring us back to computing, we can now define what a uniformly distributed random value (an unbiased random value) is in several contexts:

`u32`

: a random number between 0 and`u32::MAX`

where each value is equally likely`BigInt`

: since this type has no upper bound, we cannot produce an unbiased random value (it would be infinitely large, and use infinite amounts of memory)`f64`

: we treat this as an approximation of the real numbers, and,*by convention*, restrict to the range 0 to 1 (if not otherwise specified). Note that this type has finite precision, so we use the coin-flipping method above (but with random bits instead of coins) until we get as much precision as the type can represent; however, since floating-point numbers are much more precise close to 0 than they are near 1, we typically simplify here and stop once we have enough precision to differentiate between 1 and the next smallest value representable (`1 - ε/2`

).

## Random data

As seen above, the term "random number" is meaningless without context. "Random
data" typically means a sequence of random *bytes*, where for each byte, each of
the 256 possible values are equally likely.

`RngCore::fill_bytes`

produces exactly this: a sequence of random bytes.

If a sequence of unbiased random bytes of the correct length is instead
interpreted as an integer — say a `u32`

or `u64`

— the result is an unbiased
integer. Since this conversion is trivial, `RngCore::next_u32`

and
`RngCore::next_u64`

are part of the same trait. (In fact the conversion is
often the other way around — algorithmic generators usually work with integers
internally, which are then converted to whichever form of random data is
required.)

# Random generators

The previous section introduced `RngCore`

, the trait which all *random data
sources* must implement. But what exactly is a random data source?

This section concerns theory; see also the chapter on random number generators.

`# #![allow(unused_variables)] #fn main() { # extern crate rand; // prepare a random number generator: let mut rng = rand::thread_rng(); #}`

## True random number generators

A **true** random number generator (TRNG) is something which produces random
numbers by observing some natural process, such as atomic decay or thermal noise.
(Whether or not these things are *truly* random or are in fact deterministic —
for example if the universe itself is a simulation — is besides the point here.
For our purposes, it is sufficient that they are not distinguishable from true
randomness.)

Note that these processes are often biased, thus some type of *debiasing* must
be used to yield the unbiased random data we desire.

## Pseudo-random number generators

CPUs are of course supposed to compute deterministically, yet it turns out they can do a pretty good job of emulating random processes. Most pseudo-random number generators are deterministic and can be defined by three things:

- some initial
*state* - a function to compute a random value from the state
- a function to advance to the next state

The fact that these are deterministic can sometimes be very useful: it allows a simulation, randomised art work or game to be repeated exactly, producing a result which is a function of the seed. For more on this see the portability chapter (note that determinicity alone isn't enough to guarantee reproducibility).

The other big attraction of PRNGs is their speed: some of these algorithms require only a few CPU operations per random value, and thus can produce random data on demand much more quickly than most TRNGs.

Note however that PRNGs have several limitations:

- They are no stronger than their seed: if the seed is known or guessable, and the algorithm is known (or guessed), then only a small number of output sequences are likely.
- Since the state size is usually fixed, only a finite number of output values are possible before the generator loops and repeats itself.
- Several algorithms are easily predictable after seeing a few values, and with many other algorithms it is not clear whether they could be "cracked".

## Cryptographically secure pseudo-random number generator

Cryptographically secure pseudo-random number generators (CSPRNGs) are the subset of PRNGs which are considered secure. That is:

- their state is sufficiently large that a brute-force approach simply trying all initial values is not a feasible method of finding the initial state used to produce an observed sequence of output values,
- and there is no other algorithm which is sufficiently better than the brute-force method which would make it feasible to predict the next output value.

Achieving secure generation requires not only a secure algorithm (CSPRNG), but also a secure and sufficiently large seed value (typically 256 bits), and protection against side-channel attacks (i.e. preventing attackers from reading the internal state).

Some CSPRNGs additionally satisfy a third property:

- a CSPRNG is backtracking resistant if it is impossible for an attacker to calculate prior output values of the PRNG despite having discovered the value of the current internal state (implying that all future output is compromised).

## Hardware random number generator

A **hardware** random number generator (HRNG) is theoretically an adaptor from
some TRNG to digital information. In practice, these may use a PRNG to debias
the TRNG. Even though an HRNG has some underlying TRNG, it is not guaranteed to
be secure: the TRNG itself may produce insufficient entropy (i.e. be too
predictable), or the signal amplification and debiasing process may be flawed.

An HRNG may be used to provide the seed for a PRNG, although usually this is not the only way to obtain a secure seed (see the next section). An HRNG might replace a PRNG altogether, although since we now have very fast and very strong software PRNGs, and since software implementations are easier to verify than hardware ones, this is often not the preferred solution.

Since a PRNG needs a random seed value to be secure, an HRNG may be used to
provide that seed, or even replace the need for a PRNG. However, since the goal
is usually "only" to produce unpredictable random values, there are acceptable
alternatives to *true* random number generators (see next section).

## Entropy

As noted above, for a CSPRNG to be secure, its seed value must also be secure.
The word *entropy* can be used in two ways:

- as a measure of the amount of unknown information in some piece of data
- as a piece of unknown data

Ideally, a random boolean or a coin flip has 1 bit of entropy, although if the value is biased, there will be less. Shannon Entropy attempts to measure this.

For example, a Unix time-stamp (seconds since the start of 1970) contains both
high- and low-resolution data. This is typically a 32-bit number, but the amount
of *entropy* will depend on how precisely a hypothetical attacker can guess the
number. If an attacker can guess the number to the nearest minute, this may be
approximately 6 bits (2^6 = 64); if an attacker can guess this to the second,
this is 0 bits. `JitterRng`

uses this concept to scavenge entropy without an
HRNG (but using nanosecond resolution timers and conservatively assuming only a
couple of bits entropy is available per time-stamp, after running several tests
on the timer's quality).

# Our RNGs

There are many kinds of RNGs, with different trade-offs. Rand provides some
convenient generators in the `rngs`

module. Often you can just use
`thread_rng`

, a function which automatically initializes an RNG in
thread-local memory and returns a reference to it. It is fast, good quality,
and (to the best of our knowledge) cryptographically secure.

Contents of this documentation:

- The generators
- Performance and size
- Quality and cycle length
- Security
- Extra features
- 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. Non-cryptographic generators pre-date cryptographic ones and since we now have fast cryptographic generators, some people argue that the non-cryptographic ones are now obsolete. They can however have some advantages: small state size, fast initialisation and simplicity (though this is not true of all non-crypto PRNGs; e.g. the Mersenne Twister has a large state despite being easy to predict).

These algorithms are very important to Monte Carlo simulations, and also suitable for several other problems such as randomized algorithms and games, where predictability is not an issue. (Note that it might be problematic for betting games and multiplayer games, where a cryptographic PRNG is usually more appropriate.)

The Rand project provides the following non-cryptographic PRNGs:

name | full name | performance | memory | quality | period | features |
---|---|---|---|---|---|---|

`Pcg32` | PCG XSH RR 64/32 (LCG) | ★★★☆☆ | 16 bytes | ★★★☆☆ | `u32` * 2^{64} | — |

`Pcg64Mcg` | PCG XSL 128/64 (MCG) | ★★★★☆ | 16 bytes | ★★★☆☆ | `u64` * 2^{126} | — |

`XorShiftRng` | Xorshift 32/128 | ★★★★☆ | 16 bytes | ★☆☆☆☆ | `u32` * 2^{128} - 1 | — |

`Xoshiro256StarStar` | Xoshiro256** | ★★★★☆ | 32 bytes | ★★★☆☆ | `u64` * 2^{256} - 1 | jump-ahead |

`Xoshiro256Plus` | Xoshiro256+ | ★★★★★ | 32 bytes | ★★☆☆☆ | `u64` * 2^{256} - 1 | jump-ahead |

## 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 library provides the following CSPRNGs. We can make no guarantees of any security claims.

name | full name | performance | initialization | memory | security (predictability) | forward secrecy |
---|---|---|---|---|---|---|

`ChaCha20Rng` | ChaCha20 | ★★☆☆☆ | fast | 136 bytes | rigorously analysed | no |

`ChaCha8Rng` | ChaCha8 | ★★★☆☆ | fast | 136 bytes | small security margin | no |

`Hc128Rng` | HC-128 | ★★☆☆☆ | slow | 4176 bytes | recommended by eSTREAM | 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.

# Notes on generators

## 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

Simple PRNGs typically produce each random value on demand. In contrast, CSPRNGs usually produce a whole block at once, then read from this cache until it is exhausted, giving them much less consistent performance when drawing small quantities of random data.

### Memory usage

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 most non-crypto applications. 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*
2^{64} can be used sequentially for centuries before cycling. However,
this is not the case for parallel applications. We recommend a period of
2^{128} 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 2^{128}, and an application consumes
2^{48} values, it then takes about 2^{32} 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
2^{128}. 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 2^{64} values for a
period of 2^{128}).

## 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 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.

Verifying security claims of an algorithm is a *hard problem*, and we are not
able to provide any guarantees of the security of algorithms used or recommended
by this project. We refer you to the NIST institute and ECRYPT network
for recommendations.

### 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 very approachable and explains more concepts.

Another good paper about RNG quality is "Good random number generators are (not so) easy to find" by P. Hellekalek.

# Random values

Now that we have a way of producing random data, how can we convert it to the type of value we want?

This is a trick question: we need to know both the *range* we want and the type
of *distribution* of this value (which is what the `next`

section
is all about).

For convenience, all generators automatically implement the `Rng`

trait,
which provides short-cuts to a few ways of generating values. This has several
convenience functions for producing uniformly distributed values:

`gen`

generates an unbiased random value from a range appropriate for the type. 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. More on this in the next section.`gen_range`

generates an unbiased random value with given bounds`low`

(inclusive) and`high`

(exclusive)`fill`

and`try_fill`

are optimised functions for filling any byte or integer slice with random values

It also has convenience functions for producing non-uniform boolean values:

`gen_bool`

generates a boolean with the given probability`gen_ratio`

also generates a boolean, where the probability is defined via a fraction

Finally, it has a function to sample from arbitrary distributions:

`sample`

samples directly from some distribution

Examples:

`# #![allow(unused_variables)] #fn main() { # extern crate rand; use rand::Rng; let mut rng = rand::thread_rng(); // an unbiased integer over the entire range: let i: i32 = rng.gen(); // a uniformly distributed value between 0 and 1: let x: f64 = rng.gen(); // simulate rolling a die: let roll = rng.gen_range(1, 7); #}`

Additionally, the `random`

function is a short-cut to `gen`

on the `thread_rng`

:

`# #![allow(unused_variables)] #fn main() { if rand::random() { println!("we got lucky!"); } #}`

# Random distributions

For maximum flexibility when producing random values, we define the
`Distribution`

trait:

`# #![allow(unused_variables)] #fn main() { // a producer of data of type T: pub trait Distribution<T> { // the key function: fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T; // a convenience function defined using sample: fn sample_iter<'a, R>(&'a self, rng: &'a mut R) -> DistIter<'a, Self, R, T> where Self: Sized, R: Rng, { ... } } #}`

Rand provides implementations of many different distributions; for the full
list see the `distributions`

module; the most common are highlighted below.

## Uniform distributions

The most obvious type of distribution is the one we already discussed: one
without pattern, where each value or range of values is equally likely. This is
known as *uniform*.

Rand actually has several variants of this:

`Standard`

requires no parameters and produces uniformly distributed values over the entire range of the output type (for`bool`

and integers) or over the range from 0 to 1 (for floats) or over valid Unicode code points. It also has extensions to tuples, array types and`Option`

.`Uniform`

is parametrised with`low`

and`high`

points, and produces values uniformly distributed within this range.`Alphanumeric`

is uniform over the values`0-9A-Za-z`

`Open01`

and`OpenClosed01`

are variations of`Standard`

for floating point numbers between 0 and 1 (partially) exclusive of end points.

For convenience, `Rng::gen`

and `random`

are short-cuts to `Standard`

,
and `Rng::gen_range`

is a short-cut to `Uniform`

, allowing things like:

`# #![allow(unused_variables)] #fn main() { # extern crate rand; # use rand::prelude::*; let mut rng = thread_rng(); let coord: (f64, f64) = rng.gen(); let die_roll = rng.gen_range(1, 7); #}`

## More continuous distributions

The exponential distribution, `Exp`

, simulates time until decay, assuming a
fixed rate of decay (i.e. exponential decay).

The `Normal`

distribution (also known as Gaussian) simulates sampling from
the Normal distribution ("Bell curve") with the given mean and standard
deviation. The `LogNormal`

is related: for sample `X`

from the log-normal
distribution, `log(X)`

is normally distributed; this "skews" the normal
distribution to avoid negative values and to have a long positive tail.

The `UnitCircle`

and `UnitSphereSurface`

distributions simulate uniform
sampling from the edge of a circle or surface of a sphere.

The `Cauchy`

distribution (also known as the Lorentz distribution) is the
distribution of the x-intercept of a ray from point `(x0, γ)`

with uniformly
distributed angle.

The `Beta`

distribution is a two-parameter probability distribution, whose
output values lie between 0 and 1. The `Dirichlet`

distribution is a
generalisation to any positive number of parameters.

## Discrete distributions

The `Bernoulli`

distribution is very simple: given a probability `p`

(or a
ratio `num / denom`

), a boolean value is produced with the given probability
of being `true`

(simulating a trial with probability `p`

of success).

For convenience, `Rng::gen_bool`

and `Rng::gen_ratio`

are short-cuts to `Bernoulli`

.

The `Binomial`

distribution is related: given a probability `p`

and a number
`n`

, this distribution simulates running `n`

Bernoulli trials and tells you the
number which were successful.

The `Poisson`

distribution expresses the expected number of events occurring
within a fixed interval, given that events occur with fixed rate λ.

## Weighted sampling

Finally, `WeightedIndex`

is a discrete distribution sampling from a finite
selection of choices each with given weight.

# Sequences

Rand implements a few common random operations on sequences via the
`IteratorRandom`

and `SliceRandom`

traits:

`choose`

one element uniformly from the sequence`choose_multiple`

elements uniformly without replacement`choose_weighted`

— choose an element non-uniformly by use of a defined weight from a slice (also see the`WeightedIndex`

distribution)`shuffle`

a slice`partial_shuffle`

a slice, effectively extracting`amount`

elements in random order

# 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, but with a few important exceptions, namely:

Most functions consuming random values will not attempt any error handling, and
reduce to calls to `RngCore`

's "infallible" methods. Since most RNGs cannot
fail anyway this is usually not a problem, but the few generators which can may
be forced to fail in this case:

`OsRng`

interfaces with the Operating System's generator; in rare cases this may fail as "not ready" or simply "unavailable".`JitterRng`

is a generator based on timer jitter; if the timer does not appear to be capable of sufficient precision or is too predictable, this will fail.`EntropyRng`

is an abstraction over the above, falling back to the next option when the first fails but ultimately failing if all sources fail`thread_rng`

seeds itself via`EntropyRng`

, thus can potentially fail on its first use on each thread (though it never fails after the first use)`ReadRng`

tries to read data from its source but fails when the stream ends or errors (though it retries on interrupt).

# Portability

## Definitions

Given fixed inputs, all items (should) fall into one of three categories:

- Output is non-deterministic, thus never reproducible
- Output is deterministic, but not considered portable
- Output is deterministic and portable

In general, functionality is considered deterministic and portable *unless*
it is clearly non-deterministic (e.g. `getrandom`

, `ThreadRng`

) *or* it is
documented as being unportable (e.g. `StdRng`

, `SmallRng`

).

## Crate versions

We try to follow semver rules regarding
API-breaking changes and `MAJOR.MINOR.PATCH`

versions:

- New
*patch*versions should not include API-breaking changes or major new features - Before 1.0,
*minor*versions may include API breaking changes. After 1.0 they should not.

Additionally, we must also consider *value-breaking changes* and *portability*.
When given fixed inputs,

- For non-deterministic items, implementations may change in any release
- For deterministic unportable items, output should be preserved in patch releases, but may change in any minor release (including after 1.0)
- For portable items, any change of output across versions is considered equivalent to an API breaking change.

## Portability of usize

There is unfortunately one non-portable item baked into the heart of the Rust
language: `usize`

(and `isize`

). For example, the size of an empty
`Vec`

will differ on 32-bit and 64-bit targets. For most purposes this is not an
issue, but when it comes to generating random numbers in a portable manner
it does matter.

A simple rule follows: if portability is required, *never* sample a `usize`

or
`isize`

value directly.

Within Rand we adhere to this rule whenever possible. All sequence-releated
code requiring a bounded `usize`

value will sample a `u32`

value unless the
upper bound exceeds `u32::MAX`

.
(Note that this actually improves benchmark performance in many cases.)

# Updating

This guide is intended to facilitate upgrading to the next minor or major version of Rand. Note that updating to the next patch version (e.g. 0.5.1 to 0.5.2) should never require code changes.

This guide gives a few more details than the changelog, in particular giving guidance on how to use new features and migrate away from old ones.

# Updating to 0.5

The 0.5 release has quite significant changes over the 0.4 release; as such, it may be worth reading through the following coverage of breaking changes. This release also contains many optimisations, which are not detailed below.

## Crates

We have a new crate: `rand_core`

! This crate houses some important traits,
`RngCore`

, `BlockRngCore`

, `SeedableRng`

and `CryptoRng`

, the error types, as
well as two modules with helpers for implementations: `le`

and `impls`

. It is
recommended that implementations of generators use the `rand_core`

crate while
other users use only the `rand`

crate, which re-exports most parts of `rand_core`

.

The `rand_derive`

crate has been deprecated due to very low usage and
deprecation of `Rand`

.

## Features

Several new Cargo feature flags have been added:

`alloc`

, used without`std`

, allows use of`Box`

and`Vec`

`serde1`

adds serialization support to some PRNGs`log`

adds logging in a few places (primarily to`OsRng`

and`JitterRng`

)

`Rng`

and friends (core traits)

`Rng`

trait has been split into two traits, a "back end" `RngCore`

(implemented
by generators) and a "front end" `Rng`

implementing all the convenient extension
methods.

Implementations of generators must `impl RngCore`

instead. Usage of `rand_core`

for implementations is encouraged; the `rand_core::{le, impls}`

modules may
prove useful.

Users of `Rng`

*who don't need to implement it* won't need to make so many
changes; often users can forget about `RngCore`

and only import `Rng`

. Instead
of `RngCore::next_u32()`

/ `next_u64()`

users should prefer `Rng::gen()`

, and
instead of `RngCore::fill_bytes(dest)`

, `Rng::fill(dest)`

can be used.

`Rng`

/ `RngCore`

methods

To allow error handling from fallible sources (e.g. `OsRng`

), a new
`RngCore::try_fill_bytes`

method has been added; for example `EntropyRng`

uses
this mechanism to fall back to `JitterRng`

if `OsRng`

fails, and various
handlers produce better error messages.
As before, the other methods will panic on failure, but since these are usually
used with algorithmic generators which are usually infallible, this is
considered an appropriate compromise.

A few methods from the old `Rng`

have been removed or deprecated:

`next_f32`

and`next_f64`

; these are no longer implementable by generators; use`gen`

instead`gen_iter`

; users may instead use standard iterators with closures:`::std::iter::repeat(()).map(|()| rng.gen())`

`gen_ascii_chars`

; use`repeat`

as above and`rng.sample(Alphanumeric)`

`gen_weighted_bool(n)`

; use`gen_bool(1.0 / n)`

instead

`Rng`

has a few new methods:

`sample(distr)`

is a shortcut for`distr.sample(rng)`

for any`Distribution`

`gen_bool(p)`

generates a boolean with probability`p`

of being true`fill`

and`try_fill`

, corresponding to`fill_bytes`

and`try_fill_bytes`

respectively (i.e. the only difference is error handling); these can fill and integer slice / array directly, and provide better performance than`gen()`

### Constructing PRNGs

#### New randomly-initialised PRNGs

A new trait has been added: `FromEntropy`

. This is automatically implemented for
any type supporting `SeedableRng`

, and provides construction from fresh, strong
entropy:

`# #![allow(unused_variables)] #fn main() { use rand::{ChaChaRng, FromEntropy}; let mut rng = ChaChaRng::from_entropy(); #}`

#### Seeding PRNGs

The `SeedableRng`

trait has been modified to include the seed type via an
associated type (`SeedableRng::Seed`

) instead of a template parameter
(`SeedableRng<Seed>`

). Additionally, all PRNGs now seed from a byte-array
(`[u8; N]`

for some fixed N). This allows generic handling of PRNG seeding
which was not previously possible.

PRNGs are no longer constructed from other PRNGs via `Rand`

support / `gen()`

,
but through `SeedableRng::from_rng`

, which allows error handling and is
intentionally explicit.

`SeedableRng::reseed`

has been removed since it has no utility over `from_seed`

and its performance advantage is questionable.

Implementations of `SeedableRng`

may need to change their `Seed`

type to a
byte-array; this restriction has been made to ensure portable handling of
Endianness. Helper functions are available in `rand_core::le`

to read `u32`

and
`u64`

values from byte arrays.

### Block-based PRNGs

rand_core has a new helper trait, `BlockRngCore`

, and implementation,
`BlockRng`

. These are for use by generators which generate a block of random
data at a time instead of word-sized values. Using this trait and implementation
has two advantages: optimised `RngCore`

methods are provided, and the PRNG can
be used with `ReseedingRng`

with very low overhead.

### Cryptographic RNGs

A new trait has been added: `CryptoRng`

. This is purely a marker trait to
indicate which generators should be suitable for cryptography, e.g.
`fn foo<R: Rng + CryptoRng>(rng: &mut R)`

. *Suitability for cryptographic
use cannot be guaranteed.*

## Error handling

A new `Error`

type has been added, designed explicitly for no-std compatibility,
simplicity, and enough flexibility for our uses (carrying a `cause`

when
possible):

`# #![allow(unused_variables)] #fn main() { pub struct Error { pub kind: ErrorKind, pub msg: &'static str, // some fields omitted } #}`

The associated `ErrorKind`

allows broad classification of errors into permanent,
unexpected, transient and not-yet-ready kinds.

The following use the new error type:

`RngCore::try_fill_bytes`

`Rng::try_fill`

`OsRng::new`

`JitterRng::new`

## External generators

We have a new generator, `EntropyRng`

, which wraps `OsRng`

and `JitterRng`

(preferring to use the former, but falling back to the latter if necessary).
This allows easy construction with fallback via `SeedableRng::from_rng`

,
e.g. `IsaacRng::from_rng(EntropyRng::new())?`

. This is equivalent to using
`FromEntropy`

except for error handling.

It is recommended to use `EntropyRng`

over `OsRng`

to avoid errors on platforms
with broken system generator, but it should be noted that the `JitterRng`

fallback is very slow.

## PRNGs

*Pseudo-Random Number Generators* (i.e. deterministic algorithmic generators)
have had a few changes since 0.4, and are now housed in the `prng`

module
(old names remain temporarily available for compatibility; eventually these
generators will likely be housed outside the `rand`

crate).

All PRNGs now do not implement `Copy`

to prevent accidental copying of the
generator's state (and thus repetitions of generated values). Explicit cloning
via `Clone`

is still available. All PRNGs now have a custom implementation of
`Debug`

which does not print any internal state; this helps avoid accidentally
leaking cryptographic generator state in log files. External PRNG
implementations are advised to follow this pattern (see also doc on `RngCore`

).

`SmallRng`

has been added as a wrapper, currently around `XorShiftRng`

(but
likely another algorithm soon). This is for uses where small state and fast
initialisation are important but cryptographic strength is not required.
(Actual performance of generation varies by benchmark; depending on usage
this may or may not be the fastest algorithm, but will always be fast.)

`ReseedingRng`

The `ReseedingRng`

wrapper has been significantly altered to reduce overhead.
Unfortunately the new `ReseedingRng`

is not compatible with all RNGs, but only
those using `BlockRngCore`

.

### ISAAC PRNGs

The `IsaacRng`

and `Isaac64Rng`

PRNGs now have an additional construction
method: `new_from_u64(seed)`

. 64 bits of state is insufficient for cryptography
but may be of use in simulations and games. This will likely be superseded by
a method to construct any PRNG from any hashable object in the future.

### HC-128

This is a new cryptographic generator, selected as one of the "stream ciphers
suitable for widespread adoption" by eSTREAM. This is now the default
cryptographic generator, used by `StdRng`

and `thread_rng()`

.

## Helper functions/traits

The `Rand`

trait has been deprecated. Instead, users are encouraged to use
`Standard`

which is a real distribution and supports the same sampling as
`Rand`

. `Rng::gen()`

now uses `Standard`

and should work exactly as before.
See the documentation of the `distributions`

module on how to implement
`Distribution<T>`

for `Standard`

for user types `T`

`weak_rng()`

has been deprecated; use `SmallRng::from_entropy()`

instead.

## Distributions

The `Sample`

and `IndependentSample`

traits have been replaced by a single
trait, `Distribution`

. This is largely equivalent to `IndependentSample`

, but
with `ind_sample`

replaced by just `sample`

. Support for mutable distributions
has been dropped; although it appears there may be a few genuine uses, these
are not used widely enough to justify the existence of two independent traits
or of having to provide mutable access to a distribution object. Both `Sample`

and `IndependentSample`

are still available, but deprecated; they will be
removed in a future release.

`Distribution::sample`

(as well as several other functions) can now be called
directly on type-erased (unsized) RNGs.

`RandSample`

has been removed (see `Rand`

deprecation and new `Standard`

distribution).

The `Closed01`

wrapper has been removed, but `OpenClosed01`

has been added.

### Uniform distributions

Two new distributions are available:

`Standard`

produces uniformly-distributed samples for many different types, and acts as a replacement for`Rand`

`Alphanumeric`

samples`char`

s from the ranges`a-z A-Z 0-9`

#### Ranges

The `Range`

distribution has been heavily adapted, and renamed to `Uniform`

:

`Uniform::new(low, high)`

remains (half open`[low, high)`

)`Uniform::new_inclusive(low, high)`

has been added, including`high`

in the sample range`Uniform::sample_single(low, high, rng)`

is a faster variant for single usage sampling from`[low, high)`

`Uniform`

can now be implemented for user-defined types; see the `uniform`

module.

### Non-uniform distributions

Two distributions have been added:

- Poisson, modeling the number of events expected from a constant-rate source within a fixed time interval (e.g. nuclear decay)
- Binomial, modeling the outcome of a fixed number of yes-no trials

The sampling methods are based on those in "Numerical Recipes in C".

#### Exponential and Normal distributions

The main `Exp`

and `Normal`

distributions are unchanged, however the
"standard" versions, `Exp1`

and `StandardNormal`

are no longer wrapper types,
but full distributions. Instead of writing `let Exp1(x) = rng.gen();`

you now
write `let x = rng.sample(Exp1);`

.

# Updating to 0.6

During the 0.6 cycle, Rand found a new home under the rust-random project. We already feel at home, but if you'd like to help us decorate, a new logo would be appreciated!

We also found a new home for user-centric documentation — this book!

## PRNGs

All PRNGs in our old PRNG module have been moved to new crates. We also added an additional crate with the PCG algorithms, and an external crate with Xoshiro / Xoroshiro algorithms:

### SmallRng

This update, we switched the algorithm behind `SmallRng`

from Xorshift to a
PCG algorithm (either `Pcg64Mcg`

aka XSL 128/64 MCG, or `Pcg32`

aka
XSH RR 64/32 LCG aka the standard PCG algorithm).

## Sequences

The `seq`

module has been completely re-written,
and the `choose`

and `shuffle`

methods have been removed from the `Rng`

trait.
Most functionality can now be found in the `IteratorRandom`

and
`SliceRandom`

traits.

### Weighted choices

The `WeightedChoice`

distribution has now been replaced with
`WeightedIndex`

, solving a few issues by making the functionality more
generic.

For convenience, the `SliceRandom::choose_weighted`

method (and `_mut`

variant) allow a `WeightedIndex`

sample to be applied directly to a slice.

## Other features

### SIMD types

Rand now has rudimentary support for generating SIMD types, gated behind the
`simd_support`

feature flag.

`i128`

/ `u128`

types

Since these types are now available on stable compilers, these types are
supported automatically (with recent enough Rust version). The `i128_support`

feature flag still exists to avoid breakage, but no longer does anything.

# Contributing

Thank you for your interest in contributing to Rand!

The following is a list of notes and tips for when you want to contribute to Rand with a pull request.

## Open Participation

This project is open to contributions from anyone, with the main criteria of review being correctness, utility, project scope, and good documentation. Where correctness is less obvious (PRNGs and some type-conversion algorithms), additional criteria apply (see below).

Additionally we welcome feedback in the form of bug reports, feature requests (preferably with motivation and consideration for the scope of the project), code reviews, and input on current topics of discussion.

Since we must sometimes reject new features in order to limit the project's scope, you may wish to ask first before writing a new feature.

## Code style

Rand doesn't (yet) use rustfmt. It is best to follow the style of the surrounding code, and try to keep an 80 character line limit.

Rand does **make use of unsafe**, both for performance and out of necessity.
We consider this acceptable so long as correctness is easy to verify.
In order to make this as simple as possible,
we prefer that all parameters affecting safety of

`unsafe`

blocks are checked or
prepared close to the `unsafe`

code,
and wherever possible within the same function (thus making the function safe).# Documentation

We are very happy to recieve documentation pull-requests.

Documentation is split into two parts: the API documentation (from the code, usually in rust-random/rand), and this book (from rust-random/book).

## Style

All documentation is in English, but no particular dialect is preferred.

The documentation should be accessible to multiple audiences: both seasoned Rustaceans and relative newcomers, those with experience in statistical modelling or cryptography, as well as those new to the subjects. Since it is often impossible to write appropriate one-size-fits-all documentation, we prefer concise technical documentation with reference to extended articles aimed at more specific audiences.

## Building and testing

### API documentation

To build the API documentation locally, run:

```
# Build doc for all modules:
cargo doc --all --no-deps
# And open it:
xdg-open target/doc/rand/index.html
```

On Linux, it is easy to set up automatic rebuilds after any edit:

```
while inotifywait -r -e close_write src/ rand_core/; do cargo doc; done
```

After editing API documentation, we reccomend testing examples and checking for broken links:

```
cargo test --doc
cargo install cargo-deadlinks
# It is recommended to remove left-over files from previous compilations
rm -rf /target/doc
cargo doc --all --no-deps
cargo deadlinks --dir target/doc
```

### The book

The book is built using mdbook, which makes building and testing easy:

```
cargo install mdbook --version "^0.2"
mdbook build --open
mdbook test
# To automatically rebuild after any changes:
mdbook watch
```

Note that links in the book are relative and designed to work in the published book. If you build the book locally, you might want to set up a symbolic link pointing to your build of the API documentation:

```
ln -s ../rand/target/doc rand
```

# Scope

The `rand_core`

library has the following scope:

- the core traits which RNGs may implement
- tools for implementing these traits

The `rand`

library has the following scope:

- re-export all parts of
`rand_core`

applicable to end users - an interface to request entropy from an external source
- hooks to provide entropy from several platform-specific sources
- traits covering common RNG functionality
- some PRNGs, notably
`StdRng`

and`SmallRng`

`thread_rng`

auto-seeding source of randomness- conversion of random bits to common types and uses
- shuffling and sampling from sequences
- sampling from various random number distributions

The `rand_chacha`

, `rand_hc`

, `rand_isaac`

, `rand_pcg`

and `rand_xorshift`

libraries provide additional PRNGs. They are recommended over `StdRng`

and
`SmallRng`

when reproducibility is needed.

## New PRNG Algorithms

The Rand library includes several pseudo-random number generators, for the following reasons:

- to implement the
`StdRng`

and`SmallRng`

generators - to provide a strong, widely trusted CSPRNG (ChaCha)
- historical usage

We have received several requests to adopt new algorithms into the library; when evaluating such requests we must consider several things:

- whether the PRNG is cryptographically secure, and if so, how trustworthy such claims are
- statistical quality of output
- performance and features of the generator
- scope of the project
- reception and third-party review of the algorithm

## New distributions

Currently the `rand`

lib and `statrs`

have
significant overlap in that both libraries implement sampling for many of the
same statistical distributions. Because of this, we are reluctant to accept new
sampling algorithms in Rand itself. This issue is not yet resolved (see #290).

# Testing

Rand has a number of unit tests, though these are not comprehensive or perfect (improvements welcome). We prefer to have tests for all new functionality.

The first line of testing is simply to run `cargo test`

from the appropriate
directory. Since Rand supports `no_std`

(core-only), `core+alloc`

and `std`

environments, it is important to test all three (depending on which features
are applicable to the code in question):

```
# Test using std:
cargo test
# Test using only core:
cargo test --tests --no-default-features
# Test using core + alloc (requires nightly):
cargo +nightly test --tests --no-default-features --features=alloc
```

It may also be worth testing with other feature flags:

```
cargo test --all-features
```

Note that this only tests the current package (i.e. the main Rand lib when run
from the repo's top level). To test another lib, `cd`

to its directory.

We do not recommend using Cargo's `--package`

option due to its
surprising interactions
with `--feature`

options and failure when multiple versions of the same package
are in the build tree. The CI instead uses `--manifest-path`

to select packages;
while developing, using `cd`

is easier.

## Writing tests

Tests may be unit tests within a `test`

sub-module, documentation examples,
example applications (`examples`

dir), integration tests (`tests`

dir), or
benchmarks (`benches`

dir).

Note that *only* unit tests and integration tests are expected to pass in
`no_std`

(core only) and `core+alloc`

configurations. This is a deliberate
choice; example code should only need to target the common case (`std`

).

### Random Number Generators

Often test code needs some RNG to test with, but does not need any particular
RNG. In this case, we prefer use of `::test::rng`

which is simple, fast to
initialise and deterministic:

`# #![allow(unused_variables)] #fn main() { let mut rng = ::test::rng(528); // just pick some number #}`

Various tests concern properties which are *probably* true, but not definitely.
We prefer that such tests are deterministic to avoid spurious failures.

# Benchmarks

Running benchmarks is easy (but requires a nightly compiler):

```
cargo bench
# In a few cases, nightly features may use different code paths:
cargo bench --features=nightly
```

A lot of code in Rand is performance sensitive, most of it is expected to be
used in hot loops in some libraries/applications. If you change code in
`rand_core`

, in PRNG crates, or in the `rngs`

or `distributions`

modules
(especially when an 'obvious cleanup'), make sure the benchmarks do not regress.

Please report before-and-after results for any affected benchmarks. If you are optimising something previously not benchmarked, please add new benchmarks first, then add your changes in a separate commit (to make before-and-after benchmarking easy).