Xoshiro256++ by default
Random::new() creates a Xoshiro256++ generator seeded from the operating system. Its state is 32 bytes and its period is 2256 - 1; seeds go through SplitMix64 first, so even a poor seed gives a well-mixed state.
use Random;
let mut rng = new;
let n: u32 = rng.rand; // any u32
let die = rng.int; // i32 in [1, 6]
let x = rng.double; // f64 in [0.0, 1.0)
let coin = rng.bool; // true half the time
Ranges are unbiased: int, uint, random_range and bounded use Lemire's nearly-divisionless method rather than a plain remainder. float fills all 24 bits of an f32 mantissa and double all 53 bits of an f64.
Choosing a backend
Every backend sits behind the same Random type. Pick one with its constructor:
| Backend | Constructor | State | Cargo feature | Suitable for secrets |
|---|---|---|---|---|
| Xoshiro256++ | Random::new() | 32 B | default | no |
| Mersenne Twister (MT19937) | Random::new_mersenne_twister() | 2,488 B | alloc | no |
| PCG32 | Random::new_pcg32() | 16 B | pcg | no |
| PCG64 | Random::new_pcg64() | 32 B | pcg | no |
| ChaCha20 | Random::new_secure() | heap-allocated | crypto | yes |
The Mersenne Twister is there to reproduce existing MT19937 output, such as reference data from older tools; use it when you need its exact sequence. The ChaCha20 backend wraps rand_chacha, the rand project's implementation, rather than a cipher written for vrd.
Distributions
Four distributions are built in: uniform(low, high), normal(mean, std_dev), exponential(rate) and poisson(mean). normal uses the Ziggurat method. The Distribution<T> trait lets you add your own:
use ;
let mut rng = from_u64_seed;
let heads = Bernoulli .sample;
The distributions panic on invalid parameters, such as a non-finite mean, with a message naming the parameter. For gamma, binomial, log-normal and the rest, use rand_distr.
Reproducible sequences
The same seed gives the same sequence. Random::from_u64_seed(u64) and Random::from_seed([u8; 32]) are deterministic and allocate nothing:
use Random;
let mut a = from_u64_seed;
let mut b = from_u64_seed;
assert_eq!; // 2783027749 both times with vrd 0.0.12
With the serde feature, a generator serialises and restores with its full state, so a run can resume where it stopped. For parallel work, Random::split() returns a second Xoshiro256++ stream 2128 draws ahead of the first; on the other backends it returns None, so give each worker its own seed instead.
Slices, tokens and identifiers
Common jobs are methods on Random: choose, shuffle, sample and sample_with_replacement on slices; bytes, string, fill_array and iterators over u32, u64 and bytes; and identifiers:
| Method | Returns |
|---|---|
uuid_v4_bytes() | A version 4 UUID as [u8; 16], with no allocation |
uuid_v4() | The same UUID as a hyphenated string |
hex_token(n) | n random bytes as 2n lowercase hex characters |
base64_token(n) | n random bytes as URL-safe base64 without padding |
These come from whichever backend the Random uses. For a session token or an API key, call them on Random::new_secure().
Quasi-random sequences
The quasirandom feature adds low-discrepancy sequences for Monte Carlo integration and sampling, which cover a space more evenly than random points:
use ;
let mut vdc = new; // 0.5, 0.25, 0.75, ...
let mut halton = new; // up to 32 dimensions
let mut sobol = new; // up to 6 dimensions
let x = vdc.next_point;
let p = halton.;
let q = sobol.;
Sobol stops at six dimensions: going further needs direction numbers vrd does not ship yet.
SIMD byte fills
The simd feature fills byte buffers several streams at a time: two Xoshiro256++ states on AArch64 NEON, four on x86-64 AVX2. In the published benchmarks it was 2.18 times faster than the scalar path for 1 KiB and 2.97 times for 16 KiB. Its output for a seed differs from the scalar path's, so keep it off where you need a reproducible byte stream.
no_std, embedded and WebAssembly
With default features off, vrd needs neither the standard library nor an allocator:
[dependencies]
vrd = { version = "0.0.12", default-features = false }
Seed it yourself with Random::from_seed or Random::from_u64_seed, since there is no operating system to ask. The alloc feature adds the methods that return a Vec or String and the Mersenne Twister. CI checks both builds for thumbv7em-none-eabihf (Cortex-M4F and M7F) and wasm32-unknown-unknown. In WebAssembly, seed manually or enable entropy through getrandom in your own crate.
Works with rand
Random and each backend implement rand 0.10's TryRng and SeedableRng traits, and so Rng, so you can pass a vrd generator to code written for the rand traits. The migration guide maps rand's calls to vrd's.
Command-line tool
cargo install vrd installs a small vrd command that prints random u32 values, one per line: