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