Chris@16
|
1 ///////////////////////////////////////////////////////////////
|
Chris@16
|
2 // Copyright Jens Maurer 2006-1011
|
Chris@16
|
3 // Copyright Steven Watanabe 2011
|
Chris@16
|
4 // Copyright 2012 John Maddock. Distributed under the Boost
|
Chris@16
|
5 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
|
Chris@16
|
7
|
Chris@16
|
8 #ifndef BOOST_MP_RANDOM_HPP
|
Chris@16
|
9 #define BOOST_MP_RANDOM_HPP
|
Chris@16
|
10
|
Chris@16
|
11 #ifdef BOOST_MSVC
|
Chris@16
|
12 #pragma warning(push)
|
Chris@16
|
13 #pragma warning(disable:4127)
|
Chris@16
|
14 #endif
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/multiprecision/number.hpp>
|
Chris@16
|
17
|
Chris@16
|
18 namespace boost{ namespace random{ namespace detail{
|
Chris@16
|
19 //
|
Chris@16
|
20 // This is a horrible hack: this declaration has to appear before the definition of
|
Chris@16
|
21 // uniform_int_distribution, otherwise it won't be used...
|
Chris@16
|
22 // Need to find a better solution, like make Boost.Random safe to use with
|
Chris@16
|
23 // UDT's and depricate/remove this header altogether.
|
Chris@16
|
24 //
|
Chris@16
|
25 template<class Engine, class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
26 boost::multiprecision::number<Backend, ExpressionTemplates>
|
Chris@16
|
27 generate_uniform_int(Engine& eng, const boost::multiprecision::number<Backend, ExpressionTemplates>& min_value, const boost::multiprecision::number<Backend, ExpressionTemplates>& max_value);
|
Chris@16
|
28
|
Chris@16
|
29 }}}
|
Chris@16
|
30
|
Chris@16
|
31 #include <boost/random.hpp>
|
Chris@16
|
32 #include <boost/mpl/eval_if.hpp>
|
Chris@16
|
33
|
Chris@16
|
34 namespace boost{
|
Chris@16
|
35 namespace random{
|
Chris@16
|
36 namespace detail{
|
Chris@16
|
37
|
Chris@16
|
38 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
39 struct subtract<boost::multiprecision::number<Backend, ExpressionTemplates>, true>
|
Chris@16
|
40 {
|
Chris@16
|
41 typedef boost::multiprecision::number<Backend, ExpressionTemplates> result_type;
|
Chris@16
|
42 result_type operator()(result_type const& x, result_type const& y) { return x - y; }
|
Chris@16
|
43 };
|
Chris@16
|
44
|
Chris@16
|
45 }
|
Chris@16
|
46
|
Chris@16
|
47 template<class Engine, std::size_t w, class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
48 class independent_bits_engine<Engine, w, boost::multiprecision::number<Backend, ExpressionTemplates> >
|
Chris@16
|
49 {
|
Chris@16
|
50 public:
|
Chris@16
|
51 typedef Engine base_type;
|
Chris@16
|
52 typedef boost::multiprecision::number<Backend, ExpressionTemplates> result_type;
|
Chris@16
|
53
|
Chris@16
|
54 static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
|
Chris@16
|
55 { return 0; }
|
Chris@16
|
56 // This is the only function we modify compared to the primary template:
|
Chris@16
|
57 static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
|
Chris@16
|
58 {
|
Chris@16
|
59 // This expression allows for the possibility that w == std::numeric_limits<result_type>::digits:
|
Chris@16
|
60 return (((result_type(1) << (w - 1)) - 1) << 1) + 1;
|
Chris@16
|
61 }
|
Chris@16
|
62
|
Chris@16
|
63 independent_bits_engine() { }
|
Chris@16
|
64
|
Chris@16
|
65 BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(independent_bits_engine,
|
Chris@16
|
66 result_type, seed_arg)
|
Chris@16
|
67 {
|
Chris@16
|
68 _base.seed(seed_arg);
|
Chris@16
|
69 }
|
Chris@16
|
70
|
Chris@16
|
71 BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(independent_bits_engine,
|
Chris@16
|
72 SeedSeq, seq)
|
Chris@16
|
73 { _base.seed(seq); }
|
Chris@16
|
74
|
Chris@16
|
75 independent_bits_engine(const base_type& base_arg) : _base(base_arg) {}
|
Chris@16
|
76
|
Chris@16
|
77 template<class It>
|
Chris@16
|
78 independent_bits_engine(It& first, It last) : _base(first, last) { }
|
Chris@16
|
79
|
Chris@16
|
80 void seed() { _base.seed(); }
|
Chris@16
|
81
|
Chris@16
|
82 BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(independent_bits_engine,
|
Chris@16
|
83 result_type, seed_arg)
|
Chris@16
|
84 { _base.seed(seed_arg); }
|
Chris@16
|
85
|
Chris@16
|
86 BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(independent_bits_engine,
|
Chris@16
|
87 SeedSeq, seq)
|
Chris@16
|
88 { _base.seed(seq); }
|
Chris@16
|
89
|
Chris@16
|
90 template<class It> void seed(It& first, It last)
|
Chris@16
|
91 { _base.seed(first, last); }
|
Chris@16
|
92
|
Chris@16
|
93 result_type operator()()
|
Chris@16
|
94 {
|
Chris@16
|
95 // While it may seem wasteful to recalculate this
|
Chris@16
|
96 // every time, both msvc and gcc can propagate
|
Chris@16
|
97 // constants, resolving this at compile time.
|
Chris@16
|
98 base_unsigned range =
|
Chris@16
|
99 detail::subtract<base_result>()((_base.max)(), (_base.min)());
|
Chris@16
|
100 std::size_t m =
|
Chris@16
|
101 (range == (std::numeric_limits<base_unsigned>::max)()) ?
|
Chris@16
|
102 std::numeric_limits<base_unsigned>::digits :
|
Chris@16
|
103 detail::integer_log2(range + 1);
|
Chris@16
|
104 std::size_t n = (w + m - 1) / m;
|
Chris@16
|
105 std::size_t w0, n0;
|
Chris@16
|
106 base_unsigned y0, y1;
|
Chris@16
|
107 base_unsigned y0_mask, y1_mask;
|
Chris@16
|
108 calc_params(n, range, w0, n0, y0, y1, y0_mask, y1_mask);
|
Chris@16
|
109 if(base_unsigned(range - y0 + 1) > y0 / n) {
|
Chris@16
|
110 // increment n and try again.
|
Chris@16
|
111 ++n;
|
Chris@16
|
112 calc_params(n, range, w0, n0, y0, y1, y0_mask, y1_mask);
|
Chris@16
|
113 }
|
Chris@16
|
114
|
Chris@16
|
115 BOOST_ASSERT(n0*w0 + (n - n0)*(w0 + 1) == w);
|
Chris@16
|
116
|
Chris@16
|
117 result_type S = 0;
|
Chris@16
|
118 for(std::size_t k = 0; k < n0; ++k) {
|
Chris@16
|
119 base_unsigned u;
|
Chris@16
|
120 do {
|
Chris@16
|
121 u = detail::subtract<base_result>()(_base(), (_base.min)());
|
Chris@16
|
122 } while(u > base_unsigned(y0 - 1));
|
Chris@16
|
123 S = (S << w0) + (u & y0_mask);
|
Chris@16
|
124 }
|
Chris@16
|
125 for(std::size_t k = 0; k < (n - n0); ++k) {
|
Chris@16
|
126 base_unsigned u;
|
Chris@16
|
127 do {
|
Chris@16
|
128 u = detail::subtract<base_result>()(_base(), (_base.min)());
|
Chris@16
|
129 } while(u > base_unsigned(y1 - 1));
|
Chris@16
|
130 S = (S << (w0 + 1)) + (u & y1_mask);
|
Chris@16
|
131 }
|
Chris@16
|
132 return S;
|
Chris@16
|
133 }
|
Chris@16
|
134
|
Chris@16
|
135 /** Fills a range with random values */
|
Chris@16
|
136 template<class Iter>
|
Chris@16
|
137 void generate(Iter first, Iter last)
|
Chris@16
|
138 { detail::generate_from_int(*this, first, last); }
|
Chris@16
|
139
|
Chris@16
|
140 /** Advances the state of the generator by @c z. */
|
Chris@16
|
141 void discard(boost::uintmax_t z)
|
Chris@16
|
142 {
|
Chris@16
|
143 for(boost::uintmax_t i = 0; i < z; ++i) {
|
Chris@16
|
144 (*this)();
|
Chris@16
|
145 }
|
Chris@16
|
146 }
|
Chris@16
|
147
|
Chris@16
|
148 const base_type& base() const { return _base; }
|
Chris@16
|
149
|
Chris@16
|
150 /**
|
Chris@16
|
151 * Writes the textual representation if the generator to a @c std::ostream.
|
Chris@16
|
152 * The textual representation of the engine is the textual representation
|
Chris@16
|
153 * of the base engine.
|
Chris@16
|
154 */
|
Chris@16
|
155 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, independent_bits_engine, r)
|
Chris@16
|
156 {
|
Chris@16
|
157 os << r._base;
|
Chris@16
|
158 return os;
|
Chris@16
|
159 }
|
Chris@16
|
160
|
Chris@16
|
161 /**
|
Chris@16
|
162 * Reads the state of an @c independent_bits_engine from a
|
Chris@16
|
163 * @c std::istream.
|
Chris@16
|
164 */
|
Chris@16
|
165 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, independent_bits_engine, r)
|
Chris@16
|
166 {
|
Chris@16
|
167 is >> r._base;
|
Chris@16
|
168 return is;
|
Chris@16
|
169 }
|
Chris@16
|
170
|
Chris@16
|
171 /**
|
Chris@16
|
172 * Returns: true iff the two @c independent_bits_engines will
|
Chris@16
|
173 * produce the same sequence of values.
|
Chris@16
|
174 */
|
Chris@16
|
175 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(independent_bits_engine, x, y)
|
Chris@16
|
176 { return x._base == y._base; }
|
Chris@16
|
177 /**
|
Chris@16
|
178 * Returns: true iff the two @c independent_bits_engines will
|
Chris@16
|
179 * produce different sequences of values.
|
Chris@16
|
180 */
|
Chris@16
|
181 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(independent_bits_engine)
|
Chris@16
|
182
|
Chris@16
|
183 private:
|
Chris@16
|
184
|
Chris@16
|
185 /// \cond show_private
|
Chris@16
|
186 typedef typename base_type::result_type base_result;
|
Chris@16
|
187 typedef typename make_unsigned<base_result>::type base_unsigned;
|
Chris@16
|
188
|
Chris@16
|
189 void calc_params(
|
Chris@16
|
190 std::size_t n, base_unsigned range,
|
Chris@16
|
191 std::size_t& w0, std::size_t& n0,
|
Chris@16
|
192 base_unsigned& y0, base_unsigned& y1,
|
Chris@16
|
193 base_unsigned& y0_mask, base_unsigned& y1_mask)
|
Chris@16
|
194 {
|
Chris@16
|
195 BOOST_ASSERT(w >= n);
|
Chris@16
|
196 w0 = w/n;
|
Chris@16
|
197 n0 = n - w % n;
|
Chris@16
|
198 y0_mask = (base_unsigned(2) << (w0 - 1)) - 1;
|
Chris@16
|
199 y1_mask = (y0_mask << 1) | 1;
|
Chris@16
|
200 y0 = (range + 1) & ~y0_mask;
|
Chris@16
|
201 y1 = (range + 1) & ~y1_mask;
|
Chris@16
|
202 BOOST_ASSERT(y0 != 0 || base_unsigned(range + 1) == 0);
|
Chris@16
|
203 }
|
Chris@16
|
204 /// \endcond
|
Chris@16
|
205
|
Chris@16
|
206 Engine _base;
|
Chris@16
|
207 };
|
Chris@16
|
208
|
Chris@16
|
209 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
210 class uniform_smallint<boost::multiprecision::number<Backend, ExpressionTemplates> >
|
Chris@16
|
211 {
|
Chris@16
|
212 public:
|
Chris@16
|
213 typedef boost::multiprecision::number<Backend, ExpressionTemplates> input_type;
|
Chris@16
|
214 typedef boost::multiprecision::number<Backend, ExpressionTemplates> result_type;
|
Chris@16
|
215
|
Chris@16
|
216 class param_type
|
Chris@16
|
217 {
|
Chris@16
|
218 public:
|
Chris@16
|
219
|
Chris@16
|
220 typedef uniform_smallint distribution_type;
|
Chris@16
|
221
|
Chris@16
|
222 /** constructs the parameters of a @c uniform_smallint distribution. */
|
Chris@16
|
223 param_type(result_type const& min_arg = 0, result_type const& max_arg = 9)
|
Chris@16
|
224 : _min(min_arg), _max(max_arg)
|
Chris@16
|
225 {
|
Chris@16
|
226 BOOST_ASSERT(_min <= _max);
|
Chris@16
|
227 }
|
Chris@16
|
228
|
Chris@16
|
229 /** Returns the minimum value. */
|
Chris@16
|
230 result_type a() const { return _min; }
|
Chris@16
|
231 /** Returns the maximum value. */
|
Chris@16
|
232 result_type b() const { return _max; }
|
Chris@16
|
233
|
Chris@16
|
234
|
Chris@16
|
235 /** Writes the parameters to a @c std::ostream. */
|
Chris@16
|
236 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
|
Chris@16
|
237 {
|
Chris@16
|
238 os << parm._min << " " << parm._max;
|
Chris@16
|
239 return os;
|
Chris@16
|
240 }
|
Chris@16
|
241
|
Chris@16
|
242 /** Reads the parameters from a @c std::istream. */
|
Chris@16
|
243 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
|
Chris@16
|
244 {
|
Chris@16
|
245 is >> parm._min >> std::ws >> parm._max;
|
Chris@16
|
246 return is;
|
Chris@16
|
247 }
|
Chris@16
|
248
|
Chris@16
|
249 /** Returns true if the two sets of parameters are equal. */
|
Chris@16
|
250 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
|
Chris@16
|
251 { return lhs._min == rhs._min && lhs._max == rhs._max; }
|
Chris@16
|
252
|
Chris@16
|
253 /** Returns true if the two sets of parameters are different. */
|
Chris@16
|
254 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
|
Chris@16
|
255
|
Chris@16
|
256 private:
|
Chris@16
|
257 result_type _min;
|
Chris@16
|
258 result_type _max;
|
Chris@16
|
259 };
|
Chris@16
|
260
|
Chris@16
|
261 /**
|
Chris@16
|
262 * Constructs a @c uniform_smallint. @c min and @c max are the
|
Chris@16
|
263 * lower and upper bounds of the output range, respectively.
|
Chris@16
|
264 */
|
Chris@16
|
265 explicit uniform_smallint(result_type const& min_arg = 0, result_type const& max_arg = 9)
|
Chris@16
|
266 : _min(min_arg), _max(max_arg) {}
|
Chris@16
|
267
|
Chris@16
|
268 /**
|
Chris@16
|
269 * Constructs a @c uniform_smallint from its parameters.
|
Chris@16
|
270 */
|
Chris@16
|
271 explicit uniform_smallint(const param_type& parm)
|
Chris@16
|
272 : _min(parm.a()), _max(parm.b()) {}
|
Chris@16
|
273
|
Chris@16
|
274 /** Returns the minimum value of the distribution. */
|
Chris@16
|
275 result_type a() const { return _min; }
|
Chris@16
|
276 /** Returns the maximum value of the distribution. */
|
Chris@16
|
277 result_type b() const { return _max; }
|
Chris@16
|
278 /** Returns the minimum value of the distribution. */
|
Chris@16
|
279 result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
|
Chris@16
|
280 /** Returns the maximum value of the distribution. */
|
Chris@16
|
281 result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
|
Chris@16
|
282
|
Chris@16
|
283 /** Returns the parameters of the distribution. */
|
Chris@16
|
284 param_type param() const { return param_type(_min, _max); }
|
Chris@16
|
285 /** Sets the parameters of the distribution. */
|
Chris@16
|
286 void param(const param_type& parm)
|
Chris@16
|
287 {
|
Chris@16
|
288 _min = parm.a();
|
Chris@16
|
289 _max = parm.b();
|
Chris@16
|
290 }
|
Chris@16
|
291
|
Chris@16
|
292 /**
|
Chris@16
|
293 * Effects: Subsequent uses of the distribution do not depend
|
Chris@16
|
294 * on values produced by any engine prior to invoking reset.
|
Chris@16
|
295 */
|
Chris@16
|
296 void reset() { }
|
Chris@16
|
297
|
Chris@16
|
298 /** Returns a value uniformly distributed in the range [min(), max()]. */
|
Chris@16
|
299 template<class Engine>
|
Chris@16
|
300 result_type operator()(Engine& eng) const
|
Chris@16
|
301 {
|
Chris@16
|
302 typedef typename Engine::result_type base_result;
|
Chris@16
|
303 return generate(eng, boost::is_integral<base_result>());
|
Chris@16
|
304 }
|
Chris@16
|
305
|
Chris@16
|
306 /** Returns a value uniformly distributed in the range [param.a(), param.b()]. */
|
Chris@16
|
307 template<class Engine>
|
Chris@16
|
308 result_type operator()(Engine& eng, const param_type& parm) const
|
Chris@16
|
309 { return uniform_smallint(parm)(eng); }
|
Chris@16
|
310
|
Chris@16
|
311 /** Writes the distribution to a @c std::ostream. */
|
Chris@16
|
312 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_smallint, ud)
|
Chris@16
|
313 {
|
Chris@16
|
314 os << ud._min << " " << ud._max;
|
Chris@16
|
315 return os;
|
Chris@16
|
316 }
|
Chris@16
|
317
|
Chris@16
|
318 /** Reads the distribution from a @c std::istream. */
|
Chris@16
|
319 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_smallint, ud)
|
Chris@16
|
320 {
|
Chris@16
|
321 is >> ud._min >> std::ws >> ud._max;
|
Chris@16
|
322 return is;
|
Chris@16
|
323 }
|
Chris@16
|
324
|
Chris@16
|
325 /**
|
Chris@16
|
326 * Returns true if the two distributions will produce identical
|
Chris@16
|
327 * sequences of values given equal generators.
|
Chris@16
|
328 */
|
Chris@16
|
329 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_smallint, lhs, rhs)
|
Chris@16
|
330 { return lhs._min == rhs._min && lhs._max == rhs._max; }
|
Chris@16
|
331
|
Chris@16
|
332 /**
|
Chris@16
|
333 * Returns true if the two distributions may produce different
|
Chris@16
|
334 * sequences of values given equal generators.
|
Chris@16
|
335 */
|
Chris@16
|
336 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_smallint)
|
Chris@16
|
337
|
Chris@16
|
338 private:
|
Chris@16
|
339
|
Chris@16
|
340 // \cond show_private
|
Chris@16
|
341 template<class Engine>
|
Chris@16
|
342 result_type generate(Engine& eng, boost::mpl::true_) const
|
Chris@16
|
343 {
|
Chris@16
|
344 // equivalent to (eng() - eng.min()) % (_max - _min + 1) + _min,
|
Chris@16
|
345 // but guarantees no overflow.
|
Chris@16
|
346 typedef typename Engine::result_type base_result;
|
Chris@16
|
347 typedef typename boost::make_unsigned<base_result>::type base_unsigned;
|
Chris@16
|
348 typedef result_type range_type;
|
Chris@16
|
349 range_type range = random::detail::subtract<result_type>()(_max, _min);
|
Chris@16
|
350 base_unsigned base_range =
|
Chris@16
|
351 random::detail::subtract<result_type>()((eng.max)(), (eng.min)());
|
Chris@16
|
352 base_unsigned val =
|
Chris@16
|
353 random::detail::subtract<base_result>()(eng(), (eng.min)());
|
Chris@16
|
354 if(range >= base_range) {
|
Chris@16
|
355 return boost::random::detail::add<range_type, result_type>()(
|
Chris@16
|
356 static_cast<range_type>(val), _min);
|
Chris@16
|
357 } else {
|
Chris@16
|
358 base_unsigned modulus = static_cast<base_unsigned>(range) + 1;
|
Chris@16
|
359 return boost::random::detail::add<range_type, result_type>()(
|
Chris@16
|
360 static_cast<range_type>(val % modulus), _min);
|
Chris@16
|
361 }
|
Chris@16
|
362 }
|
Chris@16
|
363
|
Chris@16
|
364 template<class Engine>
|
Chris@16
|
365 result_type generate(Engine& eng, boost::mpl::false_) const
|
Chris@16
|
366 {
|
Chris@16
|
367 typedef typename Engine::result_type base_result;
|
Chris@16
|
368 typedef result_type range_type;
|
Chris@16
|
369 range_type range = random::detail::subtract<result_type>()(_max, _min);
|
Chris@16
|
370 base_result val = boost::uniform_01<base_result>()(eng);
|
Chris@16
|
371 // what is the worst that can possibly happen here?
|
Chris@16
|
372 // base_result may not be able to represent all the values in [0, range]
|
Chris@16
|
373 // exactly. If this happens, it will cause round off error and we
|
Chris@16
|
374 // won't be able to produce all the values in the range. We don't
|
Chris@16
|
375 // care about this because the user has already told us not to by
|
Chris@16
|
376 // using uniform_smallint. However, we do need to be careful
|
Chris@16
|
377 // to clamp the result, or floating point rounding can produce
|
Chris@16
|
378 // an out of range result.
|
Chris@16
|
379 range_type offset = static_cast<range_type>(val * (range + 1));
|
Chris@16
|
380 if(offset > range) return _max;
|
Chris@16
|
381 return boost::random::detail::add<range_type, result_type>()(offset , _min);
|
Chris@16
|
382 }
|
Chris@16
|
383 // \endcond
|
Chris@16
|
384
|
Chris@16
|
385 result_type _min;
|
Chris@16
|
386 result_type _max;
|
Chris@16
|
387 };
|
Chris@16
|
388
|
Chris@16
|
389
|
Chris@16
|
390 namespace detail{
|
Chris@16
|
391
|
Chris@16
|
392 template<class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
393 struct select_uniform_01<boost::multiprecision::number<Backend, ExpressionTemplates> >
|
Chris@16
|
394 {
|
Chris@16
|
395 template<class RealType>
|
Chris@16
|
396 struct apply
|
Chris@16
|
397 {
|
Chris@16
|
398 typedef new_uniform_01<boost::multiprecision::number<Backend, ExpressionTemplates> > type;
|
Chris@16
|
399 };
|
Chris@16
|
400 };
|
Chris@16
|
401
|
Chris@16
|
402 template<class Engine, class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
403 boost::multiprecision::number<Backend, ExpressionTemplates>
|
Chris@16
|
404 generate_uniform_int(
|
Chris@16
|
405 Engine& eng, const boost::multiprecision::number<Backend, ExpressionTemplates>& min_value, const boost::multiprecision::number<Backend, ExpressionTemplates>& max_value,
|
Chris@16
|
406 boost::mpl::true_ /** is_integral<Engine::result_type> */)
|
Chris@16
|
407 {
|
Chris@16
|
408 typedef boost::multiprecision::number<Backend, ExpressionTemplates> result_type;
|
Chris@16
|
409 // Since we're using big-numbers, use the result type for all internal calculations:
|
Chris@16
|
410 typedef result_type range_type;
|
Chris@16
|
411 typedef result_type base_result;
|
Chris@16
|
412 typedef result_type base_unsigned;
|
Chris@16
|
413 const range_type range = random::detail::subtract<result_type>()(max_value, min_value);
|
Chris@16
|
414 const base_result bmin = (eng.min)();
|
Chris@16
|
415 const base_unsigned brange =
|
Chris@16
|
416 random::detail::subtract<base_result>()((eng.max)(), (eng.min)());
|
Chris@16
|
417
|
Chris@16
|
418 if(range == 0) {
|
Chris@16
|
419 return min_value;
|
Chris@16
|
420 } else if(brange == range) {
|
Chris@16
|
421 // this will probably never happen in real life
|
Chris@16
|
422 // basically nothing to do; just take care we don't overflow / underflow
|
Chris@16
|
423 base_unsigned v = random::detail::subtract<base_result>()(eng(), bmin);
|
Chris@16
|
424 return random::detail::add<base_unsigned, result_type>()(v, min_value);
|
Chris@16
|
425 } else if(brange < range) {
|
Chris@16
|
426 // use rejection method to handle things like 0..3 --> 0..4
|
Chris@16
|
427 for(;;) {
|
Chris@16
|
428 // concatenate several invocations of the base RNG
|
Chris@16
|
429 // take extra care to avoid overflows
|
Chris@16
|
430
|
Chris@16
|
431 // limit == floor((range+1)/(brange+1))
|
Chris@16
|
432 // Therefore limit*(brange+1) <= range+1
|
Chris@16
|
433 range_type limit;
|
Chris@16
|
434 if(std::numeric_limits<range_type>::is_bounded && (range == (std::numeric_limits<range_type>::max)())) {
|
Chris@16
|
435 limit = range/(range_type(brange)+1);
|
Chris@16
|
436 if(range % (range_type(brange)+1) == range_type(brange))
|
Chris@16
|
437 ++limit;
|
Chris@16
|
438 } else {
|
Chris@16
|
439 limit = (range+1)/(range_type(brange)+1);
|
Chris@16
|
440 }
|
Chris@16
|
441
|
Chris@16
|
442 // We consider "result" as expressed to base (brange+1):
|
Chris@16
|
443 // For every power of (brange+1), we determine a random factor
|
Chris@16
|
444 range_type result = range_type(0);
|
Chris@16
|
445 range_type mult = range_type(1);
|
Chris@16
|
446
|
Chris@16
|
447 // loop invariants:
|
Chris@16
|
448 // result < mult
|
Chris@16
|
449 // mult <= range
|
Chris@16
|
450 while(mult <= limit) {
|
Chris@16
|
451 // Postcondition: result <= range, thus no overflow
|
Chris@16
|
452 //
|
Chris@16
|
453 // limit*(brange+1)<=range+1 def. of limit (1)
|
Chris@16
|
454 // eng()-bmin<=brange eng() post. (2)
|
Chris@16
|
455 // and mult<=limit. loop condition (3)
|
Chris@16
|
456 // Therefore mult*(eng()-bmin+1)<=range+1 by (1),(2),(3) (4)
|
Chris@16
|
457 // Therefore mult*(eng()-bmin)+mult<=range+1 rearranging (4) (5)
|
Chris@16
|
458 // result<mult loop invariant (6)
|
Chris@16
|
459 // Therefore result+mult*(eng()-bmin)<range+1 by (5), (6) (7)
|
Chris@16
|
460 //
|
Chris@16
|
461 // Postcondition: result < mult*(brange+1)
|
Chris@16
|
462 //
|
Chris@16
|
463 // result<mult loop invariant (1)
|
Chris@16
|
464 // eng()-bmin<=brange eng() post. (2)
|
Chris@16
|
465 // Therefore result+mult*(eng()-bmin) <
|
Chris@16
|
466 // mult+mult*(eng()-bmin) by (1) (3)
|
Chris@16
|
467 // Therefore result+(eng()-bmin)*mult <
|
Chris@16
|
468 // mult+mult*brange by (2), (3) (4)
|
Chris@16
|
469 // Therefore result+(eng()-bmin)*mult <
|
Chris@16
|
470 // mult*(brange+1) by (4)
|
Chris@16
|
471 result += static_cast<range_type>(random::detail::subtract<base_result>()(eng(), bmin) * mult);
|
Chris@16
|
472
|
Chris@16
|
473 // equivalent to (mult * (brange+1)) == range+1, but avoids overflow.
|
Chris@16
|
474 if(mult * range_type(brange) == range - mult + 1) {
|
Chris@16
|
475 // The destination range is an integer power of
|
Chris@16
|
476 // the generator's range.
|
Chris@16
|
477 return(result);
|
Chris@16
|
478 }
|
Chris@16
|
479
|
Chris@16
|
480 // Postcondition: mult <= range
|
Chris@16
|
481 //
|
Chris@16
|
482 // limit*(brange+1)<=range+1 def. of limit (1)
|
Chris@16
|
483 // mult<=limit loop condition (2)
|
Chris@16
|
484 // Therefore mult*(brange+1)<=range+1 by (1), (2) (3)
|
Chris@16
|
485 // mult*(brange+1)!=range+1 preceding if (4)
|
Chris@16
|
486 // Therefore mult*(brange+1)<range+1 by (3), (4) (5)
|
Chris@16
|
487 //
|
Chris@16
|
488 // Postcondition: result < mult
|
Chris@16
|
489 //
|
Chris@16
|
490 // See the second postcondition on the change to result.
|
Chris@16
|
491 mult *= range_type(brange)+range_type(1);
|
Chris@16
|
492 }
|
Chris@16
|
493 // loop postcondition: range/mult < brange+1
|
Chris@16
|
494 //
|
Chris@16
|
495 // mult > limit loop condition (1)
|
Chris@16
|
496 // Suppose range/mult >= brange+1 Assumption (2)
|
Chris@16
|
497 // range >= mult*(brange+1) by (2) (3)
|
Chris@16
|
498 // range+1 > mult*(brange+1) by (3) (4)
|
Chris@16
|
499 // range+1 > (limit+1)*(brange+1) by (1), (4) (5)
|
Chris@16
|
500 // (range+1)/(brange+1) > limit+1 by (5) (6)
|
Chris@16
|
501 // limit < floor((range+1)/(brange+1)) by (6) (7)
|
Chris@16
|
502 // limit==floor((range+1)/(brange+1)) def. of limit (8)
|
Chris@16
|
503 // not (2) reductio (9)
|
Chris@16
|
504 //
|
Chris@16
|
505 // loop postcondition: (range/mult)*mult+(mult-1) >= range
|
Chris@16
|
506 //
|
Chris@16
|
507 // (range/mult)*mult + range%mult == range identity (1)
|
Chris@16
|
508 // range%mult < mult def. of % (2)
|
Chris@16
|
509 // (range/mult)*mult+mult > range by (1), (2) (3)
|
Chris@16
|
510 // (range/mult)*mult+(mult-1) >= range by (3) (4)
|
Chris@16
|
511 //
|
Chris@16
|
512 // Note that the maximum value of result at this point is (mult-1),
|
Chris@16
|
513 // so after this final step, we generate numbers that can be
|
Chris@16
|
514 // at least as large as range. We have to really careful to avoid
|
Chris@16
|
515 // overflow in this final addition and in the rejection. Anything
|
Chris@16
|
516 // that overflows is larger than range and can thus be rejected.
|
Chris@16
|
517
|
Chris@16
|
518 // range/mult < brange+1 -> no endless loop
|
Chris@16
|
519 range_type result_increment =
|
Chris@16
|
520 generate_uniform_int(
|
Chris@16
|
521 eng,
|
Chris@16
|
522 static_cast<range_type>(0),
|
Chris@16
|
523 static_cast<range_type>(range/mult),
|
Chris@16
|
524 boost::mpl::true_());
|
Chris@16
|
525 if(std::numeric_limits<range_type>::is_bounded && ((std::numeric_limits<range_type>::max)() / mult < result_increment)) {
|
Chris@16
|
526 // The multiplication would overflow. Reject immediately.
|
Chris@16
|
527 continue;
|
Chris@16
|
528 }
|
Chris@16
|
529 result_increment *= mult;
|
Chris@16
|
530 // unsigned integers are guaranteed to wrap on overflow.
|
Chris@16
|
531 result += result_increment;
|
Chris@16
|
532 if(result < result_increment) {
|
Chris@16
|
533 // The addition overflowed. Reject.
|
Chris@16
|
534 continue;
|
Chris@16
|
535 }
|
Chris@16
|
536 if(result > range) {
|
Chris@16
|
537 // Too big. Reject.
|
Chris@16
|
538 continue;
|
Chris@16
|
539 }
|
Chris@16
|
540 return random::detail::add<range_type, result_type>()(result, min_value);
|
Chris@16
|
541 }
|
Chris@16
|
542 } else { // brange > range
|
Chris@16
|
543 range_type bucket_size;
|
Chris@16
|
544 // it's safe to add 1 to range, as long as we cast it first,
|
Chris@16
|
545 // because we know that it is less than brange. However,
|
Chris@16
|
546 // we do need to be careful not to cause overflow by adding 1
|
Chris@16
|
547 // to brange.
|
Chris@16
|
548 if(std::numeric_limits<base_unsigned>::is_bounded && (brange == (std::numeric_limits<base_unsigned>::max)())) {
|
Chris@16
|
549 bucket_size = brange / (range+1);
|
Chris@16
|
550 if(brange % (range+1) == range) {
|
Chris@16
|
551 ++bucket_size;
|
Chris@16
|
552 }
|
Chris@16
|
553 } else {
|
Chris@16
|
554 bucket_size = (brange+1) / (range+1);
|
Chris@16
|
555 }
|
Chris@16
|
556 for(;;) {
|
Chris@16
|
557 range_type result =
|
Chris@16
|
558 random::detail::subtract<base_result>()(eng(), bmin);
|
Chris@16
|
559 result /= bucket_size;
|
Chris@16
|
560 // result and range are non-negative, and result is possibly larger
|
Chris@16
|
561 // than range, so the cast is safe
|
Chris@16
|
562 if(result <= range)
|
Chris@16
|
563 return result + min_value;
|
Chris@16
|
564 }
|
Chris@16
|
565 }
|
Chris@16
|
566 }
|
Chris@16
|
567
|
Chris@16
|
568 template<class Engine, class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
569 inline boost::multiprecision::number<Backend, ExpressionTemplates>
|
Chris@16
|
570 generate_uniform_int(Engine& eng, const boost::multiprecision::number<Backend, ExpressionTemplates>& min_value, const boost::multiprecision::number<Backend, ExpressionTemplates>& max_value)
|
Chris@16
|
571 {
|
Chris@16
|
572 typedef typename Engine::result_type base_result;
|
Chris@16
|
573 typedef typename mpl::or_<boost::is_integral<base_result>, mpl::bool_<boost::multiprecision::number_category<Backend>::value == boost::multiprecision::number_kind_integer> >::type tag_type;
|
Chris@16
|
574 return generate_uniform_int(eng, min_value, max_value,
|
Chris@16
|
575 tag_type());
|
Chris@16
|
576 }
|
Chris@16
|
577
|
Chris@101
|
578 template<class Engine, class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@101
|
579 inline boost::multiprecision::number<Backend, ExpressionTemplates> generate_uniform_real(Engine& eng, const boost::multiprecision::number<Backend, ExpressionTemplates>& min_value, const boost::multiprecision::number<Backend, ExpressionTemplates>& max_value)
|
Chris@101
|
580 {
|
Chris@101
|
581 if(max_value / 2 - min_value / 2 > (std::numeric_limits<boost::multiprecision::number<Backend, ExpressionTemplates> >::max)() / 2)
|
Chris@101
|
582 return 2 * generate_uniform_real(eng, boost::multiprecision::number<Backend, ExpressionTemplates>(min_value / 2), boost::multiprecision::number<Backend, ExpressionTemplates>(max_value / 2));
|
Chris@101
|
583 typedef typename Engine::result_type base_result;
|
Chris@101
|
584 return generate_uniform_real(eng, min_value, max_value,
|
Chris@101
|
585 boost::is_integral<base_result>());
|
Chris@101
|
586 }
|
Chris@101
|
587
|
Chris@16
|
588 } // detail
|
Chris@16
|
589
|
Chris@16
|
590
|
Chris@16
|
591 }} // namespaces
|
Chris@16
|
592
|
Chris@16
|
593 #ifdef BOOST_MSVC
|
Chris@16
|
594 #pragma warning(pop)
|
Chris@16
|
595 #endif
|
Chris@16
|
596
|
Chris@16
|
597 #endif
|