store separate counter & seed in rand state

This commit is contained in:
jacob 2025-02-27 10:22:23 -06:00
parent b9530f6c7a
commit 942810c194
3 changed files with 19 additions and 44 deletions

View File

@ -3,17 +3,8 @@
#include "memory.h" #include "memory.h"
#include "thread_local.h" #include "thread_local.h"
/* Based on Jon Maiga's "mx3" /* TODO: Use a value that gives good precision when dividing into range 0 -> 1 */
* (https://jonkagstrom.com/mx3/mx3_rev2.html) #define F64_RAND_MAX U64_MAX
*/
INTERNAL u64 mix64(u64 x)
{
x = (x ^ (x >> 32)) * 0xbea225f9eb34556d;
x = (x ^ (x >> 29)) * 0xbea225f9eb34556d;
x = (x ^ (x >> 32)) * 0xbea225f9eb34556d;
x = (x ^ (x >> 29));
return x;
}
/* ========================== * /* ========================== *
* Stateful prng * Stateful prng
@ -21,40 +12,36 @@ INTERNAL u64 mix64(u64 x)
u64 rand_u64_from_state(struct rand_state *state) u64 rand_u64_from_state(struct rand_state *state)
{ {
u64 res = state->seed; u64 seed = state->seed;
while (res == 0) { if (seed == 0) {
sys_true_rand(STRING_FROM_STRUCT(&res)); sys_true_rand(STRING_FROM_STRUCT(&seed));
state->seed = seed;
} }
res = mix64(res); return seed ^ rand_u64_from_seed(++state->counter);
state->seed = res;
return res;
} }
f64 rand_f64_from_state(struct rand_state *state, f64 range_start, f64 range_end) f64 rand_f64_from_state(struct rand_state *state, f64 range_start, f64 range_end)
{ {
if (range_start > range_end) { return range_start + (range_end - range_start) * ((f64)(rand_u64_from_state(state) % F64_RAND_MAX) / (f64)F64_RAND_MAX);
f64 swp = range_start;
range_start = range_end;
range_end = swp;
}
return range_start + ((f64)rand_u64_from_state(state) / (f64)U64_MAX) * (range_end - range_start);
} }
/* ========================== * /* ========================== *
* Seeded prng * Seeded prng
* ========================== */ * ========================== */
/* Based on Jon Maiga's "mx3"
* https://jonkagstrom.com/mx3/mx3_rev2.html
*/
u64 rand_u64_from_seed(u64 seed) u64 rand_u64_from_seed(u64 seed)
{ {
return mix64(seed); seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
seed = (seed ^ (seed >> 29)) * 0xbea225f9eb34556d;
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
seed = (seed ^ (seed >> 29));
return seed;
} }
f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end) f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end)
{ {
if (range_start > range_end) { return range_start + (range_end - range_start) * ((f64)(rand_u64_from_seed(seed) % F64_RAND_MAX) / (f64)F64_RAND_MAX);
f64 swp = range_start;
range_start = range_end;
range_end = swp;
}
return range_start + ((f64)rand_u64_from_seed(seed) / (f64)U64_MAX) * (range_end - range_start);
} }

View File

@ -4,6 +4,7 @@
struct rand_state { struct rand_state {
/* If a state's seed = 0 upon a to a related function, it will be initialized using platform's true rng source */ /* If a state's seed = 0 upon a to a related function, it will be initialized using platform's true rng source */
u64 seed; u64 seed;
u64 counter;
}; };
u64 rand_u64_from_state(struct rand_state *state); u64 rand_u64_from_state(struct rand_state *state);

View File

@ -584,24 +584,11 @@ void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote)
struct sim_ent old = *local; struct sim_ent old = *local;
MEMCPY_STRUCT(local, remote); MEMCPY_STRUCT(local, remote);
if (!MEMEQ_STRUCT(&old._xform, &remote->_xform)) {
DEBUGBREAKABLE;
}
/* Why would 2 ents w/ different uids ever be synced? */ /* Why would 2 ents w/ different uids ever be synced? */
ASSERT(sim_ent_id_eq(local->id, old.id)); ASSERT(sim_ent_id_eq(local->id, old.id));
local->ss = old.ss; local->ss = old.ss;
local->id = old.id;
/* Keep local tree */ /* Keep local tree */
local->parent = old.parent; local->parent = old.parent;