- Next chapter
- Previous chapter
- Table of contents

# Chapter 9: Random Number Generators

9.1: Overview

These are the basic random number generators (RNGs):

Uniform
  Uniform reals on [0,1)

Normal
  Normal with specified mean and variance

Exponential
  Exponential with specified mean

DiscreteUniform
  Integers uniformly distributed over a specified range.

Beta
  Beta distribution

Gamma
  Gamma distribution

F
  F distribution

To use these generators, you need to include some subset of these headers:

    #include <random/uniform.h>
    #include <random/normal.h>
    #include <random/exponential.h>
    #include <random/discrete-uniform.h>
    #include <random/beta.h>
    #include <random/gamma.h>
    #include <random/chisquare.h>
    #include <random/F.h>

    using namespace ranlib;

All the generators are inside the namespace ranlib, so a using namespace ranlib directive is required (alternately, you can write e.g. `ranlib::Uniform<>`).

These generators are all class templates. The first template parameter is the number type you want to generate: float, double or long double for continuous distributions, and integer for discrete distributions. This parameter defaults to `float` for continuous distributions, and `unsigned int` for discrete distributions.

The constructors are:

    Uniform();
    Normal(T mean, T standardDeviation);
    Exponential(T mean);
    DiscreteUniform(T n);   // range is 0 .. n-1
    Beta(T a, T b);
    Gamma(T mean);
    ChiSquare(T df);
    F(T dfn, T dfd);

where T is the first template parameter (float, double, or long double). To obtain a random number, use the method `random()`. Here is an example of constructing and using a `Normal` generator:

    #include <random/normal.h>

    using namespace ranlib;

    void foo()
    {
        Normal<double> normalGen;
        double x = normalGen.random();    // x is a normal random number
    }

9.2: Note: Parallel random number generators

The generators which Blitz++ provides are not suitable for parallel programs. If you need parallel RNGs, you may find SPRNG useful.

9.3: Seeding a random number generator

You may seed a random number generator using the member function `seed(unsigned int)`. By default, all random number generators share the same underlying integer random number generator. So seeding one generator will seed them all. (Note: you can create generators with their own internal state; see the sections below). You should generally only seed a random number generator once, at the beginning of a program run.

Here is an example of seeding with the system clock:

    #include <random/uniform.h>
    #include <time.h>

    using namespace ranlib;

    int main()
    {
        // At start of program, seed with the system time so we get
        // a different stream of random numbers each run.
        Uniform<float> x;
        x.seed((unsigned int)time(0));

        // Rest of program
        ...
    }

Note: you may be tempted to seed the random number generator from a static initializer. Don't do it! Due to an oddity of C++, there is no guarantee on the order of static initialization when templates are involved. Hence, you may seed the RNG before its constructor is invoked, in which case your program will crash. If you don't know what a static initializer is, don't worry -- you're safe!

9.4: Detailed description of RNGs

There are really two types of RNGs:

Integer RNGs
  provide uniformly distributed, unsigned 32 bit integers.

RNGs
  use Integer RNGs to provide other kinds of random numbers.

By default, the Integer RNG used is a faithful adaptation of the Mersenne Twister MT19937 due to Matsumoto and Nishimura (see ACM Transactions on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30, web page, paper). This generator has a period of 219937-1 , passed several stringent statistical tests (including the Diehard tests), and has speed comparable to other modern generators.

9.5: Template parameters

RNGs take three template parameters, all of which have default values. Using the `Uniform` RNG as an example, the template parameters of `Uniform<T, IRNG, stateTag>` are:

T
  is the type of random number to generate (one of float, double, or long double for continuous distributions; an integer type for discrete distributions). Note that generating double and long double RNGs takes longer, because filling the entire mantissa with random bits requires several random integers. The default parameter for most generators is `float`.

IRNG
  is the underlying Integer RNG to use. The default is MersenneTwister.

stateTag
  is either `sharedState` or `independentState`. If `sharedState`, the IRNG is shared with other generators. If `independentState`, the RNG contains its own IRNG. The default is sharedState.

9.6: Member functions

RNGs have these methods:

    T random();

Returns a random number.

    void seed(unsigned int);

Seeds the underlying IRNG. See above for an example of seeding with the system timer.

9.7: Detailed listing of RNGs

To save space in the below list, template parameters have been omitted and only constructors are listed. The notation [a,b] means an interval which includes the endpoints a and b; (a,b) is an interval which does not include the endpoints.

9.7.1: `random/uniform.h`

    Uniform<>()

Continuous uniform distribution on [0,1).

    UniformClosedOpen<>()

Continuous uniform distribution on [0,1). Same as `Uniform<>`.

    UniformClosed<>()

Continuous uniform distribution on [0,1].

    UniformOpen<>()

Continuous uniform distribution on (0,1).

    UniformOpenClosed<>()

Continuous uniform distribution on (0,1].

9.7.2: `random/normal.h`

    NormalUnit<>()

Continuous normal distribution with mean 0 and variance 1.

    Normal<>(T mean, T standardDeviation)

Continuous normal distribution with specified mean and standard deviation.

9.7.3: `random/exponential.h`

    ExponentialUnit<>()

Continuous exponential distribution with mean 1.

    Exponential<>(T mean)

Continuous exponential distribution with specified mean.

9.7.4: `random/beta.h`

    Beta<>(T a, T b)

Beta distribution with parameters a and b. The mean of the distribution is a/(a+b) and its variance is ab/((a+b)^2(a+b+1)). Use the method `setParameters(T a, T b)` to change the parameters.

9.7.5: `random/chisquare.h`

    ChiSquare<>(T df)

Chi Square distribution with df degrees of freedom. The parameter df must be positive. Use the method `setDF(T df)` to change the degrees of freedom.

9.7.6: `random/gamma.h`

    Gamma<>(T mean)

Gamma distribution with specified mean. The mean must be positive. Use the method `setMean(T mean)` to change the mean.

9.7.7: `random/F.h`

    F<>(T numeratorDF, T denominatorDF)

F distribution with numerator and denominator degrees of freedom specified. Both these parameters must be positive. Use `setDF(T dfn, T dfd)` to change the degrees of freedom.

9.7.8: `random/discrete-uniform.h`

    DiscreteUniform<>(T n)

Discrete uniform distribution over 0, 1, ..., n-1.

- Next chapter
- Previous chapter
- Table of contents