annotate DEPENDENCIES/generic/include/boost/math/distributions/inverse_gamma.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // inverse_gamma.hpp
Chris@16 2
Chris@16 3 // Copyright Paul A. Bristow 2010.
Chris@16 4 // Copyright John Maddock 2010.
Chris@16 5 // Use, modification and distribution are subject to the
Chris@16 6 // Boost Software License, Version 1.0. (See accompanying file
Chris@16 7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8
Chris@16 9 #ifndef BOOST_STATS_INVERSE_GAMMA_HPP
Chris@16 10 #define BOOST_STATS_INVERSE_GAMMA_HPP
Chris@16 11
Chris@16 12 // Inverse Gamma Distribution is a two-parameter family
Chris@16 13 // of continuous probability distributions
Chris@16 14 // on the positive real line, which is the distribution of
Chris@16 15 // the reciprocal of a variable distributed according to the gamma distribution.
Chris@16 16
Chris@16 17 // http://en.wikipedia.org/wiki/Inverse-gamma_distribution
Chris@16 18 // http://rss.acs.unt.edu/Rdoc/library/pscl/html/igamma.html
Chris@16 19
Chris@16 20 // See also gamma distribution at gamma.hpp:
Chris@16 21 // http://www.itl.nist.gov/div898/handbook/eda/section3/eda366b.htm
Chris@16 22 // http://mathworld.wolfram.com/GammaDistribution.html
Chris@16 23 // http://en.wikipedia.org/wiki/Gamma_distribution
Chris@16 24
Chris@16 25 #include <boost/math/distributions/fwd.hpp>
Chris@16 26 #include <boost/math/special_functions/gamma.hpp>
Chris@16 27 #include <boost/math/distributions/detail/common_error_handling.hpp>
Chris@16 28 #include <boost/math/distributions/complement.hpp>
Chris@16 29
Chris@16 30 #include <utility>
Chris@16 31
Chris@16 32 namespace boost{ namespace math
Chris@16 33 {
Chris@16 34 namespace detail
Chris@16 35 {
Chris@16 36
Chris@16 37 template <class RealType, class Policy>
Chris@16 38 inline bool check_inverse_gamma_shape(
Chris@16 39 const char* function, // inverse_gamma
Chris@16 40 RealType shape, // shape aka alpha
Chris@16 41 RealType* result, // to update, perhaps with NaN
Chris@16 42 const Policy& pol)
Chris@16 43 { // Sources say shape argument must be > 0
Chris@16 44 // but seems logical to allow shape zero as special case,
Chris@16 45 // returning pdf and cdf zero (but not < 0).
Chris@16 46 // (Functions like mean, variance with other limits on shape are checked
Chris@16 47 // in version including an operator & limit below).
Chris@16 48 if((shape < 0) || !(boost::math::isfinite)(shape))
Chris@16 49 {
Chris@16 50 *result = policies::raise_domain_error<RealType>(
Chris@16 51 function,
Chris@16 52 "Shape parameter is %1%, but must be >= 0 !", shape, pol);
Chris@16 53 return false;
Chris@16 54 }
Chris@16 55 return true;
Chris@16 56 } //bool check_inverse_gamma_shape
Chris@16 57
Chris@16 58 template <class RealType, class Policy>
Chris@16 59 inline bool check_inverse_gamma_x(
Chris@16 60 const char* function,
Chris@16 61 RealType const& x,
Chris@16 62 RealType* result, const Policy& pol)
Chris@16 63 {
Chris@16 64 if((x < 0) || !(boost::math::isfinite)(x))
Chris@16 65 {
Chris@16 66 *result = policies::raise_domain_error<RealType>(
Chris@16 67 function,
Chris@16 68 "Random variate is %1% but must be >= 0 !", x, pol);
Chris@16 69 return false;
Chris@16 70 }
Chris@16 71 return true;
Chris@16 72 }
Chris@16 73
Chris@16 74 template <class RealType, class Policy>
Chris@16 75 inline bool check_inverse_gamma(
Chris@16 76 const char* function, // TODO swap these over, so shape is first.
Chris@16 77 RealType scale, // scale aka beta
Chris@16 78 RealType shape, // shape aka alpha
Chris@16 79 RealType* result, const Policy& pol)
Chris@16 80 {
Chris@16 81 return check_scale(function, scale, result, pol)
Chris@16 82 && check_inverse_gamma_shape(function, shape, result, pol);
Chris@16 83 } // bool check_inverse_gamma
Chris@16 84
Chris@16 85 } // namespace detail
Chris@16 86
Chris@16 87 template <class RealType = double, class Policy = policies::policy<> >
Chris@16 88 class inverse_gamma_distribution
Chris@16 89 {
Chris@16 90 public:
Chris@16 91 typedef RealType value_type;
Chris@16 92 typedef Policy policy_type;
Chris@16 93
Chris@16 94 inverse_gamma_distribution(RealType l_shape = 1, RealType l_scale = 1)
Chris@16 95 : m_shape(l_shape), m_scale(l_scale)
Chris@16 96 {
Chris@16 97 RealType result;
Chris@16 98 detail::check_inverse_gamma(
Chris@16 99 "boost::math::inverse_gamma_distribution<%1%>::inverse_gamma_distribution",
Chris@16 100 l_scale, l_shape, &result, Policy());
Chris@16 101 }
Chris@16 102
Chris@16 103 RealType shape()const
Chris@16 104 {
Chris@16 105 return m_shape;
Chris@16 106 }
Chris@16 107
Chris@16 108 RealType scale()const
Chris@16 109 {
Chris@16 110 return m_scale;
Chris@16 111 }
Chris@16 112 private:
Chris@16 113 //
Chris@16 114 // Data members:
Chris@16 115 //
Chris@16 116 RealType m_shape; // distribution shape
Chris@16 117 RealType m_scale; // distribution scale
Chris@16 118 };
Chris@16 119
Chris@16 120 typedef inverse_gamma_distribution<double> inverse_gamma;
Chris@16 121 // typedef - but potential clash with name of inverse gamma *function*.
Chris@16 122 // but there is a typedef for gamma
Chris@16 123 // typedef boost::math::gamma_distribution<Type, Policy> gamma;
Chris@16 124
Chris@16 125 // Allow random variable x to be zero, treated as a special case (unlike some definitions).
Chris@16 126
Chris@16 127 template <class RealType, class Policy>
Chris@16 128 inline const std::pair<RealType, RealType> range(const inverse_gamma_distribution<RealType, Policy>& /* dist */)
Chris@16 129 { // Range of permissible values for random variable x.
Chris@16 130 using boost::math::tools::max_value;
Chris@16 131 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
Chris@16 132 }
Chris@16 133
Chris@16 134 template <class RealType, class Policy>
Chris@16 135 inline const std::pair<RealType, RealType> support(const inverse_gamma_distribution<RealType, Policy>& /* dist */)
Chris@16 136 { // Range of supported values for random variable x.
Chris@16 137 // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
Chris@16 138 using boost::math::tools::max_value;
Chris@16 139 using boost::math::tools::min_value;
Chris@16 140 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
Chris@16 141 }
Chris@16 142
Chris@16 143 template <class RealType, class Policy>
Chris@16 144 inline RealType pdf(const inverse_gamma_distribution<RealType, Policy>& dist, const RealType& x)
Chris@16 145 {
Chris@16 146 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 147
Chris@16 148 static const char* function = "boost::math::pdf(const inverse_gamma_distribution<%1%>&, %1%)";
Chris@16 149
Chris@16 150 RealType shape = dist.shape();
Chris@16 151 RealType scale = dist.scale();
Chris@16 152
Chris@16 153 RealType result = 0;
Chris@16 154 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
Chris@16 155 { // distribution parameters bad.
Chris@16 156 return result;
Chris@16 157 }
Chris@16 158 if(x == 0)
Chris@16 159 { // Treat random variate zero as a special case.
Chris@16 160 return 0;
Chris@16 161 }
Chris@16 162 else if(false == detail::check_inverse_gamma_x(function, x, &result, Policy()))
Chris@16 163 { // x bad.
Chris@16 164 return result;
Chris@16 165 }
Chris@16 166 result = scale / x;
Chris@16 167 if(result < tools::min_value<RealType>())
Chris@16 168 return 0; // random variable is infinite or so close as to make no difference.
Chris@16 169 result = gamma_p_derivative(shape, result, Policy()) * scale;
Chris@16 170 if(0 != result)
Chris@16 171 {
Chris@16 172 if(x < 0)
Chris@16 173 {
Chris@16 174 // x * x may under or overflow, likewise our result,
Chris@16 175 // so be extra careful about the arithmetic:
Chris@16 176 RealType lim = tools::max_value<RealType>() * x;
Chris@16 177 if(lim < result)
Chris@16 178 return policies::raise_overflow_error<RealType, Policy>(function, "PDF is infinite.", Policy());
Chris@16 179 result /= x;
Chris@16 180 if(lim < result)
Chris@16 181 return policies::raise_overflow_error<RealType, Policy>(function, "PDF is infinite.", Policy());
Chris@16 182 result /= x;
Chris@16 183 }
Chris@16 184 result /= (x * x);
Chris@16 185 }
Chris@16 186 // better than naive
Chris@16 187 // result = (pow(scale, shape) * pow(x, (-shape -1)) * exp(-scale/x) ) / tgamma(shape);
Chris@16 188 return result;
Chris@16 189 } // pdf
Chris@16 190
Chris@16 191 template <class RealType, class Policy>
Chris@16 192 inline RealType cdf(const inverse_gamma_distribution<RealType, Policy>& dist, const RealType& x)
Chris@16 193 {
Chris@16 194 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 195
Chris@16 196 static const char* function = "boost::math::cdf(const inverse_gamma_distribution<%1%>&, %1%)";
Chris@16 197
Chris@16 198 RealType shape = dist.shape();
Chris@16 199 RealType scale = dist.scale();
Chris@16 200
Chris@16 201 RealType result = 0;
Chris@16 202 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
Chris@16 203 { // distribution parameters bad.
Chris@16 204 return result;
Chris@16 205 }
Chris@16 206 if (x == 0)
Chris@16 207 { // Treat zero as a special case.
Chris@16 208 return 0;
Chris@16 209 }
Chris@16 210 else if(false == detail::check_inverse_gamma_x(function, x, &result, Policy()))
Chris@16 211 { // x bad
Chris@16 212 return result;
Chris@16 213 }
Chris@16 214 result = boost::math::gamma_q(shape, scale / x, Policy());
Chris@16 215 // result = tgamma(shape, scale / x) / tgamma(shape); // naive using tgamma
Chris@16 216 return result;
Chris@16 217 } // cdf
Chris@16 218
Chris@16 219 template <class RealType, class Policy>
Chris@16 220 inline RealType quantile(const inverse_gamma_distribution<RealType, Policy>& dist, const RealType& p)
Chris@16 221 {
Chris@16 222 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 223 using boost::math::gamma_q_inv;
Chris@16 224
Chris@16 225 static const char* function = "boost::math::quantile(const inverse_gamma_distribution<%1%>&, %1%)";
Chris@16 226
Chris@16 227 RealType shape = dist.shape();
Chris@16 228 RealType scale = dist.scale();
Chris@16 229
Chris@16 230 RealType result = 0;
Chris@16 231 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
Chris@16 232 return result;
Chris@16 233 if(false == detail::check_probability(function, p, &result, Policy()))
Chris@16 234 return result;
Chris@16 235 if(p == 1)
Chris@16 236 {
Chris@16 237 return policies::raise_overflow_error<RealType>(function, 0, Policy());
Chris@16 238 }
Chris@16 239 result = gamma_q_inv(shape, p, Policy());
Chris@16 240 if((result < 1) && (result * tools::max_value<RealType>() < scale))
Chris@16 241 return policies::raise_overflow_error<RealType, Policy>(function, "Value of random variable in inverse gamma distribution quantile is infinite.", Policy());
Chris@16 242 result = scale / result;
Chris@16 243 return result;
Chris@16 244 }
Chris@16 245
Chris@16 246 template <class RealType, class Policy>
Chris@16 247 inline RealType cdf(const complemented2_type<inverse_gamma_distribution<RealType, Policy>, RealType>& c)
Chris@16 248 {
Chris@16 249 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 250
Chris@16 251 static const char* function = "boost::math::quantile(const gamma_distribution<%1%>&, %1%)";
Chris@16 252
Chris@16 253 RealType shape = c.dist.shape();
Chris@16 254 RealType scale = c.dist.scale();
Chris@16 255
Chris@16 256 RealType result = 0;
Chris@16 257 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
Chris@16 258 return result;
Chris@16 259 if(false == detail::check_inverse_gamma_x(function, c.param, &result, Policy()))
Chris@16 260 return result;
Chris@16 261
Chris@16 262 if(c.param == 0)
Chris@16 263 return 1; // Avoid division by zero
Chris@16 264
Chris@16 265 //result = 1. - gamma_q(shape, c.param / scale, Policy());
Chris@16 266 result = gamma_p(shape, scale/c.param, Policy());
Chris@16 267 return result;
Chris@16 268 }
Chris@16 269
Chris@16 270 template <class RealType, class Policy>
Chris@16 271 inline RealType quantile(const complemented2_type<inverse_gamma_distribution<RealType, Policy>, RealType>& c)
Chris@16 272 {
Chris@16 273 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 274
Chris@16 275 static const char* function = "boost::math::quantile(const inverse_gamma_distribution<%1%>&, %1%)";
Chris@16 276
Chris@16 277 RealType shape = c.dist.shape();
Chris@16 278 RealType scale = c.dist.scale();
Chris@16 279 RealType q = c.param;
Chris@16 280
Chris@16 281 RealType result = 0;
Chris@16 282 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
Chris@16 283 return result;
Chris@16 284 if(false == detail::check_probability(function, q, &result, Policy()))
Chris@16 285 return result;
Chris@16 286
Chris@16 287 if(q == 0)
Chris@16 288 {
Chris@16 289 return policies::raise_overflow_error<RealType>(function, 0, Policy());
Chris@16 290 }
Chris@16 291 result = gamma_p_inv(shape, q, Policy());
Chris@16 292 if((result < 1) && (result * tools::max_value<RealType>() < scale))
Chris@16 293 return policies::raise_overflow_error<RealType, Policy>(function, "Value of random variable in inverse gamma distribution quantile is infinite.", Policy());
Chris@16 294 result = scale / result;
Chris@16 295 return result;
Chris@16 296 }
Chris@16 297
Chris@16 298 template <class RealType, class Policy>
Chris@16 299 inline RealType mean(const inverse_gamma_distribution<RealType, Policy>& dist)
Chris@16 300 {
Chris@16 301 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 302
Chris@16 303 static const char* function = "boost::math::mean(const inverse_gamma_distribution<%1%>&)";
Chris@16 304
Chris@16 305 RealType shape = dist.shape();
Chris@16 306 RealType scale = dist.scale();
Chris@16 307
Chris@16 308 RealType result = 0;
Chris@16 309
Chris@16 310 if(false == detail::check_scale(function, scale, &result, Policy()))
Chris@16 311 {
Chris@16 312 return result;
Chris@16 313 }
Chris@16 314 if((shape <= 1) || !(boost::math::isfinite)(shape))
Chris@16 315 {
Chris@16 316 result = policies::raise_domain_error<RealType>(
Chris@16 317 function,
Chris@16 318 "Shape parameter is %1%, but for a defined mean it must be > 1", shape, Policy());
Chris@16 319 return result;
Chris@16 320 }
Chris@16 321 result = scale / (shape - 1);
Chris@16 322 return result;
Chris@16 323 } // mean
Chris@16 324
Chris@16 325 template <class RealType, class Policy>
Chris@16 326 inline RealType variance(const inverse_gamma_distribution<RealType, Policy>& dist)
Chris@16 327 {
Chris@16 328 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 329
Chris@16 330 static const char* function = "boost::math::variance(const inverse_gamma_distribution<%1%>&)";
Chris@16 331
Chris@16 332 RealType shape = dist.shape();
Chris@16 333 RealType scale = dist.scale();
Chris@16 334
Chris@16 335 RealType result = 0;
Chris@16 336 if(false == detail::check_scale(function, scale, &result, Policy()))
Chris@16 337 {
Chris@16 338 return result;
Chris@16 339 }
Chris@16 340 if((shape <= 2) || !(boost::math::isfinite)(shape))
Chris@16 341 {
Chris@16 342 result = policies::raise_domain_error<RealType>(
Chris@16 343 function,
Chris@16 344 "Shape parameter is %1%, but for a defined variance it must be > 2", shape, Policy());
Chris@16 345 return result;
Chris@16 346 }
Chris@16 347 result = (scale * scale) / ((shape - 1) * (shape -1) * (shape -2));
Chris@16 348 return result;
Chris@16 349 }
Chris@16 350
Chris@16 351 template <class RealType, class Policy>
Chris@16 352 inline RealType mode(const inverse_gamma_distribution<RealType, Policy>& dist)
Chris@16 353 {
Chris@16 354 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 355
Chris@16 356 static const char* function = "boost::math::mode(const inverse_gamma_distribution<%1%>&)";
Chris@16 357
Chris@16 358 RealType shape = dist.shape();
Chris@16 359 RealType scale = dist.scale();
Chris@16 360
Chris@16 361 RealType result = 0;
Chris@16 362 if(false == detail::check_inverse_gamma(function, scale, shape, &result, Policy()))
Chris@16 363 {
Chris@16 364 return result;
Chris@16 365 }
Chris@16 366 // Only defined for shape >= 0, but is checked by check_inverse_gamma.
Chris@16 367 result = scale / (shape + 1);
Chris@16 368 return result;
Chris@16 369 }
Chris@16 370
Chris@16 371 //template <class RealType, class Policy>
Chris@16 372 //inline RealType median(const gamma_distribution<RealType, Policy>& dist)
Chris@16 373 //{ // Wikipedia does not define median,
Chris@16 374 // so rely on default definition quantile(0.5) in derived accessors.
Chris@16 375 // return result.
Chris@16 376 //}
Chris@16 377
Chris@16 378 template <class RealType, class Policy>
Chris@16 379 inline RealType skewness(const inverse_gamma_distribution<RealType, Policy>& dist)
Chris@16 380 {
Chris@16 381 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 382
Chris@16 383 static const char* function = "boost::math::skewness(const inverse_gamma_distribution<%1%>&)";
Chris@16 384
Chris@16 385 RealType shape = dist.shape();
Chris@16 386 RealType scale = dist.scale();
Chris@16 387 RealType result = 0;
Chris@16 388
Chris@16 389 if(false == detail::check_scale(function, scale, &result, Policy()))
Chris@16 390 {
Chris@16 391 return result;
Chris@16 392 }
Chris@16 393 if((shape <= 3) || !(boost::math::isfinite)(shape))
Chris@16 394 {
Chris@16 395 result = policies::raise_domain_error<RealType>(
Chris@16 396 function,
Chris@16 397 "Shape parameter is %1%, but for a defined skewness it must be > 3", shape, Policy());
Chris@16 398 return result;
Chris@16 399 }
Chris@16 400 result = (4 * sqrt(shape - 2) ) / (shape - 3);
Chris@16 401 return result;
Chris@16 402 }
Chris@16 403
Chris@16 404 template <class RealType, class Policy>
Chris@16 405 inline RealType kurtosis_excess(const inverse_gamma_distribution<RealType, Policy>& dist)
Chris@16 406 {
Chris@16 407 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 408
Chris@16 409 static const char* function = "boost::math::kurtosis_excess(const inverse_gamma_distribution<%1%>&)";
Chris@16 410
Chris@16 411 RealType shape = dist.shape();
Chris@16 412 RealType scale = dist.scale();
Chris@16 413
Chris@16 414 RealType result = 0;
Chris@16 415 if(false == detail::check_scale(function, scale, &result, Policy()))
Chris@16 416 {
Chris@16 417 return result;
Chris@16 418 }
Chris@16 419 if((shape <= 4) || !(boost::math::isfinite)(shape))
Chris@16 420 {
Chris@16 421 result = policies::raise_domain_error<RealType>(
Chris@16 422 function,
Chris@16 423 "Shape parameter is %1%, but for a defined kurtosis excess it must be > 4", shape, Policy());
Chris@16 424 return result;
Chris@16 425 }
Chris@16 426 result = (30 * shape - 66) / ((shape - 3) * (shape - 4));
Chris@16 427 return result;
Chris@16 428 }
Chris@16 429
Chris@16 430 template <class RealType, class Policy>
Chris@16 431 inline RealType kurtosis(const inverse_gamma_distribution<RealType, Policy>& dist)
Chris@16 432 {
Chris@16 433 static const char* function = "boost::math::kurtosis(const inverse_gamma_distribution<%1%>&)";
Chris@16 434 RealType shape = dist.shape();
Chris@16 435 RealType scale = dist.scale();
Chris@16 436
Chris@16 437 RealType result = 0;
Chris@16 438
Chris@16 439 if(false == detail::check_scale(function, scale, &result, Policy()))
Chris@16 440 {
Chris@16 441 return result;
Chris@16 442 }
Chris@16 443 if((shape <= 4) || !(boost::math::isfinite)(shape))
Chris@16 444 {
Chris@16 445 result = policies::raise_domain_error<RealType>(
Chris@16 446 function,
Chris@16 447 "Shape parameter is %1%, but for a defined kurtosis it must be > 4", shape, Policy());
Chris@16 448 return result;
Chris@16 449 }
Chris@16 450 return kurtosis_excess(dist) + 3;
Chris@16 451 }
Chris@16 452
Chris@16 453 } // namespace math
Chris@16 454 } // namespace boost
Chris@16 455
Chris@16 456 // This include must be at the end, *after* the accessors
Chris@16 457 // for this distribution have been defined, in order to
Chris@16 458 // keep compilers that support two-phase lookup happy.
Chris@16 459 #include <boost/math/distributions/detail/derived_accessors.hpp>
Chris@16 460
Chris@16 461 #endif // BOOST_STATS_INVERSE_GAMMA_HPP