diff --git a/common/random.cpp b/common/random.cpp index 5da2f673378..2f0d070dc70 100644 --- a/common/random.cpp +++ b/common/random.cpp @@ -48,21 +48,20 @@ RandomSource::RandomSource(const String &name) { } void RandomSource::setSeed(uint32 seed) { + if (seed == 0) + seed++; _randSeed = seed; } uint RandomSource::getRandomNumber(uint max) { - _randSeed = 0xDEADBF03 * (_randSeed + 1); - _randSeed = (_randSeed >> 13) | (_randSeed << 19); - + scrambleSeed(); if (max == UINT_MAX) - return _randSeed; - return _randSeed % (max + 1); + return (_randSeed * 0xDEADBF03); + return (_randSeed * 0xDEADBF03) % (max + 1); } uint RandomSource::getRandomBit() { - _randSeed = 0xDEADBF03 * (_randSeed + 1); - _randSeed = (_randSeed >> 13) | (_randSeed << 19); + scrambleSeed(); return _randSeed & 1; } @@ -73,5 +72,13 @@ uint RandomSource::getRandomNumberRng(uint min, uint max) { int RandomSource::getRandomNumberRngSigned(int min, int max) { return getRandomNumber(max - min) + min; } + +inline void RandomSource::scrambleSeed() { + //marsaglia's paper says that any of 81 triplets are feasible + //(11,21,13) was chosen, with (cba) and (>>,<<,>>) + _randSeed ^= _randSeed >> 13; + _randSeed ^= _randSeed << 21; + _randSeed ^= _randSeed >> 11; +} } // End of namespace Common diff --git a/common/random.h b/common/random.h index e67183ed645..57b666d41e1 100644 --- a/common/random.h +++ b/common/random.h @@ -39,7 +39,7 @@ namespace Common { class String; /** - * Simple random number generator. Although it is definitely not suitable for + * Xorshift* random number generator. Although it is definitely not suitable for * cryptographic purposes, it serves our purposes just fine. */ class RandomSource { @@ -90,6 +90,14 @@ public: * @return a random number in the interval [min, max] */ int getRandomNumberRngSigned(int min, int max); + + /** + * Scrambles the seed in order to get a new result. + * Code is shared between getRandomNumber and getRandomBit, + * so it is split off for clarity. + */ +private: + inline void scrambleSeed(); }; /** @} */