epoc32/include/stdapis/boost/random/uniform_smallint.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
     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