# Uniform random number generators

by Agner Fog

randomc.zip contains a C++ class library of uniform random number generators of good quality.

The random number generators found in standard libraries are often of a poor quality, insufficient for large Monte Carlo calculations. This C++ implementation provides random number generators of a much better quality: Better randomness, higher resolution, and longer cycle lengths.

The same random number generators are available as libraries coded in assembly language for higher speed. These libraries can be linked into projects coded in other programming languages under Windows, Linux, BSD, etc. The library files are available in the archive randoma.zip.

Non-uniform random number generators are provided in stocc.zip.

## File list

The archive randomc.zip contains the following files:

randomc.htm
  This file. Instructions.
randomc.h
  C++ header file containing class definitions.
  You must `#include` this in all C++ files that use this library.
mersenne.cpp
  Random number generator of type Mersenne twister.
ranrotb.cpp
  Random number generator of type RANROT-B.
ranrotw.cpp
  Random number generator of type RANROT-W.
mother.cpp
  Random number generator of type Mother-of-all (multiply with carry).
rancombi.cpp
  Template class for combining any two of these random number generators.
ex-ran.cpp
  Example showing how to use these random number generators.

## Quality of randomness

All these random number generators provide excellent randomness and extremely long cycle lengths.

For all but the most demanding applications it doesn't matter which of the random number generators you use. The Mersenne twister is the one that is best understood theoretically. For this reason it is recommended by leading experts. The RANROT generators have a more chaotic behavior which is difficult to analyze theoretically, and hence maybe also more random in the sense that it has no mathematical regularity that might interfere with the structure of your application. The Mother-of-all generator has the highest bifurcation of these generators.

For the most demanding scientific applications you may combine any two of these generators.

## Technical quality

The technical qualities of these generators are compared in the table below. If you want to simulate very low probabilities with high accuracy then it is recommended to use a generator with a high resolution. If speed is important then use a generator that uses a low number of clock cycles. The amount of data cache used influences execution speed if the total amount of data handled by the critical part of your program exceeds the size of the level-1 cache in your microprocessor. A low cache use means faster execution. The same applies to the code cache use if the critical part of your program uses more than the available cache size.

Generator type | coding language | resolution bits | time consumption, clock cycles | data cache use, bytes | code cache use, bytes
bits | integer | float | hi.res. float
RANROT B | C++ | 32 |  | 282 | 96 |  | 164 | 350
RANROT W | C++ | 52 or 63 | 61 | 306 |  | 118 | 164 | 400
RANROT W | ASM | 63 | 22 | 67 |  | 77 | 160 | 200
Mother-of-all | C++ | 32 |  | 306 | 189 |  | 48 | 220
Mother-of-all | ASM | 32 | 74 | 96 | 146 |  | 48 | 170
Mersenne Twister | C++ | 32 | 38 | 258 | 91 |  | 1476 | 450
Mersenne Twister | ASM | 32 - 63 | 24 | 44 | 65 | 81 | 1472 | 600
Combined RANROT-W+ Mother-off-all | ASM | 63 | 89 | 134 |  | 130 | 224 | 300

The number of clock cycles are approximate values for a Pentium 4 microprocessor under optimal caching conditions. A count of 100 clock cycles means that you can generate 10 million random numbers per second on a 1 GHz computer.

## Instructions

Choose which one of the random number generators mentioned above you want to use.

Write `#include "randomc.h"` in any C++ file that uses one of these random number generators.

Add the appropriate cpp file to your project, either as an `#include` or as a separate module.

Make an instance (object) of the appropriate class. It needs an integer seed as initializer.

The seed can be any integer, positive, negative or zero. Repeating the calculations with the same seed will produce the same sequence of random numbers. A different seed will give different random numbers. You may use the time in seconds or milliseconds as seed.

You don't need more than one instance of the random number generator unless you have multiple threads. If, for any reason, you want more than one instance then make sure they don't have the same seed. You may, for example, add 1 to the seed for each new instance.

The file ex-ran.cpp contains an example of how to do. Try it!

## Portability

The C++ class library is supposed to work with all C++ compilers and all operating systems. It has been tested on several different systems.

There are, however, a few system differences that you need to be aware of:

1. Floating point representation. Most systems store floating point numbers according to the IEEE-754 standard with 64 bits or 80 bits storage. The fast conversion to floating point relies on this standard format. A slightly less efficient method is used when floating point numbers are not stored in a recognized format.
2. Long double precision. The Mother-of-all generator and the RANROT-W generator require long double precision (80 bits storage). Not all microprocessors and compilers support this precision. A standard PC running Windows or Linux supports the long double precision when the program is compiled with a Borland or Gnu compiler. The Microsoft C++ compiler (Visual C++) does not support long double precision. The Mother-of-all generator coded in C++ will not work without long double precision. The RANROT-W generator will work, but with lower resolution and a different random number sequence. The RANROT-W generator coded in assembly does not require long double precision.
3. Rotate function. The RANROT-B and RANROT-W generators use a rotate function `_lrotl()`. Some compilers have this as a built-in function. For other compilers you need to define it. A code for this function is given in the files ranrotb.cpp and ranrotw.cpp. If your compiler has the built-in function then remove or comment out this function.

## Theory

The theory of the Mersenne twister is given in the article:
M. Matsumoto & T. Nishimura: "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number Generator". ACM Transactions on Modeling and Computer Simulation, vol. 8, no. 1, 1998, pp. 3-30. See also http://www.math.sci.hiroshima-u.ac.jp/~m-mat/eindex.html.

The theory of Mother-of-All generators is given in George Marsaglia's DIEHARD package, see stat.fsu.edu/~geo/diehard.html or www.cs.hku.hk/internet/randomCD.html.

The theory of RANROT generators is given at www.agner.org/random/theory/.

## General public license

© 1997, 2004 by Agner Fog under GNU General Public License. You may contact me for commercial licenses.

Back to random number generators page.