Boost logo

Boost :

From: Doug Gregor (dgregor_at_[hidden])
Date: 2004-12-30 17:24:34

I'm having a few problems dealing with uniform_real and uniform_01.

The basic issue is that uniform_real does not always produce values
between its min and its max. The problem consistently occurs when I'm
using minstd_rand as my generator (one of the linear_congruential
variants). For instance, if I write:

   template<typename RandomNumberGenerator>
   void foo(RandomNumberGenerator& gen)
     uniform_int<int> rand_int(some_min_int, some_max_int);
     // Okay, some_min_int <= x <= some_max_int
     int x = rand_int(gen);

     uniform_real<double> rand_double(some_min_double, some_max_double);
     // Uh-oh, some_min_double <= y <= some_max_double doesn't always
     double y = rand_double(gen);

Looking at the source to uniform_real, the problem is obvious:

   result_type operator()(Engine& eng) { return eng() * (_max - _min) +
_min; }

uniform_real assumes that the engine returns a value in [0, 1], but
doesn't check that. If this is correct (I hope it isn't!), the
"obvious" answer is to use uniform_01<RandomNumberGenerator...> as
input to uniform_real. However, uniform_01 is also broken in several

        1) It isn't a random distribution because its operator() does not
accept an engine. Instead, the engine is embedded in the uniform_01
        2) uniform_01 stores the incoming random number generator by _value_,
so the original generator "gen" does not advance. You can't even fake
it with uniform_01<RandomNumberGenerator&>, because that creates
reference-to-reference problems.

Below is a small patch to make uniform_real<...> behave nicely. As for
uniform_01: we should deprecate it in 1.33.0 and remove it afterwords,
because it is hopelessly broken and not even included in the TR.


Index: uniform_real.hpp
RCS file: /cvsroot/boost/boost/boost/random/uniform_real.hpp,v
retrieving revision 1.14
diff -u -r1.14 uniform_real.hpp
--- uniform_real.hpp 27 Jul 2004 03:43:32 -0000 1.14
+++ uniform_real.hpp 30 Dec 2004 22:11:33 -0000
@@ -50,7 +50,11 @@
    void reset() { }

    template<class Engine>
- result_type operator()(Engine& eng) { return eng() * (_max - _min) +
_min; }
+ result_type operator()(Engine& eng) {
+ return static_cast<result_type>(eng() - eng.min())
+ / (eng.max() - eng.min())
+ * (_max - _min) + _min;
+ }

    template<class CharT, class Traits>

Boost list run by bdawes at, gregod at, cpdaniel at, john at