| 1 | /* |
| 2 | This 64 bit pseudo random number generator is based on the engine |
| 3 | written by Sebastiano Vigna from Dipartimento di Informatica of the |
| 4 | Università degli Studi di Milano. The original source code can be |
| 5 | found here http://xoshiro.di.unimi.it/xoshiro256starstar.c. The |
| 6 | engine is supposed to perform very well on various random engine |
| 7 | benchmarks. |
| 8 | The original author offered his work to the public domain per the |
| 9 | following original comment. |
| 10 | */ |
| 11 | |
| 12 | /* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) |
| 13 | |
| 14 | To the extent possible under law, the author has dedicated all copyright |
| 15 | and related and neighboring rights to this software to the public domain |
| 16 | worldwide. This software is distributed without any warranty. |
| 17 | |
| 18 | See <http://creativecommons.org/publicdomain/zero/1.0/>. */ |
| 19 | |
| 20 | static inline uint64_t rotl(const uint64_t x, int k) { |
| 21 | return (x << k) | (x >> (64 - k)); |
| 22 | } |
| 23 | |
| 24 | typedef uint64_t random_state_engine[4]; |
| 25 | |
| 26 | static inline void |
| 27 | init_random_state_engine(random_state_engine engine, uint64_t seed) |
| 28 | { |
| 29 | for (int i = 0; i < 4; i++) { |
| 30 | /* we use the splitmix64 generator to generate the 4 |
| 31 | * values in the state array from the given seed. |
| 32 | * This code is adapted from |
| 33 | * http://xoshiro.di.unimi.it/splitmix64.c which was |
| 34 | * put in the public domain in the same way as the |
| 35 | * "next" function below. */ |
| 36 | uint64_t z = (seed += 0x9e3779b97f4a7c15); |
| 37 | z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; |
| 38 | z = (z ^ (z >> 27)) * 0x94d049bb133111eb; |
| 39 | engine[i] = z ^ (z >> 31); |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | static inline uint64_t next(random_state_engine rse) { |
| 44 | const uint64_t output = rotl(rse[0] * 5, 7) * 9; |
| 45 | |
| 46 | const uint64_t t = rse[1] << 17; |
| 47 | |
| 48 | rse[2] ^= rse[0]; |
| 49 | rse[3] ^= rse[1]; |
| 50 | rse[1] ^= rse[2]; |
| 51 | rse[0] ^= rse[3]; |
| 52 | |
| 53 | rse[2] ^= t; |
| 54 | |
| 55 | rse[3] = rotl(rse[3], 45); |
| 56 | |
| 57 | return output; |
| 58 | } |
| 59 | |