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