ExRandom  3.0
unit_normal_distribution.hpp
Go to the documentation of this file.
1 /**
2  * @file unit_normal_distribution.hpp
3  * @author Charles Karney <charles.karney@sri.com>
4  * @brief Definiton of unit_normal_distribution
5  *
6  * Copyright (c) Charles Karney (2014-2020) and licensed under the MIT/X11
7  * License. For more information, see http://exrandom.sourceforge.net/
8  */
9 
10 #if !defined(EXRANDOM_UNIT_NORMAL_DISTRIBUTION_HPP)
11 #define EXRANDOM_UNIT_NORMAL_DISTRIBUTION_HPP 1
12 
13 /**
14  * @relates exrandom::unit_normal_distribution
15  *
16  * Should exrandom::unit_normal_distribution use exrandom::unit_normal_kahn
17  * instead of exrandom::unit_normal_dist as the underlying distribution.
18  * Because the output of exrandom::unit_normal_kahn is slightly biased,
19  * EXRANDOM_USE_KAHN should be set to 0.
20  */
21 #define EXRANDOM_USE_KAHN 0
22 
23 #include <iostream> // for std::ostream, etc.
24 #include <limits>
25 
26 #include <exrandom/rand_digit.hpp>
27 #if EXRANDOM_USE_KAHN
29 #else
31 #endif
32 
33 namespace exrandom {
34 
35  /**
36  * @brief Sample exactly from the unit normal distribution.
37  *
38  * This samples from the unit normal distribution
39  * P(x) = exp(&minus; x<sup>2</sup>/2) / &radic;(2&pi;).
40  * This is a replacement for std::normal_distribution (with no parameters).
41  * It is equivalent to sampling a real number exactly from the distribution
42  * and rounding it to a floating point number. This implements Algorithm N
43  * with improvements due to Du et al. (2020).
44  *
45  * @tparam RealType the floating point type of the resulting deviates. This
46  * can include various multi-precision floating point types; see
47  * u_rand::value of details.
48  *
49  * This is a wrapper for unit_normal_dist to turn it into a C++11 style
50  * random distribution. If the radix of RealType is 2 (the usual case), then
51  * the base for unit_normal_dist is set to 2<sup>32</sup>; otherwise (e.g.,
52  * RealType is a decimal system), the base is set to the radix.
53  *
54  * If the macro EXRANDOM_USE_KAHN is set to 1, then unit_normal_kahn is used
55  * instead (with the base set to the radix for RealType). Because this
56  * introduces a slight bias, this is not recommended.
57  *
58  * @tparam RealType the floating point type of the resulting deviates.
59  */
60  template<typename RealType = double>
62  public:
63  /**
64  * The type of the range of the distribution.
65  */
66  typedef RealType result_type;
67  /**
68  * @brief Parameter type for unit_normal_distribution.
69  *
70  * This holds no information because this distribution takes no parameters.
71  */
72  struct param_type {
73  /**
74  * The type of the random number distribution.
75  */
77  };
78  /**
79  * Constructs a normal distribution.
80  */
81  explicit
82  unit_normal_distribution() : _normal_dist(_D) {}
83 
84  /**
85  * Constructs a normal distribution with a parameter.
86  *
87  * The parameter is ignored because it has no state.
88  */
89  explicit
91  : _normal_dist(_D) {}
92 
93  /**
94  * Resets the distribution state.
95  */
96  void reset() {}
97 
98  /**
99  * @return the parameter set of the distribution.
100  */
101  param_type param() const { return param_type(); }
102 
103  /**
104  * Sets the parameter set of the distribution.
105  *
106  * The function does not because a param_type has no state.
107  */
108  void param(const param_type& /*param*/) {}
109 
110  /**
111  * @return the greatest lower bound value of the distribution.
112  */
113  result_type min() const
114  { return std::numeric_limits<result_type>::lowest(); }
115 
116  /**
117  * @return the least upper bound value of the distribution.
118  */
119  result_type max() const { return std::numeric_limits<result_type>::max(); }
120 
121  /**
122  * @tparam Generator the type of g.
123  * @param g the random generator engine.
124  * @return a normal deviate.
125  */
126  template<typename Generator>
127  result_type operator()(Generator& g)
128  { return _normal_dist.template value<result_type>(g); }
129 
130  /**
131  * @tparam Generator the type of g.
132  * @param g the random generator engine.
133  * @return a normal deviate.
134  */
135  template<typename Generator>
136  result_type operator()(Generator& g, const param_type& /*p*/)
137  { return this->operator()(g); }
138 
139  /**
140  * Compare two unit_normal_distributions.
141  * @return true.
142  */
143  friend bool
146  { return true; }
147 
148  /**
149  * Contrast two unit_normal_distributions.
150  * @return false.
151  */
152  friend bool
155  { return false; }
156 
157  /**
158  * Inserts a unit_normal_distribution random number distribution into the
159  * output stream @e os.
160  *
161  * @param os an output stream.
162  * @return os.
163  *
164  * This function does nothing because this distribution has no state.
165  */
166  friend std::ostream&
167  operator<<(std::ostream& os, const unit_normal_distribution<RealType>& /*x*/)
168  { return os; }
169 
170  /**
171  * Extracts a unit_normal_distribution random number distribution from the
172  * input stream @e is.
173  *
174  * @param is an input stream.
175  * @return is.
176  *
177  * This function does nothing because this distribution has no state.
178  */
179  friend std::istream&
180  operator>>(std::istream& is, unit_normal_distribution& /*x*/)
181  { return is; }
182 
183  private:
184  static_assert(!std::numeric_limits<RealType>::is_integer,
185  "template argument not a floating point type");
186  param_type _param;
187 #if EXRANDOM_USE_KAHN
188  static const uint_t _base = std::numeric_limits<RealType>::radix;
191 #else
192  static const uint_t _base = std::numeric_limits<RealType>::radix == 2 ?
193  0UL : std::numeric_limits<RealType>::radix;
196 #endif
197  };
198 
199 }
200 
201 #endif // EXRANDOM_UNIT_NORMAL_DISTRIBUTION_HPP
Sample u-rands from the normal distribution, Kahn's method (deprecated)
Sample u-rands exactly from the unit normal distribution.
friend std::istream & operator>>(std::istream &is, unit_normal_distribution &)
Parameter type for unit_normal_distribution.
Definition of rand_digit.
unit_normal_distribution< RealType > distribution_type
result_type operator()(Generator &g, const param_type &)
Sample exactly from the unit normal distribution.
The common namespace.
Definition: aux_info.hpp:18
friend bool operator==(const unit_normal_distribution< RealType > &, const unit_normal_distribution< RealType > &)
Definition of unit_normal_dist.
Definition of unit_normal_kahn.
friend bool operator!=(const unit_normal_distribution< RealType > &, const unit_normal_distribution< RealType > &)
friend std::ostream & operator<<(std::ostream &os, const unit_normal_distribution< RealType > &)