by Agner Fog
randomc 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.
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.
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.
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 |
time
consumption, clock cycles |
data cache use, bytes |
code cache use, bytes |
|||
bits |
integer |
float |
hi.res. |
|||||
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 |
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.
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!
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:
_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.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/.
© 1997, 2004 by Agner Fog under GNU General Public License. You may contact me for commercial licenses.