random.cc

This module abstracts the concept of a random number generator. The base types are:

class random_gen { public: virtual double rand()=0; }; class affinerand: public random_gen { public: double scale, offset; affinerand(double s=1, double o=0, random_gen *g=NULL); void Set_gen(random_gen*); void set_gen(TCL_args args) {Set_gen(args);} template <class T> void new_gen(const T&); double rand() {return scale*gen->rand()+offset;} };

`random_gen`

is an abstract base class representing a random
number generator. `affinerand`

performs a simple affine
transformation on the contained random generator. The
`random_gen*`

argument to `affine_rand()`

may be used to set
the random generator employed. If `NULL`

(default) is passed for
this parameter, a uniform random generator of type urand is created
and used. After creation, you can either set the random generator to
be something else using `Set_gen`

, or create a new random
generator of the same type as the passed argument using
`new_gen`

. The `set_gen`

method is callable from TCL, and
takes a named `random_gen`

object as an argument. The class's
destructor will delete a generator created with newgen, but not delete
an object passed by setgen. For example, a normal distribution with
mean m and standard deviation s can be obtained with the declaration:

affinerand(s,m).newgen(gaussrand());

The other classes are:

class urand: public random_gen { public: double rand(); void Seed(int s); void seed(TCL_args args) {Seed(args);} #if defined(UNURAN) || defined(GNUSL) void Set_gen(char *); void set_gen(TCL_args args) {Set_gen(args);} urand(const char* descr) {Set_gen(descr);} #endif }; class gaussrand: public random_gen { public: urand uni; double rand(); };

`urand`

simply returns a uniform random variate in [0,1]. The
basic * Eco Lab* code contains a uniform generator which is simply an
interface to the standard library

`rand()`

call, and a Gaussian
random generator, which is based on the algorithm described in
Abramowitz and Stegun (1964) sec. 26.8.6.a(2).
`gaussrand`

returns a normal variate with mean 0 and standard
deviation 1. Use `gaussrand`

coupled with `affinerand`

to
change the mean and standard deviation:

affinerand gen(2,.5,new gaussrand);defines a gaussian generator variable

As of * Eco Lab*.4.D7, replacements for these routines using freely
available libraries, unuran and GNUSL are available. The Makefile will
select the UNURAN
library
if available,
otherwise the GNU Scientific
Library
will be selected. If
neither of these packages are available, the original basic behaviour
is selected. Please read the section on problems with the
basic random number library.

Both UNURAN and GNUSL provide a text interface to selecting and
configuring the uniform random generator. The method `Set_gen`

provides a way passing PRNG
parameters
to the underlying PRNG generator. By default the Mersenne Twister
algorithm is used, which is acknowledged as being one of the most
efficient random generator available. The algorithms available
through PRNG are:

**EICG**- explicit inversive congruential generator
**ICG**- inversive congruential generator
**LCG**- linear congruential generator
**QCG**- quadratic congruential generator
**MT19937**- Mersenne Twister
**MEICG**- modified explicit inversive congruential generator
**DICG**- digital inversive congruential generator

The set available through GNUSL are:

**mt19937**- Mersenne Twister
**ranlxs0,ranlxs1,ranlxs2,ranlxd1,ranlxd2**- Lüscher's RANLUX at different levels of precision and luxury.
**cmrg**- combined multiple recursive generator by L'Ecuyer
**mrg**- fifth-order multiple recursive generator by L'Ecuyer, Blouin and Coutre
**taus,taus2**- maximally equidistributed combined Tausworthe generator by L'Ecuyer
**gfsr4**- Four-tap shift-register-sequence random-number generator by Ziff.

class distrand: public random_gen { public: int nsamp; /* no. of sample points in distribution */ int width; /* digits of precision (base 16) used from prob. distribution */ double min, max; /* distribution endpoints */ distrand(): nsamp(10), width(3), min(0), max(1); void Init(int argc, char *argv[]); void init(double (*f)(double)); double rand(); }; #ifdef UNURAN class unuran: public random_gen { public: urand uni; UNUR_RAN *get_gen(); //get pointer to UNUR_RAN object for UNURAN API use /* specify a random generator according to unuran's string interface */ void Set_gen(const char *descr); void set_gen(TCL_args args) {Set_gen(args);} unuran(); unuran(const char* descr) {Set_gen(descr);} double rand(); }; #endif

`distrand`

returns a deviate from an arbitrary
distribution function (which needn't be normalised) supplied to
`Init`

(or `init`

). The instance variables `nsamp=10`

,
`width=3`

, `min=0`

and `max=1`

should be modified
before calling `init`

. `Init`

provides a TCL interface --
it takes one argument, the name of a TCL procedure implementing the
distribution. This class implements the method due to
Marsaglia[4]. The UNURAN and GNUSL libraries provide
other, perhaps better routines for doing the same things.

Finally, `unuran`

allows an arbitrary UNURAN generator to be
specified using UNURAN's string
interface.
For example, `gaussrand`

is equivalent to
`unuran("normal()")`

. The string interface is powerful and
comprehensive, with a large number of predefined distributions and
methods provided, and the ability to specify arbitrary
distributions. It obviates the need to use `distrand`

, which is a
rather obsolete algorithm.

GNUSL does not provide a string interace to its general nonuniform distributions. For the moment, you will need to implement your own object interfaces to which ever routines you want to use. You may use the gaussrand example as a template.