1The \eslmod{random} module contains routines for generating uniformly
2distributed pseudorandom numbers and sampling random deviates from
3distributions. The heart of the module is the \ccode{esl\_random()}
4pseudorandom number generator.
5
6The \ccode{esl\_random()} random number generator is portable,
7reentrant, and threadsafe. It gives reproducible results on all
8platforms.
9
10The default \ccode{esl\_random()} generator implements the Mersenne
11Twister algorithm MT19937 \citep{Matsumoto98}. MT19937 has strong
12properties, including a period of $2^{19937}-1$ and equidistribution
13over $2^{32}$ values. The default Mersenne Twister should be suitable
14for all but a few speed-critical applications.
15
16Alternatively, a simple and classic linear congruential generator
17(LCG) can be chosen \citep{Knu-81a}. The LCG is much faster to
18initialize (about 20x) and somewhat faster to generate samples (about
1925\%), while still generating pseudorandom numbers suitable for most
20applications. Because of its initialization speed, the LCG is
21advantageous when a small number of reasonably random samples is
22needed in a speed-critical application. However, it has a relatively
23short period ($2^32$), making it unsuitable for large simulations.
24
25A new generator can either be seeded with a number that you provide,
26or using an arbitrary (quasirandom) seed. If you seed it yourself, you
27can guarantee reproducibility: two generators seeded with the same
28seed will give exactly the same sequence, even on different hardware
29platforms and operating systems. If you let it seed itself
30arbitrarily, you will get different sequences. Multiple instances of
31running the same program will get quite different arbitrary seeds even
32if you start them at the same time.
33
34Bit streams from \ccode{esl\_random()}'s two generators were tested
35against a National Institute of Standards and Technology statistical
36benchmark for random number generators \citep{NIST08}.  The default
37Mersenne Twister passes the benchmark suite as expected
38\citep{Matsumoto98}. The fast LCG passes most but not all of the NIST
39tests.
40
41\ccode{esl\_random()} returns a double-precision floating point sample
42on the interval $0.0 \leq x < 1$.
43
44Table~\ref{tbl:random_api} lists the functions in the \eslmod{random}
45API. The module implements one object, \ccode{ESL\_RANDOMNESS}, which
46contains state information for the random number generator.  This
47makes random number generation reentrant and threadsafe. You can have
48more than one active generator and they will not interfere with each
49other. The object is meant to be opaque; you should not need to use
50its contents.
51
52
53
54
55% Table generated by autodoc -t esl_random.c (so don't edit here, edit esl_random.c:)
56\begin{table}[hbp]
57\begin{center}
58{\small
59\begin{tabular}{|ll|}\hline
60\apisubhead{The \ccode{ESL\_RANDOMNESS} object.}\\
61\hyperlink{func:esl_randomness_Create()}{\ccode{esl\_randomness\_Create()}} & Create an RNG with a given seed.\\
62\hyperlink{func:esl_randomness_CreateFast()}{\ccode{esl\_randomness\_CreateFast()}}& Create a fast RNG with a given seed.\\
63\hyperlink{func:esl_randomness_Destroy()}{\ccode{esl\_randomness\_Destroy()}} & Free an RNG.            \\
64\hyperlink{func:esl_randomness_Init()}{\ccode{esl\_randomness\_Init()}} & Reinitialize an RNG.           \\
65\hyperlink{func:esl_randomness_GetSeed()}{\ccode{esl\_randomness\_GetSeed()}} & Returns the value of RNG's seed.\\
66\apisubhead{The generator, \ccode{esl\_random()}}\\
67\hyperlink{func:esl_random()}{\ccode{esl\_random()}} & Generate a uniform random deviate $0.0 <= x < 1.0$.
68\\
69\apisubhead{Other fundamental sampling (including Gaussian, gamma)}\\
70\hyperlink{func:esl_rnd_UniformPositive()}{\ccode{esl\_rnd\_UniformPositive()}} & Generate a uniform positive random deviate $0 < x < 1$.\\
71\hyperlink{func:esl_rnd_Gaussian()}{\ccode{esl\_rnd\_Gaussian()}} & Generate a Gaussian-distributed sample.\\
72\hyperlink{func:esl_rnd_Gamma()}{\ccode{esl\_rnd\_Gamma()}} & Returns a random deviate from a Gamma(a, 1) distribution.\\
73\apisubhead{Multinomial sampling from discrete probability n-vectors}\\
74\hyperlink{func:esl_rnd_DChoose()}{\ccode{esl\_rnd\_DChoose()}} & Return random choice from discrete multinomial distribution.
75\\
76\hline
77\end{tabular}
78}
79\end{center}
80\caption{The \eslmod{random} API.}
81\label{tbl:random_api}
82\end{table}
83
84\subsection{Example of using random}
85
86Figure~\ref{fig:random_example} shows a program that initializes the
87random number generator with a seed you provide on the command line,
88then samples 10 random numbers using \ccode{esl\_random()}.
89
90\begin{figure}
91\input{cexcerpts/random_example}
92\caption{An example of using the random number generator.}
93\label{fig:random_example}
94\end{figure}
95
96When a \ccode{ESL\_RANDOMNESS} object is created with
97\ccode{esl\_randomness\_Create()}, it needs to be given a \emph{seed},
98an integer $\geq 0$, which specifies the initial state of the
99generator. After a generator is seeded, it is typically never seeded
100again. A series of \ccode{esl\_random()} calls generates a
101pseudorandom number sequence from that starting point. If you create
102two \ccode{ESL\_RANDOMNESS} objects seeded identically, they are
103guaranteed to generate the same random number sequence on all
104platforms. This makes it possible to reproduce stochastic simulations.
105Thus, if you run the example multiple times, you get the same ten
106numbers, because the generator is always seeded with 42.
107
108Often one wants different runs to generate different random number
109sequences, which creates a chicken and the egg problem: how can we
110select a pseudorandom seed for the pseudorandom number generator?
111Calling \ccode{esl\_randomness\_Create(0)} (i.e., a seed argument of
1120) causes Easel to select an arbitrary seed. The arbitrary seed is
113constructed by a combination of the current wall clock time (in
114seconds), the elapsed cpu time since starting the program (in
115milliseconds or microseconds), and (if available) the process
116id.\footnote{Specifically, by a bitwise mixing function that combines
117  input from \ccode{time()}, \ccode{clock()}, and \ccode{getpid()}. On
118  some platforms, \ccode{getpid()} is not available, and an arbitrary
119  constant is used instead; on those platforms, arbitrary seeds are a
120  little less arbitrary, but are still quite randomly distributed.  It
121  is improbable to get two generators with the same arbitrary seed; to
122  try, you would have to start two generators in the same process at
123  the same time.} Two different \ccode{ESL\_RANDOMNESS} objects
124created this way are expected to always produce different pseudorandom
125number sequences.
126
127
128