I have a program that uses the mt19937 random number generator from boost::random. I need to do a random_shuffle and want the random numbers generated for this to be from th
In the comments, Robert Gould asked for a working version for posterity:
#include <algorithm>
#include <functional>
#include <vector>
#include <boost/random.hpp>
struct bar : std::unary_function<unsigned, unsigned> {
boost::mt19937 &_state;
unsigned operator()(unsigned i) {
boost::uniform_int<> rng(0, i - 1);
return rng(_state);
}
bar(boost::mt19937 &state) : _state(state) {}
};
void foo(std::vector<unsigned> &vec, boost::mt19937 &state)
{
bar rand(state);
std::random_shuffle(vec.begin(), vec.end(), rand);
}
In C++03, you cannot instantiate a template based on a function-local type. If you move the rand class out of the function, it should work fine (disclaimer: not tested, there could be other sinister bugs).
This requirement has been relaxed in C++0x, but I don't know whether the change has been implemented in GCC's C++0x mode yet, and I would be highly surprised to find it present in any other compiler.
I thought it was worth pointing out that this is now pretty straightforward in C++11 using only the standard library:
#include <random>
#include <algorithm>
std::random_device rd;
std::mt19937 randEng(rd());
std::shuffle(vec.begin(), vec.end(), randEng);
I'm using tr1 instead of boost::random here, but should not matter much.
The following is a bit tricky, but it works.
#include <algorithm>
#include <tr1/random>
std::tr1::mt19937 engine;
std::tr1::uniform_int<> unigen;
std::tr1::variate_generator<std::tr1::mt19937,
std::tr1::uniform_int<> >gen(engine, unigen);
std::random_shuffle(vec.begin(), vec.end(), gen);