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

View File

@ -4,6 +4,7 @@
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 */
u64 seed;
u64 counter;
};
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;
MEMCPY_STRUCT(local, remote);
if (!MEMEQ_STRUCT(&old._xform, &remote->_xform)) {
DEBUGBREAKABLE;
}
/* Why would 2 ents w/ different uids ever be synced? */
ASSERT(sim_ent_id_eq(local->id, old.id));
local->ss = old.ss;
local->id = old.id;
/* Keep local tree */
local->parent = old.parent;