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