0

I'm trying to learn C++11 random stuff, so I've copied an example from this site found here on stackoverflow...

What I want to achive here is using a std::xor_combine template to combine two engines and initilize it with 3th engine. according to link abowe this should be possible but it looks that some things are changed here since Tr1 report?

Also you'll se a exponential distrubution object bellow in the code, So one more question is how do I combine xor_combine lobject with distribution so that I pass the "combin" into distributions operator() ?

Visual studio gives me an error described in the code bellow...

#include<iostream>
#include<random>
#include<ctime>
using namespace std;

int main()

{
    minstd_rand gen1;
    mt19937 gen2;
    linear_congruential_engine<unsigned long, 34999, 0, 3405989> seeder;

seeder.seed(static_cast<unsigned long>(time(false)));
xor_combine<minstd_rand, 4, mt19937, 9> combin;

exponential_distribution<float> expdist(2);

combin.seed(seeder);

// generate numbers
for(int i = 0; i < 10; ++i)     // error in <random> 
    cout << combin() << endl; // ERROR  C:2039 generate is not a member of std::congruential_engine<...> etc... 

cin.get();
    return 0;
}

1. How do I pass 3th engine into xor_combine object?

2. How do I pas xor_combine object into distribution object? *EDIT*

#include<iostream>
#include<random>
#include<ctime>
int main()
{
    std::minstd_rand gen1;
    std::mt19937 gen2;
    std::xor_combine<std::minstd_rand, 3, std::mt19937, 6> combin(gen1, gen2);
    std::uniform_int_distribution<unsigned int> dist(0,37);
    combin.seed(static_cast<unsigned int>(time(0)));
    std::cout << dist( combin ) << std::endl;
    std::cin.get();
    return 0;
}

Error 1 error C2352: 'std::xor_combine<_Engine1,_S1,_Engine2,_S2>::max' : illegal call of non-static member function c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility 3455 Project1 1

codekiddy
  • 5,897
  • 9
  • 50
  • 80

1 Answers1

2

std::xor_combine does not exist in C++11. It has been removed as a resolution to Library Defect Report 789.

Non-controversial. Bill is right, but Fermilab believes that this is easy to use badly and hard to use right, and so it should be removed entirely. Got into TR1 by well defined route, do we have permission to remove stuff? Should probably check with Jens, as it is believed he is the originator. Broad consensus that this is not a robust engine adapter.

MSDN is not a reference to the real standard. See Where do I find the current C or C++ standard documents? to how to get the standard.


Your "generate is not a member" problem is because of

combin.seed(seeder);

which will effectively call

combin.base1().seed(seeder); // ignoring the const-ref
combin.base2().seed(seeder);

In TR1, the random number generators can be seeded by another random number generator (n1836 Table 16). However, in C++11, random number generators should be seeded by "seed sequence" instead (n3290 §26.5.1.2, not sure when the change is introduced). C++11 does not have concepts to check whether that seeder is a RNG or seed sequence in invocation, so the template instantiation will assume seeder is a seed sequence. One of the requirement of "seed sequence" is to have a .generate member function (n3290 Table 115), which is why you encountered the compiler error.

You could try to solve this by using the TR1 engines, which does not know about the "seed sequence" concept, or you could wrap the RNG into an input iterator and then into a std::seed_seq, or just seed with a number.

unsigned long seed = ....;
combin.seed(seed);

And for your last 2 questions:

  1. Notice that XOR is associative. That means, you could just use

    xor_combine<RNGa, sa, xor_combine<RNGb, sb, RNGc, sc>, 0>
    

    to combine 3 engines

  2. You pass an xor_combine object to a distribution like all other RNGs, e.g.

    std::uniform_int_distribution<> d(0, 10);
    std::cout << d(combin) << std::endl;
    
Community
  • 1
  • 1
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • Thank you so much for that explanation Kenny, Do you have an example on how to pass a combined generator into distribution? That's possible for 1 generator ie. dist(gen) but how do I do that ie dist(combin) ? – codekiddy Apr 29 '12 at 09:17
  • Ok, sily me, I deleted my previous comment :D is there a way to combine 2 engines in current c++11? thanks so much. – codekiddy Apr 29 '12 at 09:43
  • 1
    @codekiddy: You could write your own generator. But why would you need to do so? Mixing two RNG doesn't often make a better RNG. – kennytm Apr 29 '12 at 09:49