Facilities for random number generation.
Category | Functions |
---|---|
Uniform sampling | uniform uniform01 uniformDistribution |
Element sampling | choice dice |
Range sampling | randomCover randomSample |
Default Random Engines | rndGen Random unpredictableSeed |
Linear Congruential Engines | MinstdRand MinstdRand0 LinearCongruentialEngine |
Mersenne Twister Engines | Mt19937 Mt19937_64 MersenneTwisterEngine |
Xorshift Engines | Xorshift XorshiftEngine Xorshift32 Xorshift64 Xorshift96 Xorshift128 Xorshift160 Xorshift192 |
Shuffle | partialShuffle randomShuffle |
Traits | isSeedable isUniformRNG |
MinstdRand0
and MinstdRand
might be useful. The standard library provides an alias Random for whichever generator it considers the most fit for the target environment. import std.algorithm.comparison : among, equal; import std.range : iota; // seed a random generator with a constant auto rnd = Random(42); // Generate a uniformly-distributed integer in the range [0, 14] // If no random generator is passed, the global `rndGen` would be used auto i = uniform(0, 15, rnd); assert(i >= 0 && i < 15); // Generate a uniformly-distributed real in the range [0, 100) auto r = uniform(0.0L, 100.0L, rnd); assert(r >= 0 && r < 100); // Sample from a custom type enum Fruit { apple, mango, pear } auto f = rnd.uniform!Fruit; with(Fruit) assert(f.among(apple, mango, pear)); // Generate a 32-bit random number auto u = uniform!uint(rnd); static assert(is(typeof(u) == uint)); // Generate a random number in the range in the range [0, 1) auto u2 = uniform01(rnd); assert(u2 >= 0 && u2 < 1); // Select an element randomly auto el = 10.iota.choice(rnd); assert(0 <= el && el < 10); // Throw a dice with custom proportions // 0: 20%, 1: 10%, 2: 60% auto val = rnd.dice(0.2, 0.1, 0.6); assert(0 <= val && val <= 2); auto rnd2 = MinstdRand0(42); // Select a random subsample from a range assert(10.iota.randomSample(3, rnd2).equal([7, 8, 9])); // Cover all elements in an array in random order version (X86_64) // Issue 15147 assert(10.iota.randomCover(rnd2).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5])); // Shuffle an array version (X86_64) // Issue 15147 assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([2, 0, 4, 5, 1]));
Test if Rng is a random-number generator. The overload taking a ElementType also makes sure that the Rng generates values of that type.
A random-number generator has at least the following features:
struct NoRng { @property uint front() {return 0;} @property bool empty() {return false;} void popFront() {} } static assert(!isUniformRNG!(NoRng)); struct validRng { @property uint front() {return 0;} @property bool empty() {return false;} void popFront() {} enum isUniformRandom = true; } static assert(isUniformRNG!(validRng, uint)); static assert(isUniformRNG!(validRng));
Test if Rng is seedable. The overload taking a SeedType also makes sure that the Rng can be seeded with SeedType.
A seedable random-number generator has the following additional features:
struct validRng { @property uint front() {return 0;} @property bool empty() {return false;} void popFront() {} enum isUniformRandom = true; } static assert(!isSeedable!(validRng, uint)); static assert(!isSeedable!(validRng)); struct seedRng { @property uint front() {return 0;} @property bool empty() {return false;} void popFront() {} void seed(uint val){} enum isUniformRandom = true; } static assert(isSeedable!(seedRng, uint)); static assert(!isSeedable!(seedRng, ulong)); static assert(isSeedable!(seedRng));
Linear Congruential generator.
alias CPP11LCG = LinearCongruentialEngine!(uint, 48271, 0, 2_147_483_647); // seed with a constant auto rnd = CPP11LCG(42); auto n = rnd.front; // same for each run writeln(n); // 2027382
// glibc's LCG alias GLibcLCG = LinearCongruentialEngine!(uint, 1103515245, 12345, 2_147_483_648); // Seed with an unpredictable value auto rnd = GLibcLCG(unpredictableSeed); auto n = rnd.front; // different across runs
Mark this as a Rng
Does this generator have a fixed range? (true).
Lowest generated value (1
if c == 0
, 0
otherwise).
Highest generated value (modulus - 1
).
The parameters of this distribution. The random number is x = (x * multipler + increment) % modulus.
Constructs a LinearCongruentialEngine generator seeded with x0
.
(Re)seeds the generator.
Advances the random sequence.
Returns the current number in the random sequence.
Always false
(random generators are infinite ranges).
Define LinearCongruentialEngine generators with well-chosen parameters. MinstdRand0
implements Park and Miller's "minimal standard" generator that uses 16807 for the multiplier. MinstdRand
implements a variant that has slightly better spectral behavior by using the multiplier 48271. Both generators are rather simplistic.
// seed with a constant auto rnd0 = MinstdRand0(1); auto n = rnd0.front; // same for each run writeln(n); // 16807 // Seed with an unpredictable value rnd0.seed(unpredictableSeed); n = rnd0.front; // different across runs
The Mersenne Twister generator.
// seed with a constant Mt19937 gen; auto n = gen.front; // same for each run writeln(n); // 3499211612 // Seed with an unpredictable value gen.seed(unpredictableSeed); n = gen.front; // different across runs
Mark this as a Rng
Parameters for the generator.
Smallest generated value (0).
Largest generated value.
The default seed value.
Constructs a MersenneTwisterEngine object.
Seeds a MersenneTwisterEngine object.
Seeds a MersenneTwisterEngine object using an InputRange.
Exception
if the InputRange didn't provide enough elements to seed the generator. The number of elements required is the 'n' template parameter of the MersenneTwisterEngine struct.Advances the generator.
Returns the current random value.
Always false
.
A MersenneTwisterEngine
instantiated with the parameters of the original engine MT19937, generating uniformly-distributed 32-bit numbers with a period of 2 to the power of 19937. Recommended for random number generation unless memory is severely restricted, in which case a LinearCongruentialEngine
would be the generator of choice.
// seed with a constant Mt19937 gen; auto n = gen.front; // same for each run writeln(n); // 3499211612 // Seed with an unpredictable value gen.seed(unpredictableSeed); n = gen.front; // different across runs
A MersenneTwisterEngine
instantiated with the parameters of the original engine MT19937-64, generating uniformly-distributed 64-bit numbers with a period of 2 to the power of 19937.
// Seed with a constant auto gen = Mt19937_64(12345); auto n = gen.front; // same for each run writeln(n); // 6597103971274460346 // Seed with an unpredictable value gen.seed(unpredictableSeed!ulong); n = gen.front; // different across runs
Xorshift generator. Implemented according to Xorshift RNGs (Marsaglia, 2003) when the size is small. For larger sizes the generator uses Sebastino Vigna's optimization of using an index to avoid needing to rotate the internal array.
Period is 2 ^^ nbits - 1
except for a legacy 192-bit uint version (see note below).
UIntType | Word size of this xorshift generator and the return type of opCall . |
nbits | The number of bits of state of this generator. This must be a positive multiple of the size in bits of UIntType. If nbits is large this struct may occupy slightly more memory than this so it can use a circular counter instead of shifting the entire array. |
sa | The direction and magnitude of the 1st shift. Positive means left, negative means right. |
sb | The direction and magnitude of the 2nd shift. Positive means left, negative means right. |
sc | The direction and magnitude of the 3rd shift. Positive means left, negative means right. |
nbits == 192
and UIntType
is uint
a legacy hybrid PRNG is used consisting of a 160-bit xorshift combined with a 32-bit counter. This combined generator has period equal to the least common multiple of 2^^160 - 1
and 2^^32
. XorshiftEngine
did not provide any mechanism to specify the directions of the shifts, taking each shift as an unsigned magnitude. For backwards compatibility, because three shifts in the same direction cannot result in a full-period XorshiftEngine, when all three of sa
, sb
, sc, are positive
XorshiftEngine` treats them as unsigned magnitudes and uses shift directions to match the old behavior of XorshiftEngine
. Not every set of shifts results in a full-period xorshift generator. The template does not currently at compile-time perform a full check for maximum period but in a future version might reject parameters resulting in shorter periods. alias Xorshift96 = XorshiftEngine!(uint, 96, 10, 5, 26); auto rnd = Xorshift96(42); auto num = rnd.front; // same for each run writeln(num); // 2704588748
Mark this as a Rng
Always false
(random generators are infinite ranges).
Smallest generated value.
Largest generated value.
Constructs a XorshiftEngine
generator seeded with x0.
UIntType x0
| value used to deterministically initialize internal state |
(Re)seeds the generator.
UIntType x0
| value used to deterministically initialize internal state |
Returns the current number in the random sequence.
Advances the random sequence.
Captures a range state.
Define XorshiftEngine
generators with well-chosen parameters. See each bits examples of "Xorshift RNGs". Xorshift
is a Xorshift128's alias because 128bits implementation is mostly used.
// Seed with a constant auto rnd = Xorshift(1); auto num = rnd.front; // same for each run writeln(num); // 1405313047 // Seed with an unpredictable value rnd.seed(unpredictableSeed); num = rnd.front; // different across rnd
A "good" seed for initializing random number engines. Initializing with unpredictableSeed makes engines generate different random number sequences every run.
2 ^^ 19937 - 1
distinct states but after seed(uint)
is called it can only be in one of 2 ^^ 32
distinct states regardless of how excellent the source of entropy is.auto rnd = Random(unpredictableSeed); auto n = rnd.front; static assert(is(typeof(n) == uint));
The "default", "favorite", "suggested" random number generator type on the current platform. It is an alias for one of the previously-defined generators. You may want to use it if (1) you need to generate some nice random numbers, and (2) you don't care for the minutiae of the method being used.
Global random number generator used by various functions in this module whenever no generator is specified. It is allocated per-thread and initialized to an unpredictable value for each thread.
import std.algorithm.iteration : sum; import std.range : take; auto rnd = rndGen; assert(rnd.take(3).sum > 0);
Generates a number between a
and b
. The boundaries
parameter controls the shape of the interval (open vs. closed on either side). Valid values for boundaries
are "[]"
, "(]"
, "[)"
, and "()"
. The default interval is closed to the left and open to the right. The version that does not take urng
uses the default generator rndGen
.
T1 a
| lower bound of the uniform distribution |
T2 b
| upper bound of the uniform distribution |
UniformRandomNumberGenerator urng
| (optional) random number generator to use; if not specified, defaults to rndGen
|
a
and b
, whose type is the common type of these parametersauto rnd = Random(unpredictableSeed); // Generate an integer in [0, 1023] auto a = uniform(0, 1024, rnd); assert(0 <= a && a < 1024); // Generate a float in [0, 1) auto b = uniform(0.0f, 1.0f, rnd); assert(0 <= b && b < 1); // Generate a float in [0, 1] b = uniform!"[]"(0.0f, 1.0f, rnd); assert(0 <= b && b <= 1); // Generate a float in (0, 1) b = uniform!"()"(0.0f, 1.0f, rnd); assert(0 < b && b < 1);
import std.array : array; import std.range : generate, takeExactly; int[] arr = generate!(() => uniform(0, 100)).takeExactly(10).array; writeln(arr.length); // 10 assert(arr[0] >= 0 && arr[0] < 100);
Generates a uniformly-distributed number in the range [T.min, T.max]
for any integral or character type T
. If no random number generator is passed, uses the default rndGen
.
If an enum
is used as type, the random variate is drawn with equal probability from any of the possible values of the enum E
.
UniformRandomNumberGenerator urng
| (optional) random number generator to use; if not specified, defaults to rndGen
|
T
.auto rnd = MinstdRand0(42); writeln(rnd.uniform!ubyte); // 102 writeln(rnd.uniform!ulong); // 4838462006927449017 enum Fruit { apple, mango, pear } version (X86_64) // Issue 15147 writeln(rnd.uniform!Fruit); // Fruit.mango
Generates a uniformly-distributed floating point number of type T
in the range [0, 1). If no random number generator is specified, the default RNG rndGen
will be used as the source of randomness.
uniform01
offers a faster generation of random variates than the equivalent uniform!"[)"(0.0, 1.0)
and so may be preferred for some applications.
UniformRNG rng
| (optional) random number generator to use; if not specified, defaults to rndGen
|
T
drawn from the uniform distribution across the half-open interval [0, 1).import std.math : feqrel; auto rnd = MinstdRand0(42); assert(rnd.uniform01.feqrel(0.000328707) > 20); assert(rnd.uniform01!float.feqrel(0.524587) > 20);
Generates a uniform probability distribution of size n
, i.e., an array of size n
of positive numbers of type F
that sum to 1
. If useThis
is provided, it is used as storage.
import std.algorithm.iteration : reduce; import std.math : approxEqual; auto a = uniformDistribution(5); writeln(a.length); // 5 assert(approxEqual(reduce!"a + b"(a), 1)); a = uniformDistribution(10, a); writeln(a.length); // 10 assert(approxEqual(reduce!"a + b"(a), 1));
Returns a random, uniformly chosen, element e
from the supplied Range range
. If no random number generator is passed, the default rndGen
is used.
Range range
| a random access range that has the length property defined |
RandomGen urng
| (optional) random number generator to use; if not specified, defaults to rndGen
|
range
. If it can, it will return a ref
to the range element
, otherwise it will return a copy.auto rnd = MinstdRand0(42); auto elem = [1, 2, 3, 4, 5].choice(rnd); version (X86_64) // Issue 15147 writeln(elem); // 3
Shuffles elements of r
using gen
as a shuffler. r
must be a random-access range with length. If no RNG is specified, rndGen
will be used.
Range r
| random-access range whose elements are to be shuffled |
RandomGen gen
| (optional) random number generator to use; if not specified, defaults to rndGen
|
auto rnd = MinstdRand0(42); auto arr = [1, 2, 3, 4, 5].randomShuffle(rnd); version (X86_64) // Issue 15147 writeln(arr); // [3, 5, 2, 4, 1]
Partially shuffles the elements of r
such that upon returning r[0 .. n]
is a random subset of r
and is randomly ordered. r[n .. r.length]
will contain the elements not in r[0 .. n]
. These will be in an undefined order, but will not be random in the sense that their order after partialShuffle
returns will not be independent of their order before partialShuffle
was called.
r
must be a random-access range with length. n
must be less than or equal to r.length
. If no RNG is specified, rndGen
will be used.
Range r
| random-access range whose elements are to be shuffled |
size_t n
| number of elements of r to shuffle (counting from the beginning); must be less than r.length
|
RandomGen gen
| (optional) random number generator to use; if not specified, defaults to rndGen
|
auto rnd = MinstdRand0(42); auto arr = [1, 2, 3, 4, 5, 6]; arr = arr.dup.partialShuffle(1, rnd); version (X86_64) // Issue 15147 assert(arr == [2, 1, 3, 4, 5, 6]); // 1<->2 arr = arr.dup.partialShuffle(2, rnd); version (X86_64) // Issue 15147 assert(arr == [1, 4, 3, 2, 5, 6]); // 1<->2, 2<->4 arr = arr.dup.partialShuffle(3, rnd); version (X86_64) // Issue 15147 assert(arr == [5, 4, 6, 2, 1, 3]); // 1<->5, 2<->4, 3<->6
Rolls a dice with relative probabilities stored in proportions
. Returns the index in proportions
that was chosen.
Rng rnd
| (optional) random number generator to use; if not specified, defaults to rndGen
|
Num[] proportions
| forward range or list of individual values whose elements correspond to the probabilities with which to choose the corresponding index value |
proportions.length
- 1], with the probability of getting an individual index value i
being proportional to proportions[i]
.auto x = dice(0.5, 0.5); // x is 0 or 1 in equal proportions auto y = dice(50, 50); // y is 0 or 1 in equal proportions auto z = dice(70, 20, 10); // z is 0 70% of the time, 1 20% of the time, // and 2 10% of the time
auto rnd = MinstdRand0(42); auto z = rnd.dice(70, 20, 10); writeln(z); // 0 z = rnd.dice(30, 20, 40, 10); writeln(z); // 2
Covers a given range r
in a random manner, i.e. goes through each element of r
once and only once, just in a random order. r
must be a random-access range with length.
If no random number generator is passed to randomCover
, the thread-global RNG rndGen will be used internally.
Range r
| random-access range to cover |
UniformRNG rng
| (optional) random number generator to use; if not specified, defaults to rndGen
|
r
, in random order. Will be a forward range if both r
and rng
are forward ranges, an input range otherwise.import std.algorithm.comparison : equal; import std.range : iota; auto rnd = MinstdRand0(42); version (X86_64) // Issue 15147 assert(10.iota.randomCover(rnd).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5]));
Selects a random subsample out of r
, containing exactly n
elements. The order of elements is the same as in the original range. The total length of r
must be known. If total
is passed in, the total number of sample is considered to be total
. Otherwise, RandomSample
uses r.length
.
Range r
| range to sample from |
size_t n
| number of elements to include in the sample; must be less than or equal to the total number of elements in r and/or the parameter total (if provided) |
size_t total
| (semi-optional) number of elements of r from which to select the sample (counting from the beginning); must be less than or equal to the total number of elements in r itself. May be omitted if r has the .length property and the sample is to be drawn from all elements of r . |
UniformRNG rng
| (optional) random number generator to use; if not specified, defaults to rndGen
|
r
, in the same order as these elements appear in r
itself. Will be a forward range if both r
and rng
are forward ranges, an input range otherwise. RandomSample
implements Jeffrey Scott Vitter's Algorithm D (see Vitter 1984, 1987), which selects a sample of size n
in O(n) steps and requiring O(n) random variates, regardless of the size of the data being sampled. The exception to this is if traversing k elements on the input range is itself an O(k) operation (e.g. when sampling lines from an input file), in which case the sampling calculation will inevitably be of O(total). RandomSample will throw an exception if total
is verifiably less than the total number of elements available in the input, or if n > total
. If no random number generator is passed to randomSample
, the thread-global RNG rndGen will be used internally.import std.algorithm.comparison : equal; import std.range : iota; auto rnd = MinstdRand0(42); assert(10.iota.randomSample(3, rnd).equal([7, 8, 9]));
Range primitives.
Returns the index of the visited record.
© 1999–2019 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_random.html