hap.random.distribution

Implements algorithms for generating random numbers drawn from different statistical distributions. Where possible, each random distribution is provided in two different forms:

Typical reasons for rejecting a function implementation include the function needing to hold state between calls to achieve adequate performance, or the function needing to allocate memory with each call.

As with random number generators, the random distribution range objects implemented here are final classes in order to ensure reference semantics. They also assume reference type semantics on the part of the RNGs that they wrap: user-supplied value-type RNGs may produce unexpected and incorrect behaviour when combined with these objects.

Note:
hap.random.distribution.dice uses a different algorithm to its std.random counterpart and so will produce different results.

License:
Boost License 1.0.

Authors:
Andrei Alexandrescu, Chris Cain (discrete distribution and integral-based uniform), Andrej Mitrović (enum-based uniform), Joseph Rushton Wakeling

Source:
hap/random/distribution.d

size_t dice(UniformRNG, Num)(UniformRNG rng, Num[] proportions...) if (isNumeric!Num && isForwardRange!UniformRNG);
size_t dice(UniformRNG, Range)(UniformRNG rng, Range proportions) if (isUniformRNG!UniformRNG && isForwardRange!Range && isNumeric!(ElementType!Range) && !isArray!Range);
size_t dice(Range)(Range proportions) if (isForwardRange!Range && isNumeric!(ElementType!Range) && !isArray!Range);
size_t dice(Num)(Num[] proportions...) if (isNumeric!Num);
Rolls a random die with relative probabilities stored in proportions. Returns the index in proportions that was chosen.

Example:
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

The range counterpart of dice is the DiscreteDistribution class.

Note:
given an identically-seeded RNG as input, hap.random.distribution.dice will produce different values to std.random.dice.

class DiscreteDistribution(SearchPolicy search, T, UniformRNG);
auto discreteDistribution(SearchPolicy search = SearchPolicy.binarySearch, UniformRNG, Range)(UniformRNG rng, Range proportions) if (isInputRange!Range && isNumeric!(ElementType!Range) && isUniformRNG!UniformRNG);
auto discreteDistribution(SearchPolicy search = SearchPolicy.binarySearch, Range)(Range proportions) if (isInputRange!Range && isNumeric!(ElementType!Range));
auto discreteDistribution(SearchPolicy search = SearchPolicy.binarySearch, UniformRNG, Num)(UniformRNG rng, Num[] proportions...) if (isUniformRNG!UniformRNG && isNumeric!Num);
auto discreteDistribution(SearchPolicy search = SearchPolicy.binarySearch, Num)(Num[] proportions...) if (isNumeric!Num);
The range equivalent of dice, each element of which is the result of the roll of a random die with relative probabilities stored in the range proportions. Each successive value of front reflects the index in proportions that was chosen. If no random number generator is specified, the default rndGen will be used as the source of randomness.

This offers a superior option in the event of making many rolls of the same die, as the sum and CDF of proportions only needs to be calculated upon construction and not with each call.

bool empty;
const pure nothrow @property @safe size_t front();
void popFront();
@property typeof(this) save();
Range primitives

auto normal(T1, T2)(T1 mu, T2 sigma) if (isNumeric!T1 && isNumeric!T2);
auto normal(T1, T2, UniformRNG)(T1 mu, T2 sigma, UniformRNG rng) if (isNumeric!T1 && isNumeric!T2 && isUniformRNG!UniformRNG);
Returns a floating-point number drawn from a normal (Gaussian) distribution with mean mu and standard deviation sigma. If no random number generator is specified, the default rndGen will be used as the source of randomness.

Note that this function uses two variates from the uniform random number generator to generate a single normally-distributed variate. It is therefore an inefficient means of generating a large number of normally-distributed variates. If you wish to draw many variates from the normal distribution, it is better to use the range-based normalDistribution instead.

class NormalDistribution(T, UniformRNG) if (isFloatingPoint!T && isUniformRNG!UniformRNG);
auto normalDistribution(T1, T2, UniformRNG)(T1 mu, T2 sigma, UniformRNG rng) if (isNumeric!T1 && isNumeric!T2 && isUniformRNG!UniformRNG);
auto normalDistribution(T1, T2)(T1 mu, T2 sigma) if (isNumeric!T1 && isNumeric!T2);
Provides an infinite range of random numbers distributed according to the normal (Gaussian) distribution with mean mu and standard deviation sigma. If no random number generator is specified, the default rndGen will be used as the source of randomness.

bool empty;
const pure nothrow @property @safe T front();
void popFront();
@property typeof(this) save();
Range primitives.

