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