Boost logo

Boost :

From: Kris Thielemans (kris.thielemans_at_[hidden])
Date: 2004-07-05 20:04:47


Hi

3 more comments on the random number library.

1) Further on the topic started by Oliver Kullmann, and the reply by
Cromwell Enage:

-------Start Quote:---------
  typedef boost::uniform_int<> UniformDist;
  UniformDist dist(min,max);
  typedef boost::mt19937 BaseRNG;
  BaseRNG rng;
  boost::variate_generator<BaseRNG&,UniformDist>
     your_generator(rng, dist);

Note the ampersand; your program will fail silently if
you omit it.
-------End Quote:---------

An example why you could need the &:

Suppose you have your_generator being defined locally, as it depends on
some run-time parameters

  int f(int min, int max)
  {
     UniformDist dist(min,max);
     static BaseRNG rng;
     boost::variate_generator<BaseRNG&,UniformDist>
        your_generator(rng, dist);
     return your_generator();
  }

If you don't have the &, the variate_generator constructor will make a
fresh copy of the
rng object every time f() is called. Result: your random number will
always be the same!

On the other hand, using it without ampersand works fine for me in other
situations.

I find this rather subtle (i.e. it took me a few hours to understand why
my data were not what they should have been). So, maybe the
documentation for variate_generator should be more explicit about this.
I've tried to write a doc for this, but find that it probably needs
explicit examples. Here it is anyway

"Whether you use a reference, pointer, or 'plain' type for the Engine
template parameter of variate_generator<Engine, Distribution> depends on
similar considerations as for ordinary functions. E.g. if a reference is
used, subsequent calls of the variate_generator::operator() will modify
the state of the referenced Engine object, which is probably useful if
the same Engine object is used for multiple variate_generator<Engine,
Distribution> objects. "

--------------------------------------------------

2) While on the topic of references, the following generates a compiler
error.

  boost::uniform_01<BaseRNG &> random01(generator)

/home/kris/mydoc/include/boost/random/uniform_01.hpp:58: error: forming
   reference to reference type `stir::base_generator_type&'

--------------------------------------------------

3) on distribution::operator()(Engine& eng)

template<class Engine>
normal_distribution::operator()(Engine& eng) assumes that Engine is like
uniform_01. This not documented, and worse, also not checked in the
code.

  template<class Engine>
  result_type operator()(Engine& eng)
  {
    if(!_valid) {
      _r1 = eng();
      _r2 = eng();
      _cached_rho = sqrt(-result_type(2) * log(result_type(1)-_r2));
      _valid = true;
    } else {
      _valid = false;
    }
    // etc

I would recommend to insert something like
        assert(eng.min()==result_type(0));
        assert(eng.max()==result_type(1));
        
BOOST_STATIC_ASSERT(!std::numeric_limits<Engine::result_type>::is_intege
r);

Of course, when using
        variate_generator<Engine, normal_distribution<double> >
the Engine is converted into a uniform_01 if necessary.

I'm afraid that the same is true for the gamma_distribution and
geometric_distribution class. So, maybe
some_distribution::operator()(Engine& eng) should not be used at all. If
so, it should not be public (at least for compilers that can do template
friends I guess). However, it is required by the 'Random Distribution'
concept. Any particular reason that we need it?

Kris Thielemans
Hammersmith Imanet
Du Cane Road
London W12 0NN
UK
http://www.HammersmithImanet.com/~kris
 


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk