Skip to content
This repository was archived by the owner on Oct 11, 2020. It is now read-only.

Commit a32ccaf

Browse files
committed
rnd() should use a half open value range
Before this commit all our random ranges where close "[min; max]" Old code relied on ranges being half open "[min; max[". In particular the half open range was required when selecting random elements from lists. (Which caused assertion errors when we where accessing elements one index beyond the last one)
1 parent 65b5ce5 commit a32ccaf

File tree

2 files changed

+20
-23
lines changed

2 files changed

+20
-23
lines changed

inexor/test/util/random.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ array<range, 5> ranges {
4040
range({-10, 10, 100, 2}),
4141
range({-30000, -29900, 100, 1}),
4242
range({5000, 7000, 100, 1}),
43-
range({300,301, 4, 20})
43+
range({300,302, 4, 20})
4444
};
4545

4646
TEST(DeterministicRandom, XToYRange) {
@@ -98,9 +98,9 @@ TEST(PseudoRandom, XToYRange) {
9898
EXPECT_GE(r0, r.a) << "Expected "
9999
"rnd(" << r.a << ", " << r.z << ") "
100100
"to produce values x >= " << r.a << ".";
101-
EXPECT_LE(r0, r.z) << "Expected "
101+
EXPECT_LT(r0, r.z) << "Expected "
102102
"rnd(" << r.a << ", " << r.z << ") "
103-
"to produce values x <= " << r.z << ".";
103+
"to produce values x < " << r.z << ".";
104104
}
105105

106106
}
@@ -114,7 +114,7 @@ TEST(PseudoRandom, TypeFullRange) {
114114
for (int i=0; i<200000; i++)
115115
dist.insert(rnd_raw<uchar>());
116116

117-
EXPECT_EQ((unsigned int)256, dist.size()) << "Expected "
117+
EXPECT_EQ((unsigned int)255, dist.size()) << "Expected "
118118
"20000 random unsigned chars to contain every "
119119
"possible uchar but could find only "
120120
<< dist.size() << " values";

inexor/util/random.h

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,24 +39,21 @@ namespace random {
3939
/// The type of the seed the deterministic_generator expects
4040
typedef rng_engine::result_type seed_t;
4141

42-
/// Uniform real distribution with a closed range.
43-
///
4442
/// It is like the boost uniform distribution, but while
45-
/// that uses an half open distribution [min..max), this
46-
/// class uses a closed distribution [min..max].
43+
/// that uses an closed distribution [min; max], this
44+
/// class uses a half opened one [min; max).
4745
///
48-
/// This means that the boost one can't return 1.0 if
49-
/// max=1.0, but this one can.
46+
/// This means that the boost one can return 1000 if
47+
/// max=1000, but this one can.
5048
template<typename T>
51-
class uniform_closed_range_real_distribution
52-
: public boost::random::uniform_real_distribution<T> {
49+
class uniform_open_range_int_distribution
50+
: public boost::random::uniform_int_distribution<T> {
5351
public:
54-
explicit uniform_closed_range_real_distribution(T min=0.0, T max=1.0)
55-
: boost::random::uniform_real_distribution<T>(
56-
min,
57-
std::nextafter(
58-
max,
59-
std::numeric_limits<T>::infinity()) ) {}
52+
explicit uniform_open_range_int_distribution(
53+
T min = 0
54+
, T max = std::numeric_limits<T>::max)
55+
: boost::random::uniform_int_distribution<T>(
56+
min, max - 1) {}
6057
};
6158

6259
/// A generic uniform random number distribution that
@@ -67,10 +64,10 @@ namespace random {
6764
/// std::uniform_real_distribution, otherwise
6865
/// std::uniform_int_distribution.
6966
template<typename T>
70-
using uniform_generic_distribution = typename
67+
using uniform_generic_open_range_distribution = typename
7168
std::conditional< std::is_floating_point<T>::value,
72-
uniform_closed_range_real_distribution<T>,
73-
boost::random::uniform_int_distribution<T>
69+
boost::random::uniform_real_distribution<T>,
70+
uniform_open_range_int_distribution<T>
7471
>::type;
7572

7673
/// Generate a random number between Rmin and Rmax
@@ -92,7 +89,7 @@ namespace random {
9289
template<typename T>
9390
T rnd(const T Rmin, const T Rmax) {
9491
// TODO. This could be expensive
95-
uniform_generic_distribution<T> dist(Rmin, Rmax);
92+
uniform_generic_open_range_distribution<T> dist(Rmin, Rmax);
9693
return dist(generator);
9794
}
9895

@@ -129,7 +126,7 @@ namespace random {
129126
T deterministic_rnd(const seed_t seed,
130127
const T Rmin, const T Rmax) {
131128
// TODO: Use a lookup table/cache?
132-
uniform_generic_distribution<T> dist(Rmin, Rmax);
129+
uniform_generic_open_range_distribution<T> dist(Rmin, Rmax);
133130
deterministic_generator.seed(seed);
134131
return dist(deterministic_generator);
135132
}

0 commit comments

Comments
 (0)