epoc32/include/stdapis/boost/random/uniform_int.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
williamr@2
     1
/* boost random/uniform_int.hpp header file
williamr@2
     2
 *
williamr@2
     3
 * Copyright Jens Maurer 2000-2001
williamr@2
     4
 * Distributed under the Boost Software License, Version 1.0. (See
williamr@2
     5
 * accompanying file LICENSE_1_0.txt or copy at
williamr@2
     6
 * http://www.boost.org/LICENSE_1_0.txt)
williamr@2
     7
 *
williamr@2
     8
 * See http://www.boost.org for most recent version including documentation.
williamr@2
     9
 *
williamr@2
    10
 * $Id: uniform_int.hpp,v 1.27 2004/07/27 03:43:32 dgregor Exp $
williamr@2
    11
 *
williamr@2
    12
 * Revision history
williamr@2
    13
 *  2001-04-08  added min<max assertion (N. Becker)
williamr@2
    14
 *  2001-02-18  moved to individual header files
williamr@2
    15
 */
williamr@2
    16
williamr@2
    17
#ifndef BOOST_RANDOM_UNIFORM_INT_HPP
williamr@2
    18
#define BOOST_RANDOM_UNIFORM_INT_HPP
williamr@2
    19
williamr@2
    20
#include <cassert>
williamr@2
    21
#include <iostream>
williamr@2
    22
#include <boost/config.hpp>
williamr@2
    23
#include <boost/limits.hpp>
williamr@2
    24
#include <boost/static_assert.hpp>
williamr@2
    25
#include <boost/detail/workaround.hpp>
williamr@2
    26
#include <boost/random/uniform_smallint.hpp>
williamr@2
    27
#include <boost/random/detail/signed_unsigned_compare.hpp>
williamr@2
    28
#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
williamr@2
    29
#include <boost/type_traits/is_float.hpp>
williamr@2
    30
#endif
williamr@2
    31
williamr@2
    32
