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 17 #ifndef BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP 18 #define BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP 19 20 #include <boost/config/no_tr1/cmath.hpp> // std::exp, std::sqrt 21 #include <cassert> 22 #include <iosfwd> 23 #include <istream> 24 #include <boost/limits.hpp> 25 #include <boost/random/detail/config.hpp> 26 #include <boost/random/detail/operators.hpp> 27 #include <boost/random/normal_distribution.hpp> 28 29 namespace boost { 30 namespace random { 31 32 /** 33 * Instantiations of class template lognormal_distribution model a 34 * \random_distribution. Such a distribution produces random numbers 35 * with \f$\displaystyle p(x) = \frac{1}{x s \sqrt{2\pi}} e^{\frac{-\left(\log(x)-m\right)^2}{2s^2}}\f$ 36 * for x > 0. 37 * 38 * @xmlwarning 39 * This distribution has been updated to match the C++ standard. 40 * Its behavior has changed from the original 41 * boost::lognormal_distribution. A backwards compatible 42 * version is provided in namespace boost. 43 * @endxmlwarning 44 */ 45 template<class RealType = double> 46 class lognormal_distribution 47 { 48 public: 49 typedef typename normal_distribution<RealType>::input_type input_type; 50 typedef RealType result_type; 51 52 class param_type 53 { 54 public: 55 56 typedef lognormal_distribution distribution_type; 57 58 /** Constructs the parameters of a lognormal_distribution. */ param_type(RealType m_arg=RealType (0.0),RealType s_arg=RealType (1.0))59 explicit param_type(RealType m_arg = RealType(0.0), 60 RealType s_arg = RealType(1.0)) 61 : _m(m_arg), _s(s_arg) {} 62 63 /** Returns the "m" parameter of the distribution. */ m() const64 RealType m() const { return _m; } 65 66 /** Returns the "s" parameter of the distribution. */ s() const67 RealType s() const { return _s; } 68 69 /** Writes the parameters to a std::ostream. */ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os,param_type,parm)70 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm) 71 { 72 os << parm._m << " " << parm._s; 73 return os; 74 } 75 76 /** Reads the parameters from a std::istream. */ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is,param_type,parm)77 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm) 78 { 79 is >> parm._m >> std::ws >> parm._s; 80 return is; 81 } 82 83 /** Returns true if the two sets of parameters are equal. */ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type,lhs,rhs)84 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs) 85 { return lhs._m == rhs._m && lhs._s == rhs._s; } 86 87 /** Returns true if the two sets of parameters are different. */ 88 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type) 89 90 private: 91 RealType _m; 92 RealType _s; 93 }; 94 95 /** 96 * Constructs a lognormal_distribution. @c m and @c s are the 97 * parameters of the distribution. 98 */ lognormal_distribution(RealType m_arg=RealType (0.0),RealType s_arg=RealType (1.0))99 explicit lognormal_distribution(RealType m_arg = RealType(0.0), 100 RealType s_arg = RealType(1.0)) 101 : _normal(m_arg, s_arg) {} 102 103 /** 104 * Constructs a lognormal_distribution from its parameters. 105 */ lognormal_distribution(const param_type & parm)106 explicit lognormal_distribution(const param_type& parm) 107 : _normal(parm.m(), parm.s()) {} 108 109 // compiler-generated copy ctor and assignment operator are fine 110 111 /** Returns the m parameter of the distribution. */ m() const112 RealType m() const { return _normal.mean(); } 113 /** Returns the s parameter of the distribution. */ s() const114 RealType s() const { return _normal.sigma(); } 115 116 /** Returns the smallest value that the distribution can produce. */ BOOST_PREVENT_MACRO_SUBSTITUTION() const117 RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const 118 { return RealType(0); } 119 /** Returns the largest value that the distribution can produce. */ BOOST_PREVENT_MACRO_SUBSTITUTION() const120 RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const 121 { return (std::numeric_limits<RealType>::infinity)(); } 122 123 /** Returns the parameters of the distribution. */ param() const124 param_type param() const { return param_type(m(), s()); } 125 /** Sets the parameters of the distribution. */ param(const param_type & parm)126 void param(const param_type& parm) 127 { 128 typedef normal_distribution<RealType> normal_type; 129 typename normal_type::param_type normal_param(parm.m(), parm.s()); 130 _normal.param(normal_param); 131 } 132 133 /** 134 * Effects: Subsequent uses of the distribution do not depend 135 * on values produced by any engine prior to invoking reset. 136 */ reset()137 void reset() { _normal.reset(); } 138 139 /** 140 * Returns a random variate distributed according to the 141 * lognormal distribution. 142 */ 143 template<class Engine> operator ()(Engine & eng)144 result_type operator()(Engine& eng) 145 { 146 using std::exp; 147 return exp(_normal(eng)); 148 } 149 150 /** 151 * Returns a random variate distributed according to the 152 * lognormal distribution with parameters specified by param. 153 */ 154 template<class Engine> operator ()(Engine & eng,const param_type & parm)155 result_type operator()(Engine& eng, const param_type& parm) 156 { return lognormal_distribution(parm)(eng); } 157 158 /** Writes the distribution to a @c std::ostream. */ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os,lognormal_distribution,ld)159 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, lognormal_distribution, ld) 160 { 161 os << ld._normal; 162 return os; 163 } 164 165 /** Reads the distribution from a @c std::istream. */ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is,lognormal_distribution,ld)166 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, lognormal_distribution, ld) 167 { 168 is >> ld._normal; 169 return is; 170 } 171 172 /** 173 * Returns true if the two distributions will produce identical 174 * sequences of values given equal generators. 175 */ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(lognormal_distribution,lhs,rhs)176 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(lognormal_distribution, lhs, rhs) 177 { return lhs._normal == rhs._normal; } 178 179 /** 180 * Returns true if the two distributions may produce different 181 * sequences of values given equal generators. 182 */ 183 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(lognormal_distribution) 184 185 private: 186 normal_distribution<result_type> _normal; 187 }; 188 189 } // namespace random 190 191 /// \cond show_deprecated 192 193 /** 194 * Provided for backwards compatibility. This class is 195 * deprecated. It provides the old behavior of lognormal_distribution with 196 * \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$ 197 * for x > 0, where \f$\displaystyle \mu_N = \log\left(\frac{\mu^2}{\sqrt{\sigma^2 + \mu^2}}\right)\f$ and 198 * \f$\displaystyle \sigma_N = \sqrt{\log\left(1 + \frac{\sigma^2}{\mu^2}\right)}\f$. 199 */ 200 template<class RealType = double> 201 class lognormal_distribution 202 { 203 public: 204 typedef typename normal_distribution<RealType>::input_type input_type; 205 typedef RealType result_type; 206 lognormal_distribution(RealType mean_arg=RealType (1.0),RealType sigma_arg=RealType (1.0))207 lognormal_distribution(RealType mean_arg = RealType(1.0), 208 RealType sigma_arg = RealType(1.0)) 209 : _mean(mean_arg), _sigma(sigma_arg) 210 { 211 init(); 212 } mean() const213 RealType mean() const { return _mean; } sigma() const214 RealType sigma() const { return _sigma; } reset()215 void reset() { _normal.reset(); } 216 template<class Engine> operator ()(Engine & eng)217 RealType operator()(Engine& eng) 218 { 219 using std::exp; 220 return exp(_normal(eng) * _nsigma + _nmean); 221 } BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os,lognormal_distribution,ld)222 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, lognormal_distribution, ld) 223 { 224 os << ld._normal << " " << ld._mean << " " << ld._sigma; 225 return os; 226 } BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is,lognormal_distribution,ld)227 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, lognormal_distribution, ld) 228 { 229 is >> ld._normal >> std::ws >> ld._mean >> std::ws >> ld._sigma; 230 ld.init(); 231 return is; 232 } 233 private: 234 /// \cond show_private init()235 void init() 236 { 237 using std::log; 238 using std::sqrt; 239 _nmean = log(_mean*_mean/sqrt(_sigma*_sigma + _mean*_mean)); 240 _nsigma = sqrt(log(_sigma*_sigma/_mean/_mean+result_type(1))); 241 } 242 RealType _mean; 243 RealType _sigma; 244 RealType _nmean; 245 RealType _nsigma; 246 normal_distribution<RealType> _normal; 247 /// \endcond 248 }; 249 250 /// \endcond 251 252 } // namespace boost 253 254 #endif // BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP 255