File indexing completed on 2025-07-11 08:14:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP
0011 #define BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP
0012
0013 #include <boost/math/distributions/fwd.hpp>
0014 #include <boost/math/special_functions/gamma.hpp> // for incomplete gamma. gamma_q
0015 #include <boost/math/special_functions/bessel.hpp> // for cyl_bessel_i
0016 #include <boost/math/special_functions/round.hpp> // for llround
0017 #include <boost/math/distributions/complement.hpp> // complements
0018 #include <boost/math/distributions/chi_squared.hpp> // central distribution
0019 #include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
0020 #include <boost/math/special_functions/fpclassify.hpp> // isnan.
0021 #include <boost/math/tools/roots.hpp> // for root finding.
0022 #include <boost/math/distributions/detail/generic_mode.hpp>
0023 #include <boost/math/distributions/detail/generic_quantile.hpp>
0024
0025 namespace boost
0026 {
0027 namespace math
0028 {
0029
0030 template <class RealType, class Policy>
0031 class non_central_chi_squared_distribution;
0032
0033 namespace detail{
0034
0035 template <class T, class Policy>
0036 T non_central_chi_square_q(T x, T f, T theta, const Policy& pol, T init_sum = 0)
0037 {
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 BOOST_MATH_STD_USING
0054
0055
0056 if(x == 0)
0057 return 1;
0058
0059
0060
0061
0062 T lambda = theta / 2;
0063 T del = f / 2;
0064 T y = x / 2;
0065 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0066 T errtol = boost::math::policies::get_epsilon<T, Policy>();
0067 T sum = init_sum;
0068
0069
0070
0071
0072
0073
0074 long long k = llround(lambda, pol);
0075
0076 T poisf = boost::math::gamma_p_derivative(static_cast<T>(1 + k), lambda, pol);
0077 T poisb = poisf * k / lambda;
0078
0079 T gamf = boost::math::gamma_q(del + k, y, pol);
0080
0081 T xtermf = boost::math::gamma_p_derivative(del + 1 + k, y, pol);
0082 T xtermb = xtermf * (del + k) / y;
0083
0084 T gamb = gamf - xtermb;
0085
0086
0087
0088
0089
0090
0091 long long i;
0092 for(i = k; static_cast<std::uintmax_t>(i-k) < max_iter; ++i)
0093 {
0094 T term = poisf * gamf;
0095 sum += term;
0096 poisf *= lambda / (i + 1);
0097 gamf += xtermf;
0098 xtermf *= y / (del + i + 1);
0099 if(((sum == 0) || (fabs(term / sum) < errtol)) && (term >= poisf * gamf))
0100 break;
0101 }
0102
0103 if(static_cast<std::uintmax_t>(i-k) >= max_iter)
0104 return policies::raise_evaluation_error("cdf(non_central_chi_squared_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol);
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 for(i = k - 1; i >= 0; --i)
0115 {
0116 T term = poisb * gamb;
0117 sum += term;
0118 poisb *= i / lambda;
0119 xtermb *= (del + i) / y;
0120 gamb -= xtermb;
0121 if((sum == 0) || (fabs(term / sum) < errtol))
0122 break;
0123 }
0124
0125 return sum;
0126 }
0127
0128 template <class T, class Policy>
0129 T non_central_chi_square_p_ding(T x, T f, T theta, const Policy& pol, T init_sum = 0)
0130 {
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 BOOST_MATH_STD_USING
0147
0148 if(x == 0)
0149 return 0;
0150 T tk = boost::math::gamma_p_derivative(f/2 + 1, x/2, pol);
0151 T lambda = theta / 2;
0152 T vk = exp(-lambda);
0153 T uk = vk;
0154 T sum = init_sum + tk * vk;
0155 if(sum == 0)
0156 return sum;
0157
0158 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0159 T errtol = boost::math::policies::get_epsilon<T, Policy>();
0160
0161 int i;
0162 T lterm(0), term(0);
0163 for(i = 1; static_cast<std::uintmax_t>(i) < max_iter; ++i)
0164 {
0165 tk = tk * x / (f + 2 * i);
0166 uk = uk * lambda / i;
0167 vk = vk + uk;
0168 lterm = term;
0169 term = vk * tk;
0170 sum += term;
0171 if((fabs(term / sum) < errtol) && (term <= lterm))
0172 break;
0173 }
0174
0175 if(static_cast<std::uintmax_t>(i) >= max_iter)
0176 return policies::raise_evaluation_error("cdf(non_central_chi_squared_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol);
0177 return sum;
0178 }
0179
0180
0181 template <class T, class Policy>
0182 T non_central_chi_square_p(T y, T n, T lambda, const Policy& pol, T init_sum)
0183 {
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197 BOOST_MATH_STD_USING
0198
0199 if(y == 0)
0200 return 0;
0201 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0202 T errtol = boost::math::policies::get_epsilon<T, Policy>();
0203 T errorf(0), errorb(0);
0204
0205 T x = y / 2;
0206 T del = lambda / 2;
0207
0208
0209
0210
0211
0212
0213
0214 long long k = llround(del, pol);
0215 T a = n / 2 + k;
0216
0217 T gamkf = boost::math::gamma_p(a, x, pol);
0218
0219 if(lambda == 0)
0220 return gamkf;
0221
0222 T gamkb = gamkf;
0223
0224 T poiskf = gamma_p_derivative(static_cast<T>(k+1), del, pol);
0225
0226 T poiskb = poiskf;
0227
0228 T xtermf = boost::math::gamma_p_derivative(a, x, pol);
0229
0230 T xtermb = xtermf * x / a;
0231 T sum = init_sum + poiskf * gamkf;
0232 if(sum == 0)
0233 return sum;
0234 int i = 1;
0235
0236
0237
0238
0239 while(i <= k)
0240 {
0241 xtermb *= (a - i + 1) / x;
0242 gamkb += xtermb;
0243 poiskb = poiskb * (k - i + 1) / del;
0244 errorf = errorb;
0245 errorb = gamkb * poiskb;
0246 sum += errorb;
0247 if((fabs(errorb / sum) < errtol) && (errorb <= errorf))
0248 break;
0249 ++i;
0250 }
0251 i = 1;
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261 do
0262 {
0263 xtermf = xtermf * x / (a + i - 1);
0264 gamkf = gamkf - xtermf;
0265 poiskf = poiskf * del / (k + i);
0266 errorf = poiskf * gamkf;
0267 sum += errorf;
0268 ++i;
0269 }while((fabs(errorf / sum) > errtol) && (static_cast<std::uintmax_t>(i) < max_iter));
0270
0271
0272 if(static_cast<std::uintmax_t>(i) >= max_iter)
0273 return policies::raise_evaluation_error("cdf(non_central_chi_squared_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol);
0274
0275 return sum;
0276 }
0277
0278 template <class T, class Policy>
0279 T non_central_chi_square_pdf(T x, T n, T lambda, const Policy& pol)
0280 {
0281
0282
0283
0284 BOOST_MATH_STD_USING
0285 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0286 T errtol = boost::math::policies::get_epsilon<T, Policy>();
0287 T x2 = x / 2;
0288 T n2 = n / 2;
0289 T l2 = lambda / 2;
0290 T sum = 0;
0291 long long k = lltrunc(l2);
0292 T pois = gamma_p_derivative(static_cast<T>(k + 1), l2, pol) * gamma_p_derivative(static_cast<T>(n2 + k), x2);
0293 if(pois == 0)
0294 return 0;
0295 T poisb = pois;
0296 for(long long i = k; ; ++i)
0297 {
0298 sum += pois;
0299 if(pois / sum < errtol)
0300 break;
0301 if(static_cast<std::uintmax_t>(i - k) >= max_iter)
0302 return policies::raise_evaluation_error("pdf(non_central_chi_squared_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol);
0303 pois *= l2 * x2 / ((i + 1) * (n2 + i));
0304 }
0305 for(long long i = k - 1; i >= 0; --i)
0306 {
0307 poisb *= (i + 1) * (n2 + i) / (l2 * x2);
0308 sum += poisb;
0309 if(poisb / sum < errtol)
0310 break;
0311 }
0312 return sum / 2;
0313 }
0314
0315 template <class RealType, class Policy>
0316 inline RealType non_central_chi_squared_cdf(RealType x, RealType k, RealType l, bool invert, const Policy&)
0317 {
0318 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0319 typedef typename policies::normalise<
0320 Policy,
0321 policies::promote_float<false>,
0322 policies::promote_double<false>,
0323 policies::discrete_quantile<>,
0324 policies::assert_undefined<> >::type forwarding_policy;
0325
0326 BOOST_MATH_STD_USING
0327 value_type result;
0328 if(l == 0)
0329 return invert == false ? cdf(boost::math::chi_squared_distribution<RealType, Policy>(k), x) : cdf(complement(boost::math::chi_squared_distribution<RealType, Policy>(k), x));
0330 else if(x > k + l)
0331 {
0332
0333 result = detail::non_central_chi_square_q(
0334 static_cast<value_type>(x),
0335 static_cast<value_type>(k),
0336 static_cast<value_type>(l),
0337 forwarding_policy(),
0338 static_cast<value_type>(invert ? 0 : -1));
0339 invert = !invert;
0340 }
0341 else if(l < 200)
0342 {
0343
0344
0345 result = detail::non_central_chi_square_p_ding(
0346 static_cast<value_type>(x),
0347 static_cast<value_type>(k),
0348 static_cast<value_type>(l),
0349 forwarding_policy(),
0350 static_cast<value_type>(invert ? -1 : 0));
0351 }
0352 else
0353 {
0354
0355
0356
0357
0358
0359 result = detail::non_central_chi_square_p(
0360 static_cast<value_type>(x),
0361 static_cast<value_type>(k),
0362 static_cast<value_type>(l),
0363 forwarding_policy(),
0364 static_cast<value_type>(invert ? -1 : 0));
0365 }
0366 if(invert)
0367 result = -result;
0368 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0369 result,
0370 "boost::math::non_central_chi_squared_cdf<%1%>(%1%, %1%, %1%)");
0371 }
0372
0373 template <class T, class Policy>
0374 struct nccs_quantile_functor
0375 {
0376 nccs_quantile_functor(const non_central_chi_squared_distribution<T,Policy>& d, T t, bool c)
0377 : dist(d), target(t), comp(c) {}
0378
0379 T operator()(const T& x)
0380 {
0381 return comp ?
0382 target - cdf(complement(dist, x))
0383 : cdf(dist, x) - target;
0384 }
0385
0386 private:
0387 non_central_chi_squared_distribution<T,Policy> dist;
0388 T target;
0389 bool comp;
0390 };
0391
0392 template <class RealType, class Policy>
0393 RealType nccs_quantile(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& p, bool comp)
0394 {
0395 BOOST_MATH_STD_USING
0396 static const char* function = "quantile(non_central_chi_squared_distribution<%1%>, %1%)";
0397 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0398 typedef typename policies::normalise<
0399 Policy,
0400 policies::promote_float<false>,
0401 policies::promote_double<false>,
0402 policies::discrete_quantile<>,
0403 policies::assert_undefined<> >::type forwarding_policy;
0404
0405 value_type k = dist.degrees_of_freedom();
0406 value_type l = dist.non_centrality();
0407 value_type r;
0408 if(!detail::check_df(
0409 function,
0410 k, &r, Policy())
0411 ||
0412 !detail::check_non_centrality(
0413 function,
0414 l,
0415 &r,
0416 Policy())
0417 ||
0418 !detail::check_probability(
0419 function,
0420 static_cast<value_type>(p),
0421 &r,
0422 Policy()))
0423 return static_cast<RealType>(r);
0424
0425
0426
0427 if(p == 0)
0428 return comp ? policies::raise_overflow_error<RealType>(function, 0, Policy()) : 0;
0429 if(p == 1)
0430 return comp ? 0 : policies::raise_overflow_error<RealType>(function, 0, Policy());
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440 value_type b = -(l * l) / (k + 3 * l);
0441 value_type c = (k + 3 * l) / (k + 2 * l);
0442 value_type ff = (k + 2 * l) / (c * c);
0443 value_type guess;
0444 if(comp)
0445 {
0446 guess = b + c * quantile(complement(chi_squared_distribution<value_type, forwarding_policy>(ff), p));
0447 }
0448 else
0449 {
0450 guess = b + c * quantile(chi_squared_distribution<value_type, forwarding_policy>(ff), p);
0451 }
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463 if(guess < 0.005)
0464 {
0465 value_type pp = comp ? 1 - p : p;
0466
0467 guess = pow(pow(value_type(2), (k / 2 - 1)) * exp(l / 2) * pp * k * boost::math::tgamma(k / 2, forwarding_policy()), (2 / k));
0468 if(guess == 0)
0469 guess = tools::min_value<value_type>();
0470 }
0471 value_type result = detail::generic_quantile(
0472 non_central_chi_squared_distribution<value_type, forwarding_policy>(k, l),
0473 p,
0474 guess,
0475 comp,
0476 function);
0477
0478 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0479 result,
0480 function);
0481 }
0482
0483 template <class RealType, class Policy>
0484 RealType nccs_pdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
0485 {
0486 BOOST_MATH_STD_USING
0487 static const char* function = "pdf(non_central_chi_squared_distribution<%1%>, %1%)";
0488 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0489 typedef typename policies::normalise<
0490 Policy,
0491 policies::promote_float<false>,
0492 policies::promote_double<false>,
0493 policies::discrete_quantile<>,
0494 policies::assert_undefined<> >::type forwarding_policy;
0495
0496 value_type k = dist.degrees_of_freedom();
0497 value_type l = dist.non_centrality();
0498 value_type r;
0499 if(!detail::check_df(
0500 function,
0501 k, &r, Policy())
0502 ||
0503 !detail::check_non_centrality(
0504 function,
0505 l,
0506 &r,
0507 Policy())
0508 ||
0509 !detail::check_positive_x(
0510 function,
0511 (value_type)x,
0512 &r,
0513 Policy()))
0514 return static_cast<RealType>(r);
0515
0516 if(l == 0)
0517 return pdf(boost::math::chi_squared_distribution<RealType, forwarding_policy>(dist.degrees_of_freedom()), x);
0518
0519
0520 if(x == 0)
0521 return 0;
0522 if(l > 50)
0523 {
0524 r = non_central_chi_square_pdf(static_cast<value_type>(x), k, l, forwarding_policy());
0525 }
0526 else
0527 {
0528 r = log(x / l) * (k / 4 - 0.5f) - (x + l) / 2;
0529 if(fabs(r) >= tools::log_max_value<RealType>() / 4)
0530 {
0531 r = non_central_chi_square_pdf(static_cast<value_type>(x), k, l, forwarding_policy());
0532 }
0533 else
0534 {
0535 r = exp(r);
0536 r = 0.5f * r
0537 * boost::math::cyl_bessel_i(k/2 - 1, sqrt(l * x), forwarding_policy());
0538 }
0539 }
0540 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0541 r,
0542 function);
0543 }
0544
0545 template <class RealType, class Policy>
0546 struct degrees_of_freedom_finder
0547 {
0548 degrees_of_freedom_finder(
0549 RealType lam_, RealType x_, RealType p_, bool c)
0550 : lam(lam_), x(x_), p(p_), comp(c) {}
0551
0552 RealType operator()(const RealType& v)
0553 {
0554 non_central_chi_squared_distribution<RealType, Policy> d(v, lam);
0555 return comp ?
0556 RealType(p - cdf(complement(d, x)))
0557 : RealType(cdf(d, x) - p);
0558 }
0559 private:
0560 RealType lam;
0561 RealType x;
0562 RealType p;
0563 bool comp;
0564 };
0565
0566 template <class RealType, class Policy>
0567 inline RealType find_degrees_of_freedom(
0568 RealType lam, RealType x, RealType p, RealType q, const Policy& pol)
0569 {
0570 const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
0571 if((p == 0) || (q == 0))
0572 {
0573
0574
0575
0576 return policies::raise_evaluation_error<RealType>(function, "Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%",
0577 RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
0578 }
0579 degrees_of_freedom_finder<RealType, Policy> f(lam, x, p < q ? p : q, p < q ? false : true);
0580 tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
0581 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0582
0583
0584
0585
0586 RealType guess = x - lam;
0587 if(guess < 1)
0588 guess = 1;
0589 std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
0590 f, guess, RealType(2), false, tol, max_iter, pol);
0591 RealType result = ir.first + (ir.second - ir.first) / 2;
0592 if(max_iter >= policies::get_max_root_iterations<Policy>())
0593 {
0594 return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
0595 " or there is no answer to problem. Current best guess is %1%", result, Policy());
0596 }
0597 return result;
0598 }
0599
0600 template <class RealType, class Policy>
0601 struct non_centrality_finder
0602 {
0603 non_centrality_finder(
0604 RealType v_, RealType x_, RealType p_, bool c)
0605 : v(v_), x(x_), p(p_), comp(c) {}
0606
0607 RealType operator()(const RealType& lam)
0608 {
0609 non_central_chi_squared_distribution<RealType, Policy> d(v, lam);
0610 return comp ?
0611 RealType(p - cdf(complement(d, x)))
0612 : RealType(cdf(d, x) - p);
0613 }
0614 private:
0615 RealType v;
0616 RealType x;
0617 RealType p;
0618 bool comp;
0619 };
0620
0621 template <class RealType, class Policy>
0622 inline RealType find_non_centrality(
0623 RealType v, RealType x, RealType p, RealType q, const Policy& pol)
0624 {
0625 const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
0626 if((p == 0) || (q == 0))
0627 {
0628
0629
0630
0631 return policies::raise_evaluation_error<RealType>(function, "Can't find non centrality parameter when the probability is 0 or 1, only possible answer is %1%",
0632 RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
0633 }
0634 non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
0635 tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
0636 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0637
0638
0639
0640
0641 RealType guess = x - v;
0642 if(guess < 1)
0643 guess = 1;
0644 std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
0645 f, guess, RealType(2), false, tol, max_iter, pol);
0646 RealType result = ir.first + (ir.second - ir.first) / 2;
0647 if(max_iter >= policies::get_max_root_iterations<Policy>())
0648 {
0649 return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
0650 " or there is no answer to problem. Current best guess is %1%", result, Policy());
0651 }
0652 return result;
0653 }
0654
0655 }
0656
0657 template <class RealType = double, class Policy = policies::policy<> >
0658 class non_central_chi_squared_distribution
0659 {
0660 public:
0661 typedef RealType value_type;
0662 typedef Policy policy_type;
0663
0664 non_central_chi_squared_distribution(RealType df_, RealType lambda) : df(df_), ncp(lambda)
0665 {
0666 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::non_central_chi_squared_distribution(%1%,%1%)";
0667 RealType r;
0668 detail::check_df(
0669 function,
0670 df, &r, Policy());
0671 detail::check_non_centrality(
0672 function,
0673 ncp,
0674 &r,
0675 Policy());
0676 }
0677
0678 RealType degrees_of_freedom() const
0679 {
0680 return df;
0681 }
0682 RealType non_centrality() const
0683 {
0684 return ncp;
0685 }
0686 static RealType find_degrees_of_freedom(RealType lam, RealType x, RealType p)
0687 {
0688 const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
0689 typedef typename policies::evaluation<RealType, Policy>::type eval_type;
0690 typedef typename policies::normalise<
0691 Policy,
0692 policies::promote_float<false>,
0693 policies::promote_double<false>,
0694 policies::discrete_quantile<>,
0695 policies::assert_undefined<> >::type forwarding_policy;
0696 eval_type result = detail::find_degrees_of_freedom(
0697 static_cast<eval_type>(lam),
0698 static_cast<eval_type>(x),
0699 static_cast<eval_type>(p),
0700 static_cast<eval_type>(1-p),
0701 forwarding_policy());
0702 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0703 result,
0704 function);
0705 }
0706 template <class A, class B, class C>
0707 static RealType find_degrees_of_freedom(const complemented3_type<A,B,C>& c)
0708 {
0709 const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
0710 typedef typename policies::evaluation<RealType, Policy>::type eval_type;
0711 typedef typename policies::normalise<
0712 Policy,
0713 policies::promote_float<false>,
0714 policies::promote_double<false>,
0715 policies::discrete_quantile<>,
0716 policies::assert_undefined<> >::type forwarding_policy;
0717 eval_type result = detail::find_degrees_of_freedom(
0718 static_cast<eval_type>(c.dist),
0719 static_cast<eval_type>(c.param1),
0720 static_cast<eval_type>(1-c.param2),
0721 static_cast<eval_type>(c.param2),
0722 forwarding_policy());
0723 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0724 result,
0725 function);
0726 }
0727 static RealType find_non_centrality(RealType v, RealType x, RealType p)
0728 {
0729 const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
0730 typedef typename policies::evaluation<RealType, Policy>::type eval_type;
0731 typedef typename policies::normalise<
0732 Policy,
0733 policies::promote_float<false>,
0734 policies::promote_double<false>,
0735 policies::discrete_quantile<>,
0736 policies::assert_undefined<> >::type forwarding_policy;
0737 eval_type result = detail::find_non_centrality(
0738 static_cast<eval_type>(v),
0739 static_cast<eval_type>(x),
0740 static_cast<eval_type>(p),
0741 static_cast<eval_type>(1-p),
0742 forwarding_policy());
0743 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0744 result,
0745 function);
0746 }
0747 template <class A, class B, class C>
0748 static RealType find_non_centrality(const complemented3_type<A,B,C>& c)
0749 {
0750 const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
0751 typedef typename policies::evaluation<RealType, Policy>::type eval_type;
0752 typedef typename policies::normalise<
0753 Policy,
0754 policies::promote_float<false>,
0755 policies::promote_double<false>,
0756 policies::discrete_quantile<>,
0757 policies::assert_undefined<> >::type forwarding_policy;
0758 eval_type result = detail::find_non_centrality(
0759 static_cast<eval_type>(c.dist),
0760 static_cast<eval_type>(c.param1),
0761 static_cast<eval_type>(1-c.param2),
0762 static_cast<eval_type>(c.param2),
0763 forwarding_policy());
0764 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0765 result,
0766 function);
0767 }
0768 private:
0769
0770 RealType df;
0771 RealType ncp;
0772 };
0773
0774 typedef non_central_chi_squared_distribution<double> non_central_chi_squared;
0775
0776 #ifdef __cpp_deduction_guides
0777 template <class RealType>
0778 non_central_chi_squared_distribution(RealType,RealType)->non_central_chi_squared_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0779 #endif
0780
0781
0782
0783 template <class RealType, class Policy>
0784 inline const std::pair<RealType, RealType> range(const non_central_chi_squared_distribution<RealType, Policy>& )
0785 {
0786 using boost::math::tools::max_value;
0787 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0788 }
0789
0790 template <class RealType, class Policy>
0791 inline const std::pair<RealType, RealType> support(const non_central_chi_squared_distribution<RealType, Policy>& )
0792 {
0793
0794 using boost::math::tools::max_value;
0795 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0796 }
0797
0798 template <class RealType, class Policy>
0799 inline RealType mean(const non_central_chi_squared_distribution<RealType, Policy>& dist)
0800 {
0801 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::mean()";
0802 RealType k = dist.degrees_of_freedom();
0803 RealType l = dist.non_centrality();
0804 RealType r;
0805 if(!detail::check_df(
0806 function,
0807 k, &r, Policy())
0808 ||
0809 !detail::check_non_centrality(
0810 function,
0811 l,
0812 &r,
0813 Policy()))
0814 return static_cast<RealType>(r);
0815 return k + l;
0816 }
0817
0818 template <class RealType, class Policy>
0819 inline RealType mode(const non_central_chi_squared_distribution<RealType, Policy>& dist)
0820 {
0821 static const char* function = "mode(non_central_chi_squared_distribution<%1%> const&)";
0822
0823 RealType k = dist.degrees_of_freedom();
0824 RealType l = dist.non_centrality();
0825 RealType r;
0826 if(!detail::check_df(
0827 function,
0828 k, &r, Policy())
0829 ||
0830 !detail::check_non_centrality(
0831 function,
0832 l,
0833 &r,
0834 Policy()))
0835 return static_cast<RealType>(r);
0836 bool asymptotic_mode = k < l/4;
0837 RealType starting_point = asymptotic_mode ? k + l - RealType(3) : RealType(1) + k;
0838 return detail::generic_find_mode(dist, starting_point, function);
0839 }
0840
0841 template <class RealType, class Policy>
0842 inline RealType variance(const non_central_chi_squared_distribution<RealType, Policy>& dist)
0843 {
0844 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::variance()";
0845 RealType k = dist.degrees_of_freedom();
0846 RealType l = dist.non_centrality();
0847 RealType r;
0848 if(!detail::check_df(
0849 function,
0850 k, &r, Policy())
0851 ||
0852 !detail::check_non_centrality(
0853 function,
0854 l,
0855 &r,
0856 Policy()))
0857 return static_cast<RealType>(r);
0858 return 2 * (2 * l + k);
0859 }
0860
0861
0862
0863
0864 template <class RealType, class Policy>
0865 inline RealType skewness(const non_central_chi_squared_distribution<RealType, Policy>& dist)
0866 {
0867 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::skewness()";
0868 RealType k = dist.degrees_of_freedom();
0869 RealType l = dist.non_centrality();
0870 RealType r;
0871 if(!detail::check_df(
0872 function,
0873 k, &r, Policy())
0874 ||
0875 !detail::check_non_centrality(
0876 function,
0877 l,
0878 &r,
0879 Policy()))
0880 return static_cast<RealType>(r);
0881 BOOST_MATH_STD_USING
0882 return pow(2 / (k + 2 * l), RealType(3)/2) * (k + 3 * l);
0883 }
0884
0885 template <class RealType, class Policy>
0886 inline RealType kurtosis_excess(const non_central_chi_squared_distribution<RealType, Policy>& dist)
0887 {
0888 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::kurtosis_excess()";
0889 RealType k = dist.degrees_of_freedom();
0890 RealType l = dist.non_centrality();
0891 RealType r;
0892 if(!detail::check_df(
0893 function,
0894 k, &r, Policy())
0895 ||
0896 !detail::check_non_centrality(
0897 function,
0898 l,
0899 &r,
0900 Policy()))
0901 return static_cast<RealType>(r);
0902 return 12 * (k + 4 * l) / ((k + 2 * l) * (k + 2 * l));
0903 }
0904
0905 template <class RealType, class Policy>
0906 inline RealType kurtosis(const non_central_chi_squared_distribution<RealType, Policy>& dist)
0907 {
0908 return kurtosis_excess(dist) + 3;
0909 }
0910
0911 template <class RealType, class Policy>
0912 inline RealType pdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
0913 {
0914 return detail::nccs_pdf(dist, x);
0915 }
0916
0917 template <class RealType, class Policy>
0918 RealType cdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
0919 {
0920 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::cdf(%1%)";
0921 RealType k = dist.degrees_of_freedom();
0922 RealType l = dist.non_centrality();
0923 RealType r;
0924 if(!detail::check_df(
0925 function,
0926 k, &r, Policy())
0927 ||
0928 !detail::check_non_centrality(
0929 function,
0930 l,
0931 &r,
0932 Policy())
0933 ||
0934 !detail::check_positive_x(
0935 function,
0936 x,
0937 &r,
0938 Policy()))
0939 return static_cast<RealType>(r);
0940
0941 return detail::non_central_chi_squared_cdf(x, k, l, false, Policy());
0942 }
0943
0944 template <class RealType, class Policy>
0945 RealType cdf(const complemented2_type<non_central_chi_squared_distribution<RealType, Policy>, RealType>& c)
0946 {
0947 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::cdf(%1%)";
0948 non_central_chi_squared_distribution<RealType, Policy> const& dist = c.dist;
0949 RealType x = c.param;
0950 RealType k = dist.degrees_of_freedom();
0951 RealType l = dist.non_centrality();
0952 RealType r;
0953 if(!detail::check_df(
0954 function,
0955 k, &r, Policy())
0956 ||
0957 !detail::check_non_centrality(
0958 function,
0959 l,
0960 &r,
0961 Policy())
0962 ||
0963 !detail::check_positive_x(
0964 function,
0965 x,
0966 &r,
0967 Policy()))
0968 return static_cast<RealType>(r);
0969
0970 return detail::non_central_chi_squared_cdf(x, k, l, true, Policy());
0971 }
0972
0973 template <class RealType, class Policy>
0974 inline RealType quantile(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& p)
0975 {
0976 return detail::nccs_quantile(dist, p, false);
0977 }
0978
0979 template <class RealType, class Policy>
0980 inline RealType quantile(const complemented2_type<non_central_chi_squared_distribution<RealType, Policy>, RealType>& c)
0981 {
0982 return detail::nccs_quantile(c.dist, c.param, true);
0983 }
0984
0985 }
0986 }
0987
0988
0989
0990
0991 #include <boost/math/distributions/detail/derived_accessors.hpp>
0992
0993 #endif