Jon Maiga, 2020-08-11
Since I already had the tools available and matters relatively fresh in my head, I decided to see how far I can get the xmxmx
construction:
uint64_t xmxmx(uint64_t x) {
x ^= x >> xc1;
x *= mc;
x ^= x >> xc2;
x *= mc;
x ^= x >> xc3;
return x;
}
Again I am only using the mixer as a counter based PRNG (xmxmx(counter++)
) and seeing how far it takes us in PractRand.
MurMur3 and SplitMix both use the xmxmx
construction and will fail really early, around bytes (as counter based).
I started with the xor-constants I found in tuning bit mixers and did some further tweaking using the same methodology. Once the xor-constants had been settled I additionally ran SFFS (see same article) to find a decent multiplier constant.
Here is the result
uint64_t xmxmx(uint64_t x) {
x ^= x >> 27;
x *= 0xe9846af9b1a615dull;
x ^= x >> 25;
x *= 0xe9846af9b1a615dull;
x ^= x >> 27;
return x;
}
which fails PractRand at bytes.
By adding a multiplication before the first xor-shift we can get really good quality by at least passing PractRand bytes as I did in the mx3 pseudo random number generator.