mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
randomT.hpp
Go to the documentation of this file.
1 /** \file randomT.hpp
2  * \author Jared R. Males
3  * \brief Defines a random number type
4  * \ingroup gen_math_files
5  *
6  */
7 
8 //***********************************************************************//
9 // Copyright 2015, 2016, 2017, 2020 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef mx_math_randomT_hpp
28 #define mx_math_randomT_hpp
29 
30 #include <random>
31 
32 #include "randomSeed.hpp"
33 
34 namespace mx
35 {
36 namespace math
37 {
38 
39 ///A random number type, which functions like any other arithmetic type.
40 /**
41  * Combines a random engine, and a random distribution. Using the type conversion operator
42  * randomT returns the next random deviate whenever it is referenced.
43  *
44  * Example:
45  *
46  \code
47  //This can also be done using the alias definition mx::math::normDistT.
48  randomT<double, std::mt19937_64, std::normal_distribution<double> > norm_distd;
49  norm_distd.seed(); //
50 
51  double d1 = norm_distd; //get a normally distributed value
52  double d2 = norm_distd; //get the next normally distributed value
53  \endcode
54  *
55  * \test Verify compilation and basic operation of randomT with std::distributions \ref tests_math_randomT_basic "[test doc]"
56  * \test Verify compilation and basic operation of randomT with the Laplace distribution \ref tests_math_randomT_basic_laplace "[test doc]"
57  *
58  * \ingroup random
59  */
60 template<class typeT, class _ranengT, class _randistT> class randomT
61 {
62 
63 public:
64 
65  ///Typedef for the distribution type
66  typedef _randistT randistT;
67 
68  ///Typedef for the engine type
69  typedef _ranengT ranengT;
70 
71  ///Constructor
72  /** By default this calls the seed method, which will use /dev/random to seed the generator on linux, and time(0) on other systems.
73  * Set to false to suppress seeding, and/or set a seed with seed(x).
74  */
75  randomT(bool doSeed = true /**< [in] [optional] if true then the seed method is called upon construction.*/ )
76  {
77  if(doSeed) seed();
78  }
79 
80  ///The random distribution
81  _randistT distribution;
82 
83  ///The random engine
85 
86  ///The conversion operator, returns the next value in the sequence, according to the distribution.
87  operator typeT()
88  {
89  return distribution(engine);
90  }
91 
92  ///Set the seed of the random engine.
93  /** Calls the engines seed member function.
94  *
95  */
96  void seed( typename ranengT::result_type seedval /**< [in] the argument to pass to ranengT::seed() */)
97  {
98  engine.seed(seedval);
99  }
100 
101  ///Seed the random engine with a good value
102  /** Calls \ref mx::randomSeed to get the value. On linux this uses /dev/urandom. On other sytems, this uses time(0).
103  */
104  void seed()
105  {
106  typename ranengT::result_type seedval;
107  randomSeed(seedval);
108  seed(seedval);
109  }
110 
111 };
112 
113 
114 /**
115  * @brief The Laplace (double exponential) continuous distribution for random numbers.
116  *
117  * The formula for the exponential probability density function is
118  * @f$p(x|\lambda) = \frac{\lambda}{2} e^{-\lambda x}@f$.
119  *
120  * <table border=1 cellpadding=10 cellspacing=0>
121  * <caption align=top>Distribution Statistics</caption>
122  * <tr><td>Mean</td><td>@f$0@f$</td></tr>
123  * <tr><td>Median</td><td>@f$0@f$</td></tr>
124  * <tr><td>Mode</td><td>@f$0@f$</td></tr>
125  * <tr><td>Range</td><td>@f$[-\infty, \infty]@f$</td></tr>
126  * <tr><td>Standard Deviation</td><td>@f$\frac{\sqrt{2}}{\lambda}@f$</td></tr>
127  * </table>
128  *
129  * This is based on the implementation of the exponential distribution in the GNU ISO C++ Library version 4.6.
130  *
131  * \test Verify compilation and basic operation of randomT with the Laplace distribution \ref tests_math_randomT_basic_laplace "[test doc]"
132  *
133  * \ingroup random
134  */
135 template<typename _RealType = double>
137 {
138  static_assert(std::is_floating_point<_RealType>::value, "template argument not a floating point type");
139 
140 public:
141  /** The type of the range of the distribution. */
142  typedef _RealType result_type;
143 
144  /** Parameter type. */
145  struct param_type
146  {
148 
149  explicit param_type(_RealType __lambda = _RealType(1)) : _M_lambda(__lambda)
150  {}
151 
152  _RealType lambda() const
153  {
154  return _M_lambda;
155  }
156 
157  friend bool operator==(const param_type& __p1, const param_type& __p2)
158  {
159  return __p1._M_lambda == __p2._M_lambda;
160  }
161 
162  private:
163  _RealType _M_lambda;
164  };
165 
166 public:
167  /**
168  * @brief Constructs a Laplace (double exponential) distribution with inverse scale
169  * parameter @f$\lambda@f$.
170  */
171  explicit laplace_distribution(const result_type& __lambda = result_type(1)) : _M_param(__lambda){ }
172 
173  explicit laplace_distribution(const param_type& __p) : _M_param(__p) { }
174 
175  /**
176  * @brief Resets the distribution state.
177  *
178  * Has no effect on Laplace distributions.
179  */
180  void reset() { }
181 
182  /**
183  * @brief Returns the inverse scale parameter of the distribution.
184  */
185  _RealType lambda() const
186  {
187  return _M_param.lambda();
188  }
189 
190  /**
191  * @brief Returns the parameter set of the distribution.
192  */
194  {
195  return _M_param;
196  }
197 
198  /**
199  * @brief Sets the parameter set of the distribution.
200  * @param __param The new parameter set of the distribution.
201  */
202  void param(const param_type& __param)
203  {
204  _M_param = __param;
205  }
206 
207  /**
208  * @brief Returns the greatest lower bound value of the distribution.
209  */
210  result_type min() const
211  {
212  return std::numeric_limits<result_type>::min();
213  }
214 
215  /**
216  * @brief Returns the least upper bound value of the distribution.
217  */
218  result_type max() const
219  {
220  return std::numeric_limits<result_type>::max();
221  }
222 
223  /**
224  * @brief Generating functions.
225  */
226  template<typename _UniformRandomNumberGenerator> result_type operator()(_UniformRandomNumberGenerator& __urng)
227  {
228  return this->operator()(__urng, this->param());
229  }
230 
231  template<typename _UniformRandomNumberGenerator> result_type operator()
232  (_UniformRandomNumberGenerator& __urng, const param_type& __p)
233  {
234  int sgnx = 1;
235 
236  result_type __aurng = 0.5 - std::generate_canonical<result_type, std::numeric_limits<result_type>::digits, _UniformRandomNumberGenerator>(__urng);
237 
238  if(__aurng < 0)
239  {
240  sgnx = -1;
241  __aurng *= -1;
242  }
243 
244 
245  return 0. -__p.lambda()*sgnx*std::log(1.-2.*__aurng);
246  }
247 
248 private:
249  param_type _M_param;
250 };
251 
252 /**
253  * @brief Return true if two exponential distributions have the same
254  * parameters.
255  */
256 template<typename _RealType>
257 bool operator== ( const laplace_distribution<_RealType>& __d1,
259  )
260 {
261  return __d1.param() == __d2.param();
262 }
263 
264 /**
265  * @brief Return true if two exponential distributions have different
266  * parameters.
267  */
268 template<typename _RealType> bool operator!=( const laplace_distribution<_RealType>& __d1,
270  )
271 {
272  return !(__d1 == __d2);
273 }
274 
275 /**
276  * @brief Inserts a %laplace_distribution random number distribution
277  * @p __x into the output stream @p __os.
278  *
279  * @param __os An output stream.
280  * @param __x A %laplace_distribution random number distribution.
281  *
282  * @returns The output stream with the state of @p __x inserted or in
283  * an error state.
284  */
285 template<typename _RealType, typename _CharT, typename _Traits> std::basic_ostream<_CharT, _Traits>&
286  operator<<(std::basic_ostream<_CharT, _Traits>&, const laplace_distribution<_RealType>&);
287 
288 /**
289  * @brief Extracts a %laplace_distribution random number distribution
290  * @p __x from the input stream @p __is.
291  *
292  * @param __is An input stream.
293  * @param __x A %laplace_distribution random number
294  * generator engine.
295  *
296  * @returns The input stream with @p __x extracted or in an error state.
297  */
298 template<typename _RealType, typename _CharT, typename _Traits> std::basic_istream<_CharT, _Traits>&
299  operator>>(std::basic_istream<_CharT, _Traits>&, laplace_distribution<_RealType>&);
300 
301 
302 
303 
304 /** \ingroup random
305  * @{
306  */
307 
308 ///Alias for a uniform random variate
309 template<typename realT>
311 
312 ///Alias for a standard normal random variate
313 template<typename realT>
315 
316 
317 ///Alias for an exponential random variate
318 template<typename realT>
320 
321 ///Alias for a laplace random variate
322 template<typename realT>
324 
325 ///Alias for a poisson random variate
326 template<typename intT>
328 
329 ///Alias for a log normal variate
330 template<typename realT>
332 
333 /// @}
334 
335 } //namespace math
336 } //namespace mx
337 
338 #endif //mx_math_randomT_hpp
339 
340 
341 
342 
343 /*5/22/06: added 64 bit mersenne twister support
344 */
The Laplace (double exponential) continuous distribution for random numbers.
Definition: randomT.hpp:137
_RealType lambda() const
Returns the inverse scale parameter of the distribution.
Definition: randomT.hpp:185
void param(const param_type &__param)
Sets the parameter set of the distribution.
Definition: randomT.hpp:202
laplace_distribution(const result_type &__lambda=result_type(1))
Constructs a Laplace (double exponential) distribution with inverse scale parameter .
Definition: randomT.hpp:171
void reset()
Resets the distribution state.
Definition: randomT.hpp:180
result_type min() const
Returns the greatest lower bound value of the distribution.
Definition: randomT.hpp:210
param_type param() const
Returns the parameter set of the distribution.
Definition: randomT.hpp:193
result_type max() const
Returns the least upper bound value of the distribution.
Definition: randomT.hpp:218
result_type operator()(_UniformRandomNumberGenerator &__urng)
Generating functions.
Definition: randomT.hpp:226
A random number type, which functions like any other arithmetic type.
Definition: randomT.hpp:61
_randistT distribution
The random distribution.
Definition: randomT.hpp:81
randomT(bool doSeed=true)
Constructor.
Definition: randomT.hpp:75
void seed(typename ranengT::result_type seedval)
Set the seed of the random engine.
Definition: randomT.hpp:96
_ranengT ranengT
Typedef for the engine type.
Definition: randomT.hpp:69
ranengT engine
The random engine.
Definition: randomT.hpp:84
_randistT randistT
Typedef for the distribution type.
Definition: randomT.hpp:66
void seed()
Seed the random engine with a good value.
Definition: randomT.hpp:104
int randomSeed(intT &seedval)
Get a value to use as a random seed.
Definition: randomSeed.hpp:57
The mxlib c++ namespace.
Definition: mxError.hpp:107
Defines a random number seed generator.
bool operator!=(const laplace_distribution< _RealType > &__d1, const laplace_distribution< _RealType > &__d2)
Return true if two exponential distributions have different parameters.
Definition: randomT.hpp:268
std::basic_istream< _CharT, _Traits > & operator>>(std::basic_istream< _CharT, _Traits > &, laplace_distribution< _RealType > &)
Extracts a laplace_distribution random number distribution __x from the input stream __is.