32 #ifndef VSMC_RNG_DISCRETE_DISTRIBUTION_HPP
33 #define VSMC_RNG_DISCRETE_DISTRIBUTION_HPP
38 #define VSMC_RUNTIME_ASSERT_RNG_DISCRETE_DISTRIBUTION_POSITIVE(param) \
39 VSMC_RUNTIME_ASSERT(is_positive(param), \
40 ("**DiscreteDistribution** WEIGHTS ARE NOT NON-NEGATIVE"));
46 template <
typename IntType =
int>
56 template <
typename InputIter>
64 #if VSMC_HAS_CXX11LIB_INITIALIZER_LIST
66 param_(weights.begin(), weights.end())
73 template <
typename UnaryOperation>
75 UnaryOperation unary_op)
77 param_.reserve(count);
78 double delta = (xmax - xmin) / static_cast<double>(count);
80 for (std::size_t i = 0; i != count; ++i)
81 param_.push_back(unary_op(xmin + static_cast<double>(i) * delta));
93 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
102 param_type
param ()
const {
return param_;}
111 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
124 {
return param_.size() == 0 ? 0 : param_.size() - 1;}
128 template <
typename URNG>
130 {
return operator()(eng, param_.begin(), param_.end(),
true);}
154 template <
typename URNG,
typename InputIter>
155 result_type
operator() (URNG &eng, InputIter first, InputIter last,
156 bool normalized =
false)
const
158 typedef typename std::iterator_traits<InputIter>::value_type
161 cxx11::uniform_real_distribution<value_type> runif(0, 1);
162 value_type u = runif(eng);
165 value_type mulw = 1 / std::accumulate(first, last,
166 static_cast<value_type>(0));
168 result_type index = 0;
169 while (first != last) {
170 accw += *first * mulw;
181 result_type index = 0;
182 while (first != last) {
196 {
return rdisc1.param_ == rdisc2.param_;}
201 {
return rdisc1.param_ != rdisc2.param_;}
203 template <
typename CharT,
typename Traits>
204 friend inline std::basic_ostream<CharT, Traits> &
operator<< (
205 std::basic_ostream<CharT, Traits> &os,
211 os << rdisc.param_.size() <<
' ';
213 if (rdisc.param_.size() == 0)
216 if (rdisc.param_.size() == 1) {
217 os << rdisc.param_[0];
221 for (std::size_t i = 0; i != rdisc.param_.size() - 1; ++i)
222 os << rdisc.param_[i] <<
' ';
223 os << rdisc.param_.back();
228 template <
typename CharT,
typename Traits>
229 friend inline std::basic_istream<CharT, Traits> &
operator>> (
230 std::basic_istream<CharT, Traits> &is,
239 std::vector<double>
param(n);
240 for (std::size_t i = 0; i != n; ++i)
241 is >> std::ws >> param[i];
244 if (rdisc.is_positive(param)) {
248 is.setstate(std::ios_base::failbit);
261 if (param_.size() == 0)
264 double sumw = std::accumulate(param_.begin(), param_.end(), 0.0);
265 math::scal(param_.size(), 1 / sumw, ¶m_[0]);
268 bool is_positive (
const param_type &
param)
270 for (std::size_t i = 0; i != param.size(); ++i)
274 if (param.size() == 0)
277 if (std::accumulate(param.begin(), param.end(), 0.0) <= 0)
286 #endif // VSMC_RNG_DISCRETE_DISTRIBUTION_HPP
DiscreteDistribution(InputIter first, InputIter last)
DiscreteDistribution(std::size_t count, double xmin, double xmax, UnaryOperation unary_op)
void param(const param_type ¶m)
#define VSMC_RUNTIME_ASSERT_RNG_DISCRETE_DISTRIBUTION_POSITIVE(param)
std::vector< double > probability() const
DiscreteDistribution(param_type &¶m)
std::vector< double > param_type
#define VSMC_MNE
Avoid MSVC stupid behavior: MNE = Macro No Expansion.
result_type operator()(URNG &eng) const
void scal(std::size_t n, T a, T *x)
Scale a vector.
remove_reference< T >::type && move(T &&t) noexcept
DiscreteDistribution(const param_type ¶m)
friend bool operator==(const DiscreteDistribution< IntType > &rdisc1, const DiscreteDistribution< IntType > &rdisc2)
void swap(Array< T, N > &ary1, Array< T, N > &ary2)
Array ADL of swap.
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, DiscreteDistribution< IntType > &rdisc)
Draw a single sample given weights.
void param(param_type &¶m)
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const DiscreteDistribution< IntType > &rdisc)
friend bool operator!=(const DiscreteDistribution< IntType > &rdisc1, const DiscreteDistribution< IntType > &rdisc2)