Chris@16
|
1 /* boost random/discrete_distribution.hpp header file
|
Chris@16
|
2 *
|
Chris@16
|
3 * Copyright Steven Watanabe 2009-2011
|
Chris@16
|
4 * Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
5 * accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7 *
|
Chris@16
|
8 * See http://www.boost.org for most recent version including documentation.
|
Chris@16
|
9 *
|
Chris@16
|
10 * $Id: discrete_distribution.hpp 85813 2013-09-21 20:17:00Z jewillco $
|
Chris@16
|
11 */
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef BOOST_RANDOM_DISCRETE_DISTRIBUTION_HPP_INCLUDED
|
Chris@16
|
14 #define BOOST_RANDOM_DISCRETE_DISTRIBUTION_HPP_INCLUDED
|
Chris@16
|
15
|
Chris@16
|
16 #include <vector>
|
Chris@16
|
17 #include <limits>
|
Chris@16
|
18 #include <numeric>
|
Chris@16
|
19 #include <utility>
|
Chris@16
|
20 #include <iterator>
|
Chris@16
|
21 #include <boost/assert.hpp>
|
Chris@16
|
22 #include <boost/random/uniform_01.hpp>
|
Chris@16
|
23 #include <boost/random/uniform_int.hpp>
|
Chris@16
|
24 #include <boost/random/detail/config.hpp>
|
Chris@16
|
25 #include <boost/random/detail/operators.hpp>
|
Chris@16
|
26 #include <boost/random/detail/vector_io.hpp>
|
Chris@16
|
27
|
Chris@16
|
28 #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
|
Chris@16
|
29 #include <initializer_list>
|
Chris@16
|
30 #endif
|
Chris@16
|
31
|
Chris@16
|
32 #include <boost/range/begin.hpp>
|
Chris@16
|
33 #include <boost/range/end.hpp>
|
Chris@16
|
34
|
Chris@16
|
35 #include <boost/random/detail/disable_warnings.hpp>
|
Chris@16
|
36
|
Chris@16
|
37 namespace boost {
|
Chris@16
|
38 namespace random {
|
Chris@16
|
39
|
Chris@16
|
40 /**
|
Chris@16
|
41 * The class @c discrete_distribution models a \random_distribution.
|
Chris@16
|
42 * It produces integers in the range [0, n) with the probability
|
Chris@16
|
43 * of producing each value is specified by the parameters of the
|
Chris@16
|
44 * distribution.
|
Chris@16
|
45 */
|
Chris@16
|
46 template<class IntType = int, class WeightType = double>
|
Chris@16
|
47 class discrete_distribution {
|
Chris@16
|
48 public:
|
Chris@16
|
49 typedef WeightType input_type;
|
Chris@16
|
50 typedef IntType result_type;
|
Chris@16
|
51
|
Chris@16
|
52 class param_type {
|
Chris@16
|
53 public:
|
Chris@16
|
54
|
Chris@16
|
55 typedef discrete_distribution distribution_type;
|
Chris@16
|
56
|
Chris@16
|
57 /**
|
Chris@16
|
58 * Constructs a @c param_type object, representing a distribution
|
Chris@16
|
59 * with \f$p(0) = 1\f$ and \f$p(k|k>0) = 0\f$.
|
Chris@16
|
60 */
|
Chris@16
|
61 param_type() : _probabilities(1, static_cast<WeightType>(1)) {}
|
Chris@16
|
62 /**
|
Chris@16
|
63 * If @c first == @c last, equivalent to the default constructor.
|
Chris@16
|
64 * Otherwise, the values of the range represent weights for the
|
Chris@16
|
65 * possible values of the distribution.
|
Chris@16
|
66 */
|
Chris@16
|
67 template<class Iter>
|
Chris@16
|
68 param_type(Iter first, Iter last) : _probabilities(first, last)
|
Chris@16
|
69 {
|
Chris@16
|
70 normalize();
|
Chris@16
|
71 }
|
Chris@16
|
72 #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
|
Chris@16
|
73 /**
|
Chris@16
|
74 * If wl.size() == 0, equivalent to the default constructor.
|
Chris@16
|
75 * Otherwise, the values of the @c initializer_list represent
|
Chris@16
|
76 * weights for the possible values of the distribution.
|
Chris@16
|
77 */
|
Chris@16
|
78 param_type(const std::initializer_list<WeightType>& wl)
|
Chris@16
|
79 : _probabilities(wl)
|
Chris@16
|
80 {
|
Chris@16
|
81 normalize();
|
Chris@16
|
82 }
|
Chris@16
|
83 #endif
|
Chris@16
|
84 /**
|
Chris@16
|
85 * If the range is empty, equivalent to the default constructor.
|
Chris@16
|
86 * Otherwise, the elements of the range represent
|
Chris@16
|
87 * weights for the possible values of the distribution.
|
Chris@16
|
88 */
|
Chris@16
|
89 template<class Range>
|
Chris@16
|
90 explicit param_type(const Range& range)
|
Chris@16
|
91 : _probabilities(boost::begin(range), boost::end(range))
|
Chris@16
|
92 {
|
Chris@16
|
93 normalize();
|
Chris@16
|
94 }
|
Chris@16
|
95
|
Chris@16
|
96 /**
|
Chris@16
|
97 * If nw is zero, equivalent to the default constructor.
|
Chris@16
|
98 * Otherwise, the range of the distribution is [0, nw),
|
Chris@16
|
99 * and the weights are found by calling fw with values
|
Chris@16
|
100 * evenly distributed between \f$\mbox{xmin} + \delta/2\f$ and
|
Chris@16
|
101 * \f$\mbox{xmax} - \delta/2\f$, where
|
Chris@16
|
102 * \f$\delta = (\mbox{xmax} - \mbox{xmin})/\mbox{nw}\f$.
|
Chris@16
|
103 */
|
Chris@16
|
104 template<class Func>
|
Chris@16
|
105 param_type(std::size_t nw, double xmin, double xmax, Func fw)
|
Chris@16
|
106 {
|
Chris@16
|
107 std::size_t n = (nw == 0) ? 1 : nw;
|
Chris@16
|
108 double delta = (xmax - xmin) / n;
|
Chris@16
|
109 BOOST_ASSERT(delta > 0);
|
Chris@16
|
110 for(std::size_t k = 0; k < n; ++k) {
|
Chris@16
|
111 _probabilities.push_back(fw(xmin + k*delta + delta/2));
|
Chris@16
|
112 }
|
Chris@16
|
113 normalize();
|
Chris@16
|
114 }
|
Chris@16
|
115
|
Chris@16
|
116 /**
|
Chris@16
|
117 * Returns a vector containing the probabilities of each possible
|
Chris@16
|
118 * value of the distribution.
|
Chris@16
|
119 */
|
Chris@16
|
120 std::vector<WeightType> probabilities() const
|
Chris@16
|
121 {
|
Chris@16
|
122 return _probabilities;
|
Chris@16
|
123 }
|
Chris@16
|
124
|
Chris@16
|
125 /** Writes the parameters to a @c std::ostream. */
|
Chris@16
|
126 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
|
Chris@16
|
127 {
|
Chris@16
|
128 detail::print_vector(os, parm._probabilities);
|
Chris@16
|
129 return os;
|
Chris@16
|
130 }
|
Chris@16
|
131
|
Chris@16
|
132 /** Reads the parameters from a @c std::istream. */
|
Chris@16
|
133 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
|
Chris@16
|
134 {
|
Chris@16
|
135 std::vector<WeightType> temp;
|
Chris@16
|
136 detail::read_vector(is, temp);
|
Chris@16
|
137 if(is) {
|
Chris@16
|
138 parm._probabilities.swap(temp);
|
Chris@16
|
139 }
|
Chris@16
|
140 return is;
|
Chris@16
|
141 }
|
Chris@16
|
142
|
Chris@16
|
143 /** Returns true if the two sets of parameters are the same. */
|
Chris@16
|
144 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
|
Chris@16
|
145 {
|
Chris@16
|
146 return lhs._probabilities == rhs._probabilities;
|
Chris@16
|
147 }
|
Chris@16
|
148 /** Returns true if the two sets of parameters are different. */
|
Chris@16
|
149 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
|
Chris@16
|
150 private:
|
Chris@16
|
151 /// @cond show_private
|
Chris@16
|
152 friend class discrete_distribution;
|
Chris@16
|
153 explicit param_type(const discrete_distribution& dist)
|
Chris@16
|
154 : _probabilities(dist.probabilities())
|
Chris@16
|
155 {}
|
Chris@16
|
156 void normalize()
|
Chris@16
|
157 {
|
Chris@16
|
158 WeightType sum =
|
Chris@16
|
159 std::accumulate(_probabilities.begin(), _probabilities.end(),
|
Chris@16
|
160 static_cast<WeightType>(0));
|
Chris@16
|
161 for(typename std::vector<WeightType>::iterator
|
Chris@16
|
162 iter = _probabilities.begin(),
|
Chris@16
|
163 end = _probabilities.end();
|
Chris@16
|
164 iter != end; ++iter)
|
Chris@16
|
165 {
|
Chris@16
|
166 *iter /= sum;
|
Chris@16
|
167 }
|
Chris@16
|
168 }
|
Chris@16
|
169 std::vector<WeightType> _probabilities;
|
Chris@16
|
170 /// @endcond
|
Chris@16
|
171 };
|
Chris@16
|
172
|
Chris@16
|
173 /**
|
Chris@16
|
174 * Creates a new @c discrete_distribution object that has
|
Chris@16
|
175 * \f$p(0) = 1\f$ and \f$p(i|i>0) = 0\f$.
|
Chris@16
|
176 */
|
Chris@16
|
177 discrete_distribution()
|
Chris@16
|
178 {
|
Chris@16
|
179 _alias_table.push_back(std::make_pair(static_cast<WeightType>(1),
|
Chris@16
|
180 static_cast<IntType>(0)));
|
Chris@16
|
181 }
|
Chris@16
|
182 /**
|
Chris@16
|
183 * Constructs a discrete_distribution from an iterator range.
|
Chris@16
|
184 * If @c first == @c last, equivalent to the default constructor.
|
Chris@16
|
185 * Otherwise, the values of the range represent weights for the
|
Chris@16
|
186 * possible values of the distribution.
|
Chris@16
|
187 */
|
Chris@16
|
188 template<class Iter>
|
Chris@16
|
189 discrete_distribution(Iter first, Iter last)
|
Chris@16
|
190 {
|
Chris@16
|
191 init(first, last);
|
Chris@16
|
192 }
|
Chris@16
|
193 #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
|
Chris@16
|
194 /**
|
Chris@16
|
195 * Constructs a @c discrete_distribution from a @c std::initializer_list.
|
Chris@16
|
196 * If the @c initializer_list is empty, equivalent to the default
|
Chris@16
|
197 * constructor. Otherwise, the values of the @c initializer_list
|
Chris@16
|
198 * represent weights for the possible values of the distribution.
|
Chris@16
|
199 * For example, given the distribution
|
Chris@16
|
200 *
|
Chris@16
|
201 * @code
|
Chris@16
|
202 * discrete_distribution<> dist{1, 4, 5};
|
Chris@16
|
203 * @endcode
|
Chris@16
|
204 *
|
Chris@16
|
205 * The probability of a 0 is 1/10, the probability of a 1 is 2/5,
|
Chris@16
|
206 * the probability of a 2 is 1/2, and no other values are possible.
|
Chris@16
|
207 */
|
Chris@16
|
208 discrete_distribution(std::initializer_list<WeightType> wl)
|
Chris@16
|
209 {
|
Chris@16
|
210 init(wl.begin(), wl.end());
|
Chris@16
|
211 }
|
Chris@16
|
212 #endif
|
Chris@16
|
213 /**
|
Chris@16
|
214 * Constructs a discrete_distribution from a Boost.Range range.
|
Chris@16
|
215 * If the range is empty, equivalent to the default constructor.
|
Chris@16
|
216 * Otherwise, the values of the range represent weights for the
|
Chris@16
|
217 * possible values of the distribution.
|
Chris@16
|
218 */
|
Chris@16
|
219 template<class Range>
|
Chris@16
|
220 explicit discrete_distribution(const Range& range)
|
Chris@16
|
221 {
|
Chris@16
|
222 init(boost::begin(range), boost::end(range));
|
Chris@16
|
223 }
|
Chris@16
|
224 /**
|
Chris@16
|
225 * Constructs a discrete_distribution that approximates a function.
|
Chris@16
|
226 * If nw is zero, equivalent to the default constructor.
|
Chris@16
|
227 * Otherwise, the range of the distribution is [0, nw),
|
Chris@16
|
228 * and the weights are found by calling fw with values
|
Chris@16
|
229 * evenly distributed between \f$\mbox{xmin} + \delta/2\f$ and
|
Chris@16
|
230 * \f$\mbox{xmax} - \delta/2\f$, where
|
Chris@16
|
231 * \f$\delta = (\mbox{xmax} - \mbox{xmin})/\mbox{nw}\f$.
|
Chris@16
|
232 */
|
Chris@16
|
233 template<class Func>
|
Chris@16
|
234 discrete_distribution(std::size_t nw, double xmin, double xmax, Func fw)
|
Chris@16
|
235 {
|
Chris@16
|
236 std::size_t n = (nw == 0) ? 1 : nw;
|
Chris@16
|
237 double delta = (xmax - xmin) / n;
|
Chris@16
|
238 BOOST_ASSERT(delta > 0);
|
Chris@16
|
239 std::vector<WeightType> weights;
|
Chris@16
|
240 for(std::size_t k = 0; k < n; ++k) {
|
Chris@16
|
241 weights.push_back(fw(xmin + k*delta + delta/2));
|
Chris@16
|
242 }
|
Chris@16
|
243 init(weights.begin(), weights.end());
|
Chris@16
|
244 }
|
Chris@16
|
245 /**
|
Chris@16
|
246 * Constructs a discrete_distribution from its parameters.
|
Chris@16
|
247 */
|
Chris@16
|
248 explicit discrete_distribution(const param_type& parm)
|
Chris@16
|
249 {
|
Chris@16
|
250 param(parm);
|
Chris@16
|
251 }
|
Chris@16
|
252
|
Chris@16
|
253 /**
|
Chris@16
|
254 * Returns a value distributed according to the parameters of the
|
Chris@16
|
255 * discrete_distribution.
|
Chris@16
|
256 */
|
Chris@16
|
257 template<class URNG>
|
Chris@16
|
258 IntType operator()(URNG& urng) const
|
Chris@16
|
259 {
|
Chris@16
|
260 BOOST_ASSERT(!_alias_table.empty());
|
Chris@16
|
261 WeightType test = uniform_01<WeightType>()(urng);
|
Chris@16
|
262 IntType result = uniform_int<IntType>((min)(), (max)())(urng);
|
Chris@16
|
263 if(test < _alias_table[result].first) {
|
Chris@16
|
264 return result;
|
Chris@16
|
265 } else {
|
Chris@16
|
266 return(_alias_table[result].second);
|
Chris@16
|
267 }
|
Chris@16
|
268 }
|
Chris@16
|
269
|
Chris@16
|
270 /**
|
Chris@16
|
271 * Returns a value distributed according to the parameters
|
Chris@16
|
272 * specified by param.
|
Chris@16
|
273 */
|
Chris@16
|
274 template<class URNG>
|
Chris@16
|
275 IntType operator()(URNG& urng, const param_type& parm) const
|
Chris@16
|
276 {
|
Chris@16
|
277 while(true) {
|
Chris@16
|
278 WeightType val = uniform_01<WeightType>()(urng);
|
Chris@16
|
279 WeightType sum = 0;
|
Chris@16
|
280 std::size_t result = 0;
|
Chris@16
|
281 for(typename std::vector<WeightType>::const_iterator
|
Chris@16
|
282 iter = parm._probabilities.begin(),
|
Chris@16
|
283 end = parm._probabilities.end();
|
Chris@16
|
284 iter != end; ++iter, ++result)
|
Chris@16
|
285 {
|
Chris@16
|
286 sum += *iter;
|
Chris@16
|
287 if(sum > val) {
|
Chris@16
|
288 return result;
|
Chris@16
|
289 }
|
Chris@16
|
290 }
|
Chris@16
|
291 }
|
Chris@16
|
292 }
|
Chris@16
|
293
|
Chris@16
|
294 /** Returns the smallest value that the distribution can produce. */
|
Chris@16
|
295 result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
|
Chris@16
|
296 /** Returns the largest value that the distribution can produce. */
|
Chris@16
|
297 result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
|
Chris@16
|
298 { return static_cast<result_type>(_alias_table.size() - 1); }
|
Chris@16
|
299
|
Chris@16
|
300 /**
|
Chris@16
|
301 * Returns a vector containing the probabilities of each
|
Chris@16
|
302 * value of the distribution. For example, given
|
Chris@16
|
303 *
|
Chris@16
|
304 * @code
|
Chris@16
|
305 * discrete_distribution<> dist = { 1, 4, 5 };
|
Chris@16
|
306 * std::vector<double> p = dist.param();
|
Chris@16
|
307 * @endcode
|
Chris@16
|
308 *
|
Chris@16
|
309 * the vector, p will contain {0.1, 0.4, 0.5}.
|
Chris@16
|
310 */
|
Chris@16
|
311 std::vector<WeightType> probabilities() const
|
Chris@16
|
312 {
|
Chris@16
|
313 std::vector<WeightType> result(_alias_table.size());
|
Chris@16
|
314 const WeightType mean =
|
Chris@16
|
315 static_cast<WeightType>(1) / _alias_table.size();
|
Chris@16
|
316 std::size_t i = 0;
|
Chris@16
|
317 for(typename alias_table_t::const_iterator
|
Chris@16
|
318 iter = _alias_table.begin(),
|
Chris@16
|
319 end = _alias_table.end();
|
Chris@16
|
320 iter != end; ++iter, ++i)
|
Chris@16
|
321 {
|
Chris@16
|
322 WeightType val = iter->first * mean;
|
Chris@16
|
323 result[i] += val;
|
Chris@16
|
324 result[iter->second] += mean - val;
|
Chris@16
|
325 }
|
Chris@16
|
326 return(result);
|
Chris@16
|
327 }
|
Chris@16
|
328
|
Chris@16
|
329 /** Returns the parameters of the distribution. */
|
Chris@16
|
330 param_type param() const
|
Chris@16
|
331 {
|
Chris@16
|
332 return param_type(*this);
|
Chris@16
|
333 }
|
Chris@16
|
334 /** Sets the parameters of the distribution. */
|
Chris@16
|
335 void param(const param_type& parm)
|
Chris@16
|
336 {
|
Chris@16
|
337 init(parm._probabilities.begin(), parm._probabilities.end());
|
Chris@16
|
338 }
|
Chris@16
|
339
|
Chris@16
|
340 /**
|
Chris@16
|
341 * Effects: Subsequent uses of the distribution do not depend
|
Chris@16
|
342 * on values produced by any engine prior to invoking reset.
|
Chris@16
|
343 */
|
Chris@16
|
344 void reset() {}
|
Chris@16
|
345
|
Chris@16
|
346 /** Writes a distribution to a @c std::ostream. */
|
Chris@16
|
347 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, discrete_distribution, dd)
|
Chris@16
|
348 {
|
Chris@16
|
349 os << dd.param();
|
Chris@16
|
350 return os;
|
Chris@16
|
351 }
|
Chris@16
|
352
|
Chris@16
|
353 /** Reads a distribution from a @c std::istream */
|
Chris@16
|
354 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, discrete_distribution, dd)
|
Chris@16
|
355 {
|
Chris@16
|
356 param_type parm;
|
Chris@16
|
357 if(is >> parm) {
|
Chris@16
|
358 dd.param(parm);
|
Chris@16
|
359 }
|
Chris@16
|
360 return is;
|
Chris@16
|
361 }
|
Chris@16
|
362
|
Chris@16
|
363 /**
|
Chris@16
|
364 * Returns true if the two distributions will return the
|
Chris@16
|
365 * same sequence of values, when passed equal generators.
|
Chris@16
|
366 */
|
Chris@16
|
367 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(discrete_distribution, lhs, rhs)
|
Chris@16
|
368 {
|
Chris@16
|
369 return lhs._alias_table == rhs._alias_table;
|
Chris@16
|
370 }
|
Chris@16
|
371 /**
|
Chris@16
|
372 * Returns true if the two distributions may return different
|
Chris@16
|
373 * sequences of values, when passed equal generators.
|
Chris@16
|
374 */
|
Chris@16
|
375 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(discrete_distribution)
|
Chris@16
|
376
|
Chris@16
|
377 private:
|
Chris@16
|
378
|
Chris@16
|
379 /// @cond show_private
|
Chris@16
|
380
|
Chris@16
|
381 template<class Iter>
|
Chris@16
|
382 void init(Iter first, Iter last, std::input_iterator_tag)
|
Chris@16
|
383 {
|
Chris@16
|
384 std::vector<WeightType> temp(first, last);
|
Chris@16
|
385 init(temp.begin(), temp.end());
|
Chris@16
|
386 }
|
Chris@16
|
387 template<class Iter>
|
Chris@16
|
388 void init(Iter first, Iter last, std::forward_iterator_tag)
|
Chris@16
|
389 {
|
Chris@16
|
390 std::vector<std::pair<WeightType, IntType> > below_average;
|
Chris@16
|
391 std::vector<std::pair<WeightType, IntType> > above_average;
|
Chris@16
|
392 std::size_t size = std::distance(first, last);
|
Chris@16
|
393 WeightType weight_sum =
|
Chris@16
|
394 std::accumulate(first, last, static_cast<WeightType>(0));
|
Chris@16
|
395 WeightType weight_average = weight_sum / size;
|
Chris@16
|
396 std::size_t i = 0;
|
Chris@16
|
397 for(; first != last; ++first, ++i) {
|
Chris@16
|
398 WeightType val = *first / weight_average;
|
Chris@16
|
399 std::pair<WeightType, IntType> elem(val, static_cast<IntType>(i));
|
Chris@16
|
400 if(val < static_cast<WeightType>(1)) {
|
Chris@16
|
401 below_average.push_back(elem);
|
Chris@16
|
402 } else {
|
Chris@16
|
403 above_average.push_back(elem);
|
Chris@16
|
404 }
|
Chris@16
|
405 }
|
Chris@16
|
406
|
Chris@16
|
407 _alias_table.resize(size);
|
Chris@16
|
408 typename alias_table_t::iterator
|
Chris@16
|
409 b_iter = below_average.begin(),
|
Chris@16
|
410 b_end = below_average.end(),
|
Chris@16
|
411 a_iter = above_average.begin(),
|
Chris@16
|
412 a_end = above_average.end()
|
Chris@16
|
413 ;
|
Chris@16
|
414 while(b_iter != b_end && a_iter != a_end) {
|
Chris@16
|
415 _alias_table[b_iter->second] =
|
Chris@16
|
416 std::make_pair(b_iter->first, a_iter->second);
|
Chris@16
|
417 a_iter->first -= (static_cast<WeightType>(1) - b_iter->first);
|
Chris@16
|
418 if(a_iter->first < static_cast<WeightType>(1)) {
|
Chris@16
|
419 *b_iter = *a_iter++;
|
Chris@16
|
420 } else {
|
Chris@16
|
421 ++b_iter;
|
Chris@16
|
422 }
|
Chris@16
|
423 }
|
Chris@16
|
424 for(; b_iter != b_end; ++b_iter) {
|
Chris@16
|
425 _alias_table[b_iter->second].first = static_cast<WeightType>(1);
|
Chris@16
|
426 }
|
Chris@16
|
427 for(; a_iter != a_end; ++a_iter) {
|
Chris@16
|
428 _alias_table[a_iter->second].first = static_cast<WeightType>(1);
|
Chris@16
|
429 }
|
Chris@16
|
430 }
|
Chris@16
|
431 template<class Iter>
|
Chris@16
|
432 void init(Iter first, Iter last)
|
Chris@16
|
433 {
|
Chris@16
|
434 if(first == last) {
|
Chris@16
|
435 _alias_table.clear();
|
Chris@16
|
436 _alias_table.push_back(std::make_pair(static_cast<WeightType>(1),
|
Chris@16
|
437 static_cast<IntType>(0)));
|
Chris@16
|
438 } else {
|
Chris@16
|
439 typename std::iterator_traits<Iter>::iterator_category category;
|
Chris@16
|
440 init(first, last, category);
|
Chris@16
|
441 }
|
Chris@16
|
442 }
|
Chris@16
|
443 typedef std::vector<std::pair<WeightType, IntType> > alias_table_t;
|
Chris@16
|
444 alias_table_t _alias_table;
|
Chris@16
|
445 /// @endcond
|
Chris@16
|
446 };
|
Chris@16
|
447
|
Chris@16
|
448 }
|
Chris@16
|
449 }
|
Chris@16
|
450
|
Chris@16
|
451 #include <boost/random/detail/enable_warnings.hpp>
|
Chris@16
|
452
|
Chris@16
|
453 #endif
|