Boost logo

Boost Users :

Subject: Re: [Boost-users] [random] Singleton engine
From: Diederick C. Niehorster (dcnieho_at_[hidden])
Date: 2009-08-16 23:51:24


Hi Kevin, others,

Thank you for your responses, sorry for the long delay.

I have decided to try to do without the whole singleton (although I
don't really see what the point is of avoiding a singleton if we still
have a global pointer, its almost the same thing) as an exercise and
try out Kevin's implementation.

I made some small changes to the code (code at bottom fo post) to make
sure that the generator is constructed if it wasn't yet (and seeded in
the process) so i don't have to do that by hand in my code. That
exactly fits what i need, and as it is seeded automatically, i cannot
forget to do so. I would never want to change my seed, nor be able to
set it to a specific value manually.

On Wed, Aug 5, 2009 at 12:10 AM, Kevin Martin<kev82_at_[hidden]> wrote:
>
> On 4 Aug 2009, at 06:39, Diederick C. Niehorster wrote:
>
> I have looked it up, thank you for the suggestion. I, however do not
> see the advantage of wrapping the generator.
>
> Well you are wrapping up the variate_generator yourself with your
> specializations of the CRandom template. My suggestion is that
> instead of your CRandom class, you just return the variate_generator
> inside a boost function.
>

Hmm, i have tried so, but the syntax to actually extract the random
numbers becomes very complicated now (I think i am missing a point
here, i am new to boost.function). With my class, i could simply
create an instance of a variate generator and then get a random number
using the () operator. See example:

CRandom<boost::uniform_int<int>> Cr(1,100);
int test = Cr();

which with a typedef "typedef CRandom<b::uniform_int<int>> CRandomI;"
i can easily shorten to:

CRandomI Cr(1,100);
int test = Cr();

I have only managed to find two ways to get my random number using the
boost.function approach, both of which need considerably more typeing
by the user. It makes me want to wrap the boost.function in a class...
(Method one is stupid of course, it would generate a new distribution
every time i request a number.)

What step am I still missing here?

Thanks and best regards,
Diederick

----
// includes
#include <boost/random.hpp>
#include <time.h>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
// could use a macro to set the generator used in the code, for easy change
// kevin martin:
static boost::shared_ptr<boost::mt19937> generator_;
void grng_setGenerator(boost::shared_ptr<boost::mt19937> ptr)
{
    if(!ptr) throw std::runtime_error("Tried to set generator to NULL pointer");
    if(generator_) throw std::runtime_error("Tried to set generator
more than once");
    generator_ = ptr;
}
boost::mt19937 &grng_generator()
{
    if(generator_) return *generator_;
    // if doesn't exist, set
    grng_setGenerator(boost::shared_ptr<boost::mt19937>(new
boost::mt19937(unsigned int(time(NULL)))));
    if(generator_) return *generator_;
    // if still doesn't exist, error
    throw std::runtime_error("Requested RNG, but there isn't one");
}
template<class Distribution_>
boost::function<typename Distribution_::result_type ()>
grng_randomVariable(const Distribution_ &d)
{
    boost::variate_generator<boost::mt19937&, Distribution_>
rv(grng_generator(), d);
    return boost::function<typename Distribution_::result_type ()>(rv);
}
//main
int main(int argc, char* argv[])
{
    // 1
    int a = grng_randomVariable(boost::uniform_int<int>(1,100))();
    std::cout << a << std::endl;
    // 2
    boost::function<int ()>
Ci(grng_randomVariable(boost::uniform_int<int>(1,100)));
    std::cout << Ci() << std::endl;
    return 1;
}

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net