brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.6 KiB · 81a0abe Raw
495 lines · plain
1//  Copyright Thijs van den Berg, 2008.2//  Copyright John Maddock 2008.3//  Copyright Paul A. Bristow 2008, 2014.4//  Copyright Matt Borland 2024.5 6//  Use, modification and distribution are subject to the7//  Boost Software License, Version 1.0. (See accompanying file8//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)9 10// This module implements the Laplace distribution.11// Weisstein, Eric W. "Laplace Distribution." From MathWorld--A Wolfram Web Resource.12// http://mathworld.wolfram.com/LaplaceDistribution.html13// http://en.wikipedia.org/wiki/Laplace_distribution14//15// Abramowitz and Stegun 1972, p 93016// http://www.math.sfu.ca/~cbm/aands/page_930.htm17 18#ifndef BOOST_STATS_LAPLACE_HPP19#define BOOST_STATS_LAPLACE_HPP20 21#include <boost/math/tools/config.hpp>22#include <boost/math/tools/numeric_limits.hpp>23#include <boost/math/tools/tuple.hpp>24#include <boost/math/special_functions/log1p.hpp>25#include <boost/math/distributions/detail/common_error_handling.hpp>26#include <boost/math/distributions/complement.hpp>27#include <boost/math/constants/constants.hpp>28#include <boost/math/policies/policy.hpp>29#include <boost/math/policies/error_handling.hpp>30 31namespace boost{ namespace math{32 33#ifdef _MSC_VER34#  pragma warning(push)35#  pragma warning(disable:4127) // conditional expression is constant36#endif37 38template <class RealType = double, class Policy = policies::policy<> >39class laplace_distribution40{41public:42   // ----------------------------------43   // public Types44   // ----------------------------------45   using value_type = RealType;46   using policy_type = Policy;47 48   // ----------------------------------49   // Constructor(s)50   // ----------------------------------51   BOOST_MATH_GPU_ENABLED explicit laplace_distribution(RealType l_location = 0, RealType l_scale = 1)52      : m_location(l_location), m_scale(l_scale)53   {54      RealType result;55      check_parameters("boost::math::laplace_distribution<%1%>::laplace_distribution()", &result);56   }57 58 59   // ----------------------------------60   // Public functions61   // ----------------------------------62 63   BOOST_MATH_GPU_ENABLED RealType location() const64   {65      return m_location;66   }67 68   BOOST_MATH_GPU_ENABLED RealType scale() const69   {70      return m_scale;71   }72 73   BOOST_MATH_GPU_ENABLED bool check_parameters(const char* function, RealType* result) const74   {75         if(false == detail::check_scale(function, m_scale, result, Policy())) return false;76         if(false == detail::check_location(function, m_location, result, Policy())) return false;77         return true;78   }79 80private:81   RealType m_location;82   RealType m_scale;83}; // class laplace_distribution84 85//86// Convenient type synonym for double.87using laplace = laplace_distribution<double>;88 89#ifdef __cpp_deduction_guides90template <class RealType>91laplace_distribution(RealType)->laplace_distribution<typename boost::math::tools::promote_args<RealType>::type>;92template <class RealType>93laplace_distribution(RealType,RealType)->laplace_distribution<typename boost::math::tools::promote_args<RealType>::type>;94#endif95 96//97// Non-member functions.98template <class RealType, class Policy>99BOOST_MATH_GPU_ENABLED inline boost::math::pair<RealType, RealType> range(const laplace_distribution<RealType, Policy>&)100{101  BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits<RealType>::has_infinity)102  {  // Can use infinity.103     return boost::math::pair<RealType, RealType>(-boost::math::numeric_limits<RealType>::infinity(), boost::math::numeric_limits<RealType>::infinity()); // - to + infinity.104  }105  else106  { // Can only use max_value.107    using boost::math::tools::max_value;108    return boost::math::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.109  }110 111}112 113template <class RealType, class Policy>114BOOST_MATH_GPU_ENABLED inline boost::math::pair<RealType, RealType> support(const laplace_distribution<RealType, Policy>&)115{116  BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits<RealType>::has_infinity)117  { // Can Use infinity.118     return boost::math::pair<RealType, RealType>(-boost::math::numeric_limits<RealType>::infinity(), boost::math::numeric_limits<RealType>::infinity()); // - to + infinity.119  }120  else121  { // Can only use max_value.122    using boost::math::tools::max_value;123    return boost::math::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + max value.124  }125}126 127template <class RealType, class Policy>128BOOST_MATH_GPU_ENABLED inline RealType pdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)129{130   BOOST_MATH_STD_USING // for ADL of std functions131 132   // Checking function argument133   RealType result = 0;134   constexpr auto function = "boost::math::pdf(const laplace_distribution<%1%>&, %1%))";135 136   // Check scale and location.137   if (false == dist.check_parameters(function, &result)) return result;138   // Special pdf values.139   if((boost::math::isinf)(x))140   {141      return 0; // pdf + and - infinity is zero.142   }143   if (false == detail::check_x(function, x, &result, Policy())) return result;144 145   // General case146   RealType scale( dist.scale() );147   RealType location( dist.location() );148 149   RealType exponent = x - location;150   if (exponent>0) exponent = -exponent;151   exponent /= scale;152 153   result = exp(exponent);154   result /= 2 * scale;155 156   return result;157} // pdf158 159template <class RealType, class Policy>160BOOST_MATH_GPU_ENABLED inline RealType logpdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)161{162   BOOST_MATH_STD_USING // for ADL of std functions163 164   // Checking function argument165   RealType result = -boost::math::numeric_limits<RealType>::infinity();166   constexpr auto function = "boost::math::logpdf(const laplace_distribution<%1%>&, %1%))";167 168   // Check scale and location.169   if (false == dist.check_parameters(function, &result))170   {171       return result;172   }173   // Special pdf values.174   if((boost::math::isinf)(x))175   {176      return result; // pdf + and - infinity is zero so logpdf is -INF177   }178   if (false == detail::check_x(function, x, &result, Policy()))179   {180       return result;181   }182 183   const RealType mu = dist.scale();184   const RealType b = dist.location();185 186   // if b is 0 avoid divide by 0 error187   if(abs(b) < boost::math::numeric_limits<RealType>::epsilon())188   {189      result = log(pdf(dist, x));190   }191   else192   {193      // General case194      const RealType log2 = boost::math::constants::ln_two<RealType>();195      result = -abs(x-mu)/b - log(b) - log2;196   }197 198   return result;199} // logpdf200 201template <class RealType, class Policy>202BOOST_MATH_GPU_ENABLED inline RealType cdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)203{204   BOOST_MATH_STD_USING  // For ADL of std functions.205 206   RealType result = 0;207   // Checking function argument.208   constexpr auto function = "boost::math::cdf(const laplace_distribution<%1%>&, %1%)";209   // Check scale and location.210   if (false == dist.check_parameters(function, &result)) return result;211 212   // Special cdf values:213   if((boost::math::isinf)(x))214   {215     if(x < 0) return 0; // -infinity.216     return 1; // + infinity.217   }218   if (false == detail::check_x(function, x, &result, Policy())) return result;219 220   // General cdf  values221   RealType scale( dist.scale() );222   RealType location( dist.location() );223 224   if (x < location)225   {226      result = exp( (x-location)/scale )/2;227   }228   else229   {230      result = 1 - exp( (location-x)/scale )/2;231   }232   return result;233} // cdf234 235template <class RealType, class Policy>236BOOST_MATH_GPU_ENABLED inline RealType logcdf(const laplace_distribution<RealType, Policy>& dist, const RealType& x)237{238   BOOST_MATH_STD_USING  // For ADL of std functions.239 240   RealType result = 0;241   // Checking function argument.242   constexpr auto function = "boost::math::logcdf(const laplace_distribution<%1%>&, %1%)";243   // Check scale and location.244   if (false == dist.check_parameters(function, &result)) 245   {246      return result;247   }248 249   // Special cdf values:250   if((boost::math::isinf)(x))251   {252      if(x < 0) 253      {254         return 0; // -infinity.255      }256      return 1; // + infinity.257   }258 259   if (false == detail::check_x(function, x, &result, Policy())) 260   {261      return result;262   }263 264   // General cdf  values265   RealType scale( dist.scale() );266   RealType location( dist.location() );267 268   if (x < location)269   {270      result = ((x - location) / scale) - boost::math::constants::ln_two<RealType>();271   }272   else273   {274      result = log1p(-exp((location - x) / scale) / 2);275   }276 277   return result;278} // logcdf279 280template <class RealType, class Policy>281BOOST_MATH_GPU_ENABLED inline RealType quantile(const laplace_distribution<RealType, Policy>& dist, const RealType& p)282{283   BOOST_MATH_STD_USING // for ADL of std functions.284 285   // Checking function argument286   RealType result = 0;287   constexpr auto function = "boost::math::quantile(const laplace_distribution<%1%>&, %1%)";288   if (false == dist.check_parameters(function, &result)) return result;289   if(false == detail::check_probability(function, p, &result, Policy())) return result;290 291   // Extreme values of p:292   if(p == 0)293   {294      result = policies::raise_overflow_error<RealType>(function,295        "probability parameter is 0, but must be > 0!", Policy());296      return -result; // -inf297   }298  299   if(p == 1)300   {301      result = policies::raise_overflow_error<RealType>(function,302        "probability parameter is 1, but must be < 1!", Policy());303      return result; // inf304   }305   // Calculate Quantile306   RealType scale( dist.scale() );307   RealType location( dist.location() );308 309   if (p - 0.5 < 0.0)310      result = location + scale*log( static_cast<RealType>(p*2) );311   else312      result = location - scale*log( static_cast<RealType>(-p*2 + 2) );313 314   return result;315} // quantile316 317 318template <class RealType, class Policy>319BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)320{321   // Calculate complement of cdf.322   BOOST_MATH_STD_USING // for ADL of std functions323 324   RealType scale = c.dist.scale();325   RealType location = c.dist.location();326   RealType x = c.param;327   RealType result = 0;328 329   // Checking function argument.330   constexpr auto function = "boost::math::cdf(const complemented2_type<laplace_distribution<%1%>, %1%>&)";331 332   // Check scale and location.333    if (false == c.dist.check_parameters(function, &result)) return result;334 335   // Special cdf values.336   if((boost::math::isinf)(x))337   {338     if(x < 0) return 1; // cdf complement -infinity is unity.339     return 0; // cdf complement +infinity is zero.340   }341   if(false == detail::check_x(function, x, &result, Policy()))return result;342 343   // Cdf interval value.344   if (-x < -location)345   {346      result = exp( (-x+location)/scale )/2;347   }348   else349   {350      result = 1 - exp( (-location+x)/scale )/2;351   }352   return result;353} // cdf complement354 355template <class RealType, class Policy>356BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)357{358   // Calculate complement of logcdf.359   BOOST_MATH_STD_USING // for ADL of std functions360 361   RealType scale = c.dist.scale();362   RealType location = c.dist.location();363   RealType x = c.param;364   RealType result = 0;365 366   // Checking function argument.367   constexpr auto function = "boost::math::logcdf(const complemented2_type<laplace_distribution<%1%>, %1%>&)";368 369   // Check scale and location.370    if (false == c.dist.check_parameters(function, &result)) return result;371 372   // Special cdf values.373   if((boost::math::isinf)(x))374   {375     if(x < 0) 376     { 377       return 1; // cdf complement -infinity is unity.378     }379 380     return 0; // cdf complement +infinity is zero.381   }382   if(false == detail::check_x(function, x, &result, Policy()))return result;383 384   // Cdf interval value.385   if (-x < -location)386   {387      result = (-x+location)/scale - boost::math::constants::ln_two<RealType>();388   }389   else390   {391      result = log1p(-exp( (-location+x)/scale )/2, Policy());392   }393   return result;394} // cdf complement395 396template <class RealType, class Policy>397BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type<laplace_distribution<RealType, Policy>, RealType>& c)398{399   BOOST_MATH_STD_USING // for ADL of std functions.400 401   // Calculate quantile.402   RealType scale = c.dist.scale();403   RealType location = c.dist.location();404   RealType q = c.param;405   RealType result = 0;406 407   // Checking function argument.408   constexpr auto function = "quantile(const complemented2_type<laplace_distribution<%1%>, %1%>&)";409   if (false == c.dist.check_parameters(function, &result)) return result;410   411   // Extreme values.412   if(q == 0)413   {414       return boost::math::numeric_limits<RealType>::infinity();415   }416   if(q == 1)417   {418       return -boost::math::numeric_limits<RealType>::infinity();419   }420   if(false == detail::check_probability(function, q, &result, Policy())) return result;421 422   if (0.5 - q < 0.0)423      result = location + scale*log( static_cast<RealType>(-q*2 + 2) );424   else425      result = location - scale*log( static_cast<RealType>(q*2) );426 427 428   return result;429} // quantile430 431template <class RealType, class Policy>432BOOST_MATH_GPU_ENABLED inline RealType mean(const laplace_distribution<RealType, Policy>& dist)433{434   return dist.location();435}436 437template <class RealType, class Policy>438BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const laplace_distribution<RealType, Policy>& dist)439{440   return constants::root_two<RealType>() * dist.scale();441}442 443template <class RealType, class Policy>444BOOST_MATH_GPU_ENABLED inline RealType mode(const laplace_distribution<RealType, Policy>& dist)445{446   return dist.location();447}448 449template <class RealType, class Policy>450BOOST_MATH_GPU_ENABLED inline RealType median(const laplace_distribution<RealType, Policy>& dist)451{452   return dist.location();453}454 455template <class RealType, class Policy>456BOOST_MATH_GPU_ENABLED inline RealType skewness(const laplace_distribution<RealType, Policy>& /*dist*/)457{458   return 0;459}460 461template <class RealType, class Policy>462BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const laplace_distribution<RealType, Policy>& /*dist*/)463{464   return 6;465}466 467template <class RealType, class Policy>468BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const laplace_distribution<RealType, Policy>& /*dist*/)469{470   return 3;471}472 473template <class RealType, class Policy>474BOOST_MATH_GPU_ENABLED inline RealType entropy(const laplace_distribution<RealType, Policy> & dist)475{476   using std::log;477   return log(2*dist.scale()*constants::e<RealType>());478}479 480#ifdef _MSC_VER481#  pragma warning(pop)482#endif483 484} // namespace math485} // namespace boost486 487// This include must be at the end, *after* the accessors488// for this distribution have been defined, in order to489// keep compilers that support two-phase lookup happy.490#include <boost/math/distributions/detail/derived_accessors.hpp>491 492#endif // BOOST_STATS_LAPLACE_HPP493 494 495