diff options
Diffstat (limited to 'include/al')
| -rw-r--r-- | include/al/random.h | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/include/al/random.h b/include/al/random.h index f92a77b..3df3140 100644 --- a/include/al/random.h +++ b/include/al/random.h @@ -5,23 +5,53 @@ #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_rand_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)) { - // srand() is thread-local in Windows CRT. +#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 rand(); + 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); } #endif // _AL_RANDOM_H |