1 // Written in the D programming language.
2
3 /**
4 Facilities for random number generation.
5
6 $(RED Disclaimer:) The _random number generators and API provided in this
7 module are not designed to be cryptographically secure, and are therefore
8 unsuitable for cryptographic or security-related purposes such as generating
9 authentication tokens or network sequence numbers. For such needs, please use a
10 reputable cryptographic library instead.
11
12 The new-style generator objects hold their own state so they are
13 immune of threading issues. The generators feature a number of
14 well-known and well-documented methods of generating random
15 numbers. An overall fast and reliable means to generate random numbers
16 is the $(D_PARAM Mt19937) generator, which derives its name from
17 "$(LINK2 https://en.wikipedia.org/wiki/Mersenne_Twister, Mersenne Twister)
18 with a period of 2 to the power of
19 19937". In memory-constrained situations,
20 $(LINK2 https://en.wikipedia.org/wiki/Linear_congruential_generator,
21 linear congruential generators) such as $(D MinstdRand0) and $(D MinstdRand) might be
22 useful. The standard library provides an alias $(D_PARAM Random) for
23 whichever generator it considers the most fit for the target
24 environment.
25
26 In addition to random number generators, this module features
27 distributions, which skew a generator's output statistical
28 distribution in various ways. So far the uniform distribution for
29 integers and real numbers have been implemented.
30
31 Source: $(PHOBOSSRC std/_random.d)
32
33 Macros:
34
35 Copyright: Copyright Andrei Alexandrescu 2008 - 2009, Joseph Rushton Wakeling 2012.
36 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
37 Authors: $(HTTP erdani.org, Andrei Alexandrescu)
38 Masahiro Nakagawa (Xorshift random generator)
39 $(HTTP braingam.es, Joseph Rushton Wakeling) (Algorithm D for random sampling)
40 Ilya Yaroshenko (Mersenne Twister implementation, adapted from $(HTTPS github.com/libmir/mir-_random, mir-_random))
41 Credits: The entire random number library architecture is derived from the
42 excellent $(HTTP open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf, C++0X)
43 random number facility proposed by Jens Maurer and contributed to by
44 researchers at the Fermi laboratory (excluding Xorshift).
45 */
46 /*
47 Copyright Andrei Alexandrescu 2008 - 2009.
48 Distributed under the Boost Software License, Version 1.0.
49 (See accompanying file LICENSE_1_0.txt or copy at
50 http://www.boost.org/LICENSE_1_0.txt)
51 */
52 module std.random;
53
54
55 import std.range.primitives;
56 import std.traits;
57
58 ///
59 @safe unittest
60 {
61 // seed a random generator with a constant
62 auto rnd = Random(42);
63
64 // Generate a uniformly-distributed integer in the range [0, 14]
65 // If no random generator is passed, the global `rndGen` would be used
66 auto i = uniform(0, 15, rnd);
67 assert(i >= 0 && i < 15);
68
69 // Generate a uniformly-distributed real in the range [0, 100)
70 auto r = uniform(0.0L, 100.0L, rnd);
71 assert(r >= 0 && r < 100);
72
73 // Generate a 32-bit random number
74 auto u = uniform!uint(rnd);
75 static assert(is(typeof(u) == uint));
76 }
77
version(unittest)78 version (unittest)
79 {
80 static import std.meta;
81 package alias PseudoRngTypes = std.meta.AliasSeq!(MinstdRand0, MinstdRand, Mt19937, Xorshift32, Xorshift64,
82 Xorshift96, Xorshift128, Xorshift160, Xorshift192);
83 }
84
85 // Segments of the code in this file Copyright (c) 1997 by Rick Booth
86 // From "Inner Loops" by Rick Booth, Addison-Wesley
87
88 // Work derived from:
89
90 /*
91 A C-program for MT19937, with initialization improved 2002/1/26.
92 Coded by Takuji Nishimura and Makoto Matsumoto.
93
94 Before using, initialize the state by using init_genrand(seed)
95 or init_by_array(init_key, key_length).
96
97 Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
98 All rights reserved.
99
100 Redistribution and use in source and binary forms, with or without
101 modification, are permitted provided that the following conditions
102 are met:
103
104 1. Redistributions of source code must retain the above copyright
105 notice, this list of conditions and the following disclaimer.
106
107 2. Redistributions in binary form must reproduce the above copyright
108 notice, this list of conditions and the following disclaimer in the
109 documentation and/or other materials provided with the distribution.
110
111 3. The names of its contributors may not be used to endorse or promote
112 products derived from this software without specific prior written
113 permission.
114
115 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
116 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
117 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
118 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
119 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
120 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
121 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
122 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
123 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
124 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
125 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
126
127
128 Any feedback is very welcome.
129 http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
130 email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
131 */
132
133 /**
134 * Test if Rng is a random-number generator. The overload
135 * taking a ElementType also makes sure that the Rng generates
136 * values of that type.
137 *
138 * A random-number generator has at least the following features:
139 * $(UL
140 * $(LI it's an InputRange)
141 * $(LI it has a 'bool isUniformRandom' field readable in CTFE)
142 * )
143 */
isUniformRNG(Rng,ElementType)144 template isUniformRNG(Rng, ElementType)
145 {
146 enum bool isUniformRNG = isInputRange!Rng &&
147 is(typeof(Rng.front) == ElementType) &&
148 is(typeof(
149 {
150 static assert(Rng.isUniformRandom); //tag
151 }));
152 }
153
154 /**
155 * ditto
156 */
isUniformRNG(Rng)157 template isUniformRNG(Rng)
158 {
159 enum bool isUniformRNG = isInputRange!Rng &&
160 is(typeof(
161 {
162 static assert(Rng.isUniformRandom); //tag
163 }));
164 }
165
166 /**
167 * Test if Rng is seedable. The overload
168 * taking a SeedType also makes sure that the Rng can be seeded with SeedType.
169 *
170 * A seedable random-number generator has the following additional features:
171 * $(UL
172 * $(LI it has a 'seed(ElementType)' function)
173 * )
174 */
isSeedable(Rng,SeedType)175 template isSeedable(Rng, SeedType)
176 {
177 enum bool isSeedable = isUniformRNG!(Rng) &&
178 is(typeof(
179 {
180 Rng r = void; // can define a Rng object
181 r.seed(SeedType.init); // can seed a Rng
182 }));
183 }
184
185 ///ditto
isSeedable(Rng)186 template isSeedable(Rng)
187 {
188 enum bool isSeedable = isUniformRNG!Rng &&
189 is(typeof(
190 {
191 Rng r = void; // can define a Rng object
192 r.seed(typeof(r.front).init); // can seed a Rng
193 }));
194 }
195
196 @safe pure nothrow unittest
197 {
198 struct NoRng
199 {
frontNoRng200 @property uint front() {return 0;}
emptyNoRng201 @property bool empty() {return false;}
popFrontNoRng202 void popFront() {}
203 }
204 static assert(!isUniformRNG!(NoRng, uint));
205 static assert(!isUniformRNG!(NoRng));
206 static assert(!isSeedable!(NoRng, uint));
207 static assert(!isSeedable!(NoRng));
208
209 struct NoRng2
210 {
frontNoRng2211 @property uint front() {return 0;}
emptyNoRng2212 @property bool empty() {return false;}
popFrontNoRng2213 void popFront() {}
214
215 enum isUniformRandom = false;
216 }
217 static assert(!isUniformRNG!(NoRng2, uint));
218 static assert(!isUniformRNG!(NoRng2));
219 static assert(!isSeedable!(NoRng2, uint));
220 static assert(!isSeedable!(NoRng2));
221
222 struct NoRng3
223 {
emptyNoRng3224 @property bool empty() {return false;}
popFrontNoRng3225 void popFront() {}
226
227 enum isUniformRandom = true;
228 }
229 static assert(!isUniformRNG!(NoRng3, uint));
230 static assert(!isUniformRNG!(NoRng3));
231 static assert(!isSeedable!(NoRng3, uint));
232 static assert(!isSeedable!(NoRng3));
233
234 struct validRng
235 {
frontvalidRng236 @property uint front() {return 0;}
emptyvalidRng237 @property bool empty() {return false;}
popFrontvalidRng238 void popFront() {}
239
240 enum isUniformRandom = true;
241 }
242 static assert(isUniformRNG!(validRng, uint));
243 static assert(isUniformRNG!(validRng));
244 static assert(!isSeedable!(validRng, uint));
245 static assert(!isSeedable!(validRng));
246
247 struct seedRng
248 {
frontseedRng249 @property uint front() {return 0;}
emptyseedRng250 @property bool empty() {return false;}
popFrontseedRng251 void popFront() {}
seedseedRng252 void seed(uint val){}
253 enum isUniformRandom = true;
254 }
255 static assert(isUniformRNG!(seedRng, uint));
256 static assert(isUniformRNG!(seedRng));
257 static assert(isSeedable!(seedRng, uint));
258 static assert(isSeedable!(seedRng));
259 }
260
261 /**
262 Linear Congruential generator.
263 */
264 struct LinearCongruentialEngine(UIntType, UIntType a, UIntType c, UIntType m)
265 if (isUnsigned!UIntType)
266 {
267 ///Mark this as a Rng
268 enum bool isUniformRandom = true;
269 /// Does this generator have a fixed range? ($(D_PARAM true)).
270 enum bool hasFixedRange = true;
271 /// Lowest generated value ($(D 1) if $(D c == 0), $(D 0) otherwise).
272 enum UIntType min = ( c == 0 ? 1 : 0 );
273 /// Highest generated value ($(D modulus - 1)).
274 enum UIntType max = m - 1;
275 /**
276 The parameters of this distribution. The random number is $(D_PARAM x
277 = (x * multipler + increment) % modulus).
278 */
279 enum UIntType multiplier = a;
280 ///ditto
281 enum UIntType increment = c;
282 ///ditto
283 enum UIntType modulus = m;
284
285 static assert(isIntegral!(UIntType));
286 static assert(m == 0 || a < m);
287 static assert(m == 0 || c < m);
288 static assert(m == 0 ||
289 (cast(ulong) a * (m-1) + c) % m == (c < a ? c - a + m : c - a));
290
291 // Check for maximum range
gcd(ulong a,ulong b)292 private static ulong gcd(ulong a, ulong b) @safe pure nothrow @nogc
293 {
294 while (b)
295 {
296 auto t = b;
297 b = a % b;
298 a = t;
299 }
300 return a;
301 }
302
primeFactorsOnly(ulong n)303 private static ulong primeFactorsOnly(ulong n) @safe pure nothrow @nogc
304 {
305 ulong result = 1;
306 ulong iter = 2;
307 for (; n >= iter * iter; iter += 2 - (iter == 2))
308 {
309 if (n % iter) continue;
310 result *= iter;
311 do
312 {
313 n /= iter;
314 } while (n % iter == 0);
315 }
316 return result * n;
317 }
318
319 @safe pure nothrow unittest
320 {
321 static assert(primeFactorsOnly(100) == 10);
322 //writeln(primeFactorsOnly(11));
323 static assert(primeFactorsOnly(11) == 11);
324 static assert(primeFactorsOnly(7 * 7 * 7 * 11 * 15 * 11) == 7 * 11 * 15);
325 static assert(primeFactorsOnly(129 * 2) == 129 * 2);
326 // enum x = primeFactorsOnly(7 * 7 * 7 * 11 * 15);
327 // static assert(x == 7 * 11 * 15);
328 }
329
properLinearCongruentialParameters(ulong m,ulong a,ulong c)330 private static bool properLinearCongruentialParameters(ulong m,
331 ulong a, ulong c) @safe pure nothrow @nogc
332 {
333 if (m == 0)
334 {
335 static if (is(UIntType == uint))
336 {
337 // Assume m is uint.max + 1
338 m = (1uL << 32);
339 }
340 else
341 {
342 return false;
343 }
344 }
345 // Bounds checking
346 if (a == 0 || a >= m || c >= m) return false;
347 // c and m are relatively prime
348 if (c > 0 && gcd(c, m) != 1) return false;
349 // a - 1 is divisible by all prime factors of m
350 if ((a - 1) % primeFactorsOnly(m)) return false;
351 // if a - 1 is multiple of 4, then m is a multiple of 4 too.
352 if ((a - 1) % 4 == 0 && m % 4) return false;
353 // Passed all tests
354 return true;
355 }
356
357 // check here
358 static assert(c == 0 || properLinearCongruentialParameters(m, a, c),
359 "Incorrect instantiation of LinearCongruentialEngine");
360
361 /**
362 Constructs a $(D_PARAM LinearCongruentialEngine) generator seeded with
363 $(D x0).
364 */
this(UIntType x0)365 this(UIntType x0) @safe pure
366 {
367 seed(x0);
368 }
369
370 /**
371 (Re)seeds the generator.
372 */
373 void seed(UIntType x0 = 1) @safe pure
374 {
375 static if (c == 0)
376 {
377 import std.exception : enforce;
378 enforce(x0, "Invalid (zero) seed for "
379 ~ LinearCongruentialEngine.stringof);
380 }
381 _x = modulus ? (x0 % modulus) : x0;
382 popFront();
383 }
384
385 /**
386 Advances the random sequence.
387 */
popFront()388 void popFront() @safe pure nothrow @nogc
389 {
390 static if (m)
391 {
392 static if (is(UIntType == uint) && m == uint.max)
393 {
394 immutable ulong
395 x = (cast(ulong) a * _x + c),
396 v = x >> 32,
397 w = x & uint.max;
398 immutable y = cast(uint)(v + w);
399 _x = (y < v || y == uint.max) ? (y + 1) : y;
400 }
401 else static if (is(UIntType == uint) && m == int.max)
402 {
403 immutable ulong
404 x = (cast(ulong) a * _x + c),
405 v = x >> 31,
406 w = x & int.max;
407 immutable uint y = cast(uint)(v + w);
408 _x = (y >= int.max) ? (y - int.max) : y;
409 }
410 else
411 {
412 _x = cast(UIntType) ((cast(ulong) a * _x + c) % m);
413 }
414 }
415 else
416 {
417 _x = a * _x + c;
418 }
419 }
420
421 /**
422 Returns the current number in the random sequence.
423 */
front()424 @property UIntType front() const @safe pure nothrow @nogc
425 {
426 return _x;
427 }
428
429 ///
typeof(this)430 @property typeof(this) save() @safe pure nothrow @nogc
431 {
432 return this;
433 }
434
435 /**
436 Always $(D false) (random generators are infinite ranges).
437 */
438 enum bool empty = false;
439
440 /**
441 Compares against $(D_PARAM rhs) for equality.
442 */
opEquals(ref const LinearCongruentialEngine rhs)443 bool opEquals(ref const LinearCongruentialEngine rhs) const @safe pure nothrow @nogc
444 {
445 return _x == rhs._x;
446 }
447
448 private UIntType _x = m ? (a + c) % m : (a + c);
449 }
450
451 /**
452 Define $(D_PARAM LinearCongruentialEngine) generators with well-chosen
453 parameters. $(D MinstdRand0) implements Park and Miller's "minimal
454 standard" $(HTTP
455 wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator,
456 generator) that uses 16807 for the multiplier. $(D MinstdRand)
457 implements a variant that has slightly better spectral behavior by
458 using the multiplier 48271. Both generators are rather simplistic.
459 */
460 alias MinstdRand0 = LinearCongruentialEngine!(uint, 16_807, 0, 2_147_483_647);
461 /// ditto
462 alias MinstdRand = LinearCongruentialEngine!(uint, 48_271, 0, 2_147_483_647);
463
464 ///
465 @safe unittest
466 {
467 // seed with a constant
468 auto rnd0 = MinstdRand0(1);
469 auto n = rnd0.front; // same for each run
470 // Seed with an unpredictable value
471 rnd0.seed(unpredictableSeed);
472 n = rnd0.front; // different across runs
473 }
474
475 @safe unittest
476 {
477 import std.range;
478 static assert(isForwardRange!MinstdRand);
479 static assert(isUniformRNG!MinstdRand);
480 static assert(isUniformRNG!MinstdRand0);
481 static assert(isUniformRNG!(MinstdRand, uint));
482 static assert(isUniformRNG!(MinstdRand0, uint));
483 static assert(isSeedable!MinstdRand);
484 static assert(isSeedable!MinstdRand0);
485 static assert(isSeedable!(MinstdRand, uint));
486 static assert(isSeedable!(MinstdRand0, uint));
487
488 // The correct numbers are taken from The Database of Integer Sequences
489 // http://www.research.att.com/~njas/sequences/eisBTfry00128.txt
490 auto checking0 = [
491 16807UL,282475249,1622650073,984943658,1144108930,470211272,
492 101027544,1457850878,1458777923,2007237709,823564440,1115438165,
493 1784484492,74243042,114807987,1137522503,1441282327,16531729,
494 823378840,143542612 ];
495 //auto rnd0 = MinstdRand0(1);
496 MinstdRand0 rnd0;
497
foreach(e;checking0)498 foreach (e; checking0)
499 {
500 assert(rnd0.front == e);
501 rnd0.popFront();
502 }
503 // Test the 10000th invocation
504 // Correct value taken from:
505 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf
506 rnd0.seed();
507 popFrontN(rnd0, 9999);
508 assert(rnd0.front == 1043618065);
509
510 // Test MinstdRand
511 auto checking = [48271UL,182605794,1291394886,1914720637,2078669041,
512 407355683];
513 //auto rnd = MinstdRand(1);
514 MinstdRand rnd;
foreach(e;checking)515 foreach (e; checking)
516 {
517 assert(rnd.front == e);
518 rnd.popFront();
519 }
520
521 // Test the 10000th invocation
522 // Correct value taken from:
523 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf
524 rnd.seed();
525 popFrontN(rnd, 9999);
526 assert(rnd.front == 399268537);
527
528 // Check .save works
529 foreach (Type; std.meta.AliasSeq!(MinstdRand0, MinstdRand))
530 {
531 auto rnd1 = Type(unpredictableSeed);
532 auto rnd2 = rnd1.save;
533 assert(rnd1 == rnd2);
534 // Enable next test when RNGs are reference types
version(none)535 version (none) { assert(rnd1 !is rnd2); }
536 assert(rnd1.take(100).array() == rnd2.take(100).array());
537 }
538 }
539
540 /**
541 The $(LINK2 https://en.wikipedia.org/wiki/Mersenne_Twister, Mersenne Twister) generator.
542 */
543 struct MersenneTwisterEngine(UIntType, size_t w, size_t n, size_t m, size_t r,
544 UIntType a, size_t u, UIntType d, size_t s,
545 UIntType b, size_t t,
546 UIntType c, size_t l, UIntType f)
547 if (isUnsigned!UIntType)
548 {
549 static assert(0 < w && w <= UIntType.sizeof * 8);
550 static assert(1 <= m && m <= n);
551 static assert(0 <= r && 0 <= u && 0 <= s && 0 <= t && 0 <= l);
552 static assert(r <= w && u <= w && s <= w && t <= w && l <= w);
553 static assert(0 <= a && 0 <= b && 0 <= c);
554 static assert(n <= sizediff_t.max);
555
556 ///Mark this as a Rng
557 enum bool isUniformRandom = true;
558
559 /**
560 Parameters for the generator.
561 */
562 enum size_t wordSize = w;
563 enum size_t stateSize = n; /// ditto
564 enum size_t shiftSize = m; /// ditto
565 enum size_t maskBits = r; /// ditto
566 enum UIntType xorMask = a; /// ditto
567 enum size_t temperingU = u; /// ditto
568 enum UIntType temperingD = d; /// ditto
569 enum size_t temperingS = s; /// ditto
570 enum UIntType temperingB = b; /// ditto
571 enum size_t temperingT = t; /// ditto
572 enum UIntType temperingC = c; /// ditto
573 enum size_t temperingL = l; /// ditto
574 enum UIntType initializationMultiplier = f; /// ditto
575
576 /// Smallest generated value (0).
577 enum UIntType min = 0;
578 /// Largest generated value.
579 enum UIntType max = UIntType.max >> (UIntType.sizeof * 8u - w);
580 // note, `max` also serves as a bitmask for the lowest `w` bits
581 static assert(a <= max && b <= max && c <= max && f <= max);
582
583 /// The default seed value.
584 enum UIntType defaultSeed = 5489u;
585
586 // Bitmasks used in the 'twist' part of the algorithm
587 private enum UIntType lowerMask = (cast(UIntType) 1u << r) - 1,
588 upperMask = (~lowerMask) & this.max;
589
590 /*
591 Collection of all state variables
592 used by the generator
593 */
594 private struct State
595 {
596 /*
597 State array of the generator. This
598 is iterated through backwards (from
599 last element to first), providing a
600 few extra compiler optimizations by
601 comparison to the forward iteration
602 used in most implementations.
603 */
604 UIntType[n] data;
605
606 /*
607 Cached copy of most recently updated
608 element of `data` state array, ready
609 to be tempered to generate next
610 `front` value
611 */
612 UIntType z;
613
614 /*
615 Most recently generated random variate
616 */
617 UIntType front;
618
619 /*
620 Index of the entry in the `data`
621 state array that will be twisted
622 in the next `popFront()` call
623 */
624 size_t index;
625 }
626
627 /*
628 State variables used by the generator;
629 initialized to values equivalent to
630 explicitly seeding the generator with
631 `defaultSeed`
632 */
633 private State state = defaultState();
634 /* NOTE: the above is a workaround to ensure
635 backwards compatibility with the original
636 implementation, which permitted implicit
637 construction. With `@disable this();`
638 it would not be necessary. */
639
640 /**
641 Constructs a MersenneTwisterEngine object.
642 */
this(UIntType value)643 this(UIntType value) @safe pure nothrow @nogc
644 {
645 seed(value);
646 }
647
648 /**
649 Generates the default initial state for a Mersenne
650 Twister; equivalent to the internal state obtained
651 by calling `seed(defaultSeed)`
652 */
defaultState()653 private static State defaultState() @safe pure nothrow @nogc
654 {
655 if (!__ctfe) assert(false);
656 State mtState;
657 seedImpl(defaultSeed, mtState);
658 return mtState;
659 }
660
661 /**
662 Seeds a MersenneTwisterEngine object.
663 Note:
664 This seed function gives 2^w starting points (the lowest w bits of
665 the value provided will be used). To allow the RNG to be started
666 in any one of its internal states use the seed overload taking an
667 InputRange.
668 */
seed()669 void seed()(UIntType value = defaultSeed) @safe pure nothrow @nogc
670 {
671 this.seedImpl(value, this.state);
672 }
673
674 /**
675 Implementation of the seeding mechanism, which
676 can be used with an arbitrary `State` instance
677 */
seedImpl(UIntType value,ref State mtState)678 private static void seedImpl(UIntType value, ref State mtState)
679 {
680 mtState.data[$ - 1] = value;
681 static if (this.max != UIntType.max)
682 {
683 mtState.data[$ - 1] &= this.max;
684 }
685
686 foreach_reverse (size_t i, ref e; mtState.data[0 .. $ - 1])
687 {
688 e = f * (mtState.data[i + 1] ^ (mtState.data[i + 1] >> (w - 2))) + cast(UIntType)(n - (i + 1));
689 static if (this.max != UIntType.max)
690 {
691 e &= this.max;
692 }
693 }
694
695 mtState.index = n - 1;
696
697 /* double popFront() to guarantee both `mtState.z`
698 and `mtState.front` are derived from the newly
699 set values in `mtState.data` */
700 MersenneTwisterEngine.popFrontImpl(mtState);
701 MersenneTwisterEngine.popFrontImpl(mtState);
702 }
703
704 /**
705 Seeds a MersenneTwisterEngine object using an InputRange.
706
707 Throws:
708 $(D Exception) if the InputRange didn't provide enough elements to seed the generator.
709 The number of elements required is the 'n' template parameter of the MersenneTwisterEngine struct.
710 */
711 void seed(T)(T range) if (isInputRange!T && is(Unqual!(ElementType!T) == UIntType))
712 {
713 this.seedImpl(range, this.state);
714 }
715
716 /**
717 Implementation of the range-based seeding mechanism,
718 which can be used with an arbitrary `State` instance
719 */
720 private static void seedImpl(T)(T range, ref State mtState)
721 if (isInputRange!T && is(Unqual!(ElementType!T) == UIntType))
722 {
723 size_t j;
724 for (j = 0; j < n && !range.empty; ++j, range.popFront())
725 {
726 sizediff_t idx = n - j - 1;
727 mtState.data[idx] = range.front;
728 }
729
730 mtState.index = n - 1;
731
732 if (range.empty && j < n)
733 {
734 import core.internal.string : UnsignedStringBuf, unsignedToTempString;
735
736 UnsignedStringBuf buf = void;
737 string s = "MersenneTwisterEngine.seed: Input range didn't provide enough elements: Need ";
738 s ~= unsignedToTempString(n, buf, 10) ~ " elements.";
739 throw new Exception(s);
740 }
741
742 /* double popFront() to guarantee both `mtState.z`
743 and `mtState.front` are derived from the newly
744 set values in `mtState.data` */
745 MersenneTwisterEngine.popFrontImpl(mtState);
746 MersenneTwisterEngine.popFrontImpl(mtState);
747 }
748
749 /**
750 Advances the generator.
751 */
popFront()752 void popFront() @safe pure nothrow @nogc
753 {
754 this.popFrontImpl(this.state);
755 }
756
757 /*
758 Internal implementation of `popFront()`, which
759 can be used with an arbitrary `State` instance
760 */
popFrontImpl(ref State mtState)761 private static void popFrontImpl(ref State mtState)
762 {
763 /* This function blends two nominally independent
764 processes: (i) calculation of the next random
765 variate `mtState.front` from the cached previous
766 `data` entry `z`, and (ii) updating the value
767 of `data[index]` and `mtState.z` and advancing
768 the `index` value to the next in sequence.
769
770 By interweaving the steps involved in these
771 procedures, rather than performing each of
772 them separately in sequence, the variables
773 are kept 'hot' in CPU registers, allowing
774 for significantly faster performance. */
775 sizediff_t index = mtState.index;
776 sizediff_t next = index - 1;
777 if (next < 0)
778 next = n - 1;
779 auto z = mtState.z;
780 sizediff_t conj = index - m;
781 if (conj < 0)
782 conj = index - m + n;
783
784 static if (d == UIntType.max)
785 {
786 z ^= (z >> u);
787 }
788 else
789 {
790 z ^= (z >> u) & d;
791 }
792
793 auto q = mtState.data[index] & upperMask;
794 auto p = mtState.data[next] & lowerMask;
795 z ^= (z << s) & b;
796 auto y = q | p;
797 auto x = y >> 1;
798 z ^= (z << t) & c;
799 if (y & 1)
800 x ^= a;
801 auto e = mtState.data[conj] ^ x;
802 z ^= (z >> l);
803 mtState.z = mtState.data[index] = e;
804 mtState.index = next;
805
806 /* technically we should take the lowest `w`
807 bits here, but if the tempering bitmasks
808 `b` and `c` are set correctly, this should
809 be unnecessary */
810 mtState.front = z;
811 }
812
813 /**
814 Returns the current random value.
815 */
front()816 @property UIntType front() @safe const pure nothrow @nogc
817 {
818 return this.state.front;
819 }
820
821 ///
typeof(this)822 @property typeof(this) save() @safe pure nothrow @nogc
823 {
824 return this;
825 }
826
827 /**
828 Always $(D false).
829 */
830 enum bool empty = false;
831 }
832
833 /**
834 A $(D MersenneTwisterEngine) instantiated with the parameters of the
835 original engine $(HTTP math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html,
836 MT19937), generating uniformly-distributed 32-bit numbers with a
837 period of 2 to the power of 19937. Recommended for random number
838 generation unless memory is severely restricted, in which case a $(D
839 LinearCongruentialEngine) would be the generator of choice.
840 */
841 alias Mt19937 = MersenneTwisterEngine!(uint, 32, 624, 397, 31,
842 0x9908b0df, 11, 0xffffffff, 7,
843 0x9d2c5680, 15,
844 0xefc60000, 18, 1_812_433_253);
845
846 ///
847 @safe unittest
848 {
849 // seed with a constant
850 Mt19937 gen;
851 auto n = gen.front; // same for each run
852 // Seed with an unpredictable value
853 gen.seed(unpredictableSeed);
854 n = gen.front; // different across runs
855 }
856
857 @safe nothrow unittest
858 {
859 import std.algorithm;
860 import std.range;
861 static assert(isUniformRNG!Mt19937);
862 static assert(isUniformRNG!(Mt19937, uint));
863 static assert(isSeedable!Mt19937);
864 static assert(isSeedable!(Mt19937, uint));
865 static assert(isSeedable!(Mt19937, typeof(map!((a) => unpredictableSeed)(repeat(0)))));
866 Mt19937 gen;
867 assert(gen.front == 3499211612);
868 popFrontN(gen, 9999);
869 assert(gen.front == 4123659995);
catch(Exception)870 try { gen.seed(iota(624u)); } catch (Exception) { assert(false); }
871 assert(gen.front == 3708921088u);
872 popFrontN(gen, 9999);
873 assert(gen.front == 165737292u);
874 }
875
876 /**
877 A $(D MersenneTwisterEngine) instantiated with the parameters of the
878 original engine $(HTTP en.wikipedia.org/wiki/Mersenne_Twister,
879 MT19937-64), generating uniformly-distributed 64-bit numbers with a
880 period of 2 to the power of 19937.
881 */
882 alias Mt19937_64 = MersenneTwisterEngine!(ulong, 64, 312, 156, 31,
883 0xb5026f5aa96619e9, 29, 0x5555555555555555, 17,
884 0x71d67fffeda60000, 37,
885 0xfff7eee000000000, 43, 6_364_136_223_846_793_005);
886
887 ///
888 @safe unittest
889 {
890 // Seed with a constant
891 auto gen = Mt19937_64(12345);
892 auto n = gen.front; // same for each run
893 // Seed with an unpredictable value
894 gen.seed(unpredictableSeed);
895 n = gen.front; // different across runs
896 }
897
898 @safe nothrow unittest
899 {
900 import std.algorithm;
901 import std.range;
902 static assert(isUniformRNG!Mt19937_64);
903 static assert(isUniformRNG!(Mt19937_64, ulong));
904 static assert(isSeedable!Mt19937_64);
905 static assert(isSeedable!(Mt19937_64, ulong));
906 // FIXME: this test demonstrates viably that Mt19937_64
907 // is seedable with an infinite range of `ulong` values
908 // but it's a poor example of how to actually seed the
909 // generator, since it can't cover the full range of
910 // possible seed values. Ideally we need a 64-bit
911 // unpredictable seed to complement the 32-bit one!
912 static assert(isSeedable!(Mt19937_64, typeof(map!((a) => (cast(ulong) unpredictableSeed))(repeat(0)))));
913 Mt19937_64 gen;
914 assert(gen.front == 14514284786278117030uL);
915 popFrontN(gen, 9999);
916 assert(gen.front == 9981545732273789042uL);
catch(Exception)917 try { gen.seed(iota(312uL)); } catch (Exception) { assert(false); }
918 assert(gen.front == 14660652410669508483uL);
919 popFrontN(gen, 9999);
920 assert(gen.front == 15956361063660440239uL);
921 }
922
923 @safe unittest
924 {
925 import std.algorithm;
926 import std.exception;
927 import std.range;
928
929 Mt19937 gen;
930
931 assertThrown(gen.seed(map!((a) => unpredictableSeed)(repeat(0, 623))));
932
933 gen.seed(map!((a) => unpredictableSeed)(repeat(0, 624)));
934 //infinite Range
935 gen.seed(map!((a) => unpredictableSeed)(repeat(0)));
936 }
937
938 @safe pure nothrow unittest
939 {
940 uint a, b;
941 {
942 Mt19937 gen;
943 a = gen.front;
944 }
945 {
946 Mt19937 gen;
947 gen.popFront();
948 //popFrontN(gen, 1); // skip 1 element
949 b = gen.front;
950 }
951 assert(a != b);
952 }
953
954 @safe unittest
955 {
956 import std.range;
957 // Check .save works
958 foreach (Type; std.meta.AliasSeq!(Mt19937, Mt19937_64))
959 {
960 auto gen1 = Type(unpredictableSeed);
961 auto gen2 = gen1.save;
962 assert(gen1 == gen2); // Danger, Will Robinson -- no opEquals for MT
963 // Enable next test when RNGs are reference types
version(none)964 version (none) { assert(gen1 !is gen2); }
965 assert(gen1.take(100).array() == gen2.take(100).array());
966 }
967 }
968
969 @safe pure nothrow unittest //11690
970 {
971 alias MT(UIntType, uint w) = MersenneTwisterEngine!(UIntType, w, 624, 397, 31,
972 0x9908b0df, 11, 0xffffffff, 7,
973 0x9d2c5680, 15,
974 0xefc60000, 18, 1812433253);
975
976 ulong[] expectedFirstValue = [3499211612uL, 3499211612uL,
977 171143175841277uL, 1145028863177033374uL];
978
979 ulong[] expected10kValue = [4123659995uL, 4123659995uL,
980 51991688252792uL, 3031481165133029945uL];
981
982 foreach (i, R; std.meta.AliasSeq!(MT!(uint, 32), MT!(ulong, 32), MT!(ulong, 48), MT!(ulong, 64)))
983 {
984 auto a = R();
985 a.seed(a.defaultSeed); // checks that some alternative paths in `seed` are utilized
986 assert(a.front == expectedFirstValue[i]);
987 a.popFrontN(9999);
988 assert(a.front == expected10kValue[i]);
989 }
990 }
991
992
993 /**
994 * Xorshift generator using 32bit algorithm.
995 *
996 * Implemented according to $(HTTP www.jstatsoft.org/v08/i14/paper, Xorshift RNGs).
997 * Supporting bits are below, $(D bits) means second parameter of XorshiftEngine.
998 *
999 * $(BOOKTABLE ,
1000 * $(TR $(TH bits) $(TH period))
1001 * $(TR $(TD 32) $(TD 2^32 - 1))
1002 * $(TR $(TD 64) $(TD 2^64 - 1))
1003 * $(TR $(TD 96) $(TD 2^96 - 1))
1004 * $(TR $(TD 128) $(TD 2^128 - 1))
1005 * $(TR $(TD 160) $(TD 2^160 - 1))
1006 * $(TR $(TD 192) $(TD 2^192 - 2^32))
1007 * )
1008 */
1009 struct XorshiftEngine(UIntType, UIntType bits, UIntType a, UIntType b, UIntType c)
1010 if (isUnsigned!UIntType)
1011 {
1012 static assert(bits == 32 || bits == 64 || bits == 96 || bits == 128 || bits == 160 || bits == 192,
1013 "Xorshift supports only 32, 64, 96, 128, 160 and 192 bit versions. "
1014 ~ to!string(bits) ~ " is not supported.");
1015
1016 public:
1017 ///Mark this as a Rng
1018 enum bool isUniformRandom = true;
1019 /// Always $(D false) (random generators are infinite ranges).
1020 enum empty = false;
1021 /// Smallest generated value.
1022 enum UIntType min = 0;
1023 /// Largest generated value.
1024 enum UIntType max = UIntType.max;
1025
1026
1027 private:
1028 enum size = bits / 32;
1029
1030 static if (bits == 32)
1031 UIntType[size] seeds_ = [2_463_534_242];
1032 else static if (bits == 64)
1033 UIntType[size] seeds_ = [123_456_789, 362_436_069];
1034 else static if (bits == 96)
1035 UIntType[size] seeds_ = [123_456_789, 362_436_069, 521_288_629];
1036 else static if (bits == 128)
1037 UIntType[size] seeds_ = [123_456_789, 362_436_069, 521_288_629, 88_675_123];
1038 else static if (bits == 160)
1039 UIntType[size] seeds_ = [123_456_789, 362_436_069, 521_288_629, 88_675_123, 5_783_321];
1040 else static if (bits == 192)
1041 {
1042 UIntType[size] seeds_ = [123_456_789, 362_436_069, 521_288_629, 88_675_123, 5_783_321, 6_615_241];
1043 UIntType value_;
1044 }
1045 else
1046 {
1047 static assert(false, "Phobos Error: Xorshift has no instantiation rule for "
1048 ~ to!string(bits) ~ " bits.");
1049 }
1050
1051
1052 public:
1053 /**
1054 * Constructs a $(D XorshiftEngine) generator seeded with $(D_PARAM x0).
1055 */
this(UIntType x0)1056 this(UIntType x0) @safe pure nothrow @nogc
1057 {
1058 seed(x0);
1059 }
1060
1061
1062 /**
1063 * (Re)seeds the generator.
1064 */
seed(UIntType x0)1065 void seed(UIntType x0) @safe pure nothrow @nogc
1066 {
1067 // Initialization routine from MersenneTwisterEngine.
1068 foreach (i, e; seeds_)
1069 seeds_[i] = x0 = cast(UIntType)(1_812_433_253U * (x0 ^ (x0 >> 30)) + i + 1);
1070
1071 // All seeds must not be 0.
1072 sanitizeSeeds(seeds_);
1073
1074 popFront();
1075 }
1076
1077
1078 /**
1079 * Returns the current number in the random sequence.
1080 */
1081 @property
front()1082 UIntType front() const @safe pure nothrow @nogc
1083 {
1084 static if (bits == 192)
1085 return value_;
1086 else
1087 return seeds_[size - 1];
1088 }
1089
1090
1091 /**
1092 * Advances the random sequence.
1093 */
popFront()1094 void popFront() @safe pure nothrow @nogc
1095 {
1096 UIntType temp;
1097
1098 static if (bits == 32)
1099 {
1100 temp = seeds_[0] ^ (seeds_[0] << a);
1101 temp = temp ^ (temp >> b);
1102 seeds_[0] = temp ^ (temp << c);
1103 }
1104 else static if (bits == 64)
1105 {
1106 temp = seeds_[0] ^ (seeds_[0] << a);
1107 seeds_[0] = seeds_[1];
1108 seeds_[1] = seeds_[1] ^ (seeds_[1] >> c) ^ temp ^ (temp >> b);
1109 }
1110 else static if (bits == 96)
1111 {
1112 temp = seeds_[0] ^ (seeds_[0] << a);
1113 seeds_[0] = seeds_[1];
1114 seeds_[1] = seeds_[2];
1115 seeds_[2] = seeds_[2] ^ (seeds_[2] >> c) ^ temp ^ (temp >> b);
1116 }
1117 else static if (bits == 128)
1118 {
1119 temp = seeds_[0] ^ (seeds_[0] << a);
1120 seeds_[0] = seeds_[1];
1121 seeds_[1] = seeds_[2];
1122 seeds_[2] = seeds_[3];
1123 seeds_[3] = seeds_[3] ^ (seeds_[3] >> c) ^ temp ^ (temp >> b);
1124 }
1125 else static if (bits == 160)
1126 {
1127 temp = seeds_[0] ^ (seeds_[0] << a);
1128 seeds_[0] = seeds_[1];
1129 seeds_[1] = seeds_[2];
1130 seeds_[2] = seeds_[3];
1131 seeds_[3] = seeds_[4];
1132 seeds_[4] = seeds_[4] ^ (seeds_[4] >> c) ^ temp ^ (temp >> b);
1133 }
1134 else static if (bits == 192)
1135 {
1136 temp = seeds_[0] ^ (seeds_[0] >> a);
1137 seeds_[0] = seeds_[1];
1138 seeds_[1] = seeds_[2];
1139 seeds_[2] = seeds_[3];
1140 seeds_[3] = seeds_[4];
1141 seeds_[4] = seeds_[4] ^ (seeds_[4] << c) ^ temp ^ (temp << b);
1142 value_ = seeds_[4] + (seeds_[5] += 362_437);
1143 }
1144 else
1145 {
1146 static assert(false, "Phobos Error: Xorshift has no popFront() update for "
1147 ~ to!string(bits) ~ " bits.");
1148 }
1149 }
1150
1151
1152 /**
1153 * Captures a range state.
1154 */
1155 @property
typeof(this)1156 typeof(this) save() @safe pure nothrow @nogc
1157 {
1158 return this;
1159 }
1160
1161
1162 /**
1163 * Compares against $(D_PARAM rhs) for equality.
1164 */
opEquals(ref const XorshiftEngine rhs)1165 bool opEquals(ref const XorshiftEngine rhs) const @safe pure nothrow @nogc
1166 {
1167 return seeds_ == rhs.seeds_;
1168 }
1169
1170
1171 private:
sanitizeSeeds(ref UIntType[size]seeds)1172 static void sanitizeSeeds(ref UIntType[size] seeds) @safe pure nothrow @nogc
1173 {
1174 for (uint i; i < seeds.length; i++)
1175 {
1176 if (seeds[i] == 0)
1177 seeds[i] = i + 1;
1178 }
1179 }
1180
1181
1182 @safe pure nothrow unittest
1183 {
1184 static if (size == 4) // Other bits too
1185 {
1186 UIntType[size] seeds = [1, 0, 0, 4];
1187
1188 sanitizeSeeds(seeds);
1189
1190 assert(seeds == [1, 2, 3, 4]);
1191 }
1192 }
1193 }
1194
1195
1196 /**
1197 * Define $(D XorshiftEngine) generators with well-chosen parameters. See each bits examples of "Xorshift RNGs".
1198 * $(D Xorshift) is a Xorshift128's alias because 128bits implementation is mostly used.
1199 */
1200 alias Xorshift32 = XorshiftEngine!(uint, 32, 13, 17, 15) ;
1201 alias Xorshift64 = XorshiftEngine!(uint, 64, 10, 13, 10); /// ditto
1202 alias Xorshift96 = XorshiftEngine!(uint, 96, 10, 5, 26); /// ditto
1203 alias Xorshift128 = XorshiftEngine!(uint, 128, 11, 8, 19); /// ditto
1204 alias Xorshift160 = XorshiftEngine!(uint, 160, 2, 1, 4); /// ditto
1205 alias Xorshift192 = XorshiftEngine!(uint, 192, 2, 1, 4); /// ditto
1206 alias Xorshift = Xorshift128; /// ditto
1207
1208 ///
1209 @safe unittest
1210 {
1211 // Seed with a constant
1212 auto rnd = Xorshift(1);
1213 auto num = rnd.front; // same for each run
1214
1215 // Seed with an unpredictable value
1216 rnd.seed(unpredictableSeed);
1217 num = rnd.front; // different across rnd
1218 }
1219
1220 @safe unittest
1221 {
1222 import std.range;
1223 static assert(isForwardRange!Xorshift);
1224 static assert(isUniformRNG!Xorshift);
1225 static assert(isUniformRNG!(Xorshift, uint));
1226 static assert(isSeedable!Xorshift);
1227 static assert(isSeedable!(Xorshift, uint));
1228
1229 // Result from reference implementation.
1230 auto checking = [
1231 [2463534242UL, 901999875, 3371835698, 2675058524, 1053936272, 3811264849,
1232 472493137, 3856898176, 2131710969, 2312157505],
1233 [362436069UL, 2113136921, 19051112, 3010520417, 951284840, 1213972223,
1234 3173832558, 2611145638, 2515869689, 2245824891],
1235 [521288629UL, 1950277231, 185954712, 1582725458, 3580567609, 2303633688,
1236 2394948066, 4108622809, 1116800180, 3357585673],
1237 [88675123UL, 3701687786, 458299110, 2500872618, 3633119408, 516391518,
1238 2377269574, 2599949379, 717229868, 137866584],
1239 [5783321UL, 393427209, 1947109840, 565829276, 1006220149, 971147905,
1240 1436324242, 2800460115, 1484058076, 3823330032],
1241 [0UL, 246875399, 3690007200, 1264581005, 3906711041, 1866187943, 2481925219,
1242 2464530826, 1604040631, 3653403911]
1243 ];
1244
1245 alias XorshiftTypes = std.meta.AliasSeq!(Xorshift32, Xorshift64, Xorshift96, Xorshift128, Xorshift160, Xorshift192);
1246
foreach(I,Type;XorshiftTypes)1247 foreach (I, Type; XorshiftTypes)
1248 {
1249 Type rnd;
1250
1251 foreach (e; checking[I])
1252 {
1253 assert(rnd.front == e);
1254 rnd.popFront();
1255 }
1256 }
1257
1258 // Check .save works
foreach(Type;XorshiftTypes)1259 foreach (Type; XorshiftTypes)
1260 {
1261 auto rnd1 = Type(unpredictableSeed);
1262 auto rnd2 = rnd1.save;
1263 assert(rnd1 == rnd2);
1264 // Enable next test when RNGs are reference types
1265 version (none) { assert(rnd1 !is rnd2); }
1266 assert(rnd1.take(100).array() == rnd2.take(100).array());
1267 }
1268 }
1269
1270
1271 /* A complete list of all pseudo-random number generators implemented in
1272 * std.random. This can be used to confirm that a given function or
1273 * object is compatible with all the pseudo-random number generators
1274 * available. It is enabled only in unittest mode.
1275 */
1276 @safe unittest
1277 {
foreach(Rng;PseudoRngTypes)1278 foreach (Rng; PseudoRngTypes)
1279 {
1280 static assert(isUniformRNG!Rng);
1281 auto rng = Rng(unpredictableSeed);
1282 }
1283 }
1284
1285
1286 /**
1287 A "good" seed for initializing random number engines. Initializing
1288 with $(D_PARAM unpredictableSeed) makes engines generate different
1289 random number sequences every run.
1290
1291 Returns:
1292 A single unsigned integer seed value, different on each successive call
1293 */
unpredictableSeed()1294 @property uint unpredictableSeed() @trusted
1295 {
1296 import core.thread : Thread, getpid, MonoTime;
1297 static bool seeded;
1298 static MinstdRand0 rand;
1299 if (!seeded)
1300 {
1301 uint threadID = cast(uint) cast(void*) Thread.getThis();
1302 rand.seed((getpid() + threadID) ^ cast(uint) MonoTime.currTime.ticks);
1303 seeded = true;
1304 }
1305 rand.popFront();
1306 return cast(uint) (MonoTime.currTime.ticks ^ rand.front);
1307 }
1308
1309 ///
1310 @safe unittest
1311 {
1312 auto rnd = Random(unpredictableSeed);
1313 auto n = rnd.front;
1314 static assert(is(typeof(n) == uint));
1315 }
1316
1317 /**
1318 The "default", "favorite", "suggested" random number generator type on
1319 the current platform. It is an alias for one of the previously-defined
1320 generators. You may want to use it if (1) you need to generate some
1321 nice random numbers, and (2) you don't care for the minutiae of the
1322 method being used.
1323 */
1324
1325 alias Random = Mt19937;
1326
1327 @safe unittest
1328 {
1329 static assert(isUniformRNG!Random);
1330 static assert(isUniformRNG!(Random, uint));
1331 static assert(isSeedable!Random);
1332 static assert(isSeedable!(Random, uint));
1333 }
1334
1335 /**
1336 Global random number generator used by various functions in this
1337 module whenever no generator is specified. It is allocated per-thread
1338 and initialized to an unpredictable value for each thread.
1339
1340 Returns:
1341 A singleton instance of the default random number generator
1342 */
rndGen()1343 @property ref Random rndGen() @safe
1344 {
1345 import std.algorithm.iteration : map;
1346 import std.range : repeat;
1347
1348 static Random result;
1349 static bool initialized;
1350 if (!initialized)
1351 {
1352 static if (isSeedable!(Random, typeof(map!((a) => unpredictableSeed)(repeat(0)))))
1353 result.seed(map!((a) => unpredictableSeed)(repeat(0)));
1354 else
1355 result = Random(unpredictableSeed);
1356 initialized = true;
1357 }
1358 return result;
1359 }
1360
1361 /**
1362 Generates a number between $(D a) and $(D b). The $(D boundaries)
1363 parameter controls the shape of the interval (open vs. closed on
1364 either side). Valid values for $(D boundaries) are $(D "[]"), $(D
1365 "$(LPAREN)]"), $(D "[$(RPAREN)"), and $(D "()"). The default interval
1366 is closed to the left and open to the right. The version that does not
1367 take $(D urng) uses the default generator $(D rndGen).
1368
1369 Params:
1370 a = lower bound of the _uniform distribution
1371 b = upper bound of the _uniform distribution
1372 urng = (optional) random number generator to use;
1373 if not specified, defaults to $(D rndGen)
1374
1375 Returns:
1376 A single random variate drawn from the _uniform distribution
1377 between $(D a) and $(D b), whose type is the common type of
1378 these parameters
1379 */
1380 auto uniform(string boundaries = "[)", T1, T2)
1381 (T1 a, T2 b)
1382 if (!is(CommonType!(T1, T2) == void))
1383 {
1384 return uniform!(boundaries, T1, T2, Random)(a, b, rndGen);
1385 }
1386
1387 ///
1388 @safe unittest
1389 {
1390 auto gen = Random(unpredictableSeed);
1391 // Generate an integer in [0, 1023]
1392 auto a = uniform(0, 1024, gen);
1393 // Generate a float in [0, 1)
1394 auto b = uniform(0.0f, 1.0f, gen);
1395 }
1396
1397 @safe unittest
1398 {
1399 MinstdRand0 gen;
1400 foreach (i; 0 .. 20)
1401 {
1402 auto x = uniform(0.0, 15.0, gen);
1403 assert(0 <= x && x < 15);
1404 }
1405 foreach (i; 0 .. 20)
1406 {
1407 auto x = uniform!"[]"('a', 'z', gen);
1408 assert('a' <= x && x <= 'z');
1409 }
1410
1411 foreach (i; 0 .. 20)
1412 {
1413 auto x = uniform('a', 'z', gen);
1414 assert('a' <= x && x < 'z');
1415 }
1416
1417 foreach (i; 0 .. 20)
1418 {
1419 immutable ubyte a = 0;
1420 immutable ubyte b = 15;
1421 auto x = uniform(a, b, gen);
1422 assert(a <= x && x < b);
1423 }
1424 }
1425
1426 // Implementation of uniform for floating-point types
1427 /// ditto
1428 auto uniform(string boundaries = "[)",
1429 T1, T2, UniformRandomNumberGenerator)
1430 (T1 a, T2 b, ref UniformRandomNumberGenerator urng)
1431 if (isFloatingPoint!(CommonType!(T1, T2)) && isUniformRNG!UniformRandomNumberGenerator)
1432 {
1433 import std.conv : text;
1434 import std.exception : enforce;
1435 alias NumberType = Unqual!(CommonType!(T1, T2));
1436 static if (boundaries[0] == '(')
1437 {
1438 import std.math : nextafter;
1439 NumberType _a = nextafter(cast(NumberType) a, NumberType.infinity);
1440 }
1441 else
1442 {
1443 NumberType _a = a;
1444 }
1445 static if (boundaries[1] == ')')
1446 {
1447 import std.math : nextafter;
1448 NumberType _b = nextafter(cast(NumberType) b, -NumberType.infinity);
1449 }
1450 else
1451 {
1452 NumberType _b = b;
1453 }
1454 enforce(_a <= _b,
1455 text("std.random.uniform(): invalid bounding interval ",
1456 boundaries[0], a, ", ", b, boundaries[1]));
1457 NumberType result =
1458 _a + (_b - _a) * cast(NumberType) (urng.front - urng.min)
1459 / (urng.max - urng.min);
1460 urng.popFront();
1461 return result;
1462 }
1463
1464 // Implementation of uniform for integral types
1465 /+ Description of algorithm and suggestion of correctness:
1466
1467 The modulus operator maps an integer to a small, finite space. For instance, `x
1468 % 3` will map whatever x is into the range [0 .. 3). 0 maps to 0, 1 maps to 1, 2
1469 maps to 2, 3 maps to 0, and so on infinitely. As long as the integer is
1470 uniformly chosen from the infinite space of all non-negative integers then `x %
1471 3` will uniformly fall into that range.
1472
1473 (Non-negative is important in this case because some definitions of modulus,
1474 namely the one used in computers generally, map negative numbers differently to
1475 (-3 .. 0]. `uniform` does not use negative number modulus, thus we can safely
1476 ignore that fact.)
1477
1478 The issue with computers is that integers have a finite space they must fit in,
1479 and our uniformly chosen random number is picked in that finite space. So, that
1480 method is not sufficient. You can look at it as the integer space being divided
1481 into "buckets" and every bucket after the first bucket maps directly into that
1482 first bucket. `[0, 1, 2]`, `[3, 4, 5]`, ... When integers are finite, then the
1483 last bucket has the chance to be "incomplete": `[uint.max - 3, uint.max - 2,
1484 uint.max - 1]`, `[uint.max]` ... (the last bucket only has 1!). The issue here
1485 is that _every_ bucket maps _completely_ to the first bucket except for that
1486 last one. The last one doesn't have corresponding mappings to 1 or 2, in this
1487 case, which makes it unfair.
1488
1489 So, the answer is to simply "reroll" if you're in that last bucket, since it's
1490 the only unfair one. Eventually you'll roll into a fair bucket. Simply, instead
1491 of the meaning of the last bucket being "maps to `[0]`", it changes to "maps to
1492 `[0, 1, 2]`", which is precisely what we want.
1493
1494 To generalize, `upperDist` represents the size of our buckets (and, thus, the
1495 exclusive upper bound for our desired uniform number). `rnum` is a uniformly
1496 random number picked from the space of integers that a computer can hold (we'll
1497 say `UpperType` represents that type).
1498
1499 We'll first try to do the mapping into the first bucket by doing `offset = rnum
1500 % upperDist`. We can figure out the position of the front of the bucket we're in
1501 by `bucketFront = rnum - offset`.
1502
1503 If we start at `UpperType.max` and walk backwards `upperDist - 1` spaces, then
1504 the space we land on is the last acceptable position where a full bucket can
1505 fit:
1506
1507 ```
1508 bucketFront UpperType.max
1509 v v
1510 [..., 0, 1, 2, ..., upperDist - 1]
1511 ^~~ upperDist - 1 ~~^
1512 ```
1513
1514 If the bucket starts any later, then it must have lost at least one number and
1515 at least that number won't be represented fairly.
1516
1517 ```
1518 bucketFront UpperType.max
1519 v v
1520 [..., upperDist - 1, 0, 1, 2, ..., upperDist - 2]
1521 ^~~~~~~~ upperDist - 1 ~~~~~~~^
1522 ```
1523
1524 Hence, our condition to reroll is
1525 `bucketFront > (UpperType.max - (upperDist - 1))`
1526 +/
1527 auto uniform(string boundaries = "[)", T1, T2, RandomGen)
1528 (T1 a, T2 b, ref RandomGen rng)
1529 if ((isIntegral!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2))) &&
1530 isUniformRNG!RandomGen)
1531 {
1532 import std.conv : text, unsigned;
1533 import std.exception : enforce;
1534 alias ResultType = Unqual!(CommonType!(T1, T2));
1535 static if (boundaries[0] == '(')
1536 {
1537 enforce(a < ResultType.max,
1538 text("std.random.uniform(): invalid left bound ", a));
1539 ResultType lower = cast(ResultType) (a + 1);
1540 }
1541 else
1542 {
1543 ResultType lower = a;
1544 }
1545
1546 static if (boundaries[1] == ']')
1547 {
1548 enforce(lower <= b,
1549 text("std.random.uniform(): invalid bounding interval ",
1550 boundaries[0], a, ", ", b, boundaries[1]));
1551 /* Cannot use this next optimization with dchar, as dchar
1552 * only partially uses its full bit range
1553 */
1554 static if (!is(ResultType == dchar))
1555 {
1556 if (b == ResultType.max && lower == ResultType.min)
1557 {
1558 // Special case - all bits are occupied
1559 return std.random.uniform!ResultType(rng);
1560 }
1561 }
1562 auto upperDist = unsigned(b - lower) + 1u;
1563 }
1564 else
1565 {
1566 enforce(lower < b,
1567 text("std.random.uniform(): invalid bounding interval ",
1568 boundaries[0], a, ", ", b, boundaries[1]));
1569 auto upperDist = unsigned(b - lower);
1570 }
1571
1572 assert(upperDist != 0);
1573
1574 alias UpperType = typeof(upperDist);
1575 static assert(UpperType.min == 0);
1576
1577 UpperType offset, rnum, bucketFront;
1578 do
1579 {
1580 rnum = uniform!UpperType(rng);
1581 offset = rnum % upperDist;
1582 bucketFront = rnum - offset;
1583 } // while we're in an unfair bucket...
1584 while (bucketFront > (UpperType.max - (upperDist - 1)));
1585
1586 return cast(ResultType)(lower + offset);
1587 }
1588
1589 @safe unittest
1590 {
1591 import std.conv : to;
1592 auto gen = Mt19937(unpredictableSeed);
1593 static assert(isForwardRange!(typeof(gen)));
1594
1595 auto a = uniform(0, 1024, gen);
1596 assert(0 <= a && a <= 1024);
1597 auto b = uniform(0.0f, 1.0f, gen);
1598 assert(0 <= b && b < 1, to!string(b));
1599 auto c = uniform(0.0, 1.0);
1600 assert(0 <= c && c < 1);
1601
1602 foreach (T; std.meta.AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort,
1603 int, uint, long, ulong, float, double, real))
1604 {
1605 T lo = 0, hi = 100;
1606
1607 // Try tests with each of the possible bounds
1608 {
1609 T init = uniform(lo, hi);
1610 size_t i = 50;
1611 while (--i && uniform(lo, hi) == init) {}
1612 assert(i > 0);
1613 }
1614 {
1615 T init = uniform!"[)"(lo, hi);
1616 size_t i = 50;
1617 while (--i && uniform(lo, hi) == init) {}
1618 assert(i > 0);
1619 }
1620 {
1621 T init = uniform!"(]"(lo, hi);
1622 size_t i = 50;
1623 while (--i && uniform(lo, hi) == init) {}
1624 assert(i > 0);
1625 }
1626 {
1627 T init = uniform!"()"(lo, hi);
1628 size_t i = 50;
1629 while (--i && uniform(lo, hi) == init) {}
1630 assert(i > 0);
1631 }
1632 {
1633 T init = uniform!"[]"(lo, hi);
1634 size_t i = 50;
1635 while (--i && uniform(lo, hi) == init) {}
1636 assert(i > 0);
1637 }
1638
1639 /* Test case with closed boundaries covering whole range
1640 * of integral type
1641 */
1642 static if (isIntegral!T || isSomeChar!T)
1643 {
1644 foreach (immutable _; 0 .. 100)
1645 {
1646 auto u = uniform!"[]"(T.min, T.max);
1647 static assert(is(typeof(u) == T));
1648 assert(T.min <= u, "Lower bound violation for uniform!\"[]\" with " ~ T.stringof);
1649 assert(u <= T.max, "Upper bound violation for uniform!\"[]\" with " ~ T.stringof);
1650 }
1651 }
1652 }
1653
1654 auto reproRng = Xorshift(239842);
1655
1656 foreach (T; std.meta.AliasSeq!(char, wchar, dchar, byte, ubyte, short,
1657 ushort, int, uint, long, ulong))
1658 {
1659 T lo = T.min + 10, hi = T.max - 10;
1660 T init = uniform(lo, hi, reproRng);
1661 size_t i = 50;
1662 while (--i && uniform(lo, hi, reproRng) == init) {}
1663 assert(i > 0);
1664 }
1665
1666 {
1667 bool sawLB = false, sawUB = false;
1668 foreach (i; 0 .. 50)
1669 {
1670 auto x = uniform!"[]"('a', 'd', reproRng);
1671 if (x == 'a') sawLB = true;
1672 if (x == 'd') sawUB = true;
1673 assert('a' <= x && x <= 'd');
1674 }
1675 assert(sawLB && sawUB);
1676 }
1677
1678 {
1679 bool sawLB = false, sawUB = false;
1680 foreach (i; 0 .. 50)
1681 {
1682 auto x = uniform('a', 'd', reproRng);
1683 if (x == 'a') sawLB = true;
1684 if (x == 'c') sawUB = true;
1685 assert('a' <= x && x < 'd');
1686 }
1687 assert(sawLB && sawUB);
1688 }
1689
1690 {
1691 bool sawLB = false, sawUB = false;
1692 foreach (i; 0 .. 50)
1693 {
1694 immutable int lo = -2, hi = 2;
1695 auto x = uniform!"()"(lo, hi, reproRng);
1696 if (x == (lo+1)) sawLB = true;
1697 if (x == (hi-1)) sawUB = true;
1698 assert(lo < x && x < hi);
1699 }
1700 assert(sawLB && sawUB);
1701 }
1702
1703 {
1704 bool sawLB = false, sawUB = false;
1705 foreach (i; 0 .. 50)
1706 {
1707 immutable ubyte lo = 0, hi = 5;
1708 auto x = uniform(lo, hi, reproRng);
1709 if (x == lo) sawLB = true;
1710 if (x == (hi-1)) sawUB = true;
1711 assert(lo <= x && x < hi);
1712 }
1713 assert(sawLB && sawUB);
1714 }
1715
1716 {
1717 foreach (i; 0 .. 30)
1718 {
1719 assert(i == uniform(i, i+1, reproRng));
1720 }
1721 }
1722 }
1723
1724 /**
1725 Generates a uniformly-distributed number in the range $(D [T.min,
1726 T.max]) for any integral or character type $(D T). If no random
1727 number generator is passed, uses the default $(D rndGen).
1728
1729 Params:
1730 urng = (optional) random number generator to use;
1731 if not specified, defaults to $(D rndGen)
1732
1733 Returns:
1734 Random variate drawn from the _uniform distribution across all
1735 possible values of the integral or character type $(D T).
1736 */
1737 auto uniform(T, UniformRandomNumberGenerator)
1738 (ref UniformRandomNumberGenerator urng)
1739 if (!is(T == enum) && (isIntegral!T || isSomeChar!T) && isUniformRNG!UniformRandomNumberGenerator)
1740 {
1741 /* dchar does not use its full bit range, so we must
1742 * revert to the uniform with specified bounds
1743 */
1744 static if (is(T == dchar))
1745 {
1746 return uniform!"[]"(T.min, T.max);
1747 }
1748 else
1749 {
1750 auto r = urng.front;
1751 urng.popFront();
1752 static if (T.sizeof <= r.sizeof)
1753 {
1754 return cast(T) r;
1755 }
1756 else
1757 {
1758 static assert(T.sizeof == 8 && r.sizeof == 4);
1759 T r1 = urng.front | (cast(T) r << 32);
1760 urng.popFront();
1761 return r1;
1762 }
1763 }
1764 }
1765
1766 /// Ditto
1767 auto uniform(T)()
1768 if (!is(T == enum) && (isIntegral!T || isSomeChar!T))
1769 {
1770 return uniform!T(rndGen);
1771 }
1772
1773 @safe unittest
1774 {
1775 foreach (T; std.meta.AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort,
1776 int, uint, long, ulong))
1777 {
1778 T init = uniform!T();
1779 size_t i = 50;
1780 while (--i && uniform!T() == init) {}
1781 assert(i > 0);
1782
1783 foreach (immutable _; 0 .. 100)
1784 {
1785 auto u = uniform!T();
1786 static assert(is(typeof(u) == T));
1787 assert(T.min <= u, "Lower bound violation for uniform!" ~ T.stringof);
1788 assert(u <= T.max, "Upper bound violation for uniform!" ~ T.stringof);
1789 }
1790 }
1791 }
1792
1793 /**
1794 Returns a uniformly selected member of enum $(D E). If no random number
1795 generator is passed, uses the default $(D rndGen).
1796
1797 Params:
1798 urng = (optional) random number generator to use;
1799 if not specified, defaults to $(D rndGen)
1800
1801 Returns:
1802 Random variate drawn with equal probability from any
1803 of the possible values of the enum $(D E).
1804 */
1805 auto uniform(E, UniformRandomNumberGenerator)
1806 (ref UniformRandomNumberGenerator urng)
1807 if (is(E == enum) && isUniformRNG!UniformRandomNumberGenerator)
1808 {
1809 static immutable E[EnumMembers!E.length] members = [EnumMembers!E];
1810 return members[std.random.uniform(0, members.length, urng)];
1811 }
1812
1813 /// Ditto
1814 auto uniform(E)()
1815 if (is(E == enum))
1816 {
1817 return uniform!E(rndGen);
1818 }
1819
1820 ///
1821 @safe unittest
1822 {
1823 enum Fruit { apple, mango, pear }
1824 auto randFruit = uniform!Fruit();
1825 }
1826
1827 @safe unittest
1828 {
1829 enum Fruit { Apple = 12, Mango = 29, Pear = 72 }
1830 foreach (_; 0 .. 100)
1831 {
foreach(f;[uniform!Fruit (),rndGen.uniform!Fruit ()])1832 foreach (f; [uniform!Fruit(), rndGen.uniform!Fruit()])
1833 {
1834 assert(f == Fruit.Apple || f == Fruit.Mango || f == Fruit.Pear);
1835 }
1836 }
1837 }
1838
1839 /**
1840 * Generates a uniformly-distributed floating point number of type
1841 * $(D T) in the range [0, 1$(RPAREN). If no random number generator is
1842 * specified, the default RNG $(D rndGen) will be used as the source
1843 * of randomness.
1844 *
1845 * $(D uniform01) offers a faster generation of random variates than
1846 * the equivalent $(D uniform!"[$(RPAREN)"(0.0, 1.0)) and so may be preferred
1847 * for some applications.
1848 *
1849 * Params:
1850 * rng = (optional) random number generator to use;
1851 * if not specified, defaults to $(D rndGen)
1852 *
1853 * Returns:
1854 * Floating-point random variate of type $(D T) drawn from the _uniform
1855 * distribution across the half-open interval [0, 1$(RPAREN).
1856 *
1857 */
1858 T uniform01(T = double)()
1859 if (isFloatingPoint!T)
1860 {
1861 return uniform01!T(rndGen);
1862 }
1863
1864 /// ditto
1865 T uniform01(T = double, UniformRNG)(ref UniformRNG rng)
1866 if (isFloatingPoint!T && isUniformRNG!UniformRNG)
out(result)1867 out (result)
1868 {
1869 assert(0 <= result);
1870 assert(result < 1);
1871 }
1872 body
1873 {
1874 alias R = typeof(rng.front);
1875 static if (isIntegral!R)
1876 {
1877 enum T factor = 1 / (T(1) + rng.max - rng.min);
1878 }
1879 else static if (isFloatingPoint!R)
1880 {
1881 enum T factor = 1 / (rng.max - rng.min);
1882 }
1883 else
1884 {
1885 static assert(false);
1886 }
1887
1888 while (true)
1889 {
1890 immutable T u = (rng.front - rng.min) * factor;
1891 rng.popFront();
1892
1893 import core.stdc.limits : CHAR_BIT; // CHAR_BIT is always 8
1894 static if (isIntegral!R && T.mant_dig >= (CHAR_BIT * R.sizeof))
1895 {
1896 /* If RNG variates are integral and T has enough precision to hold
1897 * R without loss, we're guaranteed by the definition of factor
1898 * that precisely u < 1.
1899 */
1900 return u;
1901 }
1902 else
1903 {
1904 /* Otherwise we have to check whether u is beyond the assumed range
1905 * because of the loss of precision, or for another reason, a
1906 * floating-point RNG can return a variate that is exactly equal to
1907 * its maximum.
1908 */
1909 if (u < 1)
1910 {
1911 return u;
1912 }
1913 }
1914 }
1915
1916 // Shouldn't ever get here.
1917 assert(false);
1918 }
1919
1920 @safe unittest
1921 {
1922 import std.meta;
foreach(UniformRNG;PseudoRngTypes)1923 foreach (UniformRNG; PseudoRngTypes)
1924 {
1925
1926 foreach (T; std.meta.AliasSeq!(float, double, real))
1927 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
1928 UniformRNG rng = UniformRNG(unpredictableSeed);
1929
1930 auto a = uniform01();
1931 assert(is(typeof(a) == double));
1932 assert(0 <= a && a < 1);
1933
1934 auto b = uniform01(rng);
1935 assert(is(typeof(a) == double));
1936 assert(0 <= b && b < 1);
1937
1938 auto c = uniform01!T();
1939 assert(is(typeof(c) == T));
1940 assert(0 <= c && c < 1);
1941
1942 auto d = uniform01!T(rng);
1943 assert(is(typeof(d) == T));
1944 assert(0 <= d && d < 1);
1945
1946 T init = uniform01!T(rng);
1947 size_t i = 50;
1948 while (--i && uniform01!T(rng) == init) {}
1949 assert(i > 0);
1950 assert(i < 50);
1951 }();
1952 }
1953 }
1954
1955 /**
1956 Generates a uniform probability distribution of size $(D n), i.e., an
1957 array of size $(D n) of positive numbers of type $(D F) that sum to
1958 $(D 1). If $(D useThis) is provided, it is used as storage.
1959 */
1960 F[] uniformDistribution(F = double)(size_t n, F[] useThis = null)
1961 if (isFloatingPoint!F)
1962 {
1963 import std.numeric : normalize;
1964 useThis.length = n;
foreach(ref e;useThis)1965 foreach (ref e; useThis)
1966 {
1967 e = uniform(0.0, 1);
1968 }
1969 normalize(useThis);
1970 return useThis;
1971 }
1972
1973 @safe unittest
1974 {
1975 import std.algorithm;
1976 import std.math;
1977 static assert(is(CommonType!(double, int) == double));
1978 auto a = uniformDistribution(5);
1979 assert(a.length == 5);
1980 assert(approxEqual(reduce!"a + b"(a), 1));
1981 a = uniformDistribution(10, a);
1982 assert(a.length == 10);
1983 assert(approxEqual(reduce!"a + b"(a), 1));
1984 }
1985
1986 /**
1987 Returns a random, uniformly chosen, element `e` from the supplied
1988 $(D Range range). If no random number generator is passed, the default
1989 `rndGen` is used.
1990
1991 Params:
1992 range = a random access range that has the `length` property defined
1993 urng = (optional) random number generator to use;
1994 if not specified, defaults to `rndGen`
1995
1996 Returns:
1997 A single random element drawn from the `range`. If it can, it will
1998 return a `ref` to the $(D range element), otherwise it will return
1999 a copy.
2000 */
2001 auto ref choice(Range, RandomGen = Random)(auto ref Range range,
2002 ref RandomGen urng = rndGen)
2003 if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen)
2004 {
2005 assert(range.length > 0,
2006 __PRETTY_FUNCTION__ ~ ": invalid Range supplied. Range cannot be empty");
2007
2008 return range[uniform(size_t(0), $, urng)];
2009 }
2010
2011 ///
2012 @safe unittest
2013 {
2014 import std.algorithm.searching : canFind;
2015
2016 auto array = [1, 2, 3, 4, 5];
2017 auto elem = choice(array);
2018
2019 assert(canFind(array, elem),
2020 "Choice did not return a valid element from the given Range");
2021
2022 auto urng = Random(unpredictableSeed);
2023 elem = choice(array, urng);
2024
2025 assert(canFind(array, elem),
2026 "Choice did not return a valid element from the given Range");
2027 }
2028
2029 @safe unittest
2030 {
2031 import std.algorithm.searching : canFind;
2032
2033 class MyTestClass
2034 {
2035 int x;
2036
this(int x)2037 this(int x)
2038 {
2039 this.x = x;
2040 }
2041 }
2042
2043 MyTestClass[] testClass;
2044 foreach (i; 0 .. 5)
2045 {
2046 testClass ~= new MyTestClass(i);
2047 }
2048
2049 auto elem = choice(testClass);
2050
2051 assert(canFind!((ref MyTestClass a, ref MyTestClass b) => a.x == b.x)(testClass, elem),
2052 "Choice did not return a valid element from the given Range");
2053 }
2054
2055 @system unittest
2056 {
2057 import std.algorithm.iteration : map;
2058 import std.algorithm.searching : canFind;
2059
2060 auto array = [1, 2, 3, 4, 5];
2061 auto elemAddr = &choice(array);
2062
2063 assert(array.map!((ref e) => &e).canFind(elemAddr),
2064 "Choice did not return a ref to an element from the given Range");
2065 assert(array.canFind(*(cast(int *)(elemAddr))),
2066 "Choice did not return a valid element from the given Range");
2067 }
2068
2069 /**
2070 Shuffles elements of $(D r) using $(D gen) as a shuffler. $(D r) must be
2071 a random-access range with length. If no RNG is specified, $(D rndGen)
2072 will be used.
2073
2074 Params:
2075 r = random-access range whose elements are to be shuffled
2076 gen = (optional) random number generator to use; if not
2077 specified, defaults to $(D rndGen)
2078 */
2079
2080 void randomShuffle(Range, RandomGen)(Range r, ref RandomGen gen)
2081 if (isRandomAccessRange!Range && isUniformRNG!RandomGen)
2082 {
2083 return partialShuffle!(Range, RandomGen)(r, r.length, gen);
2084 }
2085
2086 /// ditto
2087 void randomShuffle(Range)(Range r)
2088 if (isRandomAccessRange!Range)
2089 {
2090 return randomShuffle(r, rndGen);
2091 }
2092
2093 @safe unittest
2094 {
2095 import std.algorithm.sorting : sort;
foreach(RandomGen;PseudoRngTypes)2096 foreach (RandomGen; PseudoRngTypes)
2097 {
2098 // Also tests partialShuffle indirectly.
2099 auto a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
2100 auto b = a.dup;
2101 auto gen = RandomGen(unpredictableSeed);
2102 randomShuffle(a, gen);
2103 sort(a);
2104 assert(a == b);
2105 randomShuffle(a);
2106 sort(a);
2107 assert(a == b);
2108 }
2109 }
2110
2111 /**
2112 Partially shuffles the elements of $(D r) such that upon returning $(D r[0 .. n])
2113 is a random subset of $(D r) and is randomly ordered. $(D r[n .. r.length])
2114 will contain the elements not in $(D r[0 .. n]). These will be in an undefined
2115 order, but will not be random in the sense that their order after
2116 $(D partialShuffle) returns will not be independent of their order before
2117 $(D partialShuffle) was called.
2118
2119 $(D r) must be a random-access range with length. $(D n) must be less than
2120 or equal to $(D r.length). If no RNG is specified, $(D rndGen) will be used.
2121
2122 Params:
2123 r = random-access range whose elements are to be shuffled
2124 n = number of elements of $(D r) to shuffle (counting from the beginning);
2125 must be less than $(D r.length)
2126 gen = (optional) random number generator to use; if not
2127 specified, defaults to $(D rndGen)
2128 */
2129 void partialShuffle(Range, RandomGen)(Range r, in size_t n, ref RandomGen gen)
2130 if (isRandomAccessRange!Range && isUniformRNG!RandomGen)
2131 {
2132 import std.algorithm.mutation : swapAt;
2133 import std.exception : enforce;
2134 enforce(n <= r.length, "n must be <= r.length for partialShuffle.");
2135 foreach (i; 0 .. n)
2136 {
2137 r.swapAt(i, uniform(i, r.length, gen));
2138 }
2139 }
2140
2141 /// ditto
2142 void partialShuffle(Range)(Range r, in size_t n)
2143 if (isRandomAccessRange!Range)
2144 {
2145 return partialShuffle(r, n, rndGen);
2146 }
2147
2148 @safe unittest
2149 {
2150 import std.algorithm;
foreach(RandomGen;PseudoRngTypes)2151 foreach (RandomGen; PseudoRngTypes)
2152 {
2153 auto a = [0, 1, 1, 2, 3];
2154 auto b = a.dup;
2155
2156 // Pick a fixed seed so that the outcome of the statistical
2157 // test below is deterministic.
2158 auto gen = RandomGen(12345);
2159
2160 // NUM times, pick LEN elements from the array at random.
2161 immutable int LEN = 2;
2162 immutable int NUM = 750;
2163 int[][] chk;
2164 foreach (step; 0 .. NUM)
2165 {
2166 partialShuffle(a, LEN, gen);
2167 chk ~= a[0 .. LEN].dup;
2168 }
2169
2170 // Check that each possible a[0 .. LEN] was produced at least once.
2171 // For a perfectly random RandomGen, the probability that each
2172 // particular combination failed to appear would be at most
2173 // 0.95 ^^ NUM which is approximately 1,962e-17.
2174 // As long as hardware failure (e.g. bit flip) probability
2175 // is higher, we are fine with this unittest.
2176 sort(chk);
2177 assert(equal(uniq(chk), [ [0,1], [0,2], [0,3],
2178 [1,0], [1,1], [1,2], [1,3],
2179 [2,0], [2,1], [2,3],
2180 [3,0], [3,1], [3,2], ]));
2181
2182 // Check that all the elements are still there.
2183 sort(a);
2184 assert(equal(a, b));
2185 }
2186 }
2187
2188 /**
2189 Rolls a dice with relative probabilities stored in $(D
2190 proportions). Returns the index in $(D proportions) that was chosen.
2191
2192 Params:
2193 rnd = (optional) random number generator to use; if not
2194 specified, defaults to $(D rndGen)
2195 proportions = forward range or list of individual values
2196 whose elements correspond to the probabilities
2197 with which to choose the corresponding index
2198 value
2199
2200 Returns:
2201 Random variate drawn from the index values
2202 [0, ... $(D proportions.length) - 1], with the probability
2203 of getting an individual index value $(D i) being proportional to
2204 $(D proportions[i]).
2205 */
2206 size_t dice(Rng, Num)(ref Rng rnd, Num[] proportions...)
2207 if (isNumeric!Num && isForwardRange!Rng)
2208 {
2209 return diceImpl(rnd, proportions);
2210 }
2211
2212 /// Ditto
2213 size_t dice(R, Range)(ref R rnd, Range proportions)
2214 if (isForwardRange!Range && isNumeric!(ElementType!Range) && !isArray!Range)
2215 {
2216 return diceImpl(rnd, proportions);
2217 }
2218
2219 /// Ditto
2220 size_t dice(Range)(Range proportions)
2221 if (isForwardRange!Range && isNumeric!(ElementType!Range) && !isArray!Range)
2222 {
2223 return diceImpl(rndGen, proportions);
2224 }
2225
2226 /// Ditto
2227 size_t dice(Num)(Num[] proportions...)
2228 if (isNumeric!Num)
2229 {
2230 return diceImpl(rndGen, proportions);
2231 }
2232
2233 ///
2234 @safe unittest
2235 {
2236 auto x = dice(0.5, 0.5); // x is 0 or 1 in equal proportions
2237 auto y = dice(50, 50); // y is 0 or 1 in equal proportions
2238 auto z = dice(70, 20, 10); // z is 0 70% of the time, 1 20% of the time,
2239 // and 2 10% of the time
2240 }
2241
2242 private size_t diceImpl(Rng, Range)(ref Rng rng, scope Range proportions)
2243 if (isForwardRange!Range && isNumeric!(ElementType!Range) && isForwardRange!Rng)
2244 in
2245 {
2246 import std.algorithm.searching : all;
2247 assert(proportions.save.all!"a >= 0");
2248 }
2249 body
2250 {
2251 import std.algorithm.iteration : reduce;
2252 import std.exception : enforce;
2253 double sum = reduce!"a + b"(0.0, proportions.save);
2254 enforce(sum > 0, "Proportions in a dice cannot sum to zero");
2255 immutable point = uniform(0.0, sum, rng);
2256 assert(point < sum);
2257 auto mass = 0.0;
2258
2259 size_t i = 0;
foreach(e;proportions)2260 foreach (e; proportions)
2261 {
2262 mass += e;
2263 if (point < mass) return i;
2264 i++;
2265 }
2266 // this point should not be reached
2267 assert(false);
2268 }
2269
2270 @safe unittest
2271 {
2272 auto rnd = Random(unpredictableSeed);
2273 auto i = dice(rnd, 0.0, 100.0);
2274 assert(i == 1);
2275 i = dice(rnd, 100.0, 0.0);
2276 assert(i == 0);
2277
2278 i = dice(100U, 0U);
2279 assert(i == 0);
2280 }
2281
2282 /**
2283 Covers a given range $(D r) in a random manner, i.e. goes through each
2284 element of $(D r) once and only once, just in a random order. $(D r)
2285 must be a random-access range with length.
2286
2287 If no random number generator is passed to $(D randomCover), the
2288 thread-global RNG rndGen will be used internally.
2289
2290 Params:
2291 r = random-access range to cover
2292 rng = (optional) random number generator to use;
2293 if not specified, defaults to $(D rndGen)
2294
2295 Returns:
2296 Range whose elements consist of the elements of $(D r),
2297 in random order. Will be a forward range if both $(D r) and
2298 $(D rng) are forward ranges, an input range otherwise.
2299
2300 Example:
2301 ----
2302 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ];
2303 foreach (e; randomCover(a))
2304 {
2305 writeln(e);
2306 }
2307 ----
2308
2309 $(B WARNING:) If an alternative RNG is desired, it is essential for this
2310 to be a $(I new) RNG seeded in an unpredictable manner. Passing it a RNG
2311 used elsewhere in the program will result in unintended correlations,
2312 due to the current implementation of RNGs as value types.
2313
2314 Example:
2315 ----
2316 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ];
2317 foreach (e; randomCover(a, Random(unpredictableSeed))) // correct!
2318 {
2319 writeln(e);
2320 }
2321
2322 foreach (e; randomCover(a, rndGen)) // DANGEROUS!! rndGen gets copied by value
2323 {
2324 writeln(e);
2325 }
2326
2327 foreach (e; randomCover(a, rndGen)) // ... so this second random cover
2328 { // will output the same sequence as
2329 writeln(e); // the previous one.
2330 }
2331 ----
2332 */
2333 struct RandomCover(Range, UniformRNG = void)
2334 if (isRandomAccessRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG == void)))
2335 {
2336 private Range _input;
2337 private bool[] _chosen;
2338 private size_t _current;
2339 private size_t _alreadyChosen = 0;
2340 private bool _isEmpty = false;
2341
2342 static if (is(UniformRNG == void))
2343 {
thisRandomCover2344 this(Range input)
2345 {
2346 _input = input;
2347 _chosen.length = _input.length;
2348 if (_input.empty)
2349 {
2350 _isEmpty = true;
2351 }
2352 else
2353 {
2354 _current = uniform(0, _chosen.length);
2355 }
2356 }
2357 }
2358 else
2359 {
2360 private UniformRNG _rng;
2361
thisRandomCover2362 this(Range input, ref UniformRNG rng)
2363 {
2364 _input = input;
2365 _rng = rng;
2366 _chosen.length = _input.length;
2367 if (_input.empty)
2368 {
2369 _isEmpty = true;
2370 }
2371 else
2372 {
2373 _current = uniform(0, _chosen.length, rng);
2374 }
2375 }
2376
thisRandomCover2377 this(Range input, UniformRNG rng)
2378 {
2379 this(input, rng);
2380 }
2381 }
2382
2383 static if (hasLength!Range)
2384 {
lengthRandomCover2385 @property size_t length()
2386 {
2387 return _input.length - _alreadyChosen;
2388 }
2389 }
2390
frontRandomCover2391 @property auto ref front()
2392 {
2393 assert(!_isEmpty);
2394 return _input[_current];
2395 }
2396
popFrontRandomCover2397 void popFront()
2398 {
2399 assert(!_isEmpty);
2400
2401 size_t k = _input.length - _alreadyChosen - 1;
2402 if (k == 0)
2403 {
2404 _isEmpty = true;
2405 ++_alreadyChosen;
2406 return;
2407 }
2408
2409 size_t i;
2410 foreach (e; _input)
2411 {
2412 if (_chosen[i] || i == _current) { ++i; continue; }
2413 // Roll a dice with k faces
2414 static if (is(UniformRNG == void))
2415 {
2416 auto chooseMe = uniform(0, k) == 0;
2417 }
2418 else
2419 {
2420 auto chooseMe = uniform(0, k, _rng) == 0;
2421 }
2422 assert(k > 1 || chooseMe);
2423 if (chooseMe)
2424 {
2425 _chosen[_current] = true;
2426 _current = i;
2427 ++_alreadyChosen;
2428 return;
2429 }
2430 --k;
2431 ++i;
2432 }
2433 }
2434
2435 static if (isForwardRange!UniformRNG)
2436 {
typeofRandomCover2437 @property typeof(this) save()
2438 {
2439 auto ret = this;
2440 ret._input = _input.save;
2441 ret._rng = _rng.save;
2442 return ret;
2443 }
2444 }
2445
emptyRandomCover2446 @property bool empty() { return _isEmpty; }
2447 }
2448
2449 /// Ditto
randomCover(Range,UniformRNG)2450 auto randomCover(Range, UniformRNG)(Range r, auto ref UniformRNG rng)
2451 if (isRandomAccessRange!Range && isUniformRNG!UniformRNG)
2452 {
2453 return RandomCover!(Range, UniformRNG)(r, rng);
2454 }
2455
2456 /// Ditto
2457 auto randomCover(Range)(Range r)
2458 if (isRandomAccessRange!Range)
2459 {
2460 return RandomCover!(Range, void)(r);
2461 }
2462
2463 @safe unittest
2464 {
2465 import std.algorithm;
2466 import std.conv;
2467 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ];
2468 int[] c;
2469 foreach (UniformRNG; std.meta.AliasSeq!(void, PseudoRngTypes))
2470 {
2471 static if (is(UniformRNG == void))
2472 {
2473 auto rc = randomCover(a);
2474 static assert(isInputRange!(typeof(rc)));
2475 static assert(!isForwardRange!(typeof(rc)));
2476 }
2477 else
2478 {
2479 auto rng = UniformRNG(unpredictableSeed);
2480 auto rc = randomCover(a, rng);
2481 static assert(isForwardRange!(typeof(rc)));
2482 // check for constructor passed a value-type RNG
2483 auto rc2 = RandomCover!(int[], UniformRNG)(a, UniformRNG(unpredictableSeed));
2484 static assert(isForwardRange!(typeof(rc2)));
2485 auto rcEmpty = randomCover(c, rng);
2486 assert(rcEmpty.length == 0);
2487 }
2488
2489 int[] b = new int[9];
2490 uint i;
foreach(e;rc)2491 foreach (e; rc)
2492 {
2493 //writeln(e);
2494 b[i++] = e;
2495 }
2496 sort(b);
2497 assert(a == b, text(b));
2498 }
2499 }
2500
2501 @safe unittest
2502 {
2503 // Bugzilla 12589
2504 int[] r = [];
2505 auto rc = randomCover(r);
2506 assert(rc.length == 0);
2507 assert(rc.empty);
2508
2509 // Bugzilla 16724
2510 import std.range : iota;
2511 auto range = iota(10);
2512 auto randy = range.randomCover;
2513
2514 for (int i=1; i <= range.length; i++)
2515 {
2516 randy.popFront;
2517 assert(randy.length == range.length - i);
2518 }
2519 }
2520
2521 // RandomSample
2522 /**
2523 Selects a random subsample out of $(D r), containing exactly $(D n)
2524 elements. The order of elements is the same as in the original
2525 range. The total length of $(D r) must be known. If $(D total) is
2526 passed in, the total number of sample is considered to be $(D
2527 total). Otherwise, $(D RandomSample) uses $(D r.length).
2528
2529 Params:
2530 r = range to sample from
2531 n = number of elements to include in the sample;
2532 must be less than or equal to the total number
2533 of elements in $(D r) and/or the parameter
2534 $(D total) (if provided)
2535 total = (semi-optional) number of elements of $(D r)
2536 from which to select the sample (counting from
2537 the beginning); must be less than or equal to
2538 the total number of elements in $(D r) itself.
2539 May be omitted if $(D r) has the $(D .length)
2540 property and the sample is to be drawn from
2541 all elements of $(D r).
2542 rng = (optional) random number generator to use;
2543 if not specified, defaults to $(D rndGen)
2544
2545 Returns:
2546 Range whose elements consist of a randomly selected subset of
2547 the elements of $(D r), in the same order as these elements
2548 appear in $(D r) itself. Will be a forward range if both $(D r)
2549 and $(D rng) are forward ranges, an input range otherwise.
2550
2551 $(D RandomSample) implements Jeffrey Scott Vitter's Algorithm D
2552 (see Vitter $(HTTP dx.doi.org/10.1145/358105.893, 1984), $(HTTP
2553 dx.doi.org/10.1145/23002.23003, 1987)), which selects a sample
2554 of size $(D n) in O(n) steps and requiring O(n) random variates,
2555 regardless of the size of the data being sampled. The exception
2556 to this is if traversing k elements on the input range is itself
2557 an O(k) operation (e.g. when sampling lines from an input file),
2558 in which case the sampling calculation will inevitably be of
2559 O(total).
2560
2561 RandomSample will throw an exception if $(D total) is verifiably
2562 less than the total number of elements available in the input,
2563 or if $(D n > total).
2564
2565 If no random number generator is passed to $(D randomSample), the
2566 thread-global RNG rndGen will be used internally.
2567
2568 Example:
2569 ----
2570 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
2571 // Print 5 random elements picked off from a
2572 foreach (e; randomSample(a, 5))
2573 {
2574 writeln(e);
2575 }
2576 ----
2577
2578 $(B WARNING:) If an alternative RNG is desired, it is essential for this
2579 to be a $(I new) RNG seeded in an unpredictable manner. Passing it a RNG
2580 used elsewhere in the program will result in unintended correlations,
2581 due to the current implementation of RNGs as value types.
2582
2583 Example:
2584 ----
2585 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
2586 foreach (e; randomSample(a, 5, Random(unpredictableSeed))) // correct!
2587 {
2588 writeln(e);
2589 }
2590
2591 foreach (e; randomSample(a, 5, rndGen)) // DANGEROUS!! rndGen gets
2592 { // copied by value
2593 writeln(e);
2594 }
2595
2596 foreach (e; randomSample(a, 5, rndGen)) // ... so this second random
2597 { // sample will select the same
2598 writeln(e); // values as the previous one.
2599 }
2600 ----
2601 */
2602 struct RandomSample(Range, UniformRNG = void)
2603 if (isInputRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG == void)))
2604 {
2605 private size_t _available, _toSelect;
2606 private enum ushort _alphaInverse = 13; // Vitter's recommended value.
2607 private double _Vprime;
2608 private Range _input;
2609 private size_t _index;
2610 private enum Skip { None, A, D }
2611 private Skip _skip = Skip.None;
2612
2613 // If we're using the default thread-local random number generator then
2614 // we shouldn't store a copy of it here. UniformRNG == void is a sentinel
2615 // for this. If we're using a user-specified generator then we have no
2616 // choice but to store a copy.
2617 static if (is(UniformRNG == void))
2618 {
2619 static if (hasLength!Range)
2620 {
thisRandomSample2621 this(Range input, size_t howMany)
2622 {
2623 _input = input;
2624 initialize(howMany, input.length);
2625 }
2626 }
2627
thisRandomSample2628 this(Range input, size_t howMany, size_t total)
2629 {
2630 _input = input;
2631 initialize(howMany, total);
2632 }
2633 }
2634 else
2635 {
2636 UniformRNG _rng;
2637
2638 static if (hasLength!Range)
2639 {
thisRandomSample2640 this(Range input, size_t howMany, ref UniformRNG rng)
2641 {
2642 _rng = rng;
2643 _input = input;
2644 initialize(howMany, input.length);
2645 }
2646
thisRandomSample2647 this(Range input, size_t howMany, UniformRNG rng)
2648 {
2649 this(input, howMany, rng);
2650 }
2651 }
2652
thisRandomSample2653 this(Range input, size_t howMany, size_t total, ref UniformRNG rng)
2654 {
2655 _rng = rng;
2656 _input = input;
2657 initialize(howMany, total);
2658 }
2659
thisRandomSample2660 this(Range input, size_t howMany, size_t total, UniformRNG rng)
2661 {
2662 this(input, howMany, total, rng);
2663 }
2664 }
2665
initializeRandomSample2666 private void initialize(size_t howMany, size_t total)
2667 {
2668 import std.conv : text;
2669 import std.exception : enforce;
2670 _available = total;
2671 _toSelect = howMany;
2672 enforce(_toSelect <= _available,
2673 text("RandomSample: cannot sample ", _toSelect,
2674 " items when only ", _available, " are available"));
2675 static if (hasLength!Range)
2676 {
2677 enforce(_available <= _input.length,
2678 text("RandomSample: specified ", _available,
2679 " items as available when input contains only ",
2680 _input.length));
2681 }
2682 }
2683
initializeFrontRandomSample2684 private void initializeFront()
2685 {
2686 assert(_skip == Skip.None);
2687 // We can save ourselves a random variate by checking right
2688 // at the beginning if we should use Algorithm A.
2689 if ((_alphaInverse * _toSelect) > _available)
2690 {
2691 _skip = Skip.A;
2692 }
2693 else
2694 {
2695 _skip = Skip.D;
2696 _Vprime = newVprime(_toSelect);
2697 }
2698 prime();
2699 }
2700
2701 /**
2702 Range primitives.
2703 */
emptyRandomSample2704 @property bool empty() const
2705 {
2706 return _toSelect == 0;
2707 }
2708
2709 /// Ditto
frontRandomSample2710 @property auto ref front()
2711 {
2712 assert(!empty);
2713 // The first sample point must be determined here to avoid
2714 // having it always correspond to the first element of the
2715 // input. The rest of the sample points are determined each
2716 // time we call popFront().
2717 if (_skip == Skip.None)
2718 {
2719 initializeFront();
2720 }
2721 return _input.front;
2722 }
2723
2724 /// Ditto
popFrontRandomSample2725 void popFront()
2726 {
2727 // First we need to check if the sample has
2728 // been initialized in the first place.
2729 if (_skip == Skip.None)
2730 {
2731 initializeFront();
2732 }
2733
2734 _input.popFront();
2735 --_available;
2736 --_toSelect;
2737 ++_index;
2738 prime();
2739 }
2740
2741 /// Ditto
2742 static if (isForwardRange!Range && isForwardRange!UniformRNG)
2743 {
typeofRandomSample2744 @property typeof(this) save()
2745 {
2746 auto ret = this;
2747 ret._input = _input.save;
2748 ret._rng = _rng.save;
2749 return ret;
2750 }
2751 }
2752
2753 /// Ditto
lengthRandomSample2754 @property size_t length()
2755 {
2756 return _toSelect;
2757 }
2758
2759 /**
2760 Returns the index of the visited record.
2761 */
indexRandomSample2762 @property size_t index()
2763 {
2764 if (_skip == Skip.None)
2765 {
2766 initializeFront();
2767 }
2768 return _index;
2769 }
2770
skipRandomSample2771 private size_t skip()
2772 {
2773 assert(_skip != Skip.None);
2774
2775 // Step D1: if the number of points still to select is greater
2776 // than a certain proportion of the remaining data points, i.e.
2777 // if n >= alpha * N where alpha = 1/13, we carry out the
2778 // sampling with Algorithm A.
2779 if (_skip == Skip.A)
2780 {
2781 return skipA();
2782 }
2783 else if ((_alphaInverse * _toSelect) > _available)
2784 {
2785 // We shouldn't get here unless the current selected
2786 // algorithm is D.
2787 assert(_skip == Skip.D);
2788 _skip = Skip.A;
2789 return skipA();
2790 }
2791 else
2792 {
2793 assert(_skip == Skip.D);
2794 return skipD();
2795 }
2796 }
2797
2798 /*
2799 Vitter's Algorithm A, used when the ratio of needed sample values
2800 to remaining data values is sufficiently large.
2801 */
skipARandomSample2802 private size_t skipA()
2803 {
2804 size_t s;
2805 double v, quot, top;
2806
2807 if (_toSelect == 1)
2808 {
2809 static if (is(UniformRNG == void))
2810 {
2811 s = uniform(0, _available);
2812 }
2813 else
2814 {
2815 s = uniform(0, _available, _rng);
2816 }
2817 }
2818 else
2819 {
2820 v = 0;
2821 top = _available - _toSelect;
2822 quot = top / _available;
2823
2824 static if (is(UniformRNG == void))
2825 {
2826 v = uniform!"()"(0.0, 1.0);
2827 }
2828 else
2829 {
2830 v = uniform!"()"(0.0, 1.0, _rng);
2831 }
2832
2833 while (quot > v)
2834 {
2835 ++s;
2836 quot *= (top - s) / (_available - s);
2837 }
2838 }
2839
2840 return s;
2841 }
2842
2843 /*
2844 Randomly reset the value of _Vprime.
2845 */
newVprimeRandomSample2846 private double newVprime(size_t remaining)
2847 {
2848 static if (is(UniformRNG == void))
2849 {
2850 double r = uniform!"()"(0.0, 1.0);
2851 }
2852 else
2853 {
2854 double r = uniform!"()"(0.0, 1.0, _rng);
2855 }
2856
2857 return r ^^ (1.0 / remaining);
2858 }
2859
2860 /*
2861 Vitter's Algorithm D. For an extensive description of the algorithm
2862 and its rationale, see:
2863
2864 * Vitter, J.S. (1984), "Faster methods for random sampling",
2865 Commun. ACM 27(7): 703--718
2866
2867 * Vitter, J.S. (1987) "An efficient algorithm for sequential random
2868 sampling", ACM Trans. Math. Softw. 13(1): 58-67.
2869
2870 Variable names are chosen to match those in Vitter's paper.
2871 */
skipDRandomSample2872 private size_t skipD()
2873 {
2874 import std.math : isNaN, trunc;
2875 // Confirm that the check in Step D1 is valid and we
2876 // haven't been sent here by mistake
2877 assert((_alphaInverse * _toSelect) <= _available);
2878
2879 // Now it's safe to use the standard Algorithm D mechanism.
2880 if (_toSelect > 1)
2881 {
2882 size_t s;
2883 size_t qu1 = 1 + _available - _toSelect;
2884 double x, y1;
2885
2886 assert(!_Vprime.isNaN());
2887
2888 while (true)
2889 {
2890 // Step D2: set values of x and u.
2891 while (1)
2892 {
2893 x = _available * (1-_Vprime);
2894 s = cast(size_t) trunc(x);
2895 if (s < qu1)
2896 break;
2897 _Vprime = newVprime(_toSelect);
2898 }
2899
2900 static if (is(UniformRNG == void))
2901 {
2902 double u = uniform!"()"(0.0, 1.0);
2903 }
2904 else
2905 {
2906 double u = uniform!"()"(0.0, 1.0, _rng);
2907 }
2908
2909 y1 = (u * (cast(double) _available) / qu1) ^^ (1.0/(_toSelect - 1));
2910
2911 _Vprime = y1 * ((-x/_available)+1.0) * ( qu1/( (cast(double) qu1) - s ) );
2912
2913 // Step D3: if _Vprime <= 1.0 our work is done and we return S.
2914 // Otherwise ...
2915 if (_Vprime > 1.0)
2916 {
2917 size_t top = _available - 1, limit;
2918 double y2 = 1.0, bottom;
2919
2920 if (_toSelect > (s+1))
2921 {
2922 bottom = _available - _toSelect;
2923 limit = _available - s;
2924 }
2925 else
2926 {
2927 bottom = _available - (s+1);
2928 limit = qu1;
2929 }
2930
2931 foreach (size_t t; limit .. _available)
2932 {
2933 y2 *= top/bottom;
2934 top--;
2935 bottom--;
2936 }
2937
2938 // Step D4: decide whether or not to accept the current value of S.
2939 if (_available/(_available-x) < y1 * (y2 ^^ (1.0/(_toSelect-1))))
2940 {
2941 // If it's not acceptable, we generate a new value of _Vprime
2942 // and go back to the start of the for (;;) loop.
2943 _Vprime = newVprime(_toSelect);
2944 }
2945 else
2946 {
2947 // If it's acceptable we generate a new value of _Vprime
2948 // based on the remaining number of sample points needed,
2949 // and return S.
2950 _Vprime = newVprime(_toSelect-1);
2951 return s;
2952 }
2953 }
2954 else
2955 {
2956 // Return if condition D3 satisfied.
2957 return s;
2958 }
2959 }
2960 }
2961 else
2962 {
2963 // If only one sample point remains to be taken ...
2964 return cast(size_t) trunc(_available * _Vprime);
2965 }
2966 }
2967
primeRandomSample2968 private void prime()
2969 {
2970 if (empty)
2971 {
2972 return;
2973 }
2974 assert(_available && _available >= _toSelect);
2975 immutable size_t s = skip();
2976 assert(s + _toSelect <= _available);
2977 static if (hasLength!Range)
2978 {
2979 assert(s + _toSelect <= _input.length);
2980 }
2981 assert(!_input.empty);
2982 _input.popFrontExactly(s);
2983 _index += s;
2984 _available -= s;
2985 assert(_available > 0);
2986 }
2987 }
2988
2989 /// Ditto
randomSample(Range)2990 auto randomSample(Range)(Range r, size_t n, size_t total)
2991 if (isInputRange!Range)
2992 {
2993 return RandomSample!(Range, void)(r, n, total);
2994 }
2995
2996 /// Ditto
2997 auto randomSample(Range)(Range r, size_t n)
2998 if (isInputRange!Range && hasLength!Range)
2999 {
3000 return RandomSample!(Range, void)(r, n, r.length);
3001 }
3002
3003 /// Ditto
3004 auto randomSample(Range, UniformRNG)(Range r, size_t n, size_t total, auto ref UniformRNG rng)
3005 if (isInputRange!Range && isUniformRNG!UniformRNG)
3006 {
3007 return RandomSample!(Range, UniformRNG)(r, n, total, rng);
3008 }
3009
3010 /// Ditto
3011 auto randomSample(Range, UniformRNG)(Range r, size_t n, auto ref UniformRNG rng)
3012 if (isInputRange!Range && hasLength!Range && isUniformRNG!UniformRNG)
3013 {
3014 return RandomSample!(Range, UniformRNG)(r, n, r.length, rng);
3015 }
3016
3017 @system unittest
3018 {
3019 // @system because it takes the address of a local
3020 import std.conv : text;
3021 import std.exception;
3022 import std.range;
3023 // For test purposes, an infinite input range
3024 struct TestInputRange
3025 {
3026 private auto r = recurrence!"a[n-1] + 1"(0);
emptyTestInputRange3027 bool empty() @property const pure nothrow { return r.empty; }
frontTestInputRange3028 auto front() @property pure nothrow { return r.front; }
popFrontTestInputRange3029 void popFront() pure nothrow { r.popFront(); }
3030 }
3031 static assert(isInputRange!TestInputRange);
3032 static assert(!isForwardRange!TestInputRange);
3033
3034 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
3035
foreach(UniformRNG;PseudoRngTypes)3036 foreach (UniformRNG; PseudoRngTypes)
3037 {
3038 auto rng = UniformRNG(1234);
3039 /* First test the most general case: randomSample of input range, with and
3040 * without a specified random number generator.
3041 */
3042 static assert(isInputRange!(typeof(randomSample(TestInputRange(), 5, 10))));
3043 static assert(isInputRange!(typeof(randomSample(TestInputRange(), 5, 10, rng))));
3044 static assert(!isForwardRange!(typeof(randomSample(TestInputRange(), 5, 10))));
3045 static assert(!isForwardRange!(typeof(randomSample(TestInputRange(), 5, 10, rng))));
3046 // test case with range initialized by direct call to struct
3047 {
3048 auto sample =
3049 RandomSample!(TestInputRange, UniformRNG)
3050 (TestInputRange(), 5, 10, UniformRNG(unpredictableSeed));
3051 static assert(isInputRange!(typeof(sample)));
3052 static assert(!isForwardRange!(typeof(sample)));
3053 }
3054
3055 /* Now test the case of an input range with length. We ignore the cases
3056 * already covered by the previous tests.
3057 */
3058 static assert(isInputRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5))));
3059 static assert(isInputRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5, rng))));
3060 static assert(!isForwardRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5))));
3061 static assert(!isForwardRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5, rng))));
3062 // test case with range initialized by direct call to struct
3063 {
3064 auto sample =
3065 RandomSample!(typeof(TestInputRange().takeExactly(10)), UniformRNG)
3066 (TestInputRange().takeExactly(10), 5, 10, UniformRNG(unpredictableSeed));
3067 static assert(isInputRange!(typeof(sample)));
3068 static assert(!isForwardRange!(typeof(sample)));
3069 }
3070
3071 // Now test the case of providing a forward range as input.
3072 static assert(!isForwardRange!(typeof(randomSample(a, 5))));
3073 static if (isForwardRange!UniformRNG)
3074 {
3075 static assert(isForwardRange!(typeof(randomSample(a, 5, rng))));
3076 // ... and test with range initialized directly
3077 {
3078 auto sample =
3079 RandomSample!(int[], UniformRNG)
3080 (a, 5, UniformRNG(unpredictableSeed));
3081 static assert(isForwardRange!(typeof(sample)));
3082 }
3083 }
3084 else
3085 {
3086 static assert(isInputRange!(typeof(randomSample(a, 5, rng))));
3087 static assert(!isForwardRange!(typeof(randomSample(a, 5, rng))));
3088 // ... and test with range initialized directly
3089 {
3090 auto sample =
3091 RandomSample!(int[], UniformRNG)
3092 (a, 5, UniformRNG(unpredictableSeed));
3093 static assert(isInputRange!(typeof(sample)));
3094 static assert(!isForwardRange!(typeof(sample)));
3095 }
3096 }
3097
3098 /* Check that randomSample will throw an error if we claim more
3099 * items are available than there actually are, or if we try to
3100 * sample more items than are available. */
3101 assert(collectExceptionMsg(
3102 randomSample(a, 5, 15)
3103 ) == "RandomSample: specified 15 items as available when input contains only 10");
3104 assert(collectExceptionMsg(
3105 randomSample(a, 15)
3106 ) == "RandomSample: cannot sample 15 items when only 10 are available");
3107 assert(collectExceptionMsg(
3108 randomSample(a, 9, 8)
3109 ) == "RandomSample: cannot sample 9 items when only 8 are available");
3110 assert(collectExceptionMsg(
3111 randomSample(TestInputRange(), 12, 11)
3112 ) == "RandomSample: cannot sample 12 items when only 11 are available");
3113
3114 /* Check that sampling algorithm never accidentally overruns the end of
3115 * the input range. If input is an InputRange without .length, this
3116 * relies on the user specifying the total number of available items
3117 * correctly.
3118 */
3119 {
3120 uint i = 0;
3121 foreach (e; randomSample(a, a.length))
3122 {
3123 assert(e == i);
3124 ++i;
3125 }
3126 assert(i == a.length);
3127
3128 i = 0;
3129 foreach (e; randomSample(TestInputRange(), 17, 17))
3130 {
3131 assert(e == i);
3132 ++i;
3133 }
3134 assert(i == 17);
3135 }
3136
3137
3138 // Check length properties of random samples.
3139 assert(randomSample(a, 5).length == 5);
3140 assert(randomSample(a, 5, 10).length == 5);
3141 assert(randomSample(a, 5, rng).length == 5);
3142 assert(randomSample(a, 5, 10, rng).length == 5);
3143 assert(randomSample(TestInputRange(), 5, 10).length == 5);
3144 assert(randomSample(TestInputRange(), 5, 10, rng).length == 5);
3145
3146 // ... and emptiness!
3147 assert(randomSample(a, 0).empty);
3148 assert(randomSample(a, 0, 5).empty);
3149 assert(randomSample(a, 0, rng).empty);
3150 assert(randomSample(a, 0, 5, rng).empty);
3151 assert(randomSample(TestInputRange(), 0, 10).empty);
3152 assert(randomSample(TestInputRange(), 0, 10, rng).empty);
3153
3154 /* Test that the (lazy) evaluation of random samples works correctly.
3155 *
3156 * We cover 2 different cases: a sample where the ratio of sample points
3157 * to total points is greater than the threshold for using Algorithm, and
3158 * one where the ratio is small enough (< 1/13) for Algorithm D to be used.
3159 *
3160 * For each, we also cover the case with and without a specified RNG.
3161 */
3162 {
3163 // Small sample/source ratio, no specified RNG.
3164 uint i = 0;
3165 foreach (e; randomSample(randomCover(a), 5))
3166 {
3167 ++i;
3168 }
3169 assert(i == 5);
3170
3171 // Small sample/source ratio, specified RNG.
3172 i = 0;
3173 foreach (e; randomSample(randomCover(a), 5, rng))
3174 {
3175 ++i;
3176 }
3177 assert(i == 5);
3178
3179 // Large sample/source ratio, no specified RNG.
3180 i = 0;
3181 foreach (e; randomSample(TestInputRange(), 123, 123_456))
3182 {
3183 ++i;
3184 }
3185 assert(i == 123);
3186
3187 // Large sample/source ratio, specified RNG.
3188 i = 0;
3189 foreach (e; randomSample(TestInputRange(), 123, 123_456, rng))
3190 {
3191 ++i;
3192 }
3193 assert(i == 123);
3194
3195 /* Sample/source ratio large enough to start with Algorithm D,
3196 * small enough to switch to Algorithm A.
3197 */
3198 i = 0;
3199 foreach (e; randomSample(TestInputRange(), 10, 131))
3200 {
3201 ++i;
3202 }
3203 assert(i == 10);
3204 }
3205
3206 // Test that the .index property works correctly
3207 {
3208 auto sample1 = randomSample(TestInputRange(), 654, 654_321);
3209 for (; !sample1.empty; sample1.popFront())
3210 {
3211 assert(sample1.front == sample1.index);
3212 }
3213
3214 auto sample2 = randomSample(TestInputRange(), 654, 654_321, rng);
3215 for (; !sample2.empty; sample2.popFront())
3216 {
3217 assert(sample2.front == sample2.index);
3218 }
3219
3220 /* Check that it also works if .index is called before .front.
3221 * See: http://d.puremagic.com/issues/show_bug.cgi?id=10322
3222 */
3223 auto sample3 = randomSample(TestInputRange(), 654, 654_321);
3224 for (; !sample3.empty; sample3.popFront())
3225 {
3226 assert(sample3.index == sample3.front);
3227 }
3228
3229 auto sample4 = randomSample(TestInputRange(), 654, 654_321, rng);
3230 for (; !sample4.empty; sample4.popFront())
3231 {
3232 assert(sample4.index == sample4.front);
3233 }
3234 }
3235
3236 /* Test behaviour if .popFront() is called before sample is read.
3237 * This is a rough-and-ready check that the statistical properties
3238 * are in the ballpark -- not a proper validation of statistical
3239 * quality! This incidentally also checks for reference-type
3240 * initialization bugs, as the foreach () loop will operate on a
3241 * copy of the popFronted (and hence initialized) sample.
3242 */
3243 {
3244 size_t count0, count1, count99;
3245 foreach (_; 0 .. 100_000)
3246 {
3247 auto sample = randomSample(iota(100), 5, &rng);
3248 sample.popFront();
3249 foreach (s; sample)
3250 {
3251 if (s == 0)
3252 {
3253 ++count0;
3254 }
3255 else if (s == 1)
3256 {
3257 ++count1;
3258 }
3259 else if (s == 99)
3260 {
3261 ++count99;
3262 }
3263 }
3264 }
3265 /* Statistical assumptions here: this is a sequential sampling process
3266 * so (i) 0 can only be the first sample point, so _can't_ be in the
3267 * remainder of the sample after .popFront() is called. (ii) By similar
3268 * token, 1 can only be in the remainder if it's the 2nd point of the
3269 * whole sample, and hence if 0 was the first; probability of 0 being
3270 * first and 1 second is 5/100 * 4/99 (thank you, Algorithm S:-) and
3271 * so the mean count of 1 should be about 202. Finally, 99 can only
3272 * be the _last_ sample point to be picked, so its probability of
3273 * inclusion should be independent of the .popFront() and it should
3274 * occur with frequency 5/100, hence its count should be about 5000.
3275 * Unfortunately we have to set quite a high tolerance because with
3276 * sample size small enough for unittests to run in reasonable time,
3277 * the variance can be quite high.
3278 */
3279 assert(count0 == 0);
3280 assert(count1 < 300, text("1: ", count1, " > 300."));
3281 assert(4_700 < count99, text("99: ", count99, " < 4700."));
3282 assert(count99 < 5_300, text("99: ", count99, " > 5300."));
3283 }
3284
3285 /* Odd corner-cases: RandomSample has 2 constructors that are not called
3286 * by the randomSample() helper functions, but that can be used if the
3287 * constructor is called directly. These cover the case of the user
3288 * specifying input but not input length.
3289 */
3290 {
3291 auto input1 = TestInputRange().takeExactly(456_789);
3292 static assert(hasLength!(typeof(input1)));
3293 auto sample1 = RandomSample!(typeof(input1), void)(input1, 789);
3294 static assert(isInputRange!(typeof(sample1)));
3295 static assert(!isForwardRange!(typeof(sample1)));
3296 assert(sample1.length == 789);
3297 assert(sample1._available == 456_789);
3298 uint i = 0;
3299 for (; !sample1.empty; sample1.popFront())
3300 {
3301 assert(sample1.front == sample1.index);
3302 ++i;
3303 }
3304 assert(i == 789);
3305
3306 auto input2 = TestInputRange().takeExactly(456_789);
3307 static assert(hasLength!(typeof(input2)));
3308 auto sample2 = RandomSample!(typeof(input2), typeof(rng))(input2, 789, rng);
3309 static assert(isInputRange!(typeof(sample2)));
3310 static assert(!isForwardRange!(typeof(sample2)));
3311 assert(sample2.length == 789);
3312 assert(sample2._available == 456_789);
3313 i = 0;
3314 for (; !sample2.empty; sample2.popFront())
3315 {
3316 assert(sample2.front == sample2.index);
3317 ++i;
3318 }
3319 assert(i == 789);
3320 }
3321
3322 /* Test that the save property works where input is a forward range,
3323 * and RandomSample is using a (forward range) random number generator
3324 * that is not rndGen.
3325 */
3326 static if (isForwardRange!UniformRNG)
3327 {
3328 auto sample1 = randomSample(a, 5, rng);
3329 auto sample2 = sample1.save;
3330 assert(sample1.array() == sample2.array());
3331 }
3332
3333 // Bugzilla 8314
3334 {
3335 auto sample(RandomGen)(uint seed) { return randomSample(a, 1, RandomGen(seed)).front; }
3336
3337 // Start from 1 because not all RNGs accept 0 as seed.
3338 immutable fst = sample!UniformRNG(1);
3339 uint n = 1;
3340 while (sample!UniformRNG(++n) == fst && n < n.max) {}
3341 assert(n < n.max);
3342 }
3343 }
3344 }
3345