Report a bug
If you spot a problem with this page, click here to create a Github issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

mir.random.engine

Uniform random engines.
Sections: ConvenienceEntropyThread-LocalTraitsC Interface
    Convenience
Random Default random number engine
rne Per-thread uniquely-seeded instance of default Random. Requires TLS.
    Entropy
unpredictableSeed Seed of size_t using system entropy
unpredictableSeedOf Generalization of unpredictableSeed for unsigned integers of different sizes
genRandomNonBlocking Fills a buffer with system entropy, returning number of bytes copied or negative number on error
genRandomBlocking Fills a buffer with system entropy, possibly waiting if the system believes it has insufficient entropy. Returns 0 on success.
    Thread-Local (when TLS enabled)
threadLocal!(Engine) Per-thread uniquely-seeded instance of any specified Engine. Requires TLS.
threadLocalPtr!(Engine) @safe pointer to threadLocal!Engine. Always initializes before return. Warning: do not share between threads!
threadLocalInitialized!(Engine) Explicitly manipulate "is seeded" flag for thread-local instance. Not needed by most library users.
setThreadLocalSeed!(Engine, A...) Initialize thread-local Engine with a known seed rather than a random seed.
    Traits
EngineReturnType Get return type of random number engine's opCall()
isRandomEngine Check if is random number engine
isSaturatedRandomEngine Check if random number engine G such that G.max == EngineReturnType!(G).max
preferHighBits Are the high bits of the engine's output known to have better statistical properties than the low bits?
    C Interface
mir_random_engine_ctor Perform any necessary setup. Automatically called by DRuntime.
mir_random_engine_dtor Release any resources. Automatically called by DRuntime.
mir_random_genRandomNonBlocking External name for genRandomNonBlocking
mir_random_genRandomBlocking External name for genRandomBlocking
Authors:
Ilya Yaroshenko
template EngineReturnType(T)
Like std.traits.ReturnType!T but it works even if T.opCall is a function template.
template isRandomEngine(T)
Test if T is a random engine. A type should define enum isRandomEngine = true; to be a random engine.
template isSaturatedRandomEngine(T)
Test if T is a saturated random-bit generator. A random number generator is saturated if T.max == ReturnType!T.max. A type should define enum isRandomEngine = true; to be a random engine.
template preferHighBits(G) if (isSaturatedRandomEngine!G)
Are the high bits of the engine's output known to have better statistical properties than the low bits of the output? This property is set by checking the value of an optional enum named preferHighBits. If the property is missing it is treated as false.
This should be specified as true for:
  • linear congruential generators with power-of-2 modulus
  • xorshift+ family
  • xorshift* family
  • in principle any generator whose final operation is something like multiplication or addition in which the high bits depend on the low bits but the low bits are unaffected by the high bits.
nothrow @nogc @property @trusted size_t unpredictableSeed();

nothrow @nogc @property @trusted T unpredictableSeedOf(T)()
if (isUnsigned!T);
A "good" seed for initializing random number engines. Initializing with unpredictableSeed makes engines generate different random number sequences every run.
Returns:
A single unsigned integer seed value, different on each successive call
Examples:
auto rnd = Random(unpredictableSeed);
auto n = rnd();
static assert(is(typeof(n) == size_t));
alias Random = mir.random.engine.mersenne_twister.MersenneTwisterEngine!(ulong, 64LU, 312LU, 156LU, 31LU, 13043109905998158313LU, 29LU, 6148914691236517205LU, 17LU, 8202884508482404352LU, 37LU, 18444473444759240704LU, 43LU, 6364136223846793005LU).MersenneTwisterEngine;
The "default", "favorite", "suggested" random number generator type on the current platform. It is an alias for one of the 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.
Examples:
import std.traits;
static assert(isSaturatedRandomEngine!Random);
static assert(is(EngineReturnType!Random == size_t));
alias rne = threadLocal!(MersenneTwisterEngine!(ulong, 64LU, 312LU, 156LU, 31LU, 13043109905998158313LU, 29LU, 6148914691236517205LU, 17LU, 8202884508482404352LU, 37LU, 18444473444759240704LU, 43LU, 6364136223846793005LU)).threadLocal;
Thread-local instance of the default Random allocated and seeded independently for each thread. Requires TLS.
Examples:
import mir.random;
import std.complex;

auto c = complex(rne.rand!real, rne.rand!real);

int[10] array;
foreach (ref e; array)
    e = rne.rand!int;
auto picked = array[rne.randIndex(array.length)];
@property ref Engine threadLocal(Engine)()
if (isSaturatedRandomEngine!Engine && is(Engine == struct));

@property Engine* threadLocalPtr(Engine)()
if (isSaturatedRandomEngine!Engine && is(Engine == struct));

