diff --git a/src/prng/wapp_prng.c b/src/prng/wapp_prng.c new file mode 100644 index 0000000..1cfd8f0 --- /dev/null +++ b/src/prng/wapp_prng.c @@ -0,0 +1,6 @@ +#ifndef WAPP_PRNG_C +#define WAPP_PRNG_C + +#include "xorshift/xorshift.c" + +#endif // !WAPP_PRNG_C diff --git a/src/prng/wapp_prng.h b/src/prng/wapp_prng.h new file mode 100644 index 0000000..ec5aa96 --- /dev/null +++ b/src/prng/wapp_prng.h @@ -0,0 +1,7 @@ +#ifndef WAPP_PRNG_H +#define WAPP_PRNG_H + +#include "xorshift/xorshift.h" +#include "../common/wapp_common.h" + +#endif // !WAPP_PRNG_H diff --git a/src/prng/xorshift/xorshift.c b/src/prng/xorshift/xorshift.c new file mode 100644 index 0000000..b90dda7 --- /dev/null +++ b/src/prng/xorshift/xorshift.c @@ -0,0 +1,89 @@ +#include "xorshift.h" +#include "../../common/aliases/aliases.h" +#include +#include +#include + +typedef struct split_mix_64_state SplitMix64State; +struct split_mix_64_state { + u64 seed; +}; + +internal u64 rol64(u64 x, u64 bits); +internal u64 split_mix_64(SplitMix64State *state); + +XOR256State wapp_init_xor_256_state(void) { + persistent bool seeded = false; + if (!seeded) { + seeded = true; + + struct timespec ts = {0}; + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + + srand48(ts.tv_nsec); + } + + SplitMix64State sm64 = {.seed = lrand48()}; + + return (XOR256State){ + .x = split_mix_64(&sm64), + .y = split_mix_64(&sm64), + .z = split_mix_64(&sm64), + .w = split_mix_64(&sm64), + }; +} + +u64 wapp_xorshift_256_generate(XOR256State *state) { + u64 t = state->x ^ (state->x << 11); + + state->x = state->y; + state->y = state->z; + state->z = state->w; + state->w = (state->w ^ (state->w >> 19)) ^ (t ^ (t >> 8)); + + return state->w; +} + +u64 wapp_xoshiro_256ss_generate(XOR256State *state) { + const u64 result = rol64(state->z * 5, 7) * 9; + const u64 t = state->z << 17; + + state->y ^= state->w; + state->x ^= state->z; + state->z ^= state->y; + state->w ^= state->x; + + state->y ^= t; + state->x = rol64(state->x, 45); + + return result; +} + +u64 wapp_xoshiro_256p_generate(XOR256State *state) { + const u64 result = state->w + state->x; + const u64 t = state->z << 17; + + state->y ^= state->w; + state->x ^= state->z; + state->z ^= state->y; + state->w ^= state->x; + + state->y ^= t; + state->x = rol64(state->x, 45); + + return result; +} + +internal u64 rol64(u64 x, u64 bits) { + return (x << bits) | (x >> (64 - bits)); +} + +internal u64 split_mix_64(SplitMix64State *state) { + state->seed += 0x9E3779B97f4A7C15; + + u64 result = state->seed; + result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9; + result = (result ^ (result >> 27)) * 0x94D049BB133111EB; + + return result ^ (result >> 31); +} diff --git a/src/prng/xorshift/xorshift.h b/src/prng/xorshift/xorshift.h new file mode 100644 index 0000000..eb4bc4b --- /dev/null +++ b/src/prng/xorshift/xorshift.h @@ -0,0 +1,27 @@ +#ifndef XORSHIFT_H +#define XORSHIFT_H + +#include "../../common/aliases/aliases.h" + +#ifdef __cplusplus +BEGIN_C_LINKAGE +#endif // __cplusplus + +typedef struct xor_256_state XOR256State; +struct xor_256_state { + u64 x; + u64 y; + u64 z; + u64 w; +}; + +XOR256State wapp_init_xor_256_state(void); +u64 wapp_xorshift_256_generate(XOR256State *state); +u64 wapp_xoshiro_256ss_generate(XOR256State *state); +u64 wapp_xoshiro_256p_generate(XOR256State *state); + +#ifdef __cplusplus +END_C_LINKAGE +#endif // __cplusplus + +#endif // !XORSHIFT_H diff --git a/src/wapp.c b/src/wapp.c index a06939b..16d148e 100644 --- a/src/wapp.c +++ b/src/wapp.c @@ -3,6 +3,7 @@ #include "wapp.h" #include "core/wapp_core.c" +#include "prng/wapp_prng.c" #include "testing/wapp_testing.c" #endif // !WAPP_C diff --git a/src/wapp.h b/src/wapp.h index 13e7fc6..cddb106 100644 --- a/src/wapp.h +++ b/src/wapp.h @@ -3,6 +3,7 @@ #include "common/wapp_common.h" #include "core/wapp_core.h" +#include "prng/wapp_prng.h" #include "testing/wapp_testing.h" #endif // !WAPP_H