epoc32/include/stdapis/boost/random/uniform_int.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_int.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_int.hpp,v 1.27 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_INT_HPP
    18 #define BOOST_RANDOM_UNIFORM_INT_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/detail/workaround.hpp>
    26 #include <boost/random/uniform_smallint.hpp>
    27 #include <boost/random/detail/signed_unsigned_compare.hpp>
    28 #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
    29 #include <boost/type_traits/is_float.hpp>
    30 #endif
    31 
    32 namespace boost {
    33 
    34 // uniform integer distribution on [min, max]
    35 template<class IntType = int>
    36 class uniform_int
    37 {
    38 public:
    39   typedef IntType input_type;
    40   typedef IntType result_type;
    41 
    42   explicit uniform_int(IntType min = 0, IntType max = 9)
    43     : _min(min), _max(max)
    44   {
    45 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
    46     // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope
    47     BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer);
    48 #endif
    49     assert(min <= max);
    50     init();
    51   }
    52 
    53   result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
    54   result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
    55   void reset() { }
    56   
    57   // can't have member function templates out-of-line due to MSVC bugs
    58   template<class Engine>
    59   result_type operator()(Engine& eng)
    60   {
    61     typedef typename Engine::result_type base_result;
    62     base_result bmin = (eng.min)();
    63     base_result brange = (eng.max)() - (eng.min)();
    64 
    65     if(_range == 0) {
    66       return _min;    
    67     } else if(random::equal_signed_unsigned(brange, _range)) {
    68       // this will probably never happen in real life
    69       // basically nothing to do; just take care we don't overflow / underflow
    70       return static_cast<result_type>(eng() - bmin) + _min;
    71     } else if(random::lessthan_signed_unsigned(brange, _range)) {
    72       // use rejection method to handle things like 0..3 --> 0..4
    73       for(;;) {
    74         // concatenate several invocations of the base RNG
    75         // take extra care to avoid overflows
    76         result_type limit;
    77         if(_range == (std::numeric_limits<result_type>::max)()) {
    78           limit = _range/(result_type(brange)+1);
    79           if(_range % result_type(brange)+1 == result_type(brange))
    80             ++limit;
    81         } else {
    82           limit = (_range+1)/(result_type(brange)+1);
    83         }
    84         // We consider "result" as expressed to base (brange+1):
    85         // For every power of (brange+1), we determine a random factor
    86         result_type result = result_type(0);
    87         result_type mult = result_type(1);
    88         while(mult <= limit) {
    89           result += (eng() - bmin) * mult;
    90           mult *= result_type(brange)+result_type(1);
    91         }
    92         if(mult == limit)
    93           // _range+1 is an integer power of brange+1: no rejections required
    94           return result;
    95         // _range/mult < brange+1  -> no endless loop
    96         result += uniform_int<result_type>(0, _range/mult)(eng) * mult;
    97         if(result <= _range)
    98           return result + _min;
    99       }
   100     } else {                   // brange > range
   101       if(brange / _range > 4 /* quantization_cutoff */ ) {
   102         // the new range is vastly smaller than the source range,
   103         // so quantization effects are not relevant
   104         return boost::uniform_smallint<result_type>(_min, _max)(eng);
   105       } else {
   106         // use rejection method to handle cases like 0..5 -> 0..4
   107         for(;;) {
   108           base_result result = eng() - bmin;
   109           // result and range are non-negative, and result is possibly larger
   110           // than range, so the cast is safe
   111           if(result <= static_cast<base_result>(_range))
   112             return result + _min;
   113         }
   114       }
   115     }
   116   }
   117 
   118 #if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
   119   template<class CharT, class Traits>
   120   friend std::basic_ostream<CharT,Traits>&
   121   operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_int& ud)
   122   {
   123     os << ud._min << " " << ud._max;
   124     return os;
   125   }
   126 
   127   template<class CharT, class Traits>
   128   friend std::basic_istream<CharT,Traits>&
   129   operator>>(std::basic_istream<CharT,Traits>& is, uniform_int& ud)
   130   {
   131 # if BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300
   132       return detail::extract_uniform_int(is, ud, ud.impl);
   133 # else
   134    is >> std::ws >> ud._min >> std::ws >> ud._max;
   135     ud.init();
   136     return is;
   137 # endif
   138   }
   139 #endif
   140 
   141 private:
   142   void init()
   143   {
   144     _range = _max - _min;
   145   }
   146     
   147   result_type _min, _max, _range;
   148 };
   149 
   150 } // namespace boost
   151 
   152 #endif // BOOST_RANDOM_UNIFORM_INT_HPP