Libmir Archive
mir-randommir-random

mir-random

High-quality random number generation and statistical distributions for D. BetterC compatible, @nogc, with ndslice integration for filling arrays.

📖 Full API reference → mir-random.libmir.org — every module and symbol of mir-random, regenerated from current source.

mir-random provides high-quality, statistically-sound pseudo-random number generators (PRNGs) for D, plus a full suite of statistical distributions. These are suitable for simulation, numerical computing, and statistical sampling — they are not cryptographically secure RNGs and should not be used for secrets or tokens. It integrates directly with ndslice for batch generation.

GitHub: libmir/mir-random — last commit June 2026 (most actively maintained Mir library as of mid-2026).

Install

dependency "mir-random" version="~>2.0"

Generators

Random — the default PRNG (Xorshift1024*)

import mir.random;

auto rng = Random(unpredictableSeed);  // seed from OS
ulong v  = rng.rand!ulong;            // uniform [0, ulong.max]
double d = rng.rand!double;           // uniform [0, 1)

Available generators

GeneratorSpeedPeriodNotes
Xorshift1024StarPhiVery fast2^1024 − 1Default Random
Xoroshiro128PlusFastest2^128 − 1Good for parallel streams
PCG64Fast2^128Statistically excellent
Mt19937Moderate2^19937 − 1Classic Mersenne Twister
Splitmix64Very fast2^64Seed generator
import mir.random.engine.xorshift : Xoroshiro128Plus;

auto rng = Xoroshiro128Plus(12345);

Distributions (mir.random.variable)

Uniform

import mir.random.variable : UniformVariable;

auto rng = Random(unpredictableSeed);
auto u = UniformVariable!double(0.0, 10.0);
double x = u(rng);   // uniform in [0, 10)

Normal (Gaussian)

import mir.random.variable : NormalVariable;

auto n = NormalVariable!double(0.0, 1.0);  // mean=0, std=1
double x = n(rng);

Other distributions

import mir.random.variable;

auto exp  = ExponentialVariable!double(2.0);   // rate λ=2
auto beta = BetaVariable!double(2.0, 5.0);    // α=2, β=5
auto gam  = GammaVariable!double(1.0, 2.0);   // shape=1, scale=2
auto poi  = PoissonVariable!double(3.5);       // λ=3.5
auto bin  = BinomialVariable!double(10, 0.3); // n=10, p=0.3

Filling ndslice arrays

import mir.random;
import mir.random.variable : NormalVariable;
import mir.ndslice;

auto rng  = Random(unpredictableSeed);
auto norm = NormalVariable!double(0.0, 1.0);

// Fill a matrix with standard normal samples
auto m = slice!double(100, 100);
m.each!((ref v) { v = norm(rng); });

// Or use generate (from std.range / mir.algorithm)
import mir.algorithm.iteration : each;
m.each!((ref double v) { v = norm(rng); });

Shuffling

import mir.random.algorithm : shuffle;

auto v = [1, 2, 3, 4, 5].sliced;
shuffle(rng, v);  // Fisher-Yates in-place

BetterC / @nogc usage

All generators and distributions are @nogc nothrow:

extern(C) double sample() @nogc nothrow
{
    import mir.random;
    import mir.random.variable : NormalVariable;

    static Random rng;
    static bool seeded = false;
    if (!seeded) { rng = Random(12345); seeded = true; }

    auto n = NormalVariable!double(0.0, 1.0);
    return n(rng);
}

On this page