#ifndef _AL_RANDOM_H #define _AL_RANDOM_H #include "lib.h" #include "macros.h" #define AL_RAND_MAX RAND_MAX #define AL_RAND_INIT_SEED 1738 extern u32 al_rand_seed; extern __thread bool al_rand_set; #ifndef AL_SRAND_THREAD_LOCAL extern __thread u32 al_rand_state; #endif static inline void al_random_init(u32 seed) { al_rand_seed = seed; } // @TODO: Replace this with an implementation of any PRNG algorithm where // we can control the state and make it thread-local. Trying to predict the // state in libc is pretty dumb. // al_rand() is equivalent to libc rand(), as such there is no expectation // of it being an actually good random number generator. #ifdef AL_SRAND_THREAD_LOCAL #define rrand() rand() #else #define rrand() rand_r(&al_rand_state) #endif static inline s32 al_rand(void) { if (UNLIKELY(!al_rand_set)) { #ifdef AL_SRAND_THREAD_LOCAL srand(al_rand_seed); #else al_rand_state = al_rand_seed; #endif // Call rand() once after setting the seed incase it returns the seed // on the first call, like on Windows. Having the first result potentially // be so similar run-to-run would no longer even be pseudo-random. // https://stackoverflow.com/a/76676396 rrand(); al_rand_set = true; } return rrand(); } #undef rrand // https://c-faq.com/lib/randrange.html static inline s32 al_random_int(s32 min, s32 max) // [MIN, MAX] { return min + al_rand() / (AL_RAND_MAX / (max - min + 1) + 1); } static inline void al_random_hex_chars(char *buf) { al_snprintf(buf, 9, "%08X", al_rand()); } #endif // _AL_RANDOM_H