1 /*******************************************************************************
2 
3     Random number generators
4 
5     This is an attempt at having a good flexible and easy to use random number
6     generator.
7     ease of use:
8     $(UL
9       $(LI  shared generator for quick usage available through the "rand" object
10             ---
11             int i=rand.uniformR(10); // a random number from [0;10$(RPAREN)
12             ---
13       )
14       $(LI  simple Random (non threadsafe) and RandomSync (threadsafe) types to
15             create new generators (for heavy use a good idea is one Random object per thread)
16       )
17       $(LI  several distributions can be requested like this
18             ---
19             rand.distributionD!(type)(paramForDistribution)
20             ---
21             the type can often be avoided if the parameters make it clear.
22             From it single numbers can be generated with .getRandom(), and variables
23             initialized either with call style (var) or with .randomize(var).
24             Utility functions to generate numbers directly are also available.
25             The choice to put all the distribution in a single object that caches them
26             has made (for example) the gamma distribution very easy to implement.
27       )
28       $(LI  sample usage:
29             ---
30             auto r=new Random();
31             int i; float f; real rv; real[100] ar0; real[] ar=ar0[];
32             // initialize with uniform distribution
33             i=r.uniform!(int);
34             f=r.uniform!(float);
35             rv=r.uniform!(real);
36             foreach (ref el;ar)
37               el=r.uniform!(real);
38             // another way to do all the previous in one go:
39             r(i)(f)(rv)(ar);
40             // unfortunetely one cannot use directly ar0...
41             // uniform distribution 0..10
42             i=r.uniformR(10);
43             f=r.uniformR(10.0f);
44             rv=r.uniformR(10.0L);
45             foreach (ref el;ar)
46               el=r.uniformR(10.0L);
47             // another way to do all the previous in one go:
48             r.uniformRD(10)(i)(f)(r)(ar);
49             // uniform numbers in [5;10)
50             i=r.uniformR2(5,10);
51             // uniform numbers in (5;10)
52             f=r.uniformR2(5.0f,10.0f);
53             rv=r.uniformR2(5.0L,10.0L);
54             foreach (ref el;ar)
55               el=r.uniformR2(5.0L,10.0L);
56             // another way to do all the previous in one go:
57             r.uniformR2D(5.0L,10.0L)(i)(f)(r)(ar);
58             // uniform distribution -10..10
59             i=r.uniformRSymm(10);
60             // well you get it...
61             r.uniformRSymmD(10)(i)(f)(r)(ar);
62             // any distribution can be stored
63             auto r2=r.uniformRSymmD(10);
64             // and used later
65             r2(ar);
66             // complex distributions (normal,exp,gamma) are produced for the requested type
67             r.normalSource!(float)()(f);
68             // with sigma=2
69             r.normalD(2.0f)(f);
70             // and can be used also to initialize other types
71             r.normalSource!(float)()(r)(ar);
72             r.normalD(2.0f)(r)(ar);
73             // but this is different from
74             r.normalSource!(real)()(i)(r)(ar);
75             r.normalD(2.0L)(i)(r)(ar);
76             // as the source generates numbers of its type that then are simply cast to
77             // the type needed.
78             // Uniform distribution (as its creation for different types has no overhead)
79             // is never cast, so that (for example) bounds exclusion for floats is really
80             // guaranteed.
81             // For the other distribution using a distribution of different type than
82             // the variable should be done with care, as underflow/overflow might ensue.
83             //
84             // Some utility functions are also available
85             int i2=r.uniform!(int)();
86             int i2=r.randomize(i); // both i and i2 are initialized to the same value
87             float f2=r.normalSigma(3.0f);
88             ---
89       )
90     )
91     flexibility:
92     $(UL
93       $(LI  easily swappable basic source
94             ---
95             // a random generator that uses the system provided random generator:
96             auto r=RandomG!(Urandom)();
97             ---
98             One could also build an engine that can be changed at runtime (that calls
99             a delegate for example), but this adds a little overhead, and changing
100             engine is not something done often, so this is not part of the library.
101       )
102       $(LI  ziggurat generator can be easily adapted to any decreasing derivable
103             distribution, the hard parametrization (to find xLast) can be done
104             automatically
105       )
106       $(LI  several distributions available "out of the box"
107       )
108       )
109     Quality:
110     $(UL
111       $(LI  the default Source combines two surces that pass all statistical tests
112             (KISS+CMWC)
113             (P. L'Ecuyer and R. Simard, ACM Transactions on Mathematical Software (2007),
114             33, 4, Article 22, for KISS, see CMWC engine for the other)
115       )
116       $(LI  floating point uniform generator always initializes the full mantissa, the
117             only flaw is a (*very* small) predilection of 0 as least important bit
118             (IEEE rounds to 0 in case of tie).
119             Using a method that initializes the full mantissa was shown to improve the
120             quality of subsequntly derived normal distribued numbers
121             (Thomas et al. Gaussian random number generators. Acm Comput Surv (2007)
122             vol. 39 (4) pp. 11)
123       )
124       $(LI  Ziggurat method, a very fast and accurate method was used for both Normal and
125             exp distributed numbers.
126       )
127       $(LI  gamma distribued numbers uses a method recently proposed by Marsaglia and
128             Tsang. The method is very fast, and should be good.
129             My (Fawzi's) feeling is that the transformation h(x)=(1+d*x)^3 might lose
130             a couple of bits of precision in some cases, but it is unclear if this
131             might become visible in (*very* extensive) tests or not.
132       )
133        the basic source can be easily be changed with something else
134     Efficiency:
135       $(LI  very fast methods have been used, and some effort has been put into
136             optimizing some of them, but not all, but the interface has been choosen
137             so that close to optimal implementation can be provided through the same
138             interface.
139       )
140       $(LI  Normal and Exp sources allocated only upon request: no memory waste, but
141             a (*very* small) speed hit, that can be avoided by storing the source in
142             a variable and using it (not going through the RandomG)
143       )
144     )
145     Annoyances:
146     $(UL
147       $(LI  I have added two "next" methods to RandomG for backward compatibility
148             reasons, and the .instance from Random has been
149             replaced by the "rand" object. The idea behind this is that RandomG is
150             a template and rand it should be shared across all templates.
151             If the name rand is considered bad one could change it.
152             I kept .instance static method that returns rand, so this remain a dropin
153             replacement of the old random.
154       )
155       $(LI You cannot initialize a static array directly, this because randomize is
156           declared like this:
157             ---
158             U randomize(U)(ref U a) { }
159             ---
160             and a static array cannot be passed by reference. Removing the ref would
161             make arrays initialized, and scalar not, which is much worse.
162       )
163     )
164 
165     Copyright:
166         Copyright (c) 2008. Fawzi Mohamed
167         Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH.
168         All rights reserved.
169 
170     License:
171         Tango Dual License: 3-Clause BSD License / Academic Free License v3.0.
172         See LICENSE_TANGO.txt for details.
173 
174     Version: Initial release: July 2008
175 
176     Authors: Fawzi Mohamed
177 
178 *******************************************************************************/
179 module ocean.math.random.Random;
180 
181 import ocean.meta.types.Qualifiers;
182 
183 import ocean.math.random.engines.URandom;
184 import ocean.math.random.engines.KissCmwc;
185 import ocean.math.random.engines.ArraySource;
186 import ocean.math.random.engines.Twister;
187 import ocean.math.random.NormalSource;
188 import ocean.math.random.ExpSource;
189 import ocean.math.Math;
190 import ocean.meta.types.Arrays /* : StripAllArrays */;
191 import ocean.core.Verify;
192 
193 // ----- templateFu begin --------
194 /// compile time integer power
195 private Unqual!(T) ctfe_powI(T)(T _x,int p){
196     Unqual!(T) x = _x;
197     Unqual!(T) xx = cast(Unqual!(T))1;
198     if (p<0){
199         p=-p;
200         x=1/x;
201     }
202     for (int i=0;i<p;++i)
203         xx*=x;
204     return xx;
205 }
206 // ----- templateFu end --------
207 
208 version=has_urandom;
209 
210 /// if T is a float
211 template isFloat(T){
212     static if(is(T==float)||is(T==double)||is(T==real)){
213         static immutable bool isFloat=true;
214     } else {
215         static immutable bool isFloat=false;
216     }
217 }
218 
219 /// The default engine, a reasonably collision free, with good statistical properties
220 /// not easy to invert, and with a relatively small key (but not too small)
221 alias KissCmwc_32_1 DefaultEngine;
222 
223 /// Class that represents a random number generator.
224 /// Normally you should get random numbers either with call-like interface:
225 ///   auto r=new Random(); r(i)(j)(k);
226 /// or with randomize
227 ///   r.randomize(i); r.randomize(j); r.randomize(k);
228 /// if you use this you should be able to easily switch distribution later,
229 /// as all distributions support this interface, and can be built on the top of RandomG
230 ///   auto r2=r.NormalSource!(float)(); r2(i)(j)(k);
231 /// there are utility methods within random for the cases in which you do not
232 /// want to build a special distribution for just a few numbers
233 final class RandomG(SourceT=DefaultEngine)
234 {
235     // uniform random source
236     SourceT source;
237     // normal distributed sources
238     NormalSource!(RandomG,float)  normalFloat;
239     NormalSource!(RandomG,double) normalDouble;
240     NormalSource!(RandomG,real)   normalReal;
241     // exp distributed sources
242     ExpSource!(RandomG,float)  expFloat;
243     ExpSource!(RandomG,double) expDouble;
244     ExpSource!(RandomG,real)   expReal;
245 
246     /// Creates and seeds a new generator
247     this (bool randomInit=true)
248     {
249         if (randomInit)
250             this.seed;
251     }
252 
253     /// if source.canSeed seeds the generator using the shared rand generator
254     /// (use urandom directly if available?)
255     RandomG seed ()
256     {
257         static if(is(typeof(SourceT.canSeed))) {
258             static if (SourceT.canSeed)
259                 source.seed(&rand.uniform!(uint));
260         }
261         return this;
262     }
263     /// if source.canSeed seeds the generator using the given source of uints
264     RandomG seed (scope uint delegate() seedSource)
265     {
266         static if(is(typeof(SourceT.canSeed))) {
267             static if (SourceT.canSeed)
268                 source.seed(seedSource);
269         }
270         return this;
271     }
272 
273     /// compatibility with old Random, deprecate??
274     uint next(){
275         return uniform!(uint)();
276     }
277     /// ditto
278     uint next(uint to){
279         return uniformR!(uint)(to);
280     }
281     /// ditto
282     uint next(uint from,uint to){
283         return uniformR2!(uint)(from,to);
284     }
285     /// ditto
286     static RandomG!(DefaultEngine) instance(){
287         return rand;
288     }
289     //-------- Utility functions to quickly get a uniformly distributed random number -----------
290 
291     /// uniform distribution on the whole range of integer types, and on
292     /// the (0;1) range for floating point types. Floating point guarantees the initialization
293     /// of the full mantissa, but due to rounding effects it might have *very* small
294     /// dependence due to rounding effects on the least significant bit (in case of tie 0 is favored).
295     /// if boundCheck is false in the floating point case bounds might be included (but with a
296     /// lower propability than other numbers)
297     T uniform(T,bool boundCheck=true)(){
298         static if(is(T==uint)) {
299             return source.next;
300         } else static if (is(T==int) || is(T==short) || is(T==ushort)|| is(T==char) || is(T==byte) || is(T==ubyte)){
301             union Uint2A{
302                 T t;
303                 uint u;
304             }
305             Uint2A a;
306             a.u=source.next;
307             return a.t;
308         } else static if (is(T==long) || is (T==ulong)){
309             return cast(T)source.nextL;
310         } else static if (is(T==bool)){
311             return cast(bool)(source.next & 1u); // check lowest bit
312         } else static if (is(T==float)||is(T==double)||is(T==real)){
313             static if (T.mant_dig<30) {
314                 static immutable T halfT=(cast(T)1)/(cast(T)2);
315                 static immutable T fact32=ctfe_powI(halfT,32);
316                 static immutable uint minV=1u<<(T.mant_dig-1);
317                 uint nV=source.next;
318                 if (nV>=minV) {
319                     T res=nV*fact32;
320                     static if (boundCheck){
321                         if (res!=cast(T)1) return res;
322                         // 1 due to rounding (<3.e-8), 0 impossible
323                         return uniform!(T,boundCheck)();
324                     } else {
325                         return res;
326                     }
327                 } else { // probability 0.00390625 for 24 bit mantissa
328                     T scale=fact32;
329                     while (nV==0){ // probability 2.3283064365386963e-10
330                         nV=source.next;
331                         scale*=fact32;
332                     }
333                     T res=nV*scale+source.next*scale*fact32;
334                     static if (boundCheck){
335                         if (res!=cast(T)0) return res;
336                         return uniform!(T,boundCheck)(); // 0 due to underflow (<1.e-38), 1 impossible
337                     } else {
338                         return res;
339                     }
340                 }
341             } else static if (T.mant_dig<62) {
342                 static immutable T halfT=(cast(T)1)/(cast(T)2);
343                 static immutable T fact64=ctfe_powI(halfT,64);
344                 static immutable ulong minV=1UL<<(T.mant_dig-1);
345                 ulong nV=source.nextL;
346                 if (nV>=minV) {
347                     T res=nV*fact64;
348                     static if (boundCheck){
349                         if (res!=cast(T)1) return res;
350                         // 1 due to rounding (<1.e-16), 0 impossible
351                         return uniform!(T,boundCheck)();
352                     } else {
353                         return res;
354                     }
355                 } else { // probability 0.00048828125 for 53 bit mantissa
356                     static immutable T fact32=ctfe_powI(halfT,32);
357                     static immutable ulong minV2=1UL<<(T.mant_dig-33);
358                     if (nV>=minV2){
359                         return ((cast(T)nV)+(cast(T)source.next)*fact32)*fact64;
360                     } else { // probability 1.1368683772161603e-13 for 53 bit mantissa
361                         T scale=fact64;
362                         while (nV==0){
363                             nV=source.nextL;
364                             scale*=fact64;
365                         }
366                         T res=scale*((cast(T)nV)+(cast(T)source.nextL)*fact64);
367                         static if (boundCheck){
368                             if (res!=cast(T)0) return res;
369                             // 0 due to underflow (<1.e-307)
370                             return uniform!(T,boundCheck)();
371                         } else {
372                             return res;
373                         }
374                     }
375                 }
376             } else static if (T.mant_dig<=64){
377                 static immutable T halfT=(cast(T)1)/(cast(T)2);
378                 static immutable T fact8=ctfe_powI(halfT,8);
379                 static immutable T fact72=ctfe_powI(halfT,72);
380                 ubyte nB=source.nextB;
381                 if (nB!=0){
382                     T res=nB*fact8+source.nextL*fact72;
383                     static if (boundCheck){
384                         if (res!=cast(T)1) return res;
385                         // 1 due to rounding (<1.e-16), 0 impossible
386                         return uniform!(T,boundCheck)();
387                     } else {
388                         return res;
389                     }
390                 } else { // probability 0.00390625
391                     static immutable T fact64=ctfe_powI(halfT,64);
392                     T scale=fact8;
393                     while (nB==0){
394                         nB=source.nextB;
395                         scale*=fact8;
396                     }
397                     T res=((cast(T)nB)+(cast(T)source.nextL)*fact64)*scale;
398                     static if (boundCheck){
399                         if (res!=cast(T)0) return res;
400                         // 0 due to underflow (<1.e-4932), 1 impossible
401                         return uniform!(T,boundCheck)();
402                     } else {
403                         return res;
404                     }
405                 }
406             } else {
407                 // (T.mant_dig > 64 bits), not so optimized, but works for any size
408                 static immutable T halfT=(cast(T)1)/(cast(T)2);
409                 static immutable T fact32=ctfe_powI(halfT,32);
410                 uint nL=source.next;
411                 T fact=fact32;
412                 while (nL==0){
413                     fact*=fact32;
414                     nL=source.next;
415                 }
416                 T res=nL*fact;
417                 for (int rBits=T.mant_dig-1;rBits>0;rBits-=32) {
418                     fact*=fact32;
419                     res+=source.next()*fact;
420                 }
421                 static if (boundCheck){
422                     if (res!=cast(T)0 && res !=cast(T)1) return res;
423                     return uniform!(T,boundCheck)(); // really unlikely...
424                 } else {
425                     return res;
426                 }
427             }
428         } else static if (is(T==cfloat)||is(T==cdouble)||is(T==creal)){
429             return cast(T)(uniform!(realType!(T))()+1i*uniform!(realType!(T))());
430         } else static if (is(T==ifloat)||is(T==idouble)||is(T==ireal)){
431             return cast(T)(1i*uniform!(realType!(T))());
432         } else static assert(0,T.stringof~" unsupported type for uniform distribution");
433     }
434 
435     /// uniform distribution on the range [0;to$(RPAREN) for integer types, and on
436     /// the (0;to) range for floating point types. Same caveat as uniform(T) apply
437     T uniformR(T,bool boundCheck=true)(T to)
438     {
439         verify(to>0,"empty range");
440         static if (is(T==uint) || is(T==int) || is(T==short) || is(T==ushort)
441             || is(T==char) || is(T==byte) || is(T==ubyte))
442         {
443             uint d=uint.max/cast(uint)to,dTo=to*d;
444             uint nV=source.next;
445             if (nV>=dTo){
446                 for (int i=0;i<1000;++i) {
447                     nV=source.next;
448                     if (nV<dTo) break;
449                 }
450                 verify(nV<dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
451             }
452             return cast(T)(nV%to);
453         } else static if (is(T==ulong) || is(T==long)){
454             ulong d=ulong.max/cast(ulong)to,dTo=to*d;
455             ulong nV=source.nextL;
456             if (nV>=dTo){
457                 for (int i=0;i<1000;++i) {
458                     nV=source.nextL;
459                     if (nV<dTo) break;
460                 }
461                 verify(nV<dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
462             }
463             return cast(T)(nV%to);
464         } else static if (is(T==float)|| is(T==double)||is(T==real)){
465             T res=uniform!(T,false)*to;
466             static if (boundCheck){
467                 if (res!=cast(T)0 && res!=to) return res;
468                 return uniformR(to);
469             } else {
470                 return res;
471             }
472         } else static assert(0,T.stringof~" unsupported type for uniformR distribution");
473     }
474     /// uniform distribution on the range (-to;to) for integer types, and on
475     /// the (-to;0)(0;to) range for floating point types if boundCheck is true.
476     /// If boundCheck=false the range changes to [-to;0$(RPAREN)u$(LPAREN)0;to] with a slightly
477     /// lower propability at the bounds for floating point numbers.
478     /// excludeZero controls if 0 is excluded or not (by default float exclude it,
479     /// ints no). Please note that the probability of 0 in floats is very small due
480     //  to the high density of floats close to 0.
481     /// Cannot be used on unsigned types.
482     ///
483     /// In here there is probably one of the few cases where c handling of modulo of negative
484     /// numbers is handy
485     T uniformRSymm(T,bool boundCheck=true, bool excludeZero=isFloat!(T))(T to,int iter=2000)
486     {
487         verify(to>0,"empty range");
488         static if (is(T==int)|| is(T==short) || is(T==byte)){
489             int d=int.max/to,dTo=to*d;
490             int nV=cast(int)source.next;
491             static if (excludeZero){
492                 int isIn=nV<dTo&&nV>-dTo&&nV!=0;
493             } else {
494                 int isIn=nV<dTo&&nV>-dTo;
495             }
496             if (isIn){
497                 return cast(T)(nV%to);
498             } else {
499                 for (int i=0;i<1000;++i) {
500                     nV=cast(int)source.next;
501                     if (nV<dTo && nV>-dTo) break;
502                 }
503                 verify(nV<dTo && nV>-dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
504                 return cast(T)(nV%to);
505             }
506         } else static if (is(T==long)){
507             long d=long.max/to,dTo=to*d;
508             long nV=cast(long)source.nextL;
509             static if (excludeZero){
510                 int isIn=nV<dTo&&nV>-dTo&&nV!=0;
511             } else {
512                 int isIn=nV<dTo&&nV>-dTo;
513             }
514             if (isIn){
515                 return nV%to;
516             } else {
517                 for (int i=0;i<1000;++i) {
518                     nV=source.nextL;
519                     if (nV<dTo && nV>-dTo) break;
520                 }
521                 verify(nV<dTo && nV>-dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
522                 return nV%to;
523             }
524         } else static if (is(T==float)||is(T==double)||is(T==real)){
525             static if (T.mant_dig<30){
526                 static immutable T halfT=(cast(T)1)/(cast(T)2);
527                 static immutable T fact32=ctfe_powI(halfT,32);
528                 static immutable uint minV=1u<<T.mant_dig;
529                 uint nV=source.next;
530                 if (nV>=minV) {
531                     T res=nV*fact32*to;
532                     static if (boundCheck){
533                         if (res!=to) return (1-2*cast(int)(nV&1u))*res;
534                         // to due to rounding (~3.e-8), 0 impossible with normal to values
535                         verify(iter>0,"error with the generator, probability < 10^(-8*2000)");
536                         return uniformRSymm(to,iter-1);
537                     } else {
538                         return (1-2*cast(int)(nV&1u))*res;
539                     }
540                 } else { // probability 0.008 for 24 bit mantissa
541                     T scale=fact32;
542                     while (nV==0){ // probability 2.3283064365386963e-10
543                         nV=source.next;
544                         scale*=fact32;
545                     }
546                     uint nV2=source.next;
547                     T res=(cast(T)nV+cast(T)nV2*fact32)*scale*to;
548                     static if (excludeZero){
549                         if (res!=cast(T)0) return (1-2*cast(int)(nV&1u))*res;
550                         verify(iter>0,"error with the generator, probability < 10^(-8*2000)");
551                         return uniformRSymm(to,iter-1); // 0 due to underflow (<1.e-38), 1 impossible
552                     } else {
553                         return (1-2*cast(int)(nV&1u))*res;
554                     }
555                 }
556             } else static if (T.mant_dig<62) {
557                 static immutable T halfT=(cast(T)1)/(cast(T)2);
558                 static immutable T fact64=ctfe_powI(halfT,64);
559                 static immutable ulong minV=1UL<<(T.mant_dig);
560                 ulong nV=source.nextL;
561                 if (nV>=minV) {
562                     T res=nV*fact64*to;
563                     static if (boundCheck){
564                         if (res!=to) return (1-2*cast(int)(nV&1UL))*res;
565                         // to due to rounding (<1.e-16), 0 impossible with normal to values
566                         verify(iter>0,"error with the generator, probability < 10^(-16*2000)");
567                         return uniformRSymm(to,iter-1);
568                     } else {
569                         return (1-2*cast(int)(nV&1UL))*res;
570                     }
571                 } else { // probability 0.00048828125 for 53 bit mantissa
572                     static immutable T fact32=ctfe_powI(halfT,32);
573                     static immutable ulong minV2=1UL<<(T.mant_dig-32);
574                     if (nV>=minV2){
575                         uint nV2=source.next;
576                         T res=((cast(T)nV)+(cast(T)nV2)*fact32)*fact64*to;
577                         return (1-2*cast(int)(nV2&1UL))*res; // cannot be 0 or to with normal to values
578                     } else { // probability 1.1368683772161603e-13 for 53 bit mantissa
579                         T scale=fact64;
580                         while (nV==0){
581                             nV=source.nextL;
582                             scale*=fact64;
583                         }
584                         ulong nV2=source.nextL;
585                         T res=to*scale*((cast(T)nV)+(cast(T)nV2)*fact64);
586                         static if (excludeZero){
587                             if (res!=cast(T)0) return (1-2*cast(int)(nV2&1UL))*res;
588                             // 0 due to underflow (<1.e-307)
589                             verify(iter>0,"error with the generator, probability < 10^(-16*2000)");
590                             return uniformRSymm(to,iter-1);
591                         } else {
592                             return (1-2*cast(int)(nV2&1UL))*res;
593                         }
594                     }
595                 }
596             } else static if (T.mant_dig<=64) {
597                 static immutable T halfT=(cast(T)1)/(cast(T)2);
598                 static immutable T fact8=ctfe_powI(halfT,8);
599                 static immutable T fact72=ctfe_powI(halfT,72);
600                 ubyte nB=source.nextB;
601                 if (nB!=0){
602                     ulong nL=source.nextL;
603                     T res=to*(nB*fact8+nL*fact72);
604                     static if (boundCheck){
605                         if (res!=to) return (1-2*cast(int)(nL&1UL))*res;
606                         // 1 due to rounding (<1.e-16), 0 impossible with normal to values
607                         verify(iter>0,"error with the generator, probability < 10^(-16*2000)");
608                         return uniformRSymm(to,iter-1);
609                     } else {
610                         return (1-2*cast(int)(nL&1UL))*res;
611                     }
612                 } else { // probability 0.00390625
613                     static immutable T fact64=ctfe_powI(halfT,64);
614                     T scale=fact8;
615                     while (nB==0){
616                         nB=source.nextB;
617                         scale*=fact8;
618                     }
619                     ulong nL=source.nextL;
620                     T res=((cast(T)nB)+(cast(T)nL)*fact64)*scale*to;
621                     static if (excludeZero){
622                         if (res!=cast(T)0) return ((nL&1UL)?res:-res);
623                         // 0 due to underflow (<1.e-4932), 1 impossible
624                         verify(iter>0,"error with the generator, probability < 10^(-16*2000)");
625                         return uniformRSymm(to,iter-1);
626                     } else {
627                         return ((nL&1UL)?res:-res);
628                     }
629                 }
630             } else {
631                 // (T.mant_dig > 64 bits), not so optimized, but works for any size
632                 static immutable T halfT=(cast(T)1)/(cast(T)2);
633                 static immutable T fact32=ctfe_powI(halfT,32);
634                 uint nL=source.next;
635                 T fact=fact32;
636                 while (nL==0){
637                     fact*=fact32;
638                     nL=source.next;
639                 }
640                 T res=nL*fact;
641                 for (int rBits=T.mant_dig;rBits>0;rBits-=32) {
642                     fact*=fact32;
643                     nL=source.next();
644                     res+=nL*fact;
645                 }
646                 static if (boundCheck){
647                     if (res!=to && res!=cast(T)0) return ((nL&1UL)?res:-res);
648                     // 1 due to rounding (<1.e-16), 0 impossible with normal to values
649                     verify(iter>0,"error with the generator, probability < 10^(-16*2000)");
650                     return uniformRSymm(to,iter-1);
651                 } else {
652                     return ((nL&1UL)?res:-res);
653                 }
654             }
655         } else static assert(0,T.stringof~" unsupported type for uniformRSymm distribution");
656     }
657     /// uniform distribution [from;to$(RPAREN) for integers, and (from;) for floating point numbers.
658     /// if boundCheck is false the bounds are included in the floating point number distribution.
659     /// the range for int and long is limited to only half the possible range
660     /// (it could be worked around using long aritmethic for int, and doing a carry by hand for long,
661     /// but I think it is seldomly needed, for int you are better off using long when needed)
662     T uniformR2(T,bool boundCheck=true)(T from,T to)
663     {
664         verify(to>from,"empy range in uniformR2");
665         static if (is(T==int) || is(T==long)){
666             verify(from>T.min/2&&to<T.max/2," from..to range too big");
667         }
668         static if (is(T==int)||is(T==long)||is(T==uint)||is(T==ulong)){
669             return from+uniformR(to-from);
670         } else static if (is(T==char) || is(T==byte) || is(T==ubyte) || is(T==short) || is(T==ushort)){
671             int d=cast(int)to-cast(int)from;
672             int nV=uniformR!(int)(d);
673             return cast(T)(nV+cast(int)from);
674         } else static if (is(T==float) || is(T==double) || is(T==real)){
675             T res=from+(to-from)*uniform!(T,false);
676             static if (boundCheck){
677                 if (res!=from && res!=to) return res;
678                 return uniformR2(from,to);
679             } else {
680                 return res;
681             }
682         } else static assert(0,T.stringof~" unsupported type for uniformR2 distribution");
683     }
684     /// returns a random element of the given array (which must be non empty)
685     T uniformEl(T)(T[] arr){
686         verify(arr.length>0,"array has to be non empty");
687         return arr[uniformR(arr.length)];
688     }
689 
690     /**************************************************************************
691 
692         Randomizes the given array and returns it (for some types this is
693         potentially more efficient, both from the use of random numbers
694         and speedwise)
695 
696     *************************************************************************/
697 
698     U randomizeUniform(U,bool boundCheck)(ref U a){
699         static if (is(U S:S[])){
700             alias StripAllArrays!(U) T;
701             static if (is(T==byte)||is(T==ubyte)||is(T==char)){
702                 uint val=source.next; /// begin without value?
703                 int rest=4;
704                 for (size_t i=0;i<a.length;++i) {
705                     if (rest!=0){
706                         a[i]=cast(T)(0xFFu&val);
707                         val>>=8;
708                         --rest;
709                     } else {
710                         val=source.next;
711                         a[i]=cast(T)(0xFFu&val);
712                         val>>=8;
713                         rest=3;
714                     }
715                 }
716             } else static if (is(T==uint)||is(T==int)){
717                 T* aEnd=a.ptr+a.length;
718                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr)
719                     *aPtr=cast(T)(source.next);
720             } else static if (is(T==ulong)||is(T==long)){
721                 T* aEnd=a.ptr+a.length;
722                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr)
723                     *aPtr=cast(T)(source.nextL);
724             } else static if (is(T==float)|| is(T==double)|| is(T==real)) {
725                 // optimize more? not so easy with guaranteed full mantissa initialization
726                 T* aEnd=a.ptr+a.length;
727                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
728                     *aPtr=uniform!(T,boundCheck)();
729                 }
730             } else static assert(T.stringof~" type not supported by randomizeUniform");
731         } else {
732             a=uniform!(U,boundCheck)();
733         }
734         return a;
735     }
736 
737     /**************************************************************************
738 
739         Randomizes the given array and returns it (for some types this is
740         potentially more efficient, both from the use of random numbers
741         and speedwise)
742 
743     *************************************************************************/
744 
745     U randomizeUniformR(U,V,bool boundCheck=true)(ref U a,V to)
746     {
747         verify((cast(StripAllArrays!(U))to)>0,"empty range");
748         alias StripAllArrays!(U) T;
749         static assert(is(V:T),"incompatible a and to type "~U.stringof~" "~V.stringof);
750         static if (is(U S:S[])){
751             static if (is(T==uint) || is(T==int) || is(T==char) || is(T==byte) || is(T==ubyte)){
752                 uint d=uint.max/cast(uint)to,dTo=(cast(uint)to)*d;
753                 T* aEnd=a.ptr+a.length;
754                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
755                     uint nV=source.next;
756                     if (nV<dTo){
757                         *aPtr=cast(T)(nV % cast(uint)to);
758                     } else {
759                         for (int i=0;i<1000;++i) {
760                             nV=source.next;
761                             if (nV<dTo) break;
762                         }
763                         verify(nV<dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
764                         *aPtr=cast(T)(nV % cast(uint)to);
765                     }
766                 }
767             } else static if (is(T==ulong) || is(T==long)){
768                 ulong d=ulong.max/cast(ulong)to,dTo=(cast(ulong)to)*d;
769                 T* aEnd=a.ptr+a.length;
770                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
771                     ulong nV=source.nextL;
772                     if (nV<dTo){
773                         el=cast(T)(nV % cast(ulong)to);
774                     } else {
775                         for (int i=0;i<1000;++i) {
776                             nV=source.nextL;
777                             if (nV<dTo) break;
778                         }
779                         verify(nV<dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
780                         el=cast(T)(nV% cast(ulong)to);
781                     }
782                 }
783             } else static if (is(T==float) || is(T==double) || is(T==real)){
784                 T* aEnd=a.ptr+a.length;
785                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
786                     *aPtr=uniformR!(T,boundCheck)(cast(T)to);
787                 }
788             } else static assert(0,T.stringof~" unsupported type for uniformR distribution");
789         } else {
790             a=uniformR!(T,boundCheck)(cast(T)to);
791         }
792         return a;
793     }
794 
795     /**************************************************************************
796 
797         Randomizes the given array and returns it (for some types this is
798         potentially more efficient, both from the use of random numbers
799         and speedwise)
800 
801     *************************************************************************/
802 
803     U randomizeUniformR2(U,V,W,bool boundCheck=true)(ref U a,V from, W to)
804     {
805         alias StripAllArrays!(U) T;
806         verify((cast(T)to)>(cast(T)from),"empy range in uniformR2");
807         static if (is(T==int) || is(T==long)){
808             verify(from>T.min/2&&to<T.max/2," from..to range too big");
809         }
810         alias StripAllArrays!(U) T;
811         static assert(is(V:T),"incompatible a and from type "~U.stringof~" "~V.stringof);
812         static assert(is(W:T),"incompatible a and to type "~U.stringof~" "~W.stringof);
813         static if (is(U S:S[])){
814             static if (is(T==uint)||is(T==ulong)){
815                 T d=cast(T)to-cast(T)from;
816                 T* aEnd=a.ptr+a.length;
817                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
818                     *aPtr=from+uniformR!(d)();
819                 }
820             } else if (is(T==char) || is(T==byte) || is(T==ubyte)){
821                 int d=cast(int)to-cast(int)from;
822                 T* aEnd=a.ptr+a.length;
823                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
824                     *aPtr=cast(T)(uniformR!(d)+cast(int)from);
825                 }
826             } else static if (is(T==float) || is(T==double) || is(T==real)){
827                 T* aEnd=a.ptr+a.length;
828                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
829                     T res=cast(T)from+(cast(T)to-cast(T)from)*uniform!(T,false);
830                     static if (boundCheck){
831                         if (res!=cast(T)from && res!=cast(T)to){
832                             *aPtr=res;
833                         } else {
834                             *aPtr=uniformR2!(T,boundCheck)(cast(T)from,cast(T)to);
835                         }
836                     } else {
837                         *aPtr=res;
838                     }
839                 }
840             } else static assert(0,T.stringof~" unsupported type for uniformR2 distribution");
841         } else {
842             a=uniformR2!(T,boundCheck)(from,to);
843         }
844         return a;
845     }
846     /// randomizes the given variable like uniformRSymm and returns it
847     /// (for some types this is potentially more efficient, both from the use of
848     /// random numbers and speedwise)
849     U randomizeUniformRSymm(U,V,bool boundCheck=true, bool
850             excludeZero=isFloat!(StripAllArrays!(U)))
851         (ref U a,V to)
852     {
853         alias StripAllArrays!(U) T;
854         verify((cast(T)to)>0,"empty range");
855         static assert(is(V:T),"incompatible a and to type "~U.stringof~" "~V.stringof);
856         static if (is(U S:S[])){
857             static if (is(T==int)|| is(T==byte)){
858                 int d=int.max/cast(int)to,dTo=(cast(int)to)*d;
859                 T* aEnd=a.ptr+a.length;
860                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
861                     int nV=cast(int)source.next;
862                     static if (excludeZero){
863                         int isIn=nV<dTo&&nV>-dTo&&nV!=0;
864                     } else {
865                         int isIn=nV<dTo&&nV>-dTo;
866                     }
867                     if (isIn){
868                         *aPtr=cast(T)(nV% cast(int)to);
869                     } else {
870                         for (int i=0;i<1000;++i) {
871                             nV=cast(int)source.next;
872                             if (nV<dTo&&nV>-dTo) break;
873                         }
874                         verify(nV<dTo && nV>-dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
875                         *aPtr=cast(T)(nV% cast(int)to);
876                     }
877                 }
878             } else static if (is(T==long)){
879                 long d=long.max/cast(T)to,dTo=(cast(T)to)*d;
880                 long nV=cast(long)source.nextL;
881                 T* aEnd=a.ptr+a.length;
882                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
883                     static if (excludeZero){
884                         int isIn=nV<dTo&&nV>-dTo&&nV!=0;
885                     } else {
886                         int isIn=nV<dTo&&nV>-dTo;
887                     }
888                     if (isIn){
889                         *aPtr=nV% cast(T)to;
890                     } else {
891                         for (int i=0;i<1000;++i) {
892                             nV=source.nextL;
893                             if (nV<dTo && nV>-dTo) break;
894                         }
895                         verify(nV<dTo && nV>-dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
896                         *aPtr=nV% cast(T)to;
897                     }
898                 }
899             } else static if (is(T==float)||is(T==double)||is(T==real)){
900                 T* aEnd=a.ptr+a.length;
901                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
902                     *aPtr=uniformRSymm!(T,boundCheck,excludeZero)(cast(T)to);
903                 }
904             } else static assert(0,T.stringof~" unsupported type for uniformRSymm distribution");
905         } else {
906             a=uniformRSymm!(T,boundCheck,excludeZero)(cast(T)to);
907         }
908         return a;
909     }
910 
911     /// returns another (mostly indipendent, depending on seed size) random generator
912     RandG spawn(RandG=RandomG)(){
913         RandG res=new RandG(false);
914         res.seed(&uniform!(uint));
915         return res;
916     }
917 
918     // ------- structs for uniform distributions -----
919     /// uniform distribution on the whole range for integers, and on (0;1) for floats
920     /// with boundCheck=true this is equivalent to r itself, here just for completness
921     struct UniformDistribution(T,bool boundCheck){
922         RandomG r;
923         static UniformDistribution create(RandomG r){
924             UniformDistribution res;
925             res.r=r;
926             return res;
927         }
928         /// chainable call style initialization of variables (thorugh a call to randomize)
929         UniformDistribution opCall(U,S...)(ref U a,S args){
930             randomize(a,args);
931             return this;
932         }
933         /// returns a random number
934         T getRandom(){
935             return r.uniform!(T,boundCheck)();
936         }
937         /// initialize el
938         U randomize(U)(ref U a){
939             return r.randomizeUniform!(U,boundCheck)(a);
940         }
941     }
942 
943     /// uniform distribution on the subrange [0;to$(RPAREN) for integers, (0;to) for floats
944     struct UniformRDistribution(T,bool boundCheck){
945         T to;
946         RandomG r;
947         /// initializes the probability distribution
948         static UniformRDistribution create(RandomG r,T to){
949             UniformRDistribution res;
950             res.r=r;
951             res.to=to;
952             return res;
953         }
954         /// chainable call style initialization of variables (thorugh a call to randomize)
955         UniformRDistribution opCall(U)(ref U a){
956             randomize(a);
957             return this;
958         }
959         /// returns a random number
960         T getRandom(){
961             return r.uniformR!(T,boundCheck)(to);
962         }
963         /// initialize el
964         U randomize(U)(ref U a){
965             return r.randomizeUniformR!(U,T,boundCheck)(a,to);
966         }
967     }
968 
969     /// uniform distribution on the subrange (-to;to) for integers, (-to;0)u(0;to) for floats
970     /// excludeZero controls if the zero should be excluded, boundCheck if the boundary should
971     /// be excluded for floats
972     struct UniformRSymmDistribution(T,bool boundCheck=true,bool excludeZero=isFloat!(T)){
973         T to;
974         RandomG r;
975         /// initializes the probability distribution
976         static UniformRSymmDistribution create(RandomG r,T to){
977             UniformRSymmDistribution res;
978             res.r=r;
979             res.to=to;
980             return res;
981         }
982         /// chainable call style initialization of variables (thorugh a call to randomize)
983         UniformRSymmDistribution opCall(U)(ref U a){
984             randomize(a);
985             return this;
986         }
987         /// returns a random number
988         T getRandom(){
989             return r.uniformRSymm!(T,boundCheck,excludeZero)(to);
990         }
991         /// initialize el
992         U randomize(U)(ref U a){
993             return r.randomizeUniformRSymm!(U,T,boundCheck)(a,to);
994         }
995     }
996 
997     /// uniform distribution on the subrange (-to;to) for integers, (0;to) for floats
998     struct UniformR2Distribution(T,bool boundCheck){
999         T from,to;
1000         RandomG r;
1001         /// initializes the probability distribution
1002         static UniformR2Distribution create(RandomG r,T from, T to){
1003             UniformR2Distribution res;
1004             res.r=r;
1005             res.from=from;
1006             res.to=to;
1007             return res;
1008         }
1009         /// chainable call style initialization of variables (thorugh a call to randomize)
1010         UniformR2Distribution opCall(U,S...)(ref U a,S args){
1011             randomize(a,args);
1012             return this;
1013         }
1014         /// returns a random number
1015         T getRandom(){
1016             return r.uniformR2!(T,boundCheck)(from,to);
1017         }
1018         /// initialize a
1019         U randomize(U)(ref U a){
1020             return r.randomizeUniformR2!(U,T,T,boundCheck)(a,from,to);
1021         }
1022     }
1023 
1024     // ---------- gamma distribution, move to a separate module? --------
1025     /// gamma distribution f=x^(alpha-1)*exp(-x/theta)/(gamma(alpha)*theta^alpha)
1026     /// alpha has to be bigger than 1, for alpha<1 use gammaD(alpha)=gammaD(alpha+1)*pow(r.uniform!(T),1/alpha)
1027     /// from Marsaglia and Tsang, ACM Transaction on Mathematical Software, Vol. 26, N. 3
1028     /// 2000, p 363-372
1029     struct GammaDistribution(T){
1030         RandomG r;
1031         T alpha;
1032         T theta;
1033         static GammaDistribution create(RandomG r,T alpha=cast(T)1,T theta=cast(T)1){
1034             GammaDistribution res;
1035             res.r=r;
1036             res.alpha=alpha;
1037             res.theta=theta;
1038             verify(alpha>=cast(T)1,"implemented only for alpha>=1");
1039             return res;
1040         }
1041         /// chainable call style initialization of variables (thorugh a call to randomize)
1042         GammaDistribution opCall(U,S...)(ref U a,S args){
1043             randomize(a,args);
1044             return this;
1045         }
1046         /// returns a single random number
1047         T getRandom(T a=alpha,T t=theta)
1048         {
1049             verify(a>=cast(T)1,"implemented only for alpha>=1");
1050             T d=a-(cast(T)1)/(cast(T)3);
1051             T c=(cast(T)1)/sqrt(d*cast(T)9);
1052             auto n=r.normalSource!(T)();
1053             for (;;) {
1054                 do {
1055                     T x=n.getRandom();
1056                     T v=c*x+cast(T)1;
1057                     v=v*v*v; // might underflow (in extreme situations) so it is in the loop
1058                 } while (v<=0);
1059                 T u=r.uniform!(T)();
1060                 if (u<1-(cast(T)0.331)*(x*x)*(x*x)) return t*d*v;
1061                 if (log(u)< x*x/2+d*(1-v+log(v))) return t*d*v;
1062             }
1063         }
1064         /// initializes b with gamma distribued random numbers
1065         U randomize(U)(ref U b,T a=alpha,T t=theta){
1066             static if (is(U S:S[])) {
1067                 alias StripAllArrays!(U) T;
1068                 T* bEnd=b.ptr+b.length;
1069                 for (T* bPtr=b.ptr;bPtr!=bEnd;++bPtr){
1070                     *bPtr=cast(StripAllArrays!(U)) getRandom(a,t);
1071                 }
1072             } else {
1073                 b=cast(U) getRandom(a,t);
1074             }
1075             return b;
1076         }
1077         /// maps op on random numbers (of type T) and initializes b with it
1078         U randomizeOp(U,S)(scope S delegate(T)op, ref U b,T a=alpha, T t=theta){
1079             static if(is(U S:S[])){
1080                 alias StripAllArrays!(U) T;
1081                 T* bEnd=b.ptr+b.length;
1082                 for (T* bPtr=b.ptr;bPtr!=bEnd;++bPtr){
1083                     *bPtr=cast(StripAllArrays!(U))op(getRandom(a,t));
1084                 }
1085             } else {
1086                 b=cast(U)op(getRandom(a));
1087             }
1088             return b;
1089         }
1090     }
1091 
1092     //-------- various distributions available -----------
1093 
1094     /// generators of normal numbers (sigma=1,mu=0) of the given type
1095     /// f=exp(-x*x/(2*sigma^2))/(sqrt(2 pi)*sigma)
1096     NormalSource!(RandomG,T) normalSource(T)(){
1097         static if(is(T==float)){
1098             if (!normalFloat) normalFloat=new NormalSource!(RandomG,T)(this);
1099             return normalFloat;
1100         } else static if (is(T==double)){
1101             if (!normalDouble) normalDouble=new NormalSource!(RandomG,T)(this);
1102             return normalDouble;
1103         } else static if (is(T==real)){
1104             if (!normalReal) normalReal=new NormalSource!(RandomG,T)(this);
1105             return normalReal;
1106         } else static assert(0,T.stringof~" no normal source implemented");
1107     }
1108 
1109     /// generators of exp distribued numbers (beta=1) of the given type
1110     /// f=1/beta*exp(-x/beta)
1111     ExpSource!(RandomG,T) expSource(T)(){
1112         static if(is(T==float)){
1113             if (!expFloat) expFloat=new ExpSource!(RandomG,T)(this);
1114             return expFloat;
1115         } else static if (is(T==double)){
1116             if (!expDouble) expDouble=new ExpSource!(RandomG,T)(this);
1117             return expDouble;
1118         } else static if (is(T==real)){
1119             if (!expReal) expReal=new ExpSource!(RandomG,T)(this);
1120             return expReal;
1121         } else static assert(0,T.stringof~" no exp source implemented");
1122     }
1123 
1124     /// generators of normal numbers with a different default sigma/mu
1125     /// f=exp(-x*x/(2*sigma^2))/(sqrt(2 pi)*sigma)
1126     NormalSource!(RandomG,T).NormalDistribution normalD(T)(T sigma=cast(T)1,T mu=cast(T)0){
1127         return normalSource!(T).normalD(sigma,mu);
1128     }
1129     /// exponential distribued numbers with a different default beta
1130     /// f=1/beta*exp(-x/beta)
1131     ExpSource!(RandomG,T).ExpDistribution expD(T)(T beta){
1132         return expSource!(T).expD(beta);
1133     }
1134     /// gamma distribued numbers with the given default alpha
1135     GammaDistribution!(T) gammaD(T)(T alpha=cast(T)1,T theta=cast(T)1){
1136         return GammaDistribution!(T).create(this,alpha,theta);
1137     }
1138 
1139     /// uniform distribution on the whole integer range, and on (0;1) for floats
1140     /// should return simply this??
1141     UniformDistribution!(T,true) uniformD(T)(){
1142         return UniformDistribution!(T,true).create(this);
1143     }
1144     /// uniform distribution on the whole integer range, and on [0;1] for floats
1145     UniformDistribution!(T,false) uniformBoundsD(T)(){
1146         return UniformDistribution!(T,false).create(this);
1147     }
1148     /// uniform distribution [0;to$(RPAREN) for ints, (0:to) for reals
1149     UniformRDistribution!(T,true) uniformRD(T)(T to){
1150         return UniformRDistribution!(T,true).create(this,to);
1151     }
1152     /// uniform distribution [0;to$(RPAREN) for ints, [0:to] for reals
1153     UniformRDistribution!(T,false) uniformRBoundsD(T)(T to){
1154         return UniformRDistribution!(T,false).create(this,to);
1155     }
1156     /// uniform distribution (-to;to) for ints and (-to;0)u(0;to) for reals
1157     UniformRSymmDistribution!(T,true,isFloat!(T)) uniformRSymmD(T)(T to){
1158         return UniformRSymmDistribution!(T,true,isFloat!(T)).create(this,to);
1159     }
1160     /// uniform distribution (-to;to) for ints and [-to;0$(RPAREN)u$(LPAREN)0;to] for reals
1161     UniformRSymmDistribution!(T,false,isFloat!(T)) uniformRSymmBoundsD(T)(T to){
1162         return UniformRSymmDistribution!(T,false,isFloat!(T)).create(this,to);
1163     }
1164     /// uniform distribution [from;to$(RPAREN) for ints and (from;to) for reals
1165     UniformR2Distribution!(T,true) uniformR2D(T)(T from, T to){
1166         return UniformR2Distribution!(T,true).create(this,from,to);
1167     }
1168     /// uniform distribution [from;to$(RPAREN) for ints and [from;to] for reals
1169     UniformR2Distribution!(T,false) uniformR2BoundsD(T)(T from, T to){
1170         return UniformR2Distribution!(T,false).create(this,from,to);
1171     }
1172 
1173     // -------- Utility functions for other distributions -------
1174     // add also the corresponding randomize functions?
1175 
1176     /// returns a normal distribued number
1177     T normal(T)(){
1178         return normalSource!(T).getRandom();
1179     }
1180     /// returns a normal distribued number with the given sigma
1181     T normalSigma(T)(T sigma){
1182         return normalSource!(T).getRandom(sigma);
1183     }
1184     /// returns a normal distribued number with the given sigma and mu
1185     T normalSigmaMu(T)(T sigma,T mu){
1186         return normalSource!(T).getRandom(sigma,mu);
1187     }
1188 
1189     /// returns an exp distribued number
1190     T exp(T)(){
1191         return expSource!(T).getRandom();
1192     }
1193     /// returns an exp distribued number with the given scale beta
1194     T expBeta(T)(T beta){
1195         return expSource!(T).getRandom(beta);
1196     }
1197 
1198     /// returns a gamma distribued number
1199     /// from Marsaglia and Tsang, ACM Transaction on Mathematical Software, Vol. 26, N. 3
1200     /// 2000, p 363-372
1201     T gamma(T)(T alpha=cast(T)1,T sigma=cast(T)1)
1202     {
1203         verify(alpha>=cast(T)1,"implemented only for alpha>=1");
1204         auto n=normalSource!(T);
1205         T d=alpha-(cast(T)1)/(cast(T)3);
1206         T c=(cast(T)1)/sqrt(d*cast(T)9);
1207         for (;;) {
1208             T x,v;
1209             do {
1210                 x=n.getRandom();
1211                 v=c*x+cast(T)1;
1212                 v=v*v*v; // might underflow (in extreme situations) so it is in the loop
1213             } while (v<=0);
1214             T u=uniform!(T)();
1215             if (u<1-(cast(T)0.331)*(x*x)*(x*x)) return sigma*d*v;
1216             if (log(u)< x*x/2+d*(1-v+log(v))) return sigma*d*v;
1217         }
1218     }
1219     // ---------------
1220 
1221     /// writes the current status in a string
1222     override istring toString(){
1223         return source.toString();
1224     }
1225     /// reads the current status from a string (that should have been trimmed)
1226     /// returns the number of chars read
1227     size_t fromString(cstring s){
1228         return source.fromString(s);
1229     }
1230 
1231     // make this by default a uniformRandom number generator
1232     /// chainable call style initialization of variables (thorugh a call to randomize)
1233     RandomG opCall(U)(ref U a){
1234         randomize(a);
1235         return this;
1236     }
1237     /// returns a random number
1238     T getRandom(T)(){
1239         return uniform!(T,true)();
1240     }
1241     /// initialize el
1242     U randomize(U)(ref U a){
1243         return randomizeUniform!(U,true)(a);
1244     }
1245 
1246 } // end class RandomG
1247 
1248 /// make the default random number generator type
1249 /// (a non threadsafe random number generator) easily available
1250 /// you can safely expect a new instance of this to be indipendent from all the others
1251 alias RandomG!() Random;
1252 /// default threadsafe random number generator type
1253 alias RandomG!(DefaultEngine) RandomSync;
1254 
1255 /// shared locked (threadsafe) random number generator
1256 /// initialized with urandom if available, with time otherwise
1257 static RandomSync rand;
1258 static this ()
1259 {
1260     rand = new RandomSync(false);
1261 
1262     static void set_array_source(ulong s)
1263     {
1264         uint[2] a;
1265         a[0]= cast(uint)(s & 0xFFFF_FFFFUL);
1266         a[1]= cast(uint)(s>>32);
1267         rand.seed(&(ArraySource(a).next));
1268     }
1269 
1270     version (unittest){
1271         set_array_source(9); // http://dilbert.com/strip/2001-10-25
1272     } else {
1273         URandom r;
1274         rand.seed(&r.next);
1275     }
1276 }
1277 
1278 version (unittest)
1279 {
1280     import ocean.math.random.engines.KISS;
1281     import ocean.math.random.engines.CMWC;
1282     import core.stdc.stdio:printf;
1283     import ocean.core.Test;
1284 
1285     /// very simple statistal test, mean within maxOffset, and maximum/minimum at least minmax/maxmin
1286     bool checkMean(T)(T[] a, real maxmin, real minmax, real expectedMean, real maxOffset,bool alwaysPrint=false,bool checkB=false){
1287         T minV,maxV;
1288         real meanV=0.0L;
1289         if (a.length>0){
1290             minV=a[0];
1291             maxV=a[0];
1292             foreach (el;a){
1293                 test(!checkB || (cast(T)0<el && el<cast(T)1),"el out of bounds");
1294                 if (el<minV) minV=el;
1295                 if (el>maxV) maxV=el;
1296                 meanV+=cast(real)el;
1297             }
1298             meanV/=cast(real)a.length;
1299             bool printM=false;
1300             if (cast(real)minV>maxmin) printM=true;
1301             if (cast(real)maxV<minmax) printM=true;
1302             if (expectedMean-maxOffset>meanV || meanV>expectedMean+maxOffset) printM=true;
1303             if (printM){
1304                 printf("WARNING ocean.math.Random statistic is strange: %.*s[%d] %Lg %Lg %Lg\n\0",
1305                     cast(int)T.stringof.length, T.stringof.ptr, cast(int)a.length,
1306                     cast(real)minV,meanV,cast(real)maxV);
1307             } else if (alwaysPrint) {
1308                 printf("ocean.math.Random statistic: %.*s[%d] %Lg %Lg %Lg\n\0",
1309                     cast(int)T.stringof.length, T.stringof.ptr, cast(int)a.length,
1310                     cast(real)minV,meanV,cast(real)maxV);
1311             }
1312             return printM;
1313         }
1314         return false;
1315     }
1316 
1317     /// check a given generator both on the whole array, and on each element separately
1318     bool doTests(RandG,Arrays...)(RandG r,real maxmin, real minmax, real expectedMean, real maxOffset,bool alwaysPrint,bool checkB, Arrays arrs){
1319         bool gFail=false;
1320         foreach (i,TA;Arrays){
1321             alias StripAllArrays!(TA) T;
1322             // all together
1323             r(arrs[i]);
1324             bool fail=checkMean!(T)(arrs[i],maxmin,minmax,expectedMean,maxOffset,alwaysPrint,checkB);
1325             // one by one
1326             foreach (ref el;arrs[i]){
1327                 r(el);
1328             }
1329             fail |= checkMean!(T)(arrs[i],maxmin,minmax,expectedMean,maxOffset,alwaysPrint,checkB);
1330             gFail |= fail;
1331         }
1332         return gFail;
1333     }
1334 
1335     void testRandSource(RandS)(){
1336         auto r=new RandomG!(RandS)();
1337         // r.fromString("KISS99_b66dda10_49340130_8f3bf553_224b7afa_00000000_00000000"); // to reproduce a given test...
1338         auto initialState=r.toString(); // so that you can reproduce things...
1339         bool allStats=false; // set this to true to show all statistics (helpful to track an error)
1340         try{
1341             r.uniform!(uint);
1342             r.uniform!(ubyte);
1343             r.uniform!(ulong);
1344             int count=10_000;
1345             for (int i=count;i!=0;--i){
1346                 float f=r.uniform!(float);
1347                 test(0<f && f<1,"float out of bounds");
1348                 double d=r.uniform!(double);
1349                 test(0<d && d<1,"double out of bounds");
1350                 real rr=r.uniform!(real);
1351                 test(0<rr && rr<1,"double out of bounds");
1352             }
1353             // checkpoint status (str)
1354             auto status=r.toString();
1355             uint tVal=r.uniform!(uint);
1356             ubyte t2Val=r.uniform!(ubyte);
1357             ulong t3Val=r.uniform!(ulong);
1358 
1359             byte[1000]  barr;
1360             ubyte[1000] ubarr;
1361             uint[1000]  uiarr;
1362             int[1000]   iarr;
1363             float[1000] farr;
1364             double[1000]darr;
1365             real[1000]  rarr;
1366             byte[]  barr2=barr[];
1367             ubyte[] ubarr2=ubarr[];
1368             uint[]  uiarr2=uiarr[];
1369             int[]   iarr2=iarr[];
1370             float[] farr2=farr[];
1371             double[]darr2=darr[];
1372             real[]  rarr2=rarr[];
1373 
1374             bool fail=false,gFail=false;
1375             fail =doTests(r,-100.0L,100.0L,0.0L,20.0L,allStats,false,barr2);
1376             fail|=doTests(r,100.0L,155.0L,127.5L,20.0L,allStats,false,ubarr2);
1377             fail|=doTests(r,0.25L*cast(real)(uint.max),0.75L*cast(real)uint.max,
1378                 0.5L*uint.max,0.2L*uint.max,allStats,false,uiarr2);
1379             fail|=doTests(r,0.5L*cast(real)int.min,0.5L*cast(real)int.max,
1380                 0.0L,0.2L*uint.max,allStats,false,iarr2);
1381             fail|=doTests(r,0.2L,0.8L,0.5L,0.2L,allStats,true,farr2,darr2,rarr2);
1382             gFail|=fail;
1383 
1384             fail =doTests(r.uniformD!(int)(),-100.0L,100.0L,0.0L,20.0L,allStats,false,barr2);
1385             fail|=doTests(r.uniformD!(int)(),100.0L,155.0L,127.5L,20.0L,allStats,false,ubarr2);
1386             fail|=doTests(r.uniformD!(int)(),0.25L*cast(real)(uint.max),0.75L*cast(real)uint.max,
1387                 0.5L*uint.max,0.2L*uint.max,allStats,false,uiarr2);
1388             fail|=doTests(r.uniformD!(real)(),0.5L*cast(real)int.min,0.5L*cast(real)int.max,
1389                 0.0L,0.2L*uint.max,allStats,false,iarr2);
1390             fail|=doTests(r.uniformD!(real)(),0.2L,0.8L,0.5L,0.2L,allStats,true,farr2,darr2,rarr2);
1391             gFail|=fail;
1392 
1393             fail =doTests(r.uniformBoundsD!(int)(),-100.0L,100.0L,0.0L,20.0L,allStats,false,barr2);
1394             fail|=doTests(r.uniformBoundsD!(int)(),100.0L,155.0L,127.5L,20.0L,allStats,false,ubarr2);
1395             fail|=doTests(r.uniformBoundsD!(int)(),0.25L*cast(real)(uint.max),0.75L*cast(real)uint.max,
1396                 0.5L*uint.max,0.2L*uint.max,allStats,false,uiarr2);
1397             fail|=doTests(r.uniformBoundsD!(int)(),0.5L*cast(real)int.min,0.5L*cast(real)int.max,
1398                 0.0L,0.2L*uint.max,allStats,false,iarr2);
1399             fail|=doTests(r.uniformBoundsD!(int)(),0.2L,0.8L,0.5L,0.2L,allStats,false,farr2,darr2,rarr2);
1400             gFail|=fail;
1401 
1402             fail =doTests(r.uniformRD(cast(byte)101),25.0L,75.0L,50.0L,15.0L,allStats,false,barr2);
1403             fail|=doTests(r.uniformRD(cast(ubyte)201),50.0L,150.0L,100.0L,20.0L,allStats,false,ubarr2);
1404             fail|=doTests(r.uniformRD(1001u),250.0L,750.0L,500.0L,100.0L,allStats,false,uiarr2);
1405             fail|=doTests(r.uniformRD(1001 ),250.0L,750.0L,500.0L,100.0L,allStats,false,iarr2);
1406             fail|=doTests(r.uniformRD(1000.0L),250.0L,750.0L,500.0L,100.0L,
1407                 allStats,false,farr2,darr2,rarr2);
1408             fail|=doTests(r.uniformRD(1.0L),0.2L,0.8L,0.5L,0.2L,allStats,true,farr2,darr2,rarr2);
1409             gFail|=fail;
1410 
1411             fail =doTests(r.uniformRBoundsD(cast(byte)101),25.0L,75.0L,50.0L,15.0L,allStats,false,barr2);
1412             fail|=doTests(r.uniformRBoundsD(cast(ubyte)201),50.0L,150.0L,100.0L,20.0L,allStats,false,ubarr2);
1413             fail|=doTests(r.uniformRBoundsD(1001u),250.0L,750.0L,500.0L,100.0L,allStats,false,uiarr2);
1414             fail|=doTests(r.uniformRBoundsD(1001 ),250.0L,750.0L,500.0L,100.0L,allStats,false,iarr2);
1415             fail|=doTests(r.uniformRBoundsD(1000.0L),250.0L,750.0L,500.0L,100.0L,
1416                 allStats,false,farr2,darr2,rarr2);
1417             gFail|=fail;
1418 
1419             fail =doTests(r.uniformRSymmD!(byte)(cast(byte)100),
1420                 -40.0L,40.0L,0.0L,30.0L,allStats,false,barr2);
1421             fail|=doTests(r.uniformRSymmD!(int)(1000),
1422                 -300.0L,300.0L,0.0L,200.0L,allStats,false,iarr2);
1423             fail|=doTests(r.uniformRSymmD!(real)(1.0L),
1424                 -0.3L,0.3L,0.0L,0.3L,allStats,false,farr2,darr2,rarr2);
1425             gFail|=fail;
1426 
1427             fail =doTests(r.uniformRSymmBoundsD!(byte)(cast(byte)100),
1428                 -40.0L,40.0L,0.0L,30.0L,allStats,false,barr2);
1429             fail|=doTests(r.uniformRSymmBoundsD!(int)(1000),
1430                 -300.0L,300.0L,0.0L,200.0L,allStats,false,iarr2);
1431             fail|=doTests(r.uniformRSymmBoundsD!(real)(1.0L),
1432                 -0.3L,0.3L,0.0L,0.3L,allStats,false,farr2,darr2,rarr2);
1433             gFail|=fail;
1434 
1435             fail =doTests(r.normalSource!(float)(),-0.5L,0.5L,0.0L,1.0L,
1436                 allStats,false,farr2,darr2,rarr2);
1437             fail|=doTests(r.normalSource!(double)(),-0.5L,0.5L,0.0L,1.0L,
1438                 allStats,false,farr2,darr2,rarr2);
1439             fail|=doTests(r.normalSource!(real)(),-0.5L,0.5L,0.0L,1.0L,
1440                 allStats,false,farr2,darr2,rarr2);
1441             fail|=doTests(r.normalD!(real)(0.5L,5.0L),4.5L,5.5L,5.0L,0.5L,
1442                 allStats,false,farr2,darr2,rarr2);
1443             gFail|=fail;
1444 
1445             fail =doTests(r.expSource!(float)(),0.8L,2.0L,1.0L,1.0L,
1446                 allStats,false,farr2,darr2,rarr2);
1447             fail|=doTests(r.expSource!(double)(),0.8L,2.0L,1.0L,1.0L,
1448                 allStats,false,farr2,darr2,rarr2);
1449             fail|=doTests(r.expSource!(real)(),0.8L,2.0L,1.0L,1.0L,
1450                 allStats,false,farr2,darr2,rarr2);
1451             fail|=doTests(r.expD!(real)(5.0L),1.0L,7.0L,5.0L,1.0L,
1452                 allStats,false,farr2,darr2,rarr2);
1453             gFail|=fail;
1454 
1455             uint seed = 0;
1456             r.seed({ return 2*(seed++); });
1457             auto v1 = r.uniform!(int)();
1458 
1459             seed = 0;
1460             r.seed({ return 2*(seed++); });
1461             auto v2 = r.uniform!(int)();
1462 
1463             test!("==")(v1, v2, "Re-seed failure: " ~ RandS.stringof);
1464 
1465             r.fromString(status);
1466             test!("==")(r.uniform!(uint),tVal,"restoring of status from str failed");
1467             test!("==")(r.uniform!(ubyte),t2Val,"restoring of status from str failed");
1468             test!("==")(r.uniform!(ulong),t3Val,"restoring of status from str failed");
1469             test(!gFail,"Random.d failure");
1470         } catch(Exception e) {
1471             throw e;
1472         }
1473     }
1474 }
1475 
1476 unittest {
1477     testRandSource!(Kiss99)();
1478     testRandSource!(CMWC_default)();
1479     testRandSource!(KissCmwc_default)();
1480     testRandSource!(Twister)();
1481     testRandSource!(DefaultEngine)();
1482 }