Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:48:27

0001 //  Copyright John Maddock 2006.
0002 //  Copyright Matt Borland 2024.
0003 //  Use, modification and distribution are subject to the
0004 //  Boost Software License, Version 1.0. (See accompanying file
0005 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_STATS_LOGNORMAL_HPP
0008 #define BOOST_STATS_LOGNORMAL_HPP
0009 
0010 // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3669.htm
0011 // http://mathworld.wolfram.com/LogNormalDistribution.html
0012 // http://en.wikipedia.org/wiki/Lognormal_distribution
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 } // namespace detail
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    // Data members:
0075    //
0076    RealType m_location;  // distribution location.
0077    RealType m_scale;     // distribution 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>& /*dist*/)
0091 { // Range of permissible values for random variable x is >0 to +infinity.
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>& /*dist*/)
0098 { // Range of supported values for random variable x.
0099    // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
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  // for ADL of std functions
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  // for ADL of std functions
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  // for ADL of std functions
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  // for ADL of std functions
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  // for ADL of std functions
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  // for ADL of std functions
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  // for ADL of std functions
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  // for ADL of std functions
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  // for ADL of std functions
0282    RealType mu = dist.location();
0283    return exp(mu); // e^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  // for ADL of std functions
0290 
0291    //RealType mu = dist.location();
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  // for ADL of std functions
0310 
0311    //RealType mu = dist.location();
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  // for ADL of std functions
0328 
0329    // RealType mu = dist.location();
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 } // namespace math
0352 } // namespace boost
0353 
0354 // This include must be at the end, *after* the accessors
0355 // for this distribution have been defined, in order to
0356 // keep compilers that support two-phase lookup happy.
0357 #include <boost/math/distributions/detail/derived_accessors.hpp>
0358 
0359 #endif // BOOST_STATS_STUDENTS_T_HPP
0360 
0361