File indexing completed on 2025-01-18 09:39:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_MATH_SPECIAL_NON_CENTRAL_T_HPP
0011 #define BOOST_MATH_SPECIAL_NON_CENTRAL_T_HPP
0012
0013 #include <boost/math/distributions/fwd.hpp>
0014 #include <boost/math/distributions/non_central_beta.hpp> // for nc beta
0015 #include <boost/math/distributions/normal.hpp> // for normal CDF and quantile
0016 #include <boost/math/distributions/students_t.hpp>
0017 #include <boost/math/distributions/detail/generic_quantile.hpp> // quantile
0018 #include <boost/math/special_functions/trunc.hpp>
0019
0020 namespace boost
0021 {
0022 namespace math
0023 {
0024
0025 template <class RealType, class Policy>
0026 class non_central_t_distribution;
0027
0028 namespace detail{
0029
0030 template <class T, class Policy>
0031 T non_central_t2_p(T v, T delta, T x, T y, const Policy& pol, T init_val)
0032 {
0033 BOOST_MATH_STD_USING
0034
0035
0036
0037 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0038 T errtol = policies::get_epsilon<T, Policy>();
0039 T d2 = delta * delta / 2;
0040
0041
0042
0043
0044
0045
0046
0047 long long k = lltrunc(d2);
0048 T pois;
0049 if(k == 0) k = 1;
0050
0051 pois = gamma_p_derivative(T(k+1), d2, pol)
0052 * tgamma_delta_ratio(T(k + 1), T(0.5f))
0053 * delta / constants::root_two<T>();
0054 if(pois == 0)
0055 return init_val;
0056 T xterm, beta;
0057
0058 beta = x < y
0059 ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, false, true, &xterm)
0060 : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, true, true, &xterm);
0061 xterm *= y / (v / 2 + k);
0062 T poisf(pois), betaf(beta), xtermf(xterm);
0063 T sum = init_val;
0064 if((xterm == 0) && (beta == 0))
0065 return init_val;
0066
0067
0068
0069
0070
0071 std::uintmax_t count = 0;
0072 T last_term = 0;
0073 for(auto i = k; i >= 0; --i)
0074 {
0075 T term = beta * pois;
0076 sum += term;
0077
0078 if(((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol) || (v == 2 && i == 0))
0079 break;
0080 last_term = term;
0081 pois *= (i + 0.5f) / d2;
0082 beta += xterm;
0083 xterm *= (i) / (x * (v / 2 + i - 1));
0084 ++count;
0085 }
0086 last_term = 0;
0087 for(auto i = k + 1; ; ++i)
0088 {
0089 poisf *= d2 / (i + 0.5f);
0090 xtermf *= (x * (v / 2 + i - 1)) / (i);
0091 betaf -= xtermf;
0092 T term = poisf * betaf;
0093 sum += term;
0094 if((fabs(last_term) >= fabs(term)) && (fabs(term/sum) < errtol))
0095 break;
0096 last_term = term;
0097 ++count;
0098 if(count > max_iter)
0099 {
0100 return policies::raise_evaluation_error(
0101 "cdf(non_central_t_distribution<%1%>, %1%)",
0102 "Series did not converge, closest value was %1%", sum, pol);
0103 }
0104 }
0105 return sum;
0106 }
0107
0108 template <class T, class Policy>
0109 T non_central_t2_q(T v, T delta, T x, T y, const Policy& pol, T init_val)
0110 {
0111 BOOST_MATH_STD_USING
0112
0113
0114
0115 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0116 T errtol = boost::math::policies::get_epsilon<T, Policy>();
0117 T d2 = delta * delta / 2;
0118
0119
0120
0121
0122
0123
0124
0125 long long k = lltrunc(d2);
0126 if(k == 0) k = 1;
0127
0128 T pois;
0129 if((k < static_cast<long long>(max_factorial<T>::value)) && (d2 < tools::log_max_value<T>()) && (log(d2) * k < tools::log_max_value<T>()))
0130 {
0131
0132
0133
0134
0135 pois = exp(-d2);
0136 pois *= pow(d2, static_cast<T>(k));
0137 pois /= boost::math::tgamma(T(k + 1 + 0.5), pol);
0138 pois *= delta / constants::root_two<T>();
0139 }
0140 else
0141 {
0142 pois = gamma_p_derivative(T(k+1), d2, pol)
0143 * tgamma_delta_ratio(T(k + 1), T(0.5f))
0144 * delta / constants::root_two<T>();
0145 }
0146 if(pois == 0)
0147 return init_val;
0148
0149 T xterm;
0150 T beta;
0151
0152 if(k != 0)
0153 {
0154 beta = x < y
0155 ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, true, true, &xterm)
0156 : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, false, true, &xterm);
0157
0158 xterm *= y / (v / 2 + k);
0159 }
0160 else
0161 {
0162 beta = pow(y, v / 2);
0163 xterm = beta;
0164 }
0165 T poisf(pois), betaf(beta), xtermf(xterm);
0166 T sum = init_val;
0167 if((xterm == 0) && (beta == 0))
0168 return init_val;
0169
0170
0171
0172
0173 std::uintmax_t count = 0;
0174 T last_term = 0;
0175 for(auto i = k + 1, j = k; ; ++i, --j)
0176 {
0177 poisf *= d2 / (i + 0.5f);
0178 xtermf *= (x * (v / 2 + i - 1)) / (i);
0179 betaf += xtermf;
0180 T term = poisf * betaf;
0181
0182 if(j >= 0)
0183 {
0184 term += beta * pois;
0185 pois *= (j + 0.5f) / d2;
0186 beta -= xterm;
0187 if(!(v == 2 && j == 0))
0188 xterm *= (j) / (x * (v / 2 + j - 1));
0189 }
0190
0191 sum += term;
0192
0193 if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol)
0194 break;
0195 last_term = term;
0196 if(count > max_iter)
0197 {
0198 return policies::raise_evaluation_error(
0199 "cdf(non_central_t_distribution<%1%>, %1%)",
0200 "Series did not converge, closest value was %1%", sum, pol);
0201 }
0202 ++count;
0203 }
0204 return sum;
0205 }
0206
0207 template <class T, class Policy>
0208 T non_central_t_cdf(T v, T delta, T t, bool invert, const Policy& pol)
0209 {
0210 BOOST_MATH_STD_USING
0211 if ((boost::math::isinf)(v))
0212 {
0213 normal_distribution<T, Policy> n(delta, 1);
0214 return cdf(n, t);
0215 }
0216
0217
0218 if(t < 0)
0219 {
0220 t = -t;
0221 delta = -delta;
0222 invert = !invert;
0223 }
0224 if(fabs(delta / (4 * v)) < policies::get_epsilon<T, Policy>())
0225 {
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236 T result = cdf(students_t_distribution<T, Policy>(v), t - delta);
0237 return invert ? 1 - result : result;
0238 }
0239
0240
0241
0242
0243
0244 T x = t * t / (v + t * t);
0245 T y = v / (v + t * t);
0246 T d2 = delta * delta;
0247 T a = 0.5f;
0248 T b = v / 2;
0249 T c = a + b + d2 / 2;
0250
0251
0252
0253
0254 T cross = 1 - (b / c) * (1 + d2 / (2 * c * c));
0255 T result;
0256 if(x < cross)
0257 {
0258
0259
0260
0261 if(x != 0)
0262 {
0263 result = non_central_beta_p(a, b, d2, x, y, pol);
0264 result = non_central_t2_p(v, delta, x, y, pol, result);
0265 result /= 2;
0266 }
0267 else
0268 result = 0;
0269 result += cdf(boost::math::normal_distribution<T, Policy>(), -delta);
0270 }
0271 else
0272 {
0273
0274
0275
0276 invert = !invert;
0277 if(x != 0)
0278 {
0279 result = non_central_beta_q(a, b, d2, x, y, pol);
0280 result = non_central_t2_q(v, delta, x, y, pol, result);
0281 result /= 2;
0282 }
0283 else
0284 result = cdf(complement(boost::math::normal_distribution<T, Policy>(), -delta));
0285 }
0286 if(invert)
0287 result = 1 - result;
0288 return result;
0289 }
0290
0291 template <class T, class Policy>
0292 T non_central_t_quantile(const char* function, T v, T delta, T p, T q, const Policy&)
0293 {
0294 BOOST_MATH_STD_USING
0295
0296
0297 typedef typename policies::evaluation<T, Policy>::type value_type;
0298 typedef typename policies::normalise<
0299 Policy,
0300 policies::promote_float<false>,
0301 policies::promote_double<false>,
0302 policies::discrete_quantile<>,
0303 policies::assert_undefined<> >::type forwarding_policy;
0304
0305 T r;
0306 if(!detail::check_df_gt0_to_inf(
0307 function,
0308 v, &r, Policy())
0309 ||
0310 !detail::check_non_centrality(
0311 function,
0312 static_cast<T>(delta * delta),
0313 &r,
0314 Policy())
0315 ||
0316 !detail::check_probability(
0317 function,
0318 p,
0319 &r,
0320 Policy()))
0321 return r;
0322
0323
0324 value_type guess = 0;
0325 if ( ((boost::math::isinf)(v)) || (v > 1 / boost::math::tools::epsilon<T>()) )
0326 {
0327 normal_distribution<T, Policy> n(delta, 1);
0328 if (p < q)
0329 {
0330 return quantile(n, p);
0331 }
0332 else
0333 {
0334 return quantile(complement(n, q));
0335 }
0336 }
0337 else if(v > 3)
0338 {
0339 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));
0340 value_type var = (v > 1 / policies::get_epsilon<T, Policy>()) ? value_type(1) : (((delta * delta + 1) * v) / (v - 2) - mean * mean);
0341 if(p < q)
0342 guess = quantile(normal_distribution<value_type, forwarding_policy>(mean, var), p);
0343 else
0344 guess = quantile(complement(normal_distribution<value_type, forwarding_policy>(mean, var), q));
0345 }
0346
0347
0348
0349
0350 value_type pzero = non_central_t_cdf(
0351 static_cast<value_type>(v),
0352 static_cast<value_type>(delta),
0353 static_cast<value_type>(0),
0354 !(p < q),
0355 forwarding_policy());
0356 int s;
0357 if(p < q)
0358 s = boost::math::sign(p - pzero);
0359 else
0360 s = boost::math::sign(pzero - q);
0361 if(s != boost::math::sign(guess))
0362 {
0363 guess = static_cast<T>(s);
0364 }
0365
0366 value_type result = detail::generic_quantile(
0367 non_central_t_distribution<value_type, forwarding_policy>(v, delta),
0368 (p < q ? p : q),
0369 guess,
0370 (p >= q),
0371 function);
0372 return policies::checked_narrowing_cast<T, forwarding_policy>(
0373 result,
0374 function);
0375 }
0376
0377 template <class T, class Policy>
0378 T non_central_t2_pdf(T n, T delta, T x, T y, const Policy& pol, T init_val)
0379 {
0380 BOOST_MATH_STD_USING
0381
0382
0383
0384 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0385 T errtol = boost::math::policies::get_epsilon<T, Policy>();
0386 T d2 = delta * delta / 2;
0387
0388
0389
0390
0391 long long k = lltrunc(d2);
0392 T pois, xterm;
0393 if(k == 0)
0394 k = 1;
0395
0396 pois = gamma_p_derivative(T(k+1), d2, pol)
0397 * tgamma_delta_ratio(T(k + 1), T(0.5f))
0398 * delta / constants::root_two<T>();
0399 BOOST_MATH_INSTRUMENT_VARIABLE(pois);
0400
0401 xterm = x < y
0402 ? ibeta_derivative(T(k + 1), n / 2, x, pol)
0403 : ibeta_derivative(n / 2, T(k + 1), y, pol);
0404 BOOST_MATH_INSTRUMENT_VARIABLE(xterm);
0405 T poisf(pois), xtermf(xterm);
0406 T sum = init_val;
0407 if((pois == 0) || (xterm == 0))
0408 return init_val;
0409
0410
0411
0412
0413
0414 std::uintmax_t count = 0;
0415 T old_ratio = 1;
0416 for(auto i = k; i >= 0; --i)
0417 {
0418 T term = xterm * pois;
0419 sum += term;
0420 BOOST_MATH_INSTRUMENT_VARIABLE(sum);
0421 T ratio = fabs(term / sum);
0422 if(((ratio < errtol) && (i != k) && (ratio < old_ratio)) || (term == 0))
0423 break;
0424 old_ratio = ratio;
0425 pois *= (i + 0.5f) / d2;
0426 xterm *= (i) / (x * (n / 2 + i));
0427 ++count;
0428 if(count > max_iter)
0429 {
0430 return policies::raise_evaluation_error(
0431 "pdf(non_central_t_distribution<%1%>, %1%)",
0432 "Series did not converge, closest value was %1%", sum, pol);
0433 }
0434 }
0435 BOOST_MATH_INSTRUMENT_VARIABLE(sum);
0436 for(auto i = k + 1; ; ++i)
0437 {
0438 poisf *= d2 / (i + 0.5f);
0439 xtermf *= (x * (n / 2 + i)) / (i);
0440 T term = poisf * xtermf;
0441 sum += term;
0442 if((fabs(term/sum) < errtol) || (term == 0))
0443 break;
0444 ++count;
0445 if(count > max_iter)
0446 {
0447 return policies::raise_evaluation_error(
0448 "pdf(non_central_t_distribution<%1%>, %1%)",
0449 "Series did not converge, closest value was %1%", sum, pol);
0450 }
0451 }
0452 BOOST_MATH_INSTRUMENT_VARIABLE(sum);
0453 return sum;
0454 }
0455
0456 template <class T, class Policy>
0457 T non_central_t_pdf(T n, T delta, T t, const Policy& pol)
0458 {
0459 BOOST_MATH_STD_USING
0460 if ((boost::math::isinf)(n))
0461 {
0462 normal_distribution<T, Policy> norm(delta, 1);
0463 return pdf(norm, t);
0464 }
0465
0466
0467 if(t < 0)
0468 {
0469 t = -t;
0470 delta = -delta;
0471 }
0472 if(t == 0)
0473 {
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484 return tgamma_delta_ratio(n / 2 + 0.5f, T(0.5f))
0485 * sqrt(n / constants::pi<T>())
0486 * exp(-delta * delta / 2) / 2;
0487 }
0488 if(fabs(delta / (4 * n)) < policies::get_epsilon<T, Policy>())
0489 {
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500 return pdf(students_t_distribution<T, Policy>(n), t - delta);
0501 }
0502
0503
0504
0505
0506
0507 T x = t * t / (n + t * t);
0508 T y = n / (n + t * t);
0509 T a = 0.5f;
0510 T b = n / 2;
0511 T d2 = delta * delta;
0512
0513
0514
0515 T dt = n * t / (n * n + 2 * n * t * t + t * t * t * t);
0516 BOOST_MATH_INSTRUMENT_VARIABLE(dt);
0517 T result = non_central_beta_pdf(a, b, d2, x, y, pol);
0518 BOOST_MATH_INSTRUMENT_VARIABLE(result);
0519 T tol = tools::epsilon<T>() * result * 500;
0520 result = non_central_t2_pdf(n, delta, x, y, pol, result);
0521 BOOST_MATH_INSTRUMENT_VARIABLE(result);
0522 if(result <= tol)
0523 result = 0;
0524 result *= dt;
0525 return result;
0526 }
0527
0528 template <class T, class Policy>
0529 T mean(T v, T delta, const Policy& pol)
0530 {
0531 if ((boost::math::isinf)(v))
0532 {
0533 return delta;
0534 }
0535 BOOST_MATH_STD_USING
0536 if (v > 1 / boost::math::tools::epsilon<T>() )
0537 {
0538
0539
0540 return delta;
0541 }
0542 else
0543 {
0544 return delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f), pol);
0545 }
0546
0547 }
0548
0549 template <class T, class Policy>
0550 T variance(T v, T delta, const Policy& pol)
0551 {
0552 if ((boost::math::isinf)(v))
0553 {
0554 return 1;
0555 }
0556 if (delta == 0)
0557 {
0558 return v / (v - 2);
0559 }
0560 T result = ((delta * delta + 1) * v) / (v - 2);
0561 T m = mean(v, delta, pol);
0562 result -= m * m;
0563 return result;
0564 }
0565
0566 template <class T, class Policy>
0567 T skewness(T v, T delta, const Policy& pol)
0568 {
0569 BOOST_MATH_STD_USING
0570 if ((boost::math::isinf)(v))
0571 {
0572 return 0;
0573 }
0574 if(delta == 0)
0575 {
0576 return 0;
0577 }
0578 T mean = boost::math::detail::mean(v, delta, pol);
0579 T l2 = delta * delta;
0580 T var = ((l2 + 1) * v) / (v - 2) - mean * mean;
0581 T result = -2 * var;
0582 result += v * (l2 + 2 * v - 3) / ((v - 3) * (v - 2));
0583 result *= mean;
0584 result /= pow(var, T(1.5f));
0585 return result;
0586 }
0587
0588 template <class T, class Policy>
0589 T kurtosis_excess(T v, T delta, const Policy& pol)
0590 {
0591 BOOST_MATH_STD_USING
0592 if ((boost::math::isinf)(v))
0593 {
0594 return 1;
0595 }
0596 if (delta == 0)
0597 {
0598 return 1;
0599 }
0600 T mean = boost::math::detail::mean(v, delta, pol);
0601 T l2 = delta * delta;
0602 T var = ((l2 + 1) * v) / (v - 2) - mean * mean;
0603 T result = -3 * var;
0604 result += v * (l2 * (v + 1) + 3 * (3 * v - 5)) / ((v - 3) * (v - 2));
0605 result *= -mean * mean;
0606 result += v * v * (l2 * l2 + 6 * l2 + 3) / ((v - 4) * (v - 2));
0607 result /= var * var;
0608 result -= static_cast<T>(3);
0609 return result;
0610 }
0611
0612 #if 0
0613
0614
0615
0616
0617 template <class RealType, class Policy>
0618 struct t_degrees_of_freedom_finder
0619 {
0620 t_degrees_of_freedom_finder(
0621 RealType delta_, RealType x_, RealType p_, bool c)
0622 : delta(delta_), x(x_), p(p_), comp(c) {}
0623
0624 RealType operator()(const RealType& v)
0625 {
0626 non_central_t_distribution<RealType, Policy> d(v, delta);
0627 return comp ?
0628 p - cdf(complement(d, x))
0629 : cdf(d, x) - p;
0630 }
0631 private:
0632 RealType delta;
0633 RealType x;
0634 RealType p;
0635 bool comp;
0636 };
0637
0638 template <class RealType, class Policy>
0639 inline RealType find_t_degrees_of_freedom(
0640 RealType delta, RealType x, RealType p, RealType q, const Policy& pol)
0641 {
0642 const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
0643 if((p == 0) || (q == 0))
0644 {
0645
0646
0647
0648 return policies::raise_evaluation_error<RealType>(function,
0649 "Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%",
0650 RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
0651 }
0652 t_degrees_of_freedom_finder<RealType, Policy> f(delta, x, p < q ? p : q, p < q ? false : true);
0653 tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
0654 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0655
0656
0657
0658 RealType guess = 200;
0659 std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
0660 f, guess, RealType(2), false, tol, max_iter, pol);
0661 RealType result = ir.first + (ir.second - ir.first) / 2;
0662 if(max_iter >= policies::get_max_root_iterations<Policy>())
0663 {
0664 return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
0665 " or there is no answer to problem. Current best guess is %1%", result, Policy());
0666 }
0667 return result;
0668 }
0669
0670 template <class RealType, class Policy>
0671 struct t_non_centrality_finder
0672 {
0673 t_non_centrality_finder(
0674 RealType v_, RealType x_, RealType p_, bool c)
0675 : v(v_), x(x_), p(p_), comp(c) {}
0676
0677 RealType operator()(const RealType& delta)
0678 {
0679 non_central_t_distribution<RealType, Policy> d(v, delta);
0680 return comp ?
0681 p - cdf(complement(d, x))
0682 : cdf(d, x) - p;
0683 }
0684 private:
0685 RealType v;
0686 RealType x;
0687 RealType p;
0688 bool comp;
0689 };
0690
0691 template <class RealType, class Policy>
0692 inline RealType find_t_non_centrality(
0693 RealType v, RealType x, RealType p, RealType q, const Policy& pol)
0694 {
0695 const char* function = "non_central_t<%1%>::find_t_non_centrality";
0696 if((p == 0) || (q == 0))
0697 {
0698
0699
0700
0701 return policies::raise_evaluation_error<RealType>(function,
0702 "Can't find non-centrality parameter when the probability is 0 or 1, only possible answer is %1%",
0703 RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
0704 }
0705 t_non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
0706 tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
0707 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0708
0709
0710
0711
0712 RealType guess;
0713 if(f(0) < 0)
0714 guess = 1;
0715 else
0716 guess = -1;
0717 std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
0718 f, guess, RealType(2), false, tol, max_iter, pol);
0719 RealType result = ir.first + (ir.second - ir.first) / 2;
0720 if(max_iter >= policies::get_max_root_iterations<Policy>())
0721 {
0722 return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
0723 " or there is no answer to problem. Current best guess is %1%", result, Policy());
0724 }
0725 return result;
0726 }
0727 #endif
0728 }
0729
0730 template <class RealType = double, class Policy = policies::policy<> >
0731 class non_central_t_distribution
0732 {
0733 public:
0734 typedef RealType value_type;
0735 typedef Policy policy_type;
0736
0737 non_central_t_distribution(RealType v_, RealType lambda) : v(v_), ncp(lambda)
0738 {
0739 const char* function = "boost::math::non_central_t_distribution<%1%>::non_central_t_distribution(%1%,%1%)";
0740 RealType r;
0741 detail::check_df_gt0_to_inf(
0742 function,
0743 v, &r, Policy());
0744 detail::check_non_centrality(
0745 function,
0746 static_cast<value_type>(lambda * lambda),
0747 &r,
0748 Policy());
0749 }
0750
0751 RealType degrees_of_freedom() const
0752 {
0753 return v;
0754 }
0755 RealType non_centrality() const
0756 {
0757 return ncp;
0758 }
0759 #if 0
0760
0761
0762
0763
0764 static RealType find_degrees_of_freedom(RealType delta, RealType x, RealType p)
0765 {
0766 const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
0767 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0768 typedef typename policies::normalise<
0769 Policy,
0770 policies::promote_float<false>,
0771 policies::promote_double<false>,
0772 policies::discrete_quantile<>,
0773 policies::assert_undefined<> >::type forwarding_policy;
0774 value_type result = detail::find_t_degrees_of_freedom(
0775 static_cast<value_type>(delta),
0776 static_cast<value_type>(x),
0777 static_cast<value_type>(p),
0778 static_cast<value_type>(1-p),
0779 forwarding_policy());
0780 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0781 result,
0782 function);
0783 }
0784 template <class A, class B, class C>
0785 static RealType find_degrees_of_freedom(const complemented3_type<A,B,C>& c)
0786 {
0787 const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
0788 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0789 typedef typename policies::normalise<
0790 Policy,
0791 policies::promote_float<false>,
0792 policies::promote_double<false>,
0793 policies::discrete_quantile<>,
0794 policies::assert_undefined<> >::type forwarding_policy;
0795 value_type result = detail::find_t_degrees_of_freedom(
0796 static_cast<value_type>(c.dist),
0797 static_cast<value_type>(c.param1),
0798 static_cast<value_type>(1-c.param2),
0799 static_cast<value_type>(c.param2),
0800 forwarding_policy());
0801 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0802 result,
0803 function);
0804 }
0805 static RealType find_non_centrality(RealType v, RealType x, RealType p)
0806 {
0807 const char* function = "non_central_t<%1%>::find_t_non_centrality";
0808 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0809 typedef typename policies::normalise<
0810 Policy,
0811 policies::promote_float<false>,
0812 policies::promote_double<false>,
0813 policies::discrete_quantile<>,
0814 policies::assert_undefined<> >::type forwarding_policy;
0815 value_type result = detail::find_t_non_centrality(
0816 static_cast<value_type>(v),
0817 static_cast<value_type>(x),
0818 static_cast<value_type>(p),
0819 static_cast<value_type>(1-p),
0820 forwarding_policy());
0821 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0822 result,
0823 function);
0824 }
0825 template <class A, class B, class C>
0826 static RealType find_non_centrality(const complemented3_type<A,B,C>& c)
0827 {
0828 const char* function = "non_central_t<%1%>::find_t_non_centrality";
0829 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0830 typedef typename policies::normalise<
0831 Policy,
0832 policies::promote_float<false>,
0833 policies::promote_double<false>,
0834 policies::discrete_quantile<>,
0835 policies::assert_undefined<> >::type forwarding_policy;
0836 value_type result = detail::find_t_non_centrality(
0837 static_cast<value_type>(c.dist),
0838 static_cast<value_type>(c.param1),
0839 static_cast<value_type>(1-c.param2),
0840 static_cast<value_type>(c.param2),
0841 forwarding_policy());
0842 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0843 result,
0844 function);
0845 }
0846 #endif
0847 private:
0848
0849 RealType v;
0850 RealType ncp;
0851 };
0852
0853 typedef non_central_t_distribution<double> non_central_t;
0854
0855 #ifdef __cpp_deduction_guides
0856 template <class RealType>
0857 non_central_t_distribution(RealType,RealType)->non_central_t_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0858 #endif
0859
0860
0861
0862 template <class RealType, class Policy>
0863 inline const std::pair<RealType, RealType> range(const non_central_t_distribution<RealType, Policy>& )
0864 {
0865 using boost::math::tools::max_value;
0866 return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
0867 }
0868
0869 template <class RealType, class Policy>
0870 inline const std::pair<RealType, RealType> support(const non_central_t_distribution<RealType, Policy>& )
0871 {
0872
0873 using boost::math::tools::max_value;
0874 return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
0875 }
0876
0877 template <class RealType, class Policy>
0878 inline RealType mode(const non_central_t_distribution<RealType, Policy>& dist)
0879 {
0880 static const char* function = "mode(non_central_t_distribution<%1%> const&)";
0881 RealType v = dist.degrees_of_freedom();
0882 RealType l = dist.non_centrality();
0883 RealType r;
0884 if(!detail::check_df_gt0_to_inf(
0885 function,
0886 v, &r, Policy())
0887 ||
0888 !detail::check_non_centrality(
0889 function,
0890 static_cast<RealType>(l * l),
0891 &r,
0892 Policy()))
0893 return static_cast<RealType>(r);
0894
0895 BOOST_MATH_STD_USING
0896
0897 RealType m = v < 3 ? 0 : detail::mean(v, l, Policy());
0898 RealType var = v < 4 ? 1 : detail::variance(v, l, Policy());
0899
0900 return detail::generic_find_mode(
0901 dist,
0902 m,
0903 function,
0904 sqrt(var));
0905 }
0906
0907 template <class RealType, class Policy>
0908 inline RealType mean(const non_central_t_distribution<RealType, Policy>& dist)
0909 {
0910 BOOST_MATH_STD_USING
0911 const char* function = "mean(const non_central_t_distribution<%1%>&)";
0912 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0913 typedef typename policies::normalise<
0914 Policy,
0915 policies::promote_float<false>,
0916 policies::promote_double<false>,
0917 policies::discrete_quantile<>,
0918 policies::assert_undefined<> >::type forwarding_policy;
0919 RealType v = dist.degrees_of_freedom();
0920 RealType l = dist.non_centrality();
0921 RealType r;
0922 if(!detail::check_df_gt0_to_inf(
0923 function,
0924 v, &r, Policy())
0925 ||
0926 !detail::check_non_centrality(
0927 function,
0928 static_cast<RealType>(l * l),
0929 &r,
0930 Policy()))
0931 return static_cast<RealType>(r);
0932 if(v <= 1)
0933 return policies::raise_domain_error<RealType>(
0934 function,
0935 "The non-central t distribution has no defined mean for degrees of freedom <= 1: got v=%1%.", v, Policy());
0936
0937 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0938 detail::mean(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
0939
0940 }
0941
0942 template <class RealType, class Policy>
0943 inline RealType variance(const non_central_t_distribution<RealType, Policy>& dist)
0944 {
0945 const char* function = "variance(const non_central_t_distribution<%1%>&)";
0946 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0947 typedef typename policies::normalise<
0948 Policy,
0949 policies::promote_float<false>,
0950 policies::promote_double<false>,
0951 policies::discrete_quantile<>,
0952 policies::assert_undefined<> >::type forwarding_policy;
0953 BOOST_MATH_STD_USING
0954 RealType v = dist.degrees_of_freedom();
0955 RealType l = dist.non_centrality();
0956 RealType r;
0957 if(!detail::check_df_gt0_to_inf(
0958 function,
0959 v, &r, Policy())
0960 ||
0961 !detail::check_non_centrality(
0962 function,
0963 static_cast<RealType>(l * l),
0964 &r,
0965 Policy()))
0966 return static_cast<RealType>(r);
0967 if(v <= 2)
0968 return policies::raise_domain_error<RealType>(
0969 function,
0970 "The non-central t distribution has no defined variance for degrees of freedom <= 2: got v=%1%.", v, Policy());
0971 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0972 detail::variance(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
0973 }
0974
0975
0976
0977
0978 template <class RealType, class Policy>
0979 inline RealType skewness(const non_central_t_distribution<RealType, Policy>& dist)
0980 {
0981 const char* function = "skewness(const non_central_t_distribution<%1%>&)";
0982 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0983 typedef typename policies::normalise<
0984 Policy,
0985 policies::promote_float<false>,
0986 policies::promote_double<false>,
0987 policies::discrete_quantile<>,
0988 policies::assert_undefined<> >::type forwarding_policy;
0989 RealType v = dist.degrees_of_freedom();
0990 RealType l = dist.non_centrality();
0991 RealType r;
0992 if(!detail::check_df_gt0_to_inf(
0993 function,
0994 v, &r, Policy())
0995 ||
0996 !detail::check_non_centrality(
0997 function,
0998 static_cast<RealType>(l * l),
0999 &r,
1000 Policy()))
1001 return static_cast<RealType>(r);
1002 if(v <= 3)
1003 return policies::raise_domain_error<RealType>(
1004 function,
1005 "The non-central t distribution has no defined skewness for degrees of freedom <= 3: got v=%1%.", v, Policy());;
1006 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
1007 detail::skewness(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
1008 }
1009
1010 template <class RealType, class Policy>
1011 inline RealType kurtosis_excess(const non_central_t_distribution<RealType, Policy>& dist)
1012 {
1013 const char* function = "kurtosis_excess(const non_central_t_distribution<%1%>&)";
1014 typedef typename policies::evaluation<RealType, Policy>::type value_type;
1015 typedef typename policies::normalise<
1016 Policy,
1017 policies::promote_float<false>,
1018 policies::promote_double<false>,
1019 policies::discrete_quantile<>,
1020 policies::assert_undefined<> >::type forwarding_policy;
1021 RealType v = dist.degrees_of_freedom();
1022 RealType l = dist.non_centrality();
1023 RealType r;
1024 if(!detail::check_df_gt0_to_inf(
1025 function,
1026 v, &r, Policy())
1027 ||
1028 !detail::check_non_centrality(
1029 function,
1030 static_cast<RealType>(l * l),
1031 &r,
1032 Policy()))
1033 return static_cast<RealType>(r);
1034 if(v <= 4)
1035 return policies::raise_domain_error<RealType>(
1036 function,
1037 "The non-central t distribution has no defined kurtosis for degrees of freedom <= 4: got v=%1%.", v, Policy());;
1038 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
1039 detail::kurtosis_excess(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
1040 }
1041
1042 template <class RealType, class Policy>
1043 inline RealType kurtosis(const non_central_t_distribution<RealType, Policy>& dist)
1044 {
1045 return kurtosis_excess(dist) + 3;
1046 }
1047
1048 template <class RealType, class Policy>
1049 inline RealType pdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& t)
1050 {
1051 const char* function = "pdf(non_central_t_distribution<%1%>, %1%)";
1052 typedef typename policies::evaluation<RealType, Policy>::type value_type;
1053 typedef typename policies::normalise<
1054 Policy,
1055 policies::promote_float<false>,
1056 policies::promote_double<false>,
1057 policies::discrete_quantile<>,
1058 policies::assert_undefined<> >::type forwarding_policy;
1059
1060 RealType v = dist.degrees_of_freedom();
1061 RealType l = dist.non_centrality();
1062 RealType r;
1063 if(!detail::check_df_gt0_to_inf(
1064 function,
1065 v, &r, Policy())
1066 ||
1067 !detail::check_non_centrality(
1068 function,
1069 static_cast<RealType>(l * l),
1070 &r,
1071 Policy())
1072 ||
1073 !detail::check_x(
1074 function,
1075 t,
1076 &r,
1077 Policy()))
1078 return static_cast<RealType>(r);
1079 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
1080 detail::non_central_t_pdf(static_cast<value_type>(v),
1081 static_cast<value_type>(l),
1082 static_cast<value_type>(t),
1083 Policy()),
1084 function);
1085 }
1086
1087 template <class RealType, class Policy>
1088 RealType cdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& x)
1089 {
1090 const char* function = "boost::math::cdf(non_central_t_distribution<%1%>&, %1%)";
1091
1092 typedef typename policies::evaluation<RealType, Policy>::type value_type;
1093 typedef typename policies::normalise<
1094 Policy,
1095 policies::promote_float<false>,
1096 policies::promote_double<false>,
1097 policies::discrete_quantile<>,
1098 policies::assert_undefined<> >::type forwarding_policy;
1099
1100 RealType v = dist.degrees_of_freedom();
1101 RealType l = dist.non_centrality();
1102 RealType r;
1103 if(!detail::check_df_gt0_to_inf(
1104 function,
1105 v, &r, Policy())
1106 ||
1107 !detail::check_non_centrality(
1108 function,
1109 static_cast<RealType>(l * l),
1110 &r,
1111 Policy())
1112 ||
1113 !detail::check_x(
1114 function,
1115 x,
1116 &r,
1117 Policy()))
1118 return static_cast<RealType>(r);
1119 if ((boost::math::isinf)(v))
1120 {
1121 normal_distribution<RealType, Policy> n(l, 1);
1122 cdf(n, x);
1123
1124 }
1125
1126 if(l == 0)
1127 {
1128 return cdf(students_t_distribution<RealType, Policy>(v), x);
1129 }
1130 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
1131 detail::non_central_t_cdf(
1132 static_cast<value_type>(v),
1133 static_cast<value_type>(l),
1134 static_cast<value_type>(x),
1135 false, Policy()),
1136 function);
1137 }
1138
1139 template <class RealType, class Policy>
1140 RealType cdf(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
1141 {
1142
1143 const char* function = "boost::math::cdf(const complement(non_central_t_distribution<%1%>&), %1%)";
1144 typedef typename policies::evaluation<RealType, Policy>::type value_type;
1145 typedef typename policies::normalise<
1146 Policy,
1147 policies::promote_float<false>,
1148 policies::promote_double<false>,
1149 policies::discrete_quantile<>,
1150 policies::assert_undefined<> >::type forwarding_policy;
1151
1152 non_central_t_distribution<RealType, Policy> const& dist = c.dist;
1153 RealType x = c.param;
1154 RealType v = dist.degrees_of_freedom();
1155 RealType l = dist.non_centrality();
1156 RealType r;
1157 if(!detail::check_df_gt0_to_inf(
1158 function,
1159 v, &r, Policy())
1160 ||
1161 !detail::check_non_centrality(
1162 function,
1163 static_cast<RealType>(l * l),
1164 &r,
1165 Policy())
1166 ||
1167 !detail::check_x(
1168 function,
1169 x,
1170 &r,
1171 Policy()))
1172 return static_cast<RealType>(r);
1173
1174 if ((boost::math::isinf)(v))
1175 {
1176 normal_distribution<RealType, Policy> n(l, 1);
1177 return cdf(complement(n, x));
1178 }
1179 if(l == 0)
1180 {
1181 return cdf(complement(students_t_distribution<RealType, Policy>(v), x));
1182 }
1183 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
1184 detail::non_central_t_cdf(
1185 static_cast<value_type>(v),
1186 static_cast<value_type>(l),
1187 static_cast<value_type>(x),
1188 true, Policy()),
1189 function);
1190 }
1191
1192 template <class RealType, class Policy>
1193 inline RealType quantile(const non_central_t_distribution<RealType, Policy>& dist, const RealType& p)
1194 {
1195 static const char* function = "quantile(const non_central_t_distribution<%1%>, %1%)";
1196 RealType v = dist.degrees_of_freedom();
1197 RealType l = dist.non_centrality();
1198 return detail::non_central_t_quantile(function, v, l, p, RealType(1-p), Policy());
1199 }
1200
1201 template <class RealType, class Policy>
1202 inline RealType quantile(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
1203 {
1204 static const char* function = "quantile(const complement(non_central_t_distribution<%1%>, %1%))";
1205 non_central_t_distribution<RealType, Policy> const& dist = c.dist;
1206 RealType q = c.param;
1207 RealType v = dist.degrees_of_freedom();
1208 RealType l = dist.non_centrality();
1209 return detail::non_central_t_quantile(function, v, l, RealType(1-q), q, Policy());
1210 }
1211
1212 }
1213 }
1214
1215
1216
1217
1218 #include <boost/math/distributions/detail/derived_accessors.hpp>
1219
1220 #endif
1221