Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the real definition of the xorshift128+ algorithm?

I have need of a good pseudo random number generator (PRNG), and it seems like the current state of the art is the xorshift128+ algoritm. Unfortunately, I have discovered 2 different versions. The one on wikipedia: Xorshift shows as:

uint64_t s[2];

uint64_t xorshift128plus(void) {
    uint64_t x = s[0];
    uint64_t const y = s[1];
    s[0] = y;
    x ^= x << 23; // a
    s[1] = x ^ y ^ (x >> 17) ^ (y >> 26); // b, c
    return s[1] + y;
}

Which seems straight forward enough. What's more, the edit logs appear to show that this code snippet was added by a user named "Vigna", which is presumably "Sebastiano Vigna" who is the author of the paper on xorshift128+: Further scramblings of Marsaglia’s xorshift generators. Unfortunately, the implementation in that paper is slightly different:

uint64_t next(void) {
    uint64_t s1 = s[0];
    const uint64_t s0 = s[1];
    s[0] = s0;
    s1 ^= s1 << 23; // a
    s[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5); // b, c
    return s[1] + s0;
}

Apart from some different names, these two snippets are identical except for the final two shifts. In the Wikipedia version those shifts are by 17 and 26, while the shifts in the paper are by 18 and 5.

Does anyone know which is the "right" algorithm? Does it make a difference? This is apparently a fairly widely used algorithm - but which version is used?

like image 317
N. Leavy Avatar asked Dec 22 '15 23:12

N. Leavy


1 Answers

Thanks to @Blastfurnace, it appears that the answer is that the most recent set of constants according to the author of the algorithm are: 23, 18, and 5. Apparently it doesn't matter too much, but those are theoretically better than the initial set of numbers he used. Sebastiano Vigna made these comments in response to the news that the V8 Javascript engine is shifting to using this algorithm.

The implementation that I am using is:

uint64_t a = s[0];
uint64_t b = s[1];

s[0] = b;
a ^= a << 23;
a ^= a >> 18;
a ^= b;
a ^= b >>  5;
s[1] = a;

return a + b;
like image 110
N. Leavy Avatar answered Nov 12 '22 17:11

N. Leavy