Skip to content

[nfc][math] Document shortcoming of TRandom3 #19554

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions math/mathcore/src/TRandom.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ void TRandom::Circle(Double_t &x, Double_t &y, Double_t r)

Double_t TRandom::Exp(Double_t tau)
{
Double_t x = Rndm(); // uniform on ] 0, 1 ]
Double_t x = Rndm(); // uniform on ]0, 1[
Double_t t = -tau * TMath::Log( x ); // convert to exponential distribution
return t;
}
Expand Down Expand Up @@ -577,7 +577,7 @@ Double_t TRandom::Rndm( )
}

////////////////////////////////////////////////////////////////////////////////
/// Return an array of n random numbers uniformly distributed in ]0,1].
/// Return an array of n random numbers uniformly distributed in ]0,1[.

void TRandom::RndmArray(Int_t n, Double_t *array)
{
Expand All @@ -590,7 +590,7 @@ void TRandom::RndmArray(Int_t n, Double_t *array)
}

////////////////////////////////////////////////////////////////////////////////
/// Return an array of n random numbers uniformly distributed in ]0,1].
/// Return an array of n random numbers uniformly distributed in ]0,1[.

void TRandom::RndmArray(Int_t n, Float_t *array)
{
Expand Down
4 changes: 2 additions & 2 deletions math/mathcore/src/TRandom1.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ void TRandom1::GetTableSeeds(UInt_t* seeds, Int_t index)
}

////////////////////////////////////////////////////////////////////////////////
/// \brief Returns a random number in ]0,1]
/// \brief Returns a random number in ]0,1[
Double_t TRandom1::Rndm( )
{
float next_random;
Expand Down Expand Up @@ -401,7 +401,7 @@ Double_t TRandom1::Rndm( )
}

