EARandom.html 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>
  2. <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  3. <title>EARandom</title>
  4. <link type="text/css" rel="stylesheet" href="UTFDoc.css">
  5. <meta name="author" content="Paul Pedriana">
  6. </head>
  7. <body bgcolor="#FFFFFF">
  8. <h1>EARandom</h1>
  9. <h2>Introduction</h2>
  10. <p>EARandom provides pseudo-random number generation suitable for most kinds of
  11. professional game development. Functionality is divided into two modules:</p>
  12. <ul>
  13. <li>Core random number generation (e.g. random integer, random float)</li>
  14. <li>Variable distribution generation (e.g. Gaussian distribution, triangle distribution)</li>
  15. </ul>
  16. <p>EARandom provides two core generators which address a speed/randomness tradeoff:</p>
  17. <ul>
  18. <li> RandomLinearCongruential (very fast, also known as RandomFast, but still good randomness)</li>
  19. <li>RandomMersenneTwister (very random, also known as RandomQuality)</li>
  20. </ul>
  21. <p>EARandom provides a number of distribution generators, each of which uses the
  22. above core generators underneath:</p>
  23. <ul>
  24. <li>RandomBool</li>
  25. <li>Random2, Random4, Random8, ... Random256</li>
  26. <li>RandomInt32UniformRange</li>
  27. <li>RandomDoubleUniformRange</li>
  28. <li>RandomUint32WeightedChoice</li>
  29. <li>RandomUint32Gaussian</li>
  30. <li>RandomUint32Triangle</li>
  31. </ul>
  32. <p><i>Note: EARandom is not certified nor suitable for use in certified gambling
  33. software. There are strict standards regarding such software which EARandom
  34. does not try to comply with. Similarly, EARandom is not suitable for use in security-related entropy collection (at least not by itself). EARandom's goal is to provide good random number
  35. generation with high efficiency.</i></p>
  36. <h2>Don't use the C rand() function!</h2>
  37. <p> The C library rand function does an OK job as a basic random number generator
  38. for testing and hobby purposes. However, the rand function is generally not
  39. suitable for professional game software. This is because the rand function:</p>
  40. <ul>
  41. <li>Generates only numbers between 0 and RAND_MAX, which is usually 32767.</li>
  42. <li>Doesn't generate random numbers within a prescribed range. Using the % operator
  43. to rectify this is slow (requires integer division) and produces a lopsided
  44. distribution unless the divisor is evenly divisible into RAND_MAX.</li>
  45. <li>Generates rather poor random numbers. In particular, they tend to have obvious
  46. patterns in the low bits. In some cases this can result in users taking advantage
  47. of the number generator at the expense of other players or your game franchise
  48. itself.</li>
  49. <li>Exists only as a single instance of a generator which is shared with the
  50. entire application. There is no way to make another instance.</li>
  51. <li>Is slow. Generating a random number via rand() was measured as 70% slower
  52. than the EARandom generator on modern hardware.</li>
  53. <li>Doesn't generate floating point numbers.</li>
  54. </ul>
  55. <h2>How random is EARandom?</h2>
  56. <p>Both RandomLinearCongruential (i.e. RandomFast) and RandomMersenneTwister (RandomQuality) provide randomness that is likely good enough for most convential game uses. Don't be fooled by the &quot;linear congruential&quot; name; it's not the bad generator that you might think based on what you've read about old C rand implementations. </p>
  57. <p>A good way to test randomness is with the DieHard randomness tests. See http://en.wikipedia.org/wiki/Diehard_tests for information about DieHard. We have a copy of the <a href="http://eaos.rws.ad.ea.com:8080/@md=d&cd=//EAOS/UTF/DL/UTFResearch/DieHard%20Random%20Number%20Tester/&c=2lr@//EAOS/UTF/DL/UTFResearch/DieHard%20Random%20Number%20Tester/bin/?ac=83">DieHard tester in EAOS</a> which is used to test EARandom and could test any other random number generator. EARandom produces DieHard scores which are pretty good. A number of home-grown random number generators have shown much worse results. </p>
  58. <h2>Common misuses</h2>
  59. <p>It is worth mentioning that it is surprisingly common for users of random number
  60. generators (including EARandom) to come to the belief that the generator is
  61. broken when in fact they are misusing the generator. Common misuses of generators
  62. include:</p>
  63. <ul>
  64. <li>Seeding a generator with the same seed every time it's used.</li>
  65. <li>Seeding two generators at the same time via the system clock and finding
  66. that they produce idential values.</li>
  67. <li>Using 'RandomUint32Uniform() % 5000' instead of 'RandomUint32Uniform(5000)'.</li>
  68. <li>Inventing flawed distribution generators.</li>
  69. <li>Misusing the results of a generator but assuming the generator is yielding
  70. bad values.</li>
  71. <li>Creating a random number generator for a single use right when it is needed.
  72. This is usually bad because the first generated value is no more random than
  73. the seed used to generate the number.</li>
  74. </ul>
  75. <h2>Example usage </h2>
  76. <p>EARandom is fairly straightforward to use. Just avoid the above common mistakes
  77. and things should work well.</p>
  78. <p>Mixed integer math expressions.</p>
  79. <pre class="code-example">EA::RandomFast rng(GetCPUTick()); <span class="code-example-comment">// Seed with a hypthetical CPU tick function.</span>
  80. uint32_t n = rng.RandomUint32Uniform(); <span class="code-example-comment">// Generate value in the range of [0, 0xffffffff] (all bit patterns).</span>
  81. uint32_t i = rng.RandomUint32Uniform(200); <span class="code-example-comment">// Generate value in the range of [0, 200).</span>
  82. double d = rng.RandomDoubleUniform(); <span class="code-example-comment">// Generate value in the range of [0, 1).</span>
  83. double f = rng.RandomDoubleUniform(37); <span class="code-example-comment">// Generate value in the range of [0, 37).</span></pre>
  84. How to use EARandom with STL (including EASTL).
  85. <pre class="code-example">#include &lt;algorithm&gt;
  86. #include &lt;vector&gt;
  87. std::vector v;
  88. EA::RandomFast rng;
  89. std::random_shuffle(v.begin(), v.end(), rng);</pre>
  90. How to use basic random distributions. Note that these functions take a random number generator as an argument.
  91. <pre class="code-example">EA::RandomQuality rng;
  92. bool b = EA::RandomBool(rng);
  93. int32_t n = EA::Random256(rng);
  94. double d = EA::RandomDoubleGaussian(rng, 15.0, 30.0);</pre>
  95. <p>How to use RandomUint32WeightedChoice. This function is useful for generating
  96. a custom distribution.</p>
  97. <pre class="code-example">EA::RandomQuality rng;
  98. const float weights[10] = { 1, 2, 3, 4, 5, 5, 4, 3, 2, 1 }; // Create a triangle distribution
  99. uint32_t i = EA::RandomUint32WeightedChoice(rng, 10, weights); </pre>
  100. <h2>Interface</h2>
  101. <h3>RandomLinearCongruential</h3>
  102. <p>This algorithm generates good enough pseudorandom numbers for most simulationuses.
  103. Its biggest weakness is that there are some patterns that occur in the lower
  104. bits. However, it is still far better than the C rand function. </p>
  105. <pre class="code-example">class RandomLinearCongruential
  106. {
  107. public:
  108. typedef uint32_t result_type;
  109. <span class="code-example-comment"> /// RandomLinearCongruential
  110. /// Constructs the random number generator with a given initial state (seed).
  111. /// If the seed is 0xffffffff (MAX_UINT32), then the seed is generated automatically
  112. /// by a semi-random internal mechanism such as reading the system clock. Note that
  113. /// seeding by this mechanism can yield unexpected poor results if you create multiple
  114. /// instances of this class within a short period of time, as they will all get the
  115. /// same seed due to the system clock having not advanced.
  116. </span> RandomLinearCongruential(uint32_t nSeed = 0xffffffff);
  117. <span class="code-example-comment"> /// RandomLinearCongruential
  118. /// Copy constructor
  119. </span> RandomLinearCongruential(const RandomLinearCongruential& randomLC);
  120. <span class="code-example-comment"> /// operator =
  121. </span> RandomLinearCongruential& operator=(const RandomLinearCongruential& randomLC);
  122. <span class="code-example-comment"> /// GetSeed
  123. /// Gets the state of the random number generator, which can be entirely
  124. /// defined by a single uint32_t.
  125. </span> uint32_t GetSeed() const;
  126. <span class="code-example-comment"> /// SetSeed
  127. /// Sets the current state of the random number generator, which can be
  128. /// entirely defined by a single uint32_t.
  129. </span> void SetSeed(uint32_t nSeed = 0xffffffff);
  130. <span class="code-example-comment"> /// operator ()
  131. /// Generates a random uint32 with an optional limit. Acts the same as the
  132. /// RandomUint32Uniform(uint32_t nLimit) function. This function is useful for
  133. /// some templated uses whereby you want the class to act as a function object.
  134. /// If the input nLimit is 0, then the return value is from 0 to MAX_UINT32 inclusively.
  135. </span> uint32_t operator()(uint32_t nLimit = 0);
  136. <span class="code-example-comment"> /// RandomUint32Uniform
  137. /// Return value is from 0 to MAX_UINT32 inclusively, with uniform probability.
  138. /// This is the most basic random integer generator for this class; it has no
  139. /// extra options but is also the fastest. Note that if you want a random
  140. /// integer between 0 and some value, you should use RandomUint32Uniform(nLimit)
  141. /// and not use RandomUint32Uniform() % nLimit. The former is both faster and
  142. /// more random; using % to achieve a truly random distribution fails unless
  143. /// nLimit is evenly divisible into MAX_UINT32.
  144. </span> uint32_t RandomUint32Uniform();
  145. <span class="code-example-comment"> /// RandomUint32Uniform (with limit)
  146. /// Return value is from 0 to nLimit-1 inclusively, with uniform probability.
  147. </span> uint32_t RandomUint32Uniform(uint32_t nLimit);
  148. <span class="code-example-comment"> /// RandomDoubleUniform
  149. /// Output is in range of [0, 1) with uniform distribution.
  150. </span> double RandomDoubleUniform();
  151. <span class="code-example-comment"> /// RandomDoubleUniform (with limit)
  152. /// Output is in range of [0, limit) with uniform distribution.
  153. </span> double RandomDoubleUniform(double limit);
  154. };
  155. </pre>
  156. <h3>RandomTaus</h3>
  157. <p> RandomTaus is slower than the other EARandom generators but has only 12 bytes of state data. RandomLinearCongruental has only 4 bytes of data but is not as random as RandomTaus. RandomMersenneTwister is more random than RandomTaus but has about 2500 bytes of state data. Thus RandomTaus is a tradeoff. This generator optimizes randomness and and to some degree size at the cost of speed.</p>
  158. <pre class="code-example">class RandomTaus
  159. {
  160. public:
  161. typedef uint32_t result_type;
  162. RandomTaus(uint32_t nSeed = 0xffffffff);
  163. RandomTaus(const uint32_t* pSeedArray); <span class="code-example-comment">// Array of 3 uint32_t values.</span>
  164. RandomTaus(const RandomTaus&amp; randomT);
  165. RandomTaus&amp; operator=(const RandomTaus&amp; randomT);
  166. <span class="code-example-comment"> // Single uint32_t version, for compatibility.
  167. // Use the seed array version for best behavior.
  168. // Not guaranteed to return the uint32_t set by SetSeed(uint32_t).
  169. </span> uint32_t GetSeed() const;
  170. void SetSeed(uint32_t nSeed = 0xffffffff);
  171. void GetSeed(uint32_t* pSeedArray) const; <span class="code-example-comment">// Array of 3 uint32_t values.</span>
  172. void SetSeed(const uint32_t* pSeedArray); <span class="code-example-comment">// Array of 3 uint32_t values.</span>
  173. <span class="code-example-comment"> /// Output is in range of [0, nLimit) with uniform distribution.
  174. </span> uint32_t operator()(uint32_t nLimit = 0);
  175. <span class="code-example-comment"> /// Output is in range of [0, UINT32_MAX] with uniform distribution.
  176. </span> uint32_t RandomUint32Uniform();
  177. <span class="code-example-comment"> /// Output is in range of [0, nLimit) with uniform distribution.
  178. </span> uint32_t RandomUint32Uniform(uint32_t nLimit);
  179. <span class="code-example-comment"> /// Output is in range of [0, 1) with uniform numeric (not bit) distribution.
  180. </span> double RandomDoubleUniform();
  181. <span class="code-example-comment"> /// Output is in range of [0, limit) with uniform numeric (not bit) distribution.
  182. /// limit is a value &gt; 0.
  183. </span> double RandomDoubleUniform(double limit);<br><span class="code-example-comment"></span>};</pre>
  184. <h3>RandomMersenneTwister</h3>
  185. <p>This algorithm implements a random number generator via the Mersenne Twister
  186. algorithm. This algorithm is popular for its very high degree of randomness
  187. (period of 2^19937-1 with 623-dimensional equidistribution) while achieving
  188. good speed.</p>
  189. <pre class="code-example">class RandomMersenneTwister
  190. {
  191. public:
  192. typedef uint32_t result_type;
  193. <span class="code-example-comment"> /// enum SeedArray
  194. /// This enum is public because it allows the user to know how much
  195. /// data or space to provide for the GetSeed and SetSeed functions.
  196. </span> enum SeedArray { kSeedArrayCount = 624 };
  197. RandomMersenneTwister(uint32_t nSeed = 0xffffffff);
  198. RandomMersenneTwister(const uint32_t seedArray[], unsigned nSeedArraySize);
  199. RandomMersenneTwister(const RandomMersenneTwister& randomMT);
  200. RandomMersenneTwister& operator=(const RandomMersenneTwister& randomMT);
  201. void GetSeed(uint32_t seedArray[], unsigned nSeedArraySize) const;
  202. void SetSeed(const uint32_t seedArray[], unsigned nSeedArraySize);
  203. void SetSeed(uint32_t nSeed = 0xffffffff);
  204. uint32_t operator()(uint32_t nLimit = 0);
  205. uint32_t RandomUint32Uniform();
  206. uint32_t RandomUint32Uniform(uint32_t nLimit);
  207. double RandomDoubleUniform();
  208. double RandomDoubleUniform(double limit);
  209. };</pre>
  210. <h3>Random distributions</h3>
  211. <p>Here is a list of the currently provided distribution functions.</p>
  212. <pre class="code-example"><span class="code-example-comment">/// RandomBool
  213. /// Returns true or false.
  214. </span>template &lt;typename Random&gt;
  215. bool RandomBool(Random& r);
  216. <span class="code-example-comment">/// Random2
  217. /// Returns a value between 0 and 1, inclusively.
  218. </span>template &lt;typename Random&gt;
  219. int32_t Random2(Random& r);
  220. <span class="code-example-comment">/// Random4
  221. /// Returns a value between 0 and 3, inclusively.
  222. </span>template &lt;typename Random&gt;
  223. int32_t Random4(Random& r);
  224. <span class="code-example-comment">/// Random8
  225. /// Returns a value between 0 and 7, inclusively.
  226. </span>template &lt;typename Random&gt;
  227. int32_t Random8(Random& r);
  228. <span class="code-example-comment">/// Random16
  229. /// Returns a value between 0 and 15, inclusively.
  230. </span>template &lt;typename Random&gt;
  231. int32_t Random16(Random& r);
  232. <span class="code-example-comment">/// Random32
  233. /// Returns a value between 0 and 31, inclusively.
  234. </span>template &lt;typename Random&gt;
  235. int32_t Random32(Random& r);
  236. <span class="code-example-comment">/// Random64
  237. /// Returns a value between 0 and 63, inclusively.
  238. </span>template &lt;typename Random&gt;
  239. int32_t Random64(Random& r);
  240. <span class="code-example-comment">/// Random128
  241. /// Returns a value between 0 and 127, inclusively.
  242. </span>template &lt;typename Random&gt;
  243. int32_t Random128(Random& r);
  244. <span class="code-example-comment">/// Random256
  245. /// Returns a value between 0 and 255, inclusively.
  246. </span>template &lt;typename Random&gt;
  247. int32_t Random256(Random& r);
  248. <span class="code-example-comment">/// RandomPowerOfTwo
  249. /// Returns a value between 0 and 2 ^ nPowerOfTwo - 1, inclusively.
  250. /// This is a generalized form of the RandomN set of functions.
  251. </span>template &lt;typename Random&gt;
  252. int32_t RandomPowerOfTwo(Random& r, unsigned nPowerOfTwo);
  253. <span class="code-example-comment">/// RandomInt32UniformRange
  254. /// Return value is from nBegin to nEnd-1 inclusively, with uniform probability.
  255. </span>template &lt;typename Random&gt;
  256. int32_t RandomInt32UniformRange(Random& r, int32_t nBegin, int32_t nEnd);
  257. <span class="code-example-comment">/// RandomDoubleUniformRange
  258. /// Return value is in range of [nBegin, nEnd) with uniform probability.
  259. </span>template <class Random><class Random>&lt;typename Random&gt;
  260. double RandomDoubleUniformRange(Random& r, double begin, double end);
  261. <span class="code-example-comment">/// RandomUint32WeightedChoice
  262. /// Return value is from 0 to nLimit-1 inclusively, with probabilities proportional to weights.
  263. /// The input array weights must be of length <nlimit>. These values are used to
  264. /// determine the probability of each choice. That is, weight[i] is proportional
  265. /// to the probability that this function will return i. Negative values are ignored.
  266. /// This function is useful in generating a custom distribution.
  267. </span>template &lt;typename Random&gt;
  268. uint32_t RandomUint32WeightedChoice(Random& r, uint32_t nLimit, float weights[]);
  269. <span class="code-example-comment">/// RandomUint32Gaussian
  270. /// Return value is in the range [0, nLimit) with Gaussian (a.k.a 'normal') distribution.
  271. </span>template &lt;typename Random&gt;
  272. uint32_t RandomUint32Gaussian(Random& r, int32_t nBegin, int32_t nEnd);
  273. <span class="code-example-comment">/// RandomDoubleGaussian
  274. /// Return value is in the range [0, nLimit) with Gaussian (a.k.a 'normal') distribution.
  275. </span>template &lt;typename Random&gt;
  276. double RandomDoubleGaussian(Random& r, double nBegin, double nEnd);
  277. <span class="code-example-comment">/// RandomUint32Triangle
  278. /// Return value is in the range [0, nLimit) with triangular distribution.
  279. </span>template &lt;typename Random&gt;
  280. uint32_t RandomUint32Triangle(Random& r, int32_t nBegin, int32_t nEnd);
  281. <span class="code-example-comment">/// RandomDoubleTriangle
  282. /// Return value is in the range [0, nLimit) with triangular distribution.
  283. </span>template &lt;typename Random&gt;
  284. double RandomDoubleTriangle(Random& r, double nBegin, double nEnd);
  285. </pre>
  286. <h3>Random fills and shuffles</h3>
  287. <p>How to fill a container or sequence with random uint32_t values:</p>
  288. <pre class="code-example">#include &lt;eastl/algorithm.h&gt; <span class="code-example-comment"> // or #include &lt;algorithm&gt; to use std STL.</span>
  289. EA::StdC::Random rand(someSeedValue); <span class="code-example-comment">// We can just use EA::StdC::Random directly because</span> <br>eastl::generate(myVector.begin(), myVector.end(), rand); <span class="code-example-comment">// it has an operator() that returns uint32_t.</span></pre>
  290. <p>How to randomize (shuffle) an existing container or sequence of uint32_t values:</p>
  291. <pre class="code-example">#include &lt;eastl/algorithm.h&gt; <span class="code-example-comment"> // or #include &lt;algorithm&gt; to use std STL.</span>
  292. EA::StdC::Random rand(someSeedValue);
  293. eastl::random_shuffle(myVector.begin(), myVector.end(), rand);</pre>
  294. <p>How to fill a container or sequence with random double:</p>
  295. <pre class="code-example">#include &lt;eastl/algorithm.h&gt; <span class="code-example-comment"> // or #include &lt;algorithm&gt; to use std STL.</span>
  296. struct GenerateDouble
  297. { <br> EA::StdC::Random mRand; <span class="code-example-comment">// We need to make a tiny class that simply has</span> <br> <span class="code-example-comment">// an operator() member function that returns double.</span>
  298. GenerateDouble(uint32_t seed) : mRand(seed){} <br>
  299. double operator(){ mRand.RandomDoubleUniform(); }
  300. };<br>
  301. GenerateDouble randDouble(someSeedValue);<br>eastl::generate(myVector.begin(), myVector.end(), randDouble);</pre>
  302. <hr>
  303. <p>&nbsp;</p>
  304. <p>&nbsp;</p>
  305. <p>&nbsp;</p>
  306. <p>&nbsp;</p>
  307. <p>&nbsp;</p>
  308. <p>&nbsp;</p>
  309. <p>&nbsp;</p>
  310. <p>&nbsp;</p>
  311. <p>&nbsp;</p>
  312. <p>&nbsp;</p>
  313. <p>&nbsp;</p>
  314. <p>&nbsp;</p>
  315. <p> </p>
  316. </body></html>