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