diff --git a/src/Random.hpp b/src/Random.hpp index 7361885..ca3c706 100644 --- a/src/Random.hpp +++ b/src/Random.hpp @@ -1,76 +1,83 @@ #ifndef ARBUTILS_RANDOM_HPP #define ARBUTILS_RANDOM_HPP +#include #include #include -#include namespace Arbutils { template class BaseRandom { private: + uint32_t _seed; RandomT _rng; + std::uniform_real_distribution _distribution; public: - inline constexpr BaseRandom() - : _rng(RandomT( - std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) - .count())) {} + inline constexpr BaseRandom() noexcept + : _seed(std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count()), + _rng(_seed), _distribution(0.0, 1.0) {} - explicit inline constexpr BaseRandom(int32_t seed) : _rng(seed){}; + explicit inline constexpr BaseRandom(uint64_t seed) noexcept + : _seed(seed), _rng(seed), _distribution(0.0, 1.0){}; /// Gets a random float between 0.0 and 1.0. - [[nodiscard]] inline constexpr float GetFloat() { - return static_cast(_rng()) / (static_cast(std::mt19937::max() - std::mt19937::min()) - 0.5f); + [[nodiscard]] inline constexpr float GetFloat() noexcept { + return static_cast(GetDouble()); } /// Gets a random double between 0.0 and 1.0. - [[nodiscard]] inline constexpr double GetDouble() { - return static_cast(_rng()) / - ((static_cast(std::mt19937::max()) - std::mt19937::min()) - 0.5); + [[nodiscard]] inline constexpr double GetDouble() noexcept { + return (double) _distribution(_rng); } - /// Gets a random 32 bit integer between 0 and max int. - [[nodiscard]] inline constexpr int32_t Get() { - return static_cast(GetDouble() * static_cast(std::numeric_limits::max())); - } + /// Gets a random 32 bit integer + [[nodiscard]] inline constexpr int32_t Get() noexcept { return (int32_t)_rng(); } /// Gets a random 32 bit integer between 0, and given max parameter. /// \param max The exclusive max value the random value should be. - [[nodiscard]] inline constexpr int32_t Get(int32_t max) { - return static_cast(GetDouble() * static_cast(max)); + [[nodiscard]] inline int32_t Get(int32_t max) noexcept { + std::uniform_int_distribution distribution(0, max - 1); + return distribution(_rng); } /// Gets a random 32 bit integer between given min and max parameters. /// \param min The inclusive min value the random value should be. /// \param max The exclusive max value the random value should be. - [[nodiscard]] inline constexpr int32_t Get(int32_t min, int32_t max) { - return static_cast(GetDouble() * static_cast(max - min) + min); + [[nodiscard]] inline int32_t Get(int32_t min, int32_t max) noexcept { + std::uniform_int_distribution distribution(min, max - 1); + return distribution(_rng); } /// Gets a random 32 bit unsigned integer between 0 and max unsigned int. - [[nodiscard]] inline constexpr uint32_t GetUnsigned() { - return static_cast(GetDouble() * static_cast(std::numeric_limits::max())); + [[nodiscard]] inline constexpr uint32_t GetUnsigned() noexcept { + return _rng(); } /// Gets a random 32 bit unsigned integer between 0, and given max parameter. /// \param max The exclusive max value the random value should be. - [[nodiscard]] inline constexpr uint32_t GetUnsigned(uint32_t max) { - return static_cast(GetDouble() * static_cast(max)); + [[nodiscard]] inline uint32_t GetUnsigned(uint32_t max) noexcept { + std::uniform_int_distribution distribution(0, max - 1); + return distribution(_rng); } /// Gets a random 32 bit unsigned integer between given min and max parameters. /// \param min The inclusive min value the random value should be. /// \param max The exclusive max value the random value should be. - [[nodiscard]] inline constexpr uint32_t GetUnsigned(uint32_t min, uint32_t max) { - return static_cast(GetDouble() * static_cast(max - min) + min); + [[nodiscard]] inline uint32_t GetUnsigned(uint32_t min, uint32_t max) noexcept { + std::uniform_int_distribution distribution(min, max - 1); + return distribution(_rng); } + + [[nodiscard]] inline constexpr uint32_t GetSeed() const noexcept { return _seed; } }; class Random : public BaseRandom { public: - Random() : BaseRandom() {} - Random(int32_t seed) : BaseRandom(seed) {} + constexpr Random() : BaseRandom() {} + constexpr Random(int32_t seed) : BaseRandom(seed) {} }; } #endif // ARBUTILS_RANDOM_HPP diff --git a/tests/RandomTests.cpp b/tests/RandomTests.cpp index 7dceda0..2bce9f9 100644 --- a/tests/RandomTests.cpp +++ b/tests/RandomTests.cpp @@ -6,16 +6,16 @@ TEST_CASE("Random ints", "[Utilities]") { auto rand = Arbutils::Random(10); - CHECK(rand.Get() == 1656398469); - CHECK(rand.Get() == 641584702); - CHECK(rand.Get() == 44564466); - CHECK(rand.Get() == 1062123783); - CHECK(rand.Get() == 1360749216); - CHECK(rand.Get() == 951367352); - CHECK(rand.Get() == 1608044094); - CHECK(rand.Get() == 1786516046); - CHECK(rand.Get() == 1070535660); - CHECK(rand.Get() == 1252673902); + CHECK(rand.Get() == -982170359); + CHECK(rand.Get() == 1283169405); + CHECK(rand.Get() == 89128932); + CHECK(rand.Get() == 2124247567); + CHECK(rand.Get() == -1573468864); + CHECK(rand.Get() == 1902734705); + CHECK(rand.Get() == -1078879109); + CHECK(rand.Get() == -721935204); + CHECK(rand.Get() == 2141071321); + CHECK(rand.Get() == -1789619491); } TEST_CASE("Random ints with limit", "[Utilities]") { @@ -93,7 +93,7 @@ TEST_CASE("Random distribution (max 0, min 2)", "[Utilities]") { TEST_CASE("Random distribution (max 0, min 3)", "[Utilities]") { auto rand = Arbutils::Random(10); - const int size = 100000; + const int size = 500000; int arr[size]; for (size_t i = 0; i < size; i++) { arr[i] = rand.Get(0, 3);