lognormal_distribution.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /* boost random/lognormal_distribution.hpp header file
  2. *
  3. * Copyright Jens Maurer 2000-2001
  4. * Copyright Steven Watanabe 2011
  5. * Distributed under the Boost Software License, Version 1.0. (See
  6. * accompanying file LICENSE_1_0.txt or copy at
  7. * http://www.boost.org/LICENSE_1_0.txt)
  8. *
  9. * See http://www.boost.org for most recent version including documentation.
  10. *
  11. * $Id$
  12. *
  13. * Revision history
  14. * 2001-02-18 moved to individual header files
  15. */
  16. #ifndef BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP
  17. #define BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP
  18. #include <boost/config/no_tr1/cmath.hpp> // std::exp, std::sqrt
  19. #include <cassert>
  20. #include <iosfwd>
  21. #include <istream>
  22. #include <boost/limits.hpp>
  23. #include <boost/random/detail/config.hpp>
  24. #include <boost/random/detail/operators.hpp>
  25. #include <boost/random/normal_distribution.hpp>
  26. namespace boost {
  27. namespace random {
  28. /**
  29. * Instantiations of class template lognormal_distribution model a
  30. * \random_distribution. Such a distribution produces random numbers
  31. * with \f$\displaystyle p(x) = \frac{1}{x s \sqrt{2\pi}} e^{\frac{-\left(\log(x)-m\right)^2}{2s^2}}\f$
  32. * for x > 0.
  33. *
  34. * @xmlwarning
  35. * This distribution has been updated to match the C++ standard.
  36. * Its behavior has changed from the original
  37. * boost::lognormal_distribution. A backwards compatible
  38. * version is provided in namespace boost.
  39. * @endxmlwarning
  40. */
  41. template<class RealType = double>
  42. class lognormal_distribution
  43. {
  44. public:
  45. typedef typename normal_distribution<RealType>::input_type input_type;
  46. typedef RealType result_type;
  47. class param_type
  48. {
  49. public:
  50. typedef lognormal_distribution distribution_type;
  51. /** Constructs the parameters of a lognormal_distribution. */
  52. explicit param_type(RealType m_arg = RealType(0.0),
  53. RealType s_arg = RealType(1.0))
  54. : _m(m_arg), _s(s_arg) {}
  55. /** Returns the "m" parameter of the distribution. */
  56. RealType m() const { return _m; }
  57. /** Returns the "s" parameter of the distribution. */
  58. RealType s() const { return _s; }
  59. /** Writes the parameters to a std::ostream. */
  60. BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
  61. {
  62. os << parm._m << " " << parm._s;
  63. return os;
  64. }
  65. /** Reads the parameters from a std::istream. */
  66. BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
  67. {
  68. is >> parm._m >> std::ws >> parm._s;
  69. return is;
  70. }
  71. /** Returns true if the two sets of parameters are equal. */
  72. BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
  73. { return lhs._m == rhs._m && lhs._s == rhs._s; }
  74. /** Returns true if the two sets of parameters are different. */
  75. BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
  76. private:
  77. RealType _m;
  78. RealType _s;
  79. };
  80. /**
  81. * Constructs a lognormal_distribution. @c m and @c s are the
  82. * parameters of the distribution.
  83. */
  84. explicit lognormal_distribution(RealType m_arg = RealType(0.0),
  85. RealType s_arg = RealType(1.0))
  86. : _normal(m_arg, s_arg) {}
  87. /**
  88. * Constructs a lognormal_distribution from its parameters.
  89. */
  90. explicit lognormal_distribution(const param_type& parm)
  91. : _normal(parm.m(), parm.s()) {}
  92. // compiler-generated copy ctor and assignment operator are fine
  93. /** Returns the m parameter of the distribution. */
  94. RealType m() const { return _normal.mean(); }
  95. /** Returns the s parameter of the distribution. */
  96. RealType s() const { return _normal.sigma(); }
  97. /** Returns the smallest value that the distribution can produce. */
  98. RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
  99. { return RealType(0); }
  100. /** Returns the largest value that the distribution can produce. */
  101. RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
  102. { return (std::numeric_limits<RealType>::infinity)(); }
  103. /** Returns the parameters of the distribution. */
  104. param_type param() const { return param_type(m(), s()); }
  105. /** Sets the parameters of the distribution. */
  106. void param(const param_type& parm)
  107. {
  108. typedef normal_distribution<RealType> normal_type;
  109. typename normal_type::param_type normal_param(parm.m(), parm.s());
  110. _normal.param(normal_param);
  111. }
  112. /**
  113. * Effects: Subsequent uses of the distribution do not depend
  114. * on values produced by any engine prior to invoking reset.
  115. */
  116. void reset() { _normal.reset(); }
  117. /**
  118. * Returns a random variate distributed according to the
  119. * lognormal distribution.
  120. */
  121. template<class Engine>
  122. result_type operator()(Engine& eng)
  123. {
  124. using std::exp;
  125. return exp(_normal(eng));
  126. }
  127. /**
  128. * Returns a random variate distributed according to the
  129. * lognormal distribution with parameters specified by param.
  130. */
  131. template<class Engine>
  132. result_type operator()(Engine& eng, const param_type& parm)
  133. { return lognormal_distribution(parm)(eng); }
  134. /** Writes the distribution to a @c std::ostream. */
  135. BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, lognormal_distribution, ld)
  136. {
  137. os << ld._normal;
  138. return os;
  139. }
  140. /** Reads the distribution from a @c std::istream. */
  141. BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, lognormal_distribution, ld)
  142. {
  143. is >> ld._normal;
  144. return is;
  145. }
  146. /**
  147. * Returns true if the two distributions will produce identical
  148. * sequences of values given equal generators.
  149. */
  150. BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(lognormal_distribution, lhs, rhs)
  151. { return lhs._normal == rhs._normal; }
  152. /**
  153. * Returns true if the two distributions may produce different
  154. * sequences of values given equal generators.
  155. */
  156. BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(lognormal_distribution)
  157. private:
  158. normal_distribution<result_type> _normal;
  159. };
  160. } // namespace random
  161. /// \cond show_deprecated
  162. /**
  163. * Provided for backwards compatibility. This class is
  164. * deprecated. It provides the old behavior of lognormal_distribution with
  165. * \f$\displaystyle p(x) = \frac{1}{x \sigma_N \sqrt{2\pi}} e^{\frac{-\left(\log(x)-\mu_N\right)^2}{2\sigma_N^2}}\f$
  166. * for x > 0, where \f$\displaystyle \mu_N = \log\left(\frac{\mu^2}{\sqrt{\sigma^2 + \mu^2}}\right)\f$ and
  167. * \f$\displaystyle \sigma_N = \sqrt{\log\left(1 + \frac{\sigma^2}{\mu^2}\right)}\f$.
  168. */
  169. template<class RealType = double>
  170. class lognormal_distribution
  171. {
  172. public:
  173. typedef typename normal_distribution<RealType>::input_type input_type;
  174. typedef RealType result_type;
  175. lognormal_distribution(RealType mean_arg = RealType(1.0),
  176. RealType sigma_arg = RealType(1.0))
  177. : _mean(mean_arg), _sigma(sigma_arg)
  178. {
  179. init();
  180. }
  181. RealType mean() const { return _mean; }
  182. RealType sigma() const { return _sigma; }
  183. void reset() { _normal.reset(); }
  184. template<class Engine>
  185. RealType operator()(Engine& eng)
  186. {
  187. using std::exp;
  188. return exp(_normal(eng) * _nsigma + _nmean);
  189. }
  190. BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, lognormal_distribution, ld)
  191. {
  192. os << ld._normal << " " << ld._mean << " " << ld._sigma;
  193. return os;
  194. }
  195. BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, lognormal_distribution, ld)
  196. {
  197. is >> ld._normal >> std::ws >> ld._mean >> std::ws >> ld._sigma;
  198. ld.init();
  199. return is;
  200. }
  201. private:
  202. /// \cond show_private
  203. void init()
  204. {
  205. using std::log;
  206. using std::sqrt;
  207. _nmean = log(_mean*_mean/sqrt(_sigma*_sigma + _mean*_mean));
  208. _nsigma = sqrt(log(_sigma*_sigma/_mean/_mean+result_type(1)));
  209. }
  210. RealType _mean;
  211. RealType _sigma;
  212. RealType _nmean;
  213. RealType _nsigma;
  214. normal_distribution<RealType> _normal;
  215. /// \endcond
  216. };
  217. /// \endcond
  218. } // namespace boost
  219. #endif // BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP