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