|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Hi!
I'm working on a random number generator which makes use of Boost::random. I have to write a function that gets 2 int-parameters from the GUI. One is a number that indicates which algorithm to use and the other shows which distribution we have to use. Boost uses templates so I cannot use polymorphism (Or is there a way to use polymorphism even if the classes aren't derivated from a base class?). I tried to use a template function, but I don't know the types when I call the fuction (xxParam are static variables): template<class boostEngine, class boostDistribution> void GenRandBoost() { ///Cache parameters ulong amount = amountParam; ulong ulSeed = seedParam; string filename = filenameParam; double ulDouble = ulDoubleParam; double llDouble = llDoubleParam; int distributionSelection = distributionSelectionParam; int algorithmSelection = algorithmSelectionParam; ulong bits = bitsParam; ///Initialize template pointers boostEngine *algorithm; boostDistribution *distribution; ///Open fstream fstream f(filename.c_str(), fstream: ut);//Initialize counter ulong i; ///Switch distribution switch(algorithmSelection) { case 0: ///MT 19937 { mt19937 mersenne(ulSeed); algorithm = &mersenne; break; } case 1: ///Linear congruential { minstd_rand0 linCongr(ulSeed); algorithm = &linCongr; break; } case 2: ///Additive combine { ecuyer1988 addComb(ulSeed); algorithm = &addComb; break; } case 3: ///Inverse congruential { hellekalek1995 invCongr(ulSeed); algorithm = &invCongr; break; } case 4: ///Shuffle output { kreutzer1986 shOut(ulSeed); algorithm = &shOut; break; } // case 5: ///Lagged Fibonacci // { // lagged_fibonacci lagFib(ulSeed); // algorithm = &lagFib; // break; // } default: break; } ///Switch distribution switch(distributionSelection) { case 0: ///Uniform small int { uniform_smallint<double> smallInt(llDouble, ulDouble); distribution = &smallInt; } case 1: ///Uniform integer { uniform_int<double> uniInt(llDouble, ulDouble); distribution = &uniInt; } case 2: ///Uniform 01 { //uniform_01<double, double> uni01(llDouble, ulDouble); //distribution = &uni01; } case 3: ///Uniform real { uniform_real<double> uniReal(llDouble, ulDouble); distribution = &uniReal; } case 4: ///Triangle { triangle_distribution<double> triangle(llDouble, ulDouble); distribution = ▵ } case 5: ///Bernoulli { bernoulli_distribution<double> bernoulli(llDouble, ulDouble); distribution = &bernoulli; } case 6: ///Cauchy { cauchy_distribution<double> cauchy(llDouble, ulDouble); distribution = &cauchy; } case 7: ///Exponential { exponential_distribution<double> exponential(llDouble, ulDouble); distribution = &exponential; } case 8: ///Geometric { geometric_distribution<double> geometric(llDouble, ulDouble); distribution = &geometric; } case 9: ///Normal { normal_distribution<double> normal(llDouble, ulDouble); distribution = &normal; } case 10: ///Lognormal { lognormal_distribution<double> lognormal(llDouble, ulDouble); distribution = &lognormal; } case 11: ///Uniform on Sphere { uniform_on_sphere<double> uniSphere(llDouble, ulDouble); distribution = &uniSphere; } default: {break;} } ///Variate Generator variate_generator<boostEngine, boostDistribution> generator(algorithm, distribution); ///TODO: Main loop for(;i < amount;i++) { f << generator() << endl; } } I don't want to have a distributionSelection switch in each algorithmSelection case statement. Do you have any ideas? Thanks in advance, Hans |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Have not looked at everything but I suspect that you are using objects after they have been destroyed: case 0: ///MT 19937 { mt19937 mersenne(ulSeed); algorithm = &mersenne; break; } Here the object mersenne is destroyed when it goes out of scope. Thus algorithm is left as a dangling pointer to some random piece of memory (That will probably be re-used by another object very soon). You can't use template functions to determine something at runtime. As the template instantiation is done at compile time. So a switch is your best option. Though personally I would move the switch into another object (FactoryPattern) thus keeping this method cleaner and easier to read. |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Feb 8, 4:16 pm, Martin York <Martin.YorkAma...@gmail.com> wrote:
> Have not looked at everything but I suspect that you are using objects > after they have been destroyed: > > case 0: ///MT 19937 > { > mt19937 mersenne(ulSeed); > algorithm = &mersenne; > break; > } > > Here the object mersenne is destroyed when it goes out of scope. > Thus algorithm is left as a dangling pointer to some random piece of > memory (That will probably be re-used by another object very soon). > > You can't use template functions to determine something at runtime. As > the template instantiation is done at compile time. So a switch is > your best option. Though personally I would move the switch into > another object (FactoryPattern) thus keeping this method cleaner and > easier to read. Also the OP should evaluate the Strategy Pattern. -- Cholo Lennon Bs.As. ARG |
|
![]() |
| Outils de la discussion | |
|
|