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 //}