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