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