cannam@160
|
1 // Copyright John Maddock 2006.
|
cannam@160
|
2 // Use, modification and distribution are subject to the
|
cannam@160
|
3 // Boost Software License, Version 1.0. (See accompanying file
|
cannam@160
|
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
cannam@160
|
5
|
cannam@160
|
6 #ifndef BOOST_STATS_LOGNORMAL_HPP
|
cannam@160
|
7 #define BOOST_STATS_LOGNORMAL_HPP
|
cannam@160
|
8
|
cannam@160
|
9 // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3669.htm
|
cannam@160
|
10 // http://mathworld.wolfram.com/LogNormalDistribution.html
|
cannam@160
|
11 // http://en.wikipedia.org/wiki/Lognormal_distribution
|
cannam@160
|
12
|
cannam@160
|
13 #include <boost/math/distributions/fwd.hpp>
|
cannam@160
|
14 #include <boost/math/distributions/normal.hpp>
|
cannam@160
|
15 #include <boost/math/special_functions/expm1.hpp>
|
cannam@160
|
16 #include <boost/math/distributions/detail/common_error_handling.hpp>
|
cannam@160
|
17
|
cannam@160
|
18 #include <utility>
|
cannam@160
|
19
|
cannam@160
|
20 namespace boost{ namespace math
|
cannam@160
|
21 {
|
cannam@160
|
22 namespace detail
|
cannam@160
|
23 {
|
cannam@160
|
24
|
cannam@160
|
25 template <class RealType, class Policy>
|
cannam@160
|
26 inline bool check_lognormal_x(
|
cannam@160
|
27 const char* function,
|
cannam@160
|
28 RealType const& x,
|
cannam@160
|
29 RealType* result, const Policy& pol)
|
cannam@160
|
30 {
|
cannam@160
|
31 if((x < 0) || !(boost::math::isfinite)(x))
|
cannam@160
|
32 {
|
cannam@160
|
33 *result = policies::raise_domain_error<RealType>(
|
cannam@160
|
34 function,
|
cannam@160
|
35 "Random variate is %1% but must be >= 0 !", x, pol);
|
cannam@160
|
36 return false;
|
cannam@160
|
37 }
|
cannam@160
|
38 return true;
|
cannam@160
|
39 }
|
cannam@160
|
40
|
cannam@160
|
41 } // namespace detail
|
cannam@160
|
42
|
cannam@160
|
43
|
cannam@160
|
44 template <class RealType = double, class Policy = policies::policy<> >
|
cannam@160
|
45 class lognormal_distribution
|
cannam@160
|
46 {
|
cannam@160
|
47 public:
|
cannam@160
|
48 typedef RealType value_type;
|
cannam@160
|
49 typedef Policy policy_type;
|
cannam@160
|
50
|
cannam@160
|
51 lognormal_distribution(RealType l_location = 0, RealType l_scale = 1)
|
cannam@160
|
52 : m_location(l_location), m_scale(l_scale)
|
cannam@160
|
53 {
|
cannam@160
|
54 RealType result;
|
cannam@160
|
55 detail::check_scale("boost::math::lognormal_distribution<%1%>::lognormal_distribution", l_scale, &result, Policy());
|
cannam@160
|
56 detail::check_location("boost::math::lognormal_distribution<%1%>::lognormal_distribution", l_location, &result, Policy());
|
cannam@160
|
57 }
|
cannam@160
|
58
|
cannam@160
|
59 RealType location()const
|
cannam@160
|
60 {
|
cannam@160
|
61 return m_location;
|
cannam@160
|
62 }
|
cannam@160
|
63
|
cannam@160
|
64 RealType scale()const
|
cannam@160
|
65 {
|
cannam@160
|
66 return m_scale;
|
cannam@160
|
67 }
|
cannam@160
|
68 private:
|
cannam@160
|
69 //
|
cannam@160
|
70 // Data members:
|
cannam@160
|
71 //
|
cannam@160
|
72 RealType m_location; // distribution location.
|
cannam@160
|
73 RealType m_scale; // distribution scale.
|
cannam@160
|
74 };
|
cannam@160
|
75
|
cannam@160
|
76 typedef lognormal_distribution<double> lognormal;
|
cannam@160
|
77
|
cannam@160
|
78 template <class RealType, class Policy>
|
cannam@160
|
79 inline const std::pair<RealType, RealType> range(const lognormal_distribution<RealType, Policy>& /*dist*/)
|
cannam@160
|
80 { // Range of permissible values for random variable x is >0 to +infinity.
|
cannam@160
|
81 using boost::math::tools::max_value;
|
cannam@160
|
82 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
|
cannam@160
|
83 }
|
cannam@160
|
84
|
cannam@160
|
85 template <class RealType, class Policy>
|
cannam@160
|
86 inline const std::pair<RealType, RealType> support(const lognormal_distribution<RealType, Policy>& /*dist*/)
|
cannam@160
|
87 { // Range of supported values for random variable x.
|
cannam@160
|
88 // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
|
cannam@160
|
89 using boost::math::tools::max_value;
|
cannam@160
|
90 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
|
cannam@160
|
91 }
|
cannam@160
|
92
|
cannam@160
|
93 template <class RealType, class Policy>
|
cannam@160
|
94 RealType pdf(const lognormal_distribution<RealType, Policy>& dist, const RealType& x)
|
cannam@160
|
95 {
|
cannam@160
|
96 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
97
|
cannam@160
|
98 RealType mu = dist.location();
|
cannam@160
|
99 RealType sigma = dist.scale();
|
cannam@160
|
100
|
cannam@160
|
101 static const char* function = "boost::math::pdf(const lognormal_distribution<%1%>&, %1%)";
|
cannam@160
|
102
|
cannam@160
|
103 RealType result = 0;
|
cannam@160
|
104 if(0 == detail::check_scale(function, sigma, &result, Policy()))
|
cannam@160
|
105 return result;
|
cannam@160
|
106 if(0 == detail::check_location(function, mu, &result, Policy()))
|
cannam@160
|
107 return result;
|
cannam@160
|
108 if(0 == detail::check_lognormal_x(function, x, &result, Policy()))
|
cannam@160
|
109 return result;
|
cannam@160
|
110
|
cannam@160
|
111 if(x == 0)
|
cannam@160
|
112 return 0;
|
cannam@160
|
113
|
cannam@160
|
114 RealType exponent = log(x) - mu;
|
cannam@160
|
115 exponent *= -exponent;
|
cannam@160
|
116 exponent /= 2 * sigma * sigma;
|
cannam@160
|
117
|
cannam@160
|
118 result = exp(exponent);
|
cannam@160
|
119 result /= sigma * sqrt(2 * constants::pi<RealType>()) * x;
|
cannam@160
|
120
|
cannam@160
|
121 return result;
|
cannam@160
|
122 }
|
cannam@160
|
123
|
cannam@160
|
124 template <class RealType, class Policy>
|
cannam@160
|
125 inline RealType cdf(const lognormal_distribution<RealType, Policy>& dist, const RealType& x)
|
cannam@160
|
126 {
|
cannam@160
|
127 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
128
|
cannam@160
|
129 static const char* function = "boost::math::cdf(const lognormal_distribution<%1%>&, %1%)";
|
cannam@160
|
130
|
cannam@160
|
131 RealType result = 0;
|
cannam@160
|
132 if(0 == detail::check_scale(function, dist.scale(), &result, Policy()))
|
cannam@160
|
133 return result;
|
cannam@160
|
134 if(0 == detail::check_location(function, dist.location(), &result, Policy()))
|
cannam@160
|
135 return result;
|
cannam@160
|
136 if(0 == detail::check_lognormal_x(function, x, &result, Policy()))
|
cannam@160
|
137 return result;
|
cannam@160
|
138
|
cannam@160
|
139 if(x == 0)
|
cannam@160
|
140 return 0;
|
cannam@160
|
141
|
cannam@160
|
142 normal_distribution<RealType, Policy> norm(dist.location(), dist.scale());
|
cannam@160
|
143 return cdf(norm, log(x));
|
cannam@160
|
144 }
|
cannam@160
|
145
|
cannam@160
|
146 template <class RealType, class Policy>
|
cannam@160
|
147 inline RealType quantile(const lognormal_distribution<RealType, Policy>& dist, const RealType& p)
|
cannam@160
|
148 {
|
cannam@160
|
149 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
150
|
cannam@160
|
151 static const char* function = "boost::math::quantile(const lognormal_distribution<%1%>&, %1%)";
|
cannam@160
|
152
|
cannam@160
|
153 RealType result = 0;
|
cannam@160
|
154 if(0 == detail::check_scale(function, dist.scale(), &result, Policy()))
|
cannam@160
|
155 return result;
|
cannam@160
|
156 if(0 == detail::check_location(function, dist.location(), &result, Policy()))
|
cannam@160
|
157 return result;
|
cannam@160
|
158 if(0 == detail::check_probability(function, p, &result, Policy()))
|
cannam@160
|
159 return result;
|
cannam@160
|
160
|
cannam@160
|
161 if(p == 0)
|
cannam@160
|
162 return 0;
|
cannam@160
|
163 if(p == 1)
|
cannam@160
|
164 return policies::raise_overflow_error<RealType>(function, 0, Policy());
|
cannam@160
|
165
|
cannam@160
|
166 normal_distribution<RealType, Policy> norm(dist.location(), dist.scale());
|
cannam@160
|
167 return exp(quantile(norm, p));
|
cannam@160
|
168 }
|
cannam@160
|
169
|
cannam@160
|
170 template <class RealType, class Policy>
|
cannam@160
|
171 inline RealType cdf(const complemented2_type<lognormal_distribution<RealType, Policy>, RealType>& c)
|
cannam@160
|
172 {
|
cannam@160
|
173 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
174
|
cannam@160
|
175 static const char* function = "boost::math::cdf(const lognormal_distribution<%1%>&, %1%)";
|
cannam@160
|
176
|
cannam@160
|
177 RealType result = 0;
|
cannam@160
|
178 if(0 == detail::check_scale(function, c.dist.scale(), &result, Policy()))
|
cannam@160
|
179 return result;
|
cannam@160
|
180 if(0 == detail::check_location(function, c.dist.location(), &result, Policy()))
|
cannam@160
|
181 return result;
|
cannam@160
|
182 if(0 == detail::check_lognormal_x(function, c.param, &result, Policy()))
|
cannam@160
|
183 return result;
|
cannam@160
|
184
|
cannam@160
|
185 if(c.param == 0)
|
cannam@160
|
186 return 1;
|
cannam@160
|
187
|
cannam@160
|
188 normal_distribution<RealType, Policy> norm(c.dist.location(), c.dist.scale());
|
cannam@160
|
189 return cdf(complement(norm, log(c.param)));
|
cannam@160
|
190 }
|
cannam@160
|
191
|
cannam@160
|
192 template <class RealType, class Policy>
|
cannam@160
|
193 inline RealType quantile(const complemented2_type<lognormal_distribution<RealType, Policy>, RealType>& c)
|
cannam@160
|
194 {
|
cannam@160
|
195 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
196
|
cannam@160
|
197 static const char* function = "boost::math::quantile(const lognormal_distribution<%1%>&, %1%)";
|
cannam@160
|
198
|
cannam@160
|
199 RealType result = 0;
|
cannam@160
|
200 if(0 == detail::check_scale(function, c.dist.scale(), &result, Policy()))
|
cannam@160
|
201 return result;
|
cannam@160
|
202 if(0 == detail::check_location(function, c.dist.location(), &result, Policy()))
|
cannam@160
|
203 return result;
|
cannam@160
|
204 if(0 == detail::check_probability(function, c.param, &result, Policy()))
|
cannam@160
|
205 return result;
|
cannam@160
|
206
|
cannam@160
|
207 if(c.param == 1)
|
cannam@160
|
208 return 0;
|
cannam@160
|
209 if(c.param == 0)
|
cannam@160
|
210 return policies::raise_overflow_error<RealType>(function, 0, Policy());
|
cannam@160
|
211
|
cannam@160
|
212 normal_distribution<RealType, Policy> norm(c.dist.location(), c.dist.scale());
|
cannam@160
|
213 return exp(quantile(complement(norm, c.param)));
|
cannam@160
|
214 }
|
cannam@160
|
215
|
cannam@160
|
216 template <class RealType, class Policy>
|
cannam@160
|
217 inline RealType mean(const lognormal_distribution<RealType, Policy>& dist)
|
cannam@160
|
218 {
|
cannam@160
|
219 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
220
|
cannam@160
|
221 RealType mu = dist.location();
|
cannam@160
|
222 RealType sigma = dist.scale();
|
cannam@160
|
223
|
cannam@160
|
224 RealType result = 0;
|
cannam@160
|
225 if(0 == detail::check_scale("boost::math::mean(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
|
cannam@160
|
226 return result;
|
cannam@160
|
227 if(0 == detail::check_location("boost::math::mean(const lognormal_distribution<%1%>&)", mu, &result, Policy()))
|
cannam@160
|
228 return result;
|
cannam@160
|
229
|
cannam@160
|
230 return exp(mu + sigma * sigma / 2);
|
cannam@160
|
231 }
|
cannam@160
|
232
|
cannam@160
|
233 template <class RealType, class Policy>
|
cannam@160
|
234 inline RealType variance(const lognormal_distribution<RealType, Policy>& dist)
|
cannam@160
|
235 {
|
cannam@160
|
236 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
237
|
cannam@160
|
238 RealType mu = dist.location();
|
cannam@160
|
239 RealType sigma = dist.scale();
|
cannam@160
|
240
|
cannam@160
|
241 RealType result = 0;
|
cannam@160
|
242 if(0 == detail::check_scale("boost::math::variance(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
|
cannam@160
|
243 return result;
|
cannam@160
|
244 if(0 == detail::check_location("boost::math::variance(const lognormal_distribution<%1%>&)", mu, &result, Policy()))
|
cannam@160
|
245 return result;
|
cannam@160
|
246
|
cannam@160
|
247 return boost::math::expm1(sigma * sigma, Policy()) * exp(2 * mu + sigma * sigma);
|
cannam@160
|
248 }
|
cannam@160
|
249
|
cannam@160
|
250 template <class RealType, class Policy>
|
cannam@160
|
251 inline RealType mode(const lognormal_distribution<RealType, Policy>& dist)
|
cannam@160
|
252 {
|
cannam@160
|
253 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
254
|
cannam@160
|
255 RealType mu = dist.location();
|
cannam@160
|
256 RealType sigma = dist.scale();
|
cannam@160
|
257
|
cannam@160
|
258 RealType result = 0;
|
cannam@160
|
259 if(0 == detail::check_scale("boost::math::mode(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
|
cannam@160
|
260 return result;
|
cannam@160
|
261 if(0 == detail::check_location("boost::math::mode(const lognormal_distribution<%1%>&)", mu, &result, Policy()))
|
cannam@160
|
262 return result;
|
cannam@160
|
263
|
cannam@160
|
264 return exp(mu - sigma * sigma);
|
cannam@160
|
265 }
|
cannam@160
|
266
|
cannam@160
|
267 template <class RealType, class Policy>
|
cannam@160
|
268 inline RealType median(const lognormal_distribution<RealType, Policy>& dist)
|
cannam@160
|
269 {
|
cannam@160
|
270 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
271 RealType mu = dist.location();
|
cannam@160
|
272 return exp(mu); // e^mu
|
cannam@160
|
273 }
|
cannam@160
|
274
|
cannam@160
|
275 template <class RealType, class Policy>
|
cannam@160
|
276 inline RealType skewness(const lognormal_distribution<RealType, Policy>& dist)
|
cannam@160
|
277 {
|
cannam@160
|
278 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
279
|
cannam@160
|
280 //RealType mu = dist.location();
|
cannam@160
|
281 RealType sigma = dist.scale();
|
cannam@160
|
282
|
cannam@160
|
283 RealType ss = sigma * sigma;
|
cannam@160
|
284 RealType ess = exp(ss);
|
cannam@160
|
285
|
cannam@160
|
286 RealType result = 0;
|
cannam@160
|
287 if(0 == detail::check_scale("boost::math::skewness(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
|
cannam@160
|
288 return result;
|
cannam@160
|
289 if(0 == detail::check_location("boost::math::skewness(const lognormal_distribution<%1%>&)", dist.location(), &result, Policy()))
|
cannam@160
|
290 return result;
|
cannam@160
|
291
|
cannam@160
|
292 return (ess + 2) * sqrt(boost::math::expm1(ss, Policy()));
|
cannam@160
|
293 }
|
cannam@160
|
294
|
cannam@160
|
295 template <class RealType, class Policy>
|
cannam@160
|
296 inline RealType kurtosis(const lognormal_distribution<RealType, Policy>& dist)
|
cannam@160
|
297 {
|
cannam@160
|
298 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
299
|
cannam@160
|
300 //RealType mu = dist.location();
|
cannam@160
|
301 RealType sigma = dist.scale();
|
cannam@160
|
302 RealType ss = sigma * sigma;
|
cannam@160
|
303
|
cannam@160
|
304 RealType result = 0;
|
cannam@160
|
305 if(0 == detail::check_scale("boost::math::kurtosis(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
|
cannam@160
|
306 return result;
|
cannam@160
|
307 if(0 == detail::check_location("boost::math::kurtosis(const lognormal_distribution<%1%>&)", dist.location(), &result, Policy()))
|
cannam@160
|
308 return result;
|
cannam@160
|
309
|
cannam@160
|
310 return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 3;
|
cannam@160
|
311 }
|
cannam@160
|
312
|
cannam@160
|
313 template <class RealType, class Policy>
|
cannam@160
|
314 inline RealType kurtosis_excess(const lognormal_distribution<RealType, Policy>& dist)
|
cannam@160
|
315 {
|
cannam@160
|
316 BOOST_MATH_STD_USING // for ADL of std functions
|
cannam@160
|
317
|
cannam@160
|
318 // RealType mu = dist.location();
|
cannam@160
|
319 RealType sigma = dist.scale();
|
cannam@160
|
320 RealType ss = sigma * sigma;
|
cannam@160
|
321
|
cannam@160
|
322 RealType result = 0;
|
cannam@160
|
323 if(0 == detail::check_scale("boost::math::kurtosis_excess(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
|
cannam@160
|
324 return result;
|
cannam@160
|
325 if(0 == detail::check_location("boost::math::kurtosis_excess(const lognormal_distribution<%1%>&)", dist.location(), &result, Policy()))
|
cannam@160
|
326 return result;
|
cannam@160
|
327
|
cannam@160
|
328 return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 6;
|
cannam@160
|
329 }
|
cannam@160
|
330
|
cannam@160
|
331 } // namespace math
|
cannam@160
|
332 } // namespace boost
|
cannam@160
|
333
|
cannam@160
|
334 // This include must be at the end, *after* the accessors
|
cannam@160
|
335 // for this distribution have been defined, in order to
|
cannam@160
|
336 // keep compilers that support two-phase lookup happy.
|
cannam@160
|
337 #include <boost/math/distributions/detail/derived_accessors.hpp>
|
cannam@160
|
338
|
cannam@160
|
339 #endif // BOOST_STATS_STUDENTS_T_HPP
|
cannam@160
|
340
|
cannam@160
|
341
|