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 { 1777 // `getrandom()` was introduced in Linux 3.17. 1778 1779 // Shim for missing bindings in druntime 1780 version (none) 1781 import core.sys.linux.sys.random : getrandom; 1782 else 1783 { 1784 import core.sys.posix.sys.types : ssize_t; 1785 extern extern(C) ssize_t getrandom( 1786 void* buf, 1787 size_t buflen, 1788 uint flags, 1789 ) @system nothrow @nogc; 1790 } 1791 } 1792 1793 version (Windows) 1794 { 1795 pragma(lib, "Bcrypt.lib"); 1796 1797 private bool bcryptGenRandom(T)(out T result) @trusted 1798 { 1799 import core.sys.windows.windef : PUCHAR, ULONG; 1800 import core.sys.windows.ntdef : NT_SUCCESS; 1801 import core.sys.windows.bcrypt : BCryptGenRandom, BCRYPT_USE_SYSTEM_PREFERRED_RNG; 1802 1803 const gotRandom = BCryptGenRandom( 1804 null, 1805 cast(PUCHAR) &result, 1806 ULONG(T.sizeof), 1807 BCRYPT_USE_SYSTEM_PREFERRED_RNG, 1808 ); 1809 1810 return NT_SUCCESS(gotRandom); 1811 } 1812 } 1813 1814 /** 1815 A "good" seed for initializing random number engines. Initializing 1816 with $(D_PARAM unpredictableSeed) makes engines generate different 1817 random number sequences every run. 1818 1819 This function utilizes the system $(I cryptographically-secure pseudo-random 1820 number generator (CSPRNG)) or $(I pseudo-random number generator (PRNG)) 1821 where available and implemented (currently `arc4random` on applicable BSD 1822 systems, `getrandom` on Linux or `BCryptGenRandom` on Windows) to generate 1823 “high quality” pseudo-random numbers – if possible. 1824 As a consequence, calling it may block under certain circumstances (typically 1825 during early boot when the system's entropy pool has not yet been 1826 initialized). 1827 1828 On x86 CPU models which support the `RDRAND` instruction, that will be used 1829 when no more specialized randomness source is implemented. 1830 1831 In the future, further platform-specific PRNGs may be incorporated. 1832 1833 Warning: 1834 $(B This function must not be used for cryptographic purposes.) 1835 Despite being implemented for certain targets, there are no guarantees 1836 that it sources its randomness from a CSPRNG. 1837 The implementation also includes a fallback option that provides very little 1838 randomness and is used when no better source of randomness is available or 1839 integrated on the target system. 1840 As written earlier, this function only aims to provide randomness for seeding 1841 ordinary (non-cryptographic) PRNG engines. 1842 1843 Returns: 1844 A single unsigned integer seed value, different on each successive call 1845 Note: 1846 In general periodically 'reseeding' a PRNG does not improve its quality 1847 and in some cases may harm it. For an extreme example the Mersenne 1848 Twister has `2 ^^ 19937 - 1` distinct states but after `seed(uint)` is 1849 called it can only be in one of `2 ^^ 32` distinct states regardless of 1850 how excellent the source of entropy is. 1851 */ 1852 @property uint unpredictableSeed() @trusted nothrow @nogc 1853 { 1854 version (linux) 1855 { 1856 uint buffer; 1857 1858 /* 1859 getrandom(2): 1860 If the _urandom_ source has been initialized, reads of up to 1861 256 bytes will always return as many bytes as requested and 1862 will not be interrupted by signals. No such guarantees apply 1863 for larger buffer sizes. 1864 */ 1865 static assert(buffer.sizeof <= 256); 1866 1867 const status = (() @trusted => getrandom(&buffer, buffer.sizeof, 0))(); 1868 assert(status == buffer.sizeof); 1869 1870 return buffer; 1871 } 1872 else version (Windows) 1873 { 1874 uint result; 1875 if (!bcryptGenRandom!uint(result)) 1876 { 1877 version (none) 1878 return fallbackSeed(); 1879 else 1880 assert(false, "BCryptGenRandom() failed."); 1881 } 1882 return result; 1883 } 1884 else version (AnyARC4Random) 1885 { 1886 return arc4random(); 1887 } 1888 else 1889 { 1890 version (InlineAsm_X86_Any) 1891 { 1892 import core.cpuid : hasRdrand; 1893 if (hasRdrand) 1894 { 1895 uint result; 1896 asm @nogc nothrow 1897 { 1898 db 0x0f, 0xc7, 0xf0; // rdrand EAX 1899 jnc LnotUsingRdrand; 1900 mov result, EAX; 1901 // Some AMD CPUs shipped with bugs where RDRAND could fail 1902 // but still set the carry flag to 1. In those cases the 1903 // output will be -1. 1904 cmp EAX, 0xffff_ffff; 1905 jne LusingRdrand; 1906 // If result was -1 verify RDAND isn't constantly returning -1. 1907 db 0x0f, 0xc7, 0xf0; 1908 jnc LusingRdrand; 1909 cmp EAX, 0xffff_ffff; 1910 je LnotUsingRdrand; 1911 } 1912 LusingRdrand: 1913 return result; 1914 } 1915 LnotUsingRdrand: 1916 } 1917 return cast(uint) fallbackSeed(); 1918 } 1919 } 1920 1921 /// ditto 1922 template unpredictableSeed(UIntType) 1923 if (isUnsigned!UIntType) 1924 { 1925 static if (is(UIntType == uint)) 1926 alias unpredictableSeed = .unpredictableSeed; 1927 else static if (!is(Unqual!UIntType == UIntType)) 1928 alias unpredictableSeed = .unpredictableSeed!(Unqual!UIntType); 1929 else 1930 /// ditto 1931 @property UIntType unpredictableSeed() @nogc nothrow @trusted 1932 { 1933 version (linux) 1934 { 1935 UIntType buffer; 1936 1937 /* 1938 getrandom(2): 1939 If the _urandom_ source has been initialized, reads of up to 1940 256 bytes will always return as many bytes as requested and 1941 will not be interrupted by signals. No such guarantees apply 1942 for larger buffer sizes. 1943 */ 1944 static assert(buffer.sizeof <= 256); 1945 1946 const status = (() @trusted => getrandom(&buffer, buffer.sizeof, 0))(); 1947 assert(status == buffer.sizeof); 1948 1949 return buffer; 1950 } 1951 else version (Windows) 1952 { 1953 UIntType result; 1954 if (!bcryptGenRandom!UIntType(result)) 1955 { 1956 version (none) 1957 return fallbackSeed(); 1958 else 1959 assert(false, "BCryptGenRandom() failed."); 1960 } 1961 return result; 1962 } 1963 else version (AnyARC4Random) 1964 { 1965 static if (UIntType.sizeof <= uint.sizeof) 1966 { 1967 return cast(UIntType) arc4random(); 1968 } 1969 else 1970 { 1971 UIntType result = void; 1972 arc4random_buf(&result, UIntType.sizeof); 1973 return result; 1974 } 1975 } 1976 else 1977 { 1978 version (InlineAsm_X86_Any) 1979 { 1980 import core.cpuid : hasRdrand; 1981 if (hasRdrand) 1982 { 1983 static if (UIntType.sizeof <= uint.sizeof) 1984 { 1985 uint result; 1986 asm @nogc nothrow 1987 { 1988 db 0x0f, 0xc7, 0xf0; // rdrand EAX 1989 jnc LnotUsingRdrand; 1990 mov result, EAX; 1991 // Some AMD CPUs shipped with bugs where RDRAND could fail 1992 // but still set the carry flag to 1. In those cases the 1993 // output will be -1. 1994 cmp EAX, 0xffff_ffff; 1995 jne LusingRdrand; 1996 // If result was -1 verify RDAND isn't constantly returning -1. 1997 db 0x0f, 0xc7, 0xf0; 1998 jnc LusingRdrand; 1999 cmp EAX, 0xffff_ffff; 2000 je LnotUsingRdrand; 2001 } 2002 LusingRdrand: 2003 return cast(UIntType) result; 2004 } 2005 else version (D_InlineAsm_X86_64) 2006 { 2007 ulong result; 2008 asm @nogc nothrow 2009 { 2010 db 0x48, 0x0f, 0xc7, 0xf0; // rdrand RAX 2011 jnc LnotUsingRdrand; 2012 mov result, RAX; 2013 // Some AMD CPUs shipped with bugs where RDRAND could fail 2014 // but still set the carry flag to 1. In those cases the 2015 // output will be -1. 2016 cmp RAX, 0xffff_ffff_ffff_ffff; 2017 jne LusingRdrand; 2018 // If result was -1 verify RDAND isn't constantly returning -1. 2019 db 0x48, 0x0f, 0xc7, 0xf0; 2020 jnc LusingRdrand; 2021 cmp RAX, 0xffff_ffff_ffff_ffff; 2022 je LnotUsingRdrand; 2023 } 2024 LusingRdrand: 2025 return result; 2026 } 2027 else 2028 { 2029 uint resultLow, resultHigh; 2030 asm @nogc nothrow 2031 { 2032 db 0x0f, 0xc7, 0xf0; // rdrand EAX 2033 jnc LnotUsingRdrand; 2034 mov resultLow, EAX; 2035 db 0x0f, 0xc7, 0xf0; // rdrand EAX 2036 jnc LnotUsingRdrand; 2037 mov resultHigh, EAX; 2038 } 2039 if (resultLow != uint.max || resultHigh != uint.max) // Protect against AMD RDRAND bug. 2040 return ((cast(ulong) resultHigh) << 32) ^ resultLow; 2041 } 2042 } 2043 LnotUsingRdrand: 2044 } 2045 return cast(UIntType) fallbackSeed(); 2046 } 2047 } 2048 } 2049 2050 /// 2051 @safe @nogc unittest 2052 { 2053 auto rnd = Random(unpredictableSeed); 2054 auto n = rnd.front; 2055 static assert(is(typeof(n) == uint)); 2056 } 2057 2058 /** 2059 The "default", "favorite", "suggested" random number generator type on 2060 the current platform. It is an alias for one of the previously-defined 2061 generators. You may want to use it if (1) you need to generate some 2062 nice random numbers, and (2) you don't care for the minutiae of the 2063 method being used. 2064 */ 2065 2066 alias Random = Mt19937; 2067 2068 @safe @nogc unittest 2069 { 2070 static assert(isUniformRNG!Random); 2071 static assert(isUniformRNG!(Random, uint)); 2072 static assert(isSeedable!Random); 2073 static assert(isSeedable!(Random, uint)); 2074 } 2075 2076 /** 2077 Global random number generator used by various functions in this 2078 module whenever no generator is specified. It is allocated per-thread 2079 and initialized to an unpredictable value for each thread. 2080 2081 Returns: 2082 A singleton instance of the default random number generator 2083 */ 2084 @property ref Random rndGen() @safe nothrow @nogc 2085 { 2086 static Random result; 2087 static bool initialized; 2088 if (!initialized) 2089 { 2090 static if (isSeedable!(Random, ulong)) 2091 result.seed(unpredictableSeed!ulong); // Avoid unnecessary copy. 2092 else static if (is(Random : MersenneTwisterEngine!Params, Params...)) 2093 initMTEngine(result); 2094 else static if (isSeedable!(Random, uint)) 2095 result.seed(unpredictableSeed!uint); // Avoid unnecessary copy. 2096 else 2097 result = Random(unpredictableSeed); 2098 initialized = true; 2099 } 2100 return result; 2101 } 2102 2103 /// 2104 @safe nothrow @nogc unittest 2105 { 2106 import std.algorithm.iteration : sum; 2107 import std.range : take; 2108 auto rnd = rndGen; 2109 assert(rnd.take(3).sum > 0); 2110 } 2111 2112 /+ 2113 Initialize a 32-bit MersenneTwisterEngine from 64 bits of entropy. 2114 This is private and accepts no seed as a parameter, freeing the internal 2115 implementaton from any need for stability across releases. 2116 +/ 2117 private void initMTEngine(MTEngine)(scope ref MTEngine mt) 2118 if (is(MTEngine : MersenneTwisterEngine!Params, Params...)) 2119 { 2120 pragma(inline, false); // Called no more than once per thread by rndGen. 2121 ulong seed = unpredictableSeed!ulong; 2122 static if (is(typeof(mt.seed(seed)))) 2123 { 2124 mt.seed(seed); 2125 } 2126 else 2127 { 2128 alias UIntType = typeof(mt.front()); 2129 if (seed == 0) seed = -1; // Any number but 0 is fine. 2130 uint s0 = cast(uint) seed; 2131 uint s1 = cast(uint) (seed >> 32); 2132 foreach (ref e; mt.state.data) 2133 { 2134 //http://xoshiro.di.unimi.it/xoroshiro64starstar.c 2135 const tmp = s0 * 0x9E3779BB; 2136 e = ((tmp << 5) | (tmp >> (32 - 5))) * 5; 2137 static if (MTEngine.max != UIntType.max) { e &= MTEngine.max; } 2138 2139 const tmp1 = s0 ^ s1; 2140 s0 = ((s0 << 26) | (s0 >> (32 - 26))) ^ tmp1 ^ (tmp1 << 9); 2141 s1 = (tmp1 << 13) | (tmp1 >> (32 - 13)); 2142 } 2143 2144 mt.state.index = mt.state.data.length - 1; 2145 // double popFront() to guarantee both `mt.state.z` 2146 // and `mt.state.front` are derived from the newly 2147 // set values in `mt.state.data`. 2148 mt.popFront(); 2149 mt.popFront(); 2150 } 2151 } 2152 2153 /** 2154 Generates a number between `a` and `b`. The `boundaries` 2155 parameter controls the shape of the interval (open vs. closed on 2156 either side). Valid values for `boundaries` are `"[]"`, $(D 2157 "$(LPAREN)]"), `"[$(RPAREN)"`, and `"()"`. The default interval 2158 is closed to the left and open to the right. The version that does not 2159 take `urng` uses the default generator `rndGen`. 2160 2161 Params: 2162 a = lower bound of the _uniform distribution 2163 b = upper bound of the _uniform distribution 2164 urng = (optional) random number generator to use; 2165 if not specified, defaults to `rndGen` 2166 2167 Returns: 2168 A single random variate drawn from the _uniform distribution 2169 between `a` and `b`, whose type is the common type of 2170 these parameters 2171 */ 2172 auto uniform(string boundaries = "[)", T1, T2) 2173 (T1 a, T2 b) 2174 if (!is(CommonType!(T1, T2) == void)) 2175 { 2176 return uniform!(boundaries, T1, T2, Random)(a, b, rndGen); 2177 } 2178 2179 /// 2180 @safe unittest 2181 { 2182 auto rnd = Random(unpredictableSeed); 2183 2184 // Generate an integer in [0, 1023] 2185 auto a = uniform(0, 1024, rnd); 2186 assert(0 <= a && a < 1024); 2187 2188 // Generate a float in [0, 1) 2189 auto b = uniform(0.0f, 1.0f, rnd); 2190 assert(0 <= b && b < 1); 2191 2192 // Generate a float in [0, 1] 2193 b = uniform!"[]"(0.0f, 1.0f, rnd); 2194 assert(0 <= b && b <= 1); 2195 2196 // Generate a float in (0, 1) 2197 b = uniform!"()"(0.0f, 1.0f, rnd); 2198 assert(0 < b && b < 1); 2199 } 2200 2201 /// Create an array of random numbers using range functions and UFCS 2202 @safe unittest 2203 { 2204 import std.array : array; 2205 import std.range : generate, takeExactly; 2206 2207 int[] arr = generate!(() => uniform(0, 100)).takeExactly(10).array; 2208 assert(arr.length == 10); 2209 assert(arr[0] >= 0 && arr[0] < 100); 2210 } 2211 2212 @safe unittest 2213 { 2214 MinstdRand0 gen; 2215 foreach (i; 0 .. 20) 2216 { 2217 auto x = uniform(0.0, 15.0, gen); 2218 assert(0 <= x && x < 15); 2219 } 2220 foreach (i; 0 .. 20) 2221 { 2222 auto x = uniform!"[]"('a', 'z', gen); 2223 assert('a' <= x && x <= 'z'); 2224 } 2225 2226 foreach (i; 0 .. 20) 2227 { 2228 auto x = uniform('a', 'z', gen); 2229 assert('a' <= x && x < 'z'); 2230 } 2231 2232 foreach (i; 0 .. 20) 2233 { 2234 immutable ubyte a = 0; 2235 immutable ubyte b = 15; 2236 auto x = uniform(a, b, gen); 2237 assert(a <= x && x < b); 2238 } 2239 } 2240 2241 // Implementation of uniform for floating-point types 2242 /// ditto 2243 auto uniform(string boundaries = "[)", 2244 T1, T2, UniformRandomNumberGenerator) 2245 (T1 a, T2 b, ref UniformRandomNumberGenerator urng) 2246 if (isFloatingPoint!(CommonType!(T1, T2)) && isUniformRNG!UniformRandomNumberGenerator) 2247 { 2248 import std.conv : text; 2249 import std.exception : enforce; 2250 alias NumberType = Unqual!(CommonType!(T1, T2)); 2251 static if (boundaries[0] == '(') 2252 { 2253 import std.math.operations : nextafter; 2254 NumberType _a = nextafter(cast(NumberType) a, NumberType.infinity); 2255 } 2256 else 2257 { 2258 NumberType _a = a; 2259 } 2260 static if (boundaries[1] == ')') 2261 { 2262 import std.math.operations : nextafter; 2263 NumberType _b = nextafter(cast(NumberType) b, -NumberType.infinity); 2264 } 2265 else 2266 { 2267 NumberType _b = b; 2268 } 2269 enforce(_a <= _b, 2270 text("std.random.uniform(): invalid bounding interval ", 2271 boundaries[0], a, ", ", b, boundaries[1])); 2272 NumberType result = 2273 _a + (_b - _a) * cast(NumberType) (urng.front - urng.min) 2274 / (urng.max - urng.min); 2275 urng.popFront(); 2276 return result; 2277 } 2278 2279 // Implementation of uniform for integral types 2280 /+ Description of algorithm and suggestion of correctness: 2281 2282 The modulus operator maps an integer to a small, finite space. For instance, `x 2283 % 3` will map whatever x is into the range [0 .. 3). 0 maps to 0, 1 maps to 1, 2 2284 maps to 2, 3 maps to 0, and so on infinitely. As long as the integer is 2285 uniformly chosen from the infinite space of all non-negative integers then `x % 2286 3` will uniformly fall into that range. 2287 2288 (Non-negative is important in this case because some definitions of modulus, 2289 namely the one used in computers generally, map negative numbers differently to 2290 (-3 .. 0]. `uniform` does not use negative number modulus, thus we can safely 2291 ignore that fact.) 2292 2293 The issue with computers is that integers have a finite space they must fit in, 2294 and our uniformly chosen random number is picked in that finite space. So, that 2295 method is not sufficient. You can look at it as the integer space being divided 2296 into "buckets" and every bucket after the first bucket maps directly into that 2297 first bucket. `[0, 1, 2]`, `[3, 4, 5]`, ... When integers are finite, then the 2298 last bucket has the chance to be "incomplete": `[uint.max - 3, uint.max - 2, 2299 uint.max - 1]`, `[uint.max]` ... (the last bucket only has 1!). The issue here 2300 is that _every_ bucket maps _completely_ to the first bucket except for that 2301 last one. The last one doesn't have corresponding mappings to 1 or 2, in this 2302 case, which makes it unfair. 2303 2304 So, the answer is to simply "reroll" if you're in that last bucket, since it's 2305 the only unfair one. Eventually you'll roll into a fair bucket. Simply, instead 2306 of the meaning of the last bucket being "maps to `[0]`", it changes to "maps to 2307 `[0, 1, 2]`", which is precisely what we want. 2308 2309 To generalize, `upperDist` represents the size of our buckets (and, thus, the 2310 exclusive upper bound for our desired uniform number). `rnum` is a uniformly 2311 random number picked from the space of integers that a computer can hold (we'll 2312 say `UpperType` represents that type). 2313 2314 We'll first try to do the mapping into the first bucket by doing `offset = rnum 2315 % upperDist`. We can figure out the position of the front of the bucket we're in 2316 by `bucketFront = rnum - offset`. 2317 2318 If we start at `UpperType.max` and walk backwards `upperDist - 1` spaces, then 2319 the space we land on is the last acceptable position where a full bucket can 2320 fit: 2321 2322 --- 2323 bucketFront UpperType.max 2324 v v 2325 [..., 0, 1, 2, ..., upperDist - 1] 2326 ^~~ upperDist - 1 ~~^ 2327 --- 2328 2329 If the bucket starts any later, then it must have lost at least one number and 2330 at least that number won't be represented fairly. 2331 2332 --- 2333 bucketFront UpperType.max 2334 v v 2335 [..., upperDist - 1, 0, 1, 2, ..., upperDist - 2] 2336 ^~~~~~~~ upperDist - 1 ~~~~~~~^ 2337 --- 2338 2339 Hence, our condition to reroll is 2340 `bucketFront > (UpperType.max - (upperDist - 1))` 2341 +/ 2342 /// ditto 2343 auto uniform(string boundaries = "[)", T1, T2, RandomGen) 2344 (T1 a, T2 b, ref RandomGen rng) 2345 if ((isIntegral!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2))) && 2346 isUniformRNG!RandomGen) 2347 { 2348 import std.conv : text, unsigned; 2349 import std.exception : enforce; 2350 alias ResultType = Unqual!(CommonType!(T1, T2)); 2351 static if (boundaries[0] == '(') 2352 { 2353 enforce(a < ResultType.max, 2354 text("std.random.uniform(): invalid left bound ", a)); 2355 ResultType lower = cast(ResultType) (a + 1); 2356 } 2357 else 2358 { 2359 ResultType lower = a; 2360 } 2361 2362 static if (boundaries[1] == ']') 2363 { 2364 enforce(lower <= b, 2365 text("std.random.uniform(): invalid bounding interval ", 2366 boundaries[0], a, ", ", b, boundaries[1])); 2367 /* Cannot use this next optimization with dchar, as dchar 2368 * only partially uses its full bit range 2369 */ 2370 static if (!is(ResultType == dchar)) 2371 { 2372 if (b == ResultType.max && lower == ResultType.min) 2373 { 2374 // Special case - all bits are occupied 2375 return std.random.uniform!ResultType(rng); 2376 } 2377 } 2378 auto upperDist = unsigned(b - lower) + 1u; 2379 } 2380 else 2381 { 2382 enforce(lower < b, 2383 text("std.random.uniform(): invalid bounding interval ", 2384 boundaries[0], a, ", ", b, boundaries[1])); 2385 auto upperDist = unsigned(b - lower); 2386 } 2387 2388 assert(upperDist != 0); 2389 2390 alias UpperType = typeof(upperDist); 2391 static assert(UpperType.min == 0); 2392 2393 UpperType offset, rnum, bucketFront; 2394 do 2395 { 2396 rnum = uniform!UpperType(rng); 2397 offset = rnum % upperDist; 2398 bucketFront = rnum - offset; 2399 } // while we're in an unfair bucket... 2400 while (bucketFront > (UpperType.max - (upperDist - 1))); 2401 2402 return cast(ResultType)(lower + offset); 2403 } 2404 2405 /// 2406 @safe unittest 2407 { 2408 import std.conv : to; 2409 import std.meta : AliasSeq; 2410 import std.range.primitives : isForwardRange; 2411 import std.traits : isIntegral, isSomeChar; 2412 2413 auto gen = Mt19937(123_456_789); 2414 static assert(isForwardRange!(typeof(gen))); 2415 2416 auto a = uniform(0, 1024, gen); 2417 assert(0 <= a && a <= 1024); 2418 auto b = uniform(0.0f, 1.0f, gen); 2419 assert(0 <= b && b < 1, to!string(b)); 2420 auto c = uniform(0.0, 1.0); 2421 assert(0 <= c && c < 1); 2422 2423 static foreach (T; AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort, 2424 int, uint, long, ulong, float, double, real)) 2425 {{ 2426 T lo = 0, hi = 100; 2427 2428 // Try tests with each of the possible bounds 2429 { 2430 T init = uniform(lo, hi); 2431 size_t i = 50; 2432 while (--i && uniform(lo, hi) == init) {} 2433 assert(i > 0); 2434 } 2435 { 2436 T init = uniform!"[)"(lo, hi); 2437 size_t i = 50; 2438 while (--i && uniform(lo, hi) == init) {} 2439 assert(i > 0); 2440 } 2441 { 2442 T init = uniform!"(]"(lo, hi); 2443 size_t i = 50; 2444 while (--i && uniform(lo, hi) == init) {} 2445 assert(i > 0); 2446 } 2447 { 2448 T init = uniform!"()"(lo, hi); 2449 size_t i = 50; 2450 while (--i && uniform(lo, hi) == init) {} 2451 assert(i > 0); 2452 } 2453 { 2454 T init = uniform!"[]"(lo, hi); 2455 size_t i = 50; 2456 while (--i && uniform(lo, hi) == init) {} 2457 assert(i > 0); 2458 } 2459 2460 /* Test case with closed boundaries covering whole range 2461 * of integral type 2462 */ 2463 static if (isIntegral!T || isSomeChar!T) 2464 { 2465 foreach (immutable _; 0 .. 100) 2466 { 2467 auto u = uniform!"[]"(T.min, T.max); 2468 static assert(is(typeof(u) == T)); 2469 assert(T.min <= u, "Lower bound violation for uniform!\"[]\" with " ~ T.stringof); 2470 assert(u <= T.max, "Upper bound violation for uniform!\"[]\" with " ~ T.stringof); 2471 } 2472 } 2473 }} 2474 2475 auto reproRng = Xorshift(239842); 2476 2477 static foreach (T; AliasSeq!(char, wchar, dchar, byte, ubyte, short, 2478 ushort, int, uint, long, ulong)) 2479 {{ 2480 T lo = T.min + 10, hi = T.max - 10; 2481 T init = uniform(lo, hi, reproRng); 2482 size_t i = 50; 2483 while (--i && uniform(lo, hi, reproRng) == init) {} 2484 assert(i > 0); 2485 }} 2486 2487 { 2488 bool sawLB = false, sawUB = false; 2489 foreach (i; 0 .. 50) 2490 { 2491 auto x = uniform!"[]"('a', 'd', reproRng); 2492 if (x == 'a') sawLB = true; 2493 if (x == 'd') sawUB = true; 2494 assert('a' <= x && x <= 'd'); 2495 } 2496 assert(sawLB && sawUB); 2497 } 2498 2499 { 2500 bool sawLB = false, sawUB = false; 2501 foreach (i; 0 .. 50) 2502 { 2503 auto x = uniform('a', 'd', reproRng); 2504 if (x == 'a') sawLB = true; 2505 if (x == 'c') sawUB = true; 2506 assert('a' <= x && x < 'd'); 2507 } 2508 assert(sawLB && sawUB); 2509 } 2510 2511 { 2512 bool sawLB = false, sawUB = false; 2513 foreach (i; 0 .. 50) 2514 { 2515 immutable int lo = -2, hi = 2; 2516 auto x = uniform!"()"(lo, hi, reproRng); 2517 if (x == (lo+1)) sawLB = true; 2518 if (x == (hi-1)) sawUB = true; 2519 assert(lo < x && x < hi); 2520 } 2521 assert(sawLB && sawUB); 2522 } 2523 2524 { 2525 bool sawLB = false, sawUB = false; 2526 foreach (i; 0 .. 50) 2527 { 2528 immutable ubyte lo = 0, hi = 5; 2529 auto x = uniform(lo, hi, reproRng); 2530 if (x == lo) sawLB = true; 2531 if (x == (hi-1)) sawUB = true; 2532 assert(lo <= x && x < hi); 2533 } 2534 assert(sawLB && sawUB); 2535 } 2536 2537 { 2538 foreach (i; 0 .. 30) 2539 { 2540 assert(i == uniform(i, i+1, reproRng)); 2541 } 2542 } 2543 } 2544 2545 /+ 2546 Generates an unsigned integer in the half-open range `[0, k)`. 2547 Non-public because we locally guarantee `k > 0`. 2548 2549 Params: 2550 k = unsigned exclusive upper bound; caller guarantees this is non-zero 2551 rng = random number generator to use 2552 2553 Returns: 2554 Pseudo-random unsigned integer strictly less than `k`. 2555 +/ 2556 private UInt _uniformIndex(UniformRNG, UInt = size_t)(const UInt k, ref UniformRNG rng) 2557 if (isUnsigned!UInt && isUniformRNG!UniformRNG) 2558 { 2559 alias ResultType = UInt; 2560 alias UpperType = Unsigned!(typeof(k - 0)); 2561 alias upperDist = k; 2562 2563 assert(upperDist != 0); 2564 2565 // For backwards compatibility use same algorithm as uniform(0, k, rng). 2566 UpperType offset, rnum, bucketFront; 2567 do 2568 { 2569 rnum = uniform!UpperType(rng); 2570 offset = rnum % upperDist; 2571 bucketFront = rnum - offset; 2572 } // while we're in an unfair bucket... 2573 while (bucketFront > (UpperType.max - (upperDist - 1))); 2574 2575 return cast(ResultType) offset; 2576 } 2577 2578 pure @safe unittest 2579 { 2580 // For backwards compatibility check that _uniformIndex(k, rng) 2581 // has the same result as uniform(0, k, rng). 2582 auto rng1 = Xorshift(123_456_789); 2583 auto rng2 = rng1.save(); 2584 const size_t k = (1U << 31) - 1; 2585 assert(_uniformIndex(k, rng1) == uniform(0, k, rng2)); 2586 } 2587 2588 /** 2589 Generates a uniformly-distributed number in the range $(D [T.min, 2590 T.max]) for any integral or character type `T`. If no random 2591 number generator is passed, uses the default `rndGen`. 2592 2593 If an `enum` is used as type, the random variate is drawn with 2594 equal probability from any of the possible values of the enum `E`. 2595 2596 Params: 2597 urng = (optional) random number generator to use; 2598 if not specified, defaults to `rndGen` 2599 2600 Returns: 2601 Random variate drawn from the _uniform distribution across all 2602 possible values of the integral, character or enum type `T`. 2603 */ 2604 auto uniform(T, UniformRandomNumberGenerator) 2605 (ref UniformRandomNumberGenerator urng) 2606 if (!is(T == enum) && (isIntegral!T || isSomeChar!T) && isUniformRNG!UniformRandomNumberGenerator) 2607 { 2608 /* dchar does not use its full bit range, so we must 2609 * revert to the uniform with specified bounds 2610 */ 2611 static if (is(immutable T == immutable dchar)) 2612 { 2613 return uniform!"[]"(T.min, T.max, urng); 2614 } 2615 else 2616 { 2617 auto r = urng.front; 2618 urng.popFront(); 2619 static if (T.sizeof <= r.sizeof) 2620 { 2621 return cast(T) r; 2622 } 2623 else 2624 { 2625 static assert(T.sizeof == 8 && r.sizeof == 4); 2626 T r1 = urng.front | (cast(T) r << 32); 2627 urng.popFront(); 2628 return r1; 2629 } 2630 } 2631 } 2632 2633 /// Ditto 2634 auto uniform(T)() 2635 if (!is(T == enum) && (isIntegral!T || isSomeChar!T)) 2636 { 2637 return uniform!T(rndGen); 2638 } 2639 2640 /// 2641 @safe unittest 2642 { 2643 auto rnd = MinstdRand0(42); 2644 2645 assert(rnd.uniform!ubyte == 102); 2646 assert(rnd.uniform!ulong == 4838462006927449017); 2647 2648 enum Fruit { apple, mango, pear } 2649 version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 2650 assert(rnd.uniform!Fruit == Fruit.mango); 2651 } 2652 2653 @safe unittest 2654 { 2655 // https://issues.dlang.org/show_bug.cgi?id=21383 2656 auto rng1 = Xorshift32(123456789); 2657 auto rng2 = rng1.save; 2658 assert(rng1.uniform!dchar == rng2.uniform!dchar); 2659 // https://issues.dlang.org/show_bug.cgi?id=21384 2660 assert(rng1.uniform!(const shared dchar) <= dchar.max); 2661 // https://issues.dlang.org/show_bug.cgi?id=8671 2662 double t8671 = 1.0 - uniform(0.0, 1.0); 2663 } 2664 2665 @safe unittest 2666 { 2667 static foreach (T; std.meta.AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort, 2668 int, uint, long, ulong)) 2669 {{ 2670 T init = uniform!T(); 2671 size_t i = 50; 2672 while (--i && uniform!T() == init) {} 2673 assert(i > 0); 2674 2675 foreach (immutable _; 0 .. 100) 2676 { 2677 auto u = uniform!T(); 2678 static assert(is(typeof(u) == T)); 2679 assert(T.min <= u, "Lower bound violation for uniform!" ~ T.stringof); 2680 assert(u <= T.max, "Upper bound violation for uniform!" ~ T.stringof); 2681 } 2682 }} 2683 } 2684 2685 /// ditto 2686 auto uniform(E, UniformRandomNumberGenerator) 2687 (ref UniformRandomNumberGenerator urng) 2688 if (is(E == enum) && isUniformRNG!UniformRandomNumberGenerator) 2689 { 2690 static immutable E[EnumMembers!E.length] members = [EnumMembers!E]; 2691 return members[std.random.uniform(0, members.length, urng)]; 2692 } 2693 2694 /// Ditto 2695 auto uniform(E)() 2696 if (is(E == enum)) 2697 { 2698 return uniform!E(rndGen); 2699 } 2700 2701 @safe unittest 2702 { 2703 enum Fruit { Apple = 12, Mango = 29, Pear = 72 } 2704 foreach (_; 0 .. 100) 2705 { 2706 foreach (f; [uniform!Fruit(), rndGen.uniform!Fruit()]) 2707 { 2708 assert(f == Fruit.Apple || f == Fruit.Mango || f == Fruit.Pear); 2709 } 2710 } 2711 } 2712 2713 /** 2714 * Generates a uniformly-distributed floating point number of type 2715 * `T` in the range [0, 1$(RPAREN). If no random number generator is 2716 * specified, the default RNG `rndGen` will be used as the source 2717 * of randomness. 2718 * 2719 * `uniform01` offers a faster generation of random variates than 2720 * the equivalent $(D uniform!"[$(RPAREN)"(0.0, 1.0)) and so may be preferred 2721 * for some applications. 2722 * 2723 * Params: 2724 * rng = (optional) random number generator to use; 2725 * if not specified, defaults to `rndGen` 2726 * 2727 * Returns: 2728 * Floating-point random variate of type `T` drawn from the _uniform 2729 * distribution across the half-open interval [0, 1$(RPAREN). 2730 * 2731 */ 2732 T uniform01(T = double)() 2733 if (isFloatingPoint!T) 2734 { 2735 return uniform01!T(rndGen); 2736 } 2737 2738 /// ditto 2739 T uniform01(T = double, UniformRNG)(ref UniformRNG rng) 2740 if (isFloatingPoint!T && isUniformRNG!UniformRNG) 2741 out (result) 2742 { 2743 assert(0 <= result); 2744 assert(result < 1); 2745 } 2746 do 2747 { 2748 alias R = typeof(rng.front); 2749 static if (isIntegral!R) 2750 { 2751 enum T factor = 1 / (T(1) + rng.max - rng.min); 2752 } 2753 else static if (isFloatingPoint!R) 2754 { 2755 enum T factor = 1 / (rng.max - rng.min); 2756 } 2757 else 2758 { 2759 static assert(false); 2760 } 2761 2762 while (true) 2763 { 2764 immutable T u = (rng.front - rng.min) * factor; 2765 rng.popFront(); 2766 2767 static if (isIntegral!R && T.mant_dig >= (8 * R.sizeof)) 2768 { 2769 /* If RNG variates are integral and T has enough precision to hold 2770 * R without loss, we're guaranteed by the definition of factor 2771 * that precisely u < 1. 2772 */ 2773 return u; 2774 } 2775 else 2776 { 2777 /* Otherwise we have to check whether u is beyond the assumed range 2778 * because of the loss of precision, or for another reason, a 2779 * floating-point RNG can return a variate that is exactly equal to 2780 * its maximum. 2781 */ 2782 if (u < 1) 2783 { 2784 return u; 2785 } 2786 } 2787 } 2788 2789 // Shouldn't ever get here. 2790 assert(false); 2791 } 2792 2793 /// 2794 @safe @nogc unittest 2795 { 2796 import std.math.operations : feqrel; 2797 2798 auto rnd = MinstdRand0(42); 2799 2800 // Generate random numbers in the range in the range [0, 1) 2801 auto u1 = uniform01(rnd); 2802 assert(u1 >= 0 && u1 < 1); 2803 2804 auto u2 = rnd.uniform01!float; 2805 assert(u2 >= 0 && u2 < 1); 2806 2807 // Confirm that the random values with the initial seed 42 are 0.000328707 and 0.524587 2808 assert(u1.feqrel(0.000328707) > 20); 2809 assert(u2.feqrel(0.524587) > 20); 2810 } 2811 2812 @safe @nogc unittest 2813 { 2814 import std.meta; 2815 static foreach (UniformRNG; PseudoRngTypes) 2816 {{ 2817 2818 static foreach (T; std.meta.AliasSeq!(float, double, real)) 2819 {{ 2820 UniformRNG rng = UniformRNG(123_456_789); 2821 2822 auto a = uniform01(); 2823 assert(is(typeof(a) == double)); 2824 assert(0 <= a && a < 1); 2825 2826 auto b = uniform01(rng); 2827 assert(is(typeof(a) == double)); 2828 assert(0 <= b && b < 1); 2829 2830 auto c = uniform01!T(); 2831 assert(is(typeof(c) == T)); 2832 assert(0 <= c && c < 1); 2833 2834 auto d = uniform01!T(rng); 2835 assert(is(typeof(d) == T)); 2836 assert(0 <= d && d < 1); 2837 2838 T init = uniform01!T(rng); 2839 size_t i = 50; 2840 while (--i && uniform01!T(rng) == init) {} 2841 assert(i > 0); 2842 assert(i < 50); 2843 }} 2844 }} 2845 } 2846 2847 /** 2848 Generates a uniform probability distribution of size `n`, i.e., an 2849 array of size `n` of positive numbers of type `F` that sum to 2850 `1`. If `useThis` is provided, it is used as storage. 2851 */ 2852 F[] uniformDistribution(F = double)(size_t n, F[] useThis = null) 2853 if (isFloatingPoint!F) 2854 { 2855 import std.numeric : normalize; 2856 useThis.length = n; 2857 foreach (ref e; useThis) 2858 { 2859 e = uniform(0.0, 1); 2860 } 2861 normalize(useThis); 2862 return useThis; 2863 } 2864 2865 /// 2866 @safe unittest 2867 { 2868 import std.algorithm.iteration : reduce; 2869 import std.math.operations : isClose; 2870 2871 auto a = uniformDistribution(5); 2872 assert(a.length == 5); 2873 assert(isClose(reduce!"a + b"(a), 1)); 2874 2875 a = uniformDistribution(10, a); 2876 assert(a.length == 10); 2877 assert(isClose(reduce!"a + b"(a), 1)); 2878 } 2879 2880 /** 2881 Returns a random, uniformly chosen, element `e` from the supplied 2882 $(D Range range). If no random number generator is passed, the default 2883 `rndGen` is used. 2884 2885 Params: 2886 range = a random access range that has the `length` property defined 2887 urng = (optional) random number generator to use; 2888 if not specified, defaults to `rndGen` 2889 2890 Returns: 2891 A single random element drawn from the `range`. If it can, it will 2892 return a `ref` to the $(D range element), otherwise it will return 2893 a copy. 2894 */ 2895 auto ref choice(Range, RandomGen = Random)(Range range, ref RandomGen urng) 2896 if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen) 2897 { 2898 assert(range.length > 0, 2899 __PRETTY_FUNCTION__ ~ ": invalid Range supplied. Range cannot be empty"); 2900 2901 return range[uniform(size_t(0), $, urng)]; 2902 } 2903 2904 /// ditto 2905 auto ref choice(Range)(Range range) 2906 { 2907 return choice(range, rndGen); 2908 } 2909 2910 /// ditto 2911 auto ref choice(Range, RandomGen = Random)(ref Range range, ref RandomGen urng) 2912 if (isRandomAccessRange!Range && hasLength!Range && isUniformRNG!RandomGen) 2913 { 2914 assert(range.length > 0, 2915 __PRETTY_FUNCTION__ ~ ": invalid Range supplied. Range cannot be empty"); 2916 return range[uniform(size_t(0), $, urng)]; 2917 } 2918 2919 /// ditto 2920 auto ref choice(Range)(ref Range range) 2921 { 2922 return choice(range, rndGen); 2923 } 2924 2925 /// 2926 @safe unittest 2927 { 2928 auto rnd = MinstdRand0(42); 2929 2930 auto elem = [1, 2, 3, 4, 5].choice(rnd); 2931 version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 2932 assert(elem == 3); 2933 } 2934 2935 @safe unittest 2936 { 2937 import std.algorithm.searching : canFind; 2938 2939 static class MyTestClass 2940 { 2941 int x; 2942 2943 this(int x) 2944 { 2945 this.x = x; 2946 } 2947 } 2948 2949 MyTestClass[] testClass; 2950 foreach (i; 0 .. 5) 2951 { 2952 testClass ~= new MyTestClass(i); 2953 } 2954 2955 auto elem = choice(testClass); 2956 2957 assert(canFind!((ref MyTestClass a, ref MyTestClass b) => a.x == b.x)(testClass, elem), 2958 "Choice did not return a valid element from the given Range"); 2959 } 2960 2961 @system unittest 2962 { 2963 import std.algorithm.iteration : map; 2964 import std.algorithm.searching : canFind; 2965 2966 auto array = [1, 2, 3, 4, 5]; 2967 auto elemAddr = &choice(array); 2968 2969 assert(array.map!((ref e) => &e).canFind(elemAddr), 2970 "Choice did not return a ref to an element from the given Range"); 2971 assert(array.canFind(*(cast(int *)(elemAddr))), 2972 "Choice did not return a valid element from the given Range"); 2973 } 2974 2975 @safe unittest // https://issues.dlang.org/show_bug.cgi?id=18631 2976 { 2977 auto rng = MinstdRand0(42); 2978 const a = [0,1,2]; 2979 const(int[]) b = [0, 1, 2]; 2980 auto x = choice(a); 2981 auto y = choice(b); 2982 auto z = choice(cast(const)[1, 2, 3]); 2983 auto x1 = choice(a, rng); 2984 auto y1 = choice(b, rng); 2985 auto z1 = choice(cast(const)[1, 2, 3], rng); 2986 } 2987 2988 @safe unittest // Ref range (https://issues.dlang.org/show_bug.cgi?id=18631 PR) 2989 { 2990 struct TestRange 2991 { 2992 int x; 2993 ref int front() return {return x;} 2994 ref int back() return {return x;} 2995 void popFront() {} 2996 void popBack() {} 2997 bool empty = false; 2998 TestRange save() {return this;} 2999 size_t length = 10; 3000 alias opDollar = length; 3001 ref int opIndex(size_t i) return {return x;} 3002 } 3003 3004 TestRange r = TestRange(10); 3005 int* s = &choice(r); 3006 } 3007 3008 /** 3009 Shuffles elements of `r` using `gen` as a shuffler. `r` must be 3010 a random-access range with length. If no RNG is specified, `rndGen` 3011 will be used. 3012 3013 Params: 3014 r = random-access range whose elements are to be shuffled 3015 gen = (optional) random number generator to use; if not 3016 specified, defaults to `rndGen` 3017 Returns: 3018 The shuffled random-access range. 3019 */ 3020 3021 Range randomShuffle(Range, RandomGen)(Range r, ref RandomGen gen) 3022 if (isRandomAccessRange!Range && isUniformRNG!RandomGen) 3023 { 3024 import std.algorithm.mutation : swapAt; 3025 const n = r.length; 3026 foreach (i; 0 .. n) 3027 { 3028 r.swapAt(i, i + _uniformIndex(n - i, gen)); 3029 } 3030 return r; 3031 } 3032 3033 /// ditto 3034 Range randomShuffle(Range)(Range r) 3035 if (isRandomAccessRange!Range) 3036 { 3037 return randomShuffle(r, rndGen); 3038 } 3039 3040 /// 3041 @safe unittest 3042 { 3043 auto rnd = MinstdRand0(42); 3044 3045 auto arr = [1, 2, 3, 4, 5].randomShuffle(rnd); 3046 version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 3047 assert(arr == [3, 5, 2, 4, 1]); 3048 } 3049 3050 @safe unittest 3051 { 3052 int[10] sa = void; 3053 int[10] sb = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 3054 import std.algorithm.sorting : sort; 3055 foreach (RandomGen; PseudoRngTypes) 3056 { 3057 sa[] = sb[]; 3058 auto a = sa[]; 3059 auto b = sb[]; 3060 auto gen = RandomGen(123_456_789); 3061 randomShuffle(a, gen); 3062 sort(a); 3063 assert(a == b); 3064 randomShuffle(a); 3065 sort(a); 3066 assert(a == b); 3067 } 3068 // For backwards compatibility verify randomShuffle(r, gen) 3069 // is equivalent to partialShuffle(r, 0, r.length, gen). 3070 auto gen1 = Xorshift(123_456_789); 3071 auto gen2 = gen1.save(); 3072 sa[] = sb[]; 3073 // @nogc std.random.randomShuffle. 3074 // https://issues.dlang.org/show_bug.cgi?id=19156 3075 () @nogc nothrow pure { randomShuffle(sa[], gen1); }(); 3076 partialShuffle(sb[], sb.length, gen2); 3077 assert(sa[] == sb[]); 3078 } 3079 3080 // https://issues.dlang.org/show_bug.cgi?id=18501 3081 @safe unittest 3082 { 3083 import std.algorithm.comparison : among; 3084 auto r = randomShuffle([0,1]); 3085 assert(r.among([0,1],[1,0])); 3086 } 3087 3088 /** 3089 Partially shuffles the elements of `r` such that upon returning $(D r[0 .. n]) 3090 is a random subset of `r` and is randomly ordered. $(D r[n .. r.length]) 3091 will contain the elements not in $(D r[0 .. n]). These will be in an undefined 3092 order, but will not be random in the sense that their order after 3093 `partialShuffle` returns will not be independent of their order before 3094 `partialShuffle` was called. 3095 3096 `r` must be a random-access range with length. `n` must be less than 3097 or equal to `r.length`. If no RNG is specified, `rndGen` will be used. 3098 3099 Params: 3100 r = random-access range whose elements are to be shuffled 3101 n = number of elements of `r` to shuffle (counting from the beginning); 3102 must be less than `r.length` 3103 gen = (optional) random number generator to use; if not 3104 specified, defaults to `rndGen` 3105 Returns: 3106 The shuffled random-access range. 3107 */ 3108 Range partialShuffle(Range, RandomGen)(Range r, in size_t n, ref RandomGen gen) 3109 if (isRandomAccessRange!Range && isUniformRNG!RandomGen) 3110 { 3111 import std.algorithm.mutation : swapAt; 3112 import std.exception : enforce; 3113 enforce(n <= r.length, "n must be <= r.length for partialShuffle."); 3114 foreach (i; 0 .. n) 3115 { 3116 r.swapAt(i, uniform(i, r.length, gen)); 3117 } 3118 return r; 3119 } 3120 3121 /// ditto 3122 Range partialShuffle(Range)(Range r, in size_t n) 3123 if (isRandomAccessRange!Range) 3124 { 3125 return partialShuffle(r, n, rndGen); 3126 } 3127 3128 /// 3129 @safe unittest 3130 { 3131 auto rnd = MinstdRand0(42); 3132 3133 auto arr = [1, 2, 3, 4, 5, 6]; 3134 arr = arr.dup.partialShuffle(1, rnd); 3135 3136 version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 3137 assert(arr == [2, 1, 3, 4, 5, 6]); // 1<->2 3138 3139 arr = arr.dup.partialShuffle(2, rnd); 3140 version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 3141 assert(arr == [1, 4, 3, 2, 5, 6]); // 1<->2, 2<->4 3142 3143 arr = arr.dup.partialShuffle(3, rnd); 3144 version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 3145 assert(arr == [5, 4, 6, 2, 1, 3]); // 1<->5, 2<->4, 3<->6 3146 } 3147 3148 @safe unittest 3149 { 3150 import std.algorithm; 3151 foreach (RandomGen; PseudoRngTypes) 3152 { 3153 auto a = [0, 1, 1, 2, 3]; 3154 auto b = a.dup; 3155 3156 // Pick a fixed seed so that the outcome of the statistical 3157 // test below is deterministic. 3158 auto gen = RandomGen(12345); 3159 3160 // NUM times, pick LEN elements from the array at random. 3161 immutable int LEN = 2; 3162 immutable int NUM = 750; 3163 int[][] chk; 3164 foreach (step; 0 .. NUM) 3165 { 3166 partialShuffle(a, LEN, gen); 3167 chk ~= a[0 .. LEN].dup; 3168 } 3169 3170 // Check that each possible a[0 .. LEN] was produced at least once. 3171 // For a perfectly random RandomGen, the probability that each 3172 // particular combination failed to appear would be at most 3173 // 0.95 ^^ NUM which is approximately 1,962e-17. 3174 // As long as hardware failure (e.g. bit flip) probability 3175 // is higher, we are fine with this unittest. 3176 sort(chk); 3177 assert(equal(uniq(chk), [ [0,1], [0,2], [0,3], 3178 [1,0], [1,1], [1,2], [1,3], 3179 [2,0], [2,1], [2,3], 3180 [3,0], [3,1], [3,2], ])); 3181 3182 // Check that all the elements are still there. 3183 sort(a); 3184 assert(equal(a, b)); 3185 } 3186 } 3187 3188 /** 3189 Get a random index into a list of weights corresponding to each index 3190 3191 Similar to rolling a die with relative probabilities stored in `proportions`. 3192 Returns the index in `proportions` that was chosen. 3193 3194 Note: 3195 Usually, dice are 'fair', meaning that each side has equal probability 3196 to come up, in which case `1 + uniform(0, 6)` can simply be used. 3197 In future Phobos versions, this function might get renamed to something like 3198 `weightedChoice` to avoid confusion. 3199 3200 Params: 3201 rnd = (optional) random number generator to use; if not 3202 specified, defaults to `rndGen` 3203 proportions = forward range or list of individual values 3204 whose elements correspond to the probabilities 3205 with which to choose the corresponding index 3206 value 3207 3208 Returns: 3209 Random variate drawn from the index values 3210 [0, ... `proportions.length` - 1], with the probability 3211 of getting an individual index value `i` being proportional to 3212 `proportions[i]`. 3213 */ 3214 size_t dice(Rng, Num)(ref Rng rnd, Num[] proportions...) 3215 if (isNumeric!Num && isForwardRange!Rng) 3216 { 3217 return diceImpl(rnd, proportions); 3218 } 3219 3220 /// Ditto 3221 size_t dice(R, Range)(ref R rnd, Range proportions) 3222 if (isForwardRange!Range && isNumeric!(ElementType!Range) && !isArray!Range) 3223 { 3224 return diceImpl(rnd, proportions); 3225 } 3226 3227 /// Ditto 3228 size_t dice(Range)(Range proportions) 3229 if (isForwardRange!Range && isNumeric!(ElementType!Range) && !isArray!Range) 3230 { 3231 return diceImpl(rndGen, proportions); 3232 } 3233 3234 /// Ditto 3235 size_t dice(Num)(Num[] proportions...) 3236 if (isNumeric!Num) 3237 { 3238 return diceImpl(rndGen, proportions); 3239 } 3240 3241 /// 3242 @safe unittest 3243 { 3244 auto d6 = 1 + dice(1, 1, 1, 1, 1, 1); // fair dice roll 3245 auto d6b = 1 + dice(2, 1, 1, 1, 1, 1); // double the chance to roll '1' 3246 3247 auto x = dice(0.5, 0.5); // x is 0 or 1 in equal proportions 3248 auto y = dice(50, 50); // y is 0 or 1 in equal proportions 3249 auto z = dice(70, 20, 10); // z is 0 70% of the time, 1 20% of the time, 3250 // and 2 10% of the time 3251 } 3252 3253 /// 3254 @safe unittest 3255 { 3256 auto rnd = MinstdRand0(42); 3257 auto z = rnd.dice(70, 20, 10); 3258 assert(z == 0); 3259 z = rnd.dice(30, 20, 40, 10); 3260 assert(z == 2); 3261 } 3262 3263 private size_t diceImpl(Rng, Range)(ref Rng rng, scope Range proportions) 3264 if (isForwardRange!Range && isNumeric!(ElementType!Range) && isForwardRange!Rng) 3265 in 3266 { 3267 import std.algorithm.searching : all; 3268 assert(proportions.save.all!"a >= 0"); 3269 } 3270 do 3271 { 3272 import std.algorithm.iteration : reduce; 3273 import std.exception : enforce; 3274 double sum = reduce!"a + b"(0.0, proportions.save); 3275 enforce(sum > 0, "Proportions in a dice cannot sum to zero"); 3276 immutable point = uniform(0.0, sum, rng); 3277 assert(point < sum); 3278 auto mass = 0.0; 3279 3280 size_t i = 0; 3281 foreach (e; proportions) 3282 { 3283 mass += e; 3284 if (point < mass) return i; 3285 i++; 3286 } 3287 // this point should not be reached 3288 assert(false); 3289 } 3290 3291 /// 3292 @safe unittest 3293 { 3294 auto rnd = Xorshift(123_456_789); 3295 auto i = dice(rnd, 0.0, 100.0); 3296 assert(i == 1); 3297 i = dice(rnd, 100.0, 0.0); 3298 assert(i == 0); 3299 3300 i = dice(100U, 0U); 3301 assert(i == 0); 3302 } 3303 3304 /+ @nogc bool array designed for RandomCover. 3305 - constructed with an invariable length 3306 - small length means 0 alloc and bit field (if up to 32(x86) or 64(x64) choices to cover) 3307 - bigger length means non-GC heap allocation(s) and dealloc. +/ 3308 private struct RandomCoverChoices 3309 { 3310 private size_t* buffer; 3311 private immutable size_t _length; 3312 private immutable bool hasPackedBits; 3313 private enum BITS_PER_WORD = typeof(buffer[0]).sizeof * 8; 3314 3315 void opAssign(T)(T) @disable; 3316 3317 this(this) pure nothrow @nogc @trusted 3318 { 3319 import core.stdc.string : memcpy; 3320 import std.internal.memory : enforceMalloc; 3321 3322 if (!hasPackedBits && buffer !is null) 3323 { 3324 const nBytesToAlloc = size_t.sizeof * (_length / BITS_PER_WORD + int(_length % BITS_PER_WORD != 0)); 3325 void* nbuffer = enforceMalloc(nBytesToAlloc); 3326 buffer = cast(size_t*) memcpy(nbuffer, buffer, nBytesToAlloc); 3327 } 3328 } 3329 3330 this(size_t numChoices) pure nothrow @nogc @trusted 3331 { 3332 import std.internal.memory : enforceCalloc; 3333 3334 _length = numChoices; 3335 hasPackedBits = _length <= size_t.sizeof * 8; 3336 if (!hasPackedBits) 3337 { 3338 const nWordsToAlloc = _length / BITS_PER_WORD + int(_length % BITS_PER_WORD != 0); 3339 buffer = cast(size_t*) enforceCalloc(nWordsToAlloc, BITS_PER_WORD / 8); 3340 } 3341 } 3342 3343 size_t length() const pure nothrow @nogc @safe @property {return _length;} 3344 3345 ~this() pure nothrow @nogc @trusted 3346 { 3347 import core.memory : pureFree; 3348 3349 if (!hasPackedBits && buffer !is null) 3350 pureFree(buffer); 3351 } 3352 3353 bool opIndex(size_t index) const pure nothrow @nogc @trusted 3354 { 3355 assert(index < _length); 3356 import core.bitop : bt; 3357 if (!hasPackedBits) 3358 return cast(bool) bt(buffer, index); 3359 else 3360 return ((cast(size_t) buffer) >> index) & size_t(1); 3361 } 3362 3363 void opIndexAssign(bool value, size_t index) pure nothrow @nogc @trusted 3364 { 3365 assert(index < _length); 3366 if (!hasPackedBits) 3367 { 3368 import core.bitop : btr, bts; 3369 if (value) 3370 bts(buffer, index); 3371 else 3372 btr(buffer, index); 3373 } 3374 else 3375 { 3376 if (value) 3377 (*cast(size_t*) &buffer) |= size_t(1) << index; 3378 else 3379 (*cast(size_t*) &buffer) &= ~(size_t(1) << index); 3380 } 3381 } 3382 } 3383 3384 @safe @nogc nothrow unittest 3385 { 3386 static immutable lengths = [3, 32, 65, 256]; 3387 foreach (length; lengths) 3388 { 3389 RandomCoverChoices c = RandomCoverChoices(length); 3390 assert(c.hasPackedBits == (length <= size_t.sizeof * 8)); 3391 c[0] = true; 3392 c[2] = true; 3393 assert(c[0]); 3394 assert(!c[1]); 3395 assert(c[2]); 3396 c[0] = false; 3397 c[1] = true; 3398 c[2] = false; 3399 assert(!c[0]); 3400 assert(c[1]); 3401 assert(!c[2]); 3402 } 3403 } 3404 3405 /** 3406 Covers a given range `r` in a random manner, i.e. goes through each 3407 element of `r` once and only once, just in a random order. `r` 3408 must be a random-access range with length. 3409 3410 If no random number generator is passed to `randomCover`, the 3411 thread-global RNG rndGen will be used internally. 3412 3413 Params: 3414 r = random-access range to cover 3415 rng = (optional) random number generator to use; 3416 if not specified, defaults to `rndGen` 3417 3418 Returns: 3419 Range whose elements consist of the elements of `r`, 3420 in random order. Will be a forward range if both `r` and 3421 `rng` are forward ranges, an 3422 $(REF_ALTTEXT input range, isInputRange, std,range,primitives) otherwise. 3423 */ 3424 struct RandomCover(Range, UniformRNG = void) 3425 if (isRandomAccessRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG == void))) 3426 { 3427 private Range _input; 3428 private RandomCoverChoices _chosen; 3429 private size_t _current; 3430 private size_t _alreadyChosen = 0; 3431 private bool _isEmpty = false; 3432 3433 static if (is(UniformRNG == void)) 3434 { 3435 this(Range input) 3436 { 3437 _input = input; 3438 _chosen = RandomCoverChoices(_input.length); 3439 if (_input.empty) 3440 { 3441 _isEmpty = true; 3442 } 3443 else 3444 { 3445 _current = _uniformIndex(_chosen.length, rndGen); 3446 } 3447 } 3448 } 3449 else 3450 { 3451 private UniformRNG _rng; 3452 3453 this(Range input, ref UniformRNG rng) 3454 { 3455 _input = input; 3456 _rng = rng; 3457 _chosen = RandomCoverChoices(_input.length); 3458 if (_input.empty) 3459 { 3460 _isEmpty = true; 3461 } 3462 else 3463 { 3464 _current = _uniformIndex(_chosen.length, rng); 3465 } 3466 } 3467 3468 this(Range input, UniformRNG rng) 3469 { 3470 this(input, rng); 3471 } 3472 } 3473 3474 static if (hasLength!Range) 3475 { 3476 @property size_t length() 3477 { 3478 return _input.length - _alreadyChosen; 3479 } 3480 } 3481 3482 @property auto ref front() 3483 { 3484 assert(!_isEmpty); 3485 return _input[_current]; 3486 } 3487 3488 void popFront() 3489 { 3490 assert(!_isEmpty); 3491 3492 size_t k = _input.length - _alreadyChosen - 1; 3493 if (k == 0) 3494 { 3495 _isEmpty = true; 3496 ++_alreadyChosen; 3497 return; 3498 } 3499 3500 size_t i; 3501 foreach (e; _input) 3502 { 3503 if (_chosen[i] || i == _current) { ++i; continue; } 3504 // Roll a dice with k faces 3505 static if (is(UniformRNG == void)) 3506 { 3507 auto chooseMe = _uniformIndex(k, rndGen) == 0; 3508 } 3509 else 3510 { 3511 auto chooseMe = _uniformIndex(k, _rng) == 0; 3512 } 3513 assert(k > 1 || chooseMe); 3514 if (chooseMe) 3515 { 3516 _chosen[_current] = true; 3517 _current = i; 3518 ++_alreadyChosen; 3519 return; 3520 } 3521 --k; 3522 ++i; 3523 } 3524 } 3525 3526 static if (isForwardRange!UniformRNG) 3527 { 3528 @property typeof(this) save() 3529 { 3530 auto ret = this; 3531 ret._input = _input.save; 3532 ret._rng = _rng.save; 3533 return ret; 3534 } 3535 } 3536 3537 @property bool empty() const { return _isEmpty; } 3538 } 3539 3540 /// Ditto 3541 auto randomCover(Range, UniformRNG)(Range r, auto ref UniformRNG rng) 3542 if (isRandomAccessRange!Range && isUniformRNG!UniformRNG) 3543 { 3544 return RandomCover!(Range, UniformRNG)(r, rng); 3545 } 3546 3547 /// Ditto 3548 auto randomCover(Range)(Range r) 3549 if (isRandomAccessRange!Range) 3550 { 3551 return RandomCover!(Range, void)(r); 3552 } 3553 3554 /// 3555 @safe unittest 3556 { 3557 import std.algorithm.comparison : equal; 3558 import std.range : iota; 3559 auto rnd = MinstdRand0(42); 3560 3561 version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147 3562 assert(10.iota.randomCover(rnd).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5])); 3563 } 3564 3565 @safe unittest // cover RandomCoverChoices postblit for heap storage 3566 { 3567 import std.array : array; 3568 import std.range : iota; 3569 auto a = 1337.iota.randomCover().array; 3570 assert(a.length == 1337); 3571 } 3572 3573 @nogc nothrow pure @safe unittest 3574 { 3575 // Optionally @nogc std.random.randomCover 3576 // https://issues.dlang.org/show_bug.cgi?id=14001 3577 auto rng = Xorshift(123_456_789); 3578 static immutable int[] sa = [1, 2, 3, 4, 5]; 3579 auto r = randomCover(sa, rng); 3580 assert(!r.empty); 3581 const x = r.front; 3582 r.popFront(); 3583 assert(!r.empty); 3584 const y = r.front; 3585 assert(x != y); 3586 } 3587 3588 @safe unittest 3589 { 3590 import std.algorithm; 3591 import std.conv; 3592 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]; 3593 int[] c; 3594 static foreach (UniformRNG; std.meta.AliasSeq!(void, PseudoRngTypes)) 3595 {{ 3596 static if (is(UniformRNG == void)) 3597 { 3598 auto rc = randomCover(a); 3599 static assert(isInputRange!(typeof(rc))); 3600 static assert(!isForwardRange!(typeof(rc))); 3601 } 3602 else 3603 { 3604 auto rng = UniformRNG(123_456_789); 3605 auto rc = randomCover(a, rng); 3606 static assert(isForwardRange!(typeof(rc))); 3607 // check for constructor passed a value-type RNG 3608 auto rc2 = RandomCover!(int[], UniformRNG)(a, UniformRNG(987_654_321)); 3609 static assert(isForwardRange!(typeof(rc2))); 3610 auto rcEmpty = randomCover(c, rng); 3611 assert(rcEmpty.length == 0); 3612 } 3613 3614 int[] b = new int[9]; 3615 uint i; 3616 foreach (e; rc) 3617 { 3618 //writeln(e); 3619 b[i++] = e; 3620 } 3621 sort(b); 3622 assert(a == b, text(b)); 3623 }} 3624 } 3625 3626 @safe unittest 3627 { 3628 // https://issues.dlang.org/show_bug.cgi?id=12589 3629 int[] r = []; 3630 auto rc = randomCover(r); 3631 assert(rc.length == 0); 3632 assert(rc.empty); 3633 3634 // https://issues.dlang.org/show_bug.cgi?id=16724 3635 import std.range : iota; 3636 auto range = iota(10); 3637 auto randy = range.randomCover; 3638 3639 for (int i=1; i <= range.length; i++) 3640 { 3641 randy.popFront; 3642 assert(randy.length == range.length - i); 3643 } 3644 } 3645 3646 // RandomSample 3647 /** 3648 Selects a random subsample out of `r`, containing exactly `n` 3649 elements. The order of elements is the same as in the original 3650 range. The total length of `r` must be known. If `total` is 3651 passed in, the total number of sample is considered to be $(D 3652 total). Otherwise, `RandomSample` uses `r.length`. 3653 3654 Params: 3655 r = range to sample from 3656 n = number of elements to include in the sample; 3657 must be less than or equal to the total number 3658 of elements in `r` and/or the parameter 3659 `total` (if provided) 3660 total = (semi-optional) number of elements of `r` 3661 from which to select the sample (counting from 3662 the beginning); must be less than or equal to 3663 the total number of elements in `r` itself. 3664 May be omitted if `r` has the `.length` 3665 property and the sample is to be drawn from 3666 all elements of `r`. 3667 rng = (optional) random number generator to use; 3668 if not specified, defaults to `rndGen` 3669 3670 Returns: 3671 Range whose elements consist of a randomly selected subset of 3672 the elements of `r`, in the same order as these elements 3673 appear in `r` itself. Will be a forward range if both `r` 3674 and `rng` are forward ranges, an input range otherwise. 3675 3676 `RandomSample` implements Jeffrey Scott Vitter's Algorithm D 3677 (see Vitter $(HTTP dx.doi.org/10.1145/358105.893, 1984), $(HTTP 3678 dx.doi.org/10.1145/23002.23003, 1987)), which selects a sample 3679 of size `n` in O(n) steps and requiring O(n) random variates, 3680 regardless of the size of the data being sampled. The exception 3681 to this is if traversing k elements on the input range is itself 3682 an O(k) operation (e.g. when sampling lines from an input file), 3683 in which case the sampling calculation will inevitably be of 3684 O(total). 3685 3686 RandomSample will throw an exception if `total` is verifiably 3687 less than the total number of elements available in the input, 3688 or if $(D n > total). 3689 3690 If no random number generator is passed to `randomSample`, the 3691 thread-global RNG rndGen will be used internally. 3692 */ 3693 struct RandomSample(Range, UniformRNG = void) 3694 if (isInputRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG == void))) 3695 { 3696 private size_t _available, _toSelect; 3697 private enum ushort _alphaInverse = 13; // Vitter's recommended value. 3698 private double _Vprime; 3699 private Range _input; 3700 private size_t _index; 3701 private enum Skip { None, A, D } 3702 private Skip _skip = Skip.None; 3703 3704 // If we're using the default thread-local random number generator then 3705 // we shouldn't store a copy of it here. UniformRNG == void is a sentinel 3706 // for this. If we're using a user-specified generator then we have no 3707 // choice but to store a copy. 3708 static if (is(UniformRNG == void)) 3709 { 3710 static if (hasLength!Range) 3711 { 3712 this(Range input, size_t howMany) 3713 { 3714 _input = input; 3715 initialize(howMany, input.length); 3716 } 3717 } 3718 3719 this(Range input, size_t howMany, size_t total) 3720 { 3721 _input = input; 3722 initialize(howMany, total); 3723 } 3724 } 3725 else 3726 { 3727 UniformRNG _rng; 3728 3729 static if (hasLength!Range) 3730 { 3731 this(Range input, size_t howMany, ref scope UniformRNG rng) 3732 { 3733 _rng = rng; 3734 _input = input; 3735 initialize(howMany, input.length); 3736 } 3737 3738 this(Range input, size_t howMany, UniformRNG rng) 3739 { 3740 this(input, howMany, rng); 3741 } 3742 } 3743 3744 this(Range input, size_t howMany, size_t total, ref scope UniformRNG rng) 3745 { 3746 _rng = rng; 3747 _input = input; 3748 initialize(howMany, total); 3749 } 3750 3751 this(Range input, size_t howMany, size_t total, UniformRNG rng) 3752 { 3753 this(input, howMany, total, rng); 3754 } 3755 } 3756 3757 private void initialize(size_t howMany, size_t total) 3758 { 3759 import std.conv : text; 3760 import std.exception : enforce; 3761 _available = total; 3762 _toSelect = howMany; 3763 enforce(_toSelect <= _available, 3764 text("RandomSample: cannot sample ", _toSelect, 3765 " items when only ", _available, " are available")); 3766 static if (hasLength!Range) 3767 { 3768 enforce(_available <= _input.length, 3769 text("RandomSample: specified ", _available, 3770 " items as available when input contains only ", 3771 _input.length)); 3772 } 3773 } 3774 3775 private void initializeFront() 3776 { 3777 assert(_skip == Skip.None); 3778 // We can save ourselves a random variate by checking right 3779 // at the beginning if we should use Algorithm A. 3780 if ((_alphaInverse * _toSelect) > _available) 3781 { 3782 _skip = Skip.A; 3783 } 3784 else 3785 { 3786 _skip = Skip.D; 3787 _Vprime = newVprime(_toSelect); 3788 } 3789 prime(); 3790 } 3791 3792 /** 3793 Range primitives. 3794 */ 3795 @property bool empty() const 3796 { 3797 return _toSelect == 0; 3798 } 3799 3800 /// Ditto 3801 @property auto ref front() 3802 { 3803 assert(!empty); 3804 // The first sample point must be determined here to avoid 3805 // having it always correspond to the first element of the 3806 // input. The rest of the sample points are determined each 3807 // time we call popFront(). 3808 if (_skip == Skip.None) 3809 { 3810 initializeFront(); 3811 } 3812 return _input.front; 3813 } 3814 3815 /// Ditto 3816 void popFront() 3817 { 3818 // First we need to check if the sample has 3819 // been initialized in the first place. 3820 if (_skip == Skip.None) 3821 { 3822 initializeFront(); 3823 } 3824 3825 _input.popFront(); 3826 --_available; 3827 --_toSelect; 3828 ++_index; 3829 prime(); 3830 } 3831 3832 /// Ditto 3833 static if (isForwardRange!Range && isForwardRange!UniformRNG) 3834 { 3835 static if (is(typeof(((const UniformRNG* p) => (*p).save)(null)) : UniformRNG) 3836 && is(typeof(((const Range* p) => (*p).save)(null)) : Range)) 3837 { 3838 @property typeof(this) save() const 3839 { 3840 auto ret = RandomSample.init; 3841 foreach (fieldIndex, ref val; this.tupleof) 3842 { 3843 static if (is(typeof(val) == const(Range)) || is(typeof(val) == const(UniformRNG))) 3844 ret.tupleof[fieldIndex] = val.save; 3845 else 3846 ret.tupleof[fieldIndex] = val; 3847 } 3848 return ret; 3849 } 3850 } 3851 else 3852 { 3853 @property typeof(this) save() 3854 { 3855 auto ret = this; 3856 ret._input = _input.save; 3857 ret._rng = _rng.save; 3858 return ret; 3859 } 3860 } 3861 } 3862 3863 /// Ditto 3864 @property size_t length() const 3865 { 3866 return _toSelect; 3867 } 3868 3869 /** 3870 Returns the index of the visited record. 3871 */ 3872 @property size_t index() 3873 { 3874 if (_skip == Skip.None) 3875 { 3876 initializeFront(); 3877 } 3878 return _index; 3879 } 3880 3881 private size_t skip() 3882 { 3883 assert(_skip != Skip.None); 3884 3885 // Step D1: if the number of points still to select is greater 3886 // than a certain proportion of the remaining data points, i.e. 3887 // if n >= alpha * N where alpha = 1/13, we carry out the 3888 // sampling with Algorithm A. 3889 if (_skip == Skip.A) 3890 { 3891 return skipA(); 3892 } 3893 else if ((_alphaInverse * _toSelect) > _available) 3894 { 3895 // We shouldn't get here unless the current selected 3896 // algorithm is D. 3897 assert(_skip == Skip.D); 3898 _skip = Skip.A; 3899 return skipA(); 3900 } 3901 else 3902 { 3903 assert(_skip == Skip.D); 3904 return skipD(); 3905 } 3906 } 3907 3908 /* 3909 Vitter's Algorithm A, used when the ratio of needed sample values 3910 to remaining data values is sufficiently large. 3911 */ 3912 private size_t skipA() 3913 { 3914 size_t s; 3915 double v, quot, top; 3916 3917 if (_toSelect == 1) 3918 { 3919 static if (is(UniformRNG == void)) 3920 { 3921 s = uniform(0, _available); 3922 } 3923 else 3924 { 3925 s = uniform(0, _available, _rng); 3926 } 3927 } 3928 else 3929 { 3930 v = 0; 3931 top = _available - _toSelect; 3932 quot = top / _available; 3933 3934 static if (is(UniformRNG == void)) 3935 { 3936 v = uniform!"()"(0.0, 1.0); 3937 } 3938 else 3939 { 3940 v = uniform!"()"(0.0, 1.0, _rng); 3941 } 3942 3943 while (quot > v) 3944 { 3945 ++s; 3946 quot *= (top - s) / (_available - s); 3947 } 3948 } 3949 3950 return s; 3951 } 3952 3953 /* 3954 Randomly reset the value of _Vprime. 3955 */ 3956 private double newVprime(size_t remaining) 3957 { 3958 static if (is(UniformRNG == void)) 3959 { 3960 double r = uniform!"()"(0.0, 1.0); 3961 } 3962 else 3963 { 3964 double r = uniform!"()"(0.0, 1.0, _rng); 3965 } 3966 3967 return r ^^ (1.0 / remaining); 3968 } 3969 3970 /* 3971 Vitter's Algorithm D. For an extensive description of the algorithm 3972 and its rationale, see: 3973 3974 * Vitter, J.S. (1984), "Faster methods for random sampling", 3975 Commun. ACM 27(7): 703--718 3976 3977 * Vitter, J.S. (1987) "An efficient algorithm for sequential random 3978 sampling", ACM Trans. Math. Softw. 13(1): 58-67. 3979 3980 Variable names are chosen to match those in Vitter's paper. 3981 */ 3982 private size_t skipD() 3983 { 3984 import std.math.traits : isNaN; 3985 import std.math.rounding : trunc; 3986 // Confirm that the check in Step D1 is valid and we 3987 // haven't been sent here by mistake 3988 assert((_alphaInverse * _toSelect) <= _available); 3989 3990 // Now it's safe to use the standard Algorithm D mechanism. 3991 if (_toSelect > 1) 3992 { 3993 size_t s; 3994 size_t qu1 = 1 + _available - _toSelect; 3995 double x, y1; 3996 3997 assert(!_Vprime.isNaN()); 3998 3999 while (true) 4000 { 4001 // Step D2: set values of x and u. 4002 while (1) 4003 { 4004 x = _available * (1-_Vprime); 4005 s = cast(size_t) trunc(x); 4006 if (s < qu1) 4007 break; 4008 _Vprime = newVprime(_toSelect); 4009 } 4010 4011 static if (is(UniformRNG == void)) 4012 { 4013 double u = uniform!"()"(0.0, 1.0); 4014 } 4015 else 4016 { 4017 double u = uniform!"()"(0.0, 1.0, _rng); 4018 } 4019 4020 y1 = (u * (cast(double) _available) / qu1) ^^ (1.0/(_toSelect - 1)); 4021 4022 _Vprime = y1 * ((-x/_available)+1.0) * ( qu1/( (cast(double) qu1) - s ) ); 4023 4024 // Step D3: if _Vprime <= 1.0 our work is done and we return S. 4025 // Otherwise ... 4026 if (_Vprime > 1.0) 4027 { 4028 size_t top = _available - 1, limit; 4029 double y2 = 1.0, bottom; 4030 4031 if (_toSelect > (s+1)) 4032 { 4033 bottom = _available - _toSelect; 4034 limit = _available - s; 4035 } 4036 else 4037 { 4038 bottom = _available - (s+1); 4039 limit = qu1; 4040 } 4041 4042 foreach (size_t t; limit .. _available) 4043 { 4044 y2 *= top/bottom; 4045 top--; 4046 bottom--; 4047 } 4048 4049 // Step D4: decide whether or not to accept the current value of S. 4050 if (_available/(_available-x) < y1 * (y2 ^^ (1.0/(_toSelect-1)))) 4051 { 4052 // If it's not acceptable, we generate a new value of _Vprime 4053 // and go back to the start of the for (;;) loop. 4054 _Vprime = newVprime(_toSelect); 4055 } 4056 else 4057 { 4058 // If it's acceptable we generate a new value of _Vprime 4059 // based on the remaining number of sample points needed, 4060 // and return S. 4061 _Vprime = newVprime(_toSelect-1); 4062 return s; 4063 } 4064 } 4065 else 4066 { 4067 // Return if condition D3 satisfied. 4068 return s; 4069 } 4070 } 4071 } 4072 else 4073 { 4074 // If only one sample point remains to be taken ... 4075 return cast(size_t) trunc(_available * _Vprime); 4076 } 4077 } 4078 4079 private void prime() 4080 { 4081 if (empty) 4082 { 4083 return; 4084 } 4085 assert(_available && _available >= _toSelect); 4086 immutable size_t s = skip(); 4087 assert(s + _toSelect <= _available); 4088 static if (hasLength!Range) 4089 { 4090 assert(s + _toSelect <= _input.length); 4091 } 4092 assert(!_input.empty); 4093 _input.popFrontExactly(s); 4094 _index += s; 4095 _available -= s; 4096 assert(_available > 0); 4097 } 4098 } 4099 4100 /// Ditto 4101 auto randomSample(Range)(Range r, size_t n, size_t total) 4102 if (isInputRange!Range) 4103 { 4104 return RandomSample!(Range, void)(r, n, total); 4105 } 4106 4107 /// Ditto 4108 auto randomSample(Range)(Range r, size_t n) 4109 if (isInputRange!Range && hasLength!Range) 4110 { 4111 return RandomSample!(Range, void)(r, n, r.length); 4112 } 4113 4114 /// Ditto 4115 auto randomSample(Range, UniformRNG)(Range r, size_t n, size_t total, auto ref UniformRNG rng) 4116 if (isInputRange!Range && isUniformRNG!UniformRNG) 4117 { 4118 return RandomSample!(Range, UniformRNG)(r, n, total, rng); 4119 } 4120 4121 /// Ditto 4122 auto randomSample(Range, UniformRNG)(Range r, size_t n, auto ref UniformRNG rng) 4123 if (isInputRange!Range && hasLength!Range && isUniformRNG!UniformRNG) 4124 { 4125 return RandomSample!(Range, UniformRNG)(r, n, r.length, rng); 4126 } 4127 4128 /// 4129 @safe unittest 4130 { 4131 import std.algorithm.comparison : equal; 4132 import std.range : iota; 4133 auto rnd = MinstdRand0(42); 4134 assert(10.iota.randomSample(3, rnd).equal([7, 8, 9])); 4135 } 4136 4137 @system unittest 4138 { 4139 // @system because it takes the address of a local 4140 import std.conv : text; 4141 import std.exception; 4142 import std.range; 4143 // For test purposes, an infinite input range 4144 struct TestInputRange 4145 { 4146 private auto r = recurrence!"a[n-1] + 1"(0); 4147 bool empty() @property const pure nothrow { return r.empty; } 4148 auto front() @property pure nothrow { return r.front; } 4149 void popFront() pure nothrow { r.popFront(); } 4150 } 4151 static assert(isInputRange!TestInputRange); 4152 static assert(!isForwardRange!TestInputRange); 4153 4154 const(int)[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; 4155 4156 foreach (UniformRNG; PseudoRngTypes) 4157 (){ // avoid workaround optimizations for large functions 4158 // https://issues.dlang.org/show_bug.cgi?id=2396 4159 auto rng = UniformRNG(1234); 4160 /* First test the most general case: randomSample of input range, with and 4161 * without a specified random number generator. 4162 */ 4163 static assert(isInputRange!(typeof(randomSample(TestInputRange(), 5, 10)))); 4164 static assert(isInputRange!(typeof(randomSample(TestInputRange(), 5, 10, rng)))); 4165 static assert(!isForwardRange!(typeof(randomSample(TestInputRange(), 5, 10)))); 4166 static assert(!isForwardRange!(typeof(randomSample(TestInputRange(), 5, 10, rng)))); 4167 // test case with range initialized by direct call to struct 4168 { 4169 auto sample = 4170 RandomSample!(TestInputRange, UniformRNG) 4171 (TestInputRange(), 5, 10, UniformRNG(987_654_321)); 4172 static assert(isInputRange!(typeof(sample))); 4173 static assert(!isForwardRange!(typeof(sample))); 4174 } 4175 4176 /* Now test the case of an input range with length. We ignore the cases 4177 * already covered by the previous tests. 4178 */ 4179 static assert(isInputRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5)))); 4180 static assert(isInputRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5, rng)))); 4181 static assert(!isForwardRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5)))); 4182 static assert(!isForwardRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5, rng)))); 4183 // test case with range initialized by direct call to struct 4184 { 4185 auto sample = 4186 RandomSample!(typeof(TestInputRange().takeExactly(10)), UniformRNG) 4187 (TestInputRange().takeExactly(10), 5, 10, UniformRNG(654_321_987)); 4188 static assert(isInputRange!(typeof(sample))); 4189 static assert(!isForwardRange!(typeof(sample))); 4190 } 4191 4192 // Now test the case of providing a forward range as input. 4193 static assert(!isForwardRange!(typeof(randomSample(a, 5)))); 4194 static if (isForwardRange!UniformRNG) 4195 { 4196 static assert(isForwardRange!(typeof(randomSample(a, 5, rng)))); 4197 // ... and test with range initialized directly 4198 { 4199 auto sample = 4200 RandomSample!(const(int)[], UniformRNG) 4201 (a, 5, UniformRNG(321_987_654)); 4202 static assert(isForwardRange!(typeof(sample))); 4203 } 4204 } 4205 else 4206 { 4207 static assert(isInputRange!(typeof(randomSample(a, 5, rng)))); 4208 static assert(!isForwardRange!(typeof(randomSample(a, 5, rng)))); 4209 // ... and test with range initialized directly 4210 { 4211 auto sample = 4212 RandomSample!(const(int)[], UniformRNG) 4213 (a, 5, UniformRNG(789_123_456)); 4214 static assert(isInputRange!(typeof(sample))); 4215 static assert(!isForwardRange!(typeof(sample))); 4216 } 4217 } 4218 4219 /* Check that randomSample will throw an error if we claim more 4220 * items are available than there actually are, or if we try to 4221 * sample more items than are available. */ 4222 assert(collectExceptionMsg( 4223 randomSample(a, 5, 15) 4224 ) == "RandomSample: specified 15 items as available when input contains only 10"); 4225 assert(collectExceptionMsg( 4226 randomSample(a, 15) 4227 ) == "RandomSample: cannot sample 15 items when only 10 are available"); 4228 assert(collectExceptionMsg( 4229 randomSample(a, 9, 8) 4230 ) == "RandomSample: cannot sample 9 items when only 8 are available"); 4231 assert(collectExceptionMsg( 4232 randomSample(TestInputRange(), 12, 11) 4233 ) == "RandomSample: cannot sample 12 items when only 11 are available"); 4234 4235 /* Check that sampling algorithm never accidentally overruns the end of 4236 * the input range. If input is an InputRange without .length, this 4237 * relies on the user specifying the total number of available items 4238 * correctly. 4239 */ 4240 { 4241 uint i = 0; 4242 foreach (e; randomSample(a, a.length)) 4243 { 4244 assert(e == i); 4245 ++i; 4246 } 4247 assert(i == a.length); 4248 4249 i = 0; 4250 foreach (e; randomSample(TestInputRange(), 17, 17)) 4251 { 4252 assert(e == i); 4253 ++i; 4254 } 4255 assert(i == 17); 4256 } 4257 4258 4259 // Check length properties of random samples. 4260 assert(randomSample(a, 5).length == 5); 4261 assert(randomSample(a, 5, 10).length == 5); 4262 assert(randomSample(a, 5, rng).length == 5); 4263 assert(randomSample(a, 5, 10, rng).length == 5); 4264 assert(randomSample(TestInputRange(), 5, 10).length == 5); 4265 assert(randomSample(TestInputRange(), 5, 10, rng).length == 5); 4266 4267 // ... and emptiness! 4268 assert(randomSample(a, 0).empty); 4269 assert(randomSample(a, 0, 5).empty); 4270 assert(randomSample(a, 0, rng).empty); 4271 assert(randomSample(a, 0, 5, rng).empty); 4272 assert(randomSample(TestInputRange(), 0, 10).empty); 4273 assert(randomSample(TestInputRange(), 0, 10, rng).empty); 4274 4275 /* Test that the (lazy) evaluation of random samples works correctly. 4276 * 4277 * We cover 2 different cases: a sample where the ratio of sample points 4278 * to total points is greater than the threshold for using Algorithm, and 4279 * one where the ratio is small enough (< 1/13) for Algorithm D to be used. 4280 * 4281 * For each, we also cover the case with and without a specified RNG. 4282 */ 4283 { 4284 // Small sample/source ratio, no specified RNG. 4285 uint i = 0; 4286 foreach (e; randomSample(randomCover(a), 5)) 4287 { 4288 ++i; 4289 } 4290 assert(i == 5); 4291 4292 // Small sample/source ratio, specified RNG. 4293 i = 0; 4294 foreach (e; randomSample(randomCover(a), 5, rng)) 4295 { 4296 ++i; 4297 } 4298 assert(i == 5); 4299 4300 // Large sample/source ratio, no specified RNG. 4301 i = 0; 4302 foreach (e; randomSample(TestInputRange(), 123, 123_456)) 4303 { 4304 ++i; 4305 } 4306 assert(i == 123); 4307 4308 // Large sample/source ratio, specified RNG. 4309 i = 0; 4310 foreach (e; randomSample(TestInputRange(), 123, 123_456, rng)) 4311 { 4312 ++i; 4313 } 4314 assert(i == 123); 4315 4316 /* Sample/source ratio large enough to start with Algorithm D, 4317 * small enough to switch to Algorithm A. 4318 */ 4319 i = 0; 4320 foreach (e; randomSample(TestInputRange(), 10, 131)) 4321 { 4322 ++i; 4323 } 4324 assert(i == 10); 4325 } 4326 4327 // Test that the .index property works correctly 4328 { 4329 auto sample1 = randomSample(TestInputRange(), 654, 654_321); 4330 for (; !sample1.empty; sample1.popFront()) 4331 { 4332 assert(sample1.front == sample1.index); 4333 } 4334 4335 auto sample2 = randomSample(TestInputRange(), 654, 654_321, rng); 4336 for (; !sample2.empty; sample2.popFront()) 4337 { 4338 assert(sample2.front == sample2.index); 4339 } 4340 4341 /* Check that it also works if .index is called before .front. 4342 * See: https://issues.dlang.org/show_bug.cgi?id=10322 4343 */ 4344 auto sample3 = randomSample(TestInputRange(), 654, 654_321); 4345 for (; !sample3.empty; sample3.popFront()) 4346 { 4347 assert(sample3.index == sample3.front); 4348 } 4349 4350 auto sample4 = randomSample(TestInputRange(), 654, 654_321, rng); 4351 for (; !sample4.empty; sample4.popFront()) 4352 { 4353 assert(sample4.index == sample4.front); 4354 } 4355 } 4356 4357 /* Test behaviour if .popFront() is called before sample is read. 4358 * This is a rough-and-ready check that the statistical properties 4359 * are in the ballpark -- not a proper validation of statistical 4360 * quality! This incidentally also checks for reference-type 4361 * initialization bugs, as the foreach () loop will operate on a 4362 * copy of the popFronted (and hence initialized) sample. 4363 */ 4364 { 4365 size_t count0, count1, count99; 4366 foreach (_; 0 .. 50_000) 4367 { 4368 auto sample = randomSample(iota(100), 5, &rng); 4369 sample.popFront(); 4370 foreach (s; sample) 4371 { 4372 if (s == 0) 4373 { 4374 ++count0; 4375 } 4376 else if (s == 1) 4377 { 4378 ++count1; 4379 } 4380 else if (s == 99) 4381 { 4382 ++count99; 4383 } 4384 } 4385 } 4386 /* Statistical assumptions here: this is a sequential sampling process 4387 * so (i) 0 can only be the first sample point, so _can't_ be in the 4388 * remainder of the sample after .popFront() is called. (ii) By similar 4389 * token, 1 can only be in the remainder if it's the 2nd point of the 4390 * whole sample, and hence if 0 was the first; probability of 0 being 4391 * first and 1 second is 5/100 * 4/99 (thank you, Algorithm S:-) and 4392 * so the mean count of 1 should be about 202. Finally, 99 can only 4393 * be the _last_ sample point to be picked, so its probability of 4394 * inclusion should be independent of the .popFront() and it should 4395 * occur with frequency 5/100, hence its count should be about 5000. 4396 * Unfortunately we have to set quite a high tolerance because with 4397 * sample size small enough for unittests to run in reasonable time, 4398 * the variance can be quite high. 4399 */ 4400 assert(count0 == 0); 4401 assert(count1 < 150, text("1: ", count1, " > 150.")); 4402 assert(2_200 < count99, text("99: ", count99, " < 2200.")); 4403 assert(count99 < 2_800, text("99: ", count99, " > 2800.")); 4404 } 4405 4406 /* Odd corner-cases: RandomSample has 2 constructors that are not called 4407 * by the randomSample() helper functions, but that can be used if the 4408 * constructor is called directly. These cover the case of the user 4409 * specifying input but not input length. 4410 */ 4411 { 4412 auto input1 = TestInputRange().takeExactly(456_789); 4413 static assert(hasLength!(typeof(input1))); 4414 auto sample1 = RandomSample!(typeof(input1), void)(input1, 789); 4415 static assert(isInputRange!(typeof(sample1))); 4416 static assert(!isForwardRange!(typeof(sample1))); 4417 assert(sample1.length == 789); 4418 assert(sample1._available == 456_789); 4419 uint i = 0; 4420 for (; !sample1.empty; sample1.popFront()) 4421 { 4422 assert(sample1.front == sample1.index); 4423 ++i; 4424 } 4425 assert(i == 789); 4426 4427 auto input2 = TestInputRange().takeExactly(456_789); 4428 static assert(hasLength!(typeof(input2))); 4429 auto sample2 = RandomSample!(typeof(input2), typeof(rng))(input2, 789, rng); 4430 static assert(isInputRange!(typeof(sample2))); 4431 static assert(!isForwardRange!(typeof(sample2))); 4432 assert(sample2.length == 789); 4433 assert(sample2._available == 456_789); 4434 i = 0; 4435 for (; !sample2.empty; sample2.popFront()) 4436 { 4437 assert(sample2.front == sample2.index); 4438 ++i; 4439 } 4440 assert(i == 789); 4441 } 4442 4443 /* Test that the save property works where input is a forward range, 4444 * and RandomSample is using a (forward range) random number generator 4445 * that is not rndGen. 4446 */ 4447 static if (isForwardRange!UniformRNG) 4448 { 4449 auto sample1 = randomSample(a, 5, rng); 4450 // https://issues.dlang.org/show_bug.cgi?id=15853 4451 auto sample2 = ((const ref typeof(sample1) a) => a.save)(sample1); 4452 assert(sample1.array() == sample2.array()); 4453 } 4454 4455 // https://issues.dlang.org/show_bug.cgi?id=8314 4456 { 4457 auto sample(RandomGen)(uint seed) { return randomSample(a, 1, RandomGen(seed)).front; } 4458 4459 // Start from 1 because not all RNGs accept 0 as seed. 4460 immutable fst = sample!UniformRNG(1); 4461 uint n = 1; 4462 while (sample!UniformRNG(++n) == fst && n < n.max) {} 4463 assert(n < n.max); 4464 } 4465 }(); 4466 }