Merge remote-tracking branch 'upstream/splitmix32-random' into integration

This commit is contained in:
J. Nick Koston
2026-03-19 13:38:46 -10:00
7 changed files with 31 additions and 23 deletions
+25
View File
@@ -156,6 +156,31 @@ uint32_t fnv1_hash(const char *str) {
return hash;
}
// SplitMix32 — a fast, non-cryptographic PRNG from the SplitMix family
// (Steele et al., 2014). Uses a Weyl sequence with golden-ratio increment
// and the MurmurHash3 32-bit finalizer as output mixing function.
// Reference: https://doi.org/10.1145/2714064.2660195
// Test results: https://lemire.me/blog/2017/08/22/testing-non-cryptographic-random-number-generators-my-results/
// Seeded lazily from the platform's secure RNG via random_bytes().
// ESP8266 uses os_random() instead (defined in esp8266/helpers.cpp).
#ifndef USE_ESP8266
static uint32_t splitmix32_state; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
uint32_t random_uint32() {
// State of 0 means unseeded. The state will wrap back to 0 after 2^32 calls,
// triggering one extra random_bytes() call — an acceptable trade-off vs. adding
// a separate bool flag (4 bytes BSS + branch on every call).
if (splitmix32_state == 0) {
random_bytes(reinterpret_cast<uint8_t *>(&splitmix32_state), sizeof(splitmix32_state));
}
splitmix32_state += 0x9e3779b9u;
uint32_t z = splitmix32_state;
z = (z ^ (z >> 16)) * 0x85ebca6bu;
z = (z ^ (z >> 13)) * 0xc2b2ae35u;
return z ^ (z >> 16);
}
#endif
float random_float() { return static_cast<float>(random_uint32()) / static_cast<float>(UINT32_MAX); }
// Strings