Index: src/base/utils/random-number-generator.h |
diff --git a/src/base/utils/random-number-generator.h b/src/base/utils/random-number-generator.h |
index 10f2789c7dffea7334051f58cc40a80edbf822e3..cd3e6bfdc89906d00e80340174fdb52865bbcfa9 100644 |
--- a/src/base/utils/random-number-generator.h |
+++ b/src/base/utils/random-number-generator.h |
@@ -12,10 +12,16 @@ namespace base { |
// ----------------------------------------------------------------------------- |
// RandomNumberGenerator |
-// |
-// This class is used to generate a stream of pseudorandom numbers. The class |
-// uses a 48-bit seed, which is modified using a linear congruential formula. |
-// (See Donald Knuth, The Art of Computer Programming, Volume 3, Section 3.2.1.) |
+ |
+// This class is used to generate a stream of pseudo-random numbers. The class |
+// uses a 64-bit seed, which is passed through MurmurHash3 to create two 64-bit |
+// state values. This pair of state values is then used in xorshift128+. |
+// The resulting stream of pseudo-random numbers has a period length of 2^128-1. |
+// See Marsaglia: http://www.jstatsoft.org/v08/i14/paper |
+// And Vigna: http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf |
+// NOTE: Any changes to the algorithm must be tested against TestU01. |
+// Please find instructions for this in the internal repository. |
+ |
// If two instances of RandomNumberGenerator are created with the same seed, and |
// the same sequence of method calls is made for each, they will generate and |
// return identical sequences of numbers. |
@@ -83,6 +89,27 @@ class RandomNumberGenerator final { |
int64_t initial_seed() const { return initial_seed_; } |
+ // Static and exposed for external use. |
+ static inline double ToDouble(uint64_t state0, uint64_t state1) { |
+ // Exponent for double values for [1.0 .. 2.0) |
+ static const uint64_t kExponentBits = V8_UINT64_C(0x3FF0000000000000); |
+ static const uint64_t kMantissaMask = V8_UINT64_C(0x000FFFFFFFFFFFFF); |
+ uint64_t random = ((state0 + state1) & kMantissaMask) | kExponentBits; |
+ return bit_cast<double>(random) - 1; |
+ } |
+ |
+ // Static and exposed for external use. |
+ static inline void XorShift128(uint64_t* state0, uint64_t* state1) { |
+ uint64_t s1 = *state0; |
+ uint64_t s0 = *state1; |
+ *state0 = s0; |
+ s1 ^= s1 << 23; |
+ s1 ^= s1 >> 17; |
+ s1 ^= s0; |
+ s1 ^= s0 >> 26; |
+ *state1 = s1; |
+ } |
+ |
private: |
static const int64_t kMultiplier = V8_2PART_UINT64_C(0x5, deece66d); |
static const int64_t kAddend = 0xb; |
@@ -90,8 +117,11 @@ class RandomNumberGenerator final { |
int Next(int bits) WARN_UNUSED_RESULT; |
+ static uint64_t MurmurHash3(uint64_t); |
+ |
int64_t initial_seed_; |
- int64_t seed_; |
+ uint64_t state0_; |
+ uint64_t state1_; |
}; |
} // namespace base |