// vim:fileencoding=utf-8:foldmethod=marker #include "splitmix64.h" #include "../../common/aliases/aliases.h" #include "../../common/assert/assert.h" #include "../../common/platform/platform.h" #include #include wp_intern void seedOsGenerator(u64 seed); wp_intern u64 genRandomNumber(void); WpSplitmix64State wpPrngSplitmix64Init(void) { wp_persist b8 seeded = false; if (!seeded) { seeded = true; seedOsGenerator(0); } return (WpSplitmix64State){ .seed = genRandomNumber() }; } WpSplitmix64State wpPrngSplitmix64InitWithSeed(u64 seed) { return (WpSplitmix64State){ .seed = seed }; } u64 wpPrngSplitmix64(WpSplitmix64State *state) { state->seed += 0x9E3779B97f4A7C15; u64 result = state->seed; result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9; result = (result ^ (result >> 27)) * 0x94D049BB133111EB; return result ^ (result >> 31); } u64 wpPrngSplitmix64InRange(WpSplitmix64State *state, u64 start, u64 end) { return wpPrngSplitmix64(state) % (end - start) + start; } u64 wpPrngSplitmix64Choice(WpSplitmix64State *state, u64 available_choices) { return wpPrngSplitmix64(state) % available_choices; } #if defined(WP_PLATFORM_C) && WP_PLATFORM_C_VERSION >= WP_PLATFORM_C11_VERSION #ifdef WP_PLATFORM_POSIX wp_intern void seedOsGenerator(u64 seed) { if (seed == 0) { struct timespec ts = {0}; int result = clock_gettime(CLOCK_MONOTONIC_RAW, &ts); wpRuntimeAssert(result == 0, "Invalid seed value"); seed = (u64)ts.tv_nsec; } srand48(seed); } wp_intern u64 genRandomNumber(void) { return lrand48(); } #else wp_intern void seedOsGenerator(u64 seed) { if (seed == 0) { struct timespec ts = {0}; int result = timespec_get(&ts, TIME_UTC); wpRuntimeAssert(result != 0, "Invalid seed value"); seed = (u64)ts.tv_nsec; } srand(seed); } wp_intern u64 genRandomNumber(void) { i32 n1 = rand(); i32 n2 = rand(); return (((u64)n1) << 32 | (u64)n2); } #endif // !WP_PLATFORM_POSIX #else wp_intern void seedOsGenerator(u64 seed) { if (seed == 0) { time_t result = time(NULL); wpRuntimeAssert(result != (time_t)(-1), "Invalid seed value"); seed = (u64)result; } srand(seed); } wp_intern u64 genRandomNumber(void) { i32 n1 = rand(); i32 n2 = rand(); return (((u64)n1) << 32 | (u64)n2); } #endif // !WP_PLATFORM_C