store separate counter & seed in rand state
This commit is contained in:
parent
b9530f6c7a
commit
942810c194
47
src/rand.c
47
src/rand.c
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user