blob: f578247c6ae5e35f69fe58269873540d5e44915f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
#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
|