{"id":97,"date":"2013-10-21T22:32:02","date_gmt":"2013-10-22T03:32:02","guid":{"rendered":"http:\/\/www.essentialmath.com\/blog\/?p=97"},"modified":"2013-10-21T22:44:58","modified_gmt":"2013-10-22T03:44:58","slug":"new-thoughts-on-random-numbers-part-two","status":"publish","type":"post","link":"https:\/\/www.essentialmath.com\/blog\/?p=97","title":{"rendered":"New Thoughts on Random Numbers, Part Two"},"content":{"rendered":"<p>Sorry about the long delay on this. I originally intended to post this right away, but then realized I should do some further testing&#8230; and for whatever reason that never happened until last week. In any case, as I mentioned in my previous post, I recently added a new pseudo-random number generator to the Skia test suite. The last post was about verifying that a new PRNG was needed, this one is about what I used to replace it.<\/p>\n<p>My initial thoughts about how to replace the Linear Congruential Generator was to jump right to the Mersenne Twister. However, the Mersenne Twister requires a buffer of 624 integers. While this is not terrible, it&#8217;s probably overkill for what we need, and the large buffer is not great for low-memory situations. In addition, part of my research showed that it&#8217;s possible to get large random periods with other, simpler methods. <\/p>\n<p>To cut the story short, because we do a lot of testing on mobile platforms I wanted something low-memory and super simple. I ended up taking one of Marsaglia&#8217;s generators and modifying it slightly. This is the &#8220;mother-of-all&#8221; generator that I mention in the random number generator chapter:<br \/>\n<code><br \/>\n          k=30345*(k&65535)+(k>>16);<br \/>\n          j=18000*(j&65535)+(j>>16);<br \/>\n          return((k &lt;&lt; 16)+j);<br \/>\n<\/code><br \/>\nwhere k and j are unsigned 32-bit integers, initialized to non-zero values.<\/p>\n<p>When I ran this through the Tuftests suite, it passed the GCD and Birthday Spacings tests, but failed the Gorilla test on half of the bits. So I figured, what the hey, I&#8217;ll just combine the high bits of k into the low bits of the result as well, or<br \/>\n<code><br \/>\n          k=30345*(k&65535)+(k>>16);<br \/>\n          j=18000*(j&65535)+(j>>16);<br \/>\n          return(((k &lt;&lt; 16) | (k >> 16)) + j);<br \/>\n<\/code><\/p>\n<p>Surprisingly, this passed all three tests. In addition, I ran a test to try to see what its period is. It ran over a weekend and still didn&#8217;t hit 2^64 values. While a good part of that time was running the test on each new value, it does show that in a game or your average application, we probably don&#8217;t need these large periods because practically we&#8217;ll never generate that many values (the exception might be a game server, which is up for days). For Skia&#8217;s particular bench and unit tests, we might generate a few thousand random values &#8212; as long as our period is more than that we should be okay.<\/p>\n<p>I&#8217;ve since run the <a href=\"http:\/\/www.iro.umontreal.ca\/~simardr\/testu01\/tu01.html\">TestU01<\/a> suite on this, and it passes SmallCrush, fails one of the Birthday Spacing tests (#11) on Crush, and two other Birthday Spacing tests (#13 and #15) on BigCrush. Other than that it passes. So while it&#8217;s not as random as other generators, at this point it doesn&#8217;t seem worth it to change it and rebaseline all of our results again, just for those failures.<\/p>\n<p>If that doesn&#8217;t work for you, an alternative worth trying might be Marsaglia&#8217;s <a href=\"http:\/\/mathforum.org\/kb\/message.jspa?messageID=7359611\">KISS<\/a> generator, which takes four different random number generators and mixes their bits together. He claims (or <em>claimed<\/em>: Dr. Marsaglia unfortunately passed on in 2011) that the 2011 version has a period of greater than 10^40000000. Regardless of quality, the 2011 version requires a large buffer which is probably not practical for low-memory mobile platforms. The 1993 version, on the other hand, requires only six values, and has a period of 2^123. It does still fail one Crush and one BigCrush test, but is still probably good enough for games.<\/p>\n<p>One important note: KISS is not cryptologically safe, as proven <a href=\"http:\/\/eprint.iacr.org\/2011\/007.pdf\">here<\/a>, and I strongly doubt the generator I describe above is either. And if you do need a cryptologically secure generator, it&#8217;s best to find an approved implementation and use that, as even slight changes in speed due to a naive implementation can be enough to give an attacker enough information to break your code. But of course, if the NSA was involved, you might want to be wary&#8230;<\/p>\n<p>In any case, to get results suitable for game logic, you really don&#8217;t need Mersenne Twister. Using one of these simple generators will probably do, and are leaps and bounds better than any Linear Congruential Generator.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sorry about the long delay on this. I originally intended to post this right away, but then realized I should do some further testing&#8230; and for whatever reason that never happened until last week. In any case, as I mentioned in my previous post, I recently added a new pseudo-random number generator to the Skia [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,3],"tags":[],"class_list":["post-97","post","type-post","status-publish","format-standard","hentry","category-erratical","category-mathematical"],"_links":{"self":[{"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/97","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=97"}],"version-history":[{"count":12,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/97\/revisions"}],"predecessor-version":[{"id":110,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/97\/revisions\/110"}],"wp:attachment":[{"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=97"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=97"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.essentialmath.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=97"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}