52 lines
1.4 KiB
C
52 lines
1.4 KiB
C
#include "rand.h"
|
|
#include "sys.h"
|
|
#include "memory.h"
|
|
|
|
/* TODO: Use a value that gives good precision when dividing into range 0 -> 1 */
|
|
#define F64_RAND_MAX U64_MAX
|
|
|
|
/* ========================== *
|
|
* Stateful prng
|
|
* ========================== */
|
|
|
|
u64 rand_u64_from_state(struct rand_state *state)
|
|
{
|
|
u64 seed = state->seed;
|
|
if (seed == 0) {
|
|
sys_true_rand(STRING_FROM_STRUCT(&seed));
|
|
state->seed = seed;
|
|
}
|
|
return seed ^ rand_u64_from_seed(++state->counter);
|
|
}
|
|
|
|
f64 rand_f64_from_state(struct rand_state *state, f64 range_start, f64 range_end)
|
|
{
|
|
return range_start + (range_end - range_start) * ((f64)(rand_u64_from_state(state) % F64_RAND_MAX) / (f64)F64_RAND_MAX);
|
|
}
|
|
|
|
/* ========================== *
|
|
* Seeded prng
|
|
* ========================== */
|
|
|
|
/* Based on Jon Maiga's "mx3"
|
|
* https://jonkagstrom.com/mx3/mx3_rev2.html
|
|
*/
|
|
u64 rand_u64_from_seed(u64 seed)
|
|
{
|
|
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
|
seed = (seed ^ (seed >> 29)) * 0xbea225f9eb34556d;
|
|
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
|
seed = (seed ^ (seed >> 29));
|
|
return seed;
|
|
}
|
|
|
|
u64 rand_u64_from_seeds(u64 seed_a, u64 seed_b)
|
|
{
|
|
return rand_u64_from_seed((seed_a * 3) + seed_b);
|
|
}
|
|
|
|
f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end)
|
|
{
|
|
return range_start + (range_end - range_start) * ((f64)(rand_u64_from_seed(seed) % F64_RAND_MAX) / (f64)F64_RAND_MAX);
|
|
}
|