@property ref bool threadLocalInitialized(Engine)()
if (isSaturatedRandomEngine!Engine && is(Engine == struct));
threadLocal!Engine returns a reference to a thread-local instance of the specified random number generator allocated and seeded uniquely for each thread. Requires TLS.
threadLocalPtr!Engine is a pointer to the area of thread-local storage used by threadLocal!Engine. This function is provided because the compiler can infer it is @safe, unlike &(threadLocal!Engine). Like threadLocal!Engine this function will auto-initialize the engine. Do not share pointers returned by threadLocalPtr between threads!
threadLocalInitialized!Engine is a low-level way to explicitly change the "initialized" flag used by threadLocal!Engine to determine whether the Engine needs to be seeded. Setting this to false gives a way of forcing the next call to threadLocal!Engine to reseed. In general this is unnecessary but there are some specialized use cases where users have requested this ability.
Examples:
import mir.random;
import mir.random.engine.xorshift;

alias gen = threadLocal!Xorshift1024StarPhi;
double x = gen.rand!double;
size_t i = gen.randIndex(100u);
ulong a = gen.rand!ulong;
Examples:
import mir.random;
//If you need a pointer to the engine, getting it like this is @safe:
Random* ptr = threadLocalPtr!Random;
Examples:
import mir.random;
import mir.random.engine.xorshift;
//If you need to mark the engine as uninitialized to force a reseed,
//you can do it like this:
threadLocalInitialized!Xorshift1024StarPhi = false;
Examples:
import mir.random;
import mir.random.engine.mersenne_twister;
//You can mark the engine as already initialized to skip
//automatic seeding then initialize it yourself, for instance
//if you want to use a known seed rather than a random one.
threadLocalInitialized!Mt19937 = true;
immutable uint[4] customSeed = [0x123, 0x234, 0x345, 0x456];
threadLocal!Mt19937.__ctor(customSeed);
foreach(_; 0..999)
    threadLocal!Mt19937.rand!uint;
assert(3460025646u == threadLocal!Mt19937.rand!uint);
Examples:
import mir.random;
import mir.random.engine.xorshift;

alias gen = threadLocal!Xorshift1024StarPhi;

//If you want to you can call the generator's opCall instead of using
//rand!T but it is somewhat clunky because of the ambiguity of
//@property syntax: () looks like optional function parentheses.
static assert(!__traits(compiles, {ulong x0 = gen();}));//<-- Won't work
static assert(is(typeof(gen()) == Xorshift1024StarPhi));//<-- because the type is this.
ulong x1 = gen.opCall();//<-- This works though.
ulong x2 = gen()();//<-- This also works.

//But instead of any of those you should really just use gen.rand!T.
ulong x3 = gen.rand!ulong;
void setThreadLocalSeed(Engine, A...)(auto ref A seed)
if (isSaturatedRandomEngine!Engine && is(Engine == struct) && A.length >= 1 && is(typeof((ref A a) => Engine(a))));
Sets or resets the seed of threadLocal!Engine using the given arguments. It is not necessary to call this except if you wish to ensure the PRNG uses a known seed.
Examples:
import mir.random;
alias rnd = threadLocal!Random;

setThreadLocalSeed!Random(123);
immutable float x = rnd.rand!float;

assert(x != rnd.rand!float);

setThreadLocalSeed!Random(123);
immutable float y = rnd.rand!float;

assert(x == y);
void mir_random_engine_ctor();
Constructs the mir random seed generators. This constructor needs to be called once before other calls in mir.random.engine.
Automatically called by DRuntime.
void mir_random_engine_dtor();
Destructs the mir random seed generators.
Automatically called by DRuntime.
nothrow @nogc @system ptrdiff_t mir_random_genRandomBlocking(scope void* ptr, size_t len);

alias genRandomBlocking = genRandomBlocking;

nothrow @nogc @trusted ptrdiff_t genRandomBlocking()(scope ubyte[] buffer);
Fills a buffer with random data. If not enough entropy has been gathered, it will block.
Note that on Mac OS X this method will never block.
Parameters:
void* ptr pointer to the buffer to fill
size_t len length of the buffer (in bytes)
Returns:
A non-zero integer if an error occurred.
Examples:
ubyte[] buf = new ubyte[10];
genRandomBlocking(buf);

import std.algorithm.iteration : sum;
assert(buf.sum > 0, "Only zero points generated");
nothrow @nogc @system size_t mir_random_genRandomNonBlocking(scope void* ptr, size_t len);

alias genRandomNonBlocking = genRandomNonBlocking;

nothrow @nogc @trusted size_t genRandomNonBlocking()(scope ubyte[] buffer);
Fills a buffer with random data. If not enough entropy has been gathered, it won't block. Hence the error code should be inspected.
On Linux >= 3.17 genRandomNonBlocking is guaranteed to succeed for 256 bytes and fewer.
On Mac OS X, OpenBSD, and NetBSD genRandomNonBlocking is guaranteed to succeed for any number of bytes.
Parameters:
ubyte[] buffer the buffer to fill
size_t len length of the buffer (in bytes)
Returns:
The number of bytes filled - a negative number if an error occurred
Examples:
ubyte[] buf = new ubyte[10];
genRandomNonBlocking(buf);

import std.algorithm.iteration : sum;
assert(buf.sum > 0, "Only zero points generated");