diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bdf9f1..9b98f33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `wpSip24Hasher128IO`, `wpSip48Hasher128IO`, `wpSip24Hasher64IO` and `wpSip48Hasher64IO` to setup the siphash IO structs for the different variants - `wpSipHasher128` and `wpSipHasher64` implementation for the 128 and 64 variants of siphash - Add `wpU8Const`, `wpU16Const`, `wpU32Const`, `wpU64Const`, `wpI8Const`, `wpI16Const`, `wpI32Const`, and `wpI64Const` +- `wpPrngXorshiftInitWithSeed` to allow for user control with PRNG + +### Changed + +- Switched to using `wpMiscUtilsRotl64` in `xorshift` ## [2.4.0] - 2026-08-30 diff --git a/src/prng/xorshift/xorshift.c b/src/prng/xorshift/xorshift.c index b41d5c2..722c1b7 100644 --- a/src/prng/xorshift/xorshift.c +++ b/src/prng/xorshift/xorshift.c @@ -4,6 +4,7 @@ #include "../../common/aliases/aliases.h" #include "../../common/assert/assert.h" #include "../../common/platform/platform.h" +#include "../../common/misc/misc_utils.h" #include #include @@ -12,16 +13,19 @@ struct SplitMix64State { u64 seed; }; -wp_intern u64 rol64(u64 x, u64 bits); wp_intern u64 split_mix_64(SplitMix64State *state); -wp_intern void seed_os_generator(void); +wp_intern void seed_os_generator(u64 seed); wp_intern u64 generate_random_number(void); WpXor256State wpPrngXorshiftInit(void) { + return wpPrngXorshiftInitWithSeed(0); +} + +WpXor256State wpPrngXorshiftInitWithSeed(u64 seed) { wp_persist b8 seeded = false; if (!seeded) { seeded = true; - seed_os_generator(); + seed_os_generator(seed); } SplitMix64State sm64 = {.seed = generate_random_number()}; @@ -46,7 +50,7 @@ u64 wpPrngXorshift256(WpXor256State *state) { } u64 wpPrngXorshift256ss(WpXor256State *state) { - const u64 result = rol64(state->z * 5, 7) * 9; + const u64 result = wpMiscUtilsRotl64(state->z * 5, 7) * 9; const u64 t = state->z << 17; state->y ^= state->w; @@ -55,7 +59,7 @@ u64 wpPrngXorshift256ss(WpXor256State *state) { state->w ^= state->x; state->y ^= t; - state->x = rol64(state->x, 45); + state->x = wpMiscUtilsRotl64(state->x, 45); return result; } @@ -70,15 +74,11 @@ u64 wpPrngXorshift256p(WpXor256State *state) { state->w ^= state->x; state->y ^= t; - state->x = rol64(state->x, 45); + state->x = wpMiscUtilsRotl64(state->x, 45); return result; } -wp_intern u64 rol64(u64 x, u64 bits) { - return (x << bits) | (x >> (64 - bits)); -} - wp_intern u64 split_mix_64(SplitMix64State *state) { state->seed += 0x9E3779B97f4A7C15; @@ -91,24 +91,30 @@ wp_intern u64 split_mix_64(SplitMix64State *state) { #if defined(WP_PLATFORM_C) && WP_PLATFORM_C_VERSION >= WP_PLATFORM_C11_VERSION #ifdef WP_PLATFORM_POSIX -wp_intern void seed_os_generator(void) { - struct timespec ts = {0}; - int result = clock_gettime(CLOCK_MONOTONIC_RAW, &ts); - wpRuntimeAssert(result == 0, "Invalid seed value"); +wp_intern void seed_os_generator(u64 seed) { + if (seed == 0) { + struct timespec ts = {0}; + int result = clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + wpRuntimeAssert(result == 0, "Invalid seed value"); + seed = (u64)ts.tv_nsec; + } - srand48(ts.tv_nsec); + srand48(seed); } wp_intern u64 generate_random_number(void) { return lrand48(); } #else -wp_intern void seed_os_generator(void) { - struct timespec ts = {0}; - int result = timespec_get(&ts, TIME_UTC); - wpRuntimeAssert(result != 0, "Invalid seed value"); +wp_intern void seed_os_generator(u64 seed) { + if (seed == 0) { + struct timespec ts = {0}; + int result = timespec_get(&ts, TIME_UTC); + wpRuntimeAssert(result != 0, "Invalid seed value"); + seed = (u64)ts.tv_nsec; + } - srand(ts.tv_nsec); + srand(seed); } wp_intern u64 generate_random_number(void) { @@ -119,11 +125,14 @@ wp_intern u64 generate_random_number(void) { } #endif // !WP_PLATFORM_POSIX #else -wp_intern void seed_os_generator(void) { - time_t result = time(NULL); - wpRuntimeAssert(result != (time_t)(-1), "Invalid seed value"); +wp_intern void seed_os_generator(u64 seed) { + if (seed == 0) { + time_t result = time(NULL); + wpRuntimeAssert(result != (time_t)(-1), "Invalid seed value"); + seed = (u64)result; + } - srand(result); + srand(seed); } wp_intern u64 generate_random_number(void) { diff --git a/src/prng/xorshift/xorshift.h b/src/prng/xorshift/xorshift.h index 48258cb..58166e5 100644 --- a/src/prng/xorshift/xorshift.h +++ b/src/prng/xorshift/xorshift.h @@ -19,6 +19,7 @@ struct WpXor256State { }; WpXor256State wpPrngXorshiftInit(void); +WpXor256State wpPrngXorshiftInitWithSeed(u64 seed); u64 wpPrngXorshift256(WpXor256State *state); u64 wpPrngXorshift256ss(WpXor256State *state); u64 wpPrngXorshift256p(WpXor256State *state);