ossrv_pub/boost_apis/boost/random/uniform_smallint.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* boost random/uniform_smallint.hpp header file
       
     2  *
       
     3  * Copyright Jens Maurer 2000-2001
       
     4  * Distributed under the Boost Software License, Version 1.0. (See
       
     5  * accompanying file LICENSE_1_0.txt or copy at
       
     6  * http://www.boost.org/LICENSE_1_0.txt)
       
     7  *
       
     8  * See http://www.boost.org for most recent version including documentation.
       
     9  *
       
    10  * $Id: uniform_smallint.hpp,v 1.29 2004/07/27 03:43:32 dgregor Exp $
       
    11  *
       
    12  * Revision history
       
    13  *  2001-04-08  added min<max assertion (N. Becker)
       
    14  *  2001-02-18  moved to individual header files
       
    15  */
       
    16 
       
    17 #ifndef BOOST_RANDOM_UNIFORM_SMALLINT_HPP
       
    18 #define BOOST_RANDOM_UNIFORM_SMALLINT_HPP
       
    19 
       
    20 #include <cassert>
       
    21 #include <iostream>
       
    22 #include <boost/config.hpp>
       
    23 #include <boost/limits.hpp>
       
    24 #include <boost/static_assert.hpp>
       
    25 #include <boost/random/uniform_01.hpp>
       
    26 #include <boost/detail/workaround.hpp>
       
    27 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
       
    28 #include <boost/type_traits/is_float.hpp>
       
    29 #endif
       
    30 
       
    31 
       
    32 namespace boost {
       
    33 
       
    34 // uniform integer distribution on a small range [min, max]
       
    35 
       
    36 namespace detail {
       
    37 
       
    38 template <class InputStream, class UniformInt, class Impl>
       
    39 InputStream& extract_uniform_int(InputStream& is, UniformInt& ud, Impl& impl)
       
    40 {
       
    41     typename UniformInt::result_type min, max;
       
    42     is >> std::ws >> min >> std::ws >> max;
       
    43     impl.set(min, max);
       
    44     return is;
       
    45 }
       
    46 
       
    47 template<class UniformRandomNumberGenerator, class IntType>
       
    48 struct uniform_smallint_integer
       
    49 {
       
    50 public:
       
    51   typedef UniformRandomNumberGenerator base_type;
       
    52   typedef IntType result_type;
       
    53 
       
    54   uniform_smallint_integer(base_type & rng, IntType min, IntType max)
       
    55     : _rng(&rng)
       
    56   { set(min, max); }
       
    57 
       
    58   void set(result_type min, result_type max);
       
    59   
       
    60   result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
       
    61   result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
       
    62   base_type& base() const { return *_rng; }
       
    63   
       
    64   result_type operator()()
       
    65   {
       
    66     // we must not use the low bits here, because LCGs get very bad then
       
    67     return (((*_rng)() - (_rng->min)()) / _factor) % _range + _min;
       
    68   }
       
    69 
       
    70 private:
       
    71   typedef typename base_type::result_type base_result;
       
    72   base_type * _rng;
       
    73   IntType _min, _max;
       
    74   base_result _range;
       
    75   int _factor;
       
    76 };
       
    77 
       
    78 template<class UniformRandomNumberGenerator, class IntType>
       
    79 void uniform_smallint_integer<UniformRandomNumberGenerator, IntType>::
       
    80 set(result_type min, result_type max) 
       
    81 {
       
    82   _min = min;
       
    83   _max = max;
       
    84   assert(min < max);
       
    85 
       
    86   _range = static_cast<base_result>(_max-_min)+1;
       
    87   base_result _factor = 1;
       
    88   
       
    89   // LCGs get bad when only taking the low bits.
       
    90   // (probably put this logic into a partial template specialization)
       
    91   // Check how many low bits we can ignore before we get too much
       
    92   // quantization error.
       
    93   base_result r_base = (_rng->max)() - (_rng->min)();
       
    94   if(r_base == (std::numeric_limits<base_result>::max)()) {
       
    95     _factor = 2;
       
    96     r_base /= 2;
       
    97   }
       
    98   r_base += 1;
       
    99   if(r_base % _range == 0) {
       
   100     // No quantization effects, good
       
   101     _factor = r_base / _range;
       
   102   } else {
       
   103     // carefully avoid overflow; pessimizing heree
       
   104     for( ; r_base/_range/32 >= _range; _factor *= 2)
       
   105       r_base /= 2;
       
   106   }
       
   107 }
       
   108 
       
   109 template<class UniformRandomNumberGenerator, class IntType>
       
   110 class uniform_smallint_float
       
   111 {
       
   112 public:
       
   113   typedef UniformRandomNumberGenerator base_type;
       
   114   typedef IntType result_type;
       
   115 
       
   116   uniform_smallint_float(base_type & rng, IntType min, IntType max)
       
   117     : _rng(rng)
       
   118   {
       
   119     // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope
       
   120 #if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) && !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300)
       
   121     BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer);
       
   122     BOOST_STATIC_ASSERT(!std::numeric_limits<typename base_type::result_type>::is_integer);
       
   123 #endif
       
   124 
       
   125     assert(min < max);
       
   126     set(min, max);
       
   127   }
       
   128 
       
   129   void set(result_type min, result_type max)
       
   130   {
       
   131     _min = min;
       
   132     _max = max;
       
   133     _range = static_cast<base_result>(_max-_min)+1;
       
   134   }
       
   135 
       
   136   result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
       
   137   result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
       
   138   base_type& base() const { return _rng.base(); }
       
   139 
       
   140   result_type operator()()
       
   141   {
       
   142     return static_cast<IntType>(_rng() * _range) + _min;
       
   143   }
       
   144 
       
   145 private:
       
   146   typedef typename base_type::result_type base_result;
       
   147   uniform_01<base_type> _rng;
       
   148   IntType _min, _max;
       
   149   base_result _range;
       
   150 };
       
   151 
       
   152 
       
   153 } // namespace detail
       
   154 
       
   155 
       
   156 
       
   157 
       
   158 template<class IntType = int>
       
   159 class uniform_smallint
       
   160 {
       
   161 public:
       
   162   typedef IntType input_type;
       
   163   typedef IntType result_type;
       
   164 
       
   165   explicit uniform_smallint(IntType min = 0, IntType max = 9)
       
   166     : _min(min), _max(max)
       
   167   {
       
   168 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
       
   169     // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope
       
   170     BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer);
       
   171 #endif
       
   172  }
       
   173 
       
   174   result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
       
   175   result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
       
   176   void reset() { }
       
   177 
       
   178   template<class Engine>
       
   179   result_type operator()(Engine& eng)
       
   180   {
       
   181     typedef typename Engine::result_type base_result;
       
   182     base_result _range = static_cast<base_result>(_max-_min)+1;
       
   183     base_result _factor = 1;
       
   184     
       
   185     // LCGs get bad when only taking the low bits.
       
   186     // (probably put this logic into a partial template specialization)
       
   187     // Check how many low bits we can ignore before we get too much
       
   188     // quantization error.
       
   189     base_result r_base = (eng.max)() - (eng.min)();
       
   190     if(r_base == (std::numeric_limits<base_result>::max)()) {
       
   191       _factor = 2;
       
   192       r_base /= 2;
       
   193     }
       
   194     r_base += 1;
       
   195     if(r_base % _range == 0) {
       
   196       // No quantization effects, good
       
   197       _factor = r_base / _range;
       
   198     } else {
       
   199       // carefully avoid overflow; pessimizing heree
       
   200       for( ; r_base/_range/32 >= _range; _factor *= 2)
       
   201         r_base /= 2;
       
   202     }
       
   203 
       
   204     return ((eng() - (eng.min)()) / _factor) % _range + _min;
       
   205   }
       
   206 
       
   207 #if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
       
   208   template<class CharT, class Traits>
       
   209   friend std::basic_ostream<CharT,Traits>&
       
   210   operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_smallint& ud)
       
   211   {
       
   212     os << ud._min << " " << ud._max;
       
   213     return os;
       
   214   }
       
   215 
       
   216   template<class CharT, class Traits>
       
   217   friend std::basic_istream<CharT,Traits>&
       
   218   operator>>(std::basic_istream<CharT,Traits>& is, uniform_smallint& ud)
       
   219   {
       
   220 # if BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300
       
   221       return detail::extract_uniform_int(is, ud, ud._impl);
       
   222 # else
       
   223     is >> std::ws >> ud._min >> std::ws >> ud._max;
       
   224     return is;
       
   225 # endif
       
   226   }
       
   227 #endif
       
   228 
       
   229 private:
       
   230   result_type _min;
       
   231   result_type _max;
       
   232 };
       
   233 
       
   234 } // namespace boost
       
   235 
       
   236 #endif // BOOST_RANDOM_UNIFORM_SMALLINT_HPP