ExRandom  3.0
rand_digit.hpp
Go to the documentation of this file.
1 /**
2  * @file rand_digit.hpp
3  * @author Charles Karney <charles.karney@sri.com>
4  * @brief Definition of rand_digit
5  *
6  * Copyright (c) Charles Karney (2014) and licensed under the MIT/X11 License.
7  * For more information, see http://exrandom.sourceforge.net/
8  */
9 
10 #if !defined(EXRANDOM_RAND_DIGIT_HPP)
11 #define EXRANDOM_RAND_DIGIT_HPP 1
12 
13 #include <random> // for uniform_int_distribution
14 #include <cmath> // for std::ldexp
15 
17 
18 #if defined(_MSC_VER)
19 // Squelch warnings about constant conditional expressions
20 # pragma warning (push)
21 # pragma warning (disable: 4127)
22 #endif
23 
24 namespace exrandom {
25 
26  /**
27  * @brief Machinery to convert a random generator into a random digit.
28  *
29  * @tparam b the base for the digits.
30  *
31  * This produces random digits in the range [0,b). In addition it
32  * keeps count of how many digits are produced.
33  */
34  template<uint_t b> class rand_digit {
35  public:
36  /**
37  * The base for the digits (or 0 if the base is 2<sup>32</sup>).
38  */
39  static const uint_t base = digit_arithmetic<b>::base;
40  /**
41  * The minimum value produced by operator().
42  */
43  static const uint_t min_value = 0U;
44  /**
45  * The maximum value produced by operator().
46  */
47  static const uint_t max_value = digit_arithmetic<b>::basem1;
48  /**
49  * The number of bits needed to represent a digit.
50  */
51  static const int bits = digit_arithmetic<b>::bits;
52  /**
53  * Is the base a power of two?
54  */
56  /**
57  * The constructor (which initializes the count to 0).
58  */
59  rand_digit() : _count(0) {}
60  /**
61  * @tparam Generator the type of g.
62  * @param g the random generator engine.
63  * @return the random digit.
64  */
65  template<typename Generator>
66  uint_t operator()(Generator& g) { // a random digit
67  ++_count;
68  if ( power_of_two &&
69  Generator::min() == 0UL &&
70  Generator::max() == 0xffffffffUL )
71  // optimize for std::mt19937 which creates 32 bits of randomness
72  return uint_t(g() >> (32 - bits));
73  else if ( power_of_two &&
74  Generator::min() == 0UL &&
75  Generator::max() == 0xffffffffffffffffULL )
76  // optimize for std::mt19937_64 which creates 64 bits of randomness
77  return uint_t((g() & 0xffffffffUL) >> (32 - bits));
78  else {
79  // In some cases _gen loses track of its parameters, so supply them
80  // here instead of in the constructor.
81  return _gen(g, uint_random_t::param_type(min_value, max_value));
82  }
83  }
84  /**
85  * @return the count.
86  */
87  long long count() const { return _count; }
88  /**
89  * @tparam the floating point type of the result.
90  * @return 1/@e base as a floating point number.
91  */
92  template<typename RealType>
93  static RealType invrealbase() {
94  using std::ldexp;
95  return power_of_two ? ldexp(RealType(1), -bits) : 1/RealType(base);
96  }
97  private:
98  typedef std::uniform_int_distribution<uint_t> uint_random_t;
99  uint_random_t _gen;
100  long long _count;
101  };
102 
103 }
104 
105 #if defined(_MSC_VER)
106 # pragma warning (pop)
107 #endif
108 
109 #endif // EXRANDOM_RAND_DIGIT_HPP
Machinery to manipulate bases.
Definition of digit_arithmetic.
Machinery to convert a random generator into a random digit.
Definition: rand_digit.hpp:34
static const uint_t base
Definition: rand_digit.hpp:39
uint_t operator()(Generator &g)
Definition: rand_digit.hpp:66
static RealType invrealbase()
Definition: rand_digit.hpp:93
static const int bits
Definition: rand_digit.hpp:51
The common namespace.
Definition: aux_info.hpp:18
static const uint_t max_value
Definition: rand_digit.hpp:47
static const bool power_of_two
Definition: rand_digit.hpp:55
long long count() const
Definition: rand_digit.hpp:87
static const uint_t min_value
Definition: rand_digit.hpp:43