]> git.ipfire.org Git - thirdparty/gcc.git/blob - libphobos/src/std/random.d
d: Merge upstream dmd 3982604c5, druntime bc58b1e9, phobos 12329adb6.
[thirdparty/gcc.git] / libphobos / src / std / random.d
1 // Written in the D programming language.
2
3 /**
4 Facilities for random number generation.
5
6 $(SCRIPT inhibitQuickIndex = 1;)
7 $(DIVC quickindex,
8 $(BOOKTABLE,
9 $(TR $(TH Category) $(TH Functions))
10 $(TR $(TD Uniform sampling) $(TD
11 $(LREF uniform)
12 $(LREF uniform01)
13 $(LREF uniformDistribution)
14 ))
15 $(TR $(TD Element sampling) $(TD
16 $(LREF choice)
17 $(LREF dice)
18 ))
19 $(TR $(TD Range sampling) $(TD
20 $(LREF randomCover)
21 $(LREF randomSample)
22 ))
23 $(TR $(TD Default Random Engines) $(TD
24 $(LREF rndGen)
25 $(LREF Random)
26 $(LREF unpredictableSeed)
27 ))
28 $(TR $(TD Linear Congruential Engines) $(TD
29 $(LREF MinstdRand)
30 $(LREF MinstdRand0)
31 $(LREF LinearCongruentialEngine)
32 ))
33 $(TR $(TD Mersenne Twister Engines) $(TD
34 $(LREF Mt19937)
35 $(LREF Mt19937_64)
36 $(LREF MersenneTwisterEngine)
37 ))
38 $(TR $(TD Xorshift Engines) $(TD
39 $(LREF Xorshift)
40 $(LREF XorshiftEngine)
41 $(LREF Xorshift32)
42 $(LREF Xorshift64)
43 $(LREF Xorshift96)
44 $(LREF Xorshift128)
45 $(LREF Xorshift160)
46 $(LREF Xorshift192)
47 ))
48 $(TR $(TD Shuffle) $(TD
49 $(LREF partialShuffle)
50 $(LREF randomShuffle)
51 ))
52 $(TR $(TD Traits) $(TD
53 $(LREF isSeedable)
54 $(LREF isUniformRNG)
55 ))
56 ))
57
58 $(RED Disclaimer:) The random number generators and API provided in this
59 module are not designed to be cryptographically secure, and are therefore
60 unsuitable for cryptographic or security-related purposes such as generating
61 authentication tokens or network sequence numbers. For such needs, please use a
62 reputable cryptographic library instead.
63
64 The new-style generator objects hold their own state so they are
65 immune of threading issues. The generators feature a number of
66 well-known and well-documented methods of generating random
67 numbers. An overall fast and reliable means to generate random numbers
68 is the $(D_PARAM Mt19937) generator, which derives its name from
69 "$(LINK2 https://en.wikipedia.org/wiki/Mersenne_Twister, Mersenne Twister)
70 with a period of 2 to the power of
71 19937". In memory-constrained situations,
72 $(LINK2 https://en.wikipedia.org/wiki/Linear_congruential_generator,
73 linear congruential generators) such as `MinstdRand0` and `MinstdRand` might be
74 useful. The standard library provides an alias $(D_PARAM Random) for
75 whichever generator it considers the most fit for the target
76 environment.
77
78 In addition to random number generators, this module features
79 distributions, which skew a generator's output statistical
80 distribution in various ways. So far the uniform distribution for
81 integers and real numbers have been implemented.
82
83 Source: $(PHOBOSSRC std/random.d)
84
85 Macros:
86
87 Copyright: Copyright Andrei Alexandrescu 2008 - 2009, Joseph Rushton Wakeling 2012.
88 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
89 Authors: $(HTTP erdani.org, Andrei Alexandrescu)
90 Masahiro Nakagawa (Xorshift random generator)
91 $(HTTP braingam.es, Joseph Rushton Wakeling) (Algorithm D for random sampling)
92 Ilya Yaroshenko (Mersenne Twister implementation, adapted from $(HTTPS github.com/libmir/mir-random, mir-random))
93 Credits: The entire random number library architecture is derived from the
94 excellent $(HTTP open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf, C++0X)
95 random number facility proposed by Jens Maurer and contributed to by
96 researchers at the Fermi laboratory (excluding Xorshift).
97 */
98 /*
99 Copyright Andrei Alexandrescu 2008 - 2009.
100 Distributed under the Boost Software License, Version 1.0.
101 (See accompanying file LICENSE_1_0.txt or copy at
102 http://www.boost.org/LICENSE_1_0.txt)
103 */
104 module std.random;
105
106
107 import std.range.primitives;
108 import std.traits;
109
110 version (OSX)
111 version = Darwin;
112 else version (iOS)
113 version = Darwin;
114 else version (TVOS)
115 version = Darwin;
116 else version (WatchOS)
117 version = Darwin;
118
119 version (D_InlineAsm_X86) version = InlineAsm_X86_Any;
120 version (D_InlineAsm_X86_64) version = InlineAsm_X86_Any;
121
122 ///
123 @safe unittest
124 {
125 import std.algorithm.comparison : among, equal;
126 import std.range : iota;
127
128 // seed a random generator with a constant
129 auto rnd = Random(42);
130
131 // Generate a uniformly-distributed integer in the range [0, 14]
132 // If no random generator is passed, the global `rndGen` would be used
133 auto i = uniform(0, 15, rnd);
134 assert(i >= 0 && i < 15);
135
136 // Generate a uniformly-distributed real in the range [0, 100)
137 auto r = uniform(0.0L, 100.0L, rnd);
138 assert(r >= 0 && r < 100);
139
140 // Sample from a custom type
141 enum Fruit { apple, mango, pear }
142 auto f = rnd.uniform!Fruit;
143 with(Fruit)
144 assert(f.among(apple, mango, pear));
145
146 // Generate a 32-bit random number
147 auto u = uniform!uint(rnd);
148 static assert(is(typeof(u) == uint));
149
150 // Generate a random number in the range in the range [0, 1)
151 auto u2 = uniform01(rnd);
152 assert(u2 >= 0 && u2 < 1);
153
154 // Select an element randomly
155 auto el = 10.iota.choice(rnd);
156 assert(0 <= el && el < 10);
157
158 // Throw a dice with custom proportions
159 // 0: 20%, 1: 10%, 2: 60%
160 auto val = rnd.dice(0.2, 0.1, 0.6);
161 assert(0 <= val && val <= 2);
162
163 auto rnd2 = MinstdRand0(42);
164
165 // Select a random subsample from a range
166 assert(10.iota.randomSample(3, rnd2).equal([7, 8, 9]));
167
168 // Cover all elements in an array in random order
169 version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
170 assert(10.iota.randomCover(rnd2).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5]));
171 else
172 assert(10.iota.randomCover(rnd2).equal([4, 8, 7, 3, 5, 9, 2, 6, 0, 1]));
173
174 // Shuffle an array
175 version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
176 assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([2, 0, 4, 5, 1]));
177 else
178 assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([4, 2, 5, 0, 1]));
179 }
180
181 version (StdUnittest)
182 {
183 static import std.meta;
184 package alias Xorshift64_64 = XorshiftEngine!(ulong, 64, -12, 25, -27);
185 package alias Xorshift128_64 = XorshiftEngine!(ulong, 128, 23, -18, -5);
186 package alias PseudoRngTypes = std.meta.AliasSeq!(MinstdRand0, MinstdRand, Mt19937, Xorshift32, Xorshift64,
187 Xorshift96, Xorshift128, Xorshift160, Xorshift192,
188 Xorshift64_64, Xorshift128_64);
189 }
190
191 // Segments of the code in this file Copyright (c) 1997 by Rick Booth
192 // From "Inner Loops" by Rick Booth, Addison-Wesley
193
194 // Work derived from:
195
196 /*
197 A C-program for MT19937, with initialization improved 2002/1/26.
198 Coded by Takuji Nishimura and Makoto Matsumoto.
199
200 Before using, initialize the state by using init_genrand(seed)
201 or init_by_array(init_key, key_length).
202
203 Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
204 All rights reserved.
205
206 Redistribution and use in source and binary forms, with or without
207 modification, are permitted provided that the following conditions
208 are met:
209
210 1. Redistributions of source code must retain the above copyright
211 notice, this list of conditions and the following disclaimer.
212
213 2. Redistributions in binary form must reproduce the above copyright
214 notice, this list of conditions and the following disclaimer in the
215 documentation and/or other materials provided with the distribution.
216
217 3. The names of its contributors may not be used to endorse or promote
218 products derived from this software without specific prior written
219 permission.
220
221 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
222 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
223 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
224 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
225 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
226 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
227 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
228 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
229 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
230 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
231 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
232
233
234 Any feedback is very welcome.
235 http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
236 email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
237 */
238
239 /**
240 * Test if Rng is a random-number generator. The overload
241 * taking a ElementType also makes sure that the Rng generates
242 * values of that type.
243 *
244 * A random-number generator has at least the following features:
245 * $(UL
246 * $(LI it's an InputRange)
247 * $(LI it has a 'bool isUniformRandom' field readable in CTFE)
248 * )
249 */
250 template isUniformRNG(Rng, ElementType)
251 {
252 enum bool isUniformRNG = .isUniformRNG!Rng &&
253 is(std.range.primitives.ElementType!Rng == ElementType);
254 }
255
256 /**
257 * ditto
258 */
259 template isUniformRNG(Rng)
260 {
261 enum bool isUniformRNG = isInputRange!Rng &&
262 is(typeof(
263 {
264 static assert(Rng.isUniformRandom); //tag
265 }));
266 }
267
268 ///
269 @safe unittest
270 {
271 struct NoRng
272 {
273 @property uint front() {return 0;}
274 @property bool empty() {return false;}
275 void popFront() {}
276 }
277 static assert(!isUniformRNG!(NoRng));
278
279 struct validRng
280 {
281 @property uint front() {return 0;}
282 @property bool empty() {return false;}
283 void popFront() {}
284
285 enum isUniformRandom = true;
286 }
287 static assert(isUniformRNG!(validRng, uint));
288 static assert(isUniformRNG!(validRng));
289 }
290
291 @safe unittest
292 {
293 // two-argument predicate should not require @property on `front`
294 // https://issues.dlang.org/show_bug.cgi?id=19837
295 struct Rng
296 {
297 float front() {return 0;}
298 void popFront() {}
299 enum empty = false;
300 enum isUniformRandom = true;
301 }
302 static assert(isUniformRNG!(Rng, float));
303 }
304
305 /**
306 * Test if Rng is seedable. The overload
307 * taking a SeedType also makes sure that the Rng can be seeded with SeedType.
308 *
309 * A seedable random-number generator has the following additional features:
310 * $(UL
311 * $(LI it has a 'seed(ElementType)' function)
312 * )
313 */
314 template isSeedable(Rng, SeedType)
315 {
316 enum bool isSeedable = isUniformRNG!(Rng) &&
317 is(typeof(
318 {
319 Rng r = void; // can define a Rng object
320 SeedType s = void;
321 r.seed(s); // can seed a Rng
322 }));
323 }
324
325 ///ditto
326 template isSeedable(Rng)
327 {
328 enum bool isSeedable = isUniformRNG!Rng &&
329 is(typeof(
330 {
331 Rng r = void; // can define a Rng object
332 alias SeedType = typeof(r.front);
333 SeedType s = void;
334 r.seed(s); // can seed a Rng
335 }));
336 }
337
338 ///
339 @safe unittest
340 {
341 struct validRng
342 {
343 @property uint front() {return 0;}
344 @property bool empty() {return false;}
345 void popFront() {}
346
347 enum isUniformRandom = true;
348 }
349 static assert(!isSeedable!(validRng, uint));
350 static assert(!isSeedable!(validRng));
351
352 struct seedRng
353 {
354 @property uint front() {return 0;}
355 @property bool empty() {return false;}
356 void popFront() {}
357 void seed(uint val){}
358 enum isUniformRandom = true;
359 }
360 static assert(isSeedable!(seedRng, uint));
361 static assert(!isSeedable!(seedRng, ulong));
362 static assert(isSeedable!(seedRng));
363 }
364
365 @safe @nogc pure nothrow unittest
366 {
367 struct NoRng
368 {
369 @property uint front() {return 0;}
370 @property bool empty() {return false;}
371 void popFront() {}
372 }
373 static assert(!isUniformRNG!(NoRng, uint));
374 static assert(!isUniformRNG!(NoRng));
375 static assert(!isSeedable!(NoRng, uint));
376 static assert(!isSeedable!(NoRng));
377
378 struct NoRng2
379 {
380 @property uint front() {return 0;}
381 @property bool empty() {return false;}
382 void popFront() {}
383
384 enum isUniformRandom = false;
385 }
386 static assert(!isUniformRNG!(NoRng2, uint));
387 static assert(!isUniformRNG!(NoRng2));
388 static assert(!isSeedable!(NoRng2, uint));
389 static assert(!isSeedable!(NoRng2));
390
391 struct NoRng3
392 {
393 @property bool empty() {return false;}
394 void popFront() {}
395
396 enum isUniformRandom = true;
397 }
398 static assert(!isUniformRNG!(NoRng3, uint));
399 static assert(!isUniformRNG!(NoRng3));
400 static assert(!isSeedable!(NoRng3, uint));
401 static assert(!isSeedable!(NoRng3));
402
403 struct validRng
404 {
405 @property uint front() {return 0;}
406 @property bool empty() {return false;}
407 void popFront() {}
408
409 enum isUniformRandom = true;
410 }
411 static assert(isUniformRNG!(validRng, uint));
412 static assert(isUniformRNG!(validRng));
413 static assert(!isSeedable!(validRng, uint));
414 static assert(!isSeedable!(validRng));
415
416 struct seedRng
417 {
418 @property uint front() {return 0;}
419 @property bool empty() {return false;}
420 void popFront() {}
421 void seed(uint val){}
422 enum isUniformRandom = true;
423 }
424 static assert(isUniformRNG!(seedRng, uint));
425 static assert(isUniformRNG!(seedRng));
426 static assert(isSeedable!(seedRng, uint));
427 static assert(!isSeedable!(seedRng, ulong));
428 static assert(isSeedable!(seedRng));
429 }
430
431 /**
432 Linear Congruential generator. When m = 0, no modulus is used.
433 */
434 struct LinearCongruentialEngine(UIntType, UIntType a, UIntType c, UIntType m)
435 if (isUnsigned!UIntType)
436 {
437 ///Mark this as a Rng
438 enum bool isUniformRandom = true;
439 /// Does this generator have a fixed range? ($(D_PARAM true)).
440 enum bool hasFixedRange = true;
441 /// Lowest generated value (`1` if $(D c == 0), `0` otherwise).
442 enum UIntType min = ( c == 0 ? 1 : 0 );
443 /// Highest generated value ($(D modulus - 1)).
444 enum UIntType max = m - 1;
445 /**
446 The parameters of this distribution. The random number is $(D_PARAM x
447 = (x * multipler + increment) % modulus).
448 */
449 enum UIntType multiplier = a;
450 ///ditto
451 enum UIntType increment = c;
452 ///ditto
453 enum UIntType modulus = m;
454
455 static assert(isIntegral!(UIntType));
456 static assert(m == 0 || a < m);
457 static assert(m == 0 || c < m);
458 static assert(m == 0 ||
459 (cast(ulong) a * (m-1) + c) % m == (c < a ? c - a + m : c - a));
460
461 // Check for maximum range
462 private static ulong gcd(ulong a, ulong b) @safe pure nothrow @nogc
463 {
464 while (b)
465 {
466 auto t = b;
467 b = a % b;
468 a = t;
469 }
470 return a;
471 }
472
473 private static ulong primeFactorsOnly(ulong n) @safe pure nothrow @nogc
474 {
475 ulong result = 1;
476 ulong iter = 2;
477 for (; n >= iter * iter; iter += 2 - (iter == 2))
478 {
479 if (n % iter) continue;
480 result *= iter;
481 do
482 {
483 n /= iter;
484 } while (n % iter == 0);
485 }
486 return result * n;
487 }
488
489 @safe pure nothrow unittest
490 {
491 static assert(primeFactorsOnly(100) == 10);
492 //writeln(primeFactorsOnly(11));
493 static assert(primeFactorsOnly(11) == 11);
494 static assert(primeFactorsOnly(7 * 7 * 7 * 11 * 15 * 11) == 7 * 11 * 15);
495 static assert(primeFactorsOnly(129 * 2) == 129 * 2);
496 // enum x = primeFactorsOnly(7 * 7 * 7 * 11 * 15);
497 // static assert(x == 7 * 11 * 15);
498 }
499
500 private static bool properLinearCongruentialParameters(ulong m,
501 ulong a, ulong c) @safe pure nothrow @nogc
502 {
503 if (m == 0)
504 {
505 static if (is(UIntType == uint))
506 {
507 // Assume m is uint.max + 1
508 m = (1uL << 32);
509 }
510 else
511 {
512 return false;
513 }
514 }
515 // Bounds checking
516 if (a == 0 || a >= m || c >= m) return false;
517 // c and m are relatively prime
518 if (c > 0 && gcd(c, m) != 1) return false;
519 // a - 1 is divisible by all prime factors of m
520 if ((a - 1) % primeFactorsOnly(m)) return false;
521 // if a - 1 is multiple of 4, then m is a multiple of 4 too.
522 if ((a - 1) % 4 == 0 && m % 4) return false;
523 // Passed all tests
524 return true;
525 }
526
527 // check here
528 static assert(c == 0 || properLinearCongruentialParameters(m, a, c),
529 "Incorrect instantiation of LinearCongruentialEngine");
530
531 /**
532 Constructs a $(D_PARAM LinearCongruentialEngine) generator seeded with
533 `x0`.
534 */
535 this(UIntType x0) @safe pure nothrow @nogc
536 {
537 seed(x0);
538 }
539
540 /**
541 (Re)seeds the generator.
542 */
543 void seed(UIntType x0 = 1) @safe pure nothrow @nogc
544 {
545 _x = modulus ? (x0 % modulus) : x0;
546 static if (c == 0)
547 {
548 //Necessary to prevent generator from outputting an endless series of zeroes.
549 if (_x == 0)
550 _x = max;
551 }
552 popFront();
553 }
554
555 /**
556 Advances the random sequence.
557 */
558 void popFront() @safe pure nothrow @nogc
559 {
560 static if (m)
561 {
562 static if (is(UIntType == uint) && m == uint.max)
563 {
564 immutable ulong
565 x = (cast(ulong) a * _x + c),
566 v = x >> 32,
567 w = x & uint.max;
568 immutable y = cast(uint)(v + w);
569 _x = (y < v || y == uint.max) ? (y + 1) : y;
570 }
571 else static if (is(UIntType == uint) && m == int.max)
572 {
573 immutable ulong
574 x = (cast(ulong) a * _x + c),
575 v = x >> 31,
576 w = x & int.max;
577 immutable uint y = cast(uint)(v + w);
578 _x = (y >= int.max) ? (y - int.max) : y;
579 }
580 else
581 {
582 _x = cast(UIntType) ((cast(ulong) a * _x + c) % m);
583 }
584 }
585 else
586 {
587 _x = a * _x + c;
588 }
589 }
590
591 /**
592 Returns the current number in the random sequence.
593 */
594 @property UIntType front() const @safe pure nothrow @nogc
595 {
596 return _x;
597 }
598
599 ///
600 @property typeof(this) save() const @safe pure nothrow @nogc
601 {
602 return this;
603 }
604
605 /**
606 Always `false` (random generators are infinite ranges).
607 */
608 enum bool empty = false;
609
610 // https://issues.dlang.org/show_bug.cgi?id=21610
611 static if (m)
612 {
613 private UIntType _x = (a + c) % m;
614 }
615 else
616 {
617 private UIntType _x = a + c;
618 }
619 }
620
621 /// Declare your own linear congruential engine
622 @safe unittest
623 {
624 alias CPP11LCG = LinearCongruentialEngine!(uint, 48271, 0, 2_147_483_647);
625
626 // seed with a constant
627 auto rnd = CPP11LCG(42);
628 auto n = rnd.front; // same for each run
629 assert(n == 2027382);
630 }
631
632 /// Declare your own linear congruential engine
633 @safe unittest
634 {
635 // glibc's LCG
636 alias GLibcLCG = LinearCongruentialEngine!(uint, 1103515245, 12345, 2_147_483_648);
637
638 // Seed with an unpredictable value
639 auto rnd = GLibcLCG(unpredictableSeed);
640 auto n = rnd.front; // different across runs
641 }
642
643 /// Declare your own linear congruential engine
644 @safe unittest
645 {
646 // Visual C++'s LCG
647 alias MSVCLCG = LinearCongruentialEngine!(uint, 214013, 2531011, 0);
648
649 // seed with a constant
650 auto rnd = MSVCLCG(1);
651 auto n = rnd.front; // same for each run
652 assert(n == 2745024);
653 }
654
655 // Ensure that unseeded LCGs produce correct values
656 @safe unittest
657 {
658 alias LGE = LinearCongruentialEngine!(uint, 10000, 19682, 19683);
659
660 LGE rnd;
661 assert(rnd.front == 9999);
662 }
663
664 /**
665 Define $(D_PARAM LinearCongruentialEngine) generators with well-chosen
666 parameters. `MinstdRand0` implements Park and Miller's "minimal
667 standard" $(HTTP
668 wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator,
669 generator) that uses 16807 for the multiplier. `MinstdRand`
670 implements a variant that has slightly better spectral behavior by
671 using the multiplier 48271. Both generators are rather simplistic.
672 */
673 alias MinstdRand0 = LinearCongruentialEngine!(uint, 16_807, 0, 2_147_483_647);
674 /// ditto
675 alias MinstdRand = LinearCongruentialEngine!(uint, 48_271, 0, 2_147_483_647);
676
677 ///
678 @safe @nogc unittest
679 {
680 // seed with a constant
681 auto rnd0 = MinstdRand0(1);
682 auto n = rnd0.front;
683 // same for each run
684 assert(n == 16807);
685
686 // Seed with an unpredictable value
687 rnd0.seed(unpredictableSeed);
688 n = rnd0.front; // different across runs
689 }
690
691 @safe @nogc unittest
692 {
693 import std.range;
694 static assert(isForwardRange!MinstdRand);
695 static assert(isUniformRNG!MinstdRand);
696 static assert(isUniformRNG!MinstdRand0);
697 static assert(isUniformRNG!(MinstdRand, uint));
698 static assert(isUniformRNG!(MinstdRand0, uint));
699 static assert(isSeedable!MinstdRand);
700 static assert(isSeedable!MinstdRand0);
701 static assert(isSeedable!(MinstdRand, uint));
702 static assert(isSeedable!(MinstdRand0, uint));
703
704 // The correct numbers are taken from The Database of Integer Sequences
705 // http://www.research.att.com/~njas/sequences/eisBTfry00128.txt
706 enum ulong[20] checking0 = [
707 16807UL,282475249,1622650073,984943658,1144108930,470211272,
708 101027544,1457850878,1458777923,2007237709,823564440,1115438165,
709 1784484492,74243042,114807987,1137522503,1441282327,16531729,
710 823378840,143542612 ];
711 //auto rnd0 = MinstdRand0(1);
712 MinstdRand0 rnd0;
713
714 foreach (e; checking0)
715 {
716 assert(rnd0.front == e);
717 rnd0.popFront();
718 }
719 // Test the 10000th invocation
720 // Correct value taken from:
721 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf
722 rnd0.seed();
723 popFrontN(rnd0, 9999);
724 assert(rnd0.front == 1043618065);
725
726 // Test MinstdRand
727 enum ulong[6] checking = [48271UL,182605794,1291394886,1914720637,2078669041,
728 407355683];
729 //auto rnd = MinstdRand(1);
730 MinstdRand rnd;
731 foreach (e; checking)
732 {
733 assert(rnd.front == e);
734 rnd.popFront();
735 }
736
737 // Test the 10000th invocation
738 // Correct value taken from:
739 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf
740 rnd.seed();
741 popFrontN(rnd, 9999);
742 assert(rnd.front == 399268537);
743
744 // Check .save works
745 static foreach (Type; std.meta.AliasSeq!(MinstdRand0, MinstdRand))
746 {{
747 auto rnd1 = Type(123_456_789);
748 rnd1.popFront();
749 // https://issues.dlang.org/show_bug.cgi?id=15853
750 auto rnd2 = ((const ref Type a) => a.save())(rnd1);
751 assert(rnd1 == rnd2);
752 // Enable next test when RNGs are reference types
753 version (none) { assert(rnd1 !is rnd2); }
754 for (auto i = 0; i < 3; i++, rnd1.popFront, rnd2.popFront)
755 assert(rnd1.front() == rnd2.front());
756 }}
757 }
758
759 @safe @nogc unittest
760 {
761 auto rnd0 = MinstdRand0(MinstdRand0.modulus);
762 auto n = rnd0.front;
763 rnd0.popFront();
764 assert(n != rnd0.front);
765 }
766
767 /**
768 The $(LINK2 https://en.wikipedia.org/wiki/Mersenne_Twister, Mersenne Twister) generator.
769 */
770 struct MersenneTwisterEngine(UIntType, size_t w, size_t n, size_t m, size_t r,
771 UIntType a, size_t u, UIntType d, size_t s,
772 UIntType b, size_t t,
773 UIntType c, size_t l, UIntType f)
774 if (isUnsigned!UIntType)
775 {
776 static assert(0 < w && w <= UIntType.sizeof * 8);
777 static assert(1 <= m && m <= n);
778 static assert(0 <= r && 0 <= u && 0 <= s && 0 <= t && 0 <= l);
779 static assert(r <= w && u <= w && s <= w && t <= w && l <= w);
780 static assert(0 <= a && 0 <= b && 0 <= c);
781 static assert(n <= ptrdiff_t.max);
782
783 ///Mark this as a Rng
784 enum bool isUniformRandom = true;
785
786 /**
787 Parameters for the generator.
788 */
789 enum size_t wordSize = w;
790 enum size_t stateSize = n; /// ditto
791 enum size_t shiftSize = m; /// ditto
792 enum size_t maskBits = r; /// ditto
793 enum UIntType xorMask = a; /// ditto
794 enum size_t temperingU = u; /// ditto
795 enum UIntType temperingD = d; /// ditto
796 enum size_t temperingS = s; /// ditto
797 enum UIntType temperingB = b; /// ditto
798 enum size_t temperingT = t; /// ditto
799 enum UIntType temperingC = c; /// ditto
800 enum size_t temperingL = l; /// ditto
801 enum UIntType initializationMultiplier = f; /// ditto
802
803 /// Smallest generated value (0).
804 enum UIntType min = 0;
805 /// Largest generated value.
806 enum UIntType max = UIntType.max >> (UIntType.sizeof * 8u - w);
807 // note, `max` also serves as a bitmask for the lowest `w` bits
808 static assert(a <= max && b <= max && c <= max && f <= max);
809
810 /// The default seed value.
811 enum UIntType defaultSeed = 5489u;
812
813 // Bitmasks used in the 'twist' part of the algorithm
814 private enum UIntType lowerMask = (cast(UIntType) 1u << r) - 1,
815 upperMask = (~lowerMask) & this.max;
816
817 /*
818 Collection of all state variables
819 used by the generator
820 */
821 private struct State
822 {
823 /*
824 State array of the generator. This
825 is iterated through backwards (from
826 last element to first), providing a
827 few extra compiler optimizations by
828 comparison to the forward iteration
829 used in most implementations.
830 */
831 UIntType[n] data;
832
833 /*
834 Cached copy of most recently updated
835 element of `data` state array, ready
836 to be tempered to generate next
837 `front` value
838 */
839 UIntType z;
840
841 /*
842 Most recently generated random variate
843 */
844 UIntType front;
845
846 /*
847 Index of the entry in the `data`
848 state array that will be twisted
849 in the next `popFront()` call
850 */
851 size_t index;
852 }
853
854 /*
855 State variables used by the generator;
856 initialized to values equivalent to
857 explicitly seeding the generator with
858 `defaultSeed`
859 */
860 private State state = defaultState();
861 /* NOTE: the above is a workaround to ensure
862 backwards compatibility with the original
863 implementation, which permitted implicit
864 construction. With `@disable this();`
865 it would not be necessary. */
866
867 /**
868 Constructs a MersenneTwisterEngine object.
869 */
870 this(UIntType value) @safe pure nothrow @nogc
871 {
872 seed(value);
873 }
874
875 /**
876 Generates the default initial state for a Mersenne
877 Twister; equivalent to the internal state obtained
878 by calling `seed(defaultSeed)`
879 */
880 private static State defaultState() @safe pure nothrow @nogc
881 {
882 if (!__ctfe) assert(false);
883 State mtState;
884 seedImpl(defaultSeed, mtState);
885 return mtState;
886 }
887
888 /**
889 Seeds a MersenneTwisterEngine object.
890 Note:
891 This seed function gives 2^w starting points (the lowest w bits of
892 the value provided will be used). To allow the RNG to be started
893 in any one of its internal states use the seed overload taking an
894 InputRange.
895 */
896 void seed()(UIntType value = defaultSeed) @safe pure nothrow @nogc
897 {
898 this.seedImpl(value, this.state);
899 }
900
901 /**
902 Implementation of the seeding mechanism, which
903 can be used with an arbitrary `State` instance
904 */
905 private static void seedImpl(UIntType value, ref State mtState) @nogc
906 {
907 mtState.data[$ - 1] = value;
908 static if (this.max != UIntType.max)
909 {
910 mtState.data[$ - 1] &= this.max;
911 }
912
913 foreach_reverse (size_t i, ref e; mtState.data[0 .. $ - 1])
914 {
915 e = f * (mtState.data[i + 1] ^ (mtState.data[i + 1] >> (w - 2))) + cast(UIntType)(n - (i + 1));
916 static if (this.max != UIntType.max)
917 {
918 e &= this.max;
919 }
920 }
921
922 mtState.index = n - 1;
923
924 /* double popFront() to guarantee both `mtState.z`
925 and `mtState.front` are derived from the newly
926 set values in `mtState.data` */
927 MersenneTwisterEngine.popFrontImpl(mtState);
928 MersenneTwisterEngine.popFrontImpl(mtState);
929 }
930
931 /**
932 Seeds a MersenneTwisterEngine object using an InputRange.
933
934 Throws:
935 `Exception` if the InputRange didn't provide enough elements to seed the generator.
936 The number of elements required is the 'n' template parameter of the MersenneTwisterEngine struct.
937 */
938 void seed(T)(T range) if (isInputRange!T && is(immutable ElementType!T == immutable UIntType))
939 {
940 this.seedImpl(range, this.state);
941 }
942
943 /**
944 Implementation of the range-based seeding mechanism,
945 which can be used with an arbitrary `State` instance
946 */
947 private static void seedImpl(T)(T range, ref State mtState)
948 if (isInputRange!T && is(immutable ElementType!T == immutable UIntType))
949 {
950 size_t j;
951 for (j = 0; j < n && !range.empty; ++j, range.popFront())
952 {
953 ptrdiff_t idx = n - j - 1;
954 mtState.data[idx] = range.front;
955 }
956
957 mtState.index = n - 1;
958
959 if (range.empty && j < n)
960 {
961 import core.internal.string : UnsignedStringBuf, unsignedToTempString;
962
963 UnsignedStringBuf buf = void;
964 string s = "MersenneTwisterEngine.seed: Input range didn't provide enough elements: Need ";
965 s ~= unsignedToTempString(n, buf) ~ " elements.";
966 throw new Exception(s);
967 }
968
969 /* double popFront() to guarantee both `mtState.z`
970 and `mtState.front` are derived from the newly
971 set values in `mtState.data` */
972 MersenneTwisterEngine.popFrontImpl(mtState);
973 MersenneTwisterEngine.popFrontImpl(mtState);
974 }
975
976 /**
977 Advances the generator.
978 */
979 void popFront() @safe pure nothrow @nogc
980 {
981 this.popFrontImpl(this.state);
982 }
983
984 /*
985 Internal implementation of `popFront()`, which
986 can be used with an arbitrary `State` instance
987 */
988 private static void popFrontImpl(ref State mtState) @nogc
989 {
990 /* This function blends two nominally independent
991 processes: (i) calculation of the next random
992 variate `mtState.front` from the cached previous
993 `data` entry `z`, and (ii) updating the value
994 of `data[index]` and `mtState.z` and advancing
995 the `index` value to the next in sequence.
996
997 By interweaving the steps involved in these
998 procedures, rather than performing each of
999 them separately in sequence, the variables
1000 are kept 'hot' in CPU registers, allowing
1001 for significantly faster performance. */
1002 ptrdiff_t index = mtState.index;
1003 ptrdiff_t next = index - 1;
1004 if (next < 0)
1005 next = n - 1;
1006 auto z = mtState.z;
1007 ptrdiff_t conj = index - m;
1008 if (conj < 0)
1009 conj = index - m + n;
1010
1011 static if (d == UIntType.max)
1012 {
1013 z ^= (z >> u);
1014 }
1015 else
1016 {
1017 z ^= (z >> u) & d;
1018 }
1019
1020 auto q = mtState.data[index] & upperMask;
1021 auto p = mtState.data[next] & lowerMask;
1022 z ^= (z << s) & b;
1023 auto y = q | p;
1024 auto x = y >> 1;
1025 z ^= (z << t) & c;
1026 if (y & 1)
1027 x ^= a;
1028 auto e = mtState.data[conj] ^ x;
1029 z ^= (z >> l);
1030 mtState.z = mtState.data[index] = e;
1031 mtState.index = next;
1032
1033 /* technically we should take the lowest `w`
1034 bits here, but if the tempering bitmasks
1035 `b` and `c` are set correctly, this should
1036 be unnecessary */
1037 mtState.front = z;
1038 }
1039
1040 /**
1041 Returns the current random value.
1042 */
1043 @property UIntType front() @safe const pure nothrow @nogc
1044 {
1045 return this.state.front;
1046 }
1047
1048 ///
1049 @property typeof(this) save() @safe const pure nothrow @nogc
1050 {
1051 return this;
1052 }
1053
1054 /**
1055 Always `false`.
1056 */
1057 enum bool empty = false;
1058 }
1059
1060 ///
1061 @safe unittest
1062 {
1063 // seed with a constant
1064 Mt19937 gen;
1065 auto n = gen.front; // same for each run
1066 assert(n == 3499211612);
1067
1068 // Seed with an unpredictable value
1069 gen.seed(unpredictableSeed);
1070 n = gen.front; // different across runs
1071 }
1072
1073 /**
1074 A `MersenneTwisterEngine` instantiated with the parameters of the
1075 original engine $(HTTP math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html,
1076 MT19937), generating uniformly-distributed 32-bit numbers with a
1077 period of 2 to the power of 19937. Recommended for random number
1078 generation unless memory is severely restricted, in which case a $(LREF
1079 LinearCongruentialEngine) would be the generator of choice.
1080 */
1081 alias Mt19937 = MersenneTwisterEngine!(uint, 32, 624, 397, 31,
1082 0x9908b0df, 11, 0xffffffff, 7,
1083 0x9d2c5680, 15,
1084 0xefc60000, 18, 1_812_433_253);
1085
1086 ///
1087 @safe @nogc unittest
1088 {
1089 // seed with a constant
1090 Mt19937 gen;
1091 auto n = gen.front; // same for each run
1092 assert(n == 3499211612);
1093
1094 // Seed with an unpredictable value
1095 gen.seed(unpredictableSeed);
1096 n = gen.front; // different across runs
1097 }
1098
1099 @safe nothrow unittest
1100 {
1101 import std.algorithm;
1102 import std.range;
1103 static assert(isUniformRNG!Mt19937);
1104 static assert(isUniformRNG!(Mt19937, uint));
1105 static assert(isSeedable!Mt19937);
1106 static assert(isSeedable!(Mt19937, uint));
1107 static assert(isSeedable!(Mt19937, typeof(map!((a) => unpredictableSeed)(repeat(0)))));
1108 Mt19937 gen;
1109 assert(gen.front == 3499211612);
1110 popFrontN(gen, 9999);
1111 assert(gen.front == 4123659995);
1112 try { gen.seed(iota(624u)); } catch (Exception) { assert(false); }
1113 assert(gen.front == 3708921088u);
1114 popFrontN(gen, 9999);
1115 assert(gen.front == 165737292u);
1116 }
1117
1118 /**
1119 A `MersenneTwisterEngine` instantiated with the parameters of the
1120 original engine $(HTTP en.wikipedia.org/wiki/Mersenne_Twister,
1121 MT19937-64), generating uniformly-distributed 64-bit numbers with a
1122 period of 2 to the power of 19937.
1123 */
1124 alias Mt19937_64 = MersenneTwisterEngine!(ulong, 64, 312, 156, 31,
1125 0xb5026f5aa96619e9, 29, 0x5555555555555555, 17,
1126 0x71d67fffeda60000, 37,
1127 0xfff7eee000000000, 43, 6_364_136_223_846_793_005);
1128
1129 ///
1130 @safe @nogc unittest
1131 {
1132 // Seed with a constant
1133 auto gen = Mt19937_64(12345);
1134 auto n = gen.front; // same for each run
1135 assert(n == 6597103971274460346);
1136
1137 // Seed with an unpredictable value
1138 gen.seed(unpredictableSeed!ulong);
1139 n = gen.front; // different across runs
1140 }
1141
1142 @safe nothrow unittest
1143 {
1144 import std.algorithm;
1145 import std.range;
1146 static assert(isUniformRNG!Mt19937_64);
1147 static assert(isUniformRNG!(Mt19937_64, ulong));
1148 static assert(isSeedable!Mt19937_64);
1149 static assert(isSeedable!(Mt19937_64, ulong));
1150 static assert(isSeedable!(Mt19937_64, typeof(map!((a) => unpredictableSeed!ulong)(repeat(0)))));
1151 Mt19937_64 gen;
1152 assert(gen.front == 14514284786278117030uL);
1153 popFrontN(gen, 9999);
1154 assert(gen.front == 9981545732273789042uL);
1155 try { gen.seed(iota(312uL)); } catch (Exception) { assert(false); }
1156 assert(gen.front == 14660652410669508483uL);
1157 popFrontN(gen, 9999);
1158 assert(gen.front == 15956361063660440239uL);
1159 }
1160
1161 @safe unittest
1162 {
1163 import std.algorithm;
1164 import std.exception;
1165 import std.range;
1166
1167 Mt19937 gen;
1168
1169 assertThrown(gen.seed(map!((a) => 123_456_789U)(repeat(0, 623))));
1170
1171 gen.seed(123_456_789U.repeat(624));
1172 //infinite Range
1173 gen.seed(123_456_789U.repeat);
1174 }
1175
1176 @safe @nogc pure nothrow unittest
1177 {
1178 uint a, b;
1179 {
1180 Mt19937 gen;
1181 a = gen.front;
1182 }
1183 {
1184 Mt19937 gen;
1185 gen.popFront();
1186 //popFrontN(gen, 1); // skip 1 element
1187 b = gen.front;
1188 }
1189 assert(a != b);
1190 }
1191
1192 @safe @nogc unittest
1193 {
1194 // Check .save works
1195 static foreach (Type; std.meta.AliasSeq!(Mt19937, Mt19937_64))
1196 {{
1197 auto gen1 = Type(123_456_789);
1198 gen1.popFront();
1199 // https://issues.dlang.org/show_bug.cgi?id=15853
1200 auto gen2 = ((const ref Type a) => a.save())(gen1);
1201 assert(gen1 == gen2); // Danger, Will Robinson -- no opEquals for MT
1202 // Enable next test when RNGs are reference types
1203 version (none) { assert(gen1 !is gen2); }
1204 for (auto i = 0; i < 100; i++, gen1.popFront, gen2.popFront)
1205 assert(gen1.front() == gen2.front());
1206 }}
1207 }
1208
1209 // https://issues.dlang.org/show_bug.cgi?id=11690
1210 @safe @nogc pure nothrow unittest
1211 {
1212 alias MT(UIntType, uint w) = MersenneTwisterEngine!(UIntType, w, 624, 397, 31,
1213 0x9908b0df, 11, 0xffffffff, 7,
1214 0x9d2c5680, 15,
1215 0xefc60000, 18, 1812433253);
1216
1217 static immutable ulong[] expectedFirstValue = [3499211612uL, 3499211612uL,
1218 171143175841277uL, 1145028863177033374uL];
1219
1220 static immutable ulong[] expected10kValue = [4123659995uL, 4123659995uL,
1221 51991688252792uL, 3031481165133029945uL];
1222
1223 static foreach (i, R; std.meta.AliasSeq!(MT!(uint, 32), MT!(ulong, 32), MT!(ulong, 48), MT!(ulong, 64)))
1224 {{
1225 auto a = R();
1226 a.seed(a.defaultSeed); // checks that some alternative paths in `seed` are utilized
1227 assert(a.front == expectedFirstValue[i]);
1228 a.popFrontN(9999);
1229 assert(a.front == expected10kValue[i]);
1230 }}
1231 }
1232
1233 /++
1234 Xorshift generator.
1235 Implemented according to $(HTTP www.jstatsoft.org/v08/i14/paper, Xorshift RNGs)
1236 (Marsaglia, 2003) when the size is small. For larger sizes the generator
1237 uses Sebastino Vigna's optimization of using an index to avoid needing
1238 to rotate the internal array.
1239
1240 Period is `2 ^^ nbits - 1` except for a legacy 192-bit uint version (see
1241 note below).
1242
1243 Params:
1244 UIntType = Word size of this xorshift generator and the return type
1245 of `opCall`.
1246 nbits = The number of bits of state of this generator. This must be
1247 a positive multiple of the size in bits of UIntType. If
1248 nbits is large this struct may occupy slightly more memory
1249 than this so it can use a circular counter instead of
1250 shifting the entire array.
1251 sa = The direction and magnitude of the 1st shift. Positive
1252 means left, negative means right.
1253 sb = The direction and magnitude of the 2nd shift. Positive
1254 means left, negative means right.
1255 sc = The direction and magnitude of the 3rd shift. Positive
1256 means left, negative means right.
1257
1258 Note:
1259 For historical compatibility when `nbits == 192` and `UIntType` is `uint`
1260 a legacy hybrid PRNG is used consisting of a 160-bit xorshift combined
1261 with a 32-bit counter. This combined generator has period equal to the
1262 least common multiple of `2^^160 - 1` and `2^^32`.
1263
1264 Previous versions of `XorshiftEngine` did not provide any mechanism to specify
1265 the directions of the shifts, taking each shift as an unsigned magnitude.
1266 For backwards compatibility, because three shifts in the same direction
1267 cannot result in a full-period XorshiftEngine, when all three of `sa`, `sb`,
1268 `sc, are positive `XorshiftEngine` treats them as unsigned magnitudes and
1269 uses shift directions to match the old behavior of `XorshiftEngine`.
1270
1271 Not every set of shifts results in a full-period xorshift generator.
1272 The template does not currently at compile-time perform a full check
1273 for maximum period but in a future version might reject parameters
1274 resulting in shorter periods.
1275 +/
1276 struct XorshiftEngine(UIntType, uint nbits, int sa, int sb, int sc)
1277 if (isUnsigned!UIntType && !(sa > 0 && sb > 0 && sc > 0))
1278 {
1279 static assert(nbits > 0 && nbits % (UIntType.sizeof * 8) == 0,
1280 "nbits must be an even multiple of "~UIntType.stringof
1281 ~".sizeof * 8, not "~nbits.stringof~".");
1282
1283 static assert(!((sa >= 0) == (sb >= 0) && (sa >= 0) == (sc >= 0))
1284 && (sa * sb * sc != 0),
1285 "shifts cannot be zero and cannot all be in same direction: cannot be ["
1286 ~sa.stringof~", "~sb.stringof~", "~sc.stringof~"].");
1287
1288 static assert(sa != sb && sb != sc,
1289 "consecutive shifts with the same magnitude and direction would partially or completely cancel!");
1290
1291 static assert(UIntType.sizeof == uint.sizeof || UIntType.sizeof == ulong.sizeof,
1292 "XorshiftEngine currently does not support type " ~ UIntType.sizeof
1293 ~ " because it does not have a `seed` implementation for arrays "
1294 ~ " of element types other than uint and ulong.");
1295
1296 public:
1297 ///Mark this as a Rng
1298 enum bool isUniformRandom = true;
1299 /// Always `false` (random generators are infinite ranges).
1300 enum empty = false;
1301 /// Smallest generated value.
1302 enum UIntType min = _state.length == 1 ? 1 : 0;
1303 /// Largest generated value.
1304 enum UIntType max = UIntType.max;
1305
1306
1307 private:
1308 // Legacy 192 bit uint hybrid counter/xorshift.
1309 enum bool isLegacy192Bit = UIntType.sizeof == uint.sizeof && nbits == 192;
1310
1311 // Shift magnitudes.
1312 enum a = (sa < 0 ? -sa : sa);
1313 enum b = (sb < 0 ? -sb : sb);
1314 enum c = (sc < 0 ? -sc : sc);
1315
1316 // Shift expressions to mix in.
1317 enum shiftA(string expr) = `((`~expr~`) `~(sa > 0 ? `<< a)` : ` >>> a)`);
1318 enum shiftB(string expr) = `((`~expr~`) `~(sb > 0 ? `<< b)` : ` >>> b)`);
1319 enum shiftC(string expr) = `((`~expr~`) `~(sc > 0 ? `<< c)` : ` >>> c)`);
1320
1321 enum N = nbits / (UIntType.sizeof * 8);
1322
1323 // For N <= 2 it is strictly worse to use an index.
1324 // Informal third-party benchmarks suggest that for `ulong` it is
1325 // faster to use an index when N == 4. For `uint` we err on the side
1326 // of not increasing the struct's size and only switch to the other
1327 // implementation when N > 4.
1328 enum useIndex = !isLegacy192Bit && (UIntType.sizeof >= ulong.sizeof ? N > 3 : N > 4);
1329 static if (useIndex)
1330 {
1331 enum initialIndex = N - 1;
1332 uint _index = initialIndex;
1333 }
1334
1335 static if (N == 1 && UIntType.sizeof <= uint.sizeof)
1336 {
1337 UIntType[N] _state = [cast(UIntType) 2_463_534_242];
1338 }
1339 else static if (isLegacy192Bit)
1340 {
1341 UIntType[N] _state = [123_456_789, 362_436_069, 521_288_629, 88_675_123, 5_783_321, 6_615_241];
1342 UIntType value_;
1343 }
1344 else static if (N <= 5 && UIntType.sizeof <= uint.sizeof)
1345 {
1346 UIntType[N] _state = [
1347 cast(UIntType) 123_456_789,
1348 cast(UIntType) 362_436_069,
1349 cast(UIntType) 521_288_629,
1350 cast(UIntType) 88_675_123,
1351 cast(UIntType) 5_783_321][0 .. N];
1352 }
1353 else
1354 {
1355 UIntType[N] _state = ()
1356 {
1357 static if (UIntType.sizeof < ulong.sizeof)
1358 {
1359 uint x0 = 123_456_789;
1360 enum uint m = 1_812_433_253U;
1361 }
1362 else static if (UIntType.sizeof <= ulong.sizeof)
1363 {
1364 ulong x0 = 123_456_789;
1365 enum ulong m = 6_364_136_223_846_793_005UL;
1366 }
1367 else
1368 {
1369 static assert(0, "Phobos Error: Xorshift has no instantiation rule for "
1370 ~ UIntType.stringof);
1371 }
1372 enum uint rshift = typeof(x0).sizeof * 8 - 2;
1373 UIntType[N] result = void;
1374 foreach (i, ref e; result)
1375 {
1376 e = cast(UIntType) (x0 = (m * (x0 ^ (x0 >>> rshift)) + i + 1));
1377 if (e == 0)
1378 e = cast(UIntType) (i + 1);
1379 }
1380 return result;
1381 }();
1382 }
1383
1384
1385 public:
1386 /++
1387 Constructs a `XorshiftEngine` generator seeded with $(D_PARAM x0).
1388
1389 Params:
1390 x0 = value used to deterministically initialize internal state
1391 +/
1392 this()(UIntType x0) @safe pure nothrow @nogc
1393 {
1394 seed(x0);
1395 }
1396
1397
1398 /++
1399 (Re)seeds the generator.
1400
1401 Params:
1402 x0 = value used to deterministically initialize internal state
1403 +/
1404 void seed()(UIntType x0) @safe pure nothrow @nogc
1405 {
1406 static if (useIndex)
1407 _index = initialIndex;
1408
1409 static if (UIntType.sizeof == uint.sizeof)
1410 {
1411 // Initialization routine from MersenneTwisterEngine.
1412 foreach (uint i, ref e; _state)
1413 {
1414 e = (x0 = (1_812_433_253U * (x0 ^ (x0 >> 30)) + i + 1));
1415 // Xorshift requires merely that not every word of the internal
1416 // array is 0. For historical compatibility the 32-bit word version
1417 // has the stronger requirement that not any word of the state
1418 // array is 0 after initial seeding.
1419 if (e == 0)
1420 e = (i + 1);
1421 }
1422 }
1423 else static if (UIntType.sizeof == ulong.sizeof)
1424 {
1425 static if (N > 1)
1426 {
1427 // Initialize array using splitmix64 as recommended by Sebastino Vigna.
1428 // By construction the array will not be all zeroes.
1429 // http://xoroshiro.di.unimi.it/splitmix64.c
1430 foreach (ref e; _state)
1431 {
1432 ulong z = (x0 += 0x9e37_79b9_7f4a_7c15UL);
1433 z = (z ^ (z >>> 30)) * 0xbf58_476d_1ce4_e5b9UL;
1434 z = (z ^ (z >>> 27)) * 0x94d0_49bb_1331_11ebUL;
1435 e = z ^ (z >>> 31);
1436 }
1437 }
1438 else
1439 {
1440 // Apply a transformation when N == 1 instead of just copying x0
1441 // directly because it's not unlikely that a user might initialize
1442 // a PRNG with small counting numbers (e.g. 1, 2, 3) that have the
1443 // statistically rare property of having only 1 or 2 non-zero bits.
1444 // Additionally we need to ensure that the internal state is not
1445 // entirely zero.
1446 if (x0 != 0)
1447 _state[0] = x0 * 6_364_136_223_846_793_005UL;
1448 else
1449 _state[0] = typeof(this).init._state[0];
1450 }
1451 }
1452 else
1453 {
1454 static assert(0, "Phobos Error: Xorshift has no `seed` implementation for "
1455 ~ UIntType.stringof);
1456 }
1457
1458 popFront();
1459 }
1460
1461
1462 /**
1463 * Returns the current number in the random sequence.
1464 */
1465 @property
1466 UIntType front() const @safe pure nothrow @nogc
1467 {
1468 static if (isLegacy192Bit)
1469 return value_;
1470 else static if (!useIndex)
1471 return _state[N-1];
1472 else
1473 return _state[_index];
1474 }
1475
1476
1477 /**
1478 * Advances the random sequence.
1479 */
1480 void popFront() @safe pure nothrow @nogc
1481 {
1482 alias s = _state;
1483 static if (isLegacy192Bit)
1484 {
1485 auto x = _state[0] ^ mixin(shiftA!`s[0]`);
1486 static foreach (i; 0 .. N-2)
1487 s[i] = s[i + 1];
1488 s[N-2] = s[N-2] ^ mixin(shiftC!`s[N-2]`) ^ x ^ mixin(shiftB!`x`);
1489 value_ = s[N-2] + (s[N-1] += 362_437);
1490 }
1491 else static if (N == 1)
1492 {
1493 s[0] ^= mixin(shiftA!`s[0]`);
1494 s[0] ^= mixin(shiftB!`s[0]`);
1495 s[0] ^= mixin(shiftC!`s[0]`);
1496 }
1497 else static if (!useIndex)
1498 {
1499 auto x = s[0] ^ mixin(shiftA!`s[0]`);
1500 static foreach (i; 0 .. N-1)
1501 s[i] = s[i + 1];
1502 s[N-1] = s[N-1] ^ mixin(shiftC!`s[N-1]`) ^ x ^ mixin(shiftB!`x`);
1503 }
1504 else
1505 {
1506 assert(_index < N); // Invariant.
1507 const sIndexMinus1 = s[_index];
1508 static if ((N & (N - 1)) == 0)
1509 _index = (_index + 1) & typeof(_index)(N - 1);
1510 else
1511 {
1512 if (++_index >= N)
1513 _index = 0;
1514 }
1515 auto x = s[_index];
1516 x ^= mixin(shiftA!`x`);
1517 s[_index] = sIndexMinus1 ^ mixin(shiftC!`sIndexMinus1`) ^ x ^ mixin(shiftB!`x`);
1518 }
1519 }
1520
1521
1522 /**
1523 * Captures a range state.
1524 */
1525 @property
1526 typeof(this) save() const @safe pure nothrow @nogc
1527 {
1528 return this;
1529 }
1530
1531 private:
1532 // Workaround for a DScanner bug. If we remove this `private:` DScanner
1533 // gives erroneous warnings about missing documentation for public symbols
1534 // later in the module.
1535 }
1536
1537 /// ditto
1538 template XorshiftEngine(UIntType, int bits, int a, int b, int c)
1539 if (isUnsigned!UIntType && a > 0 && b > 0 && c > 0)
1540 {
1541 // Compatibility with old parameterizations without explicit shift directions.
1542 static if (bits == UIntType.sizeof * 8)
1543 alias XorshiftEngine = .XorshiftEngine!(UIntType, bits, a, -b, c);//left, right, left
1544 else static if (bits == 192 && UIntType.sizeof == uint.sizeof)
1545 alias XorshiftEngine = .XorshiftEngine!(UIntType, bits, -a, b, c);//right, left, left
1546 else
1547 alias XorshiftEngine = .XorshiftEngine!(UIntType, bits, a, -b, -c);//left, right, right
1548 }
1549
1550 ///
1551 @safe unittest
1552 {
1553 alias Xorshift96 = XorshiftEngine!(uint, 96, 10, 5, 26);
1554 auto rnd = Xorshift96(42);
1555 auto num = rnd.front; // same for each run
1556 assert(num == 2704588748);
1557 }
1558
1559
1560 /**
1561 * Define `XorshiftEngine` generators with well-chosen parameters. See each bits examples of "Xorshift RNGs".
1562 * `Xorshift` is a Xorshift128's alias because 128bits implementation is mostly used.
1563 */
1564 alias Xorshift32 = XorshiftEngine!(uint, 32, 13, 17, 15) ;
1565 alias Xorshift64 = XorshiftEngine!(uint, 64, 10, 13, 10); /// ditto
1566 alias Xorshift96 = XorshiftEngine!(uint, 96, 10, 5, 26); /// ditto
1567 alias Xorshift128 = XorshiftEngine!(uint, 128, 11, 8, 19); /// ditto
1568 alias Xorshift160 = XorshiftEngine!(uint, 160, 2, 1, 4); /// ditto
1569 alias Xorshift192 = XorshiftEngine!(uint, 192, 2, 1, 4); /// ditto
1570 alias Xorshift = Xorshift128; /// ditto
1571
1572 ///
1573 @safe @nogc unittest
1574 {
1575 // Seed with a constant
1576 auto rnd = Xorshift(1);
1577 auto num = rnd.front; // same for each run
1578 assert(num == 1405313047);
1579
1580 // Seed with an unpredictable value
1581 rnd.seed(unpredictableSeed);
1582 num = rnd.front; // different across rnd
1583 }
1584
1585 @safe @nogc unittest
1586 {
1587 import std.range;
1588 static assert(isForwardRange!Xorshift);
1589 static assert(isUniformRNG!Xorshift);
1590 static assert(isUniformRNG!(Xorshift, uint));
1591 static assert(isSeedable!Xorshift);
1592 static assert(isSeedable!(Xorshift, uint));
1593
1594 static assert(Xorshift32.min == 1);
1595
1596 // Result from reference implementation.
1597 static ulong[][] checking = [
1598 [2463534242UL, 901999875, 3371835698, 2675058524, 1053936272, 3811264849,
1599 472493137, 3856898176, 2131710969, 2312157505],
1600 [362436069UL, 2113136921, 19051112, 3010520417, 951284840, 1213972223,
1601 3173832558, 2611145638, 2515869689, 2245824891],
1602 [521288629UL, 1950277231, 185954712, 1582725458, 3580567609, 2303633688,
1603 2394948066, 4108622809, 1116800180, 3357585673],
1604 [88675123UL, 3701687786, 458299110, 2500872618, 3633119408, 516391518,
1605 2377269574, 2599949379, 717229868, 137866584],
1606 [5783321UL, 393427209, 1947109840, 565829276, 1006220149, 971147905,
1607 1436324242, 2800460115, 1484058076, 3823330032],
1608 [0UL, 246875399, 3690007200, 1264581005, 3906711041, 1866187943, 2481925219,
1609 2464530826, 1604040631, 3653403911],
1610 [16749904790159980466UL, 14489774923612894650UL, 148813570191443371UL,
1611 6529783008780612886UL, 10182425759614080046UL, 16549659571055687844UL,
1612 542957868271744939UL, 9459127085596028450UL, 16001049981702441780UL,
1613 7351634712593111741],
1614 [14750058843113249055UL, 17731577314455387619UL, 1314705253499959044UL,
1615 3113030620614841056UL, 9468075444678629182UL, 13962152036600088141UL,
1616 9030205609946043947UL, 1856726150434672917UL, 8098922200110395314UL,
1617 2772699174618556175UL],
1618 ];
1619
1620 alias XorshiftTypes = std.meta.AliasSeq!(Xorshift32, Xorshift64, Xorshift96,
1621 Xorshift128, Xorshift160, Xorshift192, Xorshift64_64, Xorshift128_64);
1622
1623 foreach (I, Type; XorshiftTypes)
1624 {
1625 Type rnd;
1626
1627 foreach (e; checking[I])
1628 {
1629 assert(rnd.front == e);
1630 rnd.popFront();
1631 }
1632 }
1633
1634 // Check .save works
1635 foreach (Type; XorshiftTypes)
1636 {
1637 auto rnd1 = Type(123_456_789);
1638 rnd1.popFront();
1639 // https://issues.dlang.org/show_bug.cgi?id=15853
1640 auto rnd2 = ((const ref Type a) => a.save())(rnd1);
1641 assert(rnd1 == rnd2);
1642 // Enable next test when RNGs are reference types
1643 version (none) { assert(rnd1 !is rnd2); }
1644 for (auto i = 0; i <= Type.sizeof / 4; i++, rnd1.popFront, rnd2.popFront)
1645 assert(rnd1.front() == rnd2.front());
1646 }
1647 }
1648
1649
1650 /* A complete list of all pseudo-random number generators implemented in
1651 * std.random. This can be used to confirm that a given function or
1652 * object is compatible with all the pseudo-random number generators
1653 * available. It is enabled only in unittest mode.
1654 */
1655 @safe @nogc unittest
1656 {
1657 foreach (Rng; PseudoRngTypes)
1658 {
1659 static assert(isUniformRNG!Rng);
1660 auto rng = Rng(123_456_789);
1661 }
1662 }
1663
1664 version (CRuntime_Bionic)
1665 version = SecureARC4Random; // ChaCha20
1666 version (Darwin)
1667 version = SecureARC4Random; // AES
1668 version (OpenBSD)
1669 version = SecureARC4Random; // ChaCha20
1670 version (NetBSD)
1671 version = SecureARC4Random; // ChaCha20
1672
1673 version (CRuntime_UClibc)
1674 version = LegacyARC4Random; // ARC4
1675 version (FreeBSD)
1676 version = LegacyARC4Random; // ARC4
1677 version (DragonFlyBSD)
1678 version = LegacyARC4Random; // ARC4
1679 version (BSD)
1680 version = LegacyARC4Random; // Unknown implementation
1681
1682 // For the current purpose of unpredictableSeed the difference between
1683 // a secure arc4random implementation and a legacy implementation is
1684 // unimportant. The source code documents this distinction in case in the
1685 // future Phobos is altered to require cryptographically secure sources
1686 // of randomness, and also so other people reading this source code (as
1687 // Phobos is often looked to as an example of good D programming practices)
1688 // do not mistakenly use insecure versions of arc4random in contexts where
1689 // cryptographically secure sources of randomness are needed.
1690
1691 // Performance note: ChaCha20 is about 70% faster than ARC4, contrary to
1692 // what one might assume from it being more secure.
1693
1694 version (SecureARC4Random)
1695 version = AnyARC4Random;
1696 version (LegacyARC4Random)
1697 version = AnyARC4Random;
1698
1699 version (AnyARC4Random)
1700 {
1701 extern(C) private @nogc nothrow
1702 {
1703 uint arc4random() @safe;
1704 void arc4random_buf(scope void* buf, size_t nbytes) @system;
1705 }
1706 }
1707 else
1708 {
1709 private ulong bootstrapSeed() @nogc nothrow
1710 {
1711 // https://issues.dlang.org/show_bug.cgi?id=19580
1712 // previously used `ulong result = void` to start with an arbitary value
1713 // but using an uninitialized variable's value is undefined behavior
1714 // and enabled unwanted optimizations on non-DMD compilers.
1715 ulong result;
1716 enum ulong m = 0xc6a4_a793_5bd1_e995UL; // MurmurHash2_64A constant.
1717 void updateResult(ulong x)
1718 {
1719 x *= m;
1720 x = (x ^ (x >>> 47)) * m;
1721 result = (result ^ x) * m;
1722 }
1723 import core.thread : getpid, Thread;
1724 import core.time : MonoTime;
1725
1726 updateResult(cast(ulong) cast(void*) Thread.getThis());
1727 updateResult(cast(ulong) getpid());
1728 updateResult(cast(ulong) MonoTime.currTime.ticks);
1729 result = (result ^ (result >>> 47)) * m;
1730 return result ^ (result >>> 47);
1731 }
1732
1733 // If we don't have arc4random and we don't have RDRAND fall back to this.
1734 private ulong fallbackSeed() @nogc nothrow
1735 {
1736 // Bit avalanche function from MurmurHash3.
1737 static ulong fmix64(ulong k) @nogc nothrow pure @safe
1738 {
1739 k = (k ^ (k >>> 33)) * 0xff51afd7ed558ccd;
1740 k = (k ^ (k >>> 33)) * 0xc4ceb9fe1a85ec53;
1741 return k ^ (k >>> 33);
1742 }
1743 // Using SplitMix algorithm with constant gamma.
1744 // Chosen gamma is the odd number closest to 2^^64
1745 // divided by the silver ratio (1.0L + sqrt(2.0L)).
1746 enum gamma = 0x6a09e667f3bcc909UL;
1747 import core.atomic : has64BitCAS;
1748 static if (has64BitCAS)
1749 {
1750 import core.atomic : MemoryOrder, atomicLoad, atomicOp, atomicStore, cas;
1751 shared static ulong seed;
1752 shared static bool initialized;
1753 if (0 == atomicLoad!(MemoryOrder.raw)(initialized))
1754 {
1755 cas(&seed, 0UL, fmix64(bootstrapSeed()));
1756 atomicStore!(MemoryOrder.rel)(initialized, true);
1757 }
1758 return fmix64(atomicOp!"+="(seed, gamma));
1759 }
1760 else
1761 {
1762 static ulong seed;
1763 static bool initialized;
1764 if (!initialized)
1765 {
1766 seed = fmix64(bootstrapSeed());
1767 initialized = true;
1768 }
1769 return fmix64(seed += gamma);
1770 }
1771 }
1772 }
1773
1774 /**
1775 A "good" seed for initializing random number engines. Initializing
1776 with $(D_PARAM unpredictableSeed) makes engines generate different
1777 random number sequences every run.
1778
1779 Returns:
1780 A single unsigned integer seed value, different on each successive call
1781 Note:
1782 In general periodically 'reseeding' a PRNG does not improve its quality
1783 and in some cases may harm it. For an extreme example the Mersenne
1784 Twister has `2 ^^ 19937 - 1` distinct states but after `seed(uint)` is
1785 called it can only be in one of `2 ^^ 32` distinct states regardless of
1786 how excellent the source of entropy is.
1787 */
1788 @property uint unpredictableSeed() @trusted nothrow @nogc
1789 {
1790 version (AnyARC4Random)
1791 {
1792 return arc4random();
1793 }
1794 else
1795 {
1796 version (InlineAsm_X86_Any)
1797 {
1798 import core.cpuid : hasRdrand;
1799 if (hasRdrand)
1800 {
1801 uint result;
1802 asm @nogc nothrow
1803 {
1804 db 0x0f, 0xc7, 0xf0; // rdrand EAX
1805 jnc LnotUsingRdrand;
1806 mov result, EAX;
1807 // Some AMD CPUs shipped with bugs where RDRAND could fail
1808 // but still set the carry flag to 1. In those cases the
1809 // output will be -1.
1810 cmp EAX, 0xffff_ffff;
1811 jne LusingRdrand;
1812 // If result was -1 verify RDAND isn't constantly returning -1.
1813 db 0x0f, 0xc7, 0xf0;
1814 jnc LusingRdrand;
1815 cmp EAX, 0xffff_ffff;
1816 je LnotUsingRdrand;
1817 }
1818 LusingRdrand:
1819 return result;
1820 }
1821 LnotUsingRdrand:
1822 }
1823 return cast(uint) fallbackSeed();
1824 }
1825 }
1826
1827 /// ditto
1828 template unpredictableSeed(UIntType)
1829 if (isUnsigned!UIntType)
1830 {
1831 static if (is(UIntType == uint))
1832 alias unpredictableSeed = .unpredictableSeed;
1833 else static if (!is(Unqual!UIntType == UIntType))
1834 alias unpredictableSeed = .unpredictableSeed!(Unqual!UIntType);
1835 else
1836 /// ditto
1837 @property UIntType unpredictableSeed() @nogc nothrow @trusted
1838 {
1839 version (AnyARC4Random)
1840 {
1841 static if (UIntType.sizeof <= uint.sizeof)
1842 {
1843 return cast(UIntType) arc4random();
1844 }
1845 else
1846 {
1847 UIntType result = void;
1848 arc4random_buf(&result, UIntType.sizeof);
1849 return result;
1850 }
1851 }
1852 else
1853 {
1854 version (InlineAsm_X86_Any)
1855 {
1856 import core.cpuid : hasRdrand;
1857 if (hasRdrand)
1858 {
1859 static if (UIntType.sizeof <= uint.sizeof)
1860 {
1861 uint result;
1862 asm @nogc nothrow
1863 {
1864 db 0x0f, 0xc7, 0xf0; // rdrand EAX
1865 jnc LnotUsingRdrand;
1866 mov result, EAX;
1867 // Some AMD CPUs shipped with bugs where RDRAND could fail
1868 // but still set the carry flag to 1. In those cases the
1869 // output will be -1.
1870 cmp EAX, 0xffff_ffff;
1871 jne LusingRdrand;
1872 // If result was -1 verify RDAND isn't constantly returning -1.
1873 db 0x0f, 0xc7, 0xf0;
1874 jnc LusingRdrand;
1875 cmp EAX, 0xffff_ffff;
1876 je LnotUsingRdrand;
1877 }
1878 LusingRdrand:
1879 return cast(UIntType) result;
1880 }
1881 else version (D_InlineAsm_X86_64)
1882 {
1883 ulong result;
1884 asm @nogc nothrow
1885 {
1886 db 0x48, 0x0f, 0xc7, 0xf0; // rdrand RAX
1887 jnc LnotUsingRdrand;
1888 mov result, RAX;
1889 // Some AMD CPUs shipped with bugs where RDRAND could fail
1890 // but still set the carry flag to 1. In those cases the
1891 // output will be -1.
1892 cmp RAX, 0xffff_ffff_ffff_ffff;
1893 jne LusingRdrand;
1894 // If result was -1 verify RDAND isn't constantly returning -1.
1895 db 0x48, 0x0f, 0xc7, 0xf0;
1896 jnc LusingRdrand;
1897 cmp RAX, 0xffff_ffff_ffff_ffff;
1898 je LnotUsingRdrand;
1899 }
1900 LusingRdrand:
1901 return result;
1902 }
1903 else
1904 {
1905 uint resultLow, resultHigh;
1906 asm @nogc nothrow
1907 {
1908 db 0x0f, 0xc7, 0xf0; // rdrand EAX
1909 jnc LnotUsingRdrand;
1910 mov resultLow, EAX;
1911 db 0x0f, 0xc7, 0xf0; // rdrand EAX
1912 jnc LnotUsingRdrand;
1913 mov resultHigh, EAX;
1914 }
1915 if (resultLow != uint.max || resultHigh != uint.max) // Protect against AMD RDRAND bug.
1916 return ((cast(ulong) resultHigh) << 32) ^ resultLow;
1917 }
1918 }
1919 LnotUsingRdrand:
1920 }
1921 return cast(UIntType) fallbackSeed();
1922 }
1923 }
1924 }
1925
1926 ///
1927 @safe @nogc unittest
1928 {
1929 auto rnd = Random(unpredictableSeed);
1930 auto n = rnd.front;
1931 static assert(is(typeof(n) == uint));
1932 }
1933
1934 /**
1935 The "default", "favorite", "suggested" random number generator type on
1936 the current platform. It is an alias for one of the previously-defined
1937 generators. You may want to use it if (1) you need to generate some
1938 nice random numbers, and (2) you don't care for the minutiae of the
1939 method being used.
1940 */
1941
1942 alias Random = Mt19937;
1943
1944 @safe @nogc unittest
1945 {
1946 static assert(isUniformRNG!Random);
1947 static assert(isUniformRNG!(Random, uint));
1948 static assert(isSeedable!Random);
1949 static assert(isSeedable!(Random, uint));
1950 }
1951
1952 /**
1953 Global random number generator used by various functions in this
1954 module whenever no generator is specified. It is allocated per-thread
1955 and initialized to an unpredictable value for each thread.
1956
1957 Returns:
1958 A singleton instance of the default random number generator
1959 */
1960 @property ref Random rndGen() @safe nothrow @nogc
1961 {
1962 static Random result;
1963 static bool initialized;
1964 if (!initialized)
1965 {
1966 static if (isSeedable!(Random, ulong))
1967 result.seed(unpredictableSeed!ulong); // Avoid unnecessary copy.
1968 else static if (is(Random : MersenneTwisterEngine!Params, Params...))
1969 initMTEngine(result);
1970 else static if (isSeedable!(Random, uint))
1971 result.seed(unpredictableSeed!uint); // Avoid unnecessary copy.
1972 else
1973 result = Random(unpredictableSeed);
1974 initialized = true;
1975 }
1976 return result;
1977 }
1978
1979 ///
1980 @safe nothrow @nogc unittest
1981 {
1982 import std.algorithm.iteration : sum;
1983 import std.range : take;
1984 auto rnd = rndGen;
1985 assert(rnd.take(3).sum > 0);
1986 }
1987
1988 /+
1989 Initialize a 32-bit MersenneTwisterEngine from 64 bits of entropy.
1990 This is private and accepts no seed as a parameter, freeing the internal
1991 implementaton from any need for stability across releases.
1992 +/
1993 private void initMTEngine(MTEngine)(scope ref MTEngine mt)
1994 if (is(MTEngine : MersenneTwisterEngine!Params, Params...))
1995 {
1996 pragma(inline, false); // Called no more than once per thread by rndGen.
1997 ulong seed = unpredictableSeed!ulong;
1998 static if (is(typeof(mt.seed(seed))))
1999 {
2000 mt.seed(seed);
2001 }
2002 else
2003 {
2004 alias UIntType = typeof(mt.front());
2005 if (seed == 0) seed = -1; // Any number but 0 is fine.
2006 uint s0 = cast(uint) seed;
2007 uint s1 = cast(uint) (seed >> 32);
2008 foreach (ref e; mt.state.data)
2009 {
2010 //http://xoshiro.di.unimi.it/xoroshiro64starstar.c
2011 const tmp = s0 * 0x9E3779BB;
2012 e = ((tmp << 5) | (tmp >> (32 - 5))) * 5;
2013 static if (MTEngine.max != UIntType.max) { e &= MTEngine.max; }
2014
2015 const tmp1 = s0 ^ s1;
2016 s0 = ((s0 << 26) | (s0 >> (32 - 26))) ^ tmp1 ^ (tmp1 << 9);
2017 s1 = (tmp1 << 13) | (tmp1 >> (32 - 13));
2018 }
2019
2020 mt.state.index = mt.state.data.length - 1;
2021 // double popFront() to guarantee both `mt.state.z`
2022 // and `mt.state.front` are derived from the newly
2023 // set values in `mt.state.data`.
2024 mt.popFront();
2025 mt.popFront();
2026 }
2027 }
2028
2029 /**
2030 Generates a number between `a` and `b`. The `boundaries`
2031 parameter controls the shape of the interval (open vs. closed on
2032 either side). Valid values for `boundaries` are `"[]"`, $(D
2033 "$(LPAREN)]"), `"[$(RPAREN)"`, and `"()"`. The default interval
2034 is closed to the left and open to the right. The version that does not
2035 take `urng` uses the default generator `rndGen`.
2036
2037 Params:
2038 a = lower bound of the _uniform distribution
2039 b = upper bound of the _uniform distribution
2040 urng = (optional) random number generator to use;
2041 if not specified, defaults to `rndGen`
2042
2043 Returns:
2044 A single random variate drawn from the _uniform distribution
2045 between `a` and `b`, whose type is the common type of
2046 these parameters
2047 */
2048 auto uniform(string boundaries = "[)", T1, T2)
2049 (T1 a, T2 b)
2050 if (!is(CommonType!(T1, T2) == void))
2051 {
2052 return uniform!(boundaries, T1, T2, Random)(a, b, rndGen);
2053 }
2054
2055 ///
2056 @safe unittest
2057 {
2058 auto rnd = Random(unpredictableSeed);
2059
2060 // Generate an integer in [0, 1023]
2061 auto a = uniform(0, 1024, rnd);
2062 assert(0 <= a && a < 1024);
2063
2064 // Generate a float in [0, 1)
2065 auto b = uniform(0.0f, 1.0f, rnd);
2066 assert(0 <= b && b < 1);
2067
2068 // Generate a float in [0, 1]
2069 b = uniform!"[]"(0.0f, 1.0f, rnd);
2070 assert(0 <= b && b <= 1);
2071
2072 // Generate a float in (0, 1)
2073 b = uniform!"()"(0.0f, 1.0f, rnd);
2074 assert(0 < b && b < 1);
2075 }
2076
2077 /// Create an array of random numbers using range functions and UFCS
2078 @safe unittest
2079 {
2080 import std.array : array;
2081 import std.range : generate, takeExactly;
2082
2083 int[] arr = generate!(() => uniform(0, 100)).takeExactly(10).array;
2084 assert(arr.length == 10);
2085 assert(arr[0] >= 0 && arr[0] < 100);
2086 }
2087
2088 @safe unittest
2089 {
2090 MinstdRand0 gen;
2091 foreach (i; 0 .. 20)
2092 {
2093 auto x = uniform(0.0, 15.0, gen);
2094 assert(0 <= x && x < 15);
2095 }
2096 foreach (i; 0 .. 20)
2097 {
2098 auto x = uniform!"[]"('a', 'z', gen);
2099 assert('a' <= x && x <= 'z');
2100 }
2101
2102 foreach (i; 0 .. 20)
2103 {
2104 auto x = uniform('a', 'z', gen);
2105 assert('a' <= x && x < 'z');
2106 }
2107
2108 foreach (i; 0 .. 20)
2109 {
2110 immutable ubyte a = 0;
2111 immutable ubyte b = 15;
2112 auto x = uniform(a, b, gen);
2113 assert(a <= x && x < b);
2114 }
2115 }
2116
2117 // Implementation of uniform for floating-point types
2118 /// ditto
2119 auto uniform(string boundaries = "[)",
2120 T1, T2, UniformRandomNumberGenerator)
2121 (T1 a, T2 b, ref UniformRandomNumberGenerator urng)
2122 if (isFloatingPoint!(CommonType!(T1, T2)) && isUniformRNG!UniformRandomNumberGenerator)
2123 {
2124 import std.conv : text;
2125 import std.exception : enforce;
2126 alias NumberType = Unqual!(CommonType!(T1, T2));
2127 static if (boundaries[0] == '(')
2128 {
2129 import std.math.operations : nextafter;
2130 NumberType _a = nextafter(cast(NumberType) a, NumberType.infinity);
2131 }
2132 else
2133 {
2134 NumberType _a = a;
2135 }
2136 static if (boundaries[1] == ')')
2137 {
2138 import std.math.operations : nextafter;
2139 NumberType _b = nextafter(cast(NumberType) b, -NumberType.infinity);
2140 }
2141 else
2142 {
2143 NumberType _b = b;
2144 }
2145 enforce(_a <= _b,
2146 text("std.random.uniform(): invalid bounding interval ",
2147 boundaries[0], a, ", ", b, boundaries[1]));
2148 NumberType result =
2149 _a + (_b - _a) * cast(NumberType) (urng.front - urng.min)
2150 / (urng.max - urng.min);
2151 urng.popFront();
2152 return result;
2153 }
2154
2155 // Implementation of uniform for integral types
2156 /+ Description of algorithm and suggestion of correctness:
2157
2158 The modulus operator maps an integer to a small, finite space. For instance, `x
2159 % 3` will map whatever x is into the range [0 .. 3). 0 maps to 0, 1 maps to 1, 2
2160 maps to 2, 3 maps to 0, and so on infinitely. As long as the integer is
2161 uniformly chosen from the infinite space of all non-negative integers then `x %
2162 3` will uniformly fall into that range.
2163
2164 (Non-negative is important in this case because some definitions of modulus,
2165 namely the one used in computers generally, map negative numbers differently to
2166 (-3 .. 0]. `uniform` does not use negative number modulus, thus we can safely
2167 ignore that fact.)
2168
2169 The issue with computers is that integers have a finite space they must fit in,
2170 and our uniformly chosen random number is picked in that finite space. So, that
2171 method is not sufficient. You can look at it as the integer space being divided
2172 into "buckets" and every bucket after the first bucket maps directly into that
2173 first bucket. `[0, 1, 2]`, `[3, 4, 5]`, ... When integers are finite, then the
2174 last bucket has the chance to be "incomplete": `[uint.max - 3, uint.max - 2,
2175 uint.max - 1]`, `[uint.max]` ... (the last bucket only has 1!). The issue here
2176 is that _every_ bucket maps _completely_ to the first bucket except for that
2177 last one. The last one doesn't have corresponding mappings to 1 or 2, in this
2178 case, which makes it unfair.
2179
2180 So, the answer is to simply "reroll" if you're in that last bucket, since it's
2181 the only unfair one. Eventually you'll roll into a fair bucket. Simply, instead
2182 of the meaning of the last bucket being "maps to `[0]`", it changes to "maps to
2183 `[0, 1, 2]`", which is precisely what we want.
2184
2185 To generalize, `upperDist` represents the size of our buckets (and, thus, the
2186 exclusive upper bound for our desired uniform number). `rnum` is a uniformly
2187 random number picked from the space of integers that a computer can hold (we'll
2188 say `UpperType` represents that type).
2189
2190 We'll first try to do the mapping into the first bucket by doing `offset = rnum
2191 % upperDist`. We can figure out the position of the front of the bucket we're in
2192 by `bucketFront = rnum - offset`.
2193
2194 If we start at `UpperType.max` and walk backwards `upperDist - 1` spaces, then
2195 the space we land on is the last acceptable position where a full bucket can
2196 fit:
2197
2198 ---
2199 bucketFront UpperType.max
2200 v v
2201 [..., 0, 1, 2, ..., upperDist - 1]
2202 ^~~ upperDist - 1 ~~^
2203 ---
2204
2205 If the bucket starts any later, then it must have lost at least one number and
2206 at least that number won't be represented fairly.
2207
2208 ---
2209 bucketFront UpperType.max
2210 v v
2211 [..., upperDist - 1, 0, 1, 2, ..., upperDist - 2]
2212 ^~~~~~~~ upperDist - 1 ~~~~~~~^
2213 ---
2214
2215 Hence, our condition to reroll is
2216 `bucketFront > (UpperType.max - (upperDist - 1))`
2217 +/
2218 auto uniform(string boundaries = "[)", T1, T2, RandomGen)
2219 (T1 a, T2 b, ref RandomGen rng)
2220 if ((isIntegral!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2))) &&
2221 isUniformRNG!RandomGen)
2222 {
2223 import std.conv : text, unsigned;
2224 import std.exception : enforce;
2225 alias ResultType = Unqual!(CommonType!(T1, T2));
2226 static if (boundaries[0] == '(')
2227 {
2228 enforce(a < ResultType.max,
2229 text("std.random.uniform(): invalid left bound ", a));
2230 ResultType lower = cast(ResultType) (a + 1);
2231 }
2232 else
2233 {
2234 ResultType lower = a;
2235 }
2236
2237 static if (boundaries[1] == ']')
2238 {
2239 enforce(lower <= b,
2240 text("std.random.uniform(): invalid bounding interval ",
2241 boundaries[0], a, ", ", b, boundaries[1]));
2242 /* Cannot use this next optimization with dchar, as dchar
2243 * only partially uses its full bit range
2244 */
2245 static if (!is(ResultType == dchar))
2246 {
2247 if (b == ResultType.max && lower == ResultType.min)
2248 {
2249 // Special case - all bits are occupied
2250 return std.random.uniform!ResultType(rng);
2251 }
2252 }
2253 auto upperDist = unsigned(b - lower) + 1u;
2254 }
2255 else
2256 {
2257 enforce(lower < b,
2258 text("std.random.uniform(): invalid bounding interval ",
2259 boundaries[0], a, ", ", b, boundaries[1]));
2260 auto upperDist = unsigned(b - lower);
2261 }
2262
2263 assert(upperDist != 0);
2264
2265 alias UpperType = typeof(upperDist);
2266 static assert(UpperType.min == 0);
2267
2268 UpperType offset, rnum, bucketFront;
2269 do
2270 {
2271 rnum = uniform!UpperType(rng);
2272 offset = rnum % upperDist;
2273 bucketFront = rnum - offset;
2274 } // while we're in an unfair bucket...
2275 while (bucketFront > (UpperType.max - (upperDist - 1)));
2276
2277 return cast(ResultType)(lower + offset);
2278 }
2279
2280 @safe unittest
2281 {
2282 import std.conv : to;
2283 auto gen = Mt19937(123_456_789);
2284 static assert(isForwardRange!(typeof(gen)));
2285
2286 auto a = uniform(0, 1024, gen);
2287 assert(0 <= a && a <= 1024);
2288 auto b = uniform(0.0f, 1.0f, gen);
2289 assert(0 <= b && b < 1, to!string(b));
2290 auto c = uniform(0.0, 1.0);
2291 assert(0 <= c && c < 1);
2292
2293 static foreach (T; std.meta.AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort,
2294 int, uint, long, ulong, float, double, real))
2295 {{
2296 T lo = 0, hi = 100;
2297
2298 // Try tests with each of the possible bounds
2299 {
2300 T init = uniform(lo, hi);
2301 size_t i = 50;
2302 while (--i && uniform(lo, hi) == init) {}
2303 assert(i > 0);
2304 }
2305 {
2306 T init = uniform!"[)"(lo, hi);
2307 size_t i = 50;
2308 while (--i && uniform(lo, hi) == init) {}
2309 assert(i > 0);
2310 }
2311 {
2312 T init = uniform!"(]"(lo, hi);
2313 size_t i = 50;
2314 while (--i && uniform(lo, hi) == init) {}
2315 assert(i > 0);
2316 }
2317 {
2318 T init = uniform!"()"(lo, hi);
2319 size_t i = 50;
2320 while (--i && uniform(lo, hi) == init) {}
2321 assert(i > 0);
2322 }
2323 {
2324 T init = uniform!"[]"(lo, hi);
2325 size_t i = 50;
2326 while (--i && uniform(lo, hi) == init) {}
2327 assert(i > 0);
2328 }
2329
2330 /* Test case with closed boundaries covering whole range
2331 * of integral type
2332 */
2333 static if (isIntegral!T || isSomeChar!T)
2334 {
2335 foreach (immutable _; 0 .. 100)
2336 {
2337 auto u = uniform!"[]"(T.min, T.max);
2338 static assert(is(typeof(u) == T));
2339 assert(T.min <= u, "Lower bound violation for uniform!\"[]\" with " ~ T.stringof);
2340 assert(u <= T.max, "Upper bound violation for uniform!\"[]\" with " ~ T.stringof);
2341 }
2342 }
2343 }}
2344
2345 auto reproRng = Xorshift(239842);
2346
2347 static foreach (T; std.meta.AliasSeq!(char, wchar, dchar, byte, ubyte, short,
2348 ushort, int, uint, long, ulong))
2349 {{
2350 T lo = T.min + 10, hi = T.max - 10;
2351 T init = uniform(lo, hi, reproRng);
2352 size_t i = 50;
2353 while (--i && uniform(lo, hi, reproRng) == init) {}
2354 assert(i > 0);
2355 }}
2356
2357 {
2358 bool sawLB = false, sawUB = false;
2359 foreach (i; 0 .. 50)
2360 {
2361 auto x = uniform!"[]"('a', 'd', reproRng);
2362 if (x == 'a') sawLB = true;
2363 if (x == 'd') sawUB = true;
2364 assert('a' <= x && x <= 'd');
2365 }
2366 assert(sawLB && sawUB);
2367 }
2368
2369 {
2370 bool sawLB = false, sawUB = false;
2371 foreach (i; 0 .. 50)
2372 {
2373 auto x = uniform('a', 'd', reproRng);
2374 if (x == 'a') sawLB = true;
2375 if (x == 'c') sawUB = true;
2376 assert('a' <= x && x < 'd');
2377 }
2378 assert(sawLB && sawUB);
2379 }
2380
2381 {
2382 bool sawLB = false, sawUB = false;
2383 foreach (i; 0 .. 50)
2384 {
2385 immutable int lo = -2, hi = 2;
2386 auto x = uniform!"()"(lo, hi, reproRng);
2387 if (x == (lo+1)) sawLB = true;
2388 if (x == (hi-1)) sawUB = true;
2389 assert(lo < x && x < hi);
2390 }
2391 assert(sawLB && sawUB);
2392 }
2393
2394 {
2395 bool sawLB = false, sawUB = false;
2396 foreach (i; 0 .. 50)
2397 {
2398 immutable ubyte lo = 0, hi = 5;
2399 auto x = uniform(lo, hi, reproRng);
2400 if (x == lo) sawLB = true;
2401 if (x == (hi-1)) sawUB = true;
2402 assert(lo <= x && x < hi);
2403 }
2404 assert(sawLB && sawUB);
2405 }
2406
2407 {
2408 foreach (i; 0 .. 30)
2409 {
2410 assert(i == uniform(i, i+1, reproRng));
2411 }
2412 }
2413 }
2414
2415 /+
2416 Generates an unsigned integer in the half-open range `[0, k)`.
2417 Non-public because we locally guarantee `k > 0`.
2418
2419 Params:
2420 k = unsigned exclusive upper bound; caller guarantees this is non-zero
2421 rng = random number generator to use
2422
2423 Returns:
2424 Pseudo-random unsigned integer strictly less than `k`.
2425 +/
2426 private UInt _uniformIndex(UniformRNG, UInt = size_t)(const UInt k, ref UniformRNG rng)
2427 if (isUnsigned!UInt && isUniformRNG!UniformRNG)
2428 {
2429 alias ResultType = UInt;
2430 alias UpperType = Unsigned!(typeof(k - 0));
2431 alias upperDist = k;
2432
2433 assert(upperDist != 0);
2434
2435 // For backwards compatibility use same algorithm as uniform(0, k, rng).
2436 UpperType offset, rnum, bucketFront;
2437 do
2438 {
2439 rnum = uniform!UpperType(rng);
2440 offset = rnum % upperDist;
2441 bucketFront = rnum - offset;
2442 } // while we're in an unfair bucket...
2443 while (bucketFront > (UpperType.max - (upperDist - 1)));
2444
2445 return cast(ResultType) offset;
2446 }
2447
2448 pure @safe unittest
2449 {
2450 // For backwards compatibility check that _uniformIndex(k, rng)
2451 // has the same result as uniform(0, k, rng).
2452 auto rng1 = Xorshift(123_456_789);
2453 auto rng2 = rng1.save();
2454 const size_t k = (1U << 31) - 1;
2455 assert(_uniformIndex(k, rng1) == uniform(0, k, rng2));
2456 }
2457
2458 /**
2459 Generates a uniformly-distributed number in the range $(D [T.min,
2460 T.max]) for any integral or character type `T`. If no random
2461 number generator is passed, uses the default `rndGen`.
2462
2463 If an `enum` is used as type, the random variate is drawn with
2464 equal probability from any of the possible values of the enum `E`.
2465
2466 Params:
2467 urng = (optional) random number generator to use;
2468 if not specified, defaults to `rndGen`
2469
2470 Returns:
2471 Random variate drawn from the _uniform distribution across all
2472 possible values of the integral, character or enum type `T`.
2473 */
2474 auto uniform(T, UniformRandomNumberGenerator)
2475 (ref UniformRandomNumberGenerator urng)
2476 if (!is(T == enum) && (isIntegral!T || isSomeChar!T) && isUniformRNG!UniformRandomNumberGenerator)
2477 {
2478 /* dchar does not use its full bit range, so we must
2479 * revert to the uniform with specified bounds
2480 */
2481 static if (is(immutable T == immutable dchar))
2482 {
2483 return uniform!"[]"(T.min, T.max, urng);
2484 }
2485 else
2486 {
2487 auto r = urng.front;
2488 urng.popFront();
2489 static if (T.sizeof <= r.sizeof)
2490 {
2491 return cast(T) r;
2492 }
2493 else
2494 {
2495 static assert(T.sizeof == 8 && r.sizeof == 4);
2496 T r1 = urng.front | (cast(T) r << 32);
2497 urng.popFront();
2498 return r1;
2499 }
2500 }
2501 }
2502
2503 /// Ditto
2504 auto uniform(T)()
2505 if (!is(T == enum) && (isIntegral!T || isSomeChar!T))
2506 {
2507 return uniform!T(rndGen);
2508 }
2509
2510 ///
2511 @safe unittest
2512 {
2513 auto rnd = MinstdRand0(42);
2514
2515 assert(rnd.uniform!ubyte == 102);
2516 assert(rnd.uniform!ulong == 4838462006927449017);
2517
2518 enum Fruit { apple, mango, pear }
2519 version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
2520 assert(rnd.uniform!Fruit == Fruit.mango);
2521 }
2522
2523 @safe unittest
2524 {
2525 // https://issues.dlang.org/show_bug.cgi?id=21383
2526 auto rng1 = Xorshift32(123456789);
2527 auto rng2 = rng1.save;
2528 assert(rng1.uniform!dchar == rng2.uniform!dchar);
2529 // https://issues.dlang.org/show_bug.cgi?id=21384
2530 assert(rng1.uniform!(const shared dchar) <= dchar.max);
2531 // https://issues.dlang.org/show_bug.cgi?id=8671
2532 double t8671 = 1.0 - uniform(0.0, 1.0);
2533 }
2534
2535 @safe unittest
2536 {
2537 static foreach (T; std.meta.AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort,
2538 int, uint, long, ulong))
2539 {{
2540 T init = uniform!T();
2541 size_t i = 50;
2542 while (--i && uniform!T() == init) {}
2543 assert(i > 0);
2544
2545 foreach (immutable _; 0 .. 100)
2546 {
2547 auto u = uniform!T();
2548 static assert(is(typeof(u) == T));
2549 assert(T.min <= u, "Lower bound violation for uniform!" ~ T.stringof);
2550 assert(u <= T.max, "Upper bound violation for uniform!" ~ T.stringof);
2551 }
2552 }}
2553 }
2554
2555 /// ditto
2556 auto uniform(E, UniformRandomNumberGenerator)
2557 (ref UniformRandomNumberGenerator urng)
2558 if (is(E == enum) && isUniformRNG!UniformRandomNumberGenerator)
2559 {
2560 static immutable E[EnumMembers!E.length] members = [EnumMembers!E];
2561 return members[std.random.uniform(0, members.length, urng)];
2562 }
2563
2564 /// Ditto
2565 auto uniform(E)()
2566 if (is(E == enum))
2567 {
2568 return uniform!E(rndGen);
2569 }
2570
2571 @safe unittest
2572 {
2573 enum Fruit { Apple = 12, Mango = 29, Pear = 72 }
2574 foreach (_; 0 .. 100)
2575 {
2576 foreach (f; [uniform!Fruit(), rndGen.uniform!Fruit()])
2577 {
2578 assert(f == Fruit.Apple || f == Fruit.Mango || f == Fruit.Pear);
2579 }
2580 }
2581 }
2582
2583 /**
2584 * Generates a uniformly-distributed floating point number of type
2585 * `T` in the range [0, 1$(RPAREN). If no random number generator is
2586 * specified, the default RNG `rndGen` will be used as the source
2587 * of randomness.
2588 *
2589 * `uniform01` offers a faster generation of random variates than
2590 * the equivalent $(D uniform!"[$(RPAREN)"(0.0, 1.0)) and so may be preferred
2591 * for some applications.
2592 *
2593 * Params:
2594 * rng = (optional) random number generator to use;
2595 * if not specified, defaults to `rndGen`
2596 *
2597 * Returns:
2598 * Floating-point random variate of type `T` drawn from the _uniform
2599 * distribution across the half-open interval [0, 1$(RPAREN).
2600 *
2601 */
2602 T uniform01(T = double)()
2603 if (isFloatingPoint!T)
2604 {
2605 return uniform01!T(rndGen);
2606 }
2607
2608 /// ditto
2609 T uniform01(T = double, UniformRNG)(ref UniformRNG rng)
2610 if (isFloatingPoint!T && isUniformRNG!UniformRNG)
2611 out (result)
2612 {
2613 assert(0 <= result);
2614 assert(result < 1);
2615 }
2616 do
2617 {
2618 alias R = typeof(rng.front);
2619 static if (isIntegral!R)
2620 {
2621 enum T factor = 1 / (T(1) + rng.max - rng.min);
2622 }
2623 else static if (isFloatingPoint!R)
2624 {
2625 enum T factor = 1 / (rng.max - rng.min);
2626 }
2627 else
2628 {
2629 static assert(false);
2630 }
2631
2632 while (true)
2633 {
2634 immutable T u = (rng.front - rng.min) * factor;
2635 rng.popFront();
2636
2637 static if (isIntegral!R && T.mant_dig >= (8 * R.sizeof))
2638 {
2639 /* If RNG variates are integral and T has enough precision to hold
2640 * R without loss, we're guaranteed by the definition of factor
2641 * that precisely u < 1.
2642 */
2643 return u;
2644 }
2645 else
2646 {
2647 /* Otherwise we have to check whether u is beyond the assumed range
2648 * because of the loss of precision, or for another reason, a
2649 * floating-point RNG can return a variate that is exactly equal to
2650 * its maximum.
2651 */
2652 if (u < 1)
2653 {
2654 return u;
2655 }
2656 }
2657 }
2658
2659 // Shouldn't ever get here.
2660 assert(false);
2661 }
2662
2663 ///
2664 @safe @nogc unittest
2665 {
2666 import std.math.operations : feqrel;
2667
2668 auto rnd = MinstdRand0(42);
2669
2670 // Generate random numbers in the range in the range [0, 1)
2671 auto u1 = uniform01(rnd);
2672 assert(u1 >= 0 && u1 < 1);
2673
2674 auto u2 = rnd.uniform01!float;
2675 assert(u2 >= 0 && u2 < 1);
2676
2677 // Confirm that the random values with the initial seed 42 are 0.000328707 and 0.524587
2678 assert(u1.feqrel(0.000328707) > 20);
2679 assert(u2.feqrel(0.524587) > 20);
2680 }
2681
2682 @safe @nogc unittest
2683 {
2684 import std.meta;
2685 static foreach (UniformRNG; PseudoRngTypes)
2686 {{
2687
2688 static foreach (T; std.meta.AliasSeq!(float, double, real))
2689 {{
2690 UniformRNG rng = UniformRNG(123_456_789);
2691
2692 auto a = uniform01();
2693 assert(is(typeof(a) == double));
2694 assert(0 <= a && a < 1);
2695
2696 auto b = uniform01(rng);
2697 assert(is(typeof(a) == double));
2698 assert(0 <= b && b < 1);
2699
2700 auto c = uniform01!T();
2701 assert(is(typeof(c) == T));
2702 assert(0 <= c && c < 1);
2703
2704 auto d = uniform01!T(rng);
2705 assert(is(typeof(d) == T));
2706 assert(0 <= d && d < 1);
2707
2708 T init = uniform01!T(rng);
2709 size_t i = 50;
2710 while (--i && uniform01!T(rng) == init) {}
2711 assert(i > 0);
2712 assert(i < 50);
2713 }}
2714 }}
2715 }
2716
2717 /**
2718 Generates a uniform probability distribution of size `n`, i.e., an
2719 array of size `n` of positive numbers of type `F` that sum to
2720 `1`. If `useThis` is provided, it is used as storage.
2721 */
2722 F[] uniformDistribution(F = double)(size_t n, F[] useThis = null)
2723 if (isFloatingPoint!F)
2724 {
2725 import std.numeric : normalize;
2726 useThis.length = n;
2727 foreach (ref e; useThis)
2728 {
2729 e = uniform(0.0, 1);
2730 }
2731 normalize(useThis);
2732 return useThis;
2733 }
2734
2735 ///
2736 @safe unittest
2737 {
2738 import std.algorithm.iteration : reduce;
2739 import std.math.operations : isClose;
2740
2741 auto a = uniformDistribution(5);
2742 assert(a.length == 5);
2743 assert(isClose(reduce!"a + b"(a), 1));
2744
2745 a = uniformDistribution(10, a);
2746 assert(a.length == 10);
2747 assert(isClose(reduce!"a + b"(a), 1));
2748 }
2749
2750 /**
2751 Returns a random, uniformly chosen, element `e` from the supplied
2752 $(D Range range). If no random number generator is passed, the default
2753 `rndGen` is used.
2754
2755 Params:
2756 range = a random access range that has the `length` property defined
2757 urng = (optional) random number generator to use;
2758 if not specified, defaults to `rndGen`
2759
2760 Returns:
2761 A single random element drawn from the `range`. If it can, it will
2762 return a `ref` to the $(D range element), otherwise it will return
2763 a copy.
2764 */
2765 auto ref choice(Range, RandomGen = Random)(auto ref Range range, ref RandomGen urng)
2766 if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen)
2767 {
2768 assert(range.length > 0,
2769 __PRETTY_FUNCTION__ ~ ": invalid Range supplied. Range cannot be empty");
2770
2771 return range[uniform(size_t(0), $, urng)];
2772 }
2773
2774 /// ditto
2775 auto ref choice(Range)(auto ref Range range)
2776 {
2777 return choice(range, rndGen);
2778 }
2779
2780 ///
2781 @safe unittest
2782 {
2783 auto rnd = MinstdRand0(42);
2784
2785 auto elem = [1, 2, 3, 4, 5].choice(rnd);
2786 version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
2787 assert(elem == 3);
2788 }
2789
2790 @safe unittest
2791 {
2792 import std.algorithm.searching : canFind;
2793
2794 class MyTestClass
2795 {
2796 int x;
2797
2798 this(int x)
2799 {
2800 this.x = x;
2801 }
2802 }
2803
2804 MyTestClass[] testClass;
2805 foreach (i; 0 .. 5)
2806 {
2807 testClass ~= new MyTestClass(i);
2808 }
2809
2810 auto elem = choice(testClass);
2811
2812 assert(canFind!((ref MyTestClass a, ref MyTestClass b) => a.x == b.x)(testClass, elem),
2813 "Choice did not return a valid element from the given Range");
2814 }
2815
2816 @system unittest
2817 {
2818 import std.algorithm.iteration : map;
2819 import std.algorithm.searching : canFind;
2820
2821 auto array = [1, 2, 3, 4, 5];
2822 auto elemAddr = &choice(array);
2823
2824 assert(array.map!((ref e) => &e).canFind(elemAddr),
2825 "Choice did not return a ref to an element from the given Range");
2826 assert(array.canFind(*(cast(int *)(elemAddr))),
2827 "Choice did not return a valid element from the given Range");
2828 }
2829
2830 /**
2831 Shuffles elements of `r` using `gen` as a shuffler. `r` must be
2832 a random-access range with length. If no RNG is specified, `rndGen`
2833 will be used.
2834
2835 Params:
2836 r = random-access range whose elements are to be shuffled
2837 gen = (optional) random number generator to use; if not
2838 specified, defaults to `rndGen`
2839 Returns:
2840 The shuffled random-access range.
2841 */
2842
2843 Range randomShuffle(Range, RandomGen)(Range r, ref RandomGen gen)
2844 if (isRandomAccessRange!Range && isUniformRNG!RandomGen)
2845 {
2846 import std.algorithm.mutation : swapAt;
2847 const n = r.length;
2848 foreach (i; 0 .. n)
2849 {
2850 r.swapAt(i, i + _uniformIndex(n - i, gen));
2851 }
2852 return r;
2853 }
2854
2855 /// ditto
2856 Range randomShuffle(Range)(Range r)
2857 if (isRandomAccessRange!Range)
2858 {
2859 return randomShuffle(r, rndGen);
2860 }
2861
2862 ///
2863 @safe unittest
2864 {
2865 auto rnd = MinstdRand0(42);
2866
2867 auto arr = [1, 2, 3, 4, 5].randomShuffle(rnd);
2868 version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
2869 assert(arr == [3, 5, 2, 4, 1]);
2870 }
2871
2872 @safe unittest
2873 {
2874 int[10] sa = void;
2875 int[10] sb = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
2876 import std.algorithm.sorting : sort;
2877 foreach (RandomGen; PseudoRngTypes)
2878 {
2879 sa[] = sb[];
2880 auto a = sa[];
2881 auto b = sb[];
2882 auto gen = RandomGen(123_456_789);
2883 randomShuffle(a, gen);
2884 sort(a);
2885 assert(a == b);
2886 randomShuffle(a);
2887 sort(a);
2888 assert(a == b);
2889 }
2890 // For backwards compatibility verify randomShuffle(r, gen)
2891 // is equivalent to partialShuffle(r, 0, r.length, gen).
2892 auto gen1 = Xorshift(123_456_789);
2893 auto gen2 = gen1.save();
2894 sa[] = sb[];
2895 // @nogc std.random.randomShuffle.
2896 // https://issues.dlang.org/show_bug.cgi?id=19156
2897 () @nogc nothrow pure { randomShuffle(sa[], gen1); }();
2898 partialShuffle(sb[], sb.length, gen2);
2899 assert(sa[] == sb[]);
2900 }
2901
2902 // https://issues.dlang.org/show_bug.cgi?id=18501
2903 @safe unittest
2904 {
2905 import std.algorithm.comparison : among;
2906 auto r = randomShuffle([0,1]);
2907 assert(r.among([0,1],[1,0]));
2908 }
2909
2910 /**
2911 Partially shuffles the elements of `r` such that upon returning $(D r[0 .. n])
2912 is a random subset of `r` and is randomly ordered. $(D r[n .. r.length])
2913 will contain the elements not in $(D r[0 .. n]). These will be in an undefined
2914 order, but will not be random in the sense that their order after
2915 `partialShuffle` returns will not be independent of their order before
2916 `partialShuffle` was called.
2917
2918 `r` must be a random-access range with length. `n` must be less than
2919 or equal to `r.length`. If no RNG is specified, `rndGen` will be used.
2920
2921 Params:
2922 r = random-access range whose elements are to be shuffled
2923 n = number of elements of `r` to shuffle (counting from the beginning);
2924 must be less than `r.length`
2925 gen = (optional) random number generator to use; if not
2926 specified, defaults to `rndGen`
2927 Returns:
2928 The shuffled random-access range.
2929 */
2930 Range partialShuffle(Range, RandomGen)(Range r, in size_t n, ref RandomGen gen)
2931 if (isRandomAccessRange!Range && isUniformRNG!RandomGen)
2932 {
2933 import std.algorithm.mutation : swapAt;
2934 import std.exception : enforce;
2935 enforce(n <= r.length, "n must be <= r.length for partialShuffle.");
2936 foreach (i; 0 .. n)
2937 {
2938 r.swapAt(i, uniform(i, r.length, gen));
2939 }
2940 return r;
2941 }
2942
2943 /// ditto
2944 Range partialShuffle(Range)(Range r, in size_t n)
2945 if (isRandomAccessRange!Range)
2946 {
2947 return partialShuffle(r, n, rndGen);
2948 }
2949
2950 ///
2951 @safe unittest
2952 {
2953 auto rnd = MinstdRand0(42);
2954
2955 auto arr = [1, 2, 3, 4, 5, 6];
2956 arr = arr.dup.partialShuffle(1, rnd);
2957
2958 version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
2959 assert(arr == [2, 1, 3, 4, 5, 6]); // 1<->2
2960
2961 arr = arr.dup.partialShuffle(2, rnd);
2962 version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
2963 assert(arr == [1, 4, 3, 2, 5, 6]); // 1<->2, 2<->4
2964
2965 arr = arr.dup.partialShuffle(3, rnd);
2966 version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
2967 assert(arr == [5, 4, 6, 2, 1, 3]); // 1<->5, 2<->4, 3<->6
2968 }
2969
2970 @safe unittest
2971 {
2972 import std.algorithm;
2973 foreach (RandomGen; PseudoRngTypes)
2974 {
2975 auto a = [0, 1, 1, 2, 3];
2976 auto b = a.dup;
2977
2978 // Pick a fixed seed so that the outcome of the statistical
2979 // test below is deterministic.
2980 auto gen = RandomGen(12345);
2981
2982 // NUM times, pick LEN elements from the array at random.
2983 immutable int LEN = 2;
2984 immutable int NUM = 750;
2985 int[][] chk;
2986 foreach (step; 0 .. NUM)
2987 {
2988 partialShuffle(a, LEN, gen);
2989 chk ~= a[0 .. LEN].dup;
2990 }
2991
2992 // Check that each possible a[0 .. LEN] was produced at least once.
2993 // For a perfectly random RandomGen, the probability that each
2994 // particular combination failed to appear would be at most
2995 // 0.95 ^^ NUM which is approximately 1,962e-17.
2996 // As long as hardware failure (e.g. bit flip) probability
2997 // is higher, we are fine with this unittest.
2998 sort(chk);
2999 assert(equal(uniq(chk), [ [0,1], [0,2], [0,3],
3000 [1,0], [1,1], [1,2], [1,3],
3001 [2,0], [2,1], [2,3],
3002 [3,0], [3,1], [3,2], ]));
3003
3004 // Check that all the elements are still there.
3005 sort(a);
3006 assert(equal(a, b));
3007 }
3008 }
3009
3010 /**
3011 Rolls a dice with relative probabilities stored in $(D
3012 proportions). Returns the index in `proportions` that was chosen.
3013
3014 Params:
3015 rnd = (optional) random number generator to use; if not
3016 specified, defaults to `rndGen`
3017 proportions = forward range or list of individual values
3018 whose elements correspond to the probabilities
3019 with which to choose the corresponding index
3020 value
3021
3022 Returns:
3023 Random variate drawn from the index values
3024 [0, ... `proportions.length` - 1], with the probability
3025 of getting an individual index value `i` being proportional to
3026 `proportions[i]`.
3027 */
3028 size_t dice(Rng, Num)(ref Rng rnd, Num[] proportions...)
3029 if (isNumeric!Num && isForwardRange!Rng)
3030 {
3031 return diceImpl(rnd, proportions);
3032 }
3033
3034 /// Ditto
3035 size_t dice(R, Range)(ref R rnd, Range proportions)
3036 if (isForwardRange!Range && isNumeric!(ElementType!Range) && !isArray!Range)
3037 {
3038 return diceImpl(rnd, proportions);
3039 }
3040
3041 /// Ditto
3042 size_t dice(Range)(Range proportions)
3043 if (isForwardRange!Range && isNumeric!(ElementType!Range) && !isArray!Range)
3044 {
3045 return diceImpl(rndGen, proportions);
3046 }
3047
3048 /// Ditto
3049 size_t dice(Num)(Num[] proportions...)
3050 if (isNumeric!Num)
3051 {
3052 return diceImpl(rndGen, proportions);
3053 }
3054
3055 ///
3056 @safe unittest
3057 {
3058 auto x = dice(0.5, 0.5); // x is 0 or 1 in equal proportions
3059 auto y = dice(50, 50); // y is 0 or 1 in equal proportions
3060 auto z = dice(70, 20, 10); // z is 0 70% of the time, 1 20% of the time,
3061 // and 2 10% of the time
3062 }
3063
3064 ///
3065 @safe unittest
3066 {
3067 auto rnd = MinstdRand0(42);
3068 auto z = rnd.dice(70, 20, 10);
3069 assert(z == 0);
3070 z = rnd.dice(30, 20, 40, 10);
3071 assert(z == 2);
3072 }
3073
3074 private size_t diceImpl(Rng, Range)(ref Rng rng, scope Range proportions)
3075 if (isForwardRange!Range && isNumeric!(ElementType!Range) && isForwardRange!Rng)
3076 in
3077 {
3078 import std.algorithm.searching : all;
3079 assert(proportions.save.all!"a >= 0");
3080 }
3081 do
3082 {
3083 import std.algorithm.iteration : reduce;
3084 import std.exception : enforce;
3085 double sum = reduce!"a + b"(0.0, proportions.save);
3086 enforce(sum > 0, "Proportions in a dice cannot sum to zero");
3087 immutable point = uniform(0.0, sum, rng);
3088 assert(point < sum);
3089 auto mass = 0.0;
3090
3091 size_t i = 0;
3092 foreach (e; proportions)
3093 {
3094 mass += e;
3095 if (point < mass) return i;
3096 i++;
3097 }
3098 // this point should not be reached
3099 assert(false);
3100 }
3101
3102 ///
3103 @safe unittest
3104 {
3105 auto rnd = Xorshift(123_456_789);
3106 auto i = dice(rnd, 0.0, 100.0);
3107 assert(i == 1);
3108 i = dice(rnd, 100.0, 0.0);
3109 assert(i == 0);
3110
3111 i = dice(100U, 0U);
3112 assert(i == 0);
3113 }
3114
3115 /+ @nogc bool array designed for RandomCover.
3116 - constructed with an invariable length
3117 - small length means 0 alloc and bit field (if up to 32(x86) or 64(x64) choices to cover)
3118 - bigger length means non-GC heap allocation(s) and dealloc. +/
3119 private struct RandomCoverChoices
3120 {
3121 private size_t* buffer;
3122 private immutable size_t _length;
3123 private immutable bool hasPackedBits;
3124 private enum BITS_PER_WORD = typeof(buffer[0]).sizeof * 8;
3125
3126 void opAssign(T)(T) @disable;
3127
3128 this(this) pure nothrow @nogc @trusted
3129 {
3130 import core.stdc.string : memcpy;
3131 import std.internal.memory : enforceMalloc;
3132
3133 if (!hasPackedBits && buffer !is null)
3134 {
3135 const nBytesToAlloc = size_t.sizeof * (_length / BITS_PER_WORD + int(_length % BITS_PER_WORD != 0));
3136 void* nbuffer = enforceMalloc(nBytesToAlloc);
3137 buffer = cast(size_t*) memcpy(nbuffer, buffer, nBytesToAlloc);
3138 }
3139 }
3140
3141 this(size_t numChoices) pure nothrow @nogc @trusted
3142 {
3143 import std.internal.memory : enforceCalloc;
3144
3145 _length = numChoices;
3146 hasPackedBits = _length <= size_t.sizeof * 8;
3147 if (!hasPackedBits)
3148 {
3149 const nWordsToAlloc = _length / BITS_PER_WORD + int(_length % BITS_PER_WORD != 0);
3150 buffer = cast(size_t*) enforceCalloc(nWordsToAlloc, BITS_PER_WORD / 8);
3151 }
3152 }
3153
3154 size_t length() const pure nothrow @nogc @safe @property {return _length;}
3155
3156 ~this() pure nothrow @nogc @trusted
3157 {
3158 import core.memory : pureFree;
3159
3160 if (!hasPackedBits && buffer !is null)
3161 pureFree(buffer);
3162 }
3163
3164 bool opIndex(size_t index) const pure nothrow @nogc @trusted
3165 {
3166 assert(index < _length);
3167 import core.bitop : bt;
3168 if (!hasPackedBits)
3169 return cast(bool) bt(buffer, index);
3170 else
3171 return ((cast(size_t) buffer) >> index) & size_t(1);
3172 }
3173
3174 void opIndexAssign(bool value, size_t index) pure nothrow @nogc @trusted
3175 {
3176 assert(index < _length);
3177 if (!hasPackedBits)
3178 {
3179 import core.bitop : btr, bts;
3180 if (value)
3181 bts(buffer, index);
3182 else
3183 btr(buffer, index);
3184 }
3185 else
3186 {
3187 if (value)
3188 (*cast(size_t*) &buffer) |= size_t(1) << index;
3189 else
3190 (*cast(size_t*) &buffer) &= ~(size_t(1) << index);
3191 }
3192 }
3193 }
3194
3195 @safe @nogc nothrow unittest
3196 {
3197 static immutable lengths = [3, 32, 65, 256];
3198 foreach (length; lengths)
3199 {
3200 RandomCoverChoices c = RandomCoverChoices(length);
3201 assert(c.hasPackedBits == (length <= size_t.sizeof * 8));
3202 c[0] = true;
3203 c[2] = true;
3204 assert(c[0]);
3205 assert(!c[1]);
3206 assert(c[2]);
3207 c[0] = false;
3208 c[1] = true;
3209 c[2] = false;
3210 assert(!c[0]);
3211 assert(c[1]);
3212 assert(!c[2]);
3213 }
3214 }
3215
3216 /**
3217 Covers a given range `r` in a random manner, i.e. goes through each
3218 element of `r` once and only once, just in a random order. `r`
3219 must be a random-access range with length.
3220
3221 If no random number generator is passed to `randomCover`, the
3222 thread-global RNG rndGen will be used internally.
3223
3224 Params:
3225 r = random-access range to cover
3226 rng = (optional) random number generator to use;
3227 if not specified, defaults to `rndGen`
3228
3229 Returns:
3230 Range whose elements consist of the elements of `r`,
3231 in random order. Will be a forward range if both `r` and
3232 `rng` are forward ranges, an
3233 $(REF_ALTTEXT input range, isInputRange, std,range,primitives) otherwise.
3234 */
3235 struct RandomCover(Range, UniformRNG = void)
3236 if (isRandomAccessRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG == void)))
3237 {
3238 private Range _input;
3239 private RandomCoverChoices _chosen;
3240 private size_t _current;
3241 private size_t _alreadyChosen = 0;
3242 private bool _isEmpty = false;
3243
3244 static if (is(UniformRNG == void))
3245 {
3246 this(Range input)
3247 {
3248 _input = input;
3249 _chosen = RandomCoverChoices(_input.length);
3250 if (_input.empty)
3251 {
3252 _isEmpty = true;
3253 }
3254 else
3255 {
3256 _current = _uniformIndex(_chosen.length, rndGen);
3257 }
3258 }
3259 }
3260 else
3261 {
3262 private UniformRNG _rng;
3263
3264 this(Range input, ref UniformRNG rng)
3265 {
3266 _input = input;
3267 _rng = rng;
3268 _chosen = RandomCoverChoices(_input.length);
3269 if (_input.empty)
3270 {
3271 _isEmpty = true;
3272 }
3273 else
3274 {
3275 _current = _uniformIndex(_chosen.length, rng);
3276 }
3277 }
3278
3279 this(Range input, UniformRNG rng)
3280 {
3281 this(input, rng);
3282 }
3283 }
3284
3285 static if (hasLength!Range)
3286 {
3287 @property size_t length()
3288 {
3289 return _input.length - _alreadyChosen;
3290 }
3291 }
3292
3293 @property auto ref front()
3294 {
3295 assert(!_isEmpty);
3296 return _input[_current];
3297 }
3298
3299 void popFront()
3300 {
3301 assert(!_isEmpty);
3302
3303 size_t k = _input.length - _alreadyChosen - 1;
3304 if (k == 0)
3305 {
3306 _isEmpty = true;
3307 ++_alreadyChosen;
3308 return;
3309 }
3310
3311 size_t i;
3312 foreach (e; _input)
3313 {
3314 if (_chosen[i] || i == _current) { ++i; continue; }
3315 // Roll a dice with k faces
3316 static if (is(UniformRNG == void))
3317 {
3318 auto chooseMe = _uniformIndex(k, rndGen) == 0;
3319 }
3320 else
3321 {
3322 auto chooseMe = _uniformIndex(k, _rng) == 0;
3323 }
3324 assert(k > 1 || chooseMe);
3325 if (chooseMe)
3326 {
3327 _chosen[_current] = true;
3328 _current = i;
3329 ++_alreadyChosen;
3330 return;
3331 }
3332 --k;
3333 ++i;
3334 }
3335 }
3336
3337 static if (isForwardRange!UniformRNG)
3338 {
3339 @property typeof(this) save()
3340 {
3341 auto ret = this;
3342 ret._input = _input.save;
3343 ret._rng = _rng.save;
3344 return ret;
3345 }
3346 }
3347
3348 @property bool empty() const { return _isEmpty; }
3349 }
3350
3351 /// Ditto
3352 auto randomCover(Range, UniformRNG)(Range r, auto ref UniformRNG rng)
3353 if (isRandomAccessRange!Range && isUniformRNG!UniformRNG)
3354 {
3355 return RandomCover!(Range, UniformRNG)(r, rng);
3356 }
3357
3358 /// Ditto
3359 auto randomCover(Range)(Range r)
3360 if (isRandomAccessRange!Range)
3361 {
3362 return RandomCover!(Range, void)(r);
3363 }
3364
3365 ///
3366 @safe unittest
3367 {
3368 import std.algorithm.comparison : equal;
3369 import std.range : iota;
3370 auto rnd = MinstdRand0(42);
3371
3372 version (X86_64) // https://issues.dlang.org/show_bug.cgi?id=15147
3373 assert(10.iota.randomCover(rnd).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5]));
3374 }
3375
3376 @safe unittest // cover RandomCoverChoices postblit for heap storage
3377 {
3378 import std.array : array;
3379 import std.range : iota;
3380 auto a = 1337.iota.randomCover().array;
3381 assert(a.length == 1337);
3382 }
3383
3384 @nogc nothrow pure @safe unittest
3385 {
3386 // Optionally @nogc std.random.randomCover
3387 // https://issues.dlang.org/show_bug.cgi?id=14001
3388 auto rng = Xorshift(123_456_789);
3389 static immutable int[] sa = [1, 2, 3, 4, 5];
3390 auto r = randomCover(sa, rng);
3391 assert(!r.empty);
3392 const x = r.front;
3393 r.popFront();
3394 assert(!r.empty);
3395 const y = r.front;
3396 assert(x != y);
3397 }
3398
3399 @safe unittest
3400 {
3401 import std.algorithm;
3402 import std.conv;
3403 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ];
3404 int[] c;
3405 static foreach (UniformRNG; std.meta.AliasSeq!(void, PseudoRngTypes))
3406 {{
3407 static if (is(UniformRNG == void))
3408 {
3409 auto rc = randomCover(a);
3410 static assert(isInputRange!(typeof(rc)));
3411 static assert(!isForwardRange!(typeof(rc)));
3412 }
3413 else
3414 {
3415 auto rng = UniformRNG(123_456_789);
3416 auto rc = randomCover(a, rng);
3417 static assert(isForwardRange!(typeof(rc)));
3418 // check for constructor passed a value-type RNG
3419 auto rc2 = RandomCover!(int[], UniformRNG)(a, UniformRNG(987_654_321));
3420 static assert(isForwardRange!(typeof(rc2)));
3421 auto rcEmpty = randomCover(c, rng);
3422 assert(rcEmpty.length == 0);
3423 }
3424
3425 int[] b = new int[9];
3426 uint i;
3427 foreach (e; rc)
3428 {
3429 //writeln(e);
3430 b[i++] = e;
3431 }
3432 sort(b);
3433 assert(a == b, text(b));
3434 }}
3435 }
3436
3437 @safe unittest
3438 {
3439 // https://issues.dlang.org/show_bug.cgi?id=12589
3440 int[] r = [];
3441 auto rc = randomCover(r);
3442 assert(rc.length == 0);
3443 assert(rc.empty);
3444
3445 // https://issues.dlang.org/show_bug.cgi?id=16724
3446 import std.range : iota;
3447 auto range = iota(10);
3448 auto randy = range.randomCover;
3449
3450 for (int i=1; i <= range.length; i++)
3451 {
3452 randy.popFront;
3453 assert(randy.length == range.length - i);
3454 }
3455 }
3456
3457 // RandomSample
3458 /**
3459 Selects a random subsample out of `r`, containing exactly `n`
3460 elements. The order of elements is the same as in the original
3461 range. The total length of `r` must be known. If `total` is
3462 passed in, the total number of sample is considered to be $(D
3463 total). Otherwise, `RandomSample` uses `r.length`.
3464
3465 Params:
3466 r = range to sample from
3467 n = number of elements to include in the sample;
3468 must be less than or equal to the total number
3469 of elements in `r` and/or the parameter
3470 `total` (if provided)
3471 total = (semi-optional) number of elements of `r`
3472 from which to select the sample (counting from
3473 the beginning); must be less than or equal to
3474 the total number of elements in `r` itself.
3475 May be omitted if `r` has the `.length`
3476 property and the sample is to be drawn from
3477 all elements of `r`.
3478 rng = (optional) random number generator to use;
3479 if not specified, defaults to `rndGen`
3480
3481 Returns:
3482 Range whose elements consist of a randomly selected subset of
3483 the elements of `r`, in the same order as these elements
3484 appear in `r` itself. Will be a forward range if both `r`
3485 and `rng` are forward ranges, an input range otherwise.
3486
3487 `RandomSample` implements Jeffrey Scott Vitter's Algorithm D
3488 (see Vitter $(HTTP dx.doi.org/10.1145/358105.893, 1984), $(HTTP
3489 dx.doi.org/10.1145/23002.23003, 1987)), which selects a sample
3490 of size `n` in O(n) steps and requiring O(n) random variates,
3491 regardless of the size of the data being sampled. The exception
3492 to this is if traversing k elements on the input range is itself
3493 an O(k) operation (e.g. when sampling lines from an input file),
3494 in which case the sampling calculation will inevitably be of
3495 O(total).
3496
3497 RandomSample will throw an exception if `total` is verifiably
3498 less than the total number of elements available in the input,
3499 or if $(D n > total).
3500
3501 If no random number generator is passed to `randomSample`, the
3502 thread-global RNG rndGen will be used internally.
3503 */
3504 struct RandomSample(Range, UniformRNG = void)
3505 if (isInputRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG == void)))
3506 {
3507 private size_t _available, _toSelect;
3508 private enum ushort _alphaInverse = 13; // Vitter's recommended value.
3509 private double _Vprime;
3510 private Range _input;
3511 private size_t _index;
3512 private enum Skip { None, A, D }
3513 private Skip _skip = Skip.None;
3514
3515 // If we're using the default thread-local random number generator then
3516 // we shouldn't store a copy of it here. UniformRNG == void is a sentinel
3517 // for this. If we're using a user-specified generator then we have no
3518 // choice but to store a copy.
3519 static if (is(UniformRNG == void))
3520 {
3521 static if (hasLength!Range)
3522 {
3523 this(Range input, size_t howMany)
3524 {
3525 _input = input;
3526 initialize(howMany, input.length);
3527 }
3528 }
3529
3530 this(Range input, size_t howMany, size_t total)
3531 {
3532 _input = input;
3533 initialize(howMany, total);
3534 }
3535 }
3536 else
3537 {
3538 UniformRNG _rng;
3539
3540 static if (hasLength!Range)
3541 {
3542 this(Range input, size_t howMany, ref scope UniformRNG rng)
3543 {
3544 _rng = rng;
3545 _input = input;
3546 initialize(howMany, input.length);
3547 }
3548
3549 this(Range input, size_t howMany, UniformRNG rng)
3550 {
3551 this(input, howMany, rng);
3552 }
3553 }
3554
3555 this(Range input, size_t howMany, size_t total, ref scope UniformRNG rng)
3556 {
3557 _rng = rng;
3558 _input = input;
3559 initialize(howMany, total);
3560 }
3561
3562 this(Range input, size_t howMany, size_t total, UniformRNG rng)
3563 {
3564 this(input, howMany, total, rng);
3565 }
3566 }
3567
3568 private void initialize(size_t howMany, size_t total)
3569 {
3570 import std.conv : text;
3571 import std.exception : enforce;
3572 _available = total;
3573 _toSelect = howMany;
3574 enforce(_toSelect <= _available,
3575 text("RandomSample: cannot sample ", _toSelect,
3576 " items when only ", _available, " are available"));
3577 static if (hasLength!Range)
3578 {
3579 enforce(_available <= _input.length,
3580 text("RandomSample: specified ", _available,
3581 " items as available when input contains only ",
3582 _input.length));
3583 }
3584 }
3585
3586 private void initializeFront()
3587 {
3588 assert(_skip == Skip.None);
3589 // We can save ourselves a random variate by checking right
3590 // at the beginning if we should use Algorithm A.
3591 if ((_alphaInverse * _toSelect) > _available)
3592 {
3593 _skip = Skip.A;
3594 }
3595 else
3596 {
3597 _skip = Skip.D;
3598 _Vprime = newVprime(_toSelect);
3599 }
3600 prime();
3601 }
3602
3603 /**
3604 Range primitives.
3605 */
3606 @property bool empty() const
3607 {
3608 return _toSelect == 0;
3609 }
3610
3611 /// Ditto
3612 @property auto ref front()
3613 {
3614 assert(!empty);
3615 // The first sample point must be determined here to avoid
3616 // having it always correspond to the first element of the
3617 // input. The rest of the sample points are determined each
3618 // time we call popFront().
3619 if (_skip == Skip.None)
3620 {
3621 initializeFront();
3622 }
3623 return _input.front;
3624 }
3625
3626 /// Ditto
3627 void popFront()
3628 {
3629 // First we need to check if the sample has
3630 // been initialized in the first place.
3631 if (_skip == Skip.None)
3632 {
3633 initializeFront();
3634 }
3635
3636 _input.popFront();
3637 --_available;
3638 --_toSelect;
3639 ++_index;
3640 prime();
3641 }
3642
3643 /// Ditto
3644 static if (isForwardRange!Range && isForwardRange!UniformRNG)
3645 {
3646 static if (is(typeof(((const UniformRNG* p) => (*p).save)(null)) : UniformRNG)
3647 && is(typeof(((const Range* p) => (*p).save)(null)) : Range))
3648 {
3649 @property typeof(this) save() const
3650 {
3651 auto ret = RandomSample.init;
3652 foreach (fieldIndex, ref val; this.tupleof)
3653 {
3654 static if (is(typeof(val) == const(Range)) || is(typeof(val) == const(UniformRNG)))
3655 ret.tupleof[fieldIndex] = val.save;
3656 else
3657 ret.tupleof[fieldIndex] = val;
3658 }
3659 return ret;
3660 }
3661 }
3662 else
3663 {
3664 @property typeof(this) save()
3665 {
3666 auto ret = this;
3667 ret._input = _input.save;
3668 ret._rng = _rng.save;
3669 return ret;
3670 }
3671 }
3672 }
3673
3674 /// Ditto
3675 @property size_t length() const
3676 {
3677 return _toSelect;
3678 }
3679
3680 /**
3681 Returns the index of the visited record.
3682 */
3683 @property size_t index()
3684 {
3685 if (_skip == Skip.None)
3686 {
3687 initializeFront();
3688 }
3689 return _index;
3690 }
3691
3692 private size_t skip()
3693 {
3694 assert(_skip != Skip.None);
3695
3696 // Step D1: if the number of points still to select is greater
3697 // than a certain proportion of the remaining data points, i.e.
3698 // if n >= alpha * N where alpha = 1/13, we carry out the
3699 // sampling with Algorithm A.
3700 if (_skip == Skip.A)
3701 {
3702 return skipA();
3703 }
3704 else if ((_alphaInverse * _toSelect) > _available)
3705 {
3706 // We shouldn't get here unless the current selected
3707 // algorithm is D.
3708 assert(_skip == Skip.D);
3709 _skip = Skip.A;
3710 return skipA();
3711 }
3712 else
3713 {
3714 assert(_skip == Skip.D);
3715 return skipD();
3716 }
3717 }
3718
3719 /*
3720 Vitter's Algorithm A, used when the ratio of needed sample values
3721 to remaining data values is sufficiently large.
3722 */
3723 private size_t skipA()
3724 {
3725 size_t s;
3726 double v, quot, top;
3727
3728 if (_toSelect == 1)
3729 {
3730 static if (is(UniformRNG == void))
3731 {
3732 s = uniform(0, _available);
3733 }
3734 else
3735 {
3736 s = uniform(0, _available, _rng);
3737 }
3738 }
3739 else
3740 {
3741 v = 0;
3742 top = _available - _toSelect;
3743 quot = top / _available;
3744
3745 static if (is(UniformRNG == void))
3746 {
3747 v = uniform!"()"(0.0, 1.0);
3748 }
3749 else
3750 {
3751 v = uniform!"()"(0.0, 1.0, _rng);
3752 }
3753
3754 while (quot > v)
3755 {
3756 ++s;
3757 quot *= (top - s) / (_available - s);
3758 }
3759 }
3760
3761 return s;
3762 }
3763
3764 /*
3765 Randomly reset the value of _Vprime.
3766 */
3767 private double newVprime(size_t remaining)
3768 {
3769 static if (is(UniformRNG == void))
3770 {
3771 double r = uniform!"()"(0.0, 1.0);
3772 }
3773 else
3774 {
3775 double r = uniform!"()"(0.0, 1.0, _rng);
3776 }
3777
3778 return r ^^ (1.0 / remaining);
3779 }
3780
3781 /*
3782 Vitter's Algorithm D. For an extensive description of the algorithm
3783 and its rationale, see:
3784
3785 * Vitter, J.S. (1984), "Faster methods for random sampling",
3786 Commun. ACM 27(7): 703--718
3787
3788 * Vitter, J.S. (1987) "An efficient algorithm for sequential random
3789 sampling", ACM Trans. Math. Softw. 13(1): 58-67.
3790
3791 Variable names are chosen to match those in Vitter's paper.
3792 */
3793 private size_t skipD()
3794 {
3795 import std.math.traits : isNaN;
3796 import std.math.rounding : trunc;
3797 // Confirm that the check in Step D1 is valid and we
3798 // haven't been sent here by mistake
3799 assert((_alphaInverse * _toSelect) <= _available);
3800
3801 // Now it's safe to use the standard Algorithm D mechanism.
3802 if (_toSelect > 1)
3803 {
3804 size_t s;
3805 size_t qu1 = 1 + _available - _toSelect;
3806 double x, y1;
3807
3808 assert(!_Vprime.isNaN());
3809
3810 while (true)
3811 {
3812 // Step D2: set values of x and u.
3813 while (1)
3814 {
3815 x = _available * (1-_Vprime);
3816 s = cast(size_t) trunc(x);
3817 if (s < qu1)
3818 break;
3819 _Vprime = newVprime(_toSelect);
3820 }
3821
3822 static if (is(UniformRNG == void))
3823 {
3824 double u = uniform!"()"(0.0, 1.0);
3825 }
3826 else
3827 {
3828 double u = uniform!"()"(0.0, 1.0, _rng);
3829 }
3830
3831 y1 = (u * (cast(double) _available) / qu1) ^^ (1.0/(_toSelect - 1));
3832
3833 _Vprime = y1 * ((-x/_available)+1.0) * ( qu1/( (cast(double) qu1) - s ) );
3834
3835 // Step D3: if _Vprime <= 1.0 our work is done and we return S.
3836 // Otherwise ...
3837 if (_Vprime > 1.0)
3838 {
3839 size_t top = _available - 1, limit;
3840 double y2 = 1.0, bottom;
3841
3842 if (_toSelect > (s+1))
3843 {
3844 bottom = _available - _toSelect;
3845 limit = _available - s;
3846 }
3847 else
3848 {
3849 bottom = _available - (s+1);
3850 limit = qu1;
3851 }
3852
3853 foreach (size_t t; limit .. _available)
3854 {
3855 y2 *= top/bottom;
3856 top--;
3857 bottom--;
3858 }
3859
3860 // Step D4: decide whether or not to accept the current value of S.
3861 if (_available/(_available-x) < y1 * (y2 ^^ (1.0/(_toSelect-1))))
3862 {
3863 // If it's not acceptable, we generate a new value of _Vprime
3864 // and go back to the start of the for (;;) loop.
3865 _Vprime = newVprime(_toSelect);
3866 }
3867 else
3868 {
3869 // If it's acceptable we generate a new value of _Vprime
3870 // based on the remaining number of sample points needed,
3871 // and return S.
3872 _Vprime = newVprime(_toSelect-1);
3873 return s;
3874 }
3875 }
3876 else
3877 {
3878 // Return if condition D3 satisfied.
3879 return s;
3880 }
3881 }
3882 }
3883 else
3884 {
3885 // If only one sample point remains to be taken ...
3886 return cast(size_t) trunc(_available * _Vprime);
3887 }
3888 }
3889
3890 private void prime()
3891 {
3892 if (empty)
3893 {
3894 return;
3895 }
3896 assert(_available && _available >= _toSelect);
3897 immutable size_t s = skip();
3898 assert(s + _toSelect <= _available);
3899 static if (hasLength!Range)
3900 {
3901 assert(s + _toSelect <= _input.length);
3902 }
3903 assert(!_input.empty);
3904 _input.popFrontExactly(s);
3905 _index += s;
3906 _available -= s;
3907 assert(_available > 0);
3908 }
3909 }
3910
3911 /// Ditto
3912 auto randomSample(Range)(Range r, size_t n, size_t total)
3913 if (isInputRange!Range)
3914 {
3915 return RandomSample!(Range, void)(r, n, total);
3916 }
3917
3918 /// Ditto
3919 auto randomSample(Range)(Range r, size_t n)
3920 if (isInputRange!Range && hasLength!Range)
3921 {
3922 return RandomSample!(Range, void)(r, n, r.length);
3923 }
3924
3925 /// Ditto
3926 auto randomSample(Range, UniformRNG)(Range r, size_t n, size_t total, auto ref UniformRNG rng)
3927 if (isInputRange!Range && isUniformRNG!UniformRNG)
3928 {
3929 return RandomSample!(Range, UniformRNG)(r, n, total, rng);
3930 }
3931
3932 /// Ditto
3933 auto randomSample(Range, UniformRNG)(Range r, size_t n, auto ref UniformRNG rng)
3934 if (isInputRange!Range && hasLength!Range && isUniformRNG!UniformRNG)
3935 {
3936 return RandomSample!(Range, UniformRNG)(r, n, r.length, rng);
3937 }
3938
3939 ///
3940 @safe unittest
3941 {
3942 import std.algorithm.comparison : equal;
3943 import std.range : iota;
3944 auto rnd = MinstdRand0(42);
3945 assert(10.iota.randomSample(3, rnd).equal([7, 8, 9]));
3946 }
3947
3948 @system unittest
3949 {
3950 // @system because it takes the address of a local
3951 import std.conv : text;
3952 import std.exception;
3953 import std.range;
3954 // For test purposes, an infinite input range
3955 struct TestInputRange
3956 {
3957 private auto r = recurrence!"a[n-1] + 1"(0);
3958 bool empty() @property const pure nothrow { return r.empty; }
3959 auto front() @property pure nothrow { return r.front; }
3960 void popFront() pure nothrow { r.popFront(); }
3961 }
3962 static assert(isInputRange!TestInputRange);
3963 static assert(!isForwardRange!TestInputRange);
3964
3965 const(int)[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
3966
3967 foreach (UniformRNG; PseudoRngTypes)
3968 (){ // avoid workaround optimizations for large functions
3969 // https://issues.dlang.org/show_bug.cgi?id=2396
3970 auto rng = UniformRNG(1234);
3971 /* First test the most general case: randomSample of input range, with and
3972 * without a specified random number generator.
3973 */
3974 static assert(isInputRange!(typeof(randomSample(TestInputRange(), 5, 10))));
3975 static assert(isInputRange!(typeof(randomSample(TestInputRange(), 5, 10, rng))));
3976 static assert(!isForwardRange!(typeof(randomSample(TestInputRange(), 5, 10))));
3977 static assert(!isForwardRange!(typeof(randomSample(TestInputRange(), 5, 10, rng))));
3978 // test case with range initialized by direct call to struct
3979 {
3980 auto sample =
3981 RandomSample!(TestInputRange, UniformRNG)
3982 (TestInputRange(), 5, 10, UniformRNG(987_654_321));
3983 static assert(isInputRange!(typeof(sample)));
3984 static assert(!isForwardRange!(typeof(sample)));
3985 }
3986
3987 /* Now test the case of an input range with length. We ignore the cases
3988 * already covered by the previous tests.
3989 */
3990 static assert(isInputRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5))));
3991 static assert(isInputRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5, rng))));
3992 static assert(!isForwardRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5))));
3993 static assert(!isForwardRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5, rng))));
3994 // test case with range initialized by direct call to struct
3995 {
3996 auto sample =
3997 RandomSample!(typeof(TestInputRange().takeExactly(10)), UniformRNG)
3998 (TestInputRange().takeExactly(10), 5, 10, UniformRNG(654_321_987));
3999 static assert(isInputRange!(typeof(sample)));
4000 static assert(!isForwardRange!(typeof(sample)));
4001 }
4002
4003 // Now test the case of providing a forward range as input.
4004 static assert(!isForwardRange!(typeof(randomSample(a, 5))));
4005 static if (isForwardRange!UniformRNG)
4006 {
4007 static assert(isForwardRange!(typeof(randomSample(a, 5, rng))));
4008 // ... and test with range initialized directly
4009 {
4010 auto sample =
4011 RandomSample!(const(int)[], UniformRNG)
4012 (a, 5, UniformRNG(321_987_654));
4013 static assert(isForwardRange!(typeof(sample)));
4014 }
4015 }
4016 else
4017 {
4018 static assert(isInputRange!(typeof(randomSample(a, 5, rng))));
4019 static assert(!isForwardRange!(typeof(randomSample(a, 5, rng))));
4020 // ... and test with range initialized directly
4021 {
4022 auto sample =
4023 RandomSample!(const(int)[], UniformRNG)
4024 (a, 5, UniformRNG(789_123_456));
4025 static assert(isInputRange!(typeof(sample)));
4026 static assert(!isForwardRange!(typeof(sample)));
4027 }
4028 }
4029
4030 /* Check that randomSample will throw an error if we claim more
4031 * items are available than there actually are, or if we try to
4032 * sample more items than are available. */
4033 assert(collectExceptionMsg(
4034 randomSample(a, 5, 15)
4035 ) == "RandomSample: specified 15 items as available when input contains only 10");
4036 assert(collectExceptionMsg(
4037 randomSample(a, 15)
4038 ) == "RandomSample: cannot sample 15 items when only 10 are available");
4039 assert(collectExceptionMsg(
4040 randomSample(a, 9, 8)
4041 ) == "RandomSample: cannot sample 9 items when only 8 are available");
4042 assert(collectExceptionMsg(
4043 randomSample(TestInputRange(), 12, 11)
4044 ) == "RandomSample: cannot sample 12 items when only 11 are available");
4045
4046 /* Check that sampling algorithm never accidentally overruns the end of
4047 * the input range. If input is an InputRange without .length, this
4048 * relies on the user specifying the total number of available items
4049 * correctly.
4050 */
4051 {
4052 uint i = 0;
4053 foreach (e; randomSample(a, a.length))
4054 {
4055 assert(e == i);
4056 ++i;
4057 }
4058 assert(i == a.length);
4059
4060 i = 0;
4061 foreach (e; randomSample(TestInputRange(), 17, 17))
4062 {
4063 assert(e == i);
4064 ++i;
4065 }
4066 assert(i == 17);
4067 }
4068
4069
4070 // Check length properties of random samples.
4071 assert(randomSample(a, 5).length == 5);
4072 assert(randomSample(a, 5, 10).length == 5);
4073 assert(randomSample(a, 5, rng).length == 5);
4074 assert(randomSample(a, 5, 10, rng).length == 5);
4075 assert(randomSample(TestInputRange(), 5, 10).length == 5);
4076 assert(randomSample(TestInputRange(), 5, 10, rng).length == 5);
4077
4078 // ... and emptiness!
4079 assert(randomSample(a, 0).empty);
4080 assert(randomSample(a, 0, 5).empty);
4081 assert(randomSample(a, 0, rng).empty);
4082 assert(randomSample(a, 0, 5, rng).empty);
4083 assert(randomSample(TestInputRange(), 0, 10).empty);
4084 assert(randomSample(TestInputRange(), 0, 10, rng).empty);
4085
4086 /* Test that the (lazy) evaluation of random samples works correctly.
4087 *
4088 * We cover 2 different cases: a sample where the ratio of sample points
4089 * to total points is greater than the threshold for using Algorithm, and
4090 * one where the ratio is small enough (< 1/13) for Algorithm D to be used.
4091 *
4092 * For each, we also cover the case with and without a specified RNG.
4093 */
4094 {
4095 // Small sample/source ratio, no specified RNG.
4096 uint i = 0;
4097 foreach (e; randomSample(randomCover(a), 5))
4098 {
4099 ++i;
4100 }
4101 assert(i == 5);
4102
4103 // Small sample/source ratio, specified RNG.
4104 i = 0;
4105 foreach (e; randomSample(randomCover(a), 5, rng))
4106 {
4107 ++i;
4108 }
4109 assert(i == 5);
4110
4111 // Large sample/source ratio, no specified RNG.
4112 i = 0;
4113 foreach (e; randomSample(TestInputRange(), 123, 123_456))
4114 {
4115 ++i;
4116 }
4117 assert(i == 123);
4118
4119 // Large sample/source ratio, specified RNG.
4120 i = 0;
4121 foreach (e; randomSample(TestInputRange(), 123, 123_456, rng))
4122 {
4123 ++i;
4124 }
4125 assert(i == 123);
4126
4127 /* Sample/source ratio large enough to start with Algorithm D,
4128 * small enough to switch to Algorithm A.
4129 */
4130 i = 0;
4131 foreach (e; randomSample(TestInputRange(), 10, 131))
4132 {
4133 ++i;
4134 }
4135 assert(i == 10);
4136 }
4137
4138 // Test that the .index property works correctly
4139 {
4140 auto sample1 = randomSample(TestInputRange(), 654, 654_321);
4141 for (; !sample1.empty; sample1.popFront())
4142 {
4143 assert(sample1.front == sample1.index);
4144 }
4145
4146 auto sample2 = randomSample(TestInputRange(), 654, 654_321, rng);
4147 for (; !sample2.empty; sample2.popFront())
4148 {
4149 assert(sample2.front == sample2.index);
4150 }
4151
4152 /* Check that it also works if .index is called before .front.
4153 * See: https://issues.dlang.org/show_bug.cgi?id=10322
4154 */
4155 auto sample3 = randomSample(TestInputRange(), 654, 654_321);
4156 for (; !sample3.empty; sample3.popFront())
4157 {
4158 assert(sample3.index == sample3.front);
4159 }
4160
4161 auto sample4 = randomSample(TestInputRange(), 654, 654_321, rng);
4162 for (; !sample4.empty; sample4.popFront())
4163 {
4164 assert(sample4.index == sample4.front);
4165 }
4166 }
4167
4168 /* Test behaviour if .popFront() is called before sample is read.
4169 * This is a rough-and-ready check that the statistical properties
4170 * are in the ballpark -- not a proper validation of statistical
4171 * quality! This incidentally also checks for reference-type
4172 * initialization bugs, as the foreach () loop will operate on a
4173 * copy of the popFronted (and hence initialized) sample.
4174 */
4175 {
4176 size_t count0, count1, count99;
4177 foreach (_; 0 .. 50_000)
4178 {
4179 auto sample = randomSample(iota(100), 5, &rng);
4180 sample.popFront();
4181 foreach (s; sample)
4182 {
4183 if (s == 0)
4184 {
4185 ++count0;
4186 }
4187 else if (s == 1)
4188 {
4189 ++count1;
4190 }
4191 else if (s == 99)
4192 {
4193 ++count99;
4194 }
4195 }
4196 }
4197 /* Statistical assumptions here: this is a sequential sampling process
4198 * so (i) 0 can only be the first sample point, so _can't_ be in the
4199 * remainder of the sample after .popFront() is called. (ii) By similar
4200 * token, 1 can only be in the remainder if it's the 2nd point of the
4201 * whole sample, and hence if 0 was the first; probability of 0 being
4202 * first and 1 second is 5/100 * 4/99 (thank you, Algorithm S:-) and
4203 * so the mean count of 1 should be about 202. Finally, 99 can only
4204 * be the _last_ sample point to be picked, so its probability of
4205 * inclusion should be independent of the .popFront() and it should
4206 * occur with frequency 5/100, hence its count should be about 5000.
4207 * Unfortunately we have to set quite a high tolerance because with
4208 * sample size small enough for unittests to run in reasonable time,
4209 * the variance can be quite high.
4210 */
4211 assert(count0 == 0);
4212 assert(count1 < 150, text("1: ", count1, " > 150."));
4213 assert(2_200 < count99, text("99: ", count99, " < 2200."));
4214 assert(count99 < 2_800, text("99: ", count99, " > 2800."));
4215 }
4216
4217 /* Odd corner-cases: RandomSample has 2 constructors that are not called
4218 * by the randomSample() helper functions, but that can be used if the
4219 * constructor is called directly. These cover the case of the user
4220 * specifying input but not input length.
4221 */
4222 {
4223 auto input1 = TestInputRange().takeExactly(456_789);
4224 static assert(hasLength!(typeof(input1)));
4225 auto sample1 = RandomSample!(typeof(input1), void)(input1, 789);
4226 static assert(isInputRange!(typeof(sample1)));
4227 static assert(!isForwardRange!(typeof(sample1)));
4228 assert(sample1.length == 789);
4229 assert(sample1._available == 456_789);
4230 uint i = 0;
4231 for (; !sample1.empty; sample1.popFront())
4232 {
4233 assert(sample1.front == sample1.index);
4234 ++i;
4235 }
4236 assert(i == 789);
4237
4238 auto input2 = TestInputRange().takeExactly(456_789);
4239 static assert(hasLength!(typeof(input2)));
4240 auto sample2 = RandomSample!(typeof(input2), typeof(rng))(input2, 789, rng);
4241 static assert(isInputRange!(typeof(sample2)));
4242 static assert(!isForwardRange!(typeof(sample2)));
4243 assert(sample2.length == 789);
4244 assert(sample2._available == 456_789);
4245 i = 0;
4246 for (; !sample2.empty; sample2.popFront())
4247 {
4248 assert(sample2.front == sample2.index);
4249 ++i;
4250 }
4251 assert(i == 789);
4252 }
4253
4254 /* Test that the save property works where input is a forward range,
4255 * and RandomSample is using a (forward range) random number generator
4256 * that is not rndGen.
4257 */
4258 static if (isForwardRange!UniformRNG)
4259 {
4260 auto sample1 = randomSample(a, 5, rng);
4261 // https://issues.dlang.org/show_bug.cgi?id=15853
4262 auto sample2 = ((const ref typeof(sample1) a) => a.save)(sample1);
4263 assert(sample1.array() == sample2.array());
4264 }
4265
4266 // https://issues.dlang.org/show_bug.cgi?id=8314
4267 {
4268 auto sample(RandomGen)(uint seed) { return randomSample(a, 1, RandomGen(seed)).front; }
4269
4270 // Start from 1 because not all RNGs accept 0 as seed.
4271 immutable fst = sample!UniformRNG(1);
4272 uint n = 1;
4273 while (sample!UniformRNG(++n) == fst && n < n.max) {}
4274 assert(n < n.max);
4275 }
4276 }();
4277 }