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