Index: boost/random/uniform_int.hpp =================================================================== --- boost/random/uniform_int.hpp (revision 53231) +++ boost/random/uniform_int.hpp (working copy) @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -122,7 +121,7 @@ range_type limit; if(range == (std::numeric_limits::max)()) { limit = range/(range_type(brange)+1); - if(range % range_type(brange)+1 == range_type(brange)) + if(range % (range_type(brange)+1) == range_type(brange)) ++limit; } else { limit = (range+1)/(range_type(brange)+1); @@ -144,21 +143,28 @@ return random::detail::add()(result, min_value); } } else { // brange > range - if(brange / range > 4 /* quantization_cutoff */ ) { - // the new range is vastly smaller than the source range, - // so quantization effects are not relevant - return boost::uniform_smallint(min_value, max_value)(eng); + base_unsigned bucket_size; + // it's safe to add 1 to range, as long as we cast it first, + // because we know that it is less than brange. However, + // we do need to be careful not to cause overflow by adding 1 + // to brange. + if(brange == (std::numeric_limits::max)()) { + bucket_size = brange / (static_cast(range)+1); + if(brange % (static_cast(range)+1) == static_cast(range)) { + ++bucket_size; + } } else { - // use rejection method to handle cases like 0..5 -> 0..4 - for(;;) { - base_unsigned result = - random::detail::subtract()(eng(), bmin); - // result and range are non-negative, and result is possibly larger - // than range, so the cast is safe - if(result <= static_cast(range)) - return random::detail::add()(result, min_value); - } + bucket_size = (brange+1) / (static_cast(range)+1); } + for(;;) { + base_unsigned result = + random::detail::subtract()(eng(), bmin); + result /= bucket_size; + // result and range are non-negative, and result is possibly larger + // than range, so the cast is safe + if(result <= static_cast(range)) + return random::detail::add()(result, min_value); + } } } Index: libs/random/random_test.cpp =================================================================== --- libs/random/random_test.cpp (revision 53231) +++ libs/random/random_test.cpp (working copy) @@ -140,10 +140,13 @@ class ruetti_gen { public: + ruetti_gen() : state((max)() - 1) {} typedef boost::uint64_t result_type; result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; } result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION (); } - result_type operator()() { return (max)()-1; } + result_type operator()() { return state--; } +private: + result_type state; }; void test_overflow_range()