tango.math.random.Random

Random number generators

This is an attempt at having a good flexible and easy to use random number generator. ease of use:

  • shared generator for quick usage available through the "rand" object
  • simple Random (non threadsafe) and RandomSync (threadsafe) types to create new generators (for heavy use a good idea is one Random object per thread)
  • rand.distributionD!(type)(paramForDistribution)
    several distributions can be requested like this the type can often be avoided if the parameters make it clear. From it single numbers can be generated with .getRandom(), and variables initialized either with call style (var) or with .randomize(var). Utility functions to generate numbers directly are also available. The choice to put all the distribution in a single object that caches them has made (for example) the gamma distribution very easy to implement.
  • sample usage:
                            int i; float f; real rv; real[100] ar0; real[] ar=ar0[];
                // initialize with uniform distribution
                i=r.uniform!(int);
                f=r.uniform!(float);
                rv=r.uniform!(real);
                foreach (ref el;ar)
                  el=r.uniform!(real);
                // another way to do all the previous in one go:
                r(i)(f)(rv)(ar);
                // unfortunetely one cannot use directly ar0...
                // uniform distribution 0..10
                i=r.uniformR(10);
                f=r.uniformR(10.0f);
                rv=r.uniformR(10.0L);
                foreach (ref el;ar)
                  el=r.uniformR(10.0L);
                // another way to do all the previous in one go:
                r.uniformRD(10)(i)(f)(r)(ar);
                // uniform numbers in [5;10
  • i=r.uniformR2(5,10); // uniform numbers in (5;10) f=r.uniformR2(5.0f,10.0f); rv=r.uniformR2(5.0L,10.0L); foreach (ref el;ar) el=r.uniformR2(5.0L,10.0L); // another way to do all the previous in one go: r.uniformR2D(5.0L,10.0L)(i)(f)(r)(ar); // uniform distribution -10..10 i=r.uniformRSymm(10); // well you get it... r.uniformRSymmD(10)(i)(f)(r)(ar); // any distribution can be stored auto r2=r.uniformRSymmD(10); // and used later r2(ar); // complex distributions (normal,exp,gamma) are produced for the requested type r.normalSource!(float)()(f); // with sigma=2 r.normalD(2.0f)(f); // and can be used also to initialize other types r.normalSource!(float)()(r)(ar); r.normalD(2.0f)(r)(ar); // but this is different from r.normalSource!(real)()(i)(r)(ar); r.normalD(2.0L)(i)(r)(ar); // as the source generates numbers of its type that then are simply cast to // the type needed. // Uniform distribution (as its creation for different types has no overhead) // is never cast, so that (for example) bounds exclusion for floats is really // guaranteed. // For the other distribution using a distribution of different type than // the variable should be done with care, as underflow/overflow might ensue. // // Some utility functions are also available int i2=r.uniform!(int)(); int i2=r.randomize(i); // both i and i2 are initialized to the same value float f2=r.normalSigma(3.0f);

      )
    )
    flexibility:
    $(UL
      $(LI  easily swappable basic source

    // a random generator that uses the system provided random generator: auto r=RandomG!(Urandom)();

    1         One could also build an engine that can be changed at runtime (that calls
    2         a delegate for example), but this adds a little overhead, and changing
    3         engine is not something done often, so this is not part of the library.
    4   )
    5   $(LI  ziggurat generator can be easily adapted to any decreasing derivable
    6         distribution, the hard parametrization (to find xLast) can be done
    7         automatically
    8   )
    9   $(LI  several distributions available "out of the box"
    10   )
    11   )
    12   Quality:
    13   $(UL
    14   $(LI  the default Source combines two surces that pass all statistical tests 
    15         (KISS+CMWC)
    16         (P. Lcuyer and R. Simard, ACM Transactions on Mathematical Software (2007),
    17         33, 4, Article 22, for KISS, see CMWC engine for the other)
    18   )
    19   $(LI  floating point uniform generator always initializes the full mantissa, the
    20         only flaw is a (*very* small) predilection of 0 as least important bit 
    21         (IEEE rounds to 0 in case of tie).
    22         Using a method that initializes the full mantissa was shown to improve the
    23         quality of subsequntly derived normal distribued numbers
    24         (Thomas et al. Gaussian random number generators. Acm Comput Surv (2007)
    25         vol. 39 (4) pp. 11))
    26   )
    27   $(LI  Ziggurat method, a very fast and accurate method was used for both Normal and
    28         exp distributed numbers.
    29   )
    30   $(LI  gamma distribued numbers uses a method recently proposed by Marsaglia and
    31         Tsang. The method is very fast, and should be good.
    32         My (Fawzi) feeling is that the transformation h(x)=(1+d*x)^3 might lose
    33         a couple of bits of precision in some cases, but it is unclear if this
    34         might become visible in (*very* extensive) tests or not.
    35   )
    36    the basic source can be easily be changed with something else
    37   Efficiency:
    38   $(LI  very fast methods have been used, and some effort has been put into
    39         optimizing some of them, but not all, but the interface has been choosen
    40         so that close to optimal implementation can be provided through the same
    41         interface.
    42   )
    43   $(LI  Normal and Exp sources allocated only upon request: no memory waste, but
    44         a (*very* small) speed hit, that can be avoided by storing the source in
    45         a variable and using it (not going through the RandomG)
    46   )
    47 )
    48 Annoyances:
    49 $(UL
    50   $(LI  I have added two "next" methods to RandomG for backward compatibility
    51         reasons, and the .instance from Random has been
    52         replaced by the "rand" object. The idea behind this is that RandomG is
    53         a template and rand it should be shared across all templates.
    54         If the name rand is considered bad one could change it. 
    55         I kept .instance static method that returns rand, so this remain a dropin
    56         replacement of the old random.
    57   )
    58   $(LI You cannot initialize a static array directly, this because randomize is
    59       declared like this:

    U randomize(U)(ref U a) { }

    make arrays initialized, and scalar not, which is much worse. ) )

    Members

    Aliases

    DefaultEngine
    alias DefaultEngine = KissCmwc_32_1

    The default engine, a reasonably collision free, with good statistical properties not easy to invert, and with a relatively small key (but not too small)

    Random
    alias Random = RandomG!()

    make the default random number generator type (a non threadsafe random number generator) easily available you can safely expect a new instance of this to be indipendent from all the others

    RandomSync
    alias RandomSync = RandomG!(Sync!(DefaultEngine))

    default threadsafe random number generator type

    Classes

    RandomG
    class RandomG(SourceT = DefaultEngine)

    Class that represents a random number generator. Normally you should get random numbers either with call-like interface: auto r=new Random(); r(i)(j)(k); or with randomize r.randomize(i); r.randomize(j); r.randomize(k); if you use this you should be able to easily switch distribution later, as all distributions support this interface, and can be built on the top of RandomG auto r2=r.NormalSource!(float)(); r2(i)(j)(k); there are utility methods within random for the cases in which you do not want to build a special distribution for just a few numbers

    Functions

    checkMean
    bool checkMean(T[] a, real maxmin, real minmax, real expectedMean, real maxOffset, bool alwaysPrint, bool checkB)

    very simple statistal test, mean within maxOffset, and maximum/minimum at least minmax/maxmin

    doTests
    bool doTests(RandG r, real maxmin, real minmax, real expectedMean, real maxOffset, bool alwaysPrint, bool checkB, Arrays arrs)

    check a given generator both on the whole array, and on each element separately

    testRandSource
    void testRandSource()
    Undocumented in source. Be warned that the author may not have intended to support it.

    Static variables

    rand
    RandomSync rand;

    shared locked (threadsafe) random number generator initialized with urandom if available, with time otherwise

    Templates

    isFloat
    template isFloat(T)

    if T is a float

    Meta

    License

    BSD style: $(LICENSE)

    Version

    Initial release: July 2008

    Authors

    Fawzi Mohamed