| @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])); | |
| } | |