#include #include #include static uint32_t rprand_state[4] = {0}; static uint64_t rprand_seed = 0; static inline uint32_t my_rotate_left(const uint32_t x, int k) { return (x << k) | (x >> (32 - k)); } uint32_t my_rprand_xoshiro(uint32_t state[4]) { const uint32_t result = my_rotate_left(state[1] * 5, 7) * 9; const uint32_t t = state[1] << 9; state[2] ^= state[0]; state[3] ^= state[1]; state[1] ^= state[2]; state[0] ^= state[3]; state[2] ^= t; state[3] = my_rotate_left(state[3], 11); return result; } uint64_t rprand_splitmix64() { uint64_t z = (rprand_seed += 0x9e3779b97f4a7c15); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9; z = (z ^ (z >> 27)) * 0x94d049bb133111eb; return z ^ (z >> 31); } void setSeed(unsigned long long seed) { rprand_seed = (uint64_t)seed; // Set SplitMix64 seed for further use // To generate the Xoshiro128** state, we use SplitMix64 generator first // We generate 4 pseudo-random 64bit numbers that we combine using their LSB|MSB rprand_state[0] = (uint32_t)(rprand_splitmix64() & 0xffffffff); rprand_state[1] = (uint32_t)((rprand_splitmix64() & 0xffffffff00000000) >> 32); rprand_state[2] = (uint32_t)(rprand_splitmix64() & 0xffffffff); rprand_state[3] = (uint32_t)((rprand_splitmix64() & 0xffffffff00000000) >> 32); } int getValue(int min, int max) { return my_rprand_xoshiro(rprand_state) % (std::abs(max - min) + 1) + min; } double getFloat() { return my_rprand_xoshiro(rprand_state) / (double)UINT32_MAX; } typedef uint32_t (*func_t)(); #define N 100 static uint32_t Rand7Naive() { return getValue(0, N - 1); } static uint32_t Rand7Float() { return (getFloat() * N); } void Test(func_t rand, std::string name) { uint64_t *buckets = new uint64_t[N]; for (int i = 0; i < N; i++) buckets[i] = 0; for (int i = 0; i < 100000000; i++) buckets[rand()]++; uint64_t sum = 0; for (int i = 0; i < N; i++) sum += buckets[i]; printf("%s\n", name.c_str()); for (int i = 0; i < N; i++) printf("%d\t%ld\n", i, buckets[i]); printf("sum = %ld\n\n", sum); delete buckets; } int main(int argc, char const *argv[]) { setSeed((unsigned int)time(NULL)); Test(Rand7Naive, "Rand7Naive"); setSeed((unsigned int)time(NULL)); Test(Rand7Float, "Rand7Float"); return 0; }