File indexing completed on 2025-09-17 08:35:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_STATS_INVERSE_GAMMA_HPP
0011 #define BOOST_STATS_INVERSE_GAMMA_HPP
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <boost/math/tools/config.hpp>
0027 #include <boost/math/tools/tuple.hpp>
0028 #include <boost/math/tools/numeric_limits.hpp>
0029 #include <boost/math/distributions/fwd.hpp>
0030 #include <boost/math/special_functions/gamma.hpp>
0031 #include <boost/math/distributions/detail/common_error_handling.hpp>
0032 #include <boost/math/distributions/complement.hpp>
0033
0034 namespace boost{ namespace math
0035 {
0036 namespace detail
0037 {
0038
0039 template <class RealType, class Policy>
0040 BOOST_MATH_GPU_ENABLED inline bool check_inverse_gamma_shape(
0041 const char* function,
0042 RealType shape,
0043 RealType* result,
0044 const Policy& pol)
0045 {
0046
0047
0048
0049
0050 if((shape < 0) || !(boost::math::isfinite)(shape))
0051 {
0052 *result = policies::raise_domain_error<RealType>(
0053 function,
0054 "Shape parameter is %1%, but must be >= 0 !", shape, pol);
0055 return false;
0056 }
0057 return true;
0058 }
0059
0060 template <class RealType, class Policy>
0061 BOOST_MATH_GPU_ENABLED inline bool check_inverse_gamma_x(
0062 const char* function,
0063 RealType const& x,
0064 RealType* result, const Policy& pol)
0065 {
0066 if((x < 0) || !(boost::math::isfinite)(x))
0067 {
0068 *result = policies::raise_domain_error<RealType>(
0069 function,
0070 "Random variate is %1% but must be >= 0 !", x, pol);
0071 return false;
0072 }
0073 return true;
0074 }
0075
0076 template <class RealType, class Policy>
0077 BOOST_MATH_GPU_ENABLED inline bool check_inverse_gamma(
0078 const char* function,
0079 RealType scale,
0080 RealType shape,
0081 RealType* result, const Policy& pol)
0082 {
0083 return check_scale(function, scale, result, pol)
0084 && check_inverse_gamma_shape(function, shape, result, pol);
0085 }
0086
0087 }
0088
0089 template <class RealType = double, class Policy = policies::policy<> >
0090 class inverse_gamma_distribution
0091 {
0092 public:
0093 using value_type = RealType;
0094 using policy_type = Policy;
0095
0096 BOOST_MATH_GPU_ENABLED explicit inverse_gamma_distribution(RealType l_shape = 1, RealType l_scale = 1)
0097 : m_shape(l_shape), m_scale(l_scale)
0098 {
0099 RealType result;
0100 detail::check_inverse_gamma(
0101 "boost::math::inverse_gamma_distribution<%1%>::inverse_gamma_distribution",
0102 l_scale, l_shape, &result, Policy());
0103 }
0104
0105 BOOST_MATH_GPU_ENABLED RealType shape()const
0106 {
0107 return m_shape;
0108 }
0109
0110 BOOST_MATH_GPU_ENABLED RealType scale()const
0111 {
0112 return m_scale;
0113 }
0114 private:
0115
0116
0117
0118 RealType m_shape;
0119 RealType m_scale;
0120 };
0121
0122 using inverse_gamma = inverse_gamma_distribution<double>;
0123
0124
0125
0126 #ifdef __cpp_deduction_guides
0127 template <class RealType>
0128 inverse_gamma_distribution(RealType)->inverse_gamma_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0129 template <class RealType>
0130 inverse_gamma_distribution(RealType,RealType)->inverse_gamma_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0131 #endif
0132
0133
0134
0135 template <class RealType, class Policy>
0136 BOOST_MATH_GPU_ENABLED inline boost::math::pair<RealType, RealType> range(const inverse_gamma_distribution<RealType, Policy>& )
0137 {
0138 using boost::math::tools::max_value;
0139 return boost::math::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0140 }
0141
0142 template <class RealType, class Policy>
0143 BOOST_MATH_GPU_ENABLED inline boost::math::pair<RealType, RealType> support(const inverse_gamma_distribution<RealType, Policy>& )
0144 {
0145
0146 using boost::math::tools::max_value;
0147 using boost::math::tools::min_value;
0148 return boost::math::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0149 }
0150
0151 template <class RealType, class Policy>
0152 BOOST_MATH_GPU_ENABLED inline RealType pdf(const inverse_gamma_distribution<RealType, Policy>& dist, const RealType& x)
0153 {
0154 BOOST_MATH_STD_USING
0155
0156 constexpr auto function = "boost::math::pdf(const inverse_gamma_distribution<%1%>&, %1%)";
0157
0158 RealType shape = dist.shape();
0159 RealType scale = dist.scale();
0160
0161 RealType result = 0;
0162 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
0163 {
0164 return result;
0165 }
0166 if(x == 0)
0167 {
0168 return 0;
0169 }
0170 else if(false == detail::check_inverse_gamma_x(function, x, &result, Policy()))
0171 {
0172 return result;
0173 }
0174 result = scale / x;
0175 if(result < tools::min_value<RealType>())
0176 return 0;
0177 result = gamma_p_derivative(shape, result, Policy()) * scale;
0178 if(0 != result)
0179 {
0180 if(x < 0)
0181 {
0182
0183
0184 RealType lim = tools::max_value<RealType>() * x;
0185 if(lim < result)
0186 return policies::raise_overflow_error<RealType, Policy>(function, "PDF is infinite.", Policy());
0187 result /= x;
0188 if(lim < result)
0189 return policies::raise_overflow_error<RealType, Policy>(function, "PDF is infinite.", Policy());
0190 result /= x;
0191 }
0192 result /= (x * x);
0193 }
0194
0195 return result;
0196 }
0197
0198 template <class RealType, class Policy>
0199 BOOST_MATH_GPU_ENABLED inline RealType logpdf(const inverse_gamma_distribution<RealType, Policy>& dist, const RealType& x)
0200 {
0201 BOOST_MATH_STD_USING
0202 using boost::math::lgamma;
0203
0204 constexpr auto function = "boost::math::logpdf(const inverse_gamma_distribution<%1%>&, %1%)";
0205
0206 RealType shape = dist.shape();
0207 RealType scale = dist.scale();
0208
0209 RealType result = -boost::math::numeric_limits<RealType>::infinity();
0210 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
0211 {
0212 return result;
0213 }
0214 if(x == 0)
0215 {
0216 return result;
0217 }
0218 else if(false == detail::check_inverse_gamma_x(function, x, &result, Policy()))
0219 {
0220 return result;
0221 }
0222 result = scale / x;
0223 if(result < tools::min_value<RealType>())
0224 return result;
0225
0226
0227 if (!(boost::math::isfinite)(x*x))
0228 {
0229 return policies::raise_overflow_error<RealType, Policy>(function, "PDF is infinite.", Policy());
0230 }
0231
0232 return shape * log(scale) + (-shape-1)*log(x) - lgamma(shape) - (scale/x);
0233 }
0234
0235 template <class RealType, class Policy>
0236 BOOST_MATH_GPU_ENABLED inline RealType cdf(const inverse_gamma_distribution<RealType, Policy>& dist, const RealType& x)
0237 {
0238 BOOST_MATH_STD_USING
0239
0240 constexpr auto function = "boost::math::cdf(const inverse_gamma_distribution<%1%>&, %1%)";
0241
0242 RealType shape = dist.shape();
0243 RealType scale = dist.scale();
0244
0245 RealType result = 0;
0246 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
0247 {
0248 return result;
0249 }
0250 if (x == 0)
0251 {
0252 return 0;
0253 }
0254 else if(false == detail::check_inverse_gamma_x(function, x, &result, Policy()))
0255 {
0256 return result;
0257 }
0258 result = boost::math::gamma_q(shape, scale / x, Policy());
0259
0260 return result;
0261 }
0262
0263 template <class RealType, class Policy>
0264 BOOST_MATH_GPU_ENABLED inline RealType quantile(const inverse_gamma_distribution<RealType, Policy>& dist, const RealType& p)
0265 {
0266 BOOST_MATH_STD_USING
0267 using boost::math::gamma_q_inv;
0268
0269 constexpr auto function = "boost::math::quantile(const inverse_gamma_distribution<%1%>&, %1%)";
0270
0271 RealType shape = dist.shape();
0272 RealType scale = dist.scale();
0273
0274 RealType result = 0;
0275 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
0276 return result;
0277 if(false == detail::check_probability(function, p, &result, Policy()))
0278 return result;
0279 if(p == 1)
0280 {
0281 return policies::raise_overflow_error<RealType>(function, 0, Policy());
0282 }
0283 result = gamma_q_inv(shape, p, Policy());
0284 if((result < 1) && (result * tools::max_value<RealType>() < scale))
0285 return policies::raise_overflow_error<RealType, Policy>(function, "Value of random variable in inverse gamma distribution quantile is infinite.", Policy());
0286 result = scale / result;
0287 return result;
0288 }
0289
0290 template <class RealType, class Policy>
0291 BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type<inverse_gamma_distribution<RealType, Policy>, RealType>& c)
0292 {
0293 BOOST_MATH_STD_USING
0294
0295 constexpr auto function = "boost::math::quantile(const gamma_distribution<%1%>&, %1%)";
0296
0297 RealType shape = c.dist.shape();
0298 RealType scale = c.dist.scale();
0299
0300 RealType result = 0;
0301 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
0302 return result;
0303 if(false == detail::check_inverse_gamma_x(function, c.param, &result, Policy()))
0304 return result;
0305
0306 if(c.param == 0)
0307 return 1;
0308
0309 result = gamma_p(shape, scale/c.param, Policy());
0310 return result;
0311 }
0312
0313 template <class RealType, class Policy>
0314 BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type<inverse_gamma_distribution<RealType, Policy>, RealType>& c)
0315 {
0316 BOOST_MATH_STD_USING
0317
0318 constexpr auto function = "boost::math::quantile(const inverse_gamma_distribution<%1%>&, %1%)";
0319
0320 RealType shape = c.dist.shape();
0321 RealType scale = c.dist.scale();
0322 RealType q = c.param;
0323
0324 RealType result = 0;
0325 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
0326 return result;
0327 if(false == detail::check_probability(function, q, &result, Policy()))
0328 return result;
0329
0330 if(q == 0)
0331 {
0332 return policies::raise_overflow_error<RealType>(function, 0, Policy());
0333 }
0334 result = gamma_p_inv(shape, q, Policy());
0335 if((result < 1) && (result * tools::max_value<RealType>() < scale))
0336 return policies::raise_overflow_error<RealType, Policy>(function, "Value of random variable in inverse gamma distribution quantile is infinite.", Policy());
0337 result = scale / result;
0338 return result;
0339 }
0340
0341 template <class RealType, class Policy>
0342 BOOST_MATH_GPU_ENABLED inline RealType mean(const inverse_gamma_distribution<RealType, Policy>& dist)
0343 {
0344 BOOST_MATH_STD_USING
0345
0346 constexpr auto function = "boost::math::mean(const inverse_gamma_distribution<%1%>&)";
0347
0348 RealType shape = dist.shape();
0349 RealType scale = dist.scale();
0350
0351 RealType result = 0;
0352
0353 if(false == detail::check_scale(function, scale, &result, Policy()))
0354 {
0355 return result;
0356 }
0357 if((shape <= 1) || !(boost::math::isfinite)(shape))
0358 {
0359 result = policies::raise_domain_error<RealType>(
0360 function,
0361 "Shape parameter is %1%, but for a defined mean it must be > 1", shape, Policy());
0362 return result;
0363 }
0364 result = scale / (shape - 1);
0365 return result;
0366 }
0367
0368 template <class RealType, class Policy>
0369 BOOST_MATH_GPU_ENABLED inline RealType variance(const inverse_gamma_distribution<RealType, Policy>& dist)
0370 {
0371 BOOST_MATH_STD_USING
0372
0373 constexpr auto function = "boost::math::variance(const inverse_gamma_distribution<%1%>&)";
0374
0375 RealType shape = dist.shape();
0376 RealType scale = dist.scale();
0377
0378 RealType result = 0;
0379 if(false == detail::check_scale(function, scale, &result, Policy()))
0380 {
0381 return result;
0382 }
0383 if((shape <= 2) || !(boost::math::isfinite)(shape))
0384 {
0385 result = policies::raise_domain_error<RealType>(
0386 function,
0387 "Shape parameter is %1%, but for a defined variance it must be > 2", shape, Policy());
0388 return result;
0389 }
0390 result = (scale * scale) / ((shape - 1) * (shape -1) * (shape -2));
0391 return result;
0392 }
0393
0394 template <class RealType, class Policy>
0395 BOOST_MATH_GPU_ENABLED inline RealType mode(const inverse_gamma_distribution<RealType, Policy>& dist)
0396 {
0397 BOOST_MATH_STD_USING
0398
0399 constexpr auto function = "boost::math::mode(const inverse_gamma_distribution<%1%>&)";
0400
0401 RealType shape = dist.shape();
0402 RealType scale = dist.scale();
0403
0404 RealType result = 0;
0405 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
0406 {
0407 return result;
0408 }
0409
0410 result = scale / (shape + 1);
0411 return result;
0412 }
0413
0414
0415
0416
0417
0418
0419
0420
0421 template <class RealType, class Policy>
0422 BOOST_MATH_GPU_ENABLED inline RealType skewness(const inverse_gamma_distribution<RealType, Policy>& dist)
0423 {
0424 BOOST_MATH_STD_USING
0425
0426 constexpr auto function = "boost::math::skewness(const inverse_gamma_distribution<%1%>&)";
0427
0428 RealType shape = dist.shape();
0429 RealType scale = dist.scale();
0430 RealType result = 0;
0431
0432 if(false == detail::check_scale(function, scale, &result, Policy()))
0433 {
0434 return result;
0435 }
0436 if((shape <= 3) || !(boost::math::isfinite)(shape))
0437 {
0438 result = policies::raise_domain_error<RealType>(
0439 function,
0440 "Shape parameter is %1%, but for a defined skewness it must be > 3", shape, Policy());
0441 return result;
0442 }
0443 result = (4 * sqrt(shape - 2) ) / (shape - 3);
0444 return result;
0445 }
0446
0447 template <class RealType, class Policy>
0448 BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const inverse_gamma_distribution<RealType, Policy>& dist)
0449 {
0450 BOOST_MATH_STD_USING
0451
0452 constexpr auto function = "boost::math::kurtosis_excess(const inverse_gamma_distribution<%1%>&)";
0453
0454 RealType shape = dist.shape();
0455 RealType scale = dist.scale();
0456
0457 RealType result = 0;
0458 if(false == detail::check_scale(function, scale, &result, Policy()))
0459 {
0460 return result;
0461 }
0462 if((shape <= 4) || !(boost::math::isfinite)(shape))
0463 {
0464 result = policies::raise_domain_error<RealType>(
0465 function,
0466 "Shape parameter is %1%, but for a defined kurtosis excess it must be > 4", shape, Policy());
0467 return result;
0468 }
0469 result = (30 * shape - 66) / ((shape - 3) * (shape - 4));
0470 return result;
0471 }
0472
0473 template <class RealType, class Policy>
0474 BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const inverse_gamma_distribution<RealType, Policy>& dist)
0475 {
0476 constexpr auto function = "boost::math::kurtosis(const inverse_gamma_distribution<%1%>&)";
0477 RealType shape = dist.shape();
0478 RealType scale = dist.scale();
0479
0480 RealType result = 0;
0481
0482 if(false == detail::check_scale(function, scale, &result, Policy()))
0483 {
0484 return result;
0485 }
0486 if((shape <= 4) || !(boost::math::isfinite)(shape))
0487 {
0488 result = policies::raise_domain_error<RealType>(
0489 function,
0490 "Shape parameter is %1%, but for a defined kurtosis it must be > 4", shape, Policy());
0491 return result;
0492 }
0493 return kurtosis_excess(dist) + 3;
0494 }
0495
0496 }
0497 }
0498
0499
0500
0501
0502 #include <boost/math/distributions/detail/derived_accessors.hpp>
0503
0504 #endif