Repeating simulations from older versions of GAUSS

Introduction

Starting in GAUSS version 12, a new suite of random number generators was introduced. GAUSS now contains several options of high quality and high-performance random number generators (RNG), such as:

  • The Mersenne-Twister (MT-19937, SFMT-19937 and MT-2208).
  • Pierre L'ECuyer's MRG32K3a.
  • Niederreiter and Sobol quasi-random number generators.

GAUSS version 11 and older used a linear congruential generator (LCG) by default. LCG's were fine for their time, but have been superseded by higher quality RNG's such as those mentioned above.

How do I reproduce my simulations?

While new projects should always use one of the modern RNG's, it is sometimes necessary to exactly reproduce some work from the past. GAUSS has retained a set of LCG's, such as, rndLCGam, rndLCBeta, rndLCn, rndLCu and rndLCi. These functions will allow you to reproduce the random numbers from older GAUSS versions for many distributions.

However, while rndLCn does compute normally distributed random numbers, it will not match those from GAUSS version 10 and before. In GAUSS version 11 an improvement to the method for transforming the uniform random numbers created by the underlying LCG was implemented in rndn.

How do I reproduce rndn from GAUSS 10 and older?

In order to allow GAUSS users to reproduce the rndn output from older versions of GAUSS, a new function was added to GAUSS version 18. The new function is _rndng10.

rndseed 777;
x =  _rndng10(5,1);
print x;
      0.80449208
      0.83614293
     -0.32917873
     -0.47774279
      0.22364814 

As you can see it works in exactly the same manner as rndn did.

Don't just replace rndn with _rndng10

While some of you may be tempted to find-and-replace rndn with _rndng10, you should not do this for a couple of reasons.

  1. _rndng10 is available to repeat simulations run in the past. It is still inferior to the RNG used by the modern rndn.

  2. The code will be less portable. It will not work in a version of GAUSS older than GAUSS 18.

Swap random number generators with a define

You can think of #define as an instruction to GAUSS to replace all instances of one thing with another during the compile phase before the program is run. This will not change the code in the file, just how GAUSS interprets it.

In our case, we want to replace all instances of rndn with _rndng10. We can do that like this:

#define rndn _rndng10

rndseed 777;
x = rndn(5,1);
print x;
      0.80449208
      0.83614293
     -0.32917873
     -0.47774279
      0.22364814

Make it portable with #ifminkernelversion

The #define is a quick and convenient way to swap out rndn for _rndng10. However, it is still not portable. It will not run on any version of GAUSS that does not have the rndng10 function (version 17 and older).

While you could just comment it out #ifminkernelversion is a better option. #ifminkernelversion is another preprocessor (i.e. before run-time) command. It tells GAUSS to include specific code ONLY if using a certain version of GAUSS or newer.

// If we are using GAUSS 18 or newer
// replace rndn with _rndng10
#ifminkernelversion(18)
    #define rndn _rndng10
#endif

rndseed 777;
x = rndn(5,1);
print x;
      0.80449208
      0.83614293
     -0.32917873
     -0.47774279
      0.22364814

Conclusion

In this post, we have learned that:

  • The GAUSS random number generators were upgraded in versions 11 and 12.
  • How to swap between the older and newer versions of rndn in a convenient and portable manner.

Code and data from this blog can be found here.

Leave a Reply