1 /* boost random/uniform_smallint.hpp header file
\r
3 * Copyright Jens Maurer 2000-2001
\r
4 * Distributed under the Boost Software License, Version 1.0. (See
\r
5 * accompanying file LICENSE_1_0.txt or copy at
\r
6 * http://www.boost.org/LICENSE_1_0.txt)
\r
8 * See http://www.boost.org for most recent version including documentation.
\r
10 * $Id: uniform_smallint.hpp 52492 2009-04-19 14:55:57Z steven_watanabe $
\r
13 * 2001-04-08 added min<max assertion (N. Becker)
\r
14 * 2001-02-18 moved to individual header files
\r
17 #ifndef BOOST_RANDOM_UNIFORM_SMALLINT_HPP
\r
18 #define BOOST_RANDOM_UNIFORM_SMALLINT_HPP
\r
22 #include <boost/config.hpp>
\r
23 #include <boost/limits.hpp>
\r
24 #include <boost/static_assert.hpp>
\r
25 #include <boost/random/detail/config.hpp>
\r
26 #include <boost/random/uniform_01.hpp>
\r
27 #include <boost/detail/workaround.hpp>
\r
31 // uniform integer distribution on a small range [min, max]
\r
33 template<class IntType = int>
\r
34 class uniform_smallint
\r
37 typedef IntType input_type;
\r
38 typedef IntType result_type;
\r
40 explicit uniform_smallint(IntType min_arg = 0, IntType max_arg = 9)
\r
41 : _min(min_arg), _max(max_arg)
\r
43 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
\r
44 // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope
\r
45 BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer);
\r
49 result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
\r
50 result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
\r
53 template<class Engine>
\r
54 result_type operator()(Engine& eng)
\r
56 typedef typename Engine::result_type base_result;
\r
57 base_result _range = static_cast<base_result>(_max-_min)+1;
\r
58 base_result _factor = 1;
\r
60 // LCGs get bad when only taking the low bits.
\r
61 // (probably put this logic into a partial template specialization)
\r
62 // Check how many low bits we can ignore before we get too much
\r
63 // quantization error.
\r
64 base_result r_base = (eng.max)() - (eng.min)();
\r
65 if(r_base == (std::numeric_limits<base_result>::max)()) {
\r
70 if(r_base % _range == 0) {
\r
71 // No quantization effects, good
\r
72 _factor = r_base / _range;
\r
74 // carefully avoid overflow; pessimizing here
\r
75 for( ; r_base/_range/32 >= _range; _factor *= 2)
\r
79 return ((eng() - (eng.min)()) / _factor) % _range + _min;
\r
82 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
\r
83 template<class CharT, class Traits>
\r
84 friend std::basic_ostream<CharT,Traits>&
\r
85 operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_smallint& ud)
\r
87 os << ud._min << " " << ud._max;
\r
91 template<class CharT, class Traits>
\r
92 friend std::basic_istream<CharT,Traits>&
\r
93 operator>>(std::basic_istream<CharT,Traits>& is, uniform_smallint& ud)
\r
95 is >> std::ws >> ud._min >> std::ws >> ud._max;
\r
106 } // namespace boost
\r
108 #endif // BOOST_RANDOM_UNIFORM_SMALLINT_HPP
\r