annotate DEPENDENCIES/generic/include/boost/math/distributions/non_central_chi_squared.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // boost\math\distributions\non_central_chi_squared.hpp
Chris@16 2
Chris@16 3 // Copyright John Maddock 2008.
Chris@16 4
Chris@16 5 // Use, modification and distribution are subject to the
Chris@16 6 // Boost Software License, Version 1.0.
Chris@16 7 // (See accompanying file LICENSE_1_0.txt
Chris@16 8 // or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9
Chris@16 10 #ifndef BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP
Chris@16 11 #define BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP
Chris@16 12
Chris@16 13 #include <boost/math/distributions/fwd.hpp>
Chris@16 14 #include <boost/math/special_functions/gamma.hpp> // for incomplete gamma. gamma_q
Chris@16 15 #include <boost/math/special_functions/bessel.hpp> // for cyl_bessel_i
Chris@16 16 #include <boost/math/special_functions/round.hpp> // for iround
Chris@16 17 #include <boost/math/distributions/complement.hpp> // complements
Chris@16 18 #include <boost/math/distributions/chi_squared.hpp> // central distribution
Chris@16 19 #include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
Chris@16 20 #include <boost/math/special_functions/fpclassify.hpp> // isnan.
Chris@16 21 #include <boost/math/tools/roots.hpp> // for root finding.
Chris@16 22 #include <boost/math/distributions/detail/generic_mode.hpp>
Chris@16 23 #include <boost/math/distributions/detail/generic_quantile.hpp>
Chris@16 24
Chris@16 25 namespace boost
Chris@16 26 {
Chris@16 27 namespace math
Chris@16 28 {
Chris@16 29
Chris@16 30 template <class RealType, class Policy>
Chris@16 31 class non_central_chi_squared_distribution;
Chris@16 32
Chris@16 33 namespace detail{
Chris@16 34
Chris@16 35 template <class T, class Policy>
Chris@16 36 T non_central_chi_square_q(T x, T f, T theta, const Policy& pol, T init_sum = 0)
Chris@16 37 {
Chris@16 38 //
Chris@16 39 // Computes the complement of the Non-Central Chi-Square
Chris@16 40 // Distribution CDF by summing a weighted sum of complements
Chris@16 41 // of the central-distributions. The weighting factor is
Chris@16 42 // a Poisson Distribution.
Chris@16 43 //
Chris@16 44 // This is an application of the technique described in:
Chris@16 45 //
Chris@16 46 // Computing discrete mixtures of continuous
Chris@16 47 // distributions: noncentral chisquare, noncentral t
Chris@16 48 // and the distribution of the square of the sample
Chris@16 49 // multiple correlation coeficient.
Chris@16 50 // D. Benton, K. Krishnamoorthy.
Chris@16 51 // Computational Statistics & Data Analysis 43 (2003) 249 - 267
Chris@16 52 //
Chris@16 53 BOOST_MATH_STD_USING
Chris@16 54
Chris@16 55 // Special case:
Chris@16 56 if(x == 0)
Chris@16 57 return 1;
Chris@16 58
Chris@16 59 //
Chris@16 60 // Initialize the variables we'll be using:
Chris@16 61 //
Chris@16 62 T lambda = theta / 2;
Chris@16 63 T del = f / 2;
Chris@16 64 T y = x / 2;
Chris@16 65 boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
Chris@16 66 T errtol = boost::math::policies::get_epsilon<T, Policy>();
Chris@16 67 T sum = init_sum;
Chris@16 68 //
Chris@16 69 // k is the starting location for iteration, we'll
Chris@16 70 // move both forwards and backwards from this point.
Chris@16 71 // k is chosen as the peek of the Poisson weights, which
Chris@16 72 // will occur *before* the largest term.
Chris@16 73 //
Chris@16 74 int k = iround(lambda, pol);
Chris@16 75 // Forwards and backwards Poisson weights:
Chris@16 76 T poisf = boost::math::gamma_p_derivative(1 + k, lambda, pol);
Chris@16 77 T poisb = poisf * k / lambda;
Chris@16 78 // Initial forwards central chi squared term:
Chris@16 79 T gamf = boost::math::gamma_q(del + k, y, pol);
Chris@16 80 // Forwards and backwards recursion terms on the central chi squared:
Chris@16 81 T xtermf = boost::math::gamma_p_derivative(del + 1 + k, y, pol);
Chris@16 82 T xtermb = xtermf * (del + k) / y;
Chris@16 83 // Initial backwards central chi squared term:
Chris@16 84 T gamb = gamf - xtermb;
Chris@16 85
Chris@16 86 //
Chris@16 87 // Forwards iteration first, this is the
Chris@16 88 // stable direction for the gamma function
Chris@16 89 // recurrences:
Chris@16 90 //
Chris@16 91 int i;
Chris@16 92 for(i = k; static_cast<boost::uintmax_t>(i-k) < max_iter; ++i)
Chris@16 93 {
Chris@16 94 T term = poisf * gamf;
Chris@16 95 sum += term;
Chris@16 96 poisf *= lambda / (i + 1);
Chris@16 97 gamf += xtermf;
Chris@16 98 xtermf *= y / (del + i + 1);
Chris@16 99 if(((sum == 0) || (fabs(term / sum) < errtol)) && (term >= poisf * gamf))
Chris@16 100 break;
Chris@16 101 }
Chris@16 102 //Error check:
Chris@16 103 if(static_cast<boost::uintmax_t>(i-k) >= max_iter)
Chris@101 104 return policies::raise_evaluation_error(
Chris@16 105 "cdf(non_central_chi_squared_distribution<%1%>, %1%)",
Chris@16 106 "Series did not converge, closest value was %1%", sum, pol);
Chris@16 107 //
Chris@16 108 // Now backwards iteration: the gamma
Chris@16 109 // function recurrences are unstable in this
Chris@16 110 // direction, we rely on the terms deminishing in size
Chris@16 111 // faster than we introduce cancellation errors.
Chris@16 112 // For this reason it's very important that we start
Chris@16 113 // *before* the largest term so that backwards iteration
Chris@16 114 // is strictly converging.
Chris@16 115 //
Chris@16 116 for(i = k - 1; i >= 0; --i)
Chris@16 117 {
Chris@16 118 T term = poisb * gamb;
Chris@16 119 sum += term;
Chris@16 120 poisb *= i / lambda;
Chris@16 121 xtermb *= (del + i) / y;
Chris@16 122 gamb -= xtermb;
Chris@16 123 if((sum == 0) || (fabs(term / sum) < errtol))
Chris@16 124 break;
Chris@16 125 }
Chris@16 126
Chris@16 127 return sum;
Chris@16 128 }
Chris@16 129
Chris@16 130 template <class T, class Policy>
Chris@16 131 T non_central_chi_square_p_ding(T x, T f, T theta, const Policy& pol, T init_sum = 0)
Chris@16 132 {
Chris@16 133 //
Chris@16 134 // This is an implementation of:
Chris@16 135 //
Chris@16 136 // Algorithm AS 275:
Chris@16 137 // Computing the Non-Central #2 Distribution Function
Chris@16 138 // Cherng G. Ding
Chris@16 139 // Applied Statistics, Vol. 41, No. 2. (1992), pp. 478-482.
Chris@16 140 //
Chris@16 141 // This uses a stable forward iteration to sum the
Chris@16 142 // CDF, unfortunately this can not be used for large
Chris@16 143 // values of the non-centrality parameter because:
Chris@16 144 // * The first term may underfow to zero.
Chris@16 145 // * We may need an extra-ordinary number of terms
Chris@16 146 // before we reach the first *significant* term.
Chris@16 147 //
Chris@16 148 BOOST_MATH_STD_USING
Chris@16 149 // Special case:
Chris@16 150 if(x == 0)
Chris@16 151 return 0;
Chris@16 152 T tk = boost::math::gamma_p_derivative(f/2 + 1, x/2, pol);
Chris@16 153 T lambda = theta / 2;
Chris@16 154 T vk = exp(-lambda);
Chris@16 155 T uk = vk;
Chris@16 156 T sum = init_sum + tk * vk;
Chris@16 157 if(sum == 0)
Chris@16 158 return sum;
Chris@16 159
Chris@16 160 boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
Chris@16 161 T errtol = boost::math::policies::get_epsilon<T, Policy>();
Chris@16 162
Chris@16 163 int i;
Chris@16 164 T lterm(0), term(0);
Chris@16 165 for(i = 1; static_cast<boost::uintmax_t>(i) < max_iter; ++i)
Chris@16 166 {
Chris@16 167 tk = tk * x / (f + 2 * i);
Chris@16 168 uk = uk * lambda / i;
Chris@16 169 vk = vk + uk;
Chris@16 170 lterm = term;
Chris@16 171 term = vk * tk;
Chris@16 172 sum += term;
Chris@16 173 if((fabs(term / sum) < errtol) && (term <= lterm))
Chris@16 174 break;
Chris@16 175 }
Chris@16 176 //Error check:
Chris@16 177 if(static_cast<boost::uintmax_t>(i) >= max_iter)
Chris@101 178 return policies::raise_evaluation_error(
Chris@16 179 "cdf(non_central_chi_squared_distribution<%1%>, %1%)",
Chris@16 180 "Series did not converge, closest value was %1%", sum, pol);
Chris@16 181 return sum;
Chris@16 182 }
Chris@16 183
Chris@16 184
Chris@16 185 template <class T, class Policy>
Chris@16 186 T non_central_chi_square_p(T y, T n, T lambda, const Policy& pol, T init_sum)
Chris@16 187 {
Chris@16 188 //
Chris@16 189 // This is taken more or less directly from:
Chris@16 190 //
Chris@16 191 // Computing discrete mixtures of continuous
Chris@16 192 // distributions: noncentral chisquare, noncentral t
Chris@16 193 // and the distribution of the square of the sample
Chris@16 194 // multiple correlation coeficient.
Chris@16 195 // D. Benton, K. Krishnamoorthy.
Chris@16 196 // Computational Statistics & Data Analysis 43 (2003) 249 - 267
Chris@16 197 //
Chris@16 198 // We're summing a Poisson weighting term multiplied by
Chris@16 199 // a central chi squared distribution.
Chris@16 200 //
Chris@16 201 BOOST_MATH_STD_USING
Chris@16 202 // Special case:
Chris@16 203 if(y == 0)
Chris@16 204 return 0;
Chris@16 205 boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
Chris@16 206 T errtol = boost::math::policies::get_epsilon<T, Policy>();
Chris@16 207 T errorf(0), errorb(0);
Chris@16 208
Chris@16 209 T x = y / 2;
Chris@16 210 T del = lambda / 2;
Chris@16 211 //
Chris@16 212 // Starting location for the iteration, we'll iterate
Chris@16 213 // both forwards and backwards from this point. The
Chris@16 214 // location chosen is the maximum of the Poisson weight
Chris@16 215 // function, which ocurrs *after* the largest term in the
Chris@16 216 // sum.
Chris@16 217 //
Chris@16 218 int k = iround(del, pol);
Chris@16 219 T a = n / 2 + k;
Chris@16 220 // Central chi squared term for forward iteration:
Chris@16 221 T gamkf = boost::math::gamma_p(a, x, pol);
Chris@16 222
Chris@16 223 if(lambda == 0)
Chris@16 224 return gamkf;
Chris@16 225 // Central chi squared term for backward iteration:
Chris@16 226 T gamkb = gamkf;
Chris@16 227 // Forwards Poisson weight:
Chris@16 228 T poiskf = gamma_p_derivative(k+1, del, pol);
Chris@16 229 // Backwards Poisson weight:
Chris@16 230 T poiskb = poiskf;
Chris@16 231 // Forwards gamma function recursion term:
Chris@16 232 T xtermf = boost::math::gamma_p_derivative(a, x, pol);
Chris@16 233 // Backwards gamma function recursion term:
Chris@16 234 T xtermb = xtermf * x / a;
Chris@16 235 T sum = init_sum + poiskf * gamkf;
Chris@16 236 if(sum == 0)
Chris@16 237 return sum;
Chris@16 238 int i = 1;
Chris@16 239 //
Chris@16 240 // Backwards recursion first, this is the stable
Chris@16 241 // direction for gamma function recurrences:
Chris@16 242 //
Chris@16 243 while(i <= k)
Chris@16 244 {
Chris@16 245 xtermb *= (a - i + 1) / x;
Chris@16 246 gamkb += xtermb;
Chris@16 247 poiskb = poiskb * (k - i + 1) / del;
Chris@16 248 errorf = errorb;
Chris@16 249 errorb = gamkb * poiskb;
Chris@16 250 sum += errorb;
Chris@16 251 if((fabs(errorb / sum) < errtol) && (errorb <= errorf))
Chris@16 252 break;
Chris@16 253 ++i;
Chris@16 254 }
Chris@16 255 i = 1;
Chris@16 256 //
Chris@16 257 // Now forwards recursion, the gamma function
Chris@16 258 // recurrence relation is unstable in this direction,
Chris@16 259 // so we rely on the magnitude of successive terms
Chris@16 260 // decreasing faster than we introduce cancellation error.
Chris@16 261 // For this reason it's vital that k is chosen to be *after*
Chris@16 262 // the largest term, so that successive forward iterations
Chris@16 263 // are strictly (and rapidly) converging.
Chris@16 264 //
Chris@16 265 do
Chris@16 266 {
Chris@16 267 xtermf = xtermf * x / (a + i - 1);
Chris@16 268 gamkf = gamkf - xtermf;
Chris@16 269 poiskf = poiskf * del / (k + i);
Chris@16 270 errorf = poiskf * gamkf;
Chris@16 271 sum += errorf;
Chris@16 272 ++i;
Chris@16 273 }while((fabs(errorf / sum) > errtol) && (static_cast<boost::uintmax_t>(i) < max_iter));
Chris@16 274
Chris@16 275 //Error check:
Chris@16 276 if(static_cast<boost::uintmax_t>(i) >= max_iter)
Chris@101 277 return policies::raise_evaluation_error(
Chris@16 278 "cdf(non_central_chi_squared_distribution<%1%>, %1%)",
Chris@16 279 "Series did not converge, closest value was %1%", sum, pol);
Chris@16 280
Chris@16 281 return sum;
Chris@16 282 }
Chris@16 283
Chris@16 284 template <class T, class Policy>
Chris@16 285 T non_central_chi_square_pdf(T x, T n, T lambda, const Policy& pol)
Chris@16 286 {
Chris@16 287 //
Chris@16 288 // As above but for the PDF:
Chris@16 289 //
Chris@16 290 BOOST_MATH_STD_USING
Chris@16 291 boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
Chris@16 292 T errtol = boost::math::policies::get_epsilon<T, Policy>();
Chris@16 293 T x2 = x / 2;
Chris@16 294 T n2 = n / 2;
Chris@16 295 T l2 = lambda / 2;
Chris@16 296 T sum = 0;
Chris@16 297 int k = itrunc(l2);
Chris@16 298 T pois = gamma_p_derivative(k + 1, l2, pol) * gamma_p_derivative(n2 + k, x2);
Chris@16 299 if(pois == 0)
Chris@16 300 return 0;
Chris@16 301 T poisb = pois;
Chris@16 302 for(int i = k; ; ++i)
Chris@16 303 {
Chris@16 304 sum += pois;
Chris@16 305 if(pois / sum < errtol)
Chris@16 306 break;
Chris@16 307 if(static_cast<boost::uintmax_t>(i - k) >= max_iter)
Chris@16 308 return policies::raise_evaluation_error(
Chris@16 309 "pdf(non_central_chi_squared_distribution<%1%>, %1%)",
Chris@16 310 "Series did not converge, closest value was %1%", sum, pol);
Chris@16 311 pois *= l2 * x2 / ((i + 1) * (n2 + i));
Chris@16 312 }
Chris@16 313 for(int i = k - 1; i >= 0; --i)
Chris@16 314 {
Chris@16 315 poisb *= (i + 1) * (n2 + i) / (l2 * x2);
Chris@16 316 sum += poisb;
Chris@16 317 if(poisb / sum < errtol)
Chris@16 318 break;
Chris@16 319 }
Chris@16 320 return sum / 2;
Chris@16 321 }
Chris@16 322
Chris@16 323 template <class RealType, class Policy>
Chris@16 324 inline RealType non_central_chi_squared_cdf(RealType x, RealType k, RealType l, bool invert, const Policy&)
Chris@16 325 {
Chris@16 326 typedef typename policies::evaluation<RealType, Policy>::type value_type;
Chris@16 327 typedef typename policies::normalise<
Chris@16 328 Policy,
Chris@16 329 policies::promote_float<false>,
Chris@16 330 policies::promote_double<false>,
Chris@16 331 policies::discrete_quantile<>,
Chris@16 332 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 333
Chris@16 334 BOOST_MATH_STD_USING
Chris@16 335 value_type result;
Chris@16 336 if(l == 0)
Chris@16 337 result = cdf(boost::math::chi_squared_distribution<RealType, Policy>(k), x);
Chris@16 338 else if(x > k + l)
Chris@16 339 {
Chris@16 340 // Complement is the smaller of the two:
Chris@16 341 result = detail::non_central_chi_square_q(
Chris@16 342 static_cast<value_type>(x),
Chris@16 343 static_cast<value_type>(k),
Chris@16 344 static_cast<value_type>(l),
Chris@16 345 forwarding_policy(),
Chris@16 346 static_cast<value_type>(invert ? 0 : -1));
Chris@16 347 invert = !invert;
Chris@16 348 }
Chris@16 349 else if(l < 200)
Chris@16 350 {
Chris@16 351 // For small values of the non-centrality parameter
Chris@16 352 // we can use Ding's method:
Chris@16 353 result = detail::non_central_chi_square_p_ding(
Chris@16 354 static_cast<value_type>(x),
Chris@16 355 static_cast<value_type>(k),
Chris@16 356 static_cast<value_type>(l),
Chris@16 357 forwarding_policy(),
Chris@16 358 static_cast<value_type>(invert ? -1 : 0));
Chris@16 359 }
Chris@16 360 else
Chris@16 361 {
Chris@16 362 // For largers values of the non-centrality
Chris@16 363 // parameter Ding's method will consume an
Chris@16 364 // extra-ordinary number of terms, and worse
Chris@16 365 // may return zero when the result is in fact
Chris@16 366 // finite, use Krishnamoorthy's method instead:
Chris@16 367 result = detail::non_central_chi_square_p(
Chris@16 368 static_cast<value_type>(x),
Chris@16 369 static_cast<value_type>(k),
Chris@16 370 static_cast<value_type>(l),
Chris@16 371 forwarding_policy(),
Chris@16 372 static_cast<value_type>(invert ? -1 : 0));
Chris@16 373 }
Chris@16 374 if(invert)
Chris@16 375 result = -result;
Chris@16 376 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
Chris@16 377 result,
Chris@16 378 "boost::math::non_central_chi_squared_cdf<%1%>(%1%, %1%, %1%)");
Chris@16 379 }
Chris@16 380
Chris@16 381 template <class T, class Policy>
Chris@16 382 struct nccs_quantile_functor
Chris@16 383 {
Chris@16 384 nccs_quantile_functor(const non_central_chi_squared_distribution<T,Policy>& d, T t, bool c)
Chris@16 385 : dist(d), target(t), comp(c) {}
Chris@16 386
Chris@16 387 T operator()(const T& x)
Chris@16 388 {
Chris@16 389 return comp ?
Chris@16 390 target - cdf(complement(dist, x))
Chris@16 391 : cdf(dist, x) - target;
Chris@16 392 }
Chris@16 393
Chris@16 394 private:
Chris@16 395 non_central_chi_squared_distribution<T,Policy> dist;
Chris@16 396 T target;
Chris@16 397 bool comp;
Chris@16 398 };
Chris@16 399
Chris@16 400 template <class RealType, class Policy>
Chris@16 401 RealType nccs_quantile(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& p, bool comp)
Chris@16 402 {
Chris@16 403 BOOST_MATH_STD_USING
Chris@16 404 static const char* function = "quantile(non_central_chi_squared_distribution<%1%>, %1%)";
Chris@16 405 typedef typename policies::evaluation<RealType, Policy>::type value_type;
Chris@16 406 typedef typename policies::normalise<
Chris@16 407 Policy,
Chris@16 408 policies::promote_float<false>,
Chris@16 409 policies::promote_double<false>,
Chris@16 410 policies::discrete_quantile<>,
Chris@16 411 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 412
Chris@16 413 value_type k = dist.degrees_of_freedom();
Chris@16 414 value_type l = dist.non_centrality();
Chris@16 415 value_type r;
Chris@16 416 if(!detail::check_df(
Chris@16 417 function,
Chris@16 418 k, &r, Policy())
Chris@16 419 ||
Chris@16 420 !detail::check_non_centrality(
Chris@16 421 function,
Chris@16 422 l,
Chris@16 423 &r,
Chris@16 424 Policy())
Chris@16 425 ||
Chris@16 426 !detail::check_probability(
Chris@16 427 function,
Chris@16 428 static_cast<value_type>(p),
Chris@16 429 &r,
Chris@16 430 Policy()))
Chris@16 431 return (RealType)r;
Chris@16 432 //
Chris@16 433 // Special cases get short-circuited first:
Chris@16 434 //
Chris@16 435 if(p == 0)
Chris@101 436 return comp ? policies::raise_overflow_error<RealType>(function, 0, Policy()) : 0;
Chris@16 437 if(p == 1)
Chris@101 438 return comp ? 0 : policies::raise_overflow_error<RealType>(function, 0, Policy());
Chris@16 439 //
Chris@16 440 // This is Pearson's approximation to the quantile, see
Chris@16 441 // Pearson, E. S. (1959) "Note on an approximation to the distribution of
Chris@16 442 // noncentral chi squared", Biometrika 46: 364.
Chris@16 443 // See also:
Chris@16 444 // "A comparison of approximations to percentiles of the noncentral chi2-distribution",
Chris@16 445 // Hardeo Sahai and Mario Miguel Ojeda, Revista de Matematica: Teoria y Aplicaciones 2003 10(1–2) : 57–76.
Chris@16 446 // Note that the latter reference refers to an approximation of the CDF, when they really mean the quantile.
Chris@16 447 //
Chris@16 448 value_type b = -(l * l) / (k + 3 * l);
Chris@16 449 value_type c = (k + 3 * l) / (k + 2 * l);
Chris@16 450 value_type ff = (k + 2 * l) / (c * c);
Chris@16 451 value_type guess;
Chris@16 452 if(comp)
Chris@16 453 {
Chris@16 454 guess = b + c * quantile(complement(chi_squared_distribution<value_type, forwarding_policy>(ff), p));
Chris@16 455 }
Chris@16 456 else
Chris@16 457 {
Chris@16 458 guess = b + c * quantile(chi_squared_distribution<value_type, forwarding_policy>(ff), p);
Chris@16 459 }
Chris@16 460 //
Chris@16 461 // Sometimes guess goes very small or negative, in that case we have
Chris@16 462 // to do something else for the initial guess, this approximation
Chris@16 463 // was provided in a private communication from Thomas Luu, PhD candidate,
Chris@16 464 // University College London. It's an asymptotic expansion for the
Chris@16 465 // quantile which usually gets us within an order of magnitude of the
Chris@16 466 // correct answer.
Chris@16 467 //
Chris@16 468 if(guess < 0.005)
Chris@16 469 {
Chris@16 470 value_type pp = comp ? 1 - p : p;
Chris@16 471 //guess = pow(pow(value_type(2), (k / 2 - 1)) * exp(l / 2) * pp * k, 2 / k);
Chris@16 472 guess = pow(pow(value_type(2), (k / 2 - 1)) * exp(l / 2) * pp * k * boost::math::tgamma(k / 2, forwarding_policy()), (2 / k));
Chris@16 473 if(guess == 0)
Chris@16 474 guess = tools::min_value<value_type>();
Chris@16 475 }
Chris@16 476 value_type result = detail::generic_quantile(
Chris@16 477 non_central_chi_squared_distribution<value_type, forwarding_policy>(k, l),
Chris@16 478 p,
Chris@16 479 guess,
Chris@16 480 comp,
Chris@16 481 function);
Chris@16 482
Chris@16 483 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
Chris@16 484 result,
Chris@16 485 function);
Chris@16 486 }
Chris@16 487
Chris@16 488 template <class RealType, class Policy>
Chris@16 489 RealType nccs_pdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
Chris@16 490 {
Chris@16 491 BOOST_MATH_STD_USING
Chris@16 492 static const char* function = "pdf(non_central_chi_squared_distribution<%1%>, %1%)";
Chris@16 493 typedef typename policies::evaluation<RealType, Policy>::type value_type;
Chris@16 494 typedef typename policies::normalise<
Chris@16 495 Policy,
Chris@16 496 policies::promote_float<false>,
Chris@16 497 policies::promote_double<false>,
Chris@16 498 policies::discrete_quantile<>,
Chris@16 499 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 500
Chris@16 501 value_type k = dist.degrees_of_freedom();
Chris@16 502 value_type l = dist.non_centrality();
Chris@16 503 value_type r;
Chris@16 504 if(!detail::check_df(
Chris@16 505 function,
Chris@16 506 k, &r, Policy())
Chris@16 507 ||
Chris@16 508 !detail::check_non_centrality(
Chris@16 509 function,
Chris@16 510 l,
Chris@16 511 &r,
Chris@16 512 Policy())
Chris@16 513 ||
Chris@16 514 !detail::check_positive_x(
Chris@16 515 function,
Chris@16 516 (value_type)x,
Chris@16 517 &r,
Chris@16 518 Policy()))
Chris@16 519 return (RealType)r;
Chris@16 520
Chris@16 521 if(l == 0)
Chris@16 522 return pdf(boost::math::chi_squared_distribution<RealType, forwarding_policy>(dist.degrees_of_freedom()), x);
Chris@16 523
Chris@16 524 // Special case:
Chris@16 525 if(x == 0)
Chris@16 526 return 0;
Chris@16 527 if(l > 50)
Chris@16 528 {
Chris@16 529 r = non_central_chi_square_pdf(static_cast<value_type>(x), k, l, forwarding_policy());
Chris@16 530 }
Chris@16 531 else
Chris@16 532 {
Chris@16 533 r = log(x / l) * (k / 4 - 0.5f) - (x + l) / 2;
Chris@16 534 if(fabs(r) >= tools::log_max_value<RealType>() / 4)
Chris@16 535 {
Chris@16 536 r = non_central_chi_square_pdf(static_cast<value_type>(x), k, l, forwarding_policy());
Chris@16 537 }
Chris@16 538 else
Chris@16 539 {
Chris@16 540 r = exp(r);
Chris@16 541 r = 0.5f * r
Chris@16 542 * boost::math::cyl_bessel_i(k/2 - 1, sqrt(l * x), forwarding_policy());
Chris@16 543 }
Chris@16 544 }
Chris@16 545 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
Chris@16 546 r,
Chris@16 547 function);
Chris@16 548 }
Chris@16 549
Chris@16 550 template <class RealType, class Policy>
Chris@16 551 struct degrees_of_freedom_finder
Chris@16 552 {
Chris@16 553 degrees_of_freedom_finder(
Chris@16 554 RealType lam_, RealType x_, RealType p_, bool c)
Chris@16 555 : lam(lam_), x(x_), p(p_), comp(c) {}
Chris@16 556
Chris@16 557 RealType operator()(const RealType& v)
Chris@16 558 {
Chris@16 559 non_central_chi_squared_distribution<RealType, Policy> d(v, lam);
Chris@16 560 return comp ?
Chris@16 561 RealType(p - cdf(complement(d, x)))
Chris@16 562 : RealType(cdf(d, x) - p);
Chris@16 563 }
Chris@16 564 private:
Chris@16 565 RealType lam;
Chris@16 566 RealType x;
Chris@16 567 RealType p;
Chris@16 568 bool comp;
Chris@16 569 };
Chris@16 570
Chris@16 571 template <class RealType, class Policy>
Chris@16 572 inline RealType find_degrees_of_freedom(
Chris@16 573 RealType lam, RealType x, RealType p, RealType q, const Policy& pol)
Chris@16 574 {
Chris@16 575 const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
Chris@16 576 if((p == 0) || (q == 0))
Chris@16 577 {
Chris@16 578 //
Chris@16 579 // Can't a thing if one of p and q is zero:
Chris@16 580 //
Chris@16 581 return policies::raise_evaluation_error<RealType>(function,
Chris@16 582 "Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%",
Chris@16 583 RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
Chris@16 584 }
Chris@16 585 degrees_of_freedom_finder<RealType, Policy> f(lam, x, p < q ? p : q, p < q ? false : true);
Chris@16 586 tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
Chris@16 587 boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
Chris@16 588 //
Chris@16 589 // Pick an initial guess that we know will give us a probability
Chris@16 590 // right around 0.5.
Chris@16 591 //
Chris@16 592 RealType guess = x - lam;
Chris@16 593 if(guess < 1)
Chris@16 594 guess = 1;
Chris@16 595 std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
Chris@16 596 f, guess, RealType(2), false, tol, max_iter, pol);
Chris@16 597 RealType result = ir.first + (ir.second - ir.first) / 2;
Chris@16 598 if(max_iter >= policies::get_max_root_iterations<Policy>())
Chris@16 599 {
Chris@101 600 return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
Chris@16 601 " or there is no answer to problem. Current best guess is %1%", result, Policy());
Chris@16 602 }
Chris@16 603 return result;
Chris@16 604 }
Chris@16 605
Chris@16 606 template <class RealType, class Policy>
Chris@16 607 struct non_centrality_finder
Chris@16 608 {
Chris@16 609 non_centrality_finder(
Chris@16 610 RealType v_, RealType x_, RealType p_, bool c)
Chris@16 611 : v(v_), x(x_), p(p_), comp(c) {}
Chris@16 612
Chris@16 613 RealType operator()(const RealType& lam)
Chris@16 614 {
Chris@16 615 non_central_chi_squared_distribution<RealType, Policy> d(v, lam);
Chris@16 616 return comp ?
Chris@16 617 RealType(p - cdf(complement(d, x)))
Chris@16 618 : RealType(cdf(d, x) - p);
Chris@16 619 }
Chris@16 620 private:
Chris@16 621 RealType v;
Chris@16 622 RealType x;
Chris@16 623 RealType p;
Chris@16 624 bool comp;
Chris@16 625 };
Chris@16 626
Chris@16 627 template <class RealType, class Policy>
Chris@16 628 inline RealType find_non_centrality(
Chris@16 629 RealType v, RealType x, RealType p, RealType q, const Policy& pol)
Chris@16 630 {
Chris@16 631 const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
Chris@16 632 if((p == 0) || (q == 0))
Chris@16 633 {
Chris@16 634 //
Chris@16 635 // Can't do a thing if one of p and q is zero:
Chris@16 636 //
Chris@16 637 return policies::raise_evaluation_error<RealType>(function,
Chris@16 638 "Can't find non centrality parameter when the probability is 0 or 1, only possible answer is %1%",
Chris@16 639 RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
Chris@16 640 }
Chris@16 641 non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
Chris@16 642 tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
Chris@16 643 boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
Chris@16 644 //
Chris@16 645 // Pick an initial guess that we know will give us a probability
Chris@16 646 // right around 0.5.
Chris@16 647 //
Chris@16 648 RealType guess = x - v;
Chris@16 649 if(guess < 1)
Chris@16 650 guess = 1;
Chris@16 651 std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
Chris@16 652 f, guess, RealType(2), false, tol, max_iter, pol);
Chris@16 653 RealType result = ir.first + (ir.second - ir.first) / 2;
Chris@16 654 if(max_iter >= policies::get_max_root_iterations<Policy>())
Chris@16 655 {
Chris@101 656 return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
Chris@16 657 " or there is no answer to problem. Current best guess is %1%", result, Policy());
Chris@16 658 }
Chris@16 659 return result;
Chris@16 660 }
Chris@16 661
Chris@16 662 }
Chris@16 663
Chris@16 664 template <class RealType = double, class Policy = policies::policy<> >
Chris@16 665 class non_central_chi_squared_distribution
Chris@16 666 {
Chris@16 667 public:
Chris@16 668 typedef RealType value_type;
Chris@16 669 typedef Policy policy_type;
Chris@16 670
Chris@16 671 non_central_chi_squared_distribution(RealType df_, RealType lambda) : df(df_), ncp(lambda)
Chris@16 672 {
Chris@16 673 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::non_central_chi_squared_distribution(%1%,%1%)";
Chris@16 674 RealType r;
Chris@16 675 detail::check_df(
Chris@16 676 function,
Chris@16 677 df, &r, Policy());
Chris@16 678 detail::check_non_centrality(
Chris@16 679 function,
Chris@16 680 ncp,
Chris@16 681 &r,
Chris@16 682 Policy());
Chris@16 683 } // non_central_chi_squared_distribution constructor.
Chris@16 684
Chris@16 685 RealType degrees_of_freedom() const
Chris@16 686 { // Private data getter function.
Chris@16 687 return df;
Chris@16 688 }
Chris@16 689 RealType non_centrality() const
Chris@16 690 { // Private data getter function.
Chris@16 691 return ncp;
Chris@16 692 }
Chris@16 693 static RealType find_degrees_of_freedom(RealType lam, RealType x, RealType p)
Chris@16 694 {
Chris@16 695 const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
Chris@16 696 typedef typename policies::evaluation<RealType, Policy>::type value_type;
Chris@16 697 typedef typename policies::normalise<
Chris@16 698 Policy,
Chris@16 699 policies::promote_float<false>,
Chris@16 700 policies::promote_double<false>,
Chris@16 701 policies::discrete_quantile<>,
Chris@16 702 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 703 value_type result = detail::find_degrees_of_freedom(
Chris@16 704 static_cast<value_type>(lam),
Chris@16 705 static_cast<value_type>(x),
Chris@16 706 static_cast<value_type>(p),
Chris@16 707 static_cast<value_type>(1-p),
Chris@16 708 forwarding_policy());
Chris@16 709 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
Chris@16 710 result,
Chris@16 711 function);
Chris@16 712 }
Chris@16 713 template <class A, class B, class C>
Chris@16 714 static RealType find_degrees_of_freedom(const complemented3_type<A,B,C>& c)
Chris@16 715 {
Chris@16 716 const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
Chris@16 717 typedef typename policies::evaluation<RealType, Policy>::type value_type;
Chris@16 718 typedef typename policies::normalise<
Chris@16 719 Policy,
Chris@16 720 policies::promote_float<false>,
Chris@16 721 policies::promote_double<false>,
Chris@16 722 policies::discrete_quantile<>,
Chris@16 723 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 724 value_type result = detail::find_degrees_of_freedom(
Chris@16 725 static_cast<value_type>(c.dist),
Chris@16 726 static_cast<value_type>(c.param1),
Chris@16 727 static_cast<value_type>(1-c.param2),
Chris@16 728 static_cast<value_type>(c.param2),
Chris@16 729 forwarding_policy());
Chris@16 730 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
Chris@16 731 result,
Chris@16 732 function);
Chris@16 733 }
Chris@16 734 static RealType find_non_centrality(RealType v, RealType x, RealType p)
Chris@16 735 {
Chris@16 736 const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
Chris@16 737 typedef typename policies::evaluation<RealType, Policy>::type value_type;
Chris@16 738 typedef typename policies::normalise<
Chris@16 739 Policy,
Chris@16 740 policies::promote_float<false>,
Chris@16 741 policies::promote_double<false>,
Chris@16 742 policies::discrete_quantile<>,
Chris@16 743 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 744 value_type result = detail::find_non_centrality(
Chris@16 745 static_cast<value_type>(v),
Chris@16 746 static_cast<value_type>(x),
Chris@16 747 static_cast<value_type>(p),
Chris@16 748 static_cast<value_type>(1-p),
Chris@16 749 forwarding_policy());
Chris@16 750 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
Chris@16 751 result,
Chris@16 752 function);
Chris@16 753 }
Chris@16 754 template <class A, class B, class C>
Chris@16 755 static RealType find_non_centrality(const complemented3_type<A,B,C>& c)
Chris@16 756 {
Chris@16 757 const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
Chris@16 758 typedef typename policies::evaluation<RealType, Policy>::type value_type;
Chris@16 759 typedef typename policies::normalise<
Chris@16 760 Policy,
Chris@16 761 policies::promote_float<false>,
Chris@16 762 policies::promote_double<false>,
Chris@16 763 policies::discrete_quantile<>,
Chris@16 764 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 765 value_type result = detail::find_non_centrality(
Chris@16 766 static_cast<value_type>(c.dist),
Chris@16 767 static_cast<value_type>(c.param1),
Chris@16 768 static_cast<value_type>(1-c.param2),
Chris@16 769 static_cast<value_type>(c.param2),
Chris@16 770 forwarding_policy());
Chris@16 771 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
Chris@16 772 result,
Chris@16 773 function);
Chris@16 774 }
Chris@16 775 private:
Chris@16 776 // Data member, initialized by constructor.
Chris@16 777 RealType df; // degrees of freedom.
Chris@16 778 RealType ncp; // non-centrality parameter
Chris@16 779 }; // template <class RealType, class Policy> class non_central_chi_squared_distribution
Chris@16 780
Chris@16 781 typedef non_central_chi_squared_distribution<double> non_central_chi_squared; // Reserved name of type double.
Chris@16 782
Chris@16 783 // Non-member functions to give properties of the distribution.
Chris@16 784
Chris@16 785 template <class RealType, class Policy>
Chris@16 786 inline const std::pair<RealType, RealType> range(const non_central_chi_squared_distribution<RealType, Policy>& /* dist */)
Chris@16 787 { // Range of permissible values for random variable k.
Chris@16 788 using boost::math::tools::max_value;
Chris@16 789 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // Max integer?
Chris@16 790 }
Chris@16 791
Chris@16 792 template <class RealType, class Policy>
Chris@16 793 inline const std::pair<RealType, RealType> support(const non_central_chi_squared_distribution<RealType, Policy>& /* dist */)
Chris@16 794 { // Range of supported values for random variable k.
Chris@16 795 // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
Chris@16 796 using boost::math::tools::max_value;
Chris@16 797 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
Chris@16 798 }
Chris@16 799
Chris@16 800 template <class RealType, class Policy>
Chris@16 801 inline RealType mean(const non_central_chi_squared_distribution<RealType, Policy>& dist)
Chris@16 802 { // Mean of poisson distribution = lambda.
Chris@16 803 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::mean()";
Chris@16 804 RealType k = dist.degrees_of_freedom();
Chris@16 805 RealType l = dist.non_centrality();
Chris@16 806 RealType r;
Chris@16 807 if(!detail::check_df(
Chris@16 808 function,
Chris@16 809 k, &r, Policy())
Chris@16 810 ||
Chris@16 811 !detail::check_non_centrality(
Chris@16 812 function,
Chris@16 813 l,
Chris@16 814 &r,
Chris@16 815 Policy()))
Chris@16 816 return r;
Chris@16 817 return k + l;
Chris@16 818 } // mean
Chris@16 819
Chris@16 820 template <class RealType, class Policy>
Chris@16 821 inline RealType mode(const non_central_chi_squared_distribution<RealType, Policy>& dist)
Chris@16 822 { // mode.
Chris@16 823 static const char* function = "mode(non_central_chi_squared_distribution<%1%> const&)";
Chris@16 824
Chris@16 825 RealType k = dist.degrees_of_freedom();
Chris@16 826 RealType l = dist.non_centrality();
Chris@16 827 RealType r;
Chris@16 828 if(!detail::check_df(
Chris@16 829 function,
Chris@16 830 k, &r, Policy())
Chris@16 831 ||
Chris@16 832 !detail::check_non_centrality(
Chris@16 833 function,
Chris@16 834 l,
Chris@16 835 &r,
Chris@16 836 Policy()))
Chris@16 837 return (RealType)r;
Chris@16 838 return detail::generic_find_mode(dist, 1 + k, function);
Chris@16 839 }
Chris@16 840
Chris@16 841 template <class RealType, class Policy>
Chris@16 842 inline RealType variance(const non_central_chi_squared_distribution<RealType, Policy>& dist)
Chris@16 843 { // variance.
Chris@16 844 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::variance()";
Chris@16 845 RealType k = dist.degrees_of_freedom();
Chris@16 846 RealType l = dist.non_centrality();
Chris@16 847 RealType r;
Chris@16 848 if(!detail::check_df(
Chris@16 849 function,
Chris@16 850 k, &r, Policy())
Chris@16 851 ||
Chris@16 852 !detail::check_non_centrality(
Chris@16 853 function,
Chris@16 854 l,
Chris@16 855 &r,
Chris@16 856 Policy()))
Chris@16 857 return r;
Chris@16 858 return 2 * (2 * l + k);
Chris@16 859 }
Chris@16 860
Chris@16 861 // RealType standard_deviation(const non_central_chi_squared_distribution<RealType, Policy>& dist)
Chris@16 862 // standard_deviation provided by derived accessors.
Chris@16 863
Chris@16 864 template <class RealType, class Policy>
Chris@16 865 inline RealType skewness(const non_central_chi_squared_distribution<RealType, Policy>& dist)
Chris@16 866 { // skewness = sqrt(l).
Chris@16 867 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::skewness()";
Chris@16 868 RealType k = dist.degrees_of_freedom();
Chris@16 869 RealType l = dist.non_centrality();
Chris@16 870 RealType r;
Chris@16 871 if(!detail::check_df(
Chris@16 872 function,
Chris@16 873 k, &r, Policy())
Chris@16 874 ||
Chris@16 875 !detail::check_non_centrality(
Chris@16 876 function,
Chris@16 877 l,
Chris@16 878 &r,
Chris@16 879 Policy()))
Chris@16 880 return r;
Chris@16 881 BOOST_MATH_STD_USING
Chris@16 882 return pow(2 / (k + 2 * l), RealType(3)/2) * (k + 3 * l);
Chris@16 883 }
Chris@16 884
Chris@16 885 template <class RealType, class Policy>
Chris@16 886 inline RealType kurtosis_excess(const non_central_chi_squared_distribution<RealType, Policy>& dist)
Chris@16 887 {
Chris@16 888 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::kurtosis_excess()";
Chris@16 889 RealType k = dist.degrees_of_freedom();
Chris@16 890 RealType l = dist.non_centrality();
Chris@16 891 RealType r;
Chris@16 892 if(!detail::check_df(
Chris@16 893 function,
Chris@16 894 k, &r, Policy())
Chris@16 895 ||
Chris@16 896 !detail::check_non_centrality(
Chris@16 897 function,
Chris@16 898 l,
Chris@16 899 &r,
Chris@16 900 Policy()))
Chris@16 901 return r;
Chris@16 902 return 12 * (k + 4 * l) / ((k + 2 * l) * (k + 2 * l));
Chris@16 903 } // kurtosis_excess
Chris@16 904
Chris@16 905 template <class RealType, class Policy>
Chris@16 906 inline RealType kurtosis(const non_central_chi_squared_distribution<RealType, Policy>& dist)
Chris@16 907 {
Chris@16 908 return kurtosis_excess(dist) + 3;
Chris@16 909 }
Chris@16 910
Chris@16 911 template <class RealType, class Policy>
Chris@16 912 inline RealType pdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
Chris@16 913 { // Probability Density/Mass Function.
Chris@16 914 return detail::nccs_pdf(dist, x);
Chris@16 915 } // pdf
Chris@16 916
Chris@16 917 template <class RealType, class Policy>
Chris@16 918 RealType cdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
Chris@16 919 {
Chris@16 920 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::cdf(%1%)";
Chris@16 921 RealType k = dist.degrees_of_freedom();
Chris@16 922 RealType l = dist.non_centrality();
Chris@16 923 RealType r;
Chris@16 924 if(!detail::check_df(
Chris@16 925 function,
Chris@16 926 k, &r, Policy())
Chris@16 927 ||
Chris@16 928 !detail::check_non_centrality(
Chris@16 929 function,
Chris@16 930 l,
Chris@16 931 &r,
Chris@16 932 Policy())
Chris@16 933 ||
Chris@16 934 !detail::check_positive_x(
Chris@16 935 function,
Chris@16 936 x,
Chris@16 937 &r,
Chris@16 938 Policy()))
Chris@16 939 return r;
Chris@16 940
Chris@16 941 return detail::non_central_chi_squared_cdf(x, k, l, false, Policy());
Chris@16 942 } // cdf
Chris@16 943
Chris@16 944 template <class RealType, class Policy>
Chris@16 945 RealType cdf(const complemented2_type<non_central_chi_squared_distribution<RealType, Policy>, RealType>& c)
Chris@16 946 { // Complemented Cumulative Distribution Function
Chris@16 947 const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::cdf(%1%)";
Chris@16 948 non_central_chi_squared_distribution<RealType, Policy> const& dist = c.dist;
Chris@16 949 RealType x = c.param;
Chris@16 950 RealType k = dist.degrees_of_freedom();
Chris@16 951 RealType l = dist.non_centrality();
Chris@16 952 RealType r;
Chris@16 953 if(!detail::check_df(
Chris@16 954 function,
Chris@16 955 k, &r, Policy())
Chris@16 956 ||
Chris@16 957 !detail::check_non_centrality(
Chris@16 958 function,
Chris@16 959 l,
Chris@16 960 &r,
Chris@16 961 Policy())
Chris@16 962 ||
Chris@16 963 !detail::check_positive_x(
Chris@16 964 function,
Chris@16 965 x,
Chris@16 966 &r,
Chris@16 967 Policy()))
Chris@16 968 return r;
Chris@16 969
Chris@16 970 return detail::non_central_chi_squared_cdf(x, k, l, true, Policy());
Chris@16 971 } // ccdf
Chris@16 972
Chris@16 973 template <class RealType, class Policy>
Chris@16 974 inline RealType quantile(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& p)
Chris@16 975 { // Quantile (or Percent Point) function.
Chris@16 976 return detail::nccs_quantile(dist, p, false);
Chris@16 977 } // quantile
Chris@16 978
Chris@16 979 template <class RealType, class Policy>
Chris@16 980 inline RealType quantile(const complemented2_type<non_central_chi_squared_distribution<RealType, Policy>, RealType>& c)
Chris@16 981 { // Quantile (or Percent Point) function.
Chris@16 982 return detail::nccs_quantile(c.dist, c.param, true);
Chris@16 983 } // quantile complement.
Chris@16 984
Chris@16 985 } // namespace math
Chris@16 986 } // namespace boost
Chris@16 987
Chris@16 988 // This include must be at the end, *after* the accessors
Chris@16 989 // for this distribution have been defined, in order to
Chris@16 990 // keep compilers that support two-phase lookup happy.
Chris@16 991 #include <boost/math/distributions/detail/derived_accessors.hpp>
Chris@16 992
Chris@16 993 #endif // BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP
Chris@16 994
Chris@16 995
Chris@16 996