1
// boost\math\distributions\non_central_chi_squared.hpp
3
// Copyright John Maddock 2008.
5
// Use, modification and distribution are subject to the
6
// Boost Software License, Version 1.0.
7
// (See accompanying file LICENSE_1_0.txt
8
// or copy at http://www.boost.org/LICENSE_1_0.txt)
10
#ifndef BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP
11
#define BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP
13
#include <boost/math/distributions/fwd.hpp>
14
#include <boost/math/special_functions/gamma.hpp> // for incomplete gamma. gamma_q
15
#include <boost/math/special_functions/bessel.hpp> // for cyl_bessel_i
16
#include <boost/math/special_functions/round.hpp> // for iround
17
#include <boost/math/distributions/complement.hpp> // complements
18
#include <boost/math/distributions/chi_squared.hpp> // central distribution
19
#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
20
#include <boost/math/special_functions/fpclassify.hpp> // isnan.
21
#include <boost/math/tools/roots.hpp> // for root finding.
22
#include <boost/math/distributions/detail/generic_mode.hpp>
23
#include <boost/math/distributions/detail/generic_quantile.hpp>
30
template <class RealType, class Policy>
31
class non_central_chi_squared_distribution;
35
template <class T, class Policy>
36
T non_central_chi_square_q(T x, T f, T theta, const Policy& pol, T init_sum = 0)
39
// Computes the complement of the Non-Central Chi-Square
40
// Distribution CDF by summing a weighted sum of complements
41
// of the central-distributions. The weighting factor is
42
// a Poisson Distribution.
44
// This is an application of the technique described in:
46
// Computing discrete mixtures of continuous
47
// distributions: noncentral chisquare, noncentral t
48
// and the distribution of the square of the sample
49
// multiple correlation coeficient.
50
// D. Benton, K. Krishnamoorthy.
51
// Computational Statistics & Data Analysis 43 (2003) 249 - 267
60
// Initialize the variables we'll be using:
65
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
66
T errtol = boost::math::policies::get_epsilon<T, Policy>();
69
// k is the starting location for iteration, we'll
70
// move both forwards and backwards from this point.
71
// k is chosen as the peek of the Poisson weights, which
72
// will occur *before* the largest term.
74
int k = iround(lambda, pol);
75
// Forwards and backwards Poisson weights:
76
T poisf = boost::math::gamma_p_derivative(1 + k, lambda, pol);
77
T poisb = poisf * k / lambda;
78
// Initial forwards central chi squared term:
79
T gamf = boost::math::gamma_q(del + k, y, pol);
80
// Forwards and backwards recursion terms on the central chi squared:
81
T xtermf = boost::math::gamma_p_derivative(del + 1 + k, y, pol);
82
T xtermb = xtermf * (del + k) / y;
83
// Initial backwards central chi squared term:
84
T gamb = gamf - xtermb;
87
// Forwards iteration first, this is the
88
// stable direction for the gamma function
92
for(i = k; static_cast<boost::uintmax_t>(i-k) < max_iter; ++i)
94
T term = poisf * gamf;
96
poisf *= lambda / (i + 1);
98
xtermf *= y / (del + i + 1);
99
if(((sum == 0) || (fabs(term / sum) < errtol)) && (term >= poisf * gamf))
103
if(static_cast<boost::uintmax_t>(i-k) >= max_iter)
104
policies::raise_evaluation_error(
105
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
106
"Series did not converge, closest value was %1%", sum, pol);
108
// Now backwards iteration: the gamma
109
// function recurrences are unstable in this
110
// direction, we rely on the terms deminishing in size
111
// faster than we introduce cancellation errors.
112
// For this reason it's very important that we start
113
// *before* the largest term so that backwards iteration
114
// is strictly converging.
116
for(i = k - 1; i >= 0; --i)
118
T term = poisb * gamb;
121
xtermb *= (del + i) / y;
123
if((sum == 0) || (fabs(term / sum) < errtol))
130
template <class T, class Policy>
131
T non_central_chi_square_p_ding(T x, T f, T theta, const Policy& pol, T init_sum = 0)
134
// This is an implementation of:
137
// Computing the Non-Central #2 Distribution Function
139
// Applied Statistics, Vol. 41, No. 2. (1992), pp. 478-482.
141
// This uses a stable forward iteration to sum the
142
// CDF, unfortunately this can not be used for large
143
// values of the non-centrality parameter because:
144
// * The first term may underfow to zero.
145
// * We may need an extra-ordinary number of terms
146
// before we reach the first *significant* term.
152
T tk = boost::math::gamma_p_derivative(f/2 + 1, x/2, pol);
153
T lambda = theta / 2;
156
T sum = init_sum + tk * vk;
160
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
161
T errtol = boost::math::policies::get_epsilon<T, Policy>();
165
for(i = 1; static_cast<boost::uintmax_t>(i) < max_iter; ++i)
167
tk = tk * x / (f + 2 * i);
168
uk = uk * lambda / i;
173
if((fabs(term / sum) < errtol) && (term <= lterm))
177
if(static_cast<boost::uintmax_t>(i) >= max_iter)
178
policies::raise_evaluation_error(
179
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
180
"Series did not converge, closest value was %1%", sum, pol);
185
template <class T, class Policy>
186
T non_central_chi_square_p(T y, T n, T lambda, const Policy& pol, T init_sum)
189
// This is taken more or less directly from:
191
// Computing discrete mixtures of continuous
192
// distributions: noncentral chisquare, noncentral t
193
// and the distribution of the square of the sample
194
// multiple correlation coeficient.
195
// D. Benton, K. Krishnamoorthy.
196
// Computational Statistics & Data Analysis 43 (2003) 249 - 267
198
// We're summing a Poisson weighting term multiplied by
199
// a central chi squared distribution.
205
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
206
T errtol = boost::math::policies::get_epsilon<T, Policy>();
207
T errorf(0), errorb(0);
212
// Starting location for the iteration, we'll iterate
213
// both forwards and backwards from this point. The
214
// location chosen is the maximum of the Poisson weight
215
// function, which ocurrs *after* the largest term in the
218
int k = iround(del, pol);
220
// Central chi squared term for forward iteration:
221
T gamkf = boost::math::gamma_p(a, x, pol);
225
// Central chi squared term for backward iteration:
227
// Forwards Poisson weight:
228
T poiskf = gamma_p_derivative(k+1, del, pol);
229
// Backwards Poisson weight:
231
// Forwards gamma function recursion term:
232
T xtermf = boost::math::gamma_p_derivative(a, x, pol);
233
// Backwards gamma function recursion term:
234
T xtermb = xtermf * x / a;
235
T sum = init_sum + poiskf * gamkf;
240
// Backwards recursion first, this is the stable
241
// direction for gamma function recurrences:
245
xtermb *= (a - i + 1) / x;
247
poiskb = poiskb * (k - i + 1) / del;
249
errorb = gamkb * poiskb;
251
if((fabs(errorb / sum) < errtol) && (errorb <= errorf))
257
// Now forwards recursion, the gamma function
258
// recurrence relation is unstable in this direction,
259
// so we rely on the magnitude of successive terms
260
// decreasing faster than we introduce cancellation error.
261
// For this reason it's vital that k is chosen to be *after*
262
// the largest term, so that successive forward iterations
263
// are strictly (and rapidly) converging.
267
xtermf = xtermf * x / (a + i - 1);
268
gamkf = gamkf - xtermf;
269
poiskf = poiskf * del / (k + i);
270
errorf = poiskf * gamkf;
273
}while((fabs(errorf / sum) > errtol) && (static_cast<boost::uintmax_t>(i) < max_iter));
276
if(static_cast<boost::uintmax_t>(i) >= max_iter)
277
policies::raise_evaluation_error(
278
"cdf(non_central_chi_squared_distribution<%1%>, %1%)",
279
"Series did not converge, closest value was %1%", sum, pol);
284
template <class T, class Policy>
285
T non_central_chi_square_pdf(T x, T n, T lambda, const Policy& pol)
288
// As above but for the PDF:
291
boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
292
T errtol = boost::math::policies::get_epsilon<T, Policy>();
298
T pois = gamma_p_derivative(k + 1, l2, pol) * gamma_p_derivative(n2 + k, x2);
302
for(int i = k; ; ++i)
305
if(pois / sum < errtol)
307
if(static_cast<boost::uintmax_t>(i - k) >= max_iter)
308
return policies::raise_evaluation_error(
309
"pdf(non_central_chi_squared_distribution<%1%>, %1%)",
310
"Series did not converge, closest value was %1%", sum, pol);
311
pois *= l2 * x2 / ((i + 1) * (n2 + i));
313
for(int i = k - 1; i >= 0; --i)
315
poisb *= (i + 1) * (n2 + i) / (l2 * x2);
317
if(poisb / sum < errtol)
323
template <class RealType, class Policy>
324
inline RealType non_central_chi_squared_cdf(RealType x, RealType k, RealType l, bool invert, const Policy&)
326
typedef typename policies::evaluation<RealType, Policy>::type value_type;
327
typedef typename policies::normalise<
329
policies::promote_float<false>,
330
policies::promote_double<false>,
331
policies::discrete_quantile<>,
332
policies::assert_undefined<> >::type forwarding_policy;
337
result = cdf(boost::math::chi_squared_distribution<RealType, Policy>(k), x);
340
// Complement is the smaller of the two:
341
result = detail::non_central_chi_square_q(
342
static_cast<value_type>(x),
343
static_cast<value_type>(k),
344
static_cast<value_type>(l),
346
static_cast<value_type>(invert ? 0 : -1));
351
// For small values of the non-centrality parameter
352
// we can use Ding's method:
353
result = detail::non_central_chi_square_p_ding(
354
static_cast<value_type>(x),
355
static_cast<value_type>(k),
356
static_cast<value_type>(l),
358
static_cast<value_type>(invert ? -1 : 0));
362
// For largers values of the non-centrality
363
// parameter Ding's method will consume an
364
// extra-ordinary number of terms, and worse
365
// may return zero when the result is in fact
366
// finite, use Krishnamoorthy's method instead:
367
result = detail::non_central_chi_square_p(
368
static_cast<value_type>(x),
369
static_cast<value_type>(k),
370
static_cast<value_type>(l),
372
static_cast<value_type>(invert ? -1 : 0));
376
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
378
"boost::math::non_central_chi_squared_cdf<%1%>(%1%, %1%, %1%)");
381
template <class T, class Policy>
382
struct nccs_quantile_functor
384
nccs_quantile_functor(const non_central_chi_squared_distribution<T,Policy>& d, T t, bool c)
385
: dist(d), target(t), comp(c) {}
387
T operator()(const T& x)
390
target - cdf(complement(dist, x))
391
: cdf(dist, x) - target;
395
non_central_chi_squared_distribution<T,Policy> dist;
400
template <class RealType, class Policy>
401
RealType nccs_quantile(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& p, bool comp)
403
static const char* function = "quantile(non_central_chi_squared_distribution<%1%>, %1%)";
404
typedef typename policies::evaluation<RealType, Policy>::type value_type;
405
typedef typename policies::normalise<
407
policies::promote_float<false>,
408
policies::promote_double<false>,
409
policies::discrete_quantile<>,
410
policies::assert_undefined<> >::type forwarding_policy;
412
value_type k = dist.degrees_of_freedom();
413
value_type l = dist.non_centrality();
415
if(!detail::check_df(
419
!detail::check_non_centrality(
425
!detail::check_probability(
427
static_cast<value_type>(p),
432
value_type b = (l * l) / (k + 3 * l);
433
value_type c = (k + 3 * l) / (k + 2 * l);
434
value_type ff = (k + 2 * l) / (c * c);
437
guess = b + c * quantile(complement(chi_squared_distribution<value_type, forwarding_policy>(ff), p));
439
guess = b + c * quantile(chi_squared_distribution<value_type, forwarding_policy>(ff), p);
442
guess = tools::min_value<value_type>();
444
value_type result = detail::generic_quantile(
445
non_central_chi_squared_distribution<value_type, forwarding_policy>(k, l),
450
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
455
template <class RealType, class Policy>
456
RealType nccs_pdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
459
static const char* function = "pdf(non_central_chi_squared_distribution<%1%>, %1%)";
460
typedef typename policies::evaluation<RealType, Policy>::type value_type;
461
typedef typename policies::normalise<
463
policies::promote_float<false>,
464
policies::promote_double<false>,
465
policies::discrete_quantile<>,
466
policies::assert_undefined<> >::type forwarding_policy;
468
value_type k = dist.degrees_of_freedom();
469
value_type l = dist.non_centrality();
471
if(!detail::check_df(
475
!detail::check_non_centrality(
481
!detail::check_positive_x(
490
return pdf(boost::math::chi_squared_distribution<RealType, forwarding_policy>(dist.degrees_of_freedom()), x);
497
r = non_central_chi_square_pdf(static_cast<value_type>(x), k, l, forwarding_policy());
501
r = log(x / l) * (k / 4 - 0.5f) - (x + l) / 2;
502
if(fabs(r) >= tools::log_max_value<RealType>() / 4)
504
r = non_central_chi_square_pdf(static_cast<value_type>(x), k, l, forwarding_policy());
510
* boost::math::cyl_bessel_i(k/2 - 1, sqrt(l * x), forwarding_policy());
513
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
518
template <class RealType, class Policy>
519
struct degrees_of_freedom_finder
521
degrees_of_freedom_finder(
522
RealType lam_, RealType x_, RealType p_, bool c)
523
: lam(lam_), x(x_), p(p_), comp(c) {}
525
RealType operator()(const RealType& v)
527
non_central_chi_squared_distribution<RealType, Policy> d(v, lam);
529
p - cdf(complement(d, x))
539
template <class RealType, class Policy>
540
inline RealType find_degrees_of_freedom(
541
RealType lam, RealType x, RealType p, RealType q, const Policy& pol)
543
const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
544
if((p == 0) || (q == 0))
547
// Can't a thing if one of p and q is zero:
549
return policies::raise_evaluation_error<RealType>(function,
550
"Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%",
551
RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
553
degrees_of_freedom_finder<RealType, Policy> f(lam, x, p < q ? p : q, p < q ? false : true);
554
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
555
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
557
// Pick an initial guess that we know will give us a probability
560
RealType guess = x - lam;
563
std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
564
f, guess, RealType(2), false, tol, max_iter, pol);
565
RealType result = ir.first + (ir.second - ir.first) / 2;
566
if(max_iter >= policies::get_max_root_iterations<Policy>())
568
policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
569
" or there is no answer to problem. Current best guess is %1%", result, Policy());
574
template <class RealType, class Policy>
575
struct non_centrality_finder
577
non_centrality_finder(
578
RealType v_, RealType x_, RealType p_, bool c)
579
: v(v_), x(x_), p(p_), comp(c) {}
581
RealType operator()(const RealType& lam)
583
non_central_chi_squared_distribution<RealType, Policy> d(v, lam);
585
p - cdf(complement(d, x))
595
template <class RealType, class Policy>
596
inline RealType find_non_centrality(
597
RealType v, RealType x, RealType p, RealType q, const Policy& pol)
599
const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
600
if((p == 0) || (q == 0))
603
// Can't do a thing if one of p and q is zero:
605
return policies::raise_evaluation_error<RealType>(function,
606
"Can't find non centrality parameter when the probability is 0 or 1, only possible answer is %1%",
607
RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
609
non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
610
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
611
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
613
// Pick an initial guess that we know will give us a probability
616
RealType guess = x - v;
619
std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
620
f, guess, RealType(2), false, tol, max_iter, pol);
621
RealType result = ir.first + (ir.second - ir.first) / 2;
622
if(max_iter >= policies::get_max_root_iterations<Policy>())
624
policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
625
" or there is no answer to problem. Current best guess is %1%", result, Policy());
632
template <class RealType = double, class Policy = policies::policy<> >
633
class non_central_chi_squared_distribution
636
typedef RealType value_type;
637
typedef Policy policy_type;
639
non_central_chi_squared_distribution(RealType df_, RealType lambda) : df(df_), ncp(lambda)
641
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::non_central_chi_squared_distribution(%1%,%1%)";
646
detail::check_non_centrality(
651
} // non_central_chi_squared_distribution constructor.
653
RealType degrees_of_freedom() const
654
{ // Private data getter function.
657
RealType non_centrality() const
658
{ // Private data getter function.
661
static RealType find_degrees_of_freedom(RealType lam, RealType x, RealType p)
663
const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
664
typedef typename policies::evaluation<RealType, Policy>::type value_type;
665
typedef typename policies::normalise<
667
policies::promote_float<false>,
668
policies::promote_double<false>,
669
policies::discrete_quantile<>,
670
policies::assert_undefined<> >::type forwarding_policy;
671
value_type result = detail::find_degrees_of_freedom(
672
static_cast<value_type>(lam),
673
static_cast<value_type>(x),
674
static_cast<value_type>(p),
675
static_cast<value_type>(1-p),
676
forwarding_policy());
677
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
681
template <class A, class B, class C>
682
static RealType find_degrees_of_freedom(const complemented3_type<A,B,C>& c)
684
const char* function = "non_central_chi_squared<%1%>::find_degrees_of_freedom";
685
typedef typename policies::evaluation<RealType, Policy>::type value_type;
686
typedef typename policies::normalise<
688
policies::promote_float<false>,
689
policies::promote_double<false>,
690
policies::discrete_quantile<>,
691
policies::assert_undefined<> >::type forwarding_policy;
692
value_type result = detail::find_degrees_of_freedom(
693
static_cast<value_type>(c.dist),
694
static_cast<value_type>(c.param1),
695
static_cast<value_type>(1-c.param2),
696
static_cast<value_type>(c.param2),
697
forwarding_policy());
698
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
702
static RealType find_non_centrality(RealType v, RealType x, RealType p)
704
const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
705
typedef typename policies::evaluation<RealType, Policy>::type value_type;
706
typedef typename policies::normalise<
708
policies::promote_float<false>,
709
policies::promote_double<false>,
710
policies::discrete_quantile<>,
711
policies::assert_undefined<> >::type forwarding_policy;
712
value_type result = detail::find_non_centrality(
713
static_cast<value_type>(v),
714
static_cast<value_type>(x),
715
static_cast<value_type>(p),
716
static_cast<value_type>(1-p),
717
forwarding_policy());
718
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
722
template <class A, class B, class C>
723
static RealType find_non_centrality(const complemented3_type<A,B,C>& c)
725
const char* function = "non_central_chi_squared<%1%>::find_non_centrality";
726
typedef typename policies::evaluation<RealType, Policy>::type value_type;
727
typedef typename policies::normalise<
729
policies::promote_float<false>,
730
policies::promote_double<false>,
731
policies::discrete_quantile<>,
732
policies::assert_undefined<> >::type forwarding_policy;
733
value_type result = detail::find_non_centrality(
734
static_cast<value_type>(c.dist),
735
static_cast<value_type>(c.param1),
736
static_cast<value_type>(1-c.param2),
737
static_cast<value_type>(c.param2),
738
forwarding_policy());
739
return policies::checked_narrowing_cast<RealType, forwarding_policy>(
744
// Data member, initialized by constructor.
745
RealType df; // degrees of freedom.
746
RealType ncp; // non-centrality parameter
747
}; // template <class RealType, class Policy> class non_central_chi_squared_distribution
749
typedef non_central_chi_squared_distribution<double> non_central_chi_squared; // Reserved name of type double.
751
// Non-member functions to give properties of the distribution.
753
template <class RealType, class Policy>
754
inline const std::pair<RealType, RealType> range(const non_central_chi_squared_distribution<RealType, Policy>& /* dist */)
755
{ // Range of permissible values for random variable k.
756
using boost::math::tools::max_value;
757
return std::pair<RealType, RealType>(0, max_value<RealType>()); // Max integer?
760
template <class RealType, class Policy>
761
inline const std::pair<RealType, RealType> support(const non_central_chi_squared_distribution<RealType, Policy>& /* dist */)
762
{ // Range of supported values for random variable k.
763
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
764
using boost::math::tools::max_value;
765
return std::pair<RealType, RealType>(0, max_value<RealType>());
768
template <class RealType, class Policy>
769
inline RealType mean(const non_central_chi_squared_distribution<RealType, Policy>& dist)
770
{ // Mean of poisson distribution = lambda.
771
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::mean()";
772
RealType k = dist.degrees_of_freedom();
773
RealType l = dist.non_centrality();
775
if(!detail::check_df(
779
!detail::check_non_centrality(
788
template <class RealType, class Policy>
789
inline RealType mode(const non_central_chi_squared_distribution<RealType, Policy>& dist)
791
static const char* function = "mode(non_central_chi_squared_distribution<%1%> const&)";
793
RealType k = dist.degrees_of_freedom();
794
RealType l = dist.non_centrality();
796
if(!detail::check_df(
800
!detail::check_non_centrality(
806
return detail::generic_find_mode(dist, 1 + k, function);
809
template <class RealType, class Policy>
810
inline RealType variance(const non_central_chi_squared_distribution<RealType, Policy>& dist)
812
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::variance()";
813
RealType k = dist.degrees_of_freedom();
814
RealType l = dist.non_centrality();
816
if(!detail::check_df(
820
!detail::check_non_centrality(
826
return 2 * (2 * l + k);
829
// RealType standard_deviation(const non_central_chi_squared_distribution<RealType, Policy>& dist)
830
// standard_deviation provided by derived accessors.
832
template <class RealType, class Policy>
833
inline RealType skewness(const non_central_chi_squared_distribution<RealType, Policy>& dist)
834
{ // skewness = sqrt(l).
835
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::skewness()";
836
RealType k = dist.degrees_of_freedom();
837
RealType l = dist.non_centrality();
839
if(!detail::check_df(
843
!detail::check_non_centrality(
850
return pow(2 / (k + 2 * l), RealType(3)/2) * (k + 3 * l);
853
template <class RealType, class Policy>
854
inline RealType kurtosis_excess(const non_central_chi_squared_distribution<RealType, Policy>& dist)
856
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::kurtosis_excess()";
857
RealType k = dist.degrees_of_freedom();
858
RealType l = dist.non_centrality();
860
if(!detail::check_df(
864
!detail::check_non_centrality(
870
return 12 * (k + 4 * l) / ((k + 2 * l) * (k + 2 * l));
873
template <class RealType, class Policy>
874
inline RealType kurtosis(const non_central_chi_squared_distribution<RealType, Policy>& dist)
876
return kurtosis_excess(dist) + 3;
879
template <class RealType, class Policy>
880
inline RealType pdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
881
{ // Probability Density/Mass Function.
882
return detail::nccs_pdf(dist, x);
885
template <class RealType, class Policy>
886
RealType cdf(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& x)
888
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::cdf(%1%)";
889
RealType k = dist.degrees_of_freedom();
890
RealType l = dist.non_centrality();
892
if(!detail::check_df(
896
!detail::check_non_centrality(
902
!detail::check_positive_x(
909
return detail::non_central_chi_squared_cdf(x, k, l, false, Policy());
912
template <class RealType, class Policy>
913
RealType cdf(const complemented2_type<non_central_chi_squared_distribution<RealType, Policy>, RealType>& c)
914
{ // Complemented Cumulative Distribution Function
915
const char* function = "boost::math::non_central_chi_squared_distribution<%1%>::cdf(%1%)";
916
non_central_chi_squared_distribution<RealType, Policy> const& dist = c.dist;
917
RealType x = c.param;
918
RealType k = dist.degrees_of_freedom();
919
RealType l = dist.non_centrality();
921
if(!detail::check_df(
925
!detail::check_non_centrality(
931
!detail::check_positive_x(
938
return detail::non_central_chi_squared_cdf(x, k, l, true, Policy());
941
template <class RealType, class Policy>
942
inline RealType quantile(const non_central_chi_squared_distribution<RealType, Policy>& dist, const RealType& p)
943
{ // Quantile (or Percent Point) function.
944
return detail::nccs_quantile(dist, p, false);
947
template <class RealType, class Policy>
948
inline RealType quantile(const complemented2_type<non_central_chi_squared_distribution<RealType, Policy>, RealType>& c)
949
{ // Quantile (or Percent Point) function.
950
return detail::nccs_quantile(c.dist, c.param, true);
951
} // quantile complement.
956
// This include must be at the end, *after* the accessors
957
// for this distribution have been defined, in order to
958
// keep compilers that support two-phase lookup happy.
959
#include <boost/math/distributions/detail/derived_accessors.hpp>
961
#endif // BOOST_MATH_SPECIAL_NON_CENTRAL_CHI_SQUARE_HPP