This library provides several pseudo-random number generators. The
quality of a pseudo-random number generator crucially depends on both
the algorithm and its parameters. This library implements the
algorithms as class templates with template value parameters, hidden
in namespace boost::random. Any particular choice of
parameters is represented as the appropriately specializing
typedef in namespace boost.

Pseudo-random number generators should not be constructed
(initialized) frequently during program execution, for two reasons.
First, initialization requires full initialization of the internal
state of the generator. Thus, generators with a lot of internal state
(see below) are costly to initialize. Second, initialization always
requires some value used as a "seed" for the generated sequence. It
is usually difficult to obtain several good seed values. For example,
one method to obtain a seed is to determine the current time at the
highest resolution available, e.g. microseconds or nanoseconds. When
the pseudo-random number generator is initialized again with the
then-current time as the seed, it is likely that this is at a
near-constant (non-random) distance from the time given as the seed
for first initialization. The distance could even be zero if the
resolution of the clock is low, thus the generator re-iterates the
same sequence of random numbers. For some applications, this is
inappropriate.

Note that all pseudo-random number generators described below are
CopyConstructible and Assignable. Copying or assigning a generator
will copy all its internal state, so the original and the copy will
generate the identical sequence of random numbers. Often, such
behavior is not wanted. In particular, beware of the algorithms from
the standard library such as std::generate. They take a functor
argument by value, thereby invoking the copy constructor when called.

The following table gives an overview of some characteristics of the
generators. The cycle length is a rough estimate of the quality of
the generator; the approximate relative speed is a performance
measure, higher numbers mean faster random number generation.

As observable from the table, there is generally a
quality/performance/memory trade-off to be decided upon when choosing
a random-number generator. The multitude of generators provided in
this library allows the application programmer to optimize the
trade-off with regard to his application domain. Additionally,
employing several fundamentally different random number generators for
a given application of Monte Carlo simulation will improve the
confidence in the results.

If the names of the generators don't ring any bell and you have no
idea which generator to use, it is reasonable to employ
mt19937 for a start: It is fast and has acceptable
quality.

Note: These random number generators are not intended for use
in applications where non-deterministic random numbers are required.
See nondet_random.html for a choice
of (hopefully) non-deterministic random number generators.

In this description, I have refrained from documenting those members
in detail which are already defined in the
concept documentation.

Let x(n) denote the sequence of numbers returned by
some pseudo-random number generator. Then for the linear congruential
generator, x(n+1) := (a * x(n) + c) mod m. Parameters for the
generator are x(0), a, c, m.
The template parameter IntType shall denote an
integral type. It must be large enough to hold values a, c, and m.
The template parameters a and c must be smaller than m.

Note: The quality of the generator crucially depends on the
choice of the parameters. User code should use one of the sensibly
parameterized generators such as minstd_rand instead.
For each choice of the parameters a, c, m, some distinct type is
defined, so that the static members do not interfere with
regard to the one definition rule.

Description

Class rand48 models a
pseudo-random number
generator. It uses the linear congruential algorithm with the
parameters a = 0x5DEECE66D, c = 0xB, m = 2**48. It delivers identical
results to the lrand48() function available on some
systems (assuming lcong48 has not been called).

It is only available on systems where uint64_t is
provided as an integral type, so that for example static in-class
constants and/or enum definitions with large uint64_t
numbers work.

Description

Instatiations of class template shuffle_output model a
pseudo-random number
generator. It mixes the output of some (usually linear
congruential) uniform random number generator to get better
statistical properties. According to Donald E. Knuth, "The Art of
Computer Programming, Vol. 2", the algorithm is described in

The output of the base generator is buffered in an array of length
k. Every output X(n) has a second role: It gives an index into the
array where X(n+1) will be retrieved. Used array elements are
replaced with fresh output from the base generator.

Template parameters are the base generator and the array length k,
which should be around 100. The template parameter
val is the validation value checked by
validation.

Members

shuffle_output()

Effects: Constructs a shuffle_output
generator by invoking the default constructor of the base generator.

Complexity: Exactly k+1 invocations of the base
generator.

template<class T> explicit shuffle_output(T seed)

Effects: Constructs a shuffle_output
generator by invoking the one-argument constructor of the base
generator with the parameter seed.

The output sequence is defined by x(n+1) = (a*inv(x(n)) - b) (mod p),
where x(0), a, b, and the prime number p are parameters of the
generator. The expression inv(k) denotes the multiplicative inverse
of k in the field of integer numbers modulo p, with inv(0) := 0.

The template parameter IntType shall denote a signed
integral type large enough to hold p; a, b, and p are the parameters
of the generators.

Note: The implementation currently uses the Euclidian
Algorithm to compute the multiplicative inverse. Therefore, the
inversive generators are about 10-20 times slower than the others (see
section"performance"). However, the paper
talks of only 3x slowdown, so the Euclidian Algorithm is probably not
optimal for calculating the multiplicative inverse.

Members

inversive_congruential(IntType y0 = 1)

Effects: Constructs an
inversive_congruential generator with
y0 as the initial state.

Note: The boost variant has been implemented from scratch
and does not derive from or use mt19937.c provided on the above WWW
site. However, it was verified that both produce identical output.
The quality of the generator crucially depends on the choice of the
parameters. User code should employ one of the sensibly parameterized
generators such as mt19937 instead.
The generator requires considerable amounts of memory for the storage
of its state array. For example, mt11213b requires about
1408 bytes and mt19937 requires about 2496 bytes.

Constructors

mersenne_twister()

Effects: Constructs a mersenne_twister
and calls seed().

explicit mersenne_twister(result_type value)

Effects: Constructs a mersenne_twister
and calls seed(value).

template<class Generator> explicit mersenne_twister(Generator & gen)

Effects: Constructs a mersenne_twister
and calls seed(gen).

Note: When using direct-initialization syntax with an lvalue
(e.g. in the variable definition Gen gen2(gen);), this
templated constructor will be preferred over the compiler-generated
copy constructor. For variable definitions which should copy the
state of another mersenne_twister, use e.g. Gen
gen2 = gen;, which is copy-initialization syntax and guaranteed
to invoke the copy constructor.

Effects: Sets the state of this
mersenne_twister to the values returned by n
invocations of gen.

Complexity: Exactly n invocations of
gen.

Note: When invoking seed with an lvalue,
overload resolution chooses the function template unless the type of
the argument exactly matches result_type. For other
integer types, you should convert the argument to
result_type explicitly.

Note: The quality of the generator crucially depends on the
choice of the parameters. User code should employ one of the sensibly
parameterized generators such as lagged_fibonacci607
instead.
The generator requires considerable amounts of memory for the storage
of its state array. For example, lagged_fibonacci607
requires about 4856 bytes and lagged_fibonacci44497
requires about 350 KBytes.

Specializations

The test program random_speed.cpp
measures the execution times of the
random.hpp implementation of the above
algorithms in a tight loop. The performance has been evaluated on a
Pentium Pro 200 MHz with gcc 2.95.2, Linux 2.2.13, glibc 2.1.2.