summaryrefslogtreecommitdiff
path: root/include/al
diff options
context:
space:
mode:
Diffstat (limited to 'include/al')
-rw-r--r--include/al/random.h34
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