353 lines · plain
1// Copyright John Maddock 2006.2// Copyright Matt Borland 20243// Use, modification and distribution are subject to the4// Boost Software License, Version 1.0. (See accompanying file5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)6 7#ifndef BOOST_STATS_EXPONENTIAL_HPP8#define BOOST_STATS_EXPONENTIAL_HPP9 10#include <boost/math/tools/config.hpp>11#include <boost/math/tools/tuple.hpp>12#include <boost/math/tools/numeric_limits.hpp>13#include <boost/math/constants/constants.hpp>14#include <boost/math/special_functions/log1p.hpp>15#include <boost/math/special_functions/expm1.hpp>16#include <boost/math/distributions/complement.hpp>17#include <boost/math/distributions/detail/common_error_handling.hpp>18#include <boost/math/policies/policy.hpp>19#include <boost/math/policies/error_handling.hpp>20 21#ifdef _MSC_VER22# pragma warning(push)23# pragma warning(disable: 4127) // conditional expression is constant24# pragma warning(disable: 4702) // unreachable code (return after domain_error throw).25#endif26 27#ifndef BOOST_MATH_HAS_NVRTC28#include <boost/math/distributions/fwd.hpp>29#include <utility>30#include <cmath>31#endif32 33namespace boost{ namespace math{34 35namespace detail{36//37// Error check:38//39template <class RealType, class Policy>40BOOST_MATH_GPU_ENABLED inline bool verify_lambda(const char* function, RealType l, RealType* presult, const Policy& pol)41{42 if((l <= 0) || !(boost::math::isfinite)(l))43 {44 *presult = policies::raise_domain_error<RealType>(45 function,46 "The scale parameter \"lambda\" must be > 0, but was: %1%.", l, pol);47 return false;48 }49 return true;50}51 52template <class RealType, class Policy>53BOOST_MATH_GPU_ENABLED inline bool verify_exp_x(const char* function, RealType x, RealType* presult, const Policy& pol)54{55 if((x < 0) || (boost::math::isnan)(x))56 {57 *presult = policies::raise_domain_error<RealType>(58 function,59 "The random variable must be >= 0, but was: %1%.", x, pol);60 return false;61 }62 return true;63}64 65} // namespace detail66 67template <class RealType = double, class Policy = policies::policy<> >68class exponential_distribution69{70public:71 using value_type = RealType;72 using policy_type = Policy;73 74 BOOST_MATH_GPU_ENABLED explicit exponential_distribution(RealType l_lambda = 1)75 : m_lambda(l_lambda)76 {77 RealType err;78 detail::verify_lambda("boost::math::exponential_distribution<%1%>::exponential_distribution", l_lambda, &err, Policy());79 } // exponential_distribution80 81 BOOST_MATH_GPU_ENABLED RealType lambda()const { return m_lambda; }82 83private:84 RealType m_lambda;85};86 87using exponential = exponential_distribution<double>;88 89#ifdef __cpp_deduction_guides90template <class RealType>91exponential_distribution(RealType)->exponential_distribution<typename boost::math::tools::promote_args<RealType>::type>;92#endif93 94template <class RealType, class Policy>95BOOST_MATH_GPU_ENABLED inline boost::math::pair<RealType, RealType> range(const exponential_distribution<RealType, Policy>& /*dist*/)96{ // Range of permissible values for random variable x.97 BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits<RealType>::has_infinity)98 { 99 return boost::math::pair<RealType, RealType>(static_cast<RealType>(0), boost::math::numeric_limits<RealType>::infinity()); // 0 to + infinity.100 }101 else102 {103 using boost::math::tools::max_value;104 return boost::math::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // 0 to + max105 }106}107 108template <class RealType, class Policy>109BOOST_MATH_GPU_ENABLED inline boost::math::pair<RealType, RealType> support(const exponential_distribution<RealType, Policy>& /*dist*/)110{ // Range of supported values for random variable x.111 // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.112 using boost::math::tools::max_value;113 using boost::math::tools::min_value;114 return boost::math::pair<RealType, RealType>(min_value<RealType>(), max_value<RealType>());115 // min_value<RealType>() to avoid a discontinuity at x = 0.116}117 118template <class RealType, class Policy>119BOOST_MATH_GPU_ENABLED inline RealType pdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x)120{121 BOOST_MATH_STD_USING // for ADL of std functions122 123 constexpr auto function = "boost::math::pdf(const exponential_distribution<%1%>&, %1%)";124 125 RealType lambda = dist.lambda();126 RealType result = 0;127 if(0 == detail::verify_lambda(function, lambda, &result, Policy()))128 return result;129 if(0 == detail::verify_exp_x(function, x, &result, Policy()))130 return result;131 // Workaround for VC11/12 bug:132 if ((boost::math::isinf)(x))133 return 0;134 result = lambda * exp(-lambda * x);135 return result;136} // pdf137 138template <class RealType, class Policy>139BOOST_MATH_GPU_ENABLED inline RealType logpdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x)140{141 BOOST_MATH_STD_USING // for ADL of std functions142 143 constexpr auto function = "boost::math::logpdf(const exponential_distribution<%1%>&, %1%)";144 145 RealType lambda = dist.lambda();146 RealType result = -boost::math::numeric_limits<RealType>::infinity();147 if(0 == detail::verify_lambda(function, lambda, &result, Policy()))148 return result;149 if(0 == detail::verify_exp_x(function, x, &result, Policy()))150 return result;151 152 result = log(lambda) - lambda * x;153 return result;154} // logpdf155 156template <class RealType, class Policy>157BOOST_MATH_GPU_ENABLED inline RealType cdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x)158{159 BOOST_MATH_STD_USING // for ADL of std functions160 161 constexpr auto function = "boost::math::cdf(const exponential_distribution<%1%>&, %1%)";162 163 RealType result = 0;164 RealType lambda = dist.lambda();165 if(0 == detail::verify_lambda(function, lambda, &result, Policy()))166 return result;167 if(0 == detail::verify_exp_x(function, x, &result, Policy()))168 return result;169 result = -boost::math::expm1(-x * lambda, Policy());170 171 return result;172} // cdf173 174template <class RealType, class Policy>175BOOST_MATH_GPU_ENABLED inline RealType logcdf(const exponential_distribution<RealType, Policy>& dist, const RealType& x)176{177 BOOST_MATH_STD_USING // for ADL of std functions178 179 constexpr auto function = "boost::math::logcdf(const exponential_distribution<%1%>&, %1%)";180 181 RealType result = 0;182 RealType lambda = dist.lambda();183 if(0 == detail::verify_lambda(function, lambda, &result, Policy()))184 return result;185 if(0 == detail::verify_exp_x(function, x, &result, Policy()))186 return result;187 result = boost::math::log1p(-exp(-x * lambda), Policy());188 189 return result;190} // cdf191 192template <class RealType, class Policy>193BOOST_MATH_GPU_ENABLED inline RealType quantile(const exponential_distribution<RealType, Policy>& dist, const RealType& p)194{195 BOOST_MATH_STD_USING // for ADL of std functions196 197 constexpr auto function = "boost::math::quantile(const exponential_distribution<%1%>&, %1%)";198 199 RealType result = 0;200 RealType lambda = dist.lambda();201 if(0 == detail::verify_lambda(function, lambda, &result, Policy()))202 return result;203 if(0 == detail::check_probability(function, p, &result, Policy()))204 return result;205 206 if(p == 0)207 return 0;208 if(p == 1)209 return policies::raise_overflow_error<RealType>(function, 0, Policy());210 211 result = -boost::math::log1p(-p, Policy()) / lambda;212 return result;213} // quantile214 215template <class RealType, class Policy>216BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type<exponential_distribution<RealType, Policy>, RealType>& c)217{218 BOOST_MATH_STD_USING // for ADL of std functions219 220 constexpr auto function = "boost::math::cdf(const exponential_distribution<%1%>&, %1%)";221 222 RealType result = 0;223 RealType lambda = c.dist.lambda();224 if(0 == detail::verify_lambda(function, lambda, &result, Policy()))225 return result;226 if(0 == detail::verify_exp_x(function, c.param, &result, Policy()))227 return result;228 // Workaround for VC11/12 bug:229 if (c.param >= tools::max_value<RealType>())230 return 0;231 result = exp(-c.param * lambda);232 233 return result;234}235 236template <class RealType, class Policy>237BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type<exponential_distribution<RealType, Policy>, RealType>& c)238{239 BOOST_MATH_STD_USING // for ADL of std functions240 241 constexpr auto function = "boost::math::logcdf(const exponential_distribution<%1%>&, %1%)";242 243 RealType result = 0;244 RealType lambda = c.dist.lambda();245 if(0 == detail::verify_lambda(function, lambda, &result, Policy()))246 return result;247 if(0 == detail::verify_exp_x(function, c.param, &result, Policy()))248 return result;249 // Workaround for VC11/12 bug:250 if (c.param >= tools::max_value<RealType>())251 return 0;252 result = -c.param * lambda;253 254 return result;255}256 257template <class RealType, class Policy>258BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type<exponential_distribution<RealType, Policy>, RealType>& c)259{260 BOOST_MATH_STD_USING // for ADL of std functions261 262 constexpr auto function = "boost::math::quantile(const exponential_distribution<%1%>&, %1%)";263 264 RealType result = 0;265 RealType lambda = c.dist.lambda();266 if(0 == detail::verify_lambda(function, lambda, &result, Policy()))267 return result;268 269 RealType q = c.param;270 if(0 == detail::check_probability(function, q, &result, Policy()))271 return result;272 273 if(q == 1)274 return 0;275 if(q == 0)276 return policies::raise_overflow_error<RealType>(function, 0, Policy());277 278 result = -log(q) / lambda;279 return result;280}281 282template <class RealType, class Policy>283BOOST_MATH_GPU_ENABLED inline RealType mean(const exponential_distribution<RealType, Policy>& dist)284{285 RealType result = 0;286 RealType lambda = dist.lambda();287 if(0 == detail::verify_lambda("boost::math::mean(const exponential_distribution<%1%>&)", lambda, &result, Policy()))288 return result;289 return 1 / lambda;290}291 292template <class RealType, class Policy>293BOOST_MATH_GPU_ENABLED inline RealType standard_deviation(const exponential_distribution<RealType, Policy>& dist)294{295 RealType result = 0;296 RealType lambda = dist.lambda();297 if(0 == detail::verify_lambda("boost::math::standard_deviation(const exponential_distribution<%1%>&)", lambda, &result, Policy()))298 return result;299 return 1 / lambda;300}301 302template <class RealType, class Policy>303BOOST_MATH_GPU_ENABLED inline RealType mode(const exponential_distribution<RealType, Policy>& /*dist*/)304{305 return 0;306}307 308template <class RealType, class Policy>309BOOST_MATH_GPU_ENABLED inline RealType median(const exponential_distribution<RealType, Policy>& dist)310{311 using boost::math::constants::ln_two;312 return ln_two<RealType>() / dist.lambda(); // ln(2) / lambda313}314 315template <class RealType, class Policy>316BOOST_MATH_GPU_ENABLED inline RealType skewness(const exponential_distribution<RealType, Policy>& /*dist*/)317{318 return 2;319}320 321template <class RealType, class Policy>322BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const exponential_distribution<RealType, Policy>& /*dist*/)323{324 return 9;325}326 327template <class RealType, class Policy>328BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const exponential_distribution<RealType, Policy>& /*dist*/)329{330 return 6;331}332 333template <class RealType, class Policy>334BOOST_MATH_GPU_ENABLED inline RealType entropy(const exponential_distribution<RealType, Policy>& dist)335{336 using std::log;337 return 1 - log(dist.lambda());338}339 340} // namespace math341} // namespace boost342 343#ifdef _MSC_VER344# pragma warning(pop)345#endif346 347// This include must be at the end, *after* the accessors348// for this distribution have been defined, in order to349// keep compilers that support two-phase lookup happy.350#include <boost/math/distributions/detail/derived_accessors.hpp>351 352#endif // BOOST_STATS_EXPONENTIAL_HPP353