#include "rand.h" #include "sys.h" #include "memory.h" #include "thread_local.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); }