power_play/src/rng.c

112 lines
2.8 KiB
C

#include "rng.h"
#include "sys.h"
#include "resource.h"
#include "arena.h"
GLOBAL struct {
struct arena arena;
u64 *noise;
u64 noise_count;
} G = ZI, DEBUG_ALIAS(G, G_rng);
/* ========================== *
* Generate random number file
* (unused function)
* ========================== */
#if 0
INTERNAL void gen_random_file(struct string path, u32 count)
{
{
/* Clear file */
struct sys_file f = sys_file_open_write(path);
sys_file_write(f, STRING(0, 0));
sys_file_close(f);
}
struct sys_file f = sys_file_open_append(path);
for (u32 i = 0; i < count; ++i) {
u64 rand = rng_rand_u64();
sys_file_write(f, STRING_FROM_STRUCT(&rand));
}
sys_file_close(f);
}
#endif
/* ========================== *
* Startup
* ========================== */
struct rng_startup_receipt rng_startup(struct resource_startup_receipt *resource_sr)
{
(UNUSED)resource_sr;
struct string noise_path = LIT("res/noise.dat");
if (resource_exists(noise_path)) {
struct resource r = resource_open(noise_path);
G.noise_count = r.data.len / sizeof(*G.noise);
G.arena = arena_alloc(sizeof(u64) * G.noise_count);
G.noise = arena_push_array(&G.arena, u64, G.noise_count);
MEMCPY(G.noise, r.data.text, r.data.len);
resource_close(r);
} else {
sys_panic(LIT("Failed to locate pre-computed noise resource"));
}
return (struct rng_startup_receipt) { 0 };
}
/* ========================== *
* Rand
* ========================== */
u32 rng_rand_u32(void)
{
u32 v = 0;
sys_rand(STRING_FROM_STRUCT(&v));
return v;
}
u64 rng_rand_u64(void)
{
u64 v = 0;
sys_rand(STRING_FROM_STRUCT(&v));
return v;
}
f32 rng_rand_f32(f32 range_start, f32 range_end)
{
return ((f32)rng_rand_u32() / (f32)U32_MAX) * (range_end - range_start) + range_start;
}
f64 rng_rand_f64(f64 range_start, f64 range_end)
{
return ((f64)rng_rand_u64() / (f64)U64_MAX) * (range_end - range_start) + range_start;
}
/* ========================== *
* Noise
* Functions that return a deterministic pre-computed random number based on the provided seed
*
* NOTE: Noise pattern repeats after period depending on how much noise data exists in noise.dat
* ========================== */
/* TODO: Use deterministic prng rather than embedded data */
u32 rng_noise_u32(u32 seed)
{
return (u32)G.noise[seed % G.noise_count];
}
u64 rng_noise_u64(u64 seed)
{
return G.noise[seed % G.noise_count];
}
f32 rng_noise_f32(u64 seed, f32 range_start, f32 range_end)
{
return ((f32)rng_noise_u32(seed) / (f32)U32_MAX) * (range_end - range_start) + range_start;
}
f32 rng_noise_f64(u64 seed, f64 range_start, f64 range_end)
{
return ((f64)rng_noise_u64(seed) / (f64)U64_MAX) * (range_end - range_start) + range_start;
}