annotate DEPENDENCIES/generic/include/boost/math/distributions/students_t.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Copyright John Maddock 2006.
Chris@16 2 // Copyright Paul A. Bristow 2006, 2012.
Chris@16 3 // Copyright Thomas Mang 2012.
Chris@16 4
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_STUDENTS_T_HPP
Chris@16 10 #define BOOST_STATS_STUDENTS_T_HPP
Chris@16 11
Chris@16 12 // http://en.wikipedia.org/wiki/Student%27s_t_distribution
Chris@16 13 // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3664.htm
Chris@16 14
Chris@16 15 #include <boost/math/distributions/fwd.hpp>
Chris@16 16 #include <boost/math/special_functions/beta.hpp> // for ibeta(a, b, x).
Chris@16 17 #include <boost/math/distributions/complement.hpp>
Chris@16 18 #include <boost/math/distributions/detail/common_error_handling.hpp>
Chris@16 19 #include <boost/math/distributions/normal.hpp>
Chris@16 20
Chris@16 21 #include <utility>
Chris@16 22
Chris@16 23 #ifdef BOOST_MSVC
Chris@16 24 # pragma warning(push)
Chris@16 25 # pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
Chris@16 26 #endif
Chris@16 27
Chris@16 28 namespace boost{ namespace math{
Chris@16 29
Chris@16 30 template <class RealType = double, class Policy = policies::policy<> >
Chris@16 31 class students_t_distribution
Chris@16 32 {
Chris@16 33 public:
Chris@16 34 typedef RealType value_type;
Chris@16 35 typedef Policy policy_type;
Chris@16 36
Chris@16 37 students_t_distribution(RealType df) : df_(df)
Chris@16 38 { // Constructor.
Chris@16 39 RealType result;
Chris@16 40 detail::check_df_gt0_to_inf( // Checks that df > 0 or df == inf.
Chris@16 41 "boost::math::students_t_distribution<%1%>::students_t_distribution", df_, &result, Policy());
Chris@16 42 } // students_t_distribution
Chris@16 43
Chris@16 44 RealType degrees_of_freedom()const
Chris@16 45 {
Chris@16 46 return df_;
Chris@16 47 }
Chris@16 48
Chris@16 49 // Parameter estimation:
Chris@16 50 static RealType find_degrees_of_freedom(
Chris@16 51 RealType difference_from_mean,
Chris@16 52 RealType alpha,
Chris@16 53 RealType beta,
Chris@16 54 RealType sd,
Chris@16 55 RealType hint = 100);
Chris@16 56
Chris@16 57 private:
Chris@16 58 // Data member:
Chris@16 59 RealType df_; // degrees of freedom is a real number or +infinity.
Chris@16 60 };
Chris@16 61
Chris@16 62 typedef students_t_distribution<double> students_t; // Convenience typedef for double version.
Chris@16 63
Chris@16 64 template <class RealType, class Policy>
Chris@16 65 inline const std::pair<RealType, RealType> range(const students_t_distribution<RealType, Policy>& /*dist*/)
Chris@16 66 { // Range of permissible values for random variable x.
Chris@16 67 // NOT including infinity.
Chris@16 68 using boost::math::tools::max_value;
Chris@16 69 return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
Chris@16 70 }
Chris@16 71
Chris@16 72 template <class RealType, class Policy>
Chris@16 73 inline const std::pair<RealType, RealType> support(const students_t_distribution<RealType, Policy>& /*dist*/)
Chris@16 74 { // Range of supported values for random variable x.
Chris@16 75 // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
Chris@16 76 using boost::math::tools::max_value;
Chris@16 77 return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
Chris@16 78 }
Chris@16 79
Chris@16 80 template <class RealType, class Policy>
Chris@16 81 inline RealType pdf(const students_t_distribution<RealType, Policy>& dist, const RealType& x)
Chris@16 82 {
Chris@16 83 BOOST_FPU_EXCEPTION_GUARD
Chris@16 84 BOOST_MATH_STD_USING // for ADL of std functions.
Chris@16 85
Chris@16 86 RealType error_result;
Chris@16 87 if(false == detail::check_x(
Chris@16 88 "boost::math::pdf(const students_t_distribution<%1%>&, %1%)", x, &error_result, Policy()))
Chris@16 89 return error_result;
Chris@16 90 RealType df = dist.degrees_of_freedom();
Chris@16 91 if(false == detail::check_df_gt0_to_inf( // Check that df > 0 or == +infinity.
Chris@16 92 "boost::math::pdf(const students_t_distribution<%1%>&, %1%)", df, &error_result, Policy()))
Chris@16 93 return error_result;
Chris@16 94
Chris@16 95 RealType result;
Chris@16 96 if ((boost::math::isinf)(x))
Chris@16 97 { // +infinity.
Chris@16 98 normal_distribution<RealType, Policy> n(0, 1);
Chris@16 99 result = pdf(n, x);
Chris@16 100 return result;
Chris@16 101 }
Chris@16 102 RealType limit = policies::get_epsilon<RealType, Policy>();
Chris@16 103 // Use policies so that if policy requests lower precision,
Chris@16 104 // then get the normal distribution approximation earlier.
Chris@16 105 limit = static_cast<RealType>(1) / limit; // 1/eps
Chris@16 106 // for 64-bit double 1/eps = 4503599627370496
Chris@16 107 if (df > limit)
Chris@16 108 { // Special case for really big degrees_of_freedom > 1 / eps
Chris@16 109 // - use normal distribution which is much faster and more accurate.
Chris@16 110 normal_distribution<RealType, Policy> n(0, 1);
Chris@16 111 result = pdf(n, x);
Chris@16 112 }
Chris@16 113 else
Chris@16 114 { //
Chris@16 115 RealType basem1 = x * x / df;
Chris@16 116 if(basem1 < 0.125)
Chris@16 117 {
Chris@16 118 result = exp(-boost::math::log1p(basem1, Policy()) * (1+df) / 2);
Chris@16 119 }
Chris@16 120 else
Chris@16 121 {
Chris@16 122 result = pow(1 / (1 + basem1), (df + 1) / 2);
Chris@16 123 }
Chris@16 124 result /= sqrt(df) * boost::math::beta(df / 2, RealType(0.5f), Policy());
Chris@16 125 }
Chris@16 126 return result;
Chris@16 127 } // pdf
Chris@16 128
Chris@16 129 template <class RealType, class Policy>
Chris@16 130 inline RealType cdf(const students_t_distribution<RealType, Policy>& dist, const RealType& x)
Chris@16 131 {
Chris@16 132 RealType error_result;
Chris@16 133 if(false == detail::check_x(
Chris@16 134 "boost::math::pdf(const students_t_distribution<%1%>&, %1%)", x, &error_result, Policy()))
Chris@16 135 return error_result;
Chris@16 136 RealType df = dist.degrees_of_freedom();
Chris@16 137 // Error check:
Chris@16 138
Chris@16 139 if(false == detail::check_df_gt0_to_inf( // Check that df > 0 or == +infinity.
Chris@16 140 "boost::math::cdf(const students_t_distribution<%1%>&, %1%)", df, &error_result, Policy()))
Chris@16 141 return error_result;
Chris@16 142
Chris@16 143 if (x == 0)
Chris@16 144 { // Special case with exact result.
Chris@16 145 return static_cast<RealType>(0.5);
Chris@16 146 }
Chris@16 147 if ((boost::math::isinf)(x))
Chris@16 148 { // +infinity.
Chris@16 149 normal_distribution<RealType, Policy> n(0, 1);
Chris@16 150 RealType result = cdf(n, x);
Chris@16 151 return result;
Chris@16 152 }
Chris@16 153 RealType limit = policies::get_epsilon<RealType, Policy>();
Chris@16 154 // Use policies so that if policy requests lower precision,
Chris@16 155 // then get the normal distribution approximation earlier.
Chris@16 156 limit = static_cast<RealType>(1) / limit; // 1/eps
Chris@16 157 // for 64-bit double 1/eps = 4503599627370496
Chris@16 158 if (df > limit)
Chris@16 159 { // Special case for really big degrees_of_freedom > 1 / eps (perhaps infinite?)
Chris@16 160 // - use normal distribution which is much faster and more accurate.
Chris@16 161 normal_distribution<RealType, Policy> n(0, 1);
Chris@16 162 RealType result = cdf(n, x);
Chris@16 163 return result;
Chris@16 164 }
Chris@16 165 else
Chris@16 166 { // normal df case.
Chris@16 167 //
Chris@16 168 // Calculate probability of Student's t using the incomplete beta function.
Chris@16 169 // probability = ibeta(degrees_of_freedom / 2, 1/2, degrees_of_freedom / (degrees_of_freedom + t*t))
Chris@16 170 //
Chris@16 171 // However when t is small compared to the degrees of freedom, that formula
Chris@16 172 // suffers from rounding error, use the identity formula to work around
Chris@16 173 // the problem:
Chris@16 174 //
Chris@16 175 // I[x](a,b) = 1 - I[1-x](b,a)
Chris@16 176 //
Chris@16 177 // and:
Chris@16 178 //
Chris@16 179 // x = df / (df + t^2)
Chris@16 180 //
Chris@16 181 // so:
Chris@16 182 //
Chris@16 183 // 1 - x = t^2 / (df + t^2)
Chris@16 184 //
Chris@16 185 RealType x2 = x * x;
Chris@16 186 RealType probability;
Chris@16 187 if(df > 2 * x2)
Chris@16 188 {
Chris@16 189 RealType z = x2 / (df + x2);
Chris@16 190 probability = ibetac(static_cast<RealType>(0.5), df / 2, z, Policy()) / 2;
Chris@16 191 }
Chris@16 192 else
Chris@16 193 {
Chris@16 194 RealType z = df / (df + x2);
Chris@16 195 probability = ibeta(df / 2, static_cast<RealType>(0.5), z, Policy()) / 2;
Chris@16 196 }
Chris@16 197 return (x > 0 ? 1 - probability : probability);
Chris@16 198 }
Chris@16 199 } // cdf
Chris@16 200
Chris@16 201 template <class RealType, class Policy>
Chris@16 202 inline RealType quantile(const students_t_distribution<RealType, Policy>& dist, const RealType& p)
Chris@16 203 {
Chris@16 204 BOOST_MATH_STD_USING // for ADL of std functions
Chris@16 205 //
Chris@16 206 // Obtain parameters:
Chris@16 207 RealType probability = p;
Chris@16 208
Chris@16 209 // Check for domain errors:
Chris@16 210 RealType df = dist.degrees_of_freedom();
Chris@16 211 static const char* function = "boost::math::quantile(const students_t_distribution<%1%>&, %1%)";
Chris@16 212 RealType error_result;
Chris@16 213 if(false == (detail::check_df_gt0_to_inf( // Check that df > 0 or == +infinity.
Chris@16 214 function, df, &error_result, Policy())
Chris@16 215 && detail::check_probability(function, probability, &error_result, Policy())))
Chris@16 216 return error_result;
Chris@16 217 // Special cases, regardless of degrees_of_freedom.
Chris@16 218 if (probability == 0)
Chris@16 219 return -policies::raise_overflow_error<RealType>(function, 0, Policy());
Chris@16 220 if (probability == 1)
Chris@16 221 return policies::raise_overflow_error<RealType>(function, 0, Policy());
Chris@16 222 if (probability == static_cast<RealType>(0.5))
Chris@16 223 return 0; //
Chris@16 224 //
Chris@16 225 #if 0
Chris@16 226 // This next block is disabled in favour of a faster method than
Chris@16 227 // incomplete beta inverse, but code retained for future reference:
Chris@16 228 //
Chris@16 229 // Calculate quantile of Student's t using the incomplete beta function inverse:
Chris@16 230 //
Chris@16 231 probability = (probability > 0.5) ? 1 - probability : probability;
Chris@16 232 RealType t, x, y;
Chris@16 233 x = ibeta_inv(degrees_of_freedom / 2, RealType(0.5), 2 * probability, &y);
Chris@16 234 if(degrees_of_freedom * y > tools::max_value<RealType>() * x)
Chris@16 235 t = tools::overflow_error<RealType>(function);
Chris@16 236 else
Chris@16 237 t = sqrt(degrees_of_freedom * y / x);
Chris@16 238 //
Chris@16 239 // Figure out sign based on the size of p:
Chris@16 240 //
Chris@16 241 if(p < 0.5)
Chris@16 242 t = -t;
Chris@16 243
Chris@16 244 return t;
Chris@16 245 #endif
Chris@16 246 //
Chris@16 247 // Depending on how many digits RealType has, this may forward
Chris@16 248 // to the incomplete beta inverse as above. Otherwise uses a
Chris@16 249 // faster method that is accurate to ~15 digits everywhere
Chris@16 250 // and a couple of epsilon at double precision and in the central
Chris@16 251 // region where most use cases will occur...
Chris@16 252 //
Chris@16 253 return boost::math::detail::fast_students_t_quantile(df, probability, Policy());
Chris@16 254 } // quantile
Chris@16 255
Chris@16 256 template <class RealType, class Policy>
Chris@16 257 inline RealType cdf(const complemented2_type<students_t_distribution<RealType, Policy>, RealType>& c)
Chris@16 258 {
Chris@16 259 return cdf(c.dist, -c.param);
Chris@16 260 }
Chris@16 261
Chris@16 262 template <class RealType, class Policy>
Chris@16 263 inline RealType quantile(const complemented2_type<students_t_distribution<RealType, Policy>, RealType>& c)
Chris@16 264 {
Chris@16 265 return -quantile(c.dist, c.param);
Chris@16 266 }
Chris@16 267
Chris@16 268 //
Chris@16 269 // Parameter estimation follows:
Chris@16 270 //
Chris@16 271 namespace detail{
Chris@16 272 //
Chris@16 273 // Functors for finding degrees of freedom:
Chris@16 274 //
Chris@16 275 template <class RealType, class Policy>
Chris@16 276 struct sample_size_func
Chris@16 277 {
Chris@16 278 sample_size_func(RealType a, RealType b, RealType s, RealType d)
Chris@16 279 : alpha(a), beta(b), ratio(s*s/(d*d)) {}
Chris@16 280
Chris@16 281 RealType operator()(const RealType& df)
Chris@16 282 {
Chris@16 283 if(df <= tools::min_value<RealType>())
Chris@16 284 { //
Chris@16 285 return 1;
Chris@16 286 }
Chris@16 287 students_t_distribution<RealType, Policy> t(df);
Chris@16 288 RealType qa = quantile(complement(t, alpha));
Chris@16 289 RealType qb = quantile(complement(t, beta));
Chris@16 290 qa += qb;
Chris@16 291 qa *= qa;
Chris@16 292 qa *= ratio;
Chris@16 293 qa -= (df + 1);
Chris@16 294 return qa;
Chris@16 295 }
Chris@16 296 RealType alpha, beta, ratio;
Chris@16 297 };
Chris@16 298
Chris@16 299 } // namespace detail
Chris@16 300
Chris@16 301 template <class RealType, class Policy>
Chris@16 302 RealType students_t_distribution<RealType, Policy>::find_degrees_of_freedom(
Chris@16 303 RealType difference_from_mean,
Chris@16 304 RealType alpha,
Chris@16 305 RealType beta,
Chris@16 306 RealType sd,
Chris@16 307 RealType hint)
Chris@16 308 {
Chris@16 309 static const char* function = "boost::math::students_t_distribution<%1%>::find_degrees_of_freedom";
Chris@16 310 //
Chris@16 311 // Check for domain errors:
Chris@16 312 //
Chris@16 313 RealType error_result;
Chris@16 314 if(false == detail::check_probability(
Chris@16 315 function, alpha, &error_result, Policy())
Chris@16 316 && detail::check_probability(function, beta, &error_result, Policy()))
Chris@16 317 return error_result;
Chris@16 318
Chris@16 319 if(hint <= 0)
Chris@16 320 hint = 1;
Chris@16 321
Chris@16 322 detail::sample_size_func<RealType, Policy> f(alpha, beta, sd, difference_from_mean);
Chris@16 323 tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
Chris@16 324 boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
Chris@16 325 std::pair<RealType, RealType> r = tools::bracket_and_solve_root(f, hint, RealType(2), false, tol, max_iter, Policy());
Chris@16 326 RealType result = r.first + (r.second - r.first) / 2;
Chris@16 327 if(max_iter >= policies::get_max_root_iterations<Policy>())
Chris@16 328 {
Chris@101 329 return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
Chris@16 330 " either there is no answer to how many degrees of freedom are required"
Chris@16 331 " or the answer is infinite. Current best guess is %1%", result, Policy());
Chris@16 332 }
Chris@16 333 return result;
Chris@16 334 }
Chris@16 335
Chris@16 336 template <class RealType, class Policy>
Chris@16 337 inline RealType mode(const students_t_distribution<RealType, Policy>& /*dist*/)
Chris@16 338 {
Chris@16 339 // Assume no checks on degrees of freedom are useful (unlike mean).
Chris@16 340 return 0; // Always zero by definition.
Chris@16 341 }
Chris@16 342
Chris@16 343 template <class RealType, class Policy>
Chris@16 344 inline RealType median(const students_t_distribution<RealType, Policy>& /*dist*/)
Chris@16 345 {
Chris@16 346 // Assume no checks on degrees of freedom are useful (unlike mean).
Chris@16 347 return 0; // Always zero by definition.
Chris@16 348 }
Chris@16 349
Chris@16 350 // See section 5.1 on moments at http://en.wikipedia.org/wiki/Student%27s_t-distribution
Chris@16 351
Chris@16 352 template <class RealType, class Policy>
Chris@16 353 inline RealType mean(const students_t_distribution<RealType, Policy>& dist)
Chris@16 354 { // Revised for https://svn.boost.org/trac/boost/ticket/7177
Chris@16 355 RealType df = dist.degrees_of_freedom();
Chris@16 356 if(((boost::math::isnan)(df)) || (df <= 1) )
Chris@16 357 { // mean is undefined for moment <= 1!
Chris@101 358 return policies::raise_domain_error<RealType>(
Chris@16 359 "boost::math::mean(students_t_distribution<%1%> const&, %1%)",
Chris@16 360 "Mean is undefined for degrees of freedom < 1 but got %1%.", df, Policy());
Chris@16 361 return std::numeric_limits<RealType>::quiet_NaN();
Chris@16 362 }
Chris@16 363 return 0;
Chris@16 364 } // mean
Chris@16 365
Chris@16 366 template <class RealType, class Policy>
Chris@16 367 inline RealType variance(const students_t_distribution<RealType, Policy>& dist)
Chris@16 368 { // http://en.wikipedia.org/wiki/Student%27s_t-distribution
Chris@16 369 // Revised for https://svn.boost.org/trac/boost/ticket/7177
Chris@16 370 RealType df = dist.degrees_of_freedom();
Chris@16 371 if ((boost::math::isnan)(df) || (df <= 2))
Chris@16 372 { // NaN or undefined for <= 2.
Chris@101 373 return policies::raise_domain_error<RealType>(
Chris@16 374 "boost::math::variance(students_t_distribution<%1%> const&, %1%)",
Chris@16 375 "variance is undefined for degrees of freedom <= 2, but got %1%.",
Chris@16 376 df, Policy());
Chris@16 377 return std::numeric_limits<RealType>::quiet_NaN(); // Undefined.
Chris@16 378 }
Chris@16 379 if ((boost::math::isinf)(df))
Chris@16 380 { // +infinity.
Chris@16 381 return 1;
Chris@16 382 }
Chris@16 383 RealType limit = policies::get_epsilon<RealType, Policy>();
Chris@16 384 // Use policies so that if policy requests lower precision,
Chris@16 385 // then get the normal distribution approximation earlier.
Chris@16 386 limit = static_cast<RealType>(1) / limit; // 1/eps
Chris@16 387 // for 64-bit double 1/eps = 4503599627370496
Chris@16 388 if (df > limit)
Chris@16 389 { // Special case for really big degrees_of_freedom > 1 / eps.
Chris@16 390 return 1;
Chris@16 391 }
Chris@16 392 else
Chris@16 393 {
Chris@16 394 return df / (df - 2);
Chris@16 395 }
Chris@16 396 } // variance
Chris@16 397
Chris@16 398 template <class RealType, class Policy>
Chris@16 399 inline RealType skewness(const students_t_distribution<RealType, Policy>& dist)
Chris@16 400 {
Chris@16 401 RealType df = dist.degrees_of_freedom();
Chris@16 402 if( ((boost::math::isnan)(df)) || (dist.degrees_of_freedom() <= 3))
Chris@16 403 { // Undefined for moment k = 3.
Chris@101 404 return policies::raise_domain_error<RealType>(
Chris@16 405 "boost::math::skewness(students_t_distribution<%1%> const&, %1%)",
Chris@16 406 "Skewness is undefined for degrees of freedom <= 3, but got %1%.",
Chris@16 407 dist.degrees_of_freedom(), Policy());
Chris@16 408 return std::numeric_limits<RealType>::quiet_NaN();
Chris@16 409 }
Chris@16 410 return 0; // For all valid df, including infinity.
Chris@16 411 } // skewness
Chris@16 412
Chris@16 413 template <class RealType, class Policy>
Chris@16 414 inline RealType kurtosis(const students_t_distribution<RealType, Policy>& dist)
Chris@16 415 {
Chris@16 416 RealType df = dist.degrees_of_freedom();
Chris@16 417 if(((boost::math::isnan)(df)) || (df <= 4))
Chris@16 418 { // Undefined or infinity for moment k = 4.
Chris@101 419 return policies::raise_domain_error<RealType>(
Chris@16 420 "boost::math::kurtosis(students_t_distribution<%1%> const&, %1%)",
Chris@16 421 "Kurtosis is undefined for degrees of freedom <= 4, but got %1%.",
Chris@16 422 df, Policy());
Chris@16 423 return std::numeric_limits<RealType>::quiet_NaN(); // Undefined.
Chris@16 424 }
Chris@16 425 if ((boost::math::isinf)(df))
Chris@16 426 { // +infinity.
Chris@16 427 return 3;
Chris@16 428 }
Chris@16 429 RealType limit = policies::get_epsilon<RealType, Policy>();
Chris@16 430 // Use policies so that if policy requests lower precision,
Chris@16 431 // then get the normal distribution approximation earlier.
Chris@16 432 limit = static_cast<RealType>(1) / limit; // 1/eps
Chris@16 433 // for 64-bit double 1/eps = 4503599627370496
Chris@16 434 if (df > limit)
Chris@16 435 { // Special case for really big degrees_of_freedom > 1 / eps.
Chris@16 436 return 3;
Chris@16 437 }
Chris@16 438 else
Chris@16 439 {
Chris@16 440 //return 3 * (df - 2) / (df - 4); re-arranged to
Chris@16 441 return 6 / (df - 4) + 3;
Chris@16 442 }
Chris@16 443 } // kurtosis
Chris@16 444
Chris@16 445 template <class RealType, class Policy>
Chris@16 446 inline RealType kurtosis_excess(const students_t_distribution<RealType, Policy>& dist)
Chris@16 447 {
Chris@16 448 // see http://mathworld.wolfram.com/Kurtosis.html
Chris@16 449
Chris@16 450 RealType df = dist.degrees_of_freedom();
Chris@16 451 if(((boost::math::isnan)(df)) || (df <= 4))
Chris@16 452 { // Undefined or infinity for moment k = 4.
Chris@101 453 return policies::raise_domain_error<RealType>(
Chris@16 454 "boost::math::kurtosis_excess(students_t_distribution<%1%> const&, %1%)",
Chris@16 455 "Kurtosis_excess is undefined for degrees of freedom <= 4, but got %1%.",
Chris@16 456 df, Policy());
Chris@16 457 return std::numeric_limits<RealType>::quiet_NaN(); // Undefined.
Chris@16 458 }
Chris@16 459 if ((boost::math::isinf)(df))
Chris@16 460 { // +infinity.
Chris@16 461 return 0;
Chris@16 462 }
Chris@16 463 RealType limit = policies::get_epsilon<RealType, Policy>();
Chris@16 464 // Use policies so that if policy requests lower precision,
Chris@16 465 // then get the normal distribution approximation earlier.
Chris@16 466 limit = static_cast<RealType>(1) / limit; // 1/eps
Chris@16 467 // for 64-bit double 1/eps = 4503599627370496
Chris@16 468 if (df > limit)
Chris@16 469 { // Special case for really big degrees_of_freedom > 1 / eps.
Chris@16 470 return 0;
Chris@16 471 }
Chris@16 472 else
Chris@16 473 {
Chris@16 474 return 6 / (df - 4);
Chris@16 475 }
Chris@16 476 }
Chris@16 477
Chris@16 478 } // namespace math
Chris@16 479 } // namespace boost
Chris@16 480
Chris@16 481 #ifdef BOOST_MSVC
Chris@16 482 # pragma warning(pop)
Chris@16 483 #endif
Chris@16 484
Chris@16 485 // This include must be at the end, *after* the accessors
Chris@16 486 // for this distribution have been defined, in order to
Chris@16 487 // keep compilers that support two-phase lookup happy.
Chris@16 488 #include <boost/math/distributions/detail/derived_accessors.hpp>
Chris@16 489
Chris@16 490 #endif // BOOST_STATS_STUDENTS_T_HPP