From b9d072d4fc25ba4869bc5430e1ed23f192276711 Mon Sep 17 00:00:00 2001 From: Victor Gaydov Date: Sun, 11 Aug 2024 23:55:01 +0400 Subject: [PATCH] chore: Port fast_random from doubles to floats --- src/internal_modules/roc_core/fast_random.cpp | 19 +++++++++---------- src/internal_modules/roc_core/fast_random.h | 8 ++++---- src/tests/roc_core/test_fast_random.cpp | 2 +- src/tests/roc_stat/test_mov_quantile.cpp | 4 ++-- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/internal_modules/roc_core/fast_random.cpp b/src/internal_modules/roc_core/fast_random.cpp index 5c761e7dc..c3894c094 100644 --- a/src/internal_modules/roc_core/fast_random.cpp +++ b/src/internal_modules/roc_core/fast_random.cpp @@ -51,10 +51,9 @@ uint64_t fast_random_64() { return (hi << 32) | lo; } -// Doubles in [0; 1] have 47-bit precision, so we use 64-bit PRNG -// instead of 32-bit. -double fast_random_float() { - return (double)fast_random_64() / (double)UINT64_MAX; +// Floats in [0; 1] have 24-bit precision, so 32-bit PRNG is enough. +float fast_random_float() { + return (float)fast_random_32() / (float)UINT32_MAX; } // Bounded PRNG adaptation of "Bitmask with Rejection (Unbiased) — Apple's Method" @@ -77,7 +76,7 @@ uint64_t fast_random_range(uint64_t from, uint64_t to) { // 0001....... // 00011...... // 0001111.... - // Thanks to @rnovatorov for the hint + // Thanks to @rnovatorov for the hint. uint64_t mask = range; mask |= mask >> 1; mask |= mask >> 2; @@ -101,14 +100,14 @@ uint64_t fast_random_range(uint64_t from, uint64_t to) { // Gaussian PRNG implementation is based on Box-Muller transform: // https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform -double fast_random_gaussian() { +float fast_random_gaussian() { // Generate two uniform random numbers - const double u1 = fast_random_float(); - const double u2 = fast_random_float(); + const float u1 = fast_random_float(); + const float u2 = fast_random_float(); // Use Box-Muller transform to convert uniform random numbers to normal random numbers - const double r = std::sqrt(-2.0 * std::log(u1)); - const double theta = 2.0 * M_PI * u2; + const float r = std::sqrt(-2.0f * std::log(u1)); + const float theta = 2.0f * float(M_PI) * u2; // Return one of the normal random numbers return r * std::cos(theta); diff --git a/src/internal_modules/roc_core/fast_random.h b/src/internal_modules/roc_core/fast_random.h index da9936d53..8dda9fe22 100644 --- a/src/internal_modules/roc_core/fast_random.h +++ b/src/internal_modules/roc_core/fast_random.h @@ -29,11 +29,11 @@ uint32_t fast_random_32(); //! Not cryptographically secure. uint64_t fast_random_64(); -//! Get random 64-bit float in range [0; 1]. +//! Get random 32-bit float in range [0; 1]. //! Thread-safe and lock-free. //! Uniformly distributed. //! Not cryptographically secure. -double fast_random_float(); +float fast_random_float(); //! Get random 64-bit integer in range [from; to]. //! Thread-safe and lock-free. @@ -41,11 +41,11 @@ double fast_random_float(); //! Not cryptographically secure. uint64_t fast_random_range(uint64_t from, uint64_t to); -//! Get random 64-bit float with standard normal distribution. +//! Get random 32-bit float with standard normal distribution. //! Thread-safe and lock-free. //! Gaussian distribution N(0,1). //! Not cryptographically secure. -double fast_random_gaussian(); +float fast_random_gaussian(); } // namespace core } // namespace roc diff --git a/src/tests/roc_core/test_fast_random.cpp b/src/tests/roc_core/test_fast_random.cpp index c6060aea1..0f072d8d3 100644 --- a/src/tests/roc_core/test_fast_random.cpp +++ b/src/tests/roc_core/test_fast_random.cpp @@ -43,7 +43,7 @@ TEST(fast_random, range_loop) { TEST(fast_random, float_loop) { for (int i = 0; i < 10000; i++) { - double res = fast_random_float(); + float res = fast_random_float(); CHECK(res >= 0); CHECK(res <= 1); diff --git a/src/tests/roc_stat/test_mov_quantile.cpp b/src/tests/roc_stat/test_mov_quantile.cpp index 8939ab054..6e35489f1 100644 --- a/src/tests/roc_stat/test_mov_quantile.cpp +++ b/src/tests/roc_stat/test_mov_quantile.cpp @@ -138,7 +138,7 @@ TEST(mov_quantile, stress_test) { for (size_t i = 0; i < NumIterations; i++) { const size_t q_win_sz = core::fast_random_range(MinWindow, MaxWindow); - const double q = core::fast_random_float(); + const double q = (double)core::fast_random_float(); MovQuantile quant(arena, q_win_sz, q); CHECK(quant.is_valid()); @@ -146,7 +146,7 @@ TEST(mov_quantile, stress_test) { double elems[NumElems] = {}; for (size_t n = 0; n < NumElems; n++) { - elems[n] = core::fast_random_float(); + elems[n] = (double)core::fast_random_float(); quant.add(elems[n]); const size_t n_elems = n + 1;