1 // Written in the D programming language. 2 /* 3 NYSL Version 0.9982 4 5 A. This software is "Everyone'sWare". It means: 6 Anybody who has this software can use it as if he/she is 7 the author. 8 9 A-1. Freeware. No fee is required. 10 A-2. You can freely redistribute this software. 11 A-3. You can freely modify this software. And the source 12 may be used in any software with no limitation. 13 A-4. When you release a modified version to public, you 14 must publish it with your name. 15 16 B. The author is not responsible for any kind of damages or loss 17 while using or misusing this software, which is distributed 18 "AS IS". No warranty of any kind is expressed or implied. 19 You use AT YOUR OWN RISK. 20 21 C. Copyrighted to Kazuki KOMATSU 22 23 D. Above three clauses are applied both to source and binary 24 form of this software. 25 */ 26 27 /** 28 このモジュールは、標準ライブラリのstd.randomを強化します。 29 */ 30 31 module carbon.random; 32 33 34 import std.random; 35 36 37 /** 38 Mark as Uniform Random Number Generator 39 */ 40 auto asUniformRNG(R)(R range) 41 if(isInputRange!R) 42 { 43 static struct Result 44 { 45 enum bool isUniformRandom = true; 46 47 alias _this this; 48 R _this; 49 } 50 51 52 return Result(range); 53 } 54 55 56 // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/lfsr04.pdf 57 // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/wellrng-errata.txt 58 private struct WELLConstants_t(UInt) 59 { 60 alias UIntType = UInt; 61 62 uint wordSize, regSize, rotN; 63 64 uint[3] m; 65 66 string[8] ts; 67 68 bool doTempering = false; 69 UIntType[2] temperingBC; 70 71 enum UIntType[8] a = 72 [0, 73 0xda442d24, 74 0xd3e43ffd, 75 0x8bdcb91e, 76 0x86a9d87e, 77 0xa8c296d1, 78 0x5d6b45cc, 79 0xb729fcec]; 80 81 UIntType M(uint n : 0)(UIntType x) const { return 0; } 82 UIntType M(uint n : 1)(UIntType x) const { return x; } 83 UIntType M(uint n : 2, int t)(UIntType x) const 84 { 85 static if(t >= 0) 86 return x >> t; 87 else 88 return x << (-t); 89 } 90 91 UIntType M(uint n : 3, int t)(UIntType x) const { return x ^ M!(2, t)(x); } 92 UIntType M(uint n : 4, uint a)(UIntType x) const { return (x & 1u) ? ((v >> 1) ^ a) : (v >> 1); } 93 UIntType M(uint n : 5, int t, uint b)(UIntType x) const 94 { 95 return x ^ (M!(2, t)(x) & b); 96 } 97 98 UIntType M(uint n : 6, uint r, uint s, uint t, uint a)(UIntType x) const 99 { 100 immutable ds = ~(1 << (wordSize - 1 - s)), 101 dt = (1 << (wordSize - 1 - t)), 102 rot = (x << r) ^ (x >> (wordSize - r)); 103 104 if(x & dt) 105 return (rot & ds) ^ a; 106 else 107 return rot & ds; 108 } 109 110 111 static UIntType T(alias thisValue, uint n)(UIntType x) 112 if(is(typeof(thisValue) == typeof(this))) 113 { 114 with(thisValue) 115 { 116 return mixin("thisValue." ~ thisValue.ts[n] ~ "(x)"); 117 } 118 } 119 } 120 121 122 private auto _makeStructConstant(S, string expr)() 123 { 124 mixin(`S ret = {` ~ expr ~ `};`); 125 126 return ret; 127 } 128 129 130 enum WELLConstants_t!UIntType[string] 131 WELLConstants(UIntType) = 132 ["512a" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 133 wordSize : 32, regSize : 16, rotN : 0, 134 m : [13, 9, 5], 135 ts : [ 136 "M!(3, -16)", "M!(3, -15)", "M!(3, +11)", "M!(0)", 137 "M!(3, -2)", "M!(3, -18)", "M!(2, -28)", "M!(5, -5, a[1])", 138 ] 139 }), 140 141 "521a" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 142 wordSize : 32, regSize : 17, rotN : 23, 143 m : [13, 11, 10], 144 ts : [ 145 "M!(3, -13)", "M!(3, -15)", "M!(1)", "M!(2, -21)", 146 "M!(3, -13)", "M!(2, 1)", "M!(0)", "M!(3, 11)" 147 ] 148 }), 149 150 "521b" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 151 wordSize : 32, regSize : 17, rotN : 23, 152 m : [11, 10, 7], 153 ts : [ 154 "M!(3, -21)", "M!(3, 6)", "M!(0)", "M!(3, -13)", 155 "M!(3, 13)", "M!(2, -10)", "M!(2, -5)", "M!(3, 13)" 156 ] 157 }), 158 159 "607a" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 160 wordSize : 32, regSize : 19, rotN : 1, 161 m : [16, 15, 14], 162 ts : [ 163 "M!(3, 19)", "M!(3, 11)", "M!(3, -14)", "M!(1)", 164 "M!(3, 18)", "M!(1)", "M!(0)", "M!(3, -15)" 165 ] 166 }), 167 168 "607b" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 169 wordSize : 32, regSize : 25, rotN : 0, 170 m : [16, 8, 13], 171 ts : [ 172 "M!(3, -18)", "M!(3, -14)", "M!(0)", "M!(3, 18)", 173 "M!(3, -24)", "M!(3, 5)", "M!(3, -1)", "M!(0)" 174 ] 175 }), 176 177 "800a" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 178 wordSize : 32, regSize : 25, rotN : 0, 179 m : [14, 18, 17], 180 ts : [ 181 "M!(1)", "M!(3, -15)", "M!(3, 10)", "M!(3, -11)", 182 "M!(3, 16)", "M!(2, 20)", "M!(1)", "M!(3, -28)" 183 ] 184 }), 185 186 "800b" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 187 wordSize : 32, regSize : 25, rotN : 0, 188 m : [9, 4, 22], 189 ts : [ 190 "M!(3, -29)", "M!(2, -14)", "M!(1)", "M!(2, 19)", 191 "M!(1)", "M!(3, 10)", "M!(4, a[2])", "M!(3, -25)" 192 ] 193 }), 194 195 "1024a" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 196 wordSize : 32, regSize : 32, rotN : 0, 197 m : [3, 24, 10], 198 ts : [ 199 "M!(1)", "M!(3, 8)", "M!(3, -19)", "M!(3, -14)", 200 "M!(3, -11)", "M!(3, -7)", "M!(3, -13)", "M!(0)" 201 ] 202 }), 203 204 "1024b" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 205 wordSize : 32, regSize : 32, rotN : 0, 206 m : [22, 25, 26], 207 ts : [ 208 "M!(3, -21)", "M!(3, 17)", "M!(4, a[3])", "M!(3, 15)", 209 "M!(3, -14)", "M!(3, -21)", "M!(1)", "M!(0)" 210 ] 211 }), 212 213 "19937a" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 214 wordSize : 32, regSize : 624, rotN : 31, 215 m : [70, 179, 449], 216 ts : [ 217 "M!(3, -25)", "M!(3, 27)", "M!(2, 9)", "M!(3, 1)", 218 "M!(1)", "M!(3, -9)", "M!(3, -21)", "M!(3, 21)" 219 ] 220 }), 221 222 "19937b" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 223 wordSize : 32, regSize : 624, rotN : 31, 224 m : [203, 613, 123], 225 ts : [ 226 "M!(3, 7)", "M!(1)", "M!(3, 12)", "M!(3, -10)", 227 "M!(3, -19)", "M!(2, -11)", "M!(3, 4)", "M!(3, 10)" 228 ] 229 }), 230 231 "19937c" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 232 wordSize : 32, regSize : 624, rotN : 31, 233 m : [70, 179, 449], 234 ts : [ 235 "M!(3, -25)", "M!(3, 27)", "M!(2, 9)", "M!(3, 1)", 236 "M!(1)", "M!(3, -9)", "M!(3, -21)", "M!(3, 21)" 237 ], 238 doTempering : true, 239 temperingBC : [0xe46e1700U, 0x9b868000U] 240 }), 241 242 "21701a" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 243 wordSize : 32, regSize : 679, rotN : 27, 244 m : [151, 327, 84], 245 ts : [ 246 "M!(1)", "M!(3, -26)", "M!(3, 19)", "M!(0)", 247 "M!(3, 27)", "M!(3, -11)", "M!(6, 15, 27, 10, a[4])", "M!(3, -16)" 248 ] 249 }), 250 251 "23209a" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 252 wordSize : 32, regSize : 726, rotN : 23, 253 m : [667, 43, 462], 254 ts : [ 255 "M!(3, 28)", "M!(1)", "M!(3, 18)", "M!(3, 3)", 256 "M!(3, 21)", "M!(3, -17)", "M!(3, -28)", "M!(3, -1)" 257 ] 258 }), 259 260 "23209b" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 261 wordSize : 32, regSize : 726, rotN : 23, 262 m : [610, 175, 662], 263 ts : [ 264 "M!(4, a[5])", "M!(1)", "M!(6, 15, 15, 30, a[6])", "M!(3, -24)", 265 "M!(3, -26)", "M!(1)", "M!(0)", "M!(3, 16)" 266 ] 267 }), 268 269 "44497a" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 270 wordSize : 32, regSize : 1391, rotN : 15, 271 m : [23, 481, 229], 272 ts : [ 273 "M!(3, -24)", "M!(3, 30)", "M!(3, -10)", "M!(2, -26)", 274 "M!(1)", "M!(3, 20)", "M!(6, 9, 5, 14, a[7])", "M!(1)" 275 ] 276 }), 277 278 "44497b" : _makeStructConstant!(WELLConstants_t!UIntType, q{ 279 wordSize : 32, regSize : 1391, rotN : 15, 280 m : [23, 481, 229], 281 ts : [ 282 "M!(3, -24)", "M!(3, 30)", "M!(3, -10)", "M!(2, -26)", 283 "M!(1)", "M!(3, 20)", "M!(6, 9, 5, 14, a[7])", "M!(1)" 284 ], 285 doTempering : true, 286 temperingBC : [0x93dd1400U, 0xfa118000U] 287 }) 288 ]; 289 290 /** WELL(512a) Random Number Generator. 291 See: http://www.iro.umontreal.ca/~panneton/WELLRNG.html 292 */ 293 alias WELLEngine(string name) = WELLEngine!(uint, name); 294 295 /// ditto 296 struct WELLEngine(UIntType, string name) 297 if( name == "512a" 298 || name == "521a" || name == "521b" 299 || name == "607a" || name == "607b" 300 || name == "800a" || name == "800b" 301 || name == "1024a" || name == "1024b" 302 || name == "19937a" || name == "19937b" || name == "19937c" 303 || name == "21701a" 304 || name == "23209a" || name == "23209b" 305 || name == "44497a" || name == "44497b") 306 { 307 enum Constant = WELLConstants!UIntType[name]; 308 enum size_t _stateSize = Constant.regSize; 309 310 static if(Constant.rotN == 0) 311 enum uint MASKU = 0; 312 else 313 enum uint MASKU = (~0U) >> (Constant.wordSize - Constant.rotN); 314 315 enum uint MASKL = ~MASKU; 316 317 public: 318 /// Mark as Random Number Generator 319 enum isUniformRandom = true; 320 321 /// maximum value 322 enum UIntType max = uint.max; 323 324 /// minimum value 325 enum UIntType min = 0; 326 327 /** 328 */ 329 this(uint value) 330 { 331 seed(value); 332 } 333 334 335 /** 336 */ 337 void seed(uint value) 338 { 339 _state[0] = value; 340 341 // from std.range.XorshiftEngine. 342 foreach(uint i; 1 .. cast(uint)_state.length) 343 _state[i] = cast(UIntType)(1812433253UL * (_state[i-1] ^ (_state[i-1] >> (Constant.wordSize - 2))) + i + 1); 344 345 popFront(); 346 } 347 348 349 /// range primitives 350 void popFront() 351 { 352 auto V0 = &(_state[_stateIdx]), 353 VM1 = &(_state[(_stateIdx + Constant.m[0]) % Constant.regSize]), 354 VM2 = &(_state[(_stateIdx + Constant.m[1]) % Constant.regSize]), 355 VM3 = &(_state[(_stateIdx + Constant.m[2]) % Constant.regSize]), 356 VRm1 = &(_state[(_stateIdx + Constant.regSize - 1) % Constant.regSize]), 357 VRm2 = &(_state[(_stateIdx + Constant.regSize - 2) % Constant.regSize]), 358 newV0 = VRm1, 359 newV1 = V0, 360 newVRm1 = VRm2; 361 362 immutable z0 = (*VRm1 & MASKL) | (*VRm2 & MASKU), 363 z1 = Constant.T!(Constant, 0)(*V0) ^ Constant.T!(Constant, 1)(*VM1), 364 z2 = Constant.T!(Constant, 2)(*VM2) ^ Constant.T!(Constant, 3)(*VM3), 365 z3 = z1 ^ z2; 366 367 *newV1 = z3; 368 *newV0 = Constant.T!(Constant, 4)(z0) ^ Constant.T!(Constant, 5)(z1) 369 ^ Constant.T!(Constant, 6)(z2) ^ Constant.T!(Constant, 7)(z3); 370 371 _stateIdx = (_stateIdx + Constant.regSize - 1) % Constant.regSize; 372 } 373 374 375 /// ditto 376 @property uint front() pure nothrow @safe 377 { 378 static if(Constant.doTempering) 379 { 380 immutable UIntType x = _state[_stateIdx], 381 y = x ^ ((x << 7) & Constant.temperingBC[0]); 382 383 return y ^ ((y << 15) & Constant.temperingBC[1]); 384 } 385 else 386 return _state[_stateIdx]; 387 } 388 389 390 /// ditto 391 enum bool empty = false; 392 393 394 /// ditto 395 @property typeof(this) save() pure nothrow @safe 396 { 397 return this; 398 } 399 400 401 private: 402 uint[_stateSize] _state; 403 size_t _stateIdx; 404 } 405 406 /// 407 unittest 408 { 409 import std.algorithm; 410 import std.range; 411 import std.stdio; 412 413 WELLEngine!"512a" rng; 414 415 static assert(isUniformRNG!(typeof(rng))); 416 static assert(isSeedable!(typeof(rng))); 417 418 rng.seed(100); 419 420 assert(equal(rng.save.take(8), 421 [ 2230636158, 422 1842930638, 423 155680193, 424 1855495099, 425 2311897807, 426 3102313483, 427 3970788677, 428 3720522367,])); 429 430 // save test 431 auto saved1 = rng.save; 432 auto saved2 = rng.save; 433 434 rng.popFrontN(100); 435 assert(equal(saved1.save.take(64), saved2.save.take(64))); 436 437 saved1.popFrontN(100); 438 assert(equal(rng.save.take(64), saved1.save.take(64))); 439 440 assert(rng.front == 1947823519); 441 rng.popFront(); 442 rng.popFrontN(10000); 443 assert(rng.front == 2831551372); 444 } 445 446 unittest 447 { 448 import std.algorithm; 449 import std.range; 450 import std.stdio; 451 452 WELLEngine!"1024a" rng; 453 rng.seed(100); 454 455 static assert(isUniformRNG!(typeof(rng))); 456 static assert(isSeedable!(typeof(rng))); 457 458 assert(equal(rng.save.take(8), 459 [ 1729689691, 460 963076657, 461 888412938, 462 181100396, 463 3310127585, 464 3649309487, 465 2484075420, 466 1423389279,])); 467 468 rng.popFrontN(100); 469 assert(rng.front == 725664384); 470 rng.popFront(); 471 472 rng.popFrontN(10000); 473 assert(rng.front == 3953644315); 474 } 475 476 unittest 477 { 478 import std.algorithm; 479 import std.range; 480 import std.stdio; 481 482 WELLEngine!"19937a" rng; 483 rng.seed(100); 484 485 static assert(isUniformRNG!(typeof(rng))); 486 static assert(isSeedable!(typeof(rng))); 487 488 assert(equal(rng.save.take(8), 489 [ 3859347685, 490 3376854944, 491 2220854319, 492 1533421060, 493 3247527917, 494 1794400208, 495 2014239377, 496 1401918048,])); 497 498 rng.popFrontN(100); 499 assert(rng.front == 2444980538); 500 rng.popFront(); 501 502 rng.popFrontN(10000); 503 assert(rng.front == 490674394); 504 } 505 506 unittest 507 { 508 import std.algorithm; 509 import std.range; 510 import std.stdio; 511 512 WELLEngine!"44497a" rng; 513 rng.seed(100); 514 515 static assert(isUniformRNG!(typeof(rng))); 516 static assert(isSeedable!(typeof(rng))); 517 518 assert(equal(rng.save.take(8), 519 [ 1904938054, 520 1236099671, 521 761528580, 522 261553665, 523 3145325643, 524 603047593, 525 3491142409, 526 496221207,])); 527 528 rng.popFrontN(100); 529 assert(rng.front == 738539296); 530 rng.popFront(); 531 532 rng.popFrontN(10000); 533 assert(rng.front == 2913233053); 534 } 535 536 unittest 537 { 538 import std.algorithm; 539 import std.range; 540 import std.stdio; 541 542 WELLEngine!"44497b" rng; 543 rng.seed(100); 544 545 static assert(isUniformRNG!(typeof(rng))); 546 static assert(isSeedable!(typeof(rng))); 547 548 assert(equal(rng.save.take(8), 549 [1913523270, 550 3946701399, 551 3211002116, 552 1993047553, 553 3283376203, 554 3676328617, 555 425402121, 556 1179532311,])); 557 558 rng.popFrontN(100); 559 assert(rng.front == 1015818016); 560 rng.popFront(); 561 562 rng.popFrontN(10000); 563 assert(rng.front == 229698717); 564 } 565 566 567 bool diceToF(F, R)(F p, ref Rng rng) 568 if(isUniformRNG!Rng) 569 { 570 return uniform01(rng) < p; 571 } 572 573 574 auto dist(string name)(ref Rng rng) 575 if((name == "uni01" || name == "uniform01") && isUniformRNG!Rng) 576 { 577 return uniform01(rng); 578 } 579 580 581 auto dist(string name, string boundaries = "[)", T1, T2, Rng)(T1 a, T2 b, ref Rng rng) 582 if((name == "uni" || name == "uniform") && isUniformRNG!Rng) 583 { 584 return uniform!boundaries(a, b, rng); 585 } 586 587 588 auto ref dist(string name, R, B, Rng)(R p, auto ref B t, auto ref B f, ref Rng rng) 589 if((name == "ber" || name == "bernoulli") && is(R : real) && isUniformRNG!Rng) 590 { 591 immutable R r = uniform01!R(rng); 592 if(r < p) 593 return t; 594 else 595 return f; 596 } 597 598 599 R dist(string name, R, Rng)(R lambda, ref Rng rng) 600 if((name == "exp" || name == "exponential") && is(R : real) && isUniformRNG!Rng) 601 { 602 return -log(uniform01!R(rng)) / lambda; 603 } 604 605 606 R dist(string name, R, Rng)(ref Rng rng) 607 if(name == "stdNormal" && is(R : real) && isUniformRNG!Rng) 608 { 609 immutable x = uniform01!R(rng), 610 y = uniform01!R(rng); 611 612 return sqrt(-2 * log(x)) * cos(2 * PI * y); 613 } 614 615 616 R dist(string name, R, Rng)(R mu, R sigma, ref Rng rng) 617 if(name == "normal" && is(R : real) && isUniformRNG!Rng) 618 { 619 return dist!"stdNormal"(rng) * sigma + mu; 620 } 621 622 623 //N dist(string name, N, R, Rng)(N n, R p, ref Rng rng) 624 //if((name == "bin" || name == "binominal") && is(R : real) && is(N : ulong)) 625 //{ 626 627 //} 628 629 630 template dist(string name, Params...) 631 { 632 auto ref dist(T...)(auto ref T args) 633 { 634 return dist!(name, Params)(forward!args, std.random.rndGen); 635 } 636 } 637 638 639 ///** 640 //一様分布 641 //*/ 642 //auto distGenerator(string name, string boundaries = "[)", T1, T2)(T1 a, T2 b) 643 //{ 644 // static struct Generator() 645 // { 646 // alias F = typeof(uniform(T1.init, T2.init, std.random.rndGen)); 647 648 // F gen(alias bs = boundaries, T1, T2, Rng)(T1 a, T2 b, ref Rng rng) 649 // if(isUniformRNG!Rng) 650 // { 651 // return uniform!bs(a, b, rng); 652 // } 653 654 655 // F gen(alias bs = boundaries, T1, T2)(T1 a, T2 b) 656 // if(isUniformRNG!Rng) 657 // { 658 // return gen!bs(a, b, std.random.rndGen); 659 // } 660 661 662 // F gen(alias bs = boundaries, Rng)(ref Rng rng) 663 // if(isUniformRNG!Rng) 664 // { 665 // return gen!bs(_a, _b, rng); 666 // } 667 668 669 // F gen(alias bs = boundaries)() 670 // if(isUniformRNG!Rng) 671 // { 672 // return gen!bs(std.random.rndGen); 673 // } 674 675 676 // F opCall(Rng)(ref Rng rng) 677 // if(isUniformRNG!Rng) 678 // { 679 // return uniform!boundaries(_a, _b, rng); 680 // } 681 682 683 // F opCall() 684 // { 685 // return opCall(std.random.rndGen); 686 // } 687 688 689 // private: 690 // T1 _a; 691 // T2 _b; 692 // } 693 694 695 // return Generator!()(a, b); 696 //} 697 698 699 ///** 700 //ベルヌーイ分布 701 //*/ 702 //auto distGenerator(string name, R, B = bool)(R p, B t = true, B f = false) 703 //if((name == "ber" || name == "bernoulli") && is(R : real)) 704 //{ 705 // static struct Generator() 706 // { 707 // auto ref gen(R, B, Rng)(R p, auto ref B t, auto ref B f, ref Rng rng) 708 // if(is(R : real) && isUniformRNG!Rng) 709 // { 710 // auto r = uniform01!R(rng); 711 // return r < p ? forward!t : forward!f; 712 // } 713 714 715 // auto ref gen(R, B, Rng)(R p, auto ref B t, auto ref B f) 716 // if(is(R : real)) 717 // { 718 // return gen(p, forward!t, forward!f, std.random.rndGen); 719 // } 720 721 722 // auto ref gen(B, Rng)(auto ref B t, auto ref B f, ref Rng rng) 723 // { 724 // return gen(_p, forward!t, forward!f, std.random.rndGen); 725 // } 726 727 728 // B gen(R, Rng)(R p, ref Rng rng) 729 // { 730 // return gen(p, _t, _f, rng); 731 // } 732 733 734 // //B gen(R, Rng) 735 // } 736 //} 737 738 739 //template distRange(string name, TemplateParams...) 740 //{ 741 // auto distRange(RefRng, Params...)(RefRng rng, auto ref Params params) 742 // { 743 // alias D = typeof(distGenerator!(name, TemplateParams)(params)); 744 // alias F = typeof(D.init(rng)); 745 746 747 // static struct DistRange() 748 // { 749 // F front() @property 750 // { 751 // if(_cached) 752 // return _cach; 753 // else{ 754 // _cach = _dGen(_rng); 755 // _cached = true; 756 // return _cach; 757 // } 758 // } 759 760 761 // void popFront() 762 // { 763 // if(_cached) _cached = false; 764 // else{ 765 // _rng.popFront; 766 // } 767 // } 768 769 770 // static if(isInfinite!RefRng) 771 // enum bool empty = false; 772 // else 773 // { 774 // bool empty() @property 775 // { 776 // return _rng.empty; 777 // } 778 // } 779 780 781 // private: 782 // RefRng _rng; 783 // D _dGen; 784 // F _cach; 785 // bool _cached; 786 // } 787 788 // return DistRange!()(rng, distGenerator!(name, Params)(forward!params), F.init, false); 789 // } 790 //} 791 792 //unittest 793 //{ 794 // import carbon.nonametype; 795 796 // WELLEngine!"512a" rng; 797 // rng.seed(100); 798 799 // auto r = rng.scopedRef!"trusted".distRange!("uni", "[)")(0, 10); 800 // static assert(isInputRange!(typeof(r))); 801 // foreach(e; r.take(1000)) 802 // assert(e >= 0 && e < 10); 803 //}