I created a C++ templated "sample" function which uses Boost random number generators to sample from any object that provides a multinomial distribution as an iterable object.
/** Sample a value from a multinomial law with coefficient of modalities provided */
template<typename T>
int sample(const T& proportion)
{
boost::random::uniform_real_distribution<> uni(0.,
1.);
boost::variate_generator<boost::random::mt19937&,
boost::random::uniform_real_distribution<> > generator(rng_,
uni);
Real x = generator();
Real cumProb = 0.; // cumulative probability
int index = 0;
for(typename T::const_iterator it = proportion.begin();
it != proportion.end();
++it)
{
cumProb += *it;
if (x < cumProb)
{
return index;
}
++index;
}
return -1; // to accelerate sampling, no check have been computed on modalities to verify that is it actually a probability distribution
};
When I call this using an Eigen vector for example (on which I have added an iterator), I get the following error in Valgrind:
==4917== Conditional jump or move depends on uninitialised value(s)
==4917== at 0xD7B0A3C: int mixt::MultinomialStatistic::sample<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, -1, -1, false> >(Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, -1, -1, false> const&) (mixt_MultinomialStatistic.h:76)
==4917== by 0xD7B0538: mixt::ClassSampler::sampleIndividual(int) (mixt_ClassSampler.cpp:63)
==4917== by 0xD7ADBE6: mixt::IMixtureComposerBase::sStep(int) (mixt_IMixtureComposerBase.cpp:94)
==4917== by 0xD7ADAF0: mixt::IMixtureComposerBase::sStep() (mixt_IMixtureComposerBase.cpp:68)
==4917== by 0xD7AC3DE: mixt::SemStrategy::run() (mixt_SEMStrategy.cpp:83)
==4917== by 0xD74F742: mixtCompCluster(Rcpp::Vector<19, Rcpp::PreserveStorage>, Rcpp::Vector<19, Rcpp::PreserveStorage>, int, double) (mixtCompCluster.cpp:123)
==4917== by 0xD749A61: RMixtComp_mixtCompCluster (RcppExports.cpp:18)
==4917== by 0x4F0ADE7: ??? (in /usr/lib/R/lib/libR.so)
==4917== by 0x4F4981A: Rf_eval (in /usr/lib/R/lib/libR.so)
==4917== by 0x4F4B92F: ??? (in /usr/lib/R/lib/libR.so)
==4917== by 0x4F49622: Rf_eval (in /usr/lib/R/lib/libR.so)
==4917== by 0x4F4A93E: Rf_applyClosure (in /usr/lib/R/lib/libR.so)
==4917==
The line mixt_MultinomialStatistic.h:76 corresponds to if (x < cumProb)
. It seems to me that both x and cumProb are defined at this point. How can I debug this ?
EDIT
As suggested by Beta in the comments, I added the following dummy code:
if (x < 1000.)
{}
if (-1000. < cumProb)
{}
if (x < cumProb)
{ ...
And I still get the error reported for the line if (x < cumProb)
.
When lauching valgrind with the option --track-origins=yes
, I get the following indication
==10074== Uninitialised value was created by a stack allocation
pointing to the instruction:
cumProb += *it;
I faced a somewhat similar question when searching my (unit test) code for uninitialized values and found out that Eigen matrices' (and vectors') values don't get initialized in their default constructors. I had such a vector in a struct and eventually got rid of the problem using a statement à la:
Note that I had a hard time debugging this because when launching the unit test with gdb the vector would happen to contain zeros though uninitialized.