File indexing completed on 2025-01-18 09:39:42
0001
0002
0003
0004
0005
0006 #ifndef BOOST_STATS_LOGNORMAL_HPP
0007 #define BOOST_STATS_LOGNORMAL_HPP
0008
0009
0010
0011
0012
0013 #include <boost/math/distributions/fwd.hpp>
0014 #include <boost/math/distributions/normal.hpp>
0015 #include <boost/math/special_functions/expm1.hpp>
0016 #include <boost/math/distributions/detail/common_error_handling.hpp>
0017
0018 #include <utility>
0019
0020 namespace boost{ namespace math
0021 {
0022 namespace detail
0023 {
0024
0025 template <class RealType, class Policy>
0026 inline bool check_lognormal_x(
0027 const char* function,
0028 RealType const& x,
0029 RealType* result, const Policy& pol)
0030 {
0031 if((x < 0) || !(boost::math::isfinite)(x))
0032 {
0033 *result = policies::raise_domain_error<RealType>(
0034 function,
0035 "Random variate is %1% but must be >= 0 !", x, pol);
0036 return false;
0037 }
0038 return true;
0039 }
0040
0041 }
0042
0043
0044 template <class RealType = double, class Policy = policies::policy<> >
0045 class lognormal_distribution
0046 {
0047 public:
0048 typedef RealType value_type;
0049 typedef Policy policy_type;
0050
0051 lognormal_distribution(RealType l_location = 0, RealType l_scale = 1)
0052 : m_location(l_location), m_scale(l_scale)
0053 {
0054 RealType result;
0055 detail::check_scale("boost::math::lognormal_distribution<%1%>::lognormal_distribution", l_scale, &result, Policy());
0056 detail::check_location("boost::math::lognormal_distribution<%1%>::lognormal_distribution", l_location, &result, Policy());
0057 }
0058
0059 RealType location()const
0060 {
0061 return m_location;
0062 }
0063
0064 RealType scale()const
0065 {
0066 return m_scale;
0067 }
0068 private:
0069
0070
0071
0072 RealType m_location;
0073 RealType m_scale;
0074 };
0075
0076 typedef lognormal_distribution<double> lognormal;
0077
0078 #ifdef __cpp_deduction_guides
0079 template <class RealType>
0080 lognormal_distribution(RealType)->lognormal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0081 template <class RealType>
0082 lognormal_distribution(RealType,RealType)->lognormal_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0083 #endif
0084
0085 template <class RealType, class Policy>
0086 inline const std::pair<RealType, RealType> range(const lognormal_distribution<RealType, Policy>& )
0087 {
0088 using boost::math::tools::max_value;
0089 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0090 }
0091
0092 template <class RealType, class Policy>
0093 inline const std::pair<RealType, RealType> support(const lognormal_distribution<RealType, Policy>& )
0094 {
0095
0096 using boost::math::tools::max_value;
0097 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0098 }
0099
0100 template <class RealType, class Policy>
0101 RealType pdf(const lognormal_distribution<RealType, Policy>& dist, const RealType& x)
0102 {
0103 BOOST_MATH_STD_USING
0104
0105 RealType mu = dist.location();
0106 RealType sigma = dist.scale();
0107
0108 static const char* function = "boost::math::pdf(const lognormal_distribution<%1%>&, %1%)";
0109
0110 RealType result = 0;
0111 if(0 == detail::check_scale(function, sigma, &result, Policy()))
0112 return result;
0113 if(0 == detail::check_location(function, mu, &result, Policy()))
0114 return result;
0115 if(0 == detail::check_lognormal_x(function, x, &result, Policy()))
0116 return result;
0117
0118 if(x == 0)
0119 return 0;
0120
0121 RealType exponent = log(x) - mu;
0122 exponent *= -exponent;
0123 exponent /= 2 * sigma * sigma;
0124
0125 result = exp(exponent);
0126 result /= sigma * sqrt(2 * constants::pi<RealType>()) * x;
0127
0128 return result;
0129 }
0130
0131 template <class RealType, class Policy>
0132 inline RealType cdf(const lognormal_distribution<RealType, Policy>& dist, const RealType& x)
0133 {
0134 BOOST_MATH_STD_USING
0135
0136 static const char* function = "boost::math::cdf(const lognormal_distribution<%1%>&, %1%)";
0137
0138 RealType result = 0;
0139 if(0 == detail::check_scale(function, dist.scale(), &result, Policy()))
0140 return result;
0141 if(0 == detail::check_location(function, dist.location(), &result, Policy()))
0142 return result;
0143 if(0 == detail::check_lognormal_x(function, x, &result, Policy()))
0144 return result;
0145
0146 if(x == 0)
0147 return 0;
0148
0149 normal_distribution<RealType, Policy> norm(dist.location(), dist.scale());
0150 return cdf(norm, log(x));
0151 }
0152
0153 template <class RealType, class Policy>
0154 inline RealType quantile(const lognormal_distribution<RealType, Policy>& dist, const RealType& p)
0155 {
0156 BOOST_MATH_STD_USING
0157
0158 static const char* function = "boost::math::quantile(const lognormal_distribution<%1%>&, %1%)";
0159
0160 RealType result = 0;
0161 if(0 == detail::check_scale(function, dist.scale(), &result, Policy()))
0162 return result;
0163 if(0 == detail::check_location(function, dist.location(), &result, Policy()))
0164 return result;
0165 if(0 == detail::check_probability(function, p, &result, Policy()))
0166 return result;
0167
0168 if(p == 0)
0169 return 0;
0170 if(p == 1)
0171 return policies::raise_overflow_error<RealType>(function, 0, Policy());
0172
0173 normal_distribution<RealType, Policy> norm(dist.location(), dist.scale());
0174 return exp(quantile(norm, p));
0175 }
0176
0177 template <class RealType, class Policy>
0178 inline RealType cdf(const complemented2_type<lognormal_distribution<RealType, Policy>, RealType>& c)
0179 {
0180 BOOST_MATH_STD_USING
0181
0182 static const char* function = "boost::math::cdf(const lognormal_distribution<%1%>&, %1%)";
0183
0184 RealType result = 0;
0185 if(0 == detail::check_scale(function, c.dist.scale(), &result, Policy()))
0186 return result;
0187 if(0 == detail::check_location(function, c.dist.location(), &result, Policy()))
0188 return result;
0189 if(0 == detail::check_lognormal_x(function, c.param, &result, Policy()))
0190 return result;
0191
0192 if(c.param == 0)
0193 return 1;
0194
0195 normal_distribution<RealType, Policy> norm(c.dist.location(), c.dist.scale());
0196 return cdf(complement(norm, log(c.param)));
0197 }
0198
0199 template <class RealType, class Policy>
0200 inline RealType quantile(const complemented2_type<lognormal_distribution<RealType, Policy>, RealType>& c)
0201 {
0202 BOOST_MATH_STD_USING
0203
0204 static const char* function = "boost::math::quantile(const lognormal_distribution<%1%>&, %1%)";
0205
0206 RealType result = 0;
0207 if(0 == detail::check_scale(function, c.dist.scale(), &result, Policy()))
0208 return result;
0209 if(0 == detail::check_location(function, c.dist.location(), &result, Policy()))
0210 return result;
0211 if(0 == detail::check_probability(function, c.param, &result, Policy()))
0212 return result;
0213
0214 if(c.param == 1)
0215 return 0;
0216 if(c.param == 0)
0217 return policies::raise_overflow_error<RealType>(function, 0, Policy());
0218
0219 normal_distribution<RealType, Policy> norm(c.dist.location(), c.dist.scale());
0220 return exp(quantile(complement(norm, c.param)));
0221 }
0222
0223 template <class RealType, class Policy>
0224 inline RealType mean(const lognormal_distribution<RealType, Policy>& dist)
0225 {
0226 BOOST_MATH_STD_USING
0227
0228 RealType mu = dist.location();
0229 RealType sigma = dist.scale();
0230
0231 RealType result = 0;
0232 if(0 == detail::check_scale("boost::math::mean(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
0233 return result;
0234 if(0 == detail::check_location("boost::math::mean(const lognormal_distribution<%1%>&)", mu, &result, Policy()))
0235 return result;
0236
0237 return exp(mu + sigma * sigma / 2);
0238 }
0239
0240 template <class RealType, class Policy>
0241 inline RealType variance(const lognormal_distribution<RealType, Policy>& dist)
0242 {
0243 BOOST_MATH_STD_USING
0244
0245 RealType mu = dist.location();
0246 RealType sigma = dist.scale();
0247
0248 RealType result = 0;
0249 if(0 == detail::check_scale("boost::math::variance(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
0250 return result;
0251 if(0 == detail::check_location("boost::math::variance(const lognormal_distribution<%1%>&)", mu, &result, Policy()))
0252 return result;
0253
0254 return boost::math::expm1(sigma * sigma, Policy()) * exp(2 * mu + sigma * sigma);
0255 }
0256
0257 template <class RealType, class Policy>
0258 inline RealType mode(const lognormal_distribution<RealType, Policy>& dist)
0259 {
0260 BOOST_MATH_STD_USING
0261
0262 RealType mu = dist.location();
0263 RealType sigma = dist.scale();
0264
0265 RealType result = 0;
0266 if(0 == detail::check_scale("boost::math::mode(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
0267 return result;
0268 if(0 == detail::check_location("boost::math::mode(const lognormal_distribution<%1%>&)", mu, &result, Policy()))
0269 return result;
0270
0271 return exp(mu - sigma * sigma);
0272 }
0273
0274 template <class RealType, class Policy>
0275 inline RealType median(const lognormal_distribution<RealType, Policy>& dist)
0276 {
0277 BOOST_MATH_STD_USING
0278 RealType mu = dist.location();
0279 return exp(mu);
0280 }
0281
0282 template <class RealType, class Policy>
0283 inline RealType skewness(const lognormal_distribution<RealType, Policy>& dist)
0284 {
0285 BOOST_MATH_STD_USING
0286
0287
0288 RealType sigma = dist.scale();
0289
0290 RealType ss = sigma * sigma;
0291 RealType ess = exp(ss);
0292
0293 RealType result = 0;
0294 if(0 == detail::check_scale("boost::math::skewness(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
0295 return result;
0296 if(0 == detail::check_location("boost::math::skewness(const lognormal_distribution<%1%>&)", dist.location(), &result, Policy()))
0297 return result;
0298
0299 return (ess + 2) * sqrt(boost::math::expm1(ss, Policy()));
0300 }
0301
0302 template <class RealType, class Policy>
0303 inline RealType kurtosis(const lognormal_distribution<RealType, Policy>& dist)
0304 {
0305 BOOST_MATH_STD_USING
0306
0307
0308 RealType sigma = dist.scale();
0309 RealType ss = sigma * sigma;
0310
0311 RealType result = 0;
0312 if(0 == detail::check_scale("boost::math::kurtosis(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
0313 return result;
0314 if(0 == detail::check_location("boost::math::kurtosis(const lognormal_distribution<%1%>&)", dist.location(), &result, Policy()))
0315 return result;
0316
0317 return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 3;
0318 }
0319
0320 template <class RealType, class Policy>
0321 inline RealType kurtosis_excess(const lognormal_distribution<RealType, Policy>& dist)
0322 {
0323 BOOST_MATH_STD_USING
0324
0325
0326 RealType sigma = dist.scale();
0327 RealType ss = sigma * sigma;
0328
0329 RealType result = 0;
0330 if(0 == detail::check_scale("boost::math::kurtosis_excess(const lognormal_distribution<%1%>&)", sigma, &result, Policy()))
0331 return result;
0332 if(0 == detail::check_location("boost::math::kurtosis_excess(const lognormal_distribution<%1%>&)", dist.location(), &result, Policy()))
0333 return result;
0334
0335 return exp(4 * ss) + 2 * exp(3 * ss) + 3 * exp(2 * ss) - 6;
0336 }
0337
0338 template <class RealType, class Policy>
0339 inline RealType entropy(const lognormal_distribution<RealType, Policy>& dist)
0340 {
0341 using std::log;
0342 RealType mu = dist.location();
0343 RealType sigma = dist.scale();
0344 return mu + log(constants::two_pi<RealType>()*constants::e<RealType>()*sigma*sigma)/2;
0345 }
0346
0347 }
0348 }
0349
0350
0351
0352
0353 #include <boost/math/distributions/detail/derived_accessors.hpp>
0354
0355 #endif
0356
0357