auto uniform(string boundaries = "[)", T1, T2)(T1 a, T2 b) if (!is(CommonType!(T1, T2) == void));
auto uniform(string boundaries = "[)", T1, T2, UniformRNG)(T1 a, T2 b, UniformRNG rng) if (isFloatingPoint!(CommonType!(T1, T2)) && isUniformRNG!UniformRNG);
auto uniform(string boundaries = "[)", T1, T2, UniformRNG)(T1 a, T2 b, UniformRNG rng) if ((isIntegral!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2))) && isUniformRNG!UniformRNG);
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. If no random number generator is specified, the default rndGen will be used as the source of randomness.

Example:
auto gen = Random(unpredictableSeed);
// Generate an integer in [0, 1023]
auto a = uniform(0, 1024, gen);
// Generate a float in [0, 1$(RPAREN)
auto a = uniform(0.0f, 1.0f, gen);

auto uniform(T, UniformRNG)(UniformRNG rng) if (!is(T == enum) && (isIntegral!T || isSomeChar!T) && isUniformRNG!UniformRNG);
auto uniform(T)() if (!is(T == enum) && (isIntegral!T || isSomeChar!T));
Generates a uniformly-distributed number in the range [T.min, T.max] for any integral type T. If no random number generator is passed, uses the default rndGen.

auto uniform(E, UniformRNG)(UniformRNG rng) if (is(E == enum) && isUniformRNG!UniformRNG);
auto uniform(E)() if (is(E == enum));
Returns a uniformly selected member of enum E. If no random number generator is passed, uses the default rndGen.

Examples:
enum Fruit { Apple = 12, Mango = 29, Pear = 72 }
foreach (immutable _; 0 .. 100)
{
    foreach (immutable f; [uniform!Fruit(), rndGen.uniform!Fruit()])
    {
        assert(f == Fruit.Apple || f == Fruit.Mango || f == Fruit.Pear);
    }
}

class UniformDistribution(string boundaries = "[)", T, UniformRNG) if ((isNumeric!T || isSomeChar!T) && isUniformRNG!UniformRNG);
auto uniformDistribution(string boundaries = "[)", T1, T2, UniformRNG)(T1 a, T2 b, UniformRNG rng) if ((isNumeric!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2))) && isUniformRNG!UniformRNG);
auto uniformDistribution(string boundaries = "[)", T1, T2)(T1 a, T2 b) if (isNumeric!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2)));
Provides an infinite sequence of random numbers uniformly distributed 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. If no random number generator is specified, the default rndGen will be used as the source of randomness.

bool empty;
const pure nothrow @property @safe T front();
void popFront();
@property typeof(this) save();
Range primitives.

class UniformDistribution(T, UniformRNG) if (!is(T == enum) && (isIntegral!T || isSomeChar!T) && isUniformRNG!UniformRNG);
auto uniformDistribution(T, UniformRNG)(UniformRNG rng) if (!is(T == enum) && (isIntegral!T || isSomeChar!T) && isUniformRNG!UniformRNG);
auto uniformDistribution(T)() if (!is(T == enum) && (isIntegral!T || isSomeChar!T));
Generates an infinite sequence of uniformly-distributed numbers in the range [T.min, T.max] for any integral type T. If no random number generator is specified, the default rndGen will be used as the source of randomness.

bool empty;
const pure nothrow @property @safe T front();
void popFront();
@property typeof(this) save();
Range primitives.

class UniformDistribution(E, UniformRNG) if (is(E == enum) && isUniformRNG!UniformRNG);
auto uniformDistribution(E, UniformRNG)(UniformRNG rng) if (is(E == enum) && isUniformRNG!UniformRNG);
auto uniformDistribution(E)() if (is(E == enum));
Generates an infinite sequence of uniformly selected members of enum E. If no random number generator is specified, the default rndGen will be used as the source of randomness.

Examples:
enum Fruit { Apple = 12, Mango = 29, Pear = 72 }

foreach (immutable f; uniformDistribution!Fruit().take(100))
{
    assert(f == Fruit.Apple || f == Fruit.Mango || f == Fruit.Pear);
}

bool empty;
const pure nothrow @property @safe E front();
void popFront();
@property typeof(this) save();
Range primitives.

T uniform01(T = double)() if (isFloatingPoint!T);
T uniform01(T = double, UniformRNG)(UniformRNG rng) if (isFloatingPoint!T && isUniformRNG!UniformRNG);
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.

class Uniform01Distribution(T, UniformRNG) if (isFloatingPoint!T && isUniformRNG!UniformRNG);
auto uniform01Distribution(T = double, UniformRNG)(UniformRNG rng) if (isFloatingPoint!T && isUniformRNG!UniformRNG);
auto uniform01Distribution(T = double)() if (isFloatingPoint!T);
Provides an infinite sequence of random numbers uniformly distributed in the interval [0, 1). If no RNG is specified, uniformDistribution will use the default generator rndGen.

bool empty;
const pure nothrow @property @safe T front();
void popFront();
@property typeof(this) save();
Range primitives.