Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:35:29

0001 //  Copyright Thijs van den Berg, 2008.
0002 //  Copyright John Maddock 2008.
0003 //  Copyright Paul A. Bristow 2008, 2014.
0004 //  Copyright Matt Borland 2024.
0005 
0006 //  Use, modification and distribution are subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying file
0008 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 // This module implements the Laplace distribution.
0011 // Weisstein, Eric W. "Laplace Distribution." From MathWorld--A Wolfram Web Resource.
0012 // http://mathworld.wolfram.com/LaplaceDistribution.html
0013 // http://en.wikipedia.org/wiki/Laplace_distribution
0014 //
0015 // Abramowitz and Stegun 1972, p 930
0016 // http://www.math.sfu.ca/~cbm/aands/page_930.htm
0017 
0018 #ifndef BOOST_STATS_LAPLACE_HPP
0019 #define BOOST_STATS_LAPLACE_HPP
0020 
0021 #include <boost/math/tools/config.hpp>
0022 #include <boost/math/tools/numeric_limits.hpp>
0023 #include <boost/math/tools/tuple.hpp>
0024 #include <boost/math/special_functions/log1p.hpp>
0025 #include <boost/math/distributions/detail/common_error_handling.hpp>
0026 #include <boost/math/distributions/complement.hpp>
0027 #include <boost/math/constants/constants.hpp>
0028 #include <boost/math/policies/policy.hpp>
0029 #include <boost/math/policies/error_handling.hpp>
0030 
0031 namespace boost{ namespace math{
0032 
0033 #ifdef _MSC_VER
0034 #  pragma warning(push)
0035 #  pragma warning(disable:4127) // conditional expression is constant
0036 #endif
0037 
0038 template <class RealType = double, class Policy = policies::policy<> >
0039 class laplace_distribution
0040 {
0041 public:
0042    // ----------------------------------
0043    // public Types
0044    // ----------------------------------
0045    using value_type = RealType;
0046    using policy_type = Policy;
0047 
0048    // ----------------------------------
0049    // Constructor(s)
0050    // ----------------------------------
0051    BOOST_MATH_GPU_ENABLED explicit laplace_distribution(RealType l_location = 0, RealType l_scale = 1)
0052       : m_location(l_location), m_scale(l_scale)
0053    {
0054       RealType result;
0055       check_parameters("boost::math::laplace_distribution<%1%>::laplace_distribution()", &result);
0056    }
0057 
0058 
0059    // ----------------------------------
0060    // Public functions
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 
0073    BOOST_MATH_GPU_ENABLED bool check_parameters(const char* function, RealType* result) const
0074    {
0075          if(false == detail::check_scale(function, m_scale, result, Policy())) return false;
0076          if(false == detail::check_location(function, m_location, result, Policy())) return false;
0077          return true;
0078    }
0079 
0080 private:
0081    RealType m_location;
0082    RealType m_scale;
0083 }; // class laplace_distribution
0084 
0085 //
0086 // Convenient type synonym for double.
0087 using laplace = laplace_distribution<double>;
0088 
0089 #ifdef __cpp_deduction_guides
0090 template <class RealType>
0091 laplace_distribution(RealType)->laplace_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0092 template <class RealType>
0093 laplace_distribution(RealType,RealType)->laplace_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0094 #endif
0095 
0096 //
0097 // Non-member functions.
0098 template <class RealType, class Policy>
0099 BOOST_MATH_GPU_ENABLED inline boost::math::pair<RealType, RealType> range(const laplace_distribution<RealType, Policy>&)
0100 {
0101   BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits<RealType>::has_infinity)
0102   {  // Can use infinity.
0103      return boost::math::pair<RealType, RealType>(-boost::math::numeric_limits<RealType>::infinity(), boost::math::numeric_limits<RealType>::infinity()); // - to + infinity.
0104   }
0105   else
0106   { // Can only use max_value.
0107     using boost::math::tools::max_value;
0108     return boost::math::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
0109   }
0110 
0111 }
0112 
0113 template <class RealType, class Policy>
0114 BOOST_MATH_GPU_ENABLED inline boost::math::pair<RealType, RealType> support(const laplace_distribution<RealType, Policy>&)
0115 {
0116   BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits<RealType>::has_infinity)
0117   { // Can Use infinity.
0118      return boost::math::pair<RealType, RealType>(-boost::math::numeric_limits<RealType>::infinity(), boost::math::numeric_limits<RealType>::infinity()); // - to + infinity.
0119   }
0120   else
0121   { // Can only use max_value.
0122     using boost::math::tools::max_value;
0123     return boost::math::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.
0124   }
0125 }
0126 
0127 template <class RealType, class Policy>
0128 BOOST_MATH_GPU_ENABLED inline RealType pdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
0129 {
0130    BOOST_MATH_STD_USING // for ADL of std functions
0131 
0132    // Checking function argument
0133    RealType result = 0;
0134    constexpr auto function = "boost::math::pdf(const laplace_distribution<%1%>&, %1%))";
0135 
0136    // Check scale and location.
0137    if (false == dist.check_parameters(function, &result)) return result;
0138    // Special pdf values.
0139    if((boost::math::isinf)(x))
0140    {
0141       return 0; // pdf + and - infinity is zero.
0142    }
0143    if (false == detail::check_x(function, x, &result, Policy())) return result;
0144 
0145    // General case
0146    RealType scale( dist.scale() );
0147    RealType location( dist.location() );
0148 
0149    RealType exponent = x - location;
0150    if (exponent>0) exponent = -exponent;
0151    exponent /= scale;
0152 
0153    result = exp(exponent);
0154    result /= 2 * scale;
0155 
0156    return result;
0157 } // pdf
0158 
0159 template <class RealType, class Policy>
0160 BOOST_MATH_GPU_ENABLED inline RealType logpdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
0161 {
0162    BOOST_MATH_STD_USING // for ADL of std functions
0163 
0164    // Checking function argument
0165    RealType result = -boost::math::numeric_limits<RealType>::infinity();
0166    constexpr auto function = "boost::math::logpdf(const laplace_distribution<%1%>&, %1%))";
0167 
0168    // Check scale and location.
0169    if (false == dist.check_parameters(function, &result))
0170    {
0171        return result;
0172    }
0173    // Special pdf values.
0174    if((boost::math::isinf)(x))
0175    {
0176       return result; // pdf + and - infinity is zero so logpdf is -INF
0177    }
0178    if (false == detail::check_x(function, x, &result, Policy()))
0179    {
0180        return result;
0181    }
0182 
0183    const RealType mu = dist.scale();
0184    const RealType b = dist.location();
0185 
0186    // if b is 0 avoid divide by 0 error
0187    if(abs(b) < boost::math::numeric_limits<RealType>::epsilon())
0188    {
0189       result = log(pdf(dist, x));
0190    }
0191    else
0192    {
0193       // General case
0194       const RealType log2 = boost::math::constants::ln_two<RealType>();
0195       result = -abs(x-mu)/b - log(b) - log2;
0196    }
0197 
0198    return result;
0199 } // logpdf
0200 
0201 template <class RealType, class Policy>
0202 BOOST_MATH_GPU_ENABLED inline RealType cdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
0203 {
0204    BOOST_MATH_STD_USING  // For ADL of std functions.
0205 
0206    RealType result = 0;
0207    // Checking function argument.
0208    constexpr auto function = "boost::math::cdf(const laplace_distribution<%1%>&, %1%)";
0209    // Check scale and location.
0210    if (false == dist.check_parameters(function, &result)) return result;
0211 
0212    // Special cdf values:
0213    if((boost::math::isinf)(x))
0214    {
0215      if(x < 0) return 0; // -infinity.
0216      return 1; // + infinity.
0217    }
0218    if (false == detail::check_x(function, x, &result, Policy())) return result;
0219 
0220    // General cdf  values
0221    RealType scale( dist.scale() );
0222    RealType location( dist.location() );
0223 
0224    if (x < location)
0225    {
0226       result = exp( (x-location)/scale )/2;
0227    }
0228    else
0229    {
0230       result = 1 - exp( (location-x)/scale )/2;
0231    }
0232    return result;
0233 } // cdf
0234 
0235 template <class RealType, class Policy>
0236 BOOST_MATH_GPU_ENABLED inline RealType logcdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)
0237 {
0238    BOOST_MATH_STD_USING  // For ADL of std functions.
0239 
0240    RealType result = 0;
0241    // Checking function argument.
0242    constexpr auto function = "boost::math::logcdf(const laplace_distribution<%1%>&, %1%)";
0243    // Check scale and location.
0244    if (false == dist.check_parameters(function, &result)) 
0245    {
0246       return result;
0247    }
0248 
0249    // Special cdf values:
0250    if((boost::math::isinf)(x))
0251    {
0252       if(x < 0) 
0253       {
0254          return 0; // -infinity.
0255       }
0256       return 1; // + infinity.
0257    }
0258 
0259    if (false == detail::check_x(function, x, &result, Policy())) 
0260    {
0261       return result;
0262    }
0263 
0264    // General cdf  values
0265    RealType scale( dist.scale() );
0266    RealType location( dist.location() );
0267 
0268    if (x < location)
0269    {
0270       result = ((x - location) / scale) - boost::math::constants::ln_two<RealType>();
0271    }
0272    else
0273    {
0274       result = log1p(-exp((location - x) / scale) / 2);
0275    }
0276 
0277    return result;
0278 } // logcdf
0279 
0280 template <class RealType, class Policy>
0281 BOOST_MATH_GPU_ENABLED inline RealType quantile(const laplace_distribution<RealType, Policy>& dist, const RealType& p)
0282 {
0283    BOOST_MATH_STD_USING // for ADL of std functions.
0284 
0285    // Checking function argument
0286    RealType result = 0;
0287    constexpr auto function = "boost::math::quantile(const laplace_distribution<%1%>&, %1%)";
0288    if (false == dist.check_parameters(function, &result)) return result;
0289    if(false == detail::check_probability(function, p, &result, Policy())) return result;
0290 
0291    // Extreme values of p:
0292    if(p == 0)
0293    {
0294       result = policies::raise_overflow_error<RealType>(function,
0295         "probability parameter is 0, but must be > 0!", Policy());
0296       return -result; // -inf
0297    }
0298   
0299    if(p == 1)
0300    {
0301       result = policies::raise_overflow_error<RealType>(function,
0302         "probability parameter is 1, but must be < 1!", Policy());
0303       return result; // inf
0304    }
0305    // Calculate Quantile
0306    RealType scale( dist.scale() );
0307    RealType location( dist.location() );
0308 
0309    if (p - 0.5 < 0.0)
0310       result = location + scale*log( static_cast<RealType>(p*2) );
0311    else
0312       result = location - scale*log( static_cast<RealType>(-p*2 + 2) );
0313 
0314    return result;
0315 } // quantile
0316 
0317 
0318 template <class RealType, class Policy>
0319 BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
0320 {
0321    // Calculate complement of cdf.
0322    BOOST_MATH_STD_USING // for ADL of std functions
0323 
0324    RealType scale = c.dist.scale();
0325    RealType location = c.dist.location();
0326    RealType x = c.param;
0327    RealType result = 0;
0328 
0329    // Checking function argument.
0330    constexpr auto function = "boost::math::cdf(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
0331 
0332    // Check scale and location.
0333     if (false == c.dist.check_parameters(function, &result)) return result;
0334 
0335    // Special cdf values.
0336    if((boost::math::isinf)(x))
0337    {
0338      if(x < 0) return 1; // cdf complement -infinity is unity.
0339      return 0; // cdf complement +infinity is zero.
0340    }
0341    if(false == detail::check_x(function, x, &result, Policy()))return result;
0342 
0343    // Cdf interval value.
0344    if (-x < -location)
0345    {
0346       result = exp( (-x+location)/scale )/2;
0347    }
0348    else
0349    {
0350       result = 1 - exp( (-location+x)/scale )/2;
0351    }
0352    return result;
0353 } // cdf complement
0354 
0355 template <class RealType, class Policy>
0356 BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
0357 {
0358    // Calculate complement of logcdf.
0359    BOOST_MATH_STD_USING // for ADL of std functions
0360 
0361    RealType scale = c.dist.scale();
0362    RealType location = c.dist.location();
0363    RealType x = c.param;
0364    RealType result = 0;
0365 
0366    // Checking function argument.
0367    constexpr auto function = "boost::math::logcdf(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
0368 
0369    // Check scale and location.
0370     if (false == c.dist.check_parameters(function, &result)) return result;
0371 
0372    // Special cdf values.
0373    if((boost::math::isinf)(x))
0374    {
0375      if(x < 0) 
0376      { 
0377        return 1; // cdf complement -infinity is unity.
0378      }
0379 
0380      return 0; // cdf complement +infinity is zero.
0381    }
0382    if(false == detail::check_x(function, x, &result, Policy()))return result;
0383 
0384    // Cdf interval value.
0385    if (-x < -location)
0386    {
0387       result = (-x+location)/scale - boost::math::constants::ln_two<RealType>();
0388    }
0389    else
0390    {
0391       result = log1p(-exp( (-location+x)/scale )/2, Policy());
0392    }
0393    return result;
0394 } // cdf complement
0395 
0396 template <class RealType, class Policy>
0397 BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)
0398 {
0399    BOOST_MATH_STD_USING // for ADL of std functions.
0400 
0401    // Calculate quantile.
0402    RealType scale = c.dist.scale();
0403    RealType location = c.dist.location();
0404    RealType q = c.param;
0405    RealType result = 0;
0406 
0407    // Checking function argument.
0408    constexpr auto function = "quantile(const complemented2_type<laplace_distribution<%1%>, %1%>&)";
0409    if (false == c.dist.check_parameters(function, &result)) return result;
0410    
0411    // Extreme values.
0412    if(q == 0)
0413    {
0414        return boost::math::numeric_limits<RealType>::infinity();
0415    }
0416    if(q == 1)
0417    {
0418        return -boost::math::numeric_limits<RealType>::infinity();
0419    }
0420    if(false == detail::check_probability(function, q, &result, Policy())) return result;
0421 
0422    if (0.5 - q < 0.0)
0423       result = location + scale*log( static_cast<RealType>(-q*2 + 2) );
0424    else
0425       result = location - scale*log( static_cast<RealType>(q*2) );
0426 
0427 
0428    return result;
0429 } // quantile
0430 
0431 template <class RealType, class Policy>
0432 BOOST_MATH_GPU_ENABLED inline RealType mean(const laplace_distribution<RealType, Policy>& dist)
0433 {
0434    return dist.location();
0435 }
0436 
0437 template <class RealType, class Policy>
0438 BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const laplace_distribution<RealType, Policy>& dist)
0439 {
0440    return constants::root_two<RealType>() * dist.scale();
0441 }
0442 
0443 template <class RealType, class Policy>
0444 BOOST_MATH_GPU_ENABLED inline RealType mode(const laplace_distribution<RealType, Policy>& dist)
0445 {
0446    return dist.location();
0447 }
0448 
0449 template <class RealType, class Policy>
0450 BOOST_MATH_GPU_ENABLED inline RealType median(const laplace_distribution<RealType, Policy>& dist)
0451 {
0452    return dist.location();
0453 }
0454 
0455 template <class RealType, class Policy>
0456 BOOST_MATH_GPU_ENABLED inline RealType skewness(const laplace_distribution<RealType, Policy>& /*dist*/)
0457 {
0458    return 0;
0459 }
0460 
0461 template <class RealType, class Policy>
0462 BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const laplace_distribution<RealType, Policy>& /*dist*/)
0463 {
0464    return 6;
0465 }
0466 
0467 template <class RealType, class Policy>
0468 BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const laplace_distribution<RealType, Policy>& /*dist*/)
0469 {
0470    return 3;
0471 }
0472 
0473 template <class RealType, class Policy>
0474 BOOST_MATH_GPU_ENABLED inline RealType entropy(const laplace_distribution<RealType, Policy> & dist)
0475 {
0476    using std::log;
0477    return log(2*dist.scale()*constants::e<RealType>());
0478 }
0479 
0480 #ifdef _MSC_VER
0481 #  pragma warning(pop)
0482 #endif
0483 
0484 } // namespace math
0485 } // namespace boost
0486 
0487 // This include must be at the end, *after* the accessors
0488 // for this distribution have been defined, in order to
0489 // keep compilers that support two-phase lookup happy.
0490 #include <boost/math/distributions/detail/derived_accessors.hpp>
0491 
0492 #endif // BOOST_STATS_LAPLACE_HPP
0493 
0494