Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix XbtRandom::uniform_int() when used with large range.
authorArnaud Giersch <arnaud.giersch@univ-fcomte.fr>
Sat, 27 Mar 2021 20:54:44 +0000 (21:54 +0100)
committerArnaud Giersch <arnaud.giersch@univ-fcomte.fr>
Sat, 27 Mar 2021 21:10:46 +0000 (22:10 +0100)
Add more unit tests.

src/xbt/random.cpp
src/xbt/random_test.cpp

index 78d115a..088545e 100644 (file)
@@ -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<unsigned>(max) - static_cast<unsigned>(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<int>(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<int>(value % range + min);
 }
 
index 76bf59e..a474825 100644 (file)
@@ -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<int>::min();
+    constexpr int imax = std::numeric_limits<int>::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")