The HEP Random module is part of
GEANT4
and has been designed and developed
starting from the Random class of
MC++,
the CLHEP's
HepRandom module with no persistency and the
Rogue Wave approach in
Math.h++
package.
The current release consists of 12 classes implementing 5 different random
engines and 5 different random distributions.
Each random distribution belongs to a different distribution-class
which can collect different algorithms and different calling sequence for
each method to define distribution parameters or range-intervals.
Each distribution-class collects also methods to fill arrays of
specified size of distributed random values.
There are 3 different ways of shooting random values:
HepRandomEngine
Is the abstract class defining the interface for each random engine. It
implements the getSeed() and getSeeds() methods which return
the initial seed value and the initial array of seeds respectively. It
defines 7 pure virtual functions: flat(), flatArray(),
setSeed(), setSeeds(), saveStatus(), restoreStatus() and
showStatus(), which are implemented by the concrete
random engines each one inheriting from this abstract class.
Many concrete random engines can be defined and added to the structure,
simply making them inheriting from HepRandomEngine and defining concrete
methods for them in such a way that flat() and flatArray() return double
random values ranging between ]0,1[.
All the random engines have a default seed value already set. They can however
be instantiated with a different seed value set up by the user. The
user, whenever necessary, can initialise the engine with a new seed by either
using a static method defined in HepRandom, or the methods to set seeds
defined in the engine itself.
Methods saveStatus() and restoreStatus() can be used to save to
file the current status of an engine and restore it from a previous saved
configuration.
The showStatus() method dumps on screen the status of the engine
currently in use.
All these methods can be called statically from HepRandom
or directly at engine level.
HepJamesRandom
This class implements the algorithm described in "F.James, Comp. Phys.
Comm. 60 (1990) 329" for pseudo-random numbers generation.
This is the default random engine for the static generator; it will be invoked
by each distribution class unless the user sets a different one.
DRand48Engine
Random engine using the drand48() and srand48() system
functions from C standard library to implement the flat() basic
distribution and for setting seeds respectively.
DRand48Engine uses the seed48() function from C standard library
to retrieve the current internal status of the generator, which is
represented by 3 short values. Copies of an object of this kind are not
allowed.
RandEngine
Simple random engine using the rand() and srand() system
functions from C standard library to implement the flat() basic
distribution and for setting seeds respectively.
To keep track of the current status of an engine of this kind, a counter
is used and its value is stored as data-member. Copies of an object of
this kind are not allowed.
RanluxEngine
The algorithm for RanluxEngine has been taken from the original
implementation in FORTRAN77 by Fred James, part of the MATHLIB HEP
library.
The initialisation is carried out using a Multiplicative Congruential
generator using formula constants of L'Ecuyer as described in "F.James,
Comp. Phys. Comm. 60 (1990) 329-344". It provides 5 different luxury
levels:
ex. ...
RanluxEngine theRanluxEngine(seed,4);
// instantiates an engine with "seed" and the best luxury-level
... or
RanluxEngine theRanluxEngine;
// instatiates an engine with default seed value and luxury-level 3
...
The class provides a method getLuxury() to get the engine
luxury level.
ex. ...
HepRandom::setTheSeed(seed,4); // sets the seed to "seed" and luxury
// to 4
HepRandom::setTheSeed(seed); // sets the seed to "seed" keeping the
// current luxury level
RanecuEngine
ex. ...
int index=n;
long seeds[2];
const long* table;
table = HepRandom::getTheSeeds();
// it returns a pointer "table" to the local SeedTable at the
// current "index" position
...
HepRandom::setTheSeeds(seeds,index);
// sets the new "index" for seeds and modify the values inside
// the local SeedTable at the "index" position. If the index is
// not specified, the current index in the table is considered.
...
The setSeed() method resets the current status of the engine to
the original seeds stored in the static table of seeds in HepRandom, at
the specified index.
HepRandom
ex. ...
HepRandom::setTheSeed(seed); // to change the current seed to 'seed'
int startSeed = HepRandom::getTheSeed(); // to get the current
... // initial seed
HepRandom::saveEngineStatus(); // to save the current engine status
// on file.
HepRandom::restoreEngineStatus(); // to restore the current engine to
// a previous saved configuration.
HepRandom::showEngineStatus(); // to display the current engine
// status to the std output.
...
int index=n;
long seeds[2];
HepRandom::getTheTableSeeds(seeds,index);
// fills "seeds" with the values stored in the global seedTable
// at position "index"
Only one random engine can be active at a time, the user can decide at any
time to change it, define a new one (if not done already) and set it:
ex. ...
DRand48Engine theNewEngine;
HepRandom::setTheEngine(&theNewEngine);
...
or simply setting it to an old instantiated engine (the old engine status is
kept and the new random sequence will start exactly from the last one previously
interrupted):
ex. ...
HepRandom::setTheEngine(&myOldEngine);
RandFlat
Distribution-class defining methods for shooting flat
random numbers, double or integers. It provides also methods to
fill with double flat values arrays of specified size.
ex. ...
double m,n;
...
double fnum = RandFlat::shoot(); // fnum ]0,1[
double fnum = RandFlat::shoot(n); // fnum ]0,n[
double fnum = RandFlat::shoot(-m,n); // fnum ]-m,n[
long h,k;
...
long inum = RandFlat::shootInt(k); // inum [0,k[
long inum = RandFlat::shootInt(-h,k); // inum [-h,k[
...
int i = RandFlat::shootBit(); // it returns just a bit (0 or 1)
... // of a random number
const int size=n;
double vect[size];
RandFlat::shootArray(size,vect); // to fill an array "vect" of n
// double flat values
A speculate set of static methods is provided to shoot random numbers from
given random engines. Using these methods, the user is responsible of the
state of the random engine(s) he/she is activating, since these methods act
directly on the flat distribution provided by the engine, by-passing the
HepRandom generator mechanism.
ex. ...
RanecuEngine theRanecuEngine;
double m,n;
...
double fnum = RandFlat::shoot(&theRanecuEngine); // fnum ]0,1[
double fnum = RandFlat::shoot(&theRanecuEngine,n); // fnum ]0,n[
double fnum = RandFlat::shoot(&theRanecuEngine,-m,n); // fnum ]-m,n[
long h,k;
...
long inum = RandFlat::shootInt(&theRanecuEngine,k); // inum [0,k[
long inum = RandFlat::shootInt(&theRanecuEngine,-h,k); // inum [-h,k[
...
int i = RandFlat::shootBit(&theRanecuEngine); // it returns just a bit
... // of a random number
const int size=n; // to fill an array "vect"
double vect[size]; // of n double flat values
RandFlat::shootArray(&theRanecuEngine,size,vect);
A speculate set of fire()/fireArray() methods is provided to shoot random
numbers via an instantiated RandFlat object. These methods act directly
on the flat distribution provided by the engine given as argument to the
constructor of RandFlat. These methods will by-pass the HepRandom
generator mechanism. If the engine is passed by pointer to the constructor, the
corresponding engine object will be deleted by the RandFlat destructor,
if passed by reference it will not be deleted by the RandFlat destructor.
ex. ...
RanecuEngine aRanecuEngine;
RandFlat FlatDist(aRanecuEngine);
double m,n;
...
double fnum = FlatDist.fire(); // fnum ]0,1[
double fnum = FlatDist.fire(n); // fnum ]0,n[
double fnum = FlatDist.fire(-m,n); // fnum ]-m,n[
long h,k;
...
long inum = FlatDist.fireInt(k); // inum [0,k[
long inum = FlatDist.fireInt(-h,k); // inum [-h,k[
...
int i = FlatDist.fireBit(); // it returns just a bit (0 or 1)
... // of a random number
const int size=n; // to fill an array "vect"
double vect[size]; // of n double flat values
FlatDist.fireArray(size,vect);
RandExponential
ex. ...
double m;
...
double num = RandExponential::shoot(); // (mean=1)
double num = RandExponential::shoot(m); // (mean=m)
A speculate set of static methods is provided to shoot random numbers from
given random engines. Using these methods, the user is responsible of the
state of the random engine(s) he/she is activating, since these methods act
directly on the flat distribution of the engine, by-passing the
HepRandom generator mechanism.
ex. ...
RanluxEngine theRanluxEngine(19780503,4);
double m;
...
double num = RandExponential::shoot(&theRanluxEngine); // (mean=1)
double num = RandExponential::shoot(&theRanluxEngine,m); // (mean=m)
A speculate set of fire()/fireArray() methods is provided to shoot random
numbers via an instantiated RandExponential object. These methods act
directly on the flat distribution provided by the engine given as argument to
the constructor of RandExponential; they will by-pass the HepRandom
generator mechanism. If the engine is passed by pointer to the constructor, the
corresponding engine object will be deleted by the RandExponential
destructor, if passed by reference it will not be deleted by the
RandExponential destructor.
ex. ...
RanluxEngine aRanluxEngine(19780503,4);
RandExponential ExpDist(aRanluxEngine);
double m;
...
double num = ExpDist.fire(); // (mean=1)
double num = ExpDist.fire(m); // (mean=m)
RandGauss
ex. ...
double m,s;
...
double num = RandGauss::shoot(); // (mean=0)
double num = RandGauss::shoot(m,s); // (mean=m, stDev=s)
A speculate set of static methods is provided to shoot random numbers from
given random engines. Using these methods, the user is responsible of the
state of the random engine(s) he/she is activating, since these methods act
directly on the flat distribution of the engine, by-passing the
HepRandom generator mechanism.
ex. ...
RandEngine theRandEngine;
double m,s;
...
double num = RandGauss::shoot(&theRandEngine);
double num = RandGauss::shoot(&theRandEngine,m,s);
A speculate set of fire()/fireArray() methods is provided to shoot
random numbers via an instantiated RandGauss object. These methods act
directly on the flat distribution provided by the engine given as argument to
the constructor of RandGauss; they will by-pass the HepRandom
generator mechanism. If the engine is passed by pointer to the constructor, the
corresponding engine object will be deleted by the RandGauss
destructor, if passed by reference it will not be deleted by the
RandGauss destructor.
ex. ...
RandEngine aRandEngine;
RandGauss GaussDist(aRandEngine);
double m,s;
...
double num = GaussDist.fire();
double num = GaussDist.fire(m,s);
RandBreitWigner
ex. ...
double m,g,c;
...
double num = RandBreitWigner::shoot(m,g); // (mean=m, gamma=g)
double num = RandBreitWigner::shoot(m,g,c); // (mean=m, gamma=g, cut=c)
A speculate set of static methods is provided to shoot random numbers from
given random engines. Using these methods, the user is responsible of the
state of the random engine(s) he/she is activating, since these methods act
directly on the flat distribution of the engine, by-passing the
HepRandom generator mechanism.
ex. ...
double m,g,c;
DRand48Engine theDRand48Engine;
...
double num = RandBreitWigner::shoot(&theDRand48Engine,m,g);
double num = RandBreitWigner::shoot(&theDRand48Engine,m,g,c);
A speculate set of fire()/fireArray() methods is provided to shoot random
numbers via an instantiated RandBreitWigner object. These methods act
directly on the flat distribution provided by the engine given as argument to
the constructor of RandBreitWigner; they will by-pass the HepRandom
generator mechanism. If the engine is passed by pointer to the constructor,
the corresponding engine object will be deleted by the RandBreitWigner
destructor, if passed by reference it will not be deleted by the
RandBreitWigner destructor.
ex. ...
double m,g,c;
DRand48Engine aDRand48Engine;
RandBreitWigner BWDist(aDRand48Engine);
...
double num = BWDist.fire(m,g);
double num = BWDist.fire(m,g,c);
RandPoisson
ex. ...
double m;
...
long num = RandPoisson::shoot(m); // (mean=m)
Other static methods are provided to shoot random numbers from given
random engines. Using these methods, the user is responsible of the
state of the random engine(s) he/she is activating, since these methods act
directly on the flat distribution of the engine, by-passing the
HepRandom generator mechanism.
ex. ...
RanecuEngine theRanecuEngine;
double m;
...
long num = RandPoisson::shoot(&theRanecuEngine,m); // (mean=m)
Other fire()/fireArray() methods are provided to shoot random numbers
via an instantiated RandPoisson object. These methods act directly on
the flat distribution of the engine passed as argument to the
constructor of RandPoisson; they will by-pass the HepRandom
generator mechanism. If the engine is passed by pointer to the constructor,
the corresponding engine object will be deleted by the RandPoisson
destructor, if passed by reference it will not be deleted by the
RandPoisson destructor.
ex. ...
RanecuEngine aRanecuEngine;
RandPoisson PoissonDist(aRanecuEngine);
double m;
...
long num = PoissonDist.fire(m); // (mean=m)
The use of a static generator has been introduced in the original design of HEP Random as a project requirement in Geant4. In applications like Geant4, where it is necessary to shoot random numbers (normally of the same engine) in many different methods and parts of the program, it is highly desirable not to have to rely-on/know global objects instantiated. By using static methods via a unique generator, randomness of a sequence of numbers is best assured.
Analysis and design of the HEP Random module have been achieved
following the
Booch Object-Oriented methodology.
Here follows a list of diagrams describing the model according to the
Booch notation: