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             // TODO: Remove in v7.0.0
430             return cast(T)(uniform!(realType!(T))()+1i*uniform!(realType!(T))());
431         } else static if (is(T==ifloat)||is(T==idouble)||is(T==ireal)){
432             // TODO: Remove in v7.0.0
433             return cast(T)(1i*uniform!(realType!(T))());
434         } else static assert(0,T.stringof~" unsupported type for uniform distribution");
435     }
436 
437     /// uniform distribution on the range [0;to$(RPAREN) for integer types, and on
438     /// the (0;to) range for floating point types. Same caveat as uniform(T) apply
439     T uniformR(T,bool boundCheck=true)(T to)
440     {
441         verify(to>0,"empty range");
442         static if (is(T==uint) || is(T==int) || is(T==short) || is(T==ushort)
443             || is(T==char) || is(T==byte) || is(T==ubyte))
444         {
445             uint d=uint.max/cast(uint)to,dTo=to*d;
446             uint nV=source.next;
447             if (nV>=dTo){
448                 for (int i=0;i<1000;++i) {
449                     nV=source.next;
450                     if (nV<dTo) break;
451                 }
452                 verify(nV<dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
453             }
454             return cast(T)(nV%to);
455         } else static if (is(T==ulong) || is(T==long)){
456             ulong d=ulong.max/cast(ulong)to,dTo=to*d;
457             ulong nV=source.nextL;
458             if (nV>=dTo){
459                 for (int i=0;i<1000;++i) {
460                     nV=source.nextL;
461                     if (nV<dTo) break;
462                 }
463                 verify(nV<dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
464             }
465             return cast(T)(nV%to);
466         } else static if (is(T==float)|| is(T==double)||is(T==real)){
467             T res=uniform!(T,false)*to;
468             static if (boundCheck){
469                 if (res!=cast(T)0 && res!=to) return res;
470                 return uniformR(to);
471             } else {
472                 return res;
473             }
474         } else static assert(0,T.stringof~" unsupported type for uniformR distribution");
475     }
476     /// uniform distribution on the range (-to;to) for integer types, and on
477     /// the (-to;0)(0;to) range for floating point types if boundCheck is true.
478     /// If boundCheck=false the range changes to [-to;0$(RPAREN)u$(LPAREN)0;to] with a slightly
479     /// lower propability at the bounds for floating point numbers.
480     /// excludeZero controls if 0 is excluded or not (by default float exclude it,
481     /// ints no). Please note that the probability of 0 in floats is very small due
482     //  to the high density of floats close to 0.
483     /// Cannot be used on unsigned types.
484     ///
485     /// In here there is probably one of the few cases where c handling of modulo of negative
486     /// numbers is handy
487     T uniformRSymm(T,bool boundCheck=true, bool excludeZero=isFloat!(T))(T to,int iter=2000)
488     {
489         verify(to>0,"empty range");
490         static if (is(T==int)|| is(T==short) || is(T==byte)){
491             int d=int.max/to,dTo=to*d;
492             int nV=cast(int)source.next;
493             static if (excludeZero){
494                 int isIn=nV<dTo&&nV>-dTo&&nV!=0;
495             } else {
496                 int isIn=nV<dTo&&nV>-dTo;
497             }
498             if (isIn){
499                 return cast(T)(nV%to);
500             } else {
501                 for (int i=0;i<1000;++i) {
502                     nV=cast(int)source.next;
503                     if (nV<dTo && nV>-dTo) break;
504                 }
505                 verify(nV<dTo && nV>-dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
506                 return cast(T)(nV%to);
507             }
508         } else static if (is(T==long)){
509             long d=long.max/to,dTo=to*d;
510             long nV=cast(long)source.nextL;
511             static if (excludeZero){
512                 int isIn=nV<dTo&&nV>-dTo&&nV!=0;
513             } else {
514                 int isIn=nV<dTo&&nV>-dTo;
515             }
516             if (isIn){
517                 return nV%to;
518             } else {
519                 for (int i=0;i<1000;++i) {
520                     nV=source.nextL;
521                     if (nV<dTo && nV>-dTo) break;
522                 }
523                 verify(nV<dTo && nV>-dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
524                 return nV%to;
525             }
526         } else static if (is(T==float)||is(T==double)||is(T==real)){
527             static if (T.mant_dig<30){
528                 static immutable T halfT=(cast(T)1)/(cast(T)2);
529                 static immutable T fact32=ctfe_powI(halfT,32);
530                 static immutable uint minV=1u<<T.mant_dig;
531                 uint nV=source.next;
532                 if (nV>=minV) {
533                     T res=nV*fact32*to;
534                     static if (boundCheck){
535                         if (res!=to) return (1-2*cast(int)(nV&1u))*res;
536                         // to due to rounding (~3.e-8), 0 impossible with normal to values
537                         verify(iter>0,"error with the generator, probability < 10^(-8*2000)");
538                         return uniformRSymm(to,iter-1);
539                     } else {
540                         return (1-2*cast(int)(nV&1u))*res;
541                     }
542                 } else { // probability 0.008 for 24 bit mantissa
543                     T scale=fact32;
544                     while (nV==0){ // probability 2.3283064365386963e-10
545                         nV=source.next;
546                         scale*=fact32;
547                     }
548                     uint nV2=source.next;
549                     T res=(cast(T)nV+cast(T)nV2*fact32)*scale*to;
550                     static if (excludeZero){
551                         if (res!=cast(T)0) return (1-2*cast(int)(nV&1u))*res;
552                         verify(iter>0,"error with the generator, probability < 10^(-8*2000)");
553                         return uniformRSymm(to,iter-1); // 0 due to underflow (<1.e-38), 1 impossible
554                     } else {
555                         return (1-2*cast(int)(nV&1u))*res;
556                     }
557                 }
558             } else static if (T.mant_dig<62) {
559                 static immutable T halfT=(cast(T)1)/(cast(T)2);
560                 static immutable T fact64=ctfe_powI(halfT,64);
561                 static immutable ulong minV=1UL<<(T.mant_dig);
562                 ulong nV=source.nextL;
563                 if (nV>=minV) {
564                     T res=nV*fact64*to;
565                     static if (boundCheck){
566                         if (res!=to) return (1-2*cast(int)(nV&1UL))*res;
567                         // to due to rounding (<1.e-16), 0 impossible with normal to values
568                         verify(iter>0,"error with the generator, probability < 10^(-16*2000)");
569                         return uniformRSymm(to,iter-1);
570                     } else {
571                         return (1-2*cast(int)(nV&1UL))*res;
572                     }
573                 } else { // probability 0.00048828125 for 53 bit mantissa
574                     static immutable T fact32=ctfe_powI(halfT,32);
575                     static immutable ulong minV2=1UL<<(T.mant_dig-32);
576                     if (nV>=minV2){
577                         uint nV2=source.next;
578                         T res=((cast(T)nV)+(cast(T)nV2)*fact32)*fact64*to;
579                         return (1-2*cast(int)(nV2&1UL))*res; // cannot be 0 or to with normal to values
580                     } else { // probability 1.1368683772161603e-13 for 53 bit mantissa
581                         T scale=fact64;
582                         while (nV==0){
583                             nV=source.nextL;
584                             scale*=fact64;
585                         }
586                         ulong nV2=source.nextL;
587                         T res=to*scale*((cast(T)nV)+(cast(T)nV2)*fact64);
588                         static if (excludeZero){
589                             if (res!=cast(T)0) return (1-2*cast(int)(nV2&1UL))*res;
590                             // 0 due to underflow (<1.e-307)
591                             verify(iter>0,"error with the generator, probability < 10^(-16*2000)");
592                             return uniformRSymm(to,iter-1);
593                         } else {
594                             return (1-2*cast(int)(nV2&1UL))*res;
595                         }
596                     }
597                 }
598             } else static if (T.mant_dig<=64) {
599                 static immutable T halfT=(cast(T)1)/(cast(T)2);
600                 static immutable T fact8=ctfe_powI(halfT,8);
601                 static immutable T fact72=ctfe_powI(halfT,72);
602                 ubyte nB=source.nextB;
603                 if (nB!=0){
604                     ulong nL=source.nextL;
605                     T res=to*(nB*fact8+nL*fact72);
606                     static if (boundCheck){
607                         if (res!=to) return (1-2*cast(int)(nL&1UL))*res;
608                         // 1 due to rounding (<1.e-16), 0 impossible with normal to values
609                         verify(iter>0,"error with the generator, probability < 10^(-16*2000)");
610                         return uniformRSymm(to,iter-1);
611                     } else {
612                         return (1-2*cast(int)(nL&1UL))*res;
613                     }
614                 } else { // probability 0.00390625
615                     static immutable T fact64=ctfe_powI(halfT,64);
616                     T scale=fact8;
617                     while (nB==0){
618                         nB=source.nextB;
619                         scale*=fact8;
620                     }
621                     ulong nL=source.nextL;
622                     T res=((cast(T)nB)+(cast(T)nL)*fact64)*scale*to;
623                     static if (excludeZero){
624                         if (res!=cast(T)0) return ((nL&1UL)?res:-res);
625                         // 0 due to underflow (<1.e-4932), 1 impossible
626                         verify(iter>0,"error with the generator, probability < 10^(-16*2000)");
627                         return uniformRSymm(to,iter-1);
628                     } else {
629                         return ((nL&1UL)?res:-res);
630                     }
631                 }
632             } else {
633                 // (T.mant_dig > 64 bits), not so optimized, but works for any size
634                 static immutable T halfT=(cast(T)1)/(cast(T)2);
635                 static immutable T fact32=ctfe_powI(halfT,32);
636                 uint nL=source.next;
637                 T fact=fact32;
638                 while (nL==0){
639                     fact*=fact32;
640                     nL=source.next;
641                 }
642                 T res=nL*fact;
643                 for (int rBits=T.mant_dig;rBits>0;rBits-=32) {
644                     fact*=fact32;
645                     nL=source.next();
646                     res+=nL*fact;
647                 }
648                 static if (boundCheck){
649                     if (res!=to && res!=cast(T)0) return ((nL&1UL)?res:-res);
650                     // 1 due to rounding (<1.e-16), 0 impossible with normal to values
651                     verify(iter>0,"error with the generator, probability < 10^(-16*2000)");
652                     return uniformRSymm(to,iter-1);
653                 } else {
654                     return ((nL&1UL)?res:-res);
655                 }
656             }
657         } else static assert(0,T.stringof~" unsupported type for uniformRSymm distribution");
658     }
659     /// uniform distribution [from;to$(RPAREN) for integers, and (from;) for floating point numbers.
660     /// if boundCheck is false the bounds are included in the floating point number distribution.
661     /// the range for int and long is limited to only half the possible range
662     /// (it could be worked around using long aritmethic for int, and doing a carry by hand for long,
663     /// but I think it is seldomly needed, for int you are better off using long when needed)
664     T uniformR2(T,bool boundCheck=true)(T from,T to)
665     {
666         verify(to>from,"empy range in uniformR2");
667         static if (is(T==int) || is(T==long)){
668             verify(from>T.min/2&&to<T.max/2," from..to range too big");
669         }
670         static if (is(T==int)||is(T==long)||is(T==uint)||is(T==ulong)){
671             return from+uniformR(to-from);
672         } else static if (is(T==char) || is(T==byte) || is(T==ubyte) || is(T==short) || is(T==ushort)){
673             int d=cast(int)to-cast(int)from;
674             int nV=uniformR!(int)(d);
675             return cast(T)(nV+cast(int)from);
676         } else static if (is(T==float) || is(T==double) || is(T==real)){
677             T res=from+(to-from)*uniform!(T,false);
678             static if (boundCheck){
679                 if (res!=from && res!=to) return res;
680                 return uniformR2(from,to);
681             } else {
682                 return res;
683             }
684         } else static assert(0,T.stringof~" unsupported type for uniformR2 distribution");
685     }
686     /// returns a random element of the given array (which must be non empty)
687     T uniformEl(T)(T[] arr){
688         verify(arr.length>0,"array has to be non empty");
689         return arr[uniformR(arr.length)];
690     }
691 
692     /**************************************************************************
693 
694         Randomizes the given array and returns it (for some types this is
695         potentially more efficient, both from the use of random numbers
696         and speedwise)
697 
698     *************************************************************************/
699 
700     U randomizeUniform(U,bool boundCheck)(ref U a){
701         static if (is(U S:S[])){
702             alias StripAllArrays!(U) T;
703             static if (is(T==byte)||is(T==ubyte)||is(T==char)){
704                 uint val=source.next; /// begin without value?
705                 int rest=4;
706                 for (size_t i=0;i<a.length;++i) {
707                     if (rest!=0){
708                         a[i]=cast(T)(0xFFu&val);
709                         val>>=8;
710                         --rest;
711                     } else {
712                         val=source.next;
713                         a[i]=cast(T)(0xFFu&val);
714                         val>>=8;
715                         rest=3;
716                     }
717                 }
718             } else static if (is(T==uint)||is(T==int)){
719                 T* aEnd=a.ptr+a.length;
720                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr)
721                     *aPtr=cast(T)(source.next);
722             } else static if (is(T==ulong)||is(T==long)){
723                 T* aEnd=a.ptr+a.length;
724                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr)
725                     *aPtr=cast(T)(source.nextL);
726             } else static if (is(T==float)|| is(T==double)|| is(T==real)) {
727                 // optimize more? not so easy with guaranteed full mantissa initialization
728                 T* aEnd=a.ptr+a.length;
729                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
730                     *aPtr=uniform!(T,boundCheck)();
731                 }
732             } else static assert(T.stringof~" type not supported by randomizeUniform");
733         } else {
734             a=uniform!(U,boundCheck)();
735         }
736         return a;
737     }
738 
739     /**************************************************************************
740 
741         Randomizes the given array and returns it (for some types this is
742         potentially more efficient, both from the use of random numbers
743         and speedwise)
744 
745     *************************************************************************/
746 
747     U randomizeUniformR(U,V,bool boundCheck=true)(ref U a,V to)
748     {
749         verify((cast(StripAllArrays!(U))to)>0,"empty range");
750         alias StripAllArrays!(U) T;
751         static assert(is(V:T),"incompatible a and to type "~U.stringof~" "~V.stringof);
752         static if (is(U S:S[])){
753             static if (is(T==uint) || is(T==int) || is(T==char) || is(T==byte) || is(T==ubyte)){
754                 uint d=uint.max/cast(uint)to,dTo=(cast(uint)to)*d;
755                 T* aEnd=a.ptr+a.length;
756                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
757                     uint nV=source.next;
758                     if (nV<dTo){
759                         *aPtr=cast(T)(nV % cast(uint)to);
760                     } else {
761                         for (int i=0;i<1000;++i) {
762                             nV=source.next;
763                             if (nV<dTo) break;
764                         }
765                         verify(nV<dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
766                         *aPtr=cast(T)(nV % cast(uint)to);
767                     }
768                 }
769             } else static if (is(T==ulong) || is(T==long)){
770                 ulong d=ulong.max/cast(ulong)to,dTo=(cast(ulong)to)*d;
771                 T* aEnd=a.ptr+a.length;
772                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
773                     ulong nV=source.nextL;
774                     if (nV<dTo){
775                         el=cast(T)(nV % cast(ulong)to);
776                     } else {
777                         for (int i=0;i<1000;++i) {
778                             nV=source.nextL;
779                             if (nV<dTo) break;
780                         }
781                         verify(nV<dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
782                         el=cast(T)(nV% cast(ulong)to);
783                     }
784                 }
785             } else static if (is(T==float) || is(T==double) || is(T==real)){
786                 T* aEnd=a.ptr+a.length;
787                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
788                     *aPtr=uniformR!(T,boundCheck)(cast(T)to);
789                 }
790             } else static assert(0,T.stringof~" unsupported type for uniformR distribution");
791         } else {
792             a=uniformR!(T,boundCheck)(cast(T)to);
793         }
794         return a;
795     }
796 
797     /**************************************************************************
798 
799         Randomizes the given array and returns it (for some types this is
800         potentially more efficient, both from the use of random numbers
801         and speedwise)
802 
803     *************************************************************************/
804 
805     U randomizeUniformR2(U,V,W,bool boundCheck=true)(ref U a,V from, W to)
806     {
807         alias StripAllArrays!(U) T;
808         verify((cast(T)to)>(cast(T)from),"empy range in uniformR2");
809         static if (is(T==int) || is(T==long)){
810             verify(from>T.min/2&&to<T.max/2," from..to range too big");
811         }
812         alias StripAllArrays!(U) T;
813         static assert(is(V:T),"incompatible a and from type "~U.stringof~" "~V.stringof);
814         static assert(is(W:T),"incompatible a and to type "~U.stringof~" "~W.stringof);
815         static if (is(U S:S[])){
816             static if (is(T==uint)||is(T==ulong)){
817                 T d=cast(T)to-cast(T)from;
818                 T* aEnd=a.ptr+a.length;
819                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
820                     *aPtr=from+uniformR!(d)();
821                 }
822             } else if (is(T==char) || is(T==byte) || is(T==ubyte)){
823                 int d=cast(int)to-cast(int)from;
824                 T* aEnd=a.ptr+a.length;
825                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
826                     *aPtr=cast(T)(uniformR!(d)+cast(int)from);
827                 }
828             } else static if (is(T==float) || is(T==double) || is(T==real)){
829                 T* aEnd=a.ptr+a.length;
830                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
831                     T res=cast(T)from+(cast(T)to-cast(T)from)*uniform!(T,false);
832                     static if (boundCheck){
833                         if (res!=cast(T)from && res!=cast(T)to){
834                             *aPtr=res;
835                         } else {
836                             *aPtr=uniformR2!(T,boundCheck)(cast(T)from,cast(T)to);
837                         }
838                     } else {
839                         *aPtr=res;
840                     }
841                 }
842             } else static assert(0,T.stringof~" unsupported type for uniformR2 distribution");
843         } else {
844             a=uniformR2!(T,boundCheck)(from,to);
845         }
846         return a;
847     }
848     /// randomizes the given variable like uniformRSymm and returns it
849     /// (for some types this is potentially more efficient, both from the use of
850     /// random numbers and speedwise)
851     U randomizeUniformRSymm(U,V,bool boundCheck=true, bool
852             excludeZero=isFloat!(StripAllArrays!(U)))
853         (ref U a,V to)
854     {
855         alias StripAllArrays!(U) T;
856         verify((cast(T)to)>0,"empty range");
857         static assert(is(V:T),"incompatible a and to type "~U.stringof~" "~V.stringof);
858         static if (is(U S:S[])){
859             static if (is(T==int)|| is(T==byte)){
860                 int d=int.max/cast(int)to,dTo=(cast(int)to)*d;
861                 T* aEnd=a.ptr+a.length;
862                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
863                     int nV=cast(int)source.next;
864                     static if (excludeZero){
865                         int isIn=nV<dTo&&nV>-dTo&&nV!=0;
866                     } else {
867                         int isIn=nV<dTo&&nV>-dTo;
868                     }
869                     if (isIn){
870                         *aPtr=cast(T)(nV% cast(int)to);
871                     } else {
872                         for (int i=0;i<1000;++i) {
873                             nV=cast(int)source.next;
874                             if (nV<dTo&&nV>-dTo) break;
875                         }
876                         verify(nV<dTo && nV>-dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
877                         *aPtr=cast(T)(nV% cast(int)to);
878                     }
879                 }
880             } else static if (is(T==long)){
881                 long d=long.max/cast(T)to,dTo=(cast(T)to)*d;
882                 long nV=cast(long)source.nextL;
883                 T* aEnd=a.ptr+a.length;
884                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
885                     static if (excludeZero){
886                         int isIn=nV<dTo&&nV>-dTo&&nV!=0;
887                     } else {
888                         int isIn=nV<dTo&&nV>-dTo;
889                     }
890                     if (isIn){
891                         *aPtr=nV% cast(T)to;
892                     } else {
893                         for (int i=0;i<1000;++i) {
894                             nV=source.nextL;
895                             if (nV<dTo && nV>-dTo) break;
896                         }
897                         verify(nV<dTo && nV>-dTo,"this is less probable than 1.e-301, something is wrong with the random number generator");
898                         *aPtr=nV% cast(T)to;
899                     }
900                 }
901             } else static if (is(T==float)||is(T==double)||is(T==real)){
902                 T* aEnd=a.ptr+a.length;
903                 for (T* aPtr=a.ptr;aPtr!=aEnd;++aPtr){
904                     *aPtr=uniformRSymm!(T,boundCheck,excludeZero)(cast(T)to);
905                 }
906             } else static assert(0,T.stringof~" unsupported type for uniformRSymm distribution");
907         } else {
908             a=uniformRSymm!(T,boundCheck,excludeZero)(cast(T)to);
909         }
910         return a;
911     }
912 
913     /// returns another (mostly indipendent, depending on seed size) random generator
914     RandG spawn(RandG=RandomG)(){
915         RandG res=new RandG(false);
916         res.seed(&uniform!(uint));
917         return res;
918     }
919 
920     // ------- structs for uniform distributions -----
921     /// uniform distribution on the whole range for integers, and on (0;1) for floats
922     /// with boundCheck=true this is equivalent to r itself, here just for completness
923     struct UniformDistribution(T,bool boundCheck){
924         RandomG r;
925         static UniformDistribution create(RandomG r){
926             UniformDistribution res;
927             res.r=r;
928             return res;
929         }
930         /// chainable call style initialization of variables (thorugh a call to randomize)
931         UniformDistribution opCall(U,S...)(ref U a,S args){
932             randomize(a,args);
933             return this;
934         }
935         /// returns a random number
936         T getRandom(){
937             return r.uniform!(T,boundCheck)();
938         }
939         /// initialize el
940         U randomize(U)(ref U a){
941             return r.randomizeUniform!(U,boundCheck)(a);
942         }
943     }
944 
945     /// uniform distribution on the subrange [0;to$(RPAREN) for integers, (0;to) for floats
946     struct UniformRDistribution(T,bool boundCheck){
947         T to;
948         RandomG r;
949         /// initializes the probability distribution
950         static UniformRDistribution create(RandomG r,T to){
951             UniformRDistribution res;
952             res.r=r;
953             res.to=to;
954             return res;
955         }
956         /// chainable call style initialization of variables (thorugh a call to randomize)
957         UniformRDistribution opCall(U)(ref U a){
958             randomize(a);
959             return this;
960         }
961         /// returns a random number
962         T getRandom(){
963             return r.uniformR!(T,boundCheck)(to);
964         }
965         /// initialize el
966         U randomize(U)(ref U a){
967             return r.randomizeUniformR!(U,T,boundCheck)(a,to);
968         }
969     }
970 
971     /// uniform distribution on the subrange (-to;to) for integers, (-to;0)u(0;to) for floats
972     /// excludeZero controls if the zero should be excluded, boundCheck if the boundary should
973     /// be excluded for floats
974     struct UniformRSymmDistribution(T,bool boundCheck=true,bool excludeZero=isFloat!(T)){
975         T to;
976         RandomG r;
977         /// initializes the probability distribution
978         static UniformRSymmDistribution create(RandomG r,T to){
979             UniformRSymmDistribution res;
980             res.r=r;
981             res.to=to;
982             return res;
983         }
984         /// chainable call style initialization of variables (thorugh a call to randomize)
985         UniformRSymmDistribution opCall(U)(ref U a){
986             randomize(a);
987             return this;
988         }
989         /// returns a random number
990         T getRandom(){
991             return r.uniformRSymm!(T,boundCheck,excludeZero)(to);
992         }
993         /// initialize el
994         U randomize(U)(ref U a){
995             return r.randomizeUniformRSymm!(U,T,boundCheck)(a,to);
996         }
997     }
998 
999     /// uniform distribution on the subrange (-to;to) for integers, (0;to) for floats
1000     struct UniformR2Distribution(T,bool boundCheck){
1001         T from,to;
1002         RandomG r;
1003         /// initializes the probability distribution
1004         static UniformR2Distribution create(RandomG r,T from, T to){
1005             UniformR2Distribution res;
1006             res.r=r;
1007             res.from=from;
1008             res.to=to;
1009             return res;
1010         }
1011         /// chainable call style initialization of variables (thorugh a call to randomize)
1012         UniformR2Distribution opCall(U,S...)(ref U a,S args){
1013             randomize(a,args);
1014             return this;
1015         }
1016         /// returns a random number
1017         T getRandom(){
1018             return r.uniformR2!(T,boundCheck)(from,to);
1019         }
1020         /// initialize a
1021         U randomize(U)(ref U a){
1022             return r.randomizeUniformR2!(U,T,T,boundCheck)(a,from,to);
1023         }
1024     }
1025 
1026     // ---------- gamma distribution, move to a separate module? --------
1027     /// gamma distribution f=x^(alpha-1)*exp(-x/theta)/(gamma(alpha)*theta^alpha)
1028     /// alpha has to be bigger than 1, for alpha<1 use gammaD(alpha)=gammaD(alpha+1)*pow(r.uniform!(T),1/alpha)
1029     /// from Marsaglia and Tsang, ACM Transaction on Mathematical Software, Vol. 26, N. 3
1030     /// 2000, p 363-372
1031     struct GammaDistribution(T){
1032         RandomG r;
1033         T alpha;
1034         T theta;
1035         static GammaDistribution create(RandomG r,T alpha=cast(T)1,T theta=cast(T)1){
1036             GammaDistribution res;
1037             res.r=r;
1038             res.alpha=alpha;
1039             res.theta=theta;
1040             verify(alpha>=cast(T)1,"implemented only for alpha>=1");
1041             return res;
1042         }
1043         /// chainable call style initialization of variables (thorugh a call to randomize)
1044         GammaDistribution opCall(U,S...)(ref U a,S args){
1045             randomize(a,args);
1046             return this;
1047         }
1048         /// returns a single random number
1049         T getRandom(T a=alpha,T t=theta)
1050         {
1051             verify(a>=cast(T)1,"implemented only for alpha>=1");
1052             T d=a-(cast(T)1)/(cast(T)3);
1053             T c=(cast(T)1)/sqrt(d*cast(T)9);
1054             auto n=r.normalSource!(T)();
1055             for (;;) {
1056                 do {
1057                     T x=n.getRandom();
1058                     T v=c*x+cast(T)1;
1059                     v=v*v*v; // might underflow (in extreme situations) so it is in the loop
1060                 } while (v<=0);
1061                 T u=r.uniform!(T)();
1062                 if (u<1-(cast(T)0.331)*(x*x)*(x*x)) return t*d*v;
1063                 if (log(u)< x*x/2+d*(1-v+log(v))) return t*d*v;
1064             }
1065         }
1066         /// initializes b with gamma distribued random numbers
1067         U randomize(U)(ref U b,T a=alpha,T t=theta){
1068             static if (is(U S:S[])) {
1069                 alias StripAllArrays!(U) T;
1070                 T* bEnd=b.ptr+b.length;
1071                 for (T* bPtr=b.ptr;bPtr!=bEnd;++bPtr){
1072                     *bPtr=cast(StripAllArrays!(U)) getRandom(a,t);
1073                 }
1074             } else {
1075                 b=cast(U) getRandom(a,t);
1076             }
1077             return b;
1078         }
1079         /// maps op on random numbers (of type T) and initializes b with it
1080         U randomizeOp(U,S)(scope S delegate(T)op, ref U b,T a=alpha, T t=theta){
1081             static if(is(U S:S[])){
1082                 alias StripAllArrays!(U) T;
1083                 T* bEnd=b.ptr+b.length;
1084                 for (T* bPtr=b.ptr;bPtr!=bEnd;++bPtr){
1085                     *bPtr=cast(StripAllArrays!(U))op(getRandom(a,t));
1086                 }
1087             } else {
1088                 b=cast(U)op(getRandom(a));
1089             }
1090             return b;
1091         }
1092     }
1093 
1094     //-------- various distributions available -----------
1095 
1096     /// generators of normal numbers (sigma=1,mu=0) of the given type
1097     /// f=exp(-x*x/(2*sigma^2))/(sqrt(2 pi)*sigma)
1098     NormalSource!(RandomG,T) normalSource(T)(){
1099         static if(is(T==float)){
1100             if (!normalFloat) normalFloat=new NormalSource!(RandomG,T)(this);
1101             return normalFloat;
1102         } else static if (is(T==double)){
1103             if (!normalDouble) normalDouble=new NormalSource!(RandomG,T)(this);
1104             return normalDouble;
1105         } else static if (is(T==real)){
1106             if (!normalReal) normalReal=new NormalSource!(RandomG,T)(this);
1107             return normalReal;
1108         } else static assert(0,T.stringof~" no normal source implemented");
1109     }
1110 
1111     /// generators of exp distribued numbers (beta=1) of the given type
1112     /// f=1/beta*exp(-x/beta)
1113     ExpSource!(RandomG,T) expSource(T)(){
1114         static if(is(T==float)){
1115             if (!expFloat) expFloat=new ExpSource!(RandomG,T)(this);
1116             return expFloat;
1117         } else static if (is(T==double)){
1118             if (!expDouble) expDouble=new ExpSource!(RandomG,T)(this);
1119             return expDouble;
1120         } else static if (is(T==real)){
1121             if (!expReal) expReal=new ExpSource!(RandomG,T)(this);
1122             return expReal;
1123         } else static assert(0,T.stringof~" no exp source implemented");
1124     }
1125 
1126     /// generators of normal numbers with a different default sigma/mu
1127     /// f=exp(-x*x/(2*sigma^2))/(sqrt(2 pi)*sigma)
1128     NormalSource!(RandomG,T).NormalDistribution normalD(T)(T sigma=cast(T)1,T mu=cast(T)0){
1129         return normalSource!(T).normalD(sigma,mu);
1130     }
1131     /// exponential distribued numbers with a different default beta
1132     /// f=1/beta*exp(-x/beta)
1133     ExpSource!(RandomG,T).ExpDistribution expD(T)(T beta){
1134         return expSource!(T).expD(beta);
1135     }
1136     /// gamma distribued numbers with the given default alpha
1137     GammaDistribution!(T) gammaD(T)(T alpha=cast(T)1,T theta=cast(T)1){
1138         return GammaDistribution!(T).create(this,alpha,theta);
1139     }
1140 
1141     /// uniform distribution on the whole integer range, and on (0;1) for floats
1142     /// should return simply this??
1143     UniformDistribution!(T,true) uniformD(T)(){
1144         return UniformDistribution!(T,true).create(this);
1145     }
1146     /// uniform distribution on the whole integer range, and on [0;1] for floats
1147     UniformDistribution!(T,false) uniformBoundsD(T)(){
1148         return UniformDistribution!(T,false).create(this);
1149     }
1150     /// uniform distribution [0;to$(RPAREN) for ints, (0:to) for reals
1151     UniformRDistribution!(T,true) uniformRD(T)(T to){
1152         return UniformRDistribution!(T,true).create(this,to);
1153     }
1154     /// uniform distribution [0;to$(RPAREN) for ints, [0:to] for reals
1155     UniformRDistribution!(T,false) uniformRBoundsD(T)(T to){
1156         return UniformRDistribution!(T,false).create(this,to);
1157     }
1158     /// uniform distribution (-to;to) for ints and (-to;0)u(0;to) for reals
1159     UniformRSymmDistribution!(T,true,isFloat!(T)) uniformRSymmD(T)(T to){
1160         return UniformRSymmDistribution!(T,true,isFloat!(T)).create(this,to);
1161     }
1162     /// uniform distribution (-to;to) for ints and [-to;0$(RPAREN)u$(LPAREN)0;to] for reals
1163     UniformRSymmDistribution!(T,false,isFloat!(T)) uniformRSymmBoundsD(T)(T to){
1164         return UniformRSymmDistribution!(T,false,isFloat!(T)).create(this,to);
1165     }
1166     /// uniform distribution [from;to$(RPAREN) for ints and (from;to) for reals
1167     UniformR2Distribution!(T,true) uniformR2D(T)(T from, T to){
1168         return UniformR2Distribution!(T,true).create(this,from,to);
1169     }
1170     /// uniform distribution [from;to$(RPAREN) for ints and [from;to] for reals
1171     UniformR2Distribution!(T,false) uniformR2BoundsD(T)(T from, T to){
1172         return UniformR2Distribution!(T,false).create(this,from,to);
1173     }
1174 
1175     // -------- Utility functions for other distributions -------
1176     // add also the corresponding randomize functions?
1177 
1178     /// returns a normal distribued number
1179     T normal(T)(){
1180         return normalSource!(T).getRandom();
1181     }
1182     /// returns a normal distribued number with the given sigma
1183     T normalSigma(T)(T sigma){
1184         return normalSource!(T).getRandom(sigma);
1185     }
1186     /// returns a normal distribued number with the given sigma and mu
1187     T normalSigmaMu(T)(T sigma,T mu){
1188         return normalSource!(T).getRandom(sigma,mu);
1189     }
1190 
1191     /// returns an exp distribued number
1192     T exp(T)(){
1193         return expSource!(T).getRandom();
1194     }
1195     /// returns an exp distribued number with the given scale beta
1196     T expBeta(T)(T beta){
1197         return expSource!(T).getRandom(beta);
1198     }
1199 
1200     /// returns a gamma distribued number
1201     /// from Marsaglia and Tsang, ACM Transaction on Mathematical Software, Vol. 26, N. 3
1202     /// 2000, p 363-372
1203     T gamma(T)(T alpha=cast(T)1,T sigma=cast(T)1)
1204     {
1205         verify(alpha>=cast(T)1,"implemented only for alpha>=1");
1206         auto n=normalSource!(T);
1207         T d=alpha-(cast(T)1)/(cast(T)3);
1208         T c=(cast(T)1)/sqrt(d*cast(T)9);
1209         for (;;) {
1210             T x,v;
1211             do {
1212                 x=n.getRandom();
1213                 v=c*x+cast(T)1;
1214                 v=v*v*v; // might underflow (in extreme situations) so it is in the loop
1215             } while (v<=0);
1216             T u=uniform!(T)();
1217             if (u<1-(cast(T)0.331)*(x*x)*(x*x)) return sigma*d*v;
1218             if (log(u)< x*x/2+d*(1-v+log(v))) return sigma*d*v;
1219         }
1220     }
1221     // ---------------
1222 
1223     /// writes the current status in a string
1224     override istring toString(){
1225         return source.toString();
1226     }
1227     /// reads the current status from a string (that should have been trimmed)
1228     /// returns the number of chars read
1229     size_t fromString(cstring s){
1230         return source.fromString(s);
1231     }
1232 
1233     // make this by default a uniformRandom number generator
1234     /// chainable call style initialization of variables (thorugh a call to randomize)
1235     RandomG opCall(U)(ref U a){
1236         randomize(a);
1237         return this;
1238     }
1239     /// returns a random number
1240     T getRandom(T)(){
1241         return uniform!(T,true)();
1242     }
1243     /// initialize el
1244     U randomize(U)(ref U a){
1245         return randomizeUniform!(U,true)(a);
1246     }
1247 
1248 } // end class RandomG
1249 
1250 /// make the default random number generator type
1251 /// (a non threadsafe random number generator) easily available
1252 /// you can safely expect a new instance of this to be indipendent from all the others
1253 alias RandomG!() Random;
1254 /// default threadsafe random number generator type
1255 alias RandomG!(DefaultEngine) RandomSync;
1256 
1257 /// shared locked (threadsafe) random number generator
1258 /// initialized with urandom if available, with time otherwise
1259 static RandomSync rand;
1260 static this ()
1261 {
1262     rand = new RandomSync(false);
1263 
1264     static void set_array_source(ulong s)
1265     {
1266         uint[2] a;
1267         a[0]= cast(uint)(s & 0xFFFF_FFFFUL);
1268         a[1]= cast(uint)(s>>32);
1269         rand.seed(&(ArraySource(a).next));
1270     }
1271 
1272     version (unittest){
1273         set_array_source(9); // http://dilbert.com/strip/2001-10-25
1274     } else {
1275         URandom r;
1276         rand.seed(&r.next);
1277     }
1278 }
1279 
1280 version (unittest)
1281 {
1282     import ocean.math.random.engines.KISS;
1283     import ocean.math.random.engines.CMWC;
1284     import core.stdc.stdio:printf;
1285     import ocean.core.Test;
1286 
1287     /// very simple statistal test, mean within maxOffset, and maximum/minimum at least minmax/maxmin
1288     bool checkMean(T)(T[] a, real maxmin, real minmax, real expectedMean, real maxOffset,bool alwaysPrint=false,bool checkB=false){
1289         T minV,maxV;
1290         real meanV=0.0L;
1291         if (a.length>0){
1292             minV=a[0];
1293             maxV=a[0];
1294             foreach (el;a){
1295                 test(!checkB || (cast(T)0<el && el<cast(T)1),"el out of bounds");
1296                 if (el<minV) minV=el;
1297                 if (el>maxV) maxV=el;
1298                 meanV+=cast(real)el;
1299             }
1300             meanV/=cast(real)a.length;
1301             bool printM=false;
1302             if (cast(real)minV>maxmin) printM=true;
1303             if (cast(real)maxV<minmax) printM=true;
1304             if (expectedMean-maxOffset>meanV || meanV>expectedMean+maxOffset) printM=true;
1305             if (printM){
1306                 printf("WARNING ocean.math.Random statistic is strange: %.*s[%d] %Lg %Lg %Lg\n\0",
1307                     cast(int)T.stringof.length, T.stringof.ptr, cast(int)a.length,
1308                     cast(real)minV,meanV,cast(real)maxV);
1309             } else if (alwaysPrint) {
1310                 printf("ocean.math.Random statistic: %.*s[%d] %Lg %Lg %Lg\n\0",
1311                     cast(int)T.stringof.length, T.stringof.ptr, cast(int)a.length,
1312                     cast(real)minV,meanV,cast(real)maxV);
1313             }
1314             return printM;
1315         }
1316         return false;
1317     }
1318 
1319     /// check a given generator both on the whole array, and on each element separately
1320     bool doTests(RandG,Arrays...)(RandG r,real maxmin, real minmax, real expectedMean, real maxOffset,bool alwaysPrint,bool checkB, Arrays arrs){
1321         bool gFail=false;
1322         foreach (i,TA;Arrays){
1323             alias StripAllArrays!(TA) T;
1324             // all together
1325             r(arrs[i]);
1326             bool fail=checkMean!(T)(arrs[i],maxmin,minmax,expectedMean,maxOffset,alwaysPrint,checkB);
1327             // one by one
1328             foreach (ref el;arrs[i]){
1329                 r(el);
1330             }
1331             fail |= checkMean!(T)(arrs[i],maxmin,minmax,expectedMean,maxOffset,alwaysPrint,checkB);
1332             gFail |= fail;
1333         }
1334         return gFail;
1335     }
1336 
1337     void testRandSource(RandS)(){
1338         auto r=new RandomG!(RandS)();
1339         // r.fromString("KISS99_b66dda10_49340130_8f3bf553_224b7afa_00000000_00000000"); // to reproduce a given test...
1340         auto initialState=r.toString(); // so that you can reproduce things...
1341         bool allStats=false; // set this to true to show all statistics (helpful to track an error)
1342         try{
1343             r.uniform!(uint);
1344             r.uniform!(ubyte);
1345             r.uniform!(ulong);
1346             int count=10_000;
1347             for (int i=count;i!=0;--i){
1348                 float f=r.uniform!(float);
1349                 test(0<f && f<1,"float out of bounds");
1350                 double d=r.uniform!(double);
1351                 test(0<d && d<1,"double out of bounds");
1352                 real rr=r.uniform!(real);
1353                 test(0<rr && rr<1,"double out of bounds");
1354             }
1355             // checkpoint status (str)
1356             auto status=r.toString();
1357             uint tVal=r.uniform!(uint);
1358             ubyte t2Val=r.uniform!(ubyte);
1359             ulong t3Val=r.uniform!(ulong);
1360 
1361             byte[1000]  barr;
1362             ubyte[1000] ubarr;
1363             uint[1000]  uiarr;
1364             int[1000]   iarr;
1365             float[1000] farr;
1366             double[1000]darr;
1367             real[1000]  rarr;
1368             byte[]  barr2=barr[];
1369             ubyte[] ubarr2=ubarr[];
1370             uint[]  uiarr2=uiarr[];
1371             int[]   iarr2=iarr[];
1372             float[] farr2=farr[];
1373             double[]darr2=darr[];
1374             real[]  rarr2=rarr[];
1375 
1376             bool fail=false,gFail=false;
1377             fail =doTests(r,-100.0L,100.0L,0.0L,20.0L,allStats,false,barr2);
1378             fail|=doTests(r,100.0L,155.0L,127.5L,20.0L,allStats,false,ubarr2);
1379             fail|=doTests(r,0.25L*cast(real)(uint.max),0.75L*cast(real)uint.max,
1380                 0.5L*uint.max,0.2L*uint.max,allStats,false,uiarr2);
1381             fail|=doTests(r,0.5L*cast(real)int.min,0.5L*cast(real)int.max,
1382                 0.0L,0.2L*uint.max,allStats,false,iarr2);
1383             fail|=doTests(r,0.2L,0.8L,0.5L,0.2L,allStats,true,farr2,darr2,rarr2);
1384             gFail|=fail;
1385 
1386             fail =doTests(r.uniformD!(int)(),-100.0L,100.0L,0.0L,20.0L,allStats,false,barr2);
1387             fail|=doTests(r.uniformD!(int)(),100.0L,155.0L,127.5L,20.0L,allStats,false,ubarr2);
1388             fail|=doTests(r.uniformD!(int)(),0.25L*cast(real)(uint.max),0.75L*cast(real)uint.max,
1389                 0.5L*uint.max,0.2L*uint.max,allStats,false,uiarr2);
1390             fail|=doTests(r.uniformD!(real)(),0.5L*cast(real)int.min,0.5L*cast(real)int.max,
1391                 0.0L,0.2L*uint.max,allStats,false,iarr2);
1392             fail|=doTests(r.uniformD!(real)(),0.2L,0.8L,0.5L,0.2L,allStats,true,farr2,darr2,rarr2);
1393             gFail|=fail;
1394 
1395             fail =doTests(r.uniformBoundsD!(int)(),-100.0L,100.0L,0.0L,20.0L,allStats,false,barr2);
1396             fail|=doTests(r.uniformBoundsD!(int)(),100.0L,155.0L,127.5L,20.0L,allStats,false,ubarr2);
1397             fail|=doTests(r.uniformBoundsD!(int)(),0.25L*cast(real)(uint.max),0.75L*cast(real)uint.max,
1398                 0.5L*uint.max,0.2L*uint.max,allStats,false,uiarr2);
1399             fail|=doTests(r.uniformBoundsD!(int)(),0.5L*cast(real)int.min,0.5L*cast(real)int.max,
1400                 0.0L,0.2L*uint.max,allStats,false,iarr2);
1401             fail|=doTests(r.uniformBoundsD!(int)(),0.2L,0.8L,0.5L,0.2L,allStats,false,farr2,darr2,rarr2);
1402             gFail|=fail;
1403 
1404             fail =doTests(r.uniformRD(cast(byte)101),25.0L,75.0L,50.0L,15.0L,allStats,false,barr2);
1405             fail|=doTests(r.uniformRD(cast(ubyte)201),50.0L,150.0L,100.0L,20.0L,allStats,false,ubarr2);
1406             fail|=doTests(r.uniformRD(1001u),250.0L,750.0L,500.0L,100.0L,allStats,false,uiarr2);
1407             fail|=doTests(r.uniformRD(1001 ),250.0L,750.0L,500.0L,100.0L,allStats,false,iarr2);
1408             fail|=doTests(r.uniformRD(1000.0L),250.0L,750.0L,500.0L,100.0L,
1409                 allStats,false,farr2,darr2,rarr2);
1410             fail|=doTests(r.uniformRD(1.0L),0.2L,0.8L,0.5L,0.2L,allStats,true,farr2,darr2,rarr2);
1411             gFail|=fail;
1412 
1413             fail =doTests(r.uniformRBoundsD(cast(byte)101),25.0L,75.0L,50.0L,15.0L,allStats,false,barr2);
1414             fail|=doTests(r.uniformRBoundsD(cast(ubyte)201),50.0L,150.0L,100.0L,20.0L,allStats,false,ubarr2);
1415             fail|=doTests(r.uniformRBoundsD(1001u),250.0L,750.0L,500.0L,100.0L,allStats,false,uiarr2);
1416             fail|=doTests(r.uniformRBoundsD(1001 ),250.0L,750.0L,500.0L,100.0L,allStats,false,iarr2);
1417             fail|=doTests(r.uniformRBoundsD(1000.0L),250.0L,750.0L,500.0L,100.0L,
1418                 allStats,false,farr2,darr2,rarr2);
1419             gFail|=fail;
1420 
1421             fail =doTests(r.uniformRSymmD!(byte)(cast(byte)100),
1422                 -40.0L,40.0L,0.0L,30.0L,allStats,false,barr2);
1423             fail|=doTests(r.uniformRSymmD!(int)(1000),
1424                 -300.0L,300.0L,0.0L,200.0L,allStats,false,iarr2);
1425             fail|=doTests(r.uniformRSymmD!(real)(1.0L),
1426                 -0.3L,0.3L,0.0L,0.3L,allStats,false,farr2,darr2,rarr2);
1427             gFail|=fail;
1428 
1429             fail =doTests(r.uniformRSymmBoundsD!(byte)(cast(byte)100),
1430                 -40.0L,40.0L,0.0L,30.0L,allStats,false,barr2);
1431             fail|=doTests(r.uniformRSymmBoundsD!(int)(1000),
1432                 -300.0L,300.0L,0.0L,200.0L,allStats,false,iarr2);
1433             fail|=doTests(r.uniformRSymmBoundsD!(real)(1.0L),
1434                 -0.3L,0.3L,0.0L,0.3L,allStats,false,farr2,darr2,rarr2);
1435             gFail|=fail;
1436 
1437             fail =doTests(r.normalSource!(float)(),-0.5L,0.5L,0.0L,1.0L,
1438                 allStats,false,farr2,darr2,rarr2);
1439             fail|=doTests(r.normalSource!(double)(),-0.5L,0.5L,0.0L,1.0L,
1440                 allStats,false,farr2,darr2,rarr2);
1441             fail|=doTests(r.normalSource!(real)(),-0.5L,0.5L,0.0L,1.0L,
1442                 allStats,false,farr2,darr2,rarr2);
1443             fail|=doTests(r.normalD!(real)(0.5L,5.0L),4.5L,5.5L,5.0L,0.5L,
1444                 allStats,false,farr2,darr2,rarr2);
1445             gFail|=fail;
1446 
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 
1457             uint seed = 0;
1458             r.seed({ return 2*(seed++); });
1459             auto v1 = r.uniform!(int)();
1460 
1461             seed = 0;
1462             r.seed({ return 2*(seed++); });
1463             auto v2 = r.uniform!(int)();
1464 
1465             test!("==")(v1, v2, "Re-seed failure: " ~ RandS.stringof);
1466 
1467             r.fromString(status);
1468             test!("==")(r.uniform!(uint),tVal,"restoring of status from str failed");
1469             test!("==")(r.uniform!(ubyte),t2Val,"restoring of status from str failed");
1470             test!("==")(r.uniform!(ulong),t3Val,"restoring of status from str failed");
1471             test(!gFail,"Random.d failure");
1472         } catch(Exception e) {
1473             throw e;
1474         }
1475     }
1476 }
1477 
1478 unittest {
1479     testRandSource!(Kiss99)();
1480     testRandSource!(CMWC_default)();
1481     testRandSource!(KissCmwc_default)();
1482     testRandSource!(Twister)();
1483     testRandSource!(DefaultEngine)();
1484 }