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 / non_central_t.hpp @ 160:cff480c41f97
History | View | Annotate | Download (48 KB)
| 1 |
// boost\math\distributions\non_central_t.hpp
|
|---|---|
| 2 |
|
| 3 |
// Copyright John Maddock 2008.
|
| 4 |
|
| 5 |
// Use, modification and distribution are subject to the
|
| 6 |
// Boost Software License, Version 1.0.
|
| 7 |
// (See accompanying file LICENSE_1_0.txt
|
| 8 |
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
| 9 |
|
| 10 |
#ifndef BOOST_MATH_SPECIAL_NON_CENTRAL_T_HPP
|
| 11 |
#define BOOST_MATH_SPECIAL_NON_CENTRAL_T_HPP
|
| 12 |
|
| 13 |
#include <boost/math/distributions/fwd.hpp> |
| 14 |
#include <boost/math/distributions/non_central_beta.hpp> // for nc beta |
| 15 |
#include <boost/math/distributions/normal.hpp> // for normal CDF and quantile |
| 16 |
#include <boost/math/distributions/students_t.hpp> |
| 17 |
#include <boost/math/distributions/detail/generic_quantile.hpp> // quantile |
| 18 |
|
| 19 |
namespace boost
|
| 20 |
{
|
| 21 |
namespace math
|
| 22 |
{
|
| 23 |
|
| 24 |
template <class RealType, class Policy> |
| 25 |
class non_central_t_distribution; |
| 26 |
|
| 27 |
namespace detail{
|
| 28 |
|
| 29 |
template <class T, class Policy> |
| 30 |
T non_central_t2_p(T v, T delta, T x, T y, const Policy& pol, T init_val)
|
| 31 |
{
|
| 32 |
BOOST_MATH_STD_USING |
| 33 |
//
|
| 34 |
// Variables come first:
|
| 35 |
//
|
| 36 |
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); |
| 37 |
T errtol = policies::get_epsilon<T, Policy>(); |
| 38 |
T d2 = delta * delta / 2;
|
| 39 |
//
|
| 40 |
// k is the starting point for iteration, and is the
|
| 41 |
// maximum of the poisson weighting term, we don't
|
| 42 |
// ever allow k == 0 as this can lead to catastrophic
|
| 43 |
// cancellation errors later (test case is v = 1621286869049072.3
|
| 44 |
// delta = 0.16212868690490723, x = 0.86987415482475994).
|
| 45 |
//
|
| 46 |
int k = itrunc(d2);
|
| 47 |
T pois; |
| 48 |
if(k == 0) k = 1; |
| 49 |
// Starting Poisson weight:
|
| 50 |
pois = gamma_p_derivative(T(k+1), d2, pol)
|
| 51 |
* tgamma_delta_ratio(T(k + 1), T(0.5f)) |
| 52 |
* delta / constants::root_two<T>(); |
| 53 |
if(pois == 0) |
| 54 |
return init_val;
|
| 55 |
T xterm, beta; |
| 56 |
// Recurrance & starting beta terms:
|
| 57 |
beta = x < y |
| 58 |
? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, false, true, &xterm) |
| 59 |
: detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, true, true, &xterm); |
| 60 |
xterm *= y / (v / 2 + k);
|
| 61 |
T poisf(pois), betaf(beta), xtermf(xterm); |
| 62 |
T sum = init_val; |
| 63 |
if((xterm == 0) && (beta == 0)) |
| 64 |
return init_val;
|
| 65 |
|
| 66 |
//
|
| 67 |
// Backwards recursion first, this is the stable
|
| 68 |
// direction for recursion:
|
| 69 |
//
|
| 70 |
boost::uintmax_t count = 0;
|
| 71 |
T last_term = 0;
|
| 72 |
for(int i = k; i >= 0; --i) |
| 73 |
{
|
| 74 |
T term = beta * pois; |
| 75 |
sum += term; |
| 76 |
// Don't terminate on first term in case we "fixed" k above:
|
| 77 |
if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol)
|
| 78 |
break;
|
| 79 |
last_term = term; |
| 80 |
pois *= (i + 0.5f) / d2; |
| 81 |
beta += xterm; |
| 82 |
xterm *= (i) / (x * (v / 2 + i - 1)); |
| 83 |
++count; |
| 84 |
} |
| 85 |
last_term = 0;
|
| 86 |
for(int i = k + 1; ; ++i) |
| 87 |
{
|
| 88 |
poisf *= d2 / (i + 0.5f); |
| 89 |
xtermf *= (x * (v / 2 + i - 1)) / (i); |
| 90 |
betaf -= xtermf; |
| 91 |
T term = poisf * betaf; |
| 92 |
sum += term; |
| 93 |
if((fabs(last_term) >= fabs(term)) && (fabs(term/sum) < errtol))
|
| 94 |
break;
|
| 95 |
last_term = term; |
| 96 |
++count; |
| 97 |
if(count > max_iter)
|
| 98 |
{
|
| 99 |
return policies::raise_evaluation_error(
|
| 100 |
"cdf(non_central_t_distribution<%1%>, %1%)",
|
| 101 |
"Series did not converge, closest value was %1%", sum, pol);
|
| 102 |
} |
| 103 |
} |
| 104 |
return sum;
|
| 105 |
} |
| 106 |
|
| 107 |
template <class T, class Policy> |
| 108 |
T non_central_t2_q(T v, T delta, T x, T y, const Policy& pol, T init_val)
|
| 109 |
{
|
| 110 |
BOOST_MATH_STD_USING |
| 111 |
//
|
| 112 |
// Variables come first:
|
| 113 |
//
|
| 114 |
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); |
| 115 |
T errtol = boost::math::policies::get_epsilon<T, Policy>(); |
| 116 |
T d2 = delta * delta / 2;
|
| 117 |
//
|
| 118 |
// k is the starting point for iteration, and is the
|
| 119 |
// maximum of the poisson weighting term, we don't allow
|
| 120 |
// k == 0 as this can cause catastrophic cancellation errors
|
| 121 |
// (test case is v = 561908036470413.25, delta = 0.056190803647041321,
|
| 122 |
// x = 1.6155232703966216):
|
| 123 |
//
|
| 124 |
int k = itrunc(d2);
|
| 125 |
if(k == 0) k = 1; |
| 126 |
// Starting Poisson weight:
|
| 127 |
T pois; |
| 128 |
if((k < (int)(max_factorial<T>::value)) && (d2 < tools::log_max_value<T>()) && (log(d2) * k < tools::log_max_value<T>())) |
| 129 |
{
|
| 130 |
//
|
| 131 |
// For small k we can optimise this calculation by using
|
| 132 |
// a simpler reduced formula:
|
| 133 |
//
|
| 134 |
pois = exp(-d2); |
| 135 |
pois *= pow(d2, static_cast<T>(k));
|
| 136 |
pois /= boost::math::tgamma(T(k + 1 + 0.5), pol); |
| 137 |
pois *= delta / constants::root_two<T>(); |
| 138 |
} |
| 139 |
else
|
| 140 |
{
|
| 141 |
pois = gamma_p_derivative(T(k+1), d2, pol)
|
| 142 |
* tgamma_delta_ratio(T(k + 1), T(0.5f)) |
| 143 |
* delta / constants::root_two<T>(); |
| 144 |
} |
| 145 |
if(pois == 0) |
| 146 |
return init_val;
|
| 147 |
// Recurance term:
|
| 148 |
T xterm; |
| 149 |
T beta; |
| 150 |
// Starting beta term:
|
| 151 |
if(k != 0) |
| 152 |
{
|
| 153 |
beta = x < y |
| 154 |
? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, true, true, &xterm) |
| 155 |
: detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, false, true, &xterm); |
| 156 |
|
| 157 |
xterm *= y / (v / 2 + k);
|
| 158 |
} |
| 159 |
else
|
| 160 |
{
|
| 161 |
beta = pow(y, v / 2);
|
| 162 |
xterm = beta; |
| 163 |
} |
| 164 |
T poisf(pois), betaf(beta), xtermf(xterm); |
| 165 |
T sum = init_val; |
| 166 |
if((xterm == 0) && (beta == 0)) |
| 167 |
return init_val;
|
| 168 |
|
| 169 |
//
|
| 170 |
// Fused forward and backwards recursion:
|
| 171 |
//
|
| 172 |
boost::uintmax_t count = 0;
|
| 173 |
T last_term = 0;
|
| 174 |
for(int i = k + 1, j = k; ; ++i, --j) |
| 175 |
{
|
| 176 |
poisf *= d2 / (i + 0.5f); |
| 177 |
xtermf *= (x * (v / 2 + i - 1)) / (i); |
| 178 |
betaf += xtermf; |
| 179 |
T term = poisf * betaf; |
| 180 |
|
| 181 |
if(j >= 0) |
| 182 |
{
|
| 183 |
term += beta * pois; |
| 184 |
pois *= (j + 0.5f) / d2; |
| 185 |
beta -= xterm; |
| 186 |
xterm *= (j) / (x * (v / 2 + j - 1)); |
| 187 |
} |
| 188 |
|
| 189 |
sum += term; |
| 190 |
// Don't terminate on first term in case we "fixed" the value of k above:
|
| 191 |
if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol)
|
| 192 |
break;
|
| 193 |
last_term = term; |
| 194 |
if(count > max_iter)
|
| 195 |
{
|
| 196 |
return policies::raise_evaluation_error(
|
| 197 |
"cdf(non_central_t_distribution<%1%>, %1%)",
|
| 198 |
"Series did not converge, closest value was %1%", sum, pol);
|
| 199 |
} |
| 200 |
++count; |
| 201 |
} |
| 202 |
return sum;
|
| 203 |
} |
| 204 |
|
| 205 |
template <class T, class Policy> |
| 206 |
T non_central_t_cdf(T v, T delta, T t, bool invert, const Policy& pol) |
| 207 |
{
|
| 208 |
BOOST_MATH_STD_USING |
| 209 |
if ((boost::math::isinf)(v))
|
| 210 |
{ // Infinite degrees of freedom, so use normal distribution located at delta.
|
| 211 |
normal_distribution<T, Policy> n(delta, 1);
|
| 212 |
return cdf(n, t);
|
| 213 |
} |
| 214 |
//
|
| 215 |
// Otherwise, for t < 0 we have to use the reflection formula:
|
| 216 |
if(t < 0) |
| 217 |
{
|
| 218 |
t = -t; |
| 219 |
delta = -delta; |
| 220 |
invert = !invert; |
| 221 |
} |
| 222 |
if(fabs(delta / (4 * v)) < policies::get_epsilon<T, Policy>()) |
| 223 |
{
|
| 224 |
// Approximate with a Student's T centred on delta,
|
| 225 |
// the crossover point is based on eq 2.6 from
|
| 226 |
// "A Comparison of Approximations To Percentiles of the
|
| 227 |
// Noncentral t-Distribution". H. Sahai and M. M. Ojeda,
|
| 228 |
// Revista Investigacion Operacional Vol 21, No 2, 2000.
|
| 229 |
// Original sources referenced in the above are:
|
| 230 |
// "Some Approximations to the Percentage Points of the Noncentral
|
| 231 |
// t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31.
|
| 232 |
// "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and
|
| 233 |
// N. Balkrishnan. 1995. John Wiley and Sons New York.
|
| 234 |
T result = cdf(students_t_distribution<T, Policy>(v), t - delta); |
| 235 |
return invert ? 1 - result : result; |
| 236 |
} |
| 237 |
//
|
| 238 |
// x and y are the corresponding random
|
| 239 |
// variables for the noncentral beta distribution,
|
| 240 |
// with y = 1 - x:
|
| 241 |
//
|
| 242 |
T x = t * t / (v + t * t); |
| 243 |
T y = v / (v + t * t); |
| 244 |
T d2 = delta * delta; |
| 245 |
T a = 0.5f; |
| 246 |
T b = v / 2;
|
| 247 |
T c = a + b + d2 / 2;
|
| 248 |
//
|
| 249 |
// Crossover point for calculating p or q is the same
|
| 250 |
// as for the noncentral beta:
|
| 251 |
//
|
| 252 |
T cross = 1 - (b / c) * (1 + d2 / (2 * c * c)); |
| 253 |
T result; |
| 254 |
if(x < cross)
|
| 255 |
{
|
| 256 |
//
|
| 257 |
// Calculate p:
|
| 258 |
//
|
| 259 |
if(x != 0) |
| 260 |
{
|
| 261 |
result = non_central_beta_p(a, b, d2, x, y, pol); |
| 262 |
result = non_central_t2_p(v, delta, x, y, pol, result); |
| 263 |
result /= 2;
|
| 264 |
} |
| 265 |
else
|
| 266 |
result = 0;
|
| 267 |
result += cdf(boost::math::normal_distribution<T, Policy>(), -delta); |
| 268 |
} |
| 269 |
else
|
| 270 |
{
|
| 271 |
//
|
| 272 |
// Calculate q:
|
| 273 |
//
|
| 274 |
invert = !invert; |
| 275 |
if(x != 0) |
| 276 |
{
|
| 277 |
result = non_central_beta_q(a, b, d2, x, y, pol); |
| 278 |
result = non_central_t2_q(v, delta, x, y, pol, result); |
| 279 |
result /= 2;
|
| 280 |
} |
| 281 |
else // x == 0 |
| 282 |
result = cdf(complement(boost::math::normal_distribution<T, Policy>(), -delta)); |
| 283 |
} |
| 284 |
if(invert)
|
| 285 |
result = 1 - result;
|
| 286 |
return result;
|
| 287 |
} |
| 288 |
|
| 289 |
template <class T, class Policy> |
| 290 |
T non_central_t_quantile(const char* function, T v, T delta, T p, T q, const Policy&) |
| 291 |
{
|
| 292 |
BOOST_MATH_STD_USING |
| 293 |
// static const char* function = "quantile(non_central_t_distribution<%1%>, %1%)";
|
| 294 |
// now passed as function
|
| 295 |
typedef typename policies::evaluation<T, Policy>::type value_type; |
| 296 |
typedef typename policies::normalise< |
| 297 |
Policy, |
| 298 |
policies::promote_float<false>,
|
| 299 |
policies::promote_double<false>,
|
| 300 |
policies::discrete_quantile<>, |
| 301 |
policies::assert_undefined<> >::type forwarding_policy; |
| 302 |
|
| 303 |
T r; |
| 304 |
if(!detail::check_df_gt0_to_inf(
|
| 305 |
function, |
| 306 |
v, &r, Policy()) |
| 307 |
|| |
| 308 |
!detail::check_finite( |
| 309 |
function, |
| 310 |
delta, |
| 311 |
&r, |
| 312 |
Policy()) |
| 313 |
|| |
| 314 |
!detail::check_probability( |
| 315 |
function, |
| 316 |
p, |
| 317 |
&r, |
| 318 |
Policy())) |
| 319 |
return r;
|
| 320 |
|
| 321 |
|
| 322 |
value_type guess = 0;
|
| 323 |
if ( ((boost::math::isinf)(v)) || (v > 1 / boost::math::tools::epsilon<T>()) ) |
| 324 |
{ // Infinite or very large degrees of freedom, so use normal distribution located at delta.
|
| 325 |
normal_distribution<T, Policy> n(delta, 1);
|
| 326 |
if (p < q)
|
| 327 |
{
|
| 328 |
return quantile(n, p);
|
| 329 |
} |
| 330 |
else
|
| 331 |
{
|
| 332 |
return quantile(complement(n, q));
|
| 333 |
} |
| 334 |
} |
| 335 |
else if(v > 3) |
| 336 |
{ // Use normal distribution to calculate guess.
|
| 337 |
value_type mean = (v > 1 / policies::get_epsilon<T, Policy>()) ? delta : delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f)); |
| 338 |
value_type var = (v > 1 / policies::get_epsilon<T, Policy>()) ? value_type(1) : (((delta * delta + 1) * v) / (v - 2) - mean * mean); |
| 339 |
if(p < q)
|
| 340 |
guess = quantile(normal_distribution<value_type, forwarding_policy>(mean, var), p); |
| 341 |
else
|
| 342 |
guess = quantile(complement(normal_distribution<value_type, forwarding_policy>(mean, var), q)); |
| 343 |
} |
| 344 |
//
|
| 345 |
// We *must* get the sign of the initial guess correct,
|
| 346 |
// or our root-finder will fail, so double check it now:
|
| 347 |
//
|
| 348 |
value_type pzero = non_central_t_cdf( |
| 349 |
static_cast<value_type>(v),
|
| 350 |
static_cast<value_type>(delta),
|
| 351 |
static_cast<value_type>(0), |
| 352 |
!(p < q), |
| 353 |
forwarding_policy()); |
| 354 |
int s;
|
| 355 |
if(p < q)
|
| 356 |
s = boost::math::sign(p - pzero); |
| 357 |
else
|
| 358 |
s = boost::math::sign(pzero - q); |
| 359 |
if(s != boost::math::sign(guess))
|
| 360 |
{
|
| 361 |
guess = static_cast<T>(s);
|
| 362 |
} |
| 363 |
|
| 364 |
value_type result = detail::generic_quantile( |
| 365 |
non_central_t_distribution<value_type, forwarding_policy>(v, delta), |
| 366 |
(p < q ? p : q), |
| 367 |
guess, |
| 368 |
(p >= q), |
| 369 |
function); |
| 370 |
return policies::checked_narrowing_cast<T, forwarding_policy>(
|
| 371 |
result, |
| 372 |
function); |
| 373 |
} |
| 374 |
|
| 375 |
template <class T, class Policy> |
| 376 |
T non_central_t2_pdf(T n, T delta, T x, T y, const Policy& pol, T init_val)
|
| 377 |
{
|
| 378 |
BOOST_MATH_STD_USING |
| 379 |
//
|
| 380 |
// Variables come first:
|
| 381 |
//
|
| 382 |
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); |
| 383 |
T errtol = boost::math::policies::get_epsilon<T, Policy>(); |
| 384 |
T d2 = delta * delta / 2;
|
| 385 |
//
|
| 386 |
// k is the starting point for iteration, and is the
|
| 387 |
// maximum of the poisson weighting term:
|
| 388 |
//
|
| 389 |
int k = itrunc(d2);
|
| 390 |
T pois, xterm; |
| 391 |
if(k == 0) |
| 392 |
k = 1;
|
| 393 |
// Starting Poisson weight:
|
| 394 |
pois = gamma_p_derivative(T(k+1), d2, pol)
|
| 395 |
* tgamma_delta_ratio(T(k + 1), T(0.5f)) |
| 396 |
* delta / constants::root_two<T>(); |
| 397 |
// Starting beta term:
|
| 398 |
xterm = x < y |
| 399 |
? ibeta_derivative(T(k + 1), n / 2, x, pol) |
| 400 |
: ibeta_derivative(n / 2, T(k + 1), y, pol); |
| 401 |
T poisf(pois), xtermf(xterm); |
| 402 |
T sum = init_val; |
| 403 |
if((pois == 0) || (xterm == 0)) |
| 404 |
return init_val;
|
| 405 |
|
| 406 |
//
|
| 407 |
// Backwards recursion first, this is the stable
|
| 408 |
// direction for recursion:
|
| 409 |
//
|
| 410 |
boost::uintmax_t count = 0;
|
| 411 |
for(int i = k; i >= 0; --i) |
| 412 |
{
|
| 413 |
T term = xterm * pois; |
| 414 |
sum += term; |
| 415 |
if(((fabs(term/sum) < errtol) && (i != k)) || (term == 0)) |
| 416 |
break;
|
| 417 |
pois *= (i + 0.5f) / d2; |
| 418 |
xterm *= (i) / (x * (n / 2 + i));
|
| 419 |
++count; |
| 420 |
if(count > max_iter)
|
| 421 |
{
|
| 422 |
return policies::raise_evaluation_error(
|
| 423 |
"pdf(non_central_t_distribution<%1%>, %1%)",
|
| 424 |
"Series did not converge, closest value was %1%", sum, pol);
|
| 425 |
} |
| 426 |
} |
| 427 |
for(int i = k + 1; ; ++i) |
| 428 |
{
|
| 429 |
poisf *= d2 / (i + 0.5f); |
| 430 |
xtermf *= (x * (n / 2 + i)) / (i);
|
| 431 |
T term = poisf * xtermf; |
| 432 |
sum += term; |
| 433 |
if((fabs(term/sum) < errtol) || (term == 0)) |
| 434 |
break;
|
| 435 |
++count; |
| 436 |
if(count > max_iter)
|
| 437 |
{
|
| 438 |
return policies::raise_evaluation_error(
|
| 439 |
"pdf(non_central_t_distribution<%1%>, %1%)",
|
| 440 |
"Series did not converge, closest value was %1%", sum, pol);
|
| 441 |
} |
| 442 |
} |
| 443 |
return sum;
|
| 444 |
} |
| 445 |
|
| 446 |
template <class T, class Policy> |
| 447 |
T non_central_t_pdf(T n, T delta, T t, const Policy& pol)
|
| 448 |
{
|
| 449 |
BOOST_MATH_STD_USING |
| 450 |
if ((boost::math::isinf)(n))
|
| 451 |
{ // Infinite degrees of freedom, so use normal distribution located at delta.
|
| 452 |
normal_distribution<T, Policy> norm(delta, 1);
|
| 453 |
return pdf(norm, t);
|
| 454 |
} |
| 455 |
//
|
| 456 |
// Otherwise, for t < 0 we have to use the reflection formula:
|
| 457 |
if(t < 0) |
| 458 |
{
|
| 459 |
t = -t; |
| 460 |
delta = -delta; |
| 461 |
} |
| 462 |
if(t == 0) |
| 463 |
{
|
| 464 |
//
|
| 465 |
// Handle this as a special case, using the formula
|
| 466 |
// from Weisstein, Eric W.
|
| 467 |
// "Noncentral Student's t-Distribution."
|
| 468 |
// From MathWorld--A Wolfram Web Resource.
|
| 469 |
// http://mathworld.wolfram.com/NoncentralStudentst-Distribution.html
|
| 470 |
//
|
| 471 |
// The formula is simplified thanks to the relation
|
| 472 |
// 1F1(a,b,0) = 1.
|
| 473 |
//
|
| 474 |
return tgamma_delta_ratio(n / 2 + 0.5f, T(0.5f)) |
| 475 |
* sqrt(n / constants::pi<T>()) |
| 476 |
* exp(-delta * delta / 2) / 2; |
| 477 |
} |
| 478 |
if(fabs(delta / (4 * n)) < policies::get_epsilon<T, Policy>()) |
| 479 |
{
|
| 480 |
// Approximate with a Student's T centred on delta,
|
| 481 |
// the crossover point is based on eq 2.6 from
|
| 482 |
// "A Comparison of Approximations To Percentiles of the
|
| 483 |
// Noncentral t-Distribution". H. Sahai and M. M. Ojeda,
|
| 484 |
// Revista Investigacion Operacional Vol 21, No 2, 2000.
|
| 485 |
// Original sources referenced in the above are:
|
| 486 |
// "Some Approximations to the Percentage Points of the Noncentral
|
| 487 |
// t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31.
|
| 488 |
// "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and
|
| 489 |
// N. Balkrishnan. 1995. John Wiley and Sons New York.
|
| 490 |
return pdf(students_t_distribution<T, Policy>(n), t - delta);
|
| 491 |
} |
| 492 |
//
|
| 493 |
// x and y are the corresponding random
|
| 494 |
// variables for the noncentral beta distribution,
|
| 495 |
// with y = 1 - x:
|
| 496 |
//
|
| 497 |
T x = t * t / (n + t * t); |
| 498 |
T y = n / (n + t * t); |
| 499 |
T a = 0.5f; |
| 500 |
T b = n / 2;
|
| 501 |
T d2 = delta * delta; |
| 502 |
//
|
| 503 |
// Calculate pdf:
|
| 504 |
//
|
| 505 |
T dt = n * t / (n * n + 2 * n * t * t + t * t * t * t);
|
| 506 |
T result = non_central_beta_pdf(a, b, d2, x, y, pol); |
| 507 |
T tol = tools::epsilon<T>() * result * 500;
|
| 508 |
result = non_central_t2_pdf(n, delta, x, y, pol, result); |
| 509 |
if(result <= tol)
|
| 510 |
result = 0;
|
| 511 |
result *= dt; |
| 512 |
return result;
|
| 513 |
} |
| 514 |
|
| 515 |
template <class T, class Policy> |
| 516 |
T mean(T v, T delta, const Policy& pol)
|
| 517 |
{
|
| 518 |
if ((boost::math::isinf)(v))
|
| 519 |
{
|
| 520 |
return delta;
|
| 521 |
} |
| 522 |
BOOST_MATH_STD_USING |
| 523 |
if (v > 1 / boost::math::tools::epsilon<T>() ) |
| 524 |
{
|
| 525 |
//normal_distribution<T, Policy> n(delta, 1);
|
| 526 |
//return boost::math::mean(n);
|
| 527 |
return delta;
|
| 528 |
} |
| 529 |
else
|
| 530 |
{
|
| 531 |
return delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f), pol); |
| 532 |
} |
| 533 |
// Other moments use mean so using normal distribution is propagated.
|
| 534 |
} |
| 535 |
|
| 536 |
template <class T, class Policy> |
| 537 |
T variance(T v, T delta, const Policy& pol)
|
| 538 |
{
|
| 539 |
if ((boost::math::isinf)(v))
|
| 540 |
{
|
| 541 |
return 1; |
| 542 |
} |
| 543 |
if (delta == 0) |
| 544 |
{ // == Student's t
|
| 545 |
return v / (v - 2); |
| 546 |
} |
| 547 |
T result = ((delta * delta + 1) * v) / (v - 2); |
| 548 |
T m = mean(v, delta, pol); |
| 549 |
result -= m * m; |
| 550 |
return result;
|
| 551 |
} |
| 552 |
|
| 553 |
template <class T, class Policy> |
| 554 |
T skewness(T v, T delta, const Policy& pol)
|
| 555 |
{
|
| 556 |
BOOST_MATH_STD_USING |
| 557 |
if ((boost::math::isinf)(v))
|
| 558 |
{
|
| 559 |
return 0; |
| 560 |
} |
| 561 |
if(delta == 0) |
| 562 |
{ // == Student's t
|
| 563 |
return 0; |
| 564 |
} |
| 565 |
T mean = boost::math::detail::mean(v, delta, pol); |
| 566 |
T l2 = delta * delta; |
| 567 |
T var = ((l2 + 1) * v) / (v - 2) - mean * mean; |
| 568 |
T result = -2 * var;
|
| 569 |
result += v * (l2 + 2 * v - 3) / ((v - 3) * (v - 2)); |
| 570 |
result *= mean; |
| 571 |
result /= pow(var, T(1.5f)); |
| 572 |
return result;
|
| 573 |
} |
| 574 |
|
| 575 |
template <class T, class Policy> |
| 576 |
T kurtosis_excess(T v, T delta, const Policy& pol)
|
| 577 |
{
|
| 578 |
BOOST_MATH_STD_USING |
| 579 |
if ((boost::math::isinf)(v))
|
| 580 |
{
|
| 581 |
return 3; |
| 582 |
} |
| 583 |
if (delta == 0) |
| 584 |
{ // == Student's t
|
| 585 |
return 3; |
| 586 |
} |
| 587 |
T mean = boost::math::detail::mean(v, delta, pol); |
| 588 |
T l2 = delta * delta; |
| 589 |
T var = ((l2 + 1) * v) / (v - 2) - mean * mean; |
| 590 |
T result = -3 * var;
|
| 591 |
result += v * (l2 * (v + 1) + 3 * (3 * v - 5)) / ((v - 3) * (v - 2)); |
| 592 |
result *= -mean * mean; |
| 593 |
result += v * v * (l2 * l2 + 6 * l2 + 3) / ((v - 4) * (v - 2)); |
| 594 |
result /= var * var; |
| 595 |
return result;
|
| 596 |
} |
| 597 |
|
| 598 |
#if 0
|
| 599 |
//
|
| 600 |
// This code is disabled, since there can be multiple answers to the
|
| 601 |
// question, and it's not clear how to find the "right" one.
|
| 602 |
//
|
| 603 |
template <class RealType, class Policy>
|
| 604 |
struct t_degrees_of_freedom_finder
|
| 605 |
{
|
| 606 |
t_degrees_of_freedom_finder(
|
| 607 |
RealType delta_, RealType x_, RealType p_, bool c)
|
| 608 |
: delta(delta_), x(x_), p(p_), comp(c) {}
|
| 609 |
|
| 610 |
RealType operator()(const RealType& v)
|
| 611 |
{
|
| 612 |
non_central_t_distribution<RealType, Policy> d(v, delta);
|
| 613 |
return comp ?
|
| 614 |
p - cdf(complement(d, x))
|
| 615 |
: cdf(d, x) - p;
|
| 616 |
}
|
| 617 |
private:
|
| 618 |
RealType delta;
|
| 619 |
RealType x;
|
| 620 |
RealType p;
|
| 621 |
bool comp;
|
| 622 |
};
|
| 623 |
|
| 624 |
template <class RealType, class Policy>
|
| 625 |
inline RealType find_t_degrees_of_freedom(
|
| 626 |
RealType delta, RealType x, RealType p, RealType q, const Policy& pol)
|
| 627 |
{
|
| 628 |
const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
|
| 629 |
if((p == 0) || (q == 0))
|
| 630 |
{
|
| 631 |
//
|
| 632 |
// Can't a thing if one of p and q is zero:
|
| 633 |
//
|
| 634 |
return policies::raise_evaluation_error<RealType>(function,
|
| 635 |
"Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%",
|
| 636 |
RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
|
| 637 |
}
|
| 638 |
t_degrees_of_freedom_finder<RealType, Policy> f(delta, x, p < q ? p : q, p < q ? false : true);
|
| 639 |
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
|
| 640 |
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
|
| 641 |
//
|
| 642 |
// Pick an initial guess:
|
| 643 |
//
|
| 644 |
RealType guess = 200;
|
| 645 |
std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
|
| 646 |
f, guess, RealType(2), false, tol, max_iter, pol);
|
| 647 |
RealType result = ir.first + (ir.second - ir.first) / 2;
|
| 648 |
if(max_iter >= policies::get_max_root_iterations<Policy>())
|
| 649 |
{
|
| 650 |
return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
|
| 651 |
" or there is no answer to problem. Current best guess is %1%", result, Policy());
|
| 652 |
}
|
| 653 |
return result;
|
| 654 |
}
|
| 655 |
|
| 656 |
template <class RealType, class Policy>
|
| 657 |
struct t_non_centrality_finder
|
| 658 |
{
|
| 659 |
t_non_centrality_finder(
|
| 660 |
RealType v_, RealType x_, RealType p_, bool c)
|
| 661 |
: v(v_), x(x_), p(p_), comp(c) {}
|
| 662 |
|
| 663 |
RealType operator()(const RealType& delta)
|
| 664 |
{
|
| 665 |
non_central_t_distribution<RealType, Policy> d(v, delta);
|
| 666 |
return comp ?
|
| 667 |
p - cdf(complement(d, x))
|
| 668 |
: cdf(d, x) - p;
|
| 669 |
}
|
| 670 |
private:
|
| 671 |
RealType v;
|
| 672 |
RealType x;
|
| 673 |
RealType p;
|
| 674 |
bool comp;
|
| 675 |
};
|
| 676 |
|
| 677 |
template <class RealType, class Policy>
|
| 678 |
inline RealType find_t_non_centrality(
|
| 679 |
RealType v, RealType x, RealType p, RealType q, const Policy& pol)
|
| 680 |
{
|
| 681 |
const char* function = "non_central_t<%1%>::find_t_non_centrality";
|
| 682 |
if((p == 0) || (q == 0))
|
| 683 |
{
|
| 684 |
//
|
| 685 |
// Can't do a thing if one of p and q is zero:
|
| 686 |
//
|
| 687 |
return policies::raise_evaluation_error<RealType>(function,
|
| 688 |
"Can't find non-centrality parameter when the probability is 0 or 1, only possible answer is %1%",
|
| 689 |
RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
|
| 690 |
}
|
| 691 |
t_non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
|
| 692 |
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
|
| 693 |
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
|
| 694 |
//
|
| 695 |
// Pick an initial guess that we know is the right side of
|
| 696 |
// zero:
|
| 697 |
//
|
| 698 |
RealType guess;
|
| 699 |
if(f(0) < 0)
|
| 700 |
guess = 1;
|
| 701 |
else
|
| 702 |
guess = -1;
|
| 703 |
std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
|
| 704 |
f, guess, RealType(2), false, tol, max_iter, pol);
|
| 705 |
RealType result = ir.first + (ir.second - ir.first) / 2;
|
| 706 |
if(max_iter >= policies::get_max_root_iterations<Policy>())
|
| 707 |
{
|
| 708 |
return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
|
| 709 |
" or there is no answer to problem. Current best guess is %1%", result, Policy());
|
| 710 |
}
|
| 711 |
return result;
|
| 712 |
}
|
| 713 |
#endif
|
| 714 |
} // namespace detail ======================================================================
|
| 715 |
|
| 716 |
template <class RealType = double, class Policy = policies::policy<> > |
| 717 |
class non_central_t_distribution |
| 718 |
{
|
| 719 |
public:
|
| 720 |
typedef RealType value_type;
|
| 721 |
typedef Policy policy_type;
|
| 722 |
|
| 723 |
non_central_t_distribution(RealType v_, RealType lambda) : v(v_), ncp(lambda) |
| 724 |
{
|
| 725 |
const char* function = "boost::math::non_central_t_distribution<%1%>::non_central_t_distribution(%1%,%1%)"; |
| 726 |
RealType r; |
| 727 |
detail::check_df_gt0_to_inf( |
| 728 |
function, |
| 729 |
v, &r, Policy()); |
| 730 |
detail::check_finite( |
| 731 |
function, |
| 732 |
lambda, |
| 733 |
&r, |
| 734 |
Policy()); |
| 735 |
} // non_central_t_distribution constructor.
|
| 736 |
|
| 737 |
RealType degrees_of_freedom() const
|
| 738 |
{ // Private data getter function.
|
| 739 |
return v;
|
| 740 |
} |
| 741 |
RealType non_centrality() const
|
| 742 |
{ // Private data getter function.
|
| 743 |
return ncp;
|
| 744 |
} |
| 745 |
#if 0
|
| 746 |
//
|
| 747 |
// This code is disabled, since there can be multiple answers to the
|
| 748 |
// question, and it's not clear how to find the "right" one.
|
| 749 |
//
|
| 750 |
static RealType find_degrees_of_freedom(RealType delta, RealType x, RealType p)
|
| 751 |
{
|
| 752 |
const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
|
| 753 |
typedef typename policies::evaluation<RealType, Policy>::type value_type;
|
| 754 |
typedef typename policies::normalise<
|
| 755 |
Policy,
|
| 756 |
policies::promote_float<false>,
|
| 757 |
policies::promote_double<false>,
|
| 758 |
policies::discrete_quantile<>,
|
| 759 |
policies::assert_undefined<> >::type forwarding_policy;
|
| 760 |
value_type result = detail::find_t_degrees_of_freedom(
|
| 761 |
static_cast<value_type>(delta),
|
| 762 |
static_cast<value_type>(x),
|
| 763 |
static_cast<value_type>(p),
|
| 764 |
static_cast<value_type>(1-p),
|
| 765 |
forwarding_policy());
|
| 766 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 767 |
result,
|
| 768 |
function);
|
| 769 |
}
|
| 770 |
template <class A, class B, class C>
|
| 771 |
static RealType find_degrees_of_freedom(const complemented3_type<A,B,C>& c)
|
| 772 |
{
|
| 773 |
const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
|
| 774 |
typedef typename policies::evaluation<RealType, Policy>::type value_type;
|
| 775 |
typedef typename policies::normalise<
|
| 776 |
Policy,
|
| 777 |
policies::promote_float<false>,
|
| 778 |
policies::promote_double<false>,
|
| 779 |
policies::discrete_quantile<>,
|
| 780 |
policies::assert_undefined<> >::type forwarding_policy;
|
| 781 |
value_type result = detail::find_t_degrees_of_freedom(
|
| 782 |
static_cast<value_type>(c.dist),
|
| 783 |
static_cast<value_type>(c.param1),
|
| 784 |
static_cast<value_type>(1-c.param2),
|
| 785 |
static_cast<value_type>(c.param2),
|
| 786 |
forwarding_policy());
|
| 787 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 788 |
result,
|
| 789 |
function);
|
| 790 |
}
|
| 791 |
static RealType find_non_centrality(RealType v, RealType x, RealType p)
|
| 792 |
{
|
| 793 |
const char* function = "non_central_t<%1%>::find_t_non_centrality";
|
| 794 |
typedef typename policies::evaluation<RealType, Policy>::type value_type;
|
| 795 |
typedef typename policies::normalise<
|
| 796 |
Policy,
|
| 797 |
policies::promote_float<false>,
|
| 798 |
policies::promote_double<false>,
|
| 799 |
policies::discrete_quantile<>,
|
| 800 |
policies::assert_undefined<> >::type forwarding_policy;
|
| 801 |
value_type result = detail::find_t_non_centrality(
|
| 802 |
static_cast<value_type>(v),
|
| 803 |
static_cast<value_type>(x),
|
| 804 |
static_cast<value_type>(p),
|
| 805 |
static_cast<value_type>(1-p),
|
| 806 |
forwarding_policy());
|
| 807 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 808 |
result,
|
| 809 |
function);
|
| 810 |
}
|
| 811 |
template <class A, class B, class C>
|
| 812 |
static RealType find_non_centrality(const complemented3_type<A,B,C>& c)
|
| 813 |
{
|
| 814 |
const char* function = "non_central_t<%1%>::find_t_non_centrality";
|
| 815 |
typedef typename policies::evaluation<RealType, Policy>::type value_type;
|
| 816 |
typedef typename policies::normalise<
|
| 817 |
Policy,
|
| 818 |
policies::promote_float<false>,
|
| 819 |
policies::promote_double<false>,
|
| 820 |
policies::discrete_quantile<>,
|
| 821 |
policies::assert_undefined<> >::type forwarding_policy;
|
| 822 |
value_type result = detail::find_t_non_centrality(
|
| 823 |
static_cast<value_type>(c.dist),
|
| 824 |
static_cast<value_type>(c.param1),
|
| 825 |
static_cast<value_type>(1-c.param2),
|
| 826 |
static_cast<value_type>(c.param2),
|
| 827 |
forwarding_policy());
|
| 828 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 829 |
result,
|
| 830 |
function);
|
| 831 |
}
|
| 832 |
#endif
|
| 833 |
private:
|
| 834 |
// Data member, initialized by constructor.
|
| 835 |
RealType v; // degrees of freedom
|
| 836 |
RealType ncp; // non-centrality parameter
|
| 837 |
}; // template <class RealType, class Policy> class non_central_t_distribution
|
| 838 |
|
| 839 |
typedef non_central_t_distribution<double> non_central_t; // Reserved name of type double. |
| 840 |
|
| 841 |
// Non-member functions to give properties of the distribution.
|
| 842 |
|
| 843 |
template <class RealType, class Policy> |
| 844 |
inline const std::pair<RealType, RealType> range(const non_central_t_distribution<RealType, Policy>& /* dist */) |
| 845 |
{ // Range of permissible values for random variable k.
|
| 846 |
using boost::math::tools::max_value;
|
| 847 |
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
|
| 848 |
} |
| 849 |
|
| 850 |
template <class RealType, class Policy> |
| 851 |
inline const std::pair<RealType, RealType> support(const non_central_t_distribution<RealType, Policy>& /* dist */) |
| 852 |
{ // Range of supported values for random variable k.
|
| 853 |
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
|
| 854 |
using boost::math::tools::max_value;
|
| 855 |
return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
|
| 856 |
} |
| 857 |
|
| 858 |
template <class RealType, class Policy> |
| 859 |
inline RealType mode(const non_central_t_distribution<RealType, Policy>& dist) |
| 860 |
{ // mode.
|
| 861 |
static const char* function = "mode(non_central_t_distribution<%1%> const&)"; |
| 862 |
RealType v = dist.degrees_of_freedom(); |
| 863 |
RealType l = dist.non_centrality(); |
| 864 |
RealType r; |
| 865 |
if(!detail::check_df_gt0_to_inf(
|
| 866 |
function, |
| 867 |
v, &r, Policy()) |
| 868 |
|| |
| 869 |
!detail::check_finite( |
| 870 |
function, |
| 871 |
l, |
| 872 |
&r, |
| 873 |
Policy())) |
| 874 |
return (RealType)r;
|
| 875 |
|
| 876 |
BOOST_MATH_STD_USING |
| 877 |
|
| 878 |
RealType m = v < 3 ? 0 : detail::mean(v, l, Policy()); |
| 879 |
RealType var = v < 4 ? 1 : detail::variance(v, l, Policy()); |
| 880 |
|
| 881 |
return detail::generic_find_mode(
|
| 882 |
dist, |
| 883 |
m, |
| 884 |
function, |
| 885 |
sqrt(var)); |
| 886 |
} |
| 887 |
|
| 888 |
template <class RealType, class Policy> |
| 889 |
inline RealType mean(const non_central_t_distribution<RealType, Policy>& dist) |
| 890 |
{
|
| 891 |
BOOST_MATH_STD_USING |
| 892 |
const char* function = "mean(const non_central_t_distribution<%1%>&)"; |
| 893 |
typedef typename policies::evaluation<RealType, Policy>::type value_type; |
| 894 |
typedef typename policies::normalise< |
| 895 |
Policy, |
| 896 |
policies::promote_float<false>,
|
| 897 |
policies::promote_double<false>,
|
| 898 |
policies::discrete_quantile<>, |
| 899 |
policies::assert_undefined<> >::type forwarding_policy; |
| 900 |
RealType v = dist.degrees_of_freedom(); |
| 901 |
RealType l = dist.non_centrality(); |
| 902 |
RealType r; |
| 903 |
if(!detail::check_df_gt0_to_inf(
|
| 904 |
function, |
| 905 |
v, &r, Policy()) |
| 906 |
|| |
| 907 |
!detail::check_finite( |
| 908 |
function, |
| 909 |
l, |
| 910 |
&r, |
| 911 |
Policy())) |
| 912 |
return (RealType)r;
|
| 913 |
if(v <= 1) |
| 914 |
return policies::raise_domain_error<RealType>(
|
| 915 |
function, |
| 916 |
"The non-central t distribution has no defined mean for degrees of freedom <= 1: got v=%1%.", v, Policy());
|
| 917 |
// return l * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, RealType(0.5f));
|
| 918 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 919 |
detail::mean(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function); |
| 920 |
|
| 921 |
} // mean
|
| 922 |
|
| 923 |
template <class RealType, class Policy> |
| 924 |
inline RealType variance(const non_central_t_distribution<RealType, Policy>& dist) |
| 925 |
{ // variance.
|
| 926 |
const char* function = "variance(const non_central_t_distribution<%1%>&)"; |
| 927 |
typedef typename policies::evaluation<RealType, Policy>::type value_type; |
| 928 |
typedef typename policies::normalise< |
| 929 |
Policy, |
| 930 |
policies::promote_float<false>,
|
| 931 |
policies::promote_double<false>,
|
| 932 |
policies::discrete_quantile<>, |
| 933 |
policies::assert_undefined<> >::type forwarding_policy; |
| 934 |
BOOST_MATH_STD_USING |
| 935 |
RealType v = dist.degrees_of_freedom(); |
| 936 |
RealType l = dist.non_centrality(); |
| 937 |
RealType r; |
| 938 |
if(!detail::check_df_gt0_to_inf(
|
| 939 |
function, |
| 940 |
v, &r, Policy()) |
| 941 |
|| |
| 942 |
!detail::check_finite( |
| 943 |
function, |
| 944 |
l, |
| 945 |
&r, |
| 946 |
Policy())) |
| 947 |
return (RealType)r;
|
| 948 |
if(v <= 2) |
| 949 |
return policies::raise_domain_error<RealType>(
|
| 950 |
function, |
| 951 |
"The non-central t distribution has no defined variance for degrees of freedom <= 2: got v=%1%.", v, Policy());
|
| 952 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 953 |
detail::variance(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function); |
| 954 |
} |
| 955 |
|
| 956 |
// RealType standard_deviation(const non_central_t_distribution<RealType, Policy>& dist)
|
| 957 |
// standard_deviation provided by derived accessors.
|
| 958 |
|
| 959 |
template <class RealType, class Policy> |
| 960 |
inline RealType skewness(const non_central_t_distribution<RealType, Policy>& dist) |
| 961 |
{ // skewness = sqrt(l).
|
| 962 |
const char* function = "skewness(const non_central_t_distribution<%1%>&)"; |
| 963 |
typedef typename policies::evaluation<RealType, Policy>::type value_type; |
| 964 |
typedef typename policies::normalise< |
| 965 |
Policy, |
| 966 |
policies::promote_float<false>,
|
| 967 |
policies::promote_double<false>,
|
| 968 |
policies::discrete_quantile<>, |
| 969 |
policies::assert_undefined<> >::type forwarding_policy; |
| 970 |
RealType v = dist.degrees_of_freedom(); |
| 971 |
RealType l = dist.non_centrality(); |
| 972 |
RealType r; |
| 973 |
if(!detail::check_df_gt0_to_inf(
|
| 974 |
function, |
| 975 |
v, &r, Policy()) |
| 976 |
|| |
| 977 |
!detail::check_finite( |
| 978 |
function, |
| 979 |
l, |
| 980 |
&r, |
| 981 |
Policy())) |
| 982 |
return (RealType)r;
|
| 983 |
if(v <= 3) |
| 984 |
return policies::raise_domain_error<RealType>(
|
| 985 |
function, |
| 986 |
"The non-central t distribution has no defined skewness for degrees of freedom <= 3: got v=%1%.", v, Policy());;
|
| 987 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 988 |
detail::skewness(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function); |
| 989 |
} |
| 990 |
|
| 991 |
template <class RealType, class Policy> |
| 992 |
inline RealType kurtosis_excess(const non_central_t_distribution<RealType, Policy>& dist) |
| 993 |
{
|
| 994 |
const char* function = "kurtosis_excess(const non_central_t_distribution<%1%>&)"; |
| 995 |
typedef typename policies::evaluation<RealType, Policy>::type value_type; |
| 996 |
typedef typename policies::normalise< |
| 997 |
Policy, |
| 998 |
policies::promote_float<false>,
|
| 999 |
policies::promote_double<false>,
|
| 1000 |
policies::discrete_quantile<>, |
| 1001 |
policies::assert_undefined<> >::type forwarding_policy; |
| 1002 |
RealType v = dist.degrees_of_freedom(); |
| 1003 |
RealType l = dist.non_centrality(); |
| 1004 |
RealType r; |
| 1005 |
if(!detail::check_df_gt0_to_inf(
|
| 1006 |
function, |
| 1007 |
v, &r, Policy()) |
| 1008 |
|| |
| 1009 |
!detail::check_finite( |
| 1010 |
function, |
| 1011 |
l, |
| 1012 |
&r, |
| 1013 |
Policy())) |
| 1014 |
return (RealType)r;
|
| 1015 |
if(v <= 4) |
| 1016 |
return policies::raise_domain_error<RealType>(
|
| 1017 |
function, |
| 1018 |
"The non-central t distribution has no defined kurtosis for degrees of freedom <= 4: got v=%1%.", v, Policy());;
|
| 1019 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 1020 |
detail::kurtosis_excess(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function); |
| 1021 |
} // kurtosis_excess
|
| 1022 |
|
| 1023 |
template <class RealType, class Policy> |
| 1024 |
inline RealType kurtosis(const non_central_t_distribution<RealType, Policy>& dist) |
| 1025 |
{
|
| 1026 |
return kurtosis_excess(dist) + 3; |
| 1027 |
} |
| 1028 |
|
| 1029 |
template <class RealType, class Policy> |
| 1030 |
inline RealType pdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& t) |
| 1031 |
{ // Probability Density/Mass Function.
|
| 1032 |
const char* function = "pdf(non_central_t_distribution<%1%>, %1%)"; |
| 1033 |
typedef typename policies::evaluation<RealType, Policy>::type value_type; |
| 1034 |
typedef typename policies::normalise< |
| 1035 |
Policy, |
| 1036 |
policies::promote_float<false>,
|
| 1037 |
policies::promote_double<false>,
|
| 1038 |
policies::discrete_quantile<>, |
| 1039 |
policies::assert_undefined<> >::type forwarding_policy; |
| 1040 |
|
| 1041 |
RealType v = dist.degrees_of_freedom(); |
| 1042 |
RealType l = dist.non_centrality(); |
| 1043 |
RealType r; |
| 1044 |
if(!detail::check_df_gt0_to_inf(
|
| 1045 |
function, |
| 1046 |
v, &r, Policy()) |
| 1047 |
|| |
| 1048 |
!detail::check_finite( |
| 1049 |
function, |
| 1050 |
l, |
| 1051 |
&r, |
| 1052 |
Policy()) |
| 1053 |
|| |
| 1054 |
!detail::check_x( |
| 1055 |
function, |
| 1056 |
t, |
| 1057 |
&r, |
| 1058 |
Policy())) |
| 1059 |
return (RealType)r;
|
| 1060 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 1061 |
detail::non_central_t_pdf(static_cast<value_type>(v),
|
| 1062 |
static_cast<value_type>(l),
|
| 1063 |
static_cast<value_type>(t),
|
| 1064 |
Policy()), |
| 1065 |
function); |
| 1066 |
} // pdf
|
| 1067 |
|
| 1068 |
template <class RealType, class Policy> |
| 1069 |
RealType cdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& x) |
| 1070 |
{
|
| 1071 |
const char* function = "boost::math::cdf(non_central_t_distribution<%1%>&, %1%)"; |
| 1072 |
// was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
|
| 1073 |
typedef typename policies::evaluation<RealType, Policy>::type value_type; |
| 1074 |
typedef typename policies::normalise< |
| 1075 |
Policy, |
| 1076 |
policies::promote_float<false>,
|
| 1077 |
policies::promote_double<false>,
|
| 1078 |
policies::discrete_quantile<>, |
| 1079 |
policies::assert_undefined<> >::type forwarding_policy; |
| 1080 |
|
| 1081 |
RealType v = dist.degrees_of_freedom(); |
| 1082 |
RealType l = dist.non_centrality(); |
| 1083 |
RealType r; |
| 1084 |
if(!detail::check_df_gt0_to_inf(
|
| 1085 |
function, |
| 1086 |
v, &r, Policy()) |
| 1087 |
|| |
| 1088 |
!detail::check_finite( |
| 1089 |
function, |
| 1090 |
l, |
| 1091 |
&r, |
| 1092 |
Policy()) |
| 1093 |
|| |
| 1094 |
!detail::check_x( |
| 1095 |
function, |
| 1096 |
x, |
| 1097 |
&r, |
| 1098 |
Policy())) |
| 1099 |
return (RealType)r;
|
| 1100 |
if ((boost::math::isinf)(v))
|
| 1101 |
{ // Infinite degrees of freedom, so use normal distribution located at delta.
|
| 1102 |
normal_distribution<RealType, Policy> n(l, 1);
|
| 1103 |
cdf(n, x); |
| 1104 |
//return cdf(normal_distribution<RealType, Policy>(l, 1), x);
|
| 1105 |
} |
| 1106 |
|
| 1107 |
if(l == 0) |
| 1108 |
{ // NO non-centrality, so use Student's t instead.
|
| 1109 |
return cdf(students_t_distribution<RealType, Policy>(v), x);
|
| 1110 |
} |
| 1111 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 1112 |
detail::non_central_t_cdf( |
| 1113 |
static_cast<value_type>(v),
|
| 1114 |
static_cast<value_type>(l),
|
| 1115 |
static_cast<value_type>(x),
|
| 1116 |
false, Policy()),
|
| 1117 |
function); |
| 1118 |
} // cdf
|
| 1119 |
|
| 1120 |
template <class RealType, class Policy> |
| 1121 |
RealType cdf(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
|
| 1122 |
{ // Complemented Cumulative Distribution Function
|
| 1123 |
// was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
|
| 1124 |
const char* function = "boost::math::cdf(const complement(non_central_t_distribution<%1%>&), %1%)"; |
| 1125 |
typedef typename policies::evaluation<RealType, Policy>::type value_type; |
| 1126 |
typedef typename policies::normalise< |
| 1127 |
Policy, |
| 1128 |
policies::promote_float<false>,
|
| 1129 |
policies::promote_double<false>,
|
| 1130 |
policies::discrete_quantile<>, |
| 1131 |
policies::assert_undefined<> >::type forwarding_policy; |
| 1132 |
|
| 1133 |
non_central_t_distribution<RealType, Policy> const& dist = c.dist;
|
| 1134 |
RealType x = c.param; |
| 1135 |
RealType v = dist.degrees_of_freedom(); |
| 1136 |
RealType l = dist.non_centrality(); // aka delta
|
| 1137 |
RealType r; |
| 1138 |
if(!detail::check_df_gt0_to_inf(
|
| 1139 |
function, |
| 1140 |
v, &r, Policy()) |
| 1141 |
|| |
| 1142 |
!detail::check_finite( |
| 1143 |
function, |
| 1144 |
l, |
| 1145 |
&r, |
| 1146 |
Policy()) |
| 1147 |
|| |
| 1148 |
!detail::check_x( |
| 1149 |
function, |
| 1150 |
x, |
| 1151 |
&r, |
| 1152 |
Policy())) |
| 1153 |
return (RealType)r;
|
| 1154 |
|
| 1155 |
if ((boost::math::isinf)(v))
|
| 1156 |
{ // Infinite degrees of freedom, so use normal distribution located at delta.
|
| 1157 |
normal_distribution<RealType, Policy> n(l, 1);
|
| 1158 |
return cdf(complement(n, x));
|
| 1159 |
} |
| 1160 |
if(l == 0) |
| 1161 |
{ // zero non-centrality so use Student's t distribution.
|
| 1162 |
return cdf(complement(students_t_distribution<RealType, Policy>(v), x));
|
| 1163 |
} |
| 1164 |
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
|
| 1165 |
detail::non_central_t_cdf( |
| 1166 |
static_cast<value_type>(v),
|
| 1167 |
static_cast<value_type>(l),
|
| 1168 |
static_cast<value_type>(x),
|
| 1169 |
true, Policy()),
|
| 1170 |
function); |
| 1171 |
} // ccdf
|
| 1172 |
|
| 1173 |
template <class RealType, class Policy> |
| 1174 |
inline RealType quantile(const non_central_t_distribution<RealType, Policy>& dist, const RealType& p) |
| 1175 |
{ // Quantile (or Percent Point) function.
|
| 1176 |
static const char* function = "quantile(const non_central_t_distribution<%1%>, %1%)"; |
| 1177 |
RealType v = dist.degrees_of_freedom(); |
| 1178 |
RealType l = dist.non_centrality(); |
| 1179 |
return detail::non_central_t_quantile(function, v, l, p, RealType(1-p), Policy()); |
| 1180 |
} // quantile
|
| 1181 |
|
| 1182 |
template <class RealType, class Policy> |
| 1183 |
inline RealType quantile(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c) |
| 1184 |
{ // Quantile (or Percent Point) function.
|
| 1185 |
static const char* function = "quantile(const complement(non_central_t_distribution<%1%>, %1%))"; |
| 1186 |
non_central_t_distribution<RealType, Policy> const& dist = c.dist;
|
| 1187 |
RealType q = c.param; |
| 1188 |
RealType v = dist.degrees_of_freedom(); |
| 1189 |
RealType l = dist.non_centrality(); |
| 1190 |
return detail::non_central_t_quantile(function, v, l, RealType(1-q), q, Policy()); |
| 1191 |
} // quantile complement.
|
| 1192 |
|
| 1193 |
} // namespace math
|
| 1194 |
} // namespace boost
|
| 1195 |
|
| 1196 |
// This include must be at the end, *after* the accessors
|
| 1197 |
// for this distribution have been defined, in order to
|
| 1198 |
// keep compilers that support two-phase lookup happy.
|
| 1199 |
#include <boost/math/distributions/detail/derived_accessors.hpp> |
| 1200 |
|
| 1201 |
#endif // BOOST_MATH_SPECIAL_NON_CENTRAL_T_HPP |
| 1202 |
|