From 0ffe6c466e437ebbda9be47bbd77d3775623a2d7 Mon Sep 17 00:00:00 2001 From: Arnaud Giersch Date: Sat, 27 Mar 2021 21:54:44 +0100 Subject: [PATCH] Fix XbtRandom::uniform_int() when used with large range. Add more unit tests. --- src/xbt/random.cpp | 12 +++++++++--- src/xbt/random_test.cpp | 12 ++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/xbt/random.cpp b/src/xbt/random.cpp index 78d115a814..088545eb5f 100644 --- a/src/xbt/random.cpp +++ b/src/xbt/random.cpp @@ -65,14 +65,20 @@ double StdRandom::normal(double mean, double sd) int XbtRandom::uniform_int(int min, int max) { - unsigned long range = max - min + 1; + unsigned long range = static_cast(max) - static_cast(min); xbt_assert(min <= max, "The minimum value for the uniform integer distribution must not be greater than the maximum value"); - xbt_assert(range > 0, "Overflow in the uniform integer distribution, please use a smaller range."); + xbt_assert(range <= decltype(mt19937_gen)::max(), + "Overflow in the uniform integer distribution, please use a smaller range."); + if (range == decltype(mt19937_gen)::max()) + return static_cast(mt19937_gen() + min); + + ++range; + unsigned long limit = decltype(mt19937_gen)::max() - decltype(mt19937_gen)::max() % range; unsigned long value; do { value = mt19937_gen(); - } while (value >= decltype(mt19937_gen)::max() - decltype(mt19937_gen)::max() % range); + } while (value >= limit); return static_cast(value % range + min); } diff --git a/src/xbt/random_test.cpp b/src/xbt/random_test.cpp index 76bf59e387..a474825426 100644 --- a/src/xbt/random_test.cpp +++ b/src/xbt/random_test.cpp @@ -21,6 +21,18 @@ TEST_CASE("xbt::random: Random Number Generation") REQUIRE(simgrid::xbt::random::uniform_int(1, 6) == 4); REQUIRE_THAT(simgrid::xbt::random::uniform_real(0, 1), EpsilonApprox(0.31637556043369124970)); REQUIRE_THAT(simgrid::xbt::random::normal(0, 2), EpsilonApprox(1.62746784745133976635)); + + constexpr int imin = std::numeric_limits::min(); + constexpr int imax = std::numeric_limits::max(); + REQUIRE(simgrid::xbt::random::uniform_int(0, 0) == 0); + REQUIRE(simgrid::xbt::random::uniform_int(imin, imin) == imin); + REQUIRE(simgrid::xbt::random::uniform_int(imax, imax) == imax); + + REQUIRE(simgrid::xbt::random::uniform_int(-6, -1) == -3); + REQUIRE(simgrid::xbt::random::uniform_int(-10, 10) == 7); + REQUIRE(simgrid::xbt::random::uniform_int(imin, 2) == -163525263); + REQUIRE(simgrid::xbt::random::uniform_int(-2, imax) == 1605979225); + REQUIRE(simgrid::xbt::random::uniform_int(imin, imax) == 659577591); } SECTION("Using XBT_RNG_std") -- 2.20.1