[core] Use SplitMix32 PRNG for random_uint32() across platforms

Replace platform-specific random_uint32() implementations with a
unified SplitMix32 PRNG seeded from random_bytes(). This provides
consistent, fast, non-cryptographic random numbers on all platforms.

ESP8266 retains os_random() as it is already faster on that platform.

Benchmarked on real hardware (ns/call, before -> after):
- RP2040: 2815 -> 333 (8.5x faster)
- ESP32: 871 -> 354 (2.5x faster)
- BK72xx: 1073 -> 882 (1.2x faster, replaces weak rand())
- RTL87xx: 330 -> 283 (1.2x faster, replaces weak rand())
- ESP8266: 763 (unchanged, keeps os_random())

random_bytes() remains platform-specific hardware RNG for crypto use.
This commit is contained in:
J. Nick Koston
2026-03-19 13:17:24 -10:00
parent c2a96ea293
commit f02bf07630
7 changed files with 25 additions and 23 deletions
+19
View File
@@ -156,6 +156,25 @@ uint32_t fnv1_hash(const char *str) {
return hash;
}
// SplitMix32 PRNG — MurmurHash3 finalizer with golden-ratio increment.
// Provides fast, uniform, non-cryptographic random numbers.
// Seeded lazily from the platform's hardware 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() {
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