annotate DEPENDENCIES/generic/include/boost/multiprecision/random.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
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