////////////////////////////////////////////////////////////////////////////////
/// \brief Returns an array of random numbers in ]0,1]
/// \brief Returns an array of random numbers in ]0,1[
void TRandom1::RndmArray(const Int_t size, Float_t *vect)
{
for (Int_t i=0;i<size;i++) vect[i] = Rndm();
Expand Down
6 changes: 3 additions & 3 deletions math/mathcore/src/TRandom2.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ TRandom2::~TRandom2()
/// TausWorth generator from L'Ecuyer, uses as seed 3x32bits integers
/// Use a mask of 0xffffffffUL to make in work on 64 bit machines
/// Periodicity of about 10**26
/// Generate number in interval (0,1) : 0 and 1 are not included in the interval
/// Generate number in interval (0,1): 0 and 1 are not included in the interval

Double_t TRandom2::Rndm()
{
Expand All @@ -69,7 +69,7 @@ Double_t TRandom2::Rndm()
}

////////////////////////////////////////////////////////////////////////////////
/// Return an array of n random numbers uniformly distributed in ]0,1]
/// Return an array of n random numbers uniformly distributed in ]0, 1[

void TRandom2::RndmArray(Int_t n, Float_t *array)
{
Expand All @@ -89,7 +89,7 @@ void TRandom2::RndmArray(Int_t n, Float_t *array)
}

////////////////////////////////////////////////////////////////////////////////
/// Return an array of n random numbers uniformly distributed in ]0,1]
/// Return an array of n random numbers uniformly distributed in ]0, 1[

void TRandom2::RndmArray(Int_t n, Double_t *array)
{
Expand Down
57 changes: 34 additions & 23 deletions math/mathcore/src/TRandom3.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,32 @@

Random number generator class based on
M. Matsumoto and T. Nishimura,
Mersenne Twister: A 623-diminsionally equidistributed
Mersenne Twister: A 623-dimensionally equidistributed
uniform pseudorandom number generator
ACM Transactions on Modeling and Computer Simulation,
Vol. 8, No. 1, January 1998, pp 3--30.

For more information see the Mersenne Twister homepage
[http://www.math.keio.ac.jp/~matumoto/emt.html]

Advantage:

- large period 2**19937 -1
Advantages:
- large period (slightly less than 2**19937 -1)
- relatively fast (slightly slower than TRandom2 but much faster than TRandom1)

Drawback:
Drawbacks:
- a relative large internal state of 624 integers
- generate only 32 random bits
- not passing all the random generator tests. It fails some tests in TestU01
(see [http://simul.iro.umontreal.ca/testu01/tu01.html])

An altenativly excellent generator passing all tests of TestU01, having 61 random bits and
fast as Mersenne and Twister is MIXMAX (TRandomMixMax).
An alternatively excellent generator passing all tests of TestU01, having 61 random bits and
being as fast as Mersenne and Twister is MIXMAX (TRandomMixMax).
Also, TRandomRanluxpp is a recommended alternative over TRandom3.

@warning TRandom3 is not a fully correct Mersenne and Twister random number generator, since
zeroes of the sequence are skipped, and thus the actual period is slightly less than
2**19937 -1. Consider using instead std::mt19937. Other differences are that, unlike in the paper, 0 (skip)
and 1 (here we divide by UINT_MAX + 1 instead of UINT_MAX - 1) are not included in the sequence.

@ingroup Random

Expand Down Expand Up @@ -73,8 +78,10 @@ namespace {
ClassImp(TRandom3);

////////////////////////////////////////////////////////////////////////////////
/// Default constructor
/// If seed is 0, the seed is automatically computed via a TUUID object.
/// \brief Default constructor.
///
/// If seed is 0, the seed array is automatically computed via a TRandom2
/// object, which internally uses TUUID.
/// In this case the seed is guaranteed to be unique in space and time.

TRandom3::TRandom3(UInt_t seed)
Expand All @@ -85,16 +92,18 @@ TRandom3::TRandom3(UInt_t seed)
}

////////////////////////////////////////////////////////////////////////////////
/// Default destructor
/// \brief Default destructor.

TRandom3::~TRandom3()
{
}

////////////////////////////////////////////////////////////////////////////////
/// Machine independent random number generator.
/// Produces uniformly-distributed floating points in (0,1)
/// \brief Machine independent random number generator.
///
/// Produces uniformly-distributed floating points in ]0, 1[.
/// Method: Mersenne Twister
/// Generate number in interval (0,1): 0 and 1 are not included in the interval

Double_t TRandom3::Rndm()
{
Expand Down Expand Up @@ -132,21 +141,21 @@ Double_t TRandom3::Rndm()
y ^= ((y << 15) & kTemperingMaskC );
y ^= (y >> 18);

// 2.3283064365386963e-10 == 1./(max<UINt_t>+1) -> then returned value cannot be = 1.0
// 2.3283064365386963e-10 == 1./(UINT_MAX+1UL) -> then returned value cannot be = 1.0
if (y) return ( (Double_t) y * 2.3283064365386963e-10); // * Power(2,-32)
return Rndm();
}

////////////////////////////////////////////////////////////////////////////////
/// Return an array of n random numbers uniformly distributed in ]0,1]
/// \brief Return an array of n random numbers uniformly distributed in ]0, 1[.

void TRandom3::RndmArray(Int_t n, Float_t *array)
{
for(Int_t i=0; i<n; i++) array[i]=(Float_t)Rndm();
}

////////////////////////////////////////////////////////////////////////////////
/// Return an array of n random numbers uniformly distributed in ]0,1]
/// \brief Return an array of n random numbers uniformly distributed in ]0, 1[.

void TRandom3::RndmArray(Int_t n, Double_t *array)
{
Expand Down Expand Up @@ -195,13 +204,15 @@ void TRandom3::RndmArray(Int_t n, Double_t *array)
}

////////////////////////////////////////////////////////////////////////////////
/// Set the random generator sequence
/// if seed is 0 (default value) a TUUID is generated and used to fill
/// the first 8 integers of the seed array.
/// \brief Set the random generator sequence.
///
/// If seed is 0 (default value) a TRandom2 (internally uses TUUID) is used to
/// generate all 624 unsigned integers of the seed array.
/// In this case the seed is guaranteed to be unique in space and time.
/// Use upgraded seeding procedure to fix a known problem when seeding with values
/// with many zero in the bit pattern (like 2**28).
/// see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
///
/// Upgraded seeding procedure is used to fix a known problem when seeding with
/// values with many zero in the bit pattern (like 2**28), see
/// http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html

void TRandom3::SetSeed(ULong_t seed)
{
Expand All @@ -217,7 +228,7 @@ void TRandom3::SetSeed(ULong_t seed)

} else {

// use TRandom2 (which is based on TUUId to generate the seed
// use TRandom2 (which is based on TUUID to generate the seed.
// TRandom2 works fairly well and has been tested against example
// layout in https://savannah.cern.ch/bugs/?99516
TRandom2 r(0);
Expand All @@ -232,7 +243,7 @@ void TRandom3::SetSeed(ULong_t seed)
}

////////////////////////////////////////////////////////////////////////////////
/// Stream an object of class TRandom3.
/// \brief Streamer for an object of class TRandom3.

void TRandom3::Streamer(TBuffer &R__b)
{
Expand Down