#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; }