Daenyth/Cockatrice — pull request #59 by VanNostrand (2014-03-08 17:19:01+00:00)
Title: RNG Update

After my comment in pull request #58 about a possible update to the included external RNG code, I updated the SFMT sources from v1.3.3 to the current v1.4.1, updated the RNG_SFMT class accordingly, documented the usage in the source code and got rid of some really ugly corpses there:
1. There was no reason to loop 100000 times and generate random numbers while discarding them. Maybe it is a copy paste leftover from SFMT's test.c?
2. The seed variable was useless and has been replaced by an expression. This is one of those efficiency things; there is probably more scattered throughout the code, like in the old shuffling algorithm. For primitive datatypes the compiler's optimizer removes such variables but it is good practise to omit them in the first place ;-)
3. The calculation of the ranged RNG itself was horrible (come on - seriously?):
min + (unsigned int) (((double) (max + 1 - min)) * r / (18446744073709551616.0 + 1.0))
versus
(unsigned int) (r % (max - min + 1) + min)
Which means:
1. no magic numbers (it took a too long time to understand that 1844... == 2^64)
2. no casting from unsigned int to double and back to unsigned int, just from uint64_t to unsigned int, which is basically the same on 64bit architectures.
3. No errors from numerical division. Nobody likes residuals ^^
4. Now it is: min and max define an interval with n numbers, so compute the random number modulo n to get a number from [0, n-1], add one, then add at the lower bound.

There are two things I'd like to know - just saying, it always worked this way but we should think about this:
1. Why was the number generation put into a Mutex? Sure, there is just one RNG object, which is used from several other code parts. Is Qt multithreaded? (Also: If we are able to get rid of the Mutex, then the r variable can be omitted again ^^)
2. I'd like to know what happens when casting a 64 bit variable to a 32bit variable (because int is 32bit on 32bit architectures). Could be creepy if someone shuffles a deck with UINT32_MAX + 1 cards on a 32bit server ^^. So if 64 bit random numbers are used, then all components should use 64 bit integers.

Further things:
I removed the Qt based RNG, because it was unused since SFMT was introduced and I also shut up the info which RNG is used because there is only one and adapted the cmake buildfile.

The author has some compiling remarks on http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/howto-compile.html, e.g. if the build system detects gcc, then we could enable -O3 -fno-strict-aliasing to improve the RNG's speed.
Also: There is an SSE2 version which could be included and enabled at compile time - 11 year old CPUs have SSE2.