12#ifndef EIGENRAND_MVDISTS_MULTINOMIAL_H 
   13#define EIGENRAND_MVDISTS_MULTINOMIAL_H 
   25        template<
typename _Scalar = int32_t, Index Dim = -1>
 
   28            static_assert(std::is_same<_Scalar, int32_t>::value, 
"`MultinomialGen` needs integral types.");
 
   30            Matrix<double, Dim, 1> probs;
 
   40            template<
typename WeightTy>
 
   42                : trials{ _trials }, probs{ _weights.template cast<double>() }, 
discrete(probs.data(), probs.data() + probs.size())
 
   44                eigen_assert(_weights.cols() == 1);
 
   45                for (Index i = 0; i < probs.size(); ++i)
 
   47                    eigen_assert(probs[i] >= 0);
 
   58            Index dims()
 const { 
return probs.rows(); }
 
   60            template<
typename Urng>
 
   61            inline Matrix<_Scalar, Dim, -1> generate(Urng&& urng, Index samples)
 
   63                const Index dim = probs.size();
 
   64                Matrix<_Scalar, Dim, -1> ret(dim, samples);
 
   65                if (trials < std::max(30 * (dim - 1), (Index)100))
 
   67                    for (Index s = 0; s < samples; ++s)
 
   69                        ret.col(s) = generate(urng);
 
   74                    Array<_Scalar, 1, -1> r_trials{ samples }, t{ samples };
 
   75                    Map<
const Array<float, -1, 1>> fr_trials{ 
reinterpret_cast<float*
>(r_trials.data()), samples };
 
   76                    Map<Array<float, -1, 1>> ft{ 
reinterpret_cast<float*
>(t.data()), samples };
 
   77                    r_trials.setConstant(trials);
 
   78                    ft = impl::binomial(urng, fr_trials, probs[0]);
 
   80                    ret.row(0) = t.matrix();
 
   81                    double rest_p = 1 - probs[0];
 
   82                    for (Index i = 1; i < dim - 1; ++i)
 
   84                        ft = impl::binomial(urng, fr_trials, probs[i] / rest_p);
 
   86                        ret.row(i) = t.matrix();
 
   90                    ret.row(dim - 1) = r_trials;
 
   95            template<
typename Urng>
 
   96            inline Matrix<_Scalar, Dim, 1> generate(Urng&& urng)
 
   98                const Index dim = probs.size();
 
   99                Matrix<_Scalar, Dim, 1> ret(dim);
 
  103                    auto d = 
discrete.template generate<Matrix<_Scalar, 16, 1>>(16, 1, urng);
 
  104                    Matrix<_Scalar, 16, 1> buf;
 
  106                    for (i = 0; i < (trials & ~15); i += 16)
 
  109                        for (Index j = 0; j < 16; ++j)
 
  114                    buf.middleRows(0, trials - i) = d.middleRows(0, trials - i);
 
  115                    for (Index j = 0; j < trials - i; ++j)
 
  146        template<
typename IntTy, 
typename WeightTy>
 
  159        template<
typename _Scalar, Index Dim = -1>
 
  162            static_assert(std::is_floating_point<_Scalar>::value, 
"`DirichletGen` needs floating point types.");
 
  164            Matrix<_Scalar, Dim, 1> alpha;
 
  165            std::vector<GammaGen<_Scalar>> gammas;
 
  173            template<
typename AlphaTy>
 
  177                eigen_assert(_alpha.cols() == 1);
 
  178                for (Index i = 0; i < alpha.size(); ++i)
 
  180                    eigen_assert(alpha[i] > 0);
 
  181                    gammas.emplace_back(alpha[i]);
 
  188            Index dims()
 const { 
return alpha.rows(); }
 
  190            template<
typename Urng>
 
  191            inline Matrix<_Scalar, Dim, -1> generate(Urng&& urng, Index samples)
 
  193                const Index dim = alpha.size();
 
  194                Matrix<_Scalar, Dim, -1> ret(dim, samples);
 
  195                Matrix<_Scalar, -1, 1> tmp(samples);
 
  196                for (Index i = 0; i < dim; ++i)
 
  198                    tmp = gammas[i].generateLike(tmp, urng);
 
  199                    ret.row(i) = tmp.transpose();
 
  201                ret.array().rowwise() /= ret.array().colwise().sum();
 
  205            template<
typename Urng>
 
  206            inline Matrix<_Scalar, Dim, 1> generate(Urng&& urng)
 
  208                const Index dim = alpha.size();
 
  209                Matrix<_Scalar, Dim, 1> ret(dim);
 
  210                for (Index i = 0; i < dim; ++i)
 
  212                    ret[i] = gammas[i].template generate<Matrix<_Scalar, 1, 1>>(1, 1, urng)(0);
 
  227        template<
typename AlphaTy>
 
Generator of reals on a Dirichlet distribution.
Definition: Multinomial.h:161
DirichletGen(const MatrixBase< AlphaTy > &_alpha)
Construct a new Dirichlet generator.
Definition: Multinomial.h:174
Generator of integers on the interval [0, n), where the probability of each individual integer i is p...
Definition: Discrete.h:329
Generator of real vectors on a multinomial distribution.
Definition: Multinomial.h:27
MultinomialGen(_Scalar _trials, const MatrixBase< WeightTy > &_weights)
Construct a new multinomial generator.
Definition: Multinomial.h:41
Base class of all multivariate random vector generators.
Definition: Basic.h:160
auto makeMultinomialGen(IntTy trials, const MatrixBase< WeightTy > &probs) -> MultinomialGen< IntTy, MatrixBase< WeightTy >::RowsAtCompileTime >
helper function constructing Eigen::Rand::MultinomialGen
Definition: Multinomial.h:147
auto makeDirichletGen(const MatrixBase< AlphaTy > &alpha) -> DirichletGen< typename MatrixBase< AlphaTy >::Scalar, MatrixBase< AlphaTy >::RowsAtCompileTime >
helper function constructing Eigen::Rand::DirichletGen
Definition: Multinomial.h:228
const DiscreteType< Derived, Urng > discrete(Index rows, Index cols, Urng &&urng, RealIter first, RealIter last)
generates random integers on the interval [0, n), where the probability of each individual integer i ...
Definition: Discrete.h:1580