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