namespace boost {
williamr@2
    33
williamr@2
    34
// uniform integer distribution on [min, max]
williamr@2
    35
template<class IntType = int>
williamr@2
    36
class uniform_int
williamr@2
    37
{
williamr@2
    38
public:
williamr@2
    39
  typedef IntType input_type;
williamr@2
    40
  typedef IntType result_type;
williamr@2
    41
williamr@2
    42
  explicit uniform_int(IntType min = 0, IntType max = 9)
williamr@2
    43
    : _min(min), _max(max)
williamr@2
    44
  {
williamr@2
    45
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
williamr@2
    46
    // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope
williamr@2
    47
    BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer);
williamr@2
    48
#endif
williamr@2
    49
    assert(min <= max);
williamr@2
    50
    init();
williamr@2
    51
  }
williamr@2
    52
williamr@2
    53
  result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
williamr@2
    54
  result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
williamr@2
    55
  void reset() { }
williamr@2
    56
  
williamr@2
    57
  // can't have member function templates out-of-line due to MSVC bugs
williamr@2
    58
  template<class Engine>
williamr@2
    59
  result_type operator()(Engine& eng)
williamr@2
    60
  {
williamr@2
    61
    typedef typename Engine::result_type base_result;
williamr@2
    62
    base_result bmin = (eng.min)();
williamr@2
    63
    base_result brange = (eng.max)() - (eng.min)();
williamr@2
    64
williamr@2
    65
    if(_range == 0) {
williamr@2
    66
      return _min;    
williamr@2
    67
    } else if(random::equal_signed_unsigned(brange, _range)) {
williamr@2
    68
      // this will probably never happen in real life
williamr@2
    69
      // basically nothing to do; just take care we don't overflow / underflow
williamr@2
    70
      return static_cast<result_type>(eng() - bmin) + _min;
williamr@2
    71
    } else if(random::lessthan_signed_unsigned(brange, _range)) {
williamr@2
    72
      // use rejection method to handle things like 0..3 --> 0..4
williamr@2
    73
      for(;;) {
williamr@2
    74
        // concatenate several invocations of the base RNG
williamr@2
    75
        // take extra care to avoid overflows
williamr@2
    76
        result_type limit;
williamr@2
    77
        if(_range == (std::numeric_limits<result_type>::max)()) {
williamr@2
    78
          limit = _range/(result_type(brange)+1);
williamr@2
    79
          if(_range % result_type(brange)+1 == result_type(brange))
williamr@2
    80
            ++limit;
williamr@2
    81
        } else {
williamr@2
    82
          limit = (_range+1)/(result_type(brange)+1);
williamr@2
    83
        }
williamr@2
    84
        // We consider "result" as expressed to base (brange+1):
williamr@2
    85
        // For every power of (brange+1), we determine a random factor
williamr@2
    86
        result_type result = result_type(0);
williamr@2
    87
        result_type mult = result_type(1);
williamr@2
    88
        while(mult <= limit) {
williamr@2
    89
          result += (eng() - bmin) * mult;
williamr@2
    90
          mult *= result_type(brange)+result_type(1);
williamr@2
    91
        }
williamr@2
    92
        if(mult == limit)
williamr@2
    93
          // _range+1 is an integer power of brange+1: no rejections required
williamr@2
    94
          return result;
williamr@2
    95
        // _range/mult < brange+1  -> no endless loop
williamr@2
    96
        result += uniform_int<result_type>(0, _range/mult)(eng) * mult;
williamr@2
    97
        if(result <= _range)
williamr@2
    98
          return result + _min;
williamr@2
    99
      }
williamr@2
   100
    } else {                   // brange > range
williamr@2
   101
      if(brange / _range > 4 /* quantization_cutoff */ ) {
williamr@2
   102
        // the new range is vastly smaller than the source range,
williamr@2
   103
        // so quantization effects are not relevant
williamr@2
   104
        return boost::uniform_smallint<result_type>(_min, _max)(eng);
williamr@2
   105
      } else {
williamr@2
   106
        // use rejection method to handle cases like 0..5 -> 0..4
williamr@2
   107
        for(;;) {
williamr@2
   108
          base_result result = eng() - bmin;
williamr@2
   109
          // result and range are non-negative, and result is possibly larger
williamr@2
   110
          // than range, so the cast is safe
williamr@2
   111
          if(result <= static_cast<base_result>(_range))
williamr@2
   112
            return result + _min;
williamr@2
   113
        }
williamr@2
   114
      }
williamr@2
   115
    }
williamr@2
   116
  }
williamr@2
   117
williamr@2
   118
#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
williamr@2
   119
  template<class CharT, class Traits>
williamr@2
   120
  friend std::basic_ostream<CharT,Traits>&
williamr@2
   121
  operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_int& ud)
williamr@2
   122
  {
williamr@2
   123
    os << ud._min << " " << ud._max;
williamr@2
   124
    return os;
williamr@2
   125
  }
williamr@2
   126
williamr@2
   127
  template<class CharT, class Traits>
williamr@2
   128
  friend std::basic_istream<CharT,Traits>&
williamr@2
   129
  operator>>(std::basic_istream<CharT,Traits>& is, uniform_int& ud)
williamr@2
   130
  {
williamr@2
   131
# if BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300
williamr@2
   132
      return detail::extract_uniform_int(is, ud, ud.impl);
williamr@2
   133
# else
williamr@2
   134
   is >> std::ws >> ud._min >> std::ws >> ud._max;
williamr@2
   135
    ud.init();
williamr@2
   136
    return is;
williamr@2
   137
# endif
williamr@2
   138
  }
williamr@2
   139
#endif
williamr@2
   140
williamr@2
   141
private:
williamr@2
   142
  void init()
williamr@2
   143
  {
williamr@2
   144
    _range = _max - _min;
williamr@2
   145
  }
williamr@2
   146
    
williamr@2
   147
  result_type _min, _max, _range;
williamr@2
   148
};
williamr@2
   149
williamr@2
   150
} // namespace boost
williamr@2
   151
williamr@2
   152
#endif // BOOST_RANDOM_UNIFORM_INT_HPP