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