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 | |