12 #if !defined(RANDOMLIB_RANDOMSELECT_HPP)
13 #define RANDOMLIB_RANDOMSELECT_HPP 1
21 # pragma warning (push)
22 # pragma warning (disable: 4127)
93 template<
typename WeightType>
105 template<
typename InputIterator>
112 { _k = 0; _wsum = 0; _wmax = 0; _Q.clear(); _Y.clear(); }
121 template<
typename WeightType>
122 void Init(
const std::vector<WeightType>& w) {
Init(w.begin(), w.end()); }
132 template<
typename InputIterator>
133 void Init(InputIterator a, InputIterator b) {
148 template<
class Random>
152 const unsigned K = r.template Integer<unsigned>(_k);
154 return (std::numeric_limits<NumericType>::is_integer ?
155 r.template Prob<NumericType>(NumericType(_Q[K]),
156 NumericType(_wsum)) :
157 r.template Prob<NumericType>(NumericType(_Q[K]))) ?
176 NumericType
Weight(
unsigned i)
const throw() {
178 return NumericType(0);
181 const NumericType n = std::numeric_limits<NumericType>::is_integer ?
182 _wsum : NumericType(1);
183 NumericType p = _Q[i];
184 for (
unsigned j = _k; j;)
189 return (p / NumericType(_k)) * (_wsum / n);
195 unsigned Choices()
const throw() {
return _k; }
206 std::vector<NumericType> _Q;
210 std::vector<unsigned> _Y;
222 template<
typename NumericType>
template<
typename InputIterator>
225 typedef typename std::iterator_traits<InputIterator>::value_type
229 !std::numeric_limits<NumericType>::is_integer,
230 "RandomSelect: inconsistent WeightType and NumericType");
235 std::numeric_limits<NumericType>::is_integer ||
236 std::numeric_limits<NumericType>::digits >=
237 std::numeric_limits<WeightType>::digits,
238 "RandomSelect: NumericType insufficiently precise");
242 std::vector<NumericType> p;
244 for (InputIterator wptr = a; wptr != b; ++wptr) {
247 if (!(*wptr > 0 || *wptr == 0))
249 throw RandomErr(
"RandomSelect: Illegal weight");
250 NumericType w = NumericType(*wptr);
251 if (w > (std::numeric_limits<NumericType>::max)() - _wsum)
252 throw RandomErr(
"RandomSelect: Overflow");
254 _wmax = w > _wmax ? w : _wmax;
258 _k = unsigned(p.size());
260 throw RandomErr(
"RandomSelect: Zero total weight");
269 if ((std::numeric_limits<NumericType>::max)()/NumericType(_k) <
271 throw RandomErr(
"RandomSelect: Overflow");
273 std::vector<unsigned> j(_k);
284 for (
unsigned i = 0; i < _k; ++i) {
285 p[i] *= NumericType(_k);
286 j[p[i] > _wsum ? v-- : u++] = i;
301 const NumericType n = std::numeric_limits<NumericType>::is_integer ?
302 NumericType(1) : _wsum;
306 _Q[j[u]] = p[j[u]] / n;
311 _Y[j[u]] = j[p[j[u]] < _wsum ? v : u];
320 p[j[v]] = p[j[v]] - (_wsum - p[j[u]]);
331 #if defined(_MSC_VER)
332 # pragma warning (pop)
335 #endif // RANDOMLIB_RANDOMSELECT_HPP
void Init(const std::vector< WeightType > &w)
RandomSelect(const std::vector< WeightType > &w)
Generate random integers, reals, and booleans.
Random selection from a discrete set.
NumericType Weight(unsigned i) const
void Init(InputIterator a, InputIterator b)
Exception handling for RandomLib.
#define STATIC_ASSERT(cond, reason)
unsigned operator()(Random &r) const
NumericType TotalWeight() const
NumericType MaxWeight() const