@safe unittest { import std.random; 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 (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 assert(10.iota.randomCover(rnd2).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5])); else assert(10.iota.randomCover(rnd2).equal([4, 8, 7, 3, 5, 9, 2, 6, 0, 1])); // Shuffle an array version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([2, 0, 4, 5, 1])); else assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([4, 2, 5, 0, 1])); } @safe unittest { import std.random; 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)); } @safe unittest { import std.random; 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)); } @safe unittest { import std.random; 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 assert(n == 2027382); } @safe unittest { import std.random; // 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 } @safe unittest { import std.random; // Visual C++'s LCG alias MSVCLCG = LinearCongruentialEngine!(uint, 214013, 2531011, 0); // seed with a constant auto rnd = MSVCLCG(1); auto n = rnd.front; // same for each run assert(n == 2745024); } @safe @nogc unittest { import std.random; // seed with a constant auto rnd0 = MinstdRand0(1); auto n = rnd0.front; // same for each run assert(n == 16807); // Seed with an unpredictable value rnd0.seed(unpredictableSeed); n = rnd0.front; // different across runs } @safe unittest { import std.random; // seed with a constant Mt19937 gen; auto n = gen.front; // same for each run assert(n == 3499211612); // Seed with an unpredictable value gen.seed(unpredictableSeed); n = gen.front; // different across runs } @safe @nogc unittest { import std.random; // seed with a constant Mt19937 gen; auto n = gen.front; // same for each run assert(n == 3499211612); // Seed with an unpredictable value gen.seed(unpredictableSeed); n = gen.front; // different across runs } @safe @nogc unittest { import std.random; // Seed with a constant auto gen = Mt19937_64(12345); auto n = gen.front; // same for each run assert(n == 6597103971274460346); // Seed with an unpredictable value gen.seed(unpredictableSeed!ulong); n = gen.front; // different across runs } @safe unittest { import std.random; alias Xorshift96 = XorshiftEngine!(uint, 96, 10, 5, 26); auto rnd = Xorshift96(42); auto num = rnd.front; // same for each run assert(num == 2704588748); } @safe @nogc unittest { import std.random; // Seed with a constant auto rnd = Xorshift(1); auto num = rnd.front; // same for each run assert(num == 1405313047); // Seed with an unpredictable value rnd.seed(unpredictableSeed); num = rnd.front; // different across rnd } @safe @nogc unittest { import std.random; auto rnd = Random(unpredictableSeed); auto n = rnd.front; static assert(is(typeof(n) == uint)); } @safe nothrow @nogc unittest { import std.random; import std.algorithm.iteration : sum; import std.range : take; auto rnd = rndGen; assert(rnd.take(3).sum > 0); } @safe unittest { import std.random; auto 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); } @safe unittest { import std.random; import std.array : array; import std.range : generate, takeExactly; int[] arr = generate!(() => uniform(0, 100)).takeExactly(10).array; assert(arr.length == 10); assert(arr[0] >= 0 && arr[0] < 100); } @safe unittest { import std.random; import std.conv : to; import std.meta : AliasSeq; import std.range.primitives : isForwardRange; import std.traits : isIntegral, isSomeChar; auto gen = Mt19937(123_456_789); static assert(isForwardRange!(typeof(gen))); auto a = uniform(0, 1024, gen); assert(0 <= a && a <= 1024); auto b = uniform(0.0f, 1.0f, gen); assert(0 <= b && b < 1, to!string(b)); auto c = uniform(0.0, 1.0); assert(0 <= c && c < 1); static foreach (T; AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong, float, double, real)) {{ T lo = 0, hi = 100; // Try tests with each of the possible bounds { T init = uniform(lo, hi); size_t i = 50; while (--i && uniform(lo, hi) == init) {} assert(i > 0); } { T init = uniform!"[)"(lo, hi); size_t i = 50; while (--i && uniform(lo, hi) == init) {} assert(i > 0); } { T init = uniform!"(]"(lo, hi); size_t i = 50; while (--i && uniform(lo, hi) == init) {} assert(i > 0); } { T init = uniform!"()"(lo, hi); size_t i = 50; while (--i && uniform(lo, hi) == init) {} assert(i > 0); } { T init = uniform!"[]"(lo, hi); size_t i = 50; while (--i && uniform(lo, hi) == init) {} assert(i > 0); } /* Test case with closed boundaries covering whole range * of integral type */ static if (isIntegral!T || isSomeChar!T) { foreach (immutable _; 0 .. 100) { auto u = uniform!"[]"(T.min, T.max); static assert(is(typeof(u) == T)); assert(T.min <= u, "Lower bound violation for uniform!\"[]\" with " ~ T.stringof); assert(u <= T.max, "Upper bound violation for uniform!\"[]\" with " ~ T.stringof); } } }} auto reproRng = Xorshift(239842); static foreach (T; AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort, int, uint, long, ulong)) {{ T lo = T.min + 10, hi = T.max - 10; T init = uniform(lo, hi, reproRng); size_t i = 50; while (--i && uniform(lo, hi, reproRng) == init) {} assert(i > 0); }} { bool sawLB = false, sawUB = false; foreach (i; 0 .. 50) { auto x = uniform!"[]"('a', 'd', reproRng); if (x == 'a') sawLB = true; if (x == 'd') sawUB = true; assert('a' <= x && x <= 'd'); } assert(sawLB && sawUB); } { bool sawLB = false, sawUB = false; foreach (i; 0 .. 50) { auto x = uniform('a', 'd', reproRng); if (x == 'a') sawLB = true; if (x == 'c') sawUB = true; assert('a' <= x && x < 'd'); } assert(sawLB && sawUB); } { bool sawLB = false, sawUB = false; foreach (i; 0 .. 50) { immutable int lo = -2, hi = 2; auto x = uniform!"()"(lo, hi, reproRng); if (x == (lo+1)) sawLB = true; if (x == (hi-1)) sawUB = true; assert(lo < x && x < hi); } assert(sawLB && sawUB); } { bool sawLB = false, sawUB = false; foreach (i; 0 .. 50) { immutable ubyte lo = 0, hi = 5; auto x = uniform(lo, hi, reproRng); if (x == lo) sawLB = true; if (x == (hi-1)) sawUB = true; assert(lo <= x && x < hi); } assert(sawLB && sawUB); } { foreach (i; 0 .. 30) { assert(i == uniform(i, i+1, reproRng)); } } } @safe unittest { import std.random; auto rnd = MinstdRand0(42); assert(rnd.uniform!ubyte == 102); assert(rnd.uniform!ulong == 4838462006927449017); enum Fruit { apple, mango, pear } version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 assert(rnd.uniform!Fruit == Fruit.mango); } @safe @nogc unittest { import std.random; import std.math.operations : feqrel; auto rnd = MinstdRand0(42); // Generate random numbers in the range in the range [0, 1) auto u1 = uniform01(rnd); assert(u1 >= 0 && u1 < 1); auto u2 = rnd.uniform01!float; assert(u2 >= 0 && u2 < 1); // Confirm that the random values with the initial seed 42 are 0.000328707 and 0.524587 assert(u1.feqrel(0.000328707) > 20); assert(u2.feqrel(0.524587) > 20); } @safe unittest { import std.random; import std.algorithm.iteration : reduce; import std.math.operations : isClose; auto a = uniformDistribution(5); assert(a.length == 5); assert(isClose(reduce!"a + b"(a), 1)); a = uniformDistribution(10, a); assert(a.length == 10); assert(isClose(reduce!"a + b"(a), 1)); } @safe unittest { import std.random; auto rnd = MinstdRand0(42); auto elem = [1, 2, 3, 4, 5].choice(rnd); version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 assert(elem == 3); } @safe unittest { import std.random; auto rnd = MinstdRand0(42); auto arr = [1, 2, 3, 4, 5].randomShuffle(rnd); version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 assert(arr == [3, 5, 2, 4, 1]); } @safe unittest { import std.random; auto rnd = MinstdRand0(42); auto arr = [1, 2, 3, 4, 5, 6]; arr = arr.dup.partialShuffle(1, rnd); version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 assert(arr == [2, 1, 3, 4, 5, 6]); // 1<->2 arr = arr.dup.partialShuffle(2, rnd); version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 assert(arr == [1, 4, 3, 2, 5, 6]); // 1<->2, 2<->4 arr = arr.dup.partialShuffle(3, rnd); version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 assert(arr == [5, 4, 6, 2, 1, 3]); // 1<->5, 2<->4, 3<->6 } @safe unittest { import std.random; auto d6 = 1 + dice(1, 1, 1, 1, 1, 1); // fair dice roll auto d6b = 1 + dice(2, 1, 1, 1, 1, 1); // double the chance to roll '1' 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 } @safe unittest { import std.random; auto rnd = MinstdRand0(42); auto z = rnd.dice(70, 20, 10); assert(z == 0); z = rnd.dice(30, 20, 40, 10); assert(z == 2); } @safe unittest { import std.random; auto rnd = Xorshift(123_456_789); auto i = dice(rnd, 0.0, 100.0); assert(i == 1); i = dice(rnd, 100.0, 0.0); assert(i == 0); i = dice(100U, 0U); assert(i == 0); } @safe unittest { import std.random; import std.algorithm.comparison : equal; import std.range : iota; auto rnd = MinstdRand0(42); version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 assert(10.iota.randomCover(rnd).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5])); } @safe unittest { import std.random; import std.algorithm.comparison : equal; import std.range : iota; auto rnd = MinstdRand0(42); assert(10.iota.randomSample(3, rnd).equal([7, 8, 9])); }