|
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