| Category | Functions |
|---|---|
| Uniform sampling | uniformuniform01uniformDistribution |
| Element sampling | choicedice |
| Range sampling | randomCoverrandomSample |
| Default Random Engines | rndGenRandomunpredictableSeed |
| Linear Congruential Engines | MinstdRandMinstdRand0LinearCongruentialEngine |
| Mersenne Twister Engines | Mt19937Mt19937_64MersenneTwisterEngine |
| Xorshift Engines | XorshiftXorshiftEngineXorshift32Xorshift64Xorshift96Xorshift128Xorshift160Xorshift192 |
| Shuffle | partialShufflerandomShuffle |
| Traits | isSeedableisUniformRNG |
Sourcestd/random.d
CreditsThe entire random number library architecture is derived from the excellentC++0X random number facility proposed by Jens Maurer and contributed to by researchers at the Fermi laboratory (excluding Xorshift).
import std.algorithm.comparison : among, equal;import std.range : iota;// seed a random generator with a constantauto rnd = Random(42);// Generate a uniformly-distributed integer in the range [0, 14]// If no random generator is passed, the global `rndGen` would be usedauto 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 typeenum Fruit { apple, mango, pear }auto f = rnd.uniform!Fruit;with(Fruit)assert(f.among(apple, mango, pear));// Generate a 32-bit random numberauto u = uniform!uint(rnd);staticassert(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 randomlyauto 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 rangeassert(10.iota.randomSample(3, rnd2).equal([7, 8, 9]));// Cover all elements in an array in random orderversion (D_LP64)// https://issues.dlang.org/show_bug.cgi?id=15147assert(10.iota.randomCover(rnd2).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5]));elseassert(10.iota.randomCover(rnd2).equal([4, 8, 7, 3, 5, 9, 2, 6, 0, 1]));// Shuffle an arrayversion (D_LP64)// https://issues.dlang.org/show_bug.cgi?id=15147assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([2, 0, 4, 5, 1]));elseassert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([4, 2, 5, 0, 1]));
isUniformRNG(Rng, ElementType);isUniformRNG(Rng);struct NoRng{ @propertyuint front() {return 0;} @propertybool empty() {returnfalse;}void popFront() {}}staticassert(!isUniformRNG!(NoRng));struct validRng{ @propertyuint front() {return 0;} @propertybool empty() {returnfalse;}void popFront() {}enum isUniformRandom =true;}staticassert(isUniformRNG!(validRng,uint));staticassert(isUniformRNG!(validRng));
isSeedable(Rng, SeedType);isSeedable(Rng);struct validRng{ @propertyuint front() {return 0;} @propertybool empty() {returnfalse;}void popFront() {}enum isUniformRandom =true;}staticassert(!isSeedable!(validRng,uint));staticassert(!isSeedable!(validRng));struct seedRng{ @propertyuint front() {return 0;} @propertybool empty() {returnfalse;}void popFront() {}void seed(uint val){}enum isUniformRandom =true;}staticassert(isSeedable!(seedRng,uint));staticassert(!isSeedable!(seedRng,ulong));staticassert(isSeedable!(seedRng));
LinearCongruentialEngine(UIntType, UIntType a, UIntType c, UIntType m) if (isUnsigned!UIntType);alias CPP11LCG =LinearCongruentialEngine!(uint, 48271, 0, 2_147_483_647);// seed with a constantauto rnd = CPP11LCG(42);auto n = rnd.front;// same for each runwriteln(n);// 2027382
// glibc's LCGalias GLibcLCG =LinearCongruentialEngine!(uint, 1103515245, 12345, 2_147_483_648);// Seed with an unpredictable valueauto rnd = GLibcLCG(unpredictableSeed);auto n = rnd.front;// different across runs
// Visual C++'s LCGalias MSVCLCG =LinearCongruentialEngine!(uint, 214013, 2531011, 0);// seed with a constantauto rnd = MSVCLCG(1);auto n = rnd.front;// same for each runwriteln(n);// 2745024
isUniformRandom;hasFixedRange;min;max;multiplier;increment;modulus;x0);x0.seed(UIntTypex0 = 1);popFront();front() const;save() const;empty;MinstdRand0 = LinearCongruentialEngine!(uint, 16807u, 0u, 2147483647u).LinearCongruentialEngine;MinstdRand = LinearCongruentialEngine!(uint, 48271u, 0u, 2147483647u).LinearCongruentialEngine;MinstdRand0 implements Park and Miller's "minimalstandard"generator that uses 16807 for the multiplier.MinstdRandimplements a variant that has slightly better spectral behavior byusing the multiplier 48271. Both generators are rather simplistic.// seed with a constantauto rnd0 =MinstdRand0(1);auto n = rnd0.front;// same for each runwriteln(n);// 16807// Seed with an unpredictable valuernd0.seed(unpredictableSeed);n = rnd0.front;// different across runs
MersenneTwisterEngine(UIntType, size_t w, size_t n, size_t m, size_t r, UIntType a, size_t u, UIntType d, size_t s, UIntType b, size_t t, UIntType c, size_t l, UIntType f) if (isUnsigned!UIntType);// seed with a constantMt19937 gen;auto n = gen.front;// same for each runwriteln(n);// 3499211612// Seed with an unpredictable valuegen.seed(unpredictableSeed);n = gen.front;// different across runs
isUniformRandom;wordSize;stateSize;shiftSize;maskBits;xorMask;temperingU;temperingD;temperingS;temperingB;temperingT;temperingC;temperingL;initializationMultiplier;min;max;defaultSeed;value);seed()(UIntTypevalue = defaultSeed);NoteThis seed function gives 2^w starting points (the lowest w bits of the value provided will be used). To allow the RNG to be started in any one of its internal states use the seed overload taking an InputRange.
seed(T)(Trange)popFront();front() const;save() const;empty;Mt19937 = MersenneTwisterEngine!(uint, 32LU, 624LU, 397LU, 31LU, 2567483615u, 11LU, 4294967295u, 7LU, 2636928640u, 15LU, 4022730752u, 18LU, 1812433253u).MersenneTwisterEngine;// seed with a constantMt19937 gen;auto n = gen.front;// same for each runwriteln(n);// 3499211612// Seed with an unpredictable valuegen.seed(unpredictableSeed);n = gen.front;// different across runs
Mt19937_64 = MersenneTwisterEngine!(ulong, 64LU, 312LU, 156LU, 31LU, 13043109905998158313LU, 29LU, 6148914691236517205LU, 17LU, 8202884508482404352LU, 37LU, 18444473444759240704LU, 43LU, 6364136223846793005LU).MersenneTwisterEngine;// Seed with a constantauto gen =Mt19937_64(12345);auto n = gen.front;// same for each runwriteln(n);// 6597103971274460346// Seed with an unpredictable valuegen.seed(unpredictableSeed!ulong);n = gen.front;// different across runs
XorshiftEngine(UIntType, uint nbits, int sa, int sb, int sc) if (isUnsigned!UIntType && !(sa > 0 && (sb > 0) && (sc > 0)));XorshiftEngine(UIntType, int bits, int a, int b, int c) if (isUnsigned!UIntType && (a > 0) && (b > 0) && (c > 0))| UIntType | Word size of this xorshift generator and the return type ofopCall. |
| nbits | The number of bits of state of this generator. This must be a positive multiple of the size in bits of UIntType. If nbits is large this struct may occupy slightly more memory than this so it can use a circular counter instead of shifting the entire array. |
| sa | The direction and magnitude of the 1st shift. Positive means left, negative means right. |
| sb | The direction and magnitude of the 2nd shift. Positive means left, negative means right. |
| sc | The direction and magnitude of the 3rd shift. Positive means left, negative means right. |
NoteFor historical compatibility whennbits == 192 andUIntType isuinta legacy hybrid PRNG is used consisting of a 160-bit xorshift combinedwith a 32-bit counter. This combined generator has period equal to theleast common multiple of2^^160 - 1 and2^^32.
Previous versions ofXorshiftEngine did not provide any mechanism to specifythe directions of the shifts, taking each shift as an unsigned magnitude.For backwards compatibility, because three shifts in the same directioncannot result in a full-period XorshiftEngine, when all three ofsa,sb,sc, are positiveXorshiftEngine` treats them as unsigned magnitudes anduses shift directions to match the old behavior ofXorshiftEngine.Not every set of shifts results in a full-period xorshift generator.The template does not currently at compile-time perform a full checkfor maximum period but in a future version might reject parametersresulting in shorter periods.alias Xorshift96 =XorshiftEngine!(uint, 96, 10, 5, 26);auto rnd = Xorshift96(42);auto num = rnd.front;// same for each runwriteln(num);// 2704588748
isUniformRandom;empty;min;max;x0);UIntTypex0 | value used to deterministically initialize internal state |
seed()(UIntTypex0);UIntTypex0 | value used to deterministically initialize internal state |
front() const;popFront();save() const;Xorshift32 = XorshiftEngine!(uint, 32u, 13, -17, 15).XorshiftEngine;Xorshift64 = XorshiftEngine!(uint, 64u, 10, -13, -10).XorshiftEngine;Xorshift96 = XorshiftEngine!(uint, 96u, 10, -5, -26).XorshiftEngine;Xorshift128 = XorshiftEngine!(uint, 128u, 11, -8, -19).XorshiftEngine;Xorshift160 = XorshiftEngine!(uint, 160u, 2, -1, -4).XorshiftEngine;Xorshift192 = XorshiftEngine!(uint, 192u, -2, 1, 4).XorshiftEngine;Xorshift = XorshiftEngine!(uint, 128u, 11, -8, -19).XorshiftEngine;Xorshift is a Xorshift128's alias because 128bits implementation is mostly used.// Seed with a constantauto rnd =Xorshift(1);auto num = rnd.front;// same for each runwriteln(num);// 1405313047// Seed with an unpredictable valuernd.seed(unpredictableSeed);num = rnd.front;// different across rnd
unpredictableSeed();unpredictableSeed(UIntType) if (isUnsigned!UIntType)WarningThis function must not be used for cryptographic purposes.Despite being implemented for certain targets, there are no guaranteesthat it sources its randomness from a CSPRNG.The implementation also includes a fallback option that provides very littlerandomness and is used when no better source of randomness is available orintegrated on the target system.As written earlier, this function only aims to provide randomness for seedingordinary (non-cryptographic) PRNG engines.
NoteIn general periodically 'reseeding' a PRNG does not improve its qualityand in some cases may harm it. For an extreme example the MersenneTwister has2 ^^ 19937 - 1 distinct states but afterseed(uint) iscalled it can only be in one of2 ^^ 32 distinct states regardless ofhow excellent the source of entropy is.
auto rnd = Random(unpredictableSeed);auto n = rnd.front;staticassert(is(typeof(n) ==uint));
Random = MersenneTwisterEngine!(uint, 32LU, 624LU, 397LU, 31LU, 2567483615u, 11LU, 4294967295u, 7LU, 2636928640u, 15LU, 4022730752u, 18LU, 1812433253u).MersenneTwisterEngine;rndGen();import std.algorithm.iteration : sum;import std.range : take;auto rnd =rndGen;assert(rnd.take(3).sum > 0);
uniform(string boundaries = "[)", T1, T2)(T1a, T2b)uniform(string boundaries = "[)", T1, T2, UniformRandomNumberGenerator)(T1a, T2b, ref UniformRandomNumberGeneratorurng)uniform(string boundaries = "[)", T1, T2, RandomGen)(T1a, T2b, ref RandomGenrng)a andb. Theboundariesparameter controls the shape of the interval (open vs. closed oneither side). Valid values forboundaries are"[]","(]","[)", and"()". The default intervalis closed to the left and open to the right. The version that does nottakeurng uses the default generatorrndGen.T1a | lower bound of the uniform distribution |
T2b | upper bound of the uniform distribution |
UniformRandomNumberGeneratorurng | (optional) random number generator to use; if not specified, defaults torndGen |
a andb, whose type is the common type of these parametersauto rnd = Random(unpredictableSeed);// Generate an integer in [0, 1023]autoa =uniform(0, 1024, rnd);assert(0 <=a &&a < 1024);// Generate a float in [0, 1)autob =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);
import std.array : array;import std.range : generate, takeExactly;int[] arr = generate!(() =>uniform(0, 100)).takeExactly(10).array;writeln(arr.length);// 10assert(arr[0] >= 0 && arr[0] < 100);
import std.conv : to;import std.meta : AliasSeq;import std.range.primitives : isForwardRange;import std.traits : isIntegral, isSomeChar;auto gen = Mt19937(123_456_789);staticassert(isForwardRange!(typeof(gen)));autoa =uniform(0, 1024, gen);assert(0 <=a &&a <= 1024);autob =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);staticforeach (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 */staticif (isIntegral!T || isSomeChar!T) {foreach (immutable _; 0 .. 100) {auto u =uniform!"[]"(T.min, T.max);staticassert(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);staticforeach (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) {immutableint 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) {immutableubyte 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) { writeln(i);// uniform(i, i + 1, reproRng) }}
uniform(T, UniformRandomNumberGenerator)(ref UniformRandomNumberGeneratorurng)uniform(T)()uniform(E, UniformRandomNumberGenerator)(ref UniformRandomNumberGeneratorurng)uniform(E)()UniformRandomNumberGeneratorurng | (optional) random number generator to use; if not specified, defaults torndGen |
auto rnd = MinstdRand0(42);writeln(rnd.uniform!ubyte);// 102writeln(rnd.uniform!ulong);// 4838462006927449017enum Fruit { apple, mango, pear }version (D_LP64)// https://issues.dlang.org/show_bug.cgi?id=15147writeln(rnd.uniform!Fruit);// Fruit.mango
uniform01(T = double)()uniform01(T = double, UniformRNG)(ref UniformRNGrng)uniform01 offers a faster generation of random variates than the equivalentuniform!"[)"(0.0, 1.0) and so may be preferred for some applications.UniformRNGrng | (optional) random number generator to use; if not specified, defaults torndGen |
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.524587assert(u1.feqrel(0.000328707) > 20);assert(u2.feqrel(0.524587) > 20);
uniformDistribution(F = double)(size_tn, F[]useThis = null)n, i.e., anarray of sizen of positive numbers of typeF that sum to1. IfuseThis is provided, it is used as storage.import std.algorithm.iteration : reduce;import std.math.operations : isClose;auto a =uniformDistribution(5);writeln(a.length);// 5assert(isClose(reduce!"a + b"(a), 1));a =uniformDistribution(10, a);writeln(a.length);// 10assert(isClose(reduce!"a + b"(a), 1));
choice(Range, RandomGen = Random)(Rangerange, ref RandomGenurng)choice(Range)(Rangerange);choice(Range, RandomGen = Random)(ref Rangerange, ref RandomGenurng)choice(Range)(ref Rangerange);Rangerange | a random access range that has thelength property defined |
RandomGenurng | (optional) random number generator to use; if not specified, defaults torndGen |
range. If it can, it will return aref to therange element, otherwise it will return a copy.auto rnd = MinstdRand0(42);auto elem = [1, 2, 3, 4, 5].choice(rnd);version (D_LP64)// https://issues.dlang.org/show_bug.cgi?id=15147writeln(elem);// 3
randomShuffle(Range, RandomGen)(Ranger, ref RandomGengen)randomShuffle(Range)(Ranger)r usinggen as a shuffler.r must bea random-access range with length. If no RNG is specified,rndGenwill be used.Ranger | random-access range whose elements are to be shuffled |
RandomGengen | (optional) random number generator to use; if not specified, defaults torndGen |
auto rnd = MinstdRand0(42);auto arr = [1, 2, 3, 4, 5].randomShuffle(rnd);version (D_LP64)// https://issues.dlang.org/show_bug.cgi?id=15147writeln(arr);// [3, 5, 2, 4, 1]
partialShuffle(Range, RandomGen)(Ranger, in size_tn, ref RandomGengen)partialShuffle(Range)(Ranger, in size_tn)r such that upon returningr[0 .. n]is a random subset ofr and is randomly ordered.r[n .. r.length]will contain the elements not inr[0 .. n]. These will be in an undefinedorder, but will not be random in the sense that their order afterpartialShuffle returns will not be independent of their order beforepartialShuffle was called.r must be a random-access range with length.n must be less thanor equal tor.length. If no RNG is specified,rndGen will be used.Ranger | random-access range whose elements are to be shuffled |
size_tn | number of elements ofr to shuffle (counting from the beginning); must be less thanr.length |
RandomGengen | (optional) random number generator to use; if not specified, defaults torndGen |
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=15147assert(arr == [2, 1, 3, 4, 5, 6]);// 1<->2arr = arr.dup.partialShuffle(2, rnd);version (D_LP64)// https://issues.dlang.org/show_bug.cgi?id=15147assert(arr == [1, 4, 3, 2, 5, 6]);// 1<->2, 2<->4arr = arr.dup.partialShuffle(3, rnd);version (D_LP64)// https://issues.dlang.org/show_bug.cgi?id=15147assert(arr == [5, 4, 6, 2, 1, 3]);// 1<->5, 2<->4, 3<->6
dice(Rng, Num)(ref Rngrnd, Num[]proportions...)dice(R, Range)(ref Rrnd, Rangeproportions)dice(Range)(Rangeproportions)dice(Num)(Num[]proportions...)proportions.Returns the index inproportions that was chosen.NoteUsually, dice are 'fair', meaning that each side has equal probability to come up, in which case1 + uniform(0, 6) can simply be used. In future Phobos versions, this function might get renamed to something likeweightedChoice to avoid confusion.
Rngrnd | (optional) random number generator to use; if not specified, defaults torndGen |
Num[]proportions | forward range or list of individual values whose elements correspond to the probabilities with which to choose the corresponding index value |
proportions.length - 1], with the probability of getting an individual index valuei being proportional toproportions[i].auto d6 = 1 +dice(1, 1, 1, 1, 1, 1);// fair dice rollauto 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 proportionsauto y =dice(50, 50);// y is 0 or 1 in equal proportionsauto z =dice(70, 20, 10);// z is 0 70% of the time, 1 20% of the time,// and 2 10% of the time
autornd = MinstdRand0(42);auto z =rnd.dice(70, 20, 10);writeln(z);// 0z =rnd.dice(30, 20, 40, 10);writeln(z);// 2
RandomCover(Range, UniformRNG = void) if (isRandomAccessRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG == void)));randomCover(Range, UniformRNG)(Ranger, auto ref UniformRNGrng)randomCover(Range)(Ranger)r in a random manner, i.e. goes through eachelement ofr once and only once, just in a random order.rmust be a random-access range with length.randomCover, thethread-global RNG rndGen will be used internally.Ranger | random-access range to cover |
UniformRNGrng | (optional) random number generator to use; if not specified, defaults torndGen |
r, in random order. Will be a forward range if bothr andrng are forward ranges, aninput range otherwise.import std.algorithm.comparison : equal;import std.range : iota;auto rnd = MinstdRand0(42);version (D_LP64)// https://issues.dlang.org/show_bug.cgi?id=15147assert(10.iota.randomCover(rnd).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5]));
RandomSample(Range, UniformRNG = void) if (isInputRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG == void)));randomSample(Range)(Ranger, size_tn, size_ttotal)randomSample(Range)(Ranger, size_tn)randomSample(Range, UniformRNG)(Ranger, size_tn, size_ttotal, auto ref UniformRNGrng)randomSample(Range, UniformRNG)(Ranger, size_tn, auto ref UniformRNGrng)r, containing exactlynelements. The order of elements is the same as in the originalrange. The total length ofr must be known. Iftotal ispassed in, the total number of sample is considered to betotal. Otherwise,RandomSample usesr.length.Ranger | range to sample from |
size_tn | number of elements to include in the sample; must be less than or equal to the total number of elements inr and/or the parametertotal (if provided) |
size_ttotal | (semi-optional) number of elements ofr from which to select the sample (counting from the beginning); must be less than or equal to the total number of elements inr itself. May be omitted ifr has the.length property and the sample is to be drawn from all elements ofr. |
UniformRNGrng | (optional) random number generator to use; if not specified, defaults torndGen |
r, in the same order as these elements appear inr itself. Will be a forward range if bothr andrng are forward ranges, an input range otherwise.RandomSample implements Jeffrey Scott Vitter's Algorithm D(see Vitter1984,1987), which selects a sampleof sizen in O(n) steps and requiring O(n) random variates,regardless of the size of the data being sampled. The exceptionto this is if traversing k elements on the input range is itselfan O(k) operation (e.g. when sampling lines from an input file),in which case the sampling calculation will inevitably be ofO(total).RandomSample will throw an exception iftotal is verifiablyless than the total number of elements available in the input,or ifn > total.If no random number generator is passed torandomSample, thethread-global RNG rndGen will be used internally.import std.algorithm.comparison : equal;import std.range : iota;auto rnd = MinstdRand0(42);assert(10.iota.randomSample(3, rnd).equal([7, 8, 9]));
empty() const;front();popFront();save() const;length() const;index();