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