| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330 |
- // boost\math\distributions\non_central_t.hpp
- // Copyright John Maddock 2008.
- // Use, modification and distribution are subject to the
- // Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt
- // or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_MATH_SPECIAL_NON_CENTRAL_T_HPP
- #define BOOST_MATH_SPECIAL_NON_CENTRAL_T_HPP
- #include <boost/math/distributions/fwd.hpp>
- #include <boost/math/distributions/non_central_beta.hpp> // for nc beta
- #include <boost/math/distributions/normal.hpp> // for normal CDF and quantile
- #include <boost/math/distributions/students_t.hpp>
- #include <boost/math/distributions/detail/generic_quantile.hpp> // quantile
- #include <boost/math/special_functions/trunc.hpp>
- #include <boost/math/special_functions/detail/hypergeometric_series.hpp>
- #include <boost/math/quadrature/exp_sinh.hpp>
- namespace boost
- {
- namespace math
- {
- template <class RealType, class Policy>
- class non_central_t_distribution;
- namespace detail{
- template <class T, class Policy>
- T non_central_t2_p(T v, T delta, T x, T y, const Policy& pol, T init_val)
- {
- BOOST_MATH_STD_USING
- //
- // Variables come first:
- //
- std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
- T errtol = policies::get_epsilon<T, Policy>();
- T d2 = delta * delta / 2;
- //
- // k is the starting point for iteration, and is the
- // maximum of the poisson weighting term, we don't
- // ever allow k == 0 as this can lead to catastrophic
- // cancellation errors later (test case is v = 1621286869049072.3
- // delta = 0.16212868690490723, x = 0.86987415482475994).
- //
- long long k = lltrunc(d2);
- T pois;
- if(k == 0) k = 1;
- // Starting Poisson weight:
- pois = gamma_p_derivative(T(k+1), d2, pol)
- * tgamma_delta_ratio(T(k + 1), T(0.5f))
- * delta / constants::root_two<T>();
- if(pois == 0)
- return init_val;
- T xterm, beta;
- // Recurrence & starting beta terms:
- beta = x < y
- ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, false, true, &xterm)
- : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, true, true, &xterm);
- while (fabs(beta * pois) < tools::min_value<T>())
- {
- if ((k == 0) || (pois == 0))
- return init_val;
- k /= 2;
- pois = gamma_p_derivative(T(k + 1), d2, pol)
- * tgamma_delta_ratio(T(k + 1), T(0.5f))
- * delta / constants::root_two<T>();
- beta = x < y
- ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, false, true, &xterm)
- : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, true, true, &xterm);
- }
- xterm *= y / (v / 2 + k);
- T poisf(pois), betaf(beta), xtermf(xterm);
- T sum = init_val;
- if((xterm == 0) && (beta == 0))
- return init_val;
- //
- // Backwards recursion first, this is the stable
- // direction for recursion:
- //
- std::uintmax_t count = 0;
- T last_term = 0;
- for(auto i = k; i >= 0; --i)
- {
- T term = beta * pois;
- sum += term;
- // Don't terminate on first term in case we "fixed" k above:
- if(((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol) || (v == 2 && i == 0))
- break;
- last_term = term;
- pois *= (i + 0.5f) / d2;
- beta += xterm;
- xterm *= (i) / (x * (v / 2 + i - 1));
- ++count;
- }
- last_term = 0;
- T betaf_lim = betaf * tools::epsilon<T>() * 4;
- for(auto i = k + 1; ; ++i)
- {
- poisf *= d2 / (i + 0.5f);
- xtermf *= (x * (v / 2 + i - 1)) / (i);
- betaf -= xtermf;
- if (betaf < betaf_lim)
- break; // Nothing but garbage left in betaf now!!
- T term = poisf * betaf;
- sum += term;
- if((fabs(last_term) >= fabs(term)) && (fabs(term/sum) < errtol))
- break;
- last_term = term;
- ++count;
- if(count > max_iter)
- {
- return policies::raise_evaluation_error("cdf(non_central_t_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE
- }
- }
- return sum;
- }
- template <class T, class Policy>
- T non_central_t2_q(T v, T delta, T x, T y, const Policy& pol, T init_val)
- {
- BOOST_MATH_STD_USING
- //
- // Variables come first:
- //
- std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
- T errtol = boost::math::policies::get_epsilon<T, Policy>();
- T d2 = delta * delta / 2;
- //
- // k is the starting point for iteration, and is the
- // maximum of the poisson weighting term, we don't allow
- // k == 0 as this can cause catastrophic cancellation errors
- // (test case is v = 561908036470413.25, delta = 0.056190803647041321,
- // x = 1.6155232703966216):
- //
- long long k = lltrunc(d2);
- if(k == 0) k = 1;
- // Starting Poisson weight:
- T pois;
- if((k < static_cast<long long>(max_factorial<T>::value)) && (d2 < tools::log_max_value<T>()) && (log(d2) * k < tools::log_max_value<T>()))
- {
- //
- // For small k we can optimise this calculation by using
- // a simpler reduced formula:
- //
- pois = exp(-d2);
- pois *= pow(d2, static_cast<T>(k));
- pois /= boost::math::tgamma(T(k + 1 + 0.5), pol);
- pois *= delta / constants::root_two<T>();
- }
- else
- {
- pois = gamma_p_derivative(T(k+1), d2, pol)
- * tgamma_delta_ratio(T(k + 1), T(0.5f))
- * delta / constants::root_two<T>();
- }
- if(pois == 0)
- return init_val;
- // Recurance term:
- T xterm;
- T beta;
- // Starting beta term:
- if(k != 0)
- {
- beta = x < y
- ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, true, true, &xterm)
- : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, false, true, &xterm);
- xterm *= y / (v / 2 + k);
- }
- else
- {
- beta = pow(y, v / 2);
- xterm = beta;
- }
- T poisf(pois), betaf(beta), xtermf(xterm);
- T sum = init_val;
- if((xterm == 0) && (beta == 0))
- return init_val;
- //
- // Fused forward and backwards recursion:
- //
- std::uintmax_t count = 0;
- T last_term = 0;
- for(auto i = k + 1, j = k; ; ++i, --j)
- {
- poisf *= d2 / (i + 0.5f);
- xtermf *= (x * (v / 2 + i - 1)) / (i);
- betaf += xtermf;
- T term = poisf * betaf;
- if(j >= 0)
- {
- term += beta * pois;
- pois *= (j + 0.5f) / d2;
- beta -= xterm;
- if(!(v == 2 && j == 0))
- xterm *= (j) / (x * (v / 2 + j - 1));
- }
- sum += term;
- // Don't terminate on first term in case we "fixed" the value of k above:
- if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol)
- break;
- last_term = term;
- if(count > max_iter)
- {
- return policies::raise_evaluation_error("cdf(non_central_t_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE
- }
- ++count;
- }
- return sum;
- }
- template <class T, class Policy>
- T non_central_t_cdf(T v, T delta, T t, bool invert, const Policy& pol)
- {
- BOOST_MATH_STD_USING
- if ((boost::math::isinf)(v))
- { // Infinite degrees of freedom, so use normal distribution located at delta.
- normal_distribution<T, Policy> n(delta, 1);
- return cdf(n, t);
- }
- //
- // Otherwise, for t < 0 we have to use the reflection formula:
- if(t < 0)
- {
- t = -t;
- delta = -delta;
- invert = !invert;
- }
- if(fabs(delta / (4 * v)) < policies::get_epsilon<T, Policy>())
- {
- // Approximate with a Student's T centred on delta,
- // the crossover point is based on eq 2.6 from
- // "A Comparison of Approximations To Percentiles of the
- // Noncentral t-Distribution". H. Sahai and M. M. Ojeda,
- // Revista Investigacion Operacional Vol 21, No 2, 2000.
- // Original sources referenced in the above are:
- // "Some Approximations to the Percentage Points of the Noncentral
- // t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31.
- // "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and
- // N. Balkrishnan. 1995. John Wiley and Sons New York.
- T result = cdf(students_t_distribution<T, Policy>(v), t - delta);
- return invert ? 1 - result : result;
- }
- //
- // x and y are the corresponding random
- // variables for the noncentral beta distribution,
- // with y = 1 - x:
- //
- T x = t * t / (v + t * t);
- T y = v / (v + t * t);
- T d2 = delta * delta;
- T a = 0.5f;
- T b = v / 2;
- T c = a + b + d2 / 2;
- //
- // Crossover point for calculating p or q is the same
- // as for the noncentral beta:
- //
- T cross = 1 - (b / c) * (1 + d2 / (2 * c * c));
- T result;
- if(x < cross)
- {
- //
- // Calculate p:
- //
- if(x != 0)
- {
- result = non_central_beta_p(a, b, d2, x, y, pol);
- result = non_central_t2_p(v, delta, x, y, pol, result);
- result /= 2;
- }
- else
- result = 0;
- if (invert)
- {
- result = cdf(complement(boost::math::normal_distribution<T, Policy>(), -delta)) - result;
- invert = false;
- }
- else
- result += cdf(boost::math::normal_distribution<T, Policy>(), -delta);
- }
- else
- {
- //
- // Calculate q:
- //
- invert = !invert;
- if(x != 0)
- {
- result = non_central_beta_q(a, b, d2, x, y, pol);
- result = non_central_t2_q(v, delta, x, y, pol, result);
- result /= 2;
- }
- else // x == 0
- result = cdf(complement(boost::math::normal_distribution<T, Policy>(), -delta));
- }
- if(invert)
- result = 1 - result;
- return result;
- }
- template <class T, class Policy>
- T non_central_t_quantile(const char* function, T v, T delta, T p, T q, const Policy&)
- {
- BOOST_MATH_STD_USING
- // static const char* function = "quantile(non_central_t_distribution<%1%>, %1%)";
- // now passed as function
- typedef typename policies::evaluation<T, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- T r;
- if(!detail::check_df_gt0_to_inf(
- function,
- v, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- static_cast<T>(delta * delta),
- &r,
- Policy())
- ||
- !detail::check_probability(
- function,
- p,
- &r,
- Policy()))
- return r;
- value_type guess = 0;
- if ( ((boost::math::isinf)(v)) || (v > 1 / boost::math::tools::epsilon<T>()) )
- { // Infinite or very large degrees of freedom, so use normal distribution located at delta.
- normal_distribution<T, Policy> n(delta, 1);
- if (p < q)
- {
- return quantile(n, p);
- }
- else
- {
- return quantile(complement(n, q));
- }
- }
- else if(v > 3)
- { // Use normal distribution to calculate guess.
- value_type mean = (v > 1 / policies::get_epsilon<T, Policy>()) ? delta : delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f));
- value_type var = (v > 1 / policies::get_epsilon<T, Policy>()) ? value_type(1) : (((delta * delta + 1) * v) / (v - 2) - mean * mean);
- if(p < q)
- guess = quantile(normal_distribution<value_type, forwarding_policy>(mean, var), p);
- else
- guess = quantile(complement(normal_distribution<value_type, forwarding_policy>(mean, var), q));
- }
- //
- // We *must* get the sign of the initial guess correct,
- // or our root-finder will fail, so double check it now:
- //
- value_type pzero = non_central_t_cdf(
- static_cast<value_type>(v),
- static_cast<value_type>(delta),
- static_cast<value_type>(0),
- !(p < q),
- forwarding_policy());
- int s;
- if(p < q)
- s = boost::math::sign(p - pzero);
- else
- s = boost::math::sign(pzero - q);
- if(s != boost::math::sign(guess))
- {
- guess = static_cast<T>(s);
- }
- value_type result = detail::generic_quantile(
- non_central_t_distribution<value_type, forwarding_policy>(v, delta),
- (p < q ? p : q),
- guess,
- (p >= q),
- function);
- return policies::checked_narrowing_cast<T, forwarding_policy>(
- result,
- function);
- }
- template <class T, class Policy>
- T non_central_t_pdf_integral(T x, T v, T mu, const Policy& pol)
- {
- BOOST_MATH_STD_USING
- boost::math::quadrature::exp_sinh<T, Policy> integrator;
- T integral = pow(v, v / 2) * exp(-v * mu * mu / (2 * (x * x + v)));
- if (integral != 0)
- {
- integral *= integrator.integrate([&x, v, mu](T y)
- {
- T p;
- if (v * log(y) < tools::log_max_value<T>())
- p = pow(y, v) * exp(boost::math::pow<2>((y - mu * x / sqrt(x * x + v))) / -2);
- else
- p = exp(log(y) * v + boost::math::pow<2>((y - mu * x / sqrt(x * x + v))) / -2);
- return p;
- });
- }
- integral /= boost::math::constants::root_pi<T>() * boost::math::tgamma(v / 2, pol) * pow(T(2), (v - 1) / 2) * pow(x * x + v, (v + 1) / 2);
- return integral;
- }
- template <class T, class Policy>
- T non_central_t_pdf_hypergeometric(T x, T v, T mu, const Policy& pol)
- {
- BOOST_MATH_STD_USING
- long long scale = 0;
- const char* function = "non central T PDF";
- //
- // We only call this routine when we know that the series form of 1F1 is cheap to evaluate,
- // so no need to call the whole 1F1 function, just the series will do:
- //
- T Av = hypergeometric_1F1_generic_series(static_cast<T>((v + 1) / 2), boost::math::constants::half<T>(), static_cast<T>(mu * mu * x * x / (2 * (x * x + v))), pol, scale, function);
- Av = ldexp(Av, static_cast<int>(scale));
- scale = 0;
- T Bv = hypergeometric_1F1_generic_series(static_cast<T>(v / 2 + T(1)), static_cast<T>(T(3) / 2), static_cast<T>(mu * mu * x * x / (2 * (x * x + v))), pol, scale, function);
- Bv = ldexp(Bv, static_cast<int>(scale));
- Bv *= boost::math::tgamma_delta_ratio(v / 2 + T(1), -constants::half<T>(), pol);
- Bv *= boost::math::constants::root_two<T>() * mu * x / sqrt(x * x + v);
- T tolerance = tools::root_epsilon<T>() * Av * 4;
- Av += Bv;
- if (Av < tolerance)
- {
- // More than half the digits have cancelled, fall back to the integral method:
- return non_central_t_pdf_integral(x, v, mu, pol);
- }
- Av *= exp(-mu * mu / 2) * pow(1 + x * x / v, -(v + 1) / 2) * boost::math::tgamma_delta_ratio(v / 2 + constants::half<T>(), -constants::half<T>(), pol);
- Av /= sqrt(v) * boost::math::constants::root_pi<T>();
- return Av;
- }
- template <class T, class Policy>
- T non_central_t2_pdf(T n, T delta, T x, T y, const Policy& pol, T init_val)
- {
- BOOST_MATH_STD_USING
- //
- // Variables come first:
- //
- std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
- T errtol = boost::math::policies::get_epsilon<T, Policy>();
- T d2 = delta * delta / 2;
- //
- // k is the starting point for iteration, and is the
- // maximum of the poisson weighting term:
- //
- long long k = lltrunc(d2);
- T pois, xterm;
- if(k == 0)
- k = 1;
- // Starting Poisson weight:
- pois = gamma_p_derivative(T(k+1), d2, pol)
- * tgamma_delta_ratio(T(k + 1), T(0.5f))
- * delta / constants::root_two<T>();
- BOOST_MATH_INSTRUMENT_VARIABLE(pois);
- // Starting beta term:
- xterm = x < y
- ? ibeta_derivative(T(k + 1), n / 2, x, pol)
- : ibeta_derivative(n / 2, T(k + 1), y, pol);
- BOOST_MATH_INSTRUMENT_VARIABLE(xterm);
- while (fabs(xterm * pois) < tools::min_value<T>())
- {
- if (k == 0)
- return init_val;
- k /= 2;
- pois = gamma_p_derivative(T(k + 1), d2, pol)
- * tgamma_delta_ratio(T(k + 1), T(0.5f))
- * delta / constants::root_two<T>();
- BOOST_MATH_INSTRUMENT_VARIABLE(pois);
- // Starting beta term:
- xterm = x < y
- ? ibeta_derivative(T(k + 1), n / 2, x, pol)
- : ibeta_derivative(n / 2, T(k + 1), y, pol);
- BOOST_MATH_INSTRUMENT_VARIABLE(xterm);
- }
- T poisf(pois), xtermf(xterm);
- T sum = init_val;
- //
- // Backwards recursion first, this is the stable
- // direction for recursion:
- //
- std::uintmax_t count = 0;
- T old_ratio = 1; // arbitrary "large" value
- for(auto i = k; i >= 0; --i)
- {
- T term = xterm * pois;
- sum += term;
- BOOST_MATH_INSTRUMENT_VARIABLE(sum);
- T ratio = fabs(term / sum);
- if(((ratio < errtol) && (i != k) && (ratio < old_ratio)) || (term == 0))
- break;
- old_ratio = ratio;
- pois *= (i + 0.5f) / d2;
- xterm *= (i) / (x * (n / 2 + i));
- ++count;
- if(count > max_iter)
- {
- return policies::raise_evaluation_error("pdf(non_central_t_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE
- }
- }
- BOOST_MATH_INSTRUMENT_VARIABLE(sum);
- old_ratio = 0;
- for(auto i = k + 1; ; ++i)
- {
- poisf *= d2 / (i + 0.5f);
- xtermf *= (x * (n / 2 + i)) / (i);
- T term = poisf * xtermf;
- sum += term;
- T ratio = fabs(term / sum);
- if(((ratio < errtol) && (ratio < old_ratio)) || (term == 0))
- break;
- ++count;
- old_ratio = ratio;
- if(count > max_iter)
- {
- return policies::raise_evaluation_error("pdf(non_central_t_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); // LCOV_EXCL_LINE
- }
- }
- BOOST_MATH_INSTRUMENT_VARIABLE(sum);
- return sum;
- }
- template <class T, class Policy>
- T non_central_t_pdf(T n, T delta, T t, const Policy& pol)
- {
- BOOST_MATH_STD_USING
- if ((boost::math::isinf)(n))
- { // Infinite degrees of freedom, so use normal distribution located at delta.
- normal_distribution<T, Policy> norm(delta, 1);
- return pdf(norm, t);
- }
- if(t * t < tools::epsilon<T>())
- {
- //
- // Handle this as a special case, using the formula
- // from Weisstein, Eric W.
- // "Noncentral Student's t-Distribution."
- // From MathWorld--A Wolfram Web Resource.
- // http://mathworld.wolfram.com/NoncentralStudentst-Distribution.html
- //
- // The formula is simplified thanks to the relation
- // 1F1(a,b,0) = 1.
- //
- return tgamma_delta_ratio(n / 2 + 0.5f, T(0.5f))
- * sqrt(n / constants::pi<T>())
- * exp(-delta * delta / 2) / 2;
- }
- if(fabs(delta / (4 * n)) < policies::get_epsilon<T, Policy>())
- {
- // Approximate with a Student's T centred on delta,
- // the crossover point is based on eq 2.6 from
- // "A Comparison of Approximations To Percentiles of the
- // Noncentral t-Distribution". H. Sahai and M. M. Ojeda,
- // Revista Investigacion Operacional Vol 21, No 2, 2000.
- // Original sources referenced in the above are:
- // "Some Approximations to the Percentage Points of the Noncentral
- // t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31.
- // "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and
- // N. Balkrishnan. 1995. John Wiley and Sons New York.
- return pdf(students_t_distribution<T, Policy>(n), t - delta);
- }
- //
- // Figure out if the hypergeometric formula will be efficient or not,
- // based on where the summit of the series.
- //
- T a = (n + 1) / 2;
- T x = delta * delta * t * t / (2 * (t * t + n));
- T summit = (sqrt(x * (4 * a + x)) + x) / 2;
- if (summit < 40)
- return non_central_t_pdf_hypergeometric(t, n, delta, pol);
- //
- // Otherwise, for t < 0 we have to use the reflection formula:
- //
- if (t < 0)
- {
- t = -t;
- delta = -delta;
- }
- //
- // x and y are the corresponding random
- // variables for the noncentral beta distribution,
- // with y = 1 - x:
- //
- x = t * t / (n + t * t);
- T y = n / (n + t * t);
- a = 0.5f;
- T b = n / 2;
- T d2 = delta * delta;
- //
- // Calculate pdf:
- //
- T dt = n * t / (n * n + 2 * n * t * t + t * t * t * t);
- BOOST_MATH_INSTRUMENT_VARIABLE(dt);
- T result = non_central_beta_pdf(a, b, d2, x, y, pol);
- BOOST_MATH_INSTRUMENT_VARIABLE(result);
- T tol = tools::root_epsilon<T>() * result;
- result = non_central_t2_pdf(n, delta, x, y, pol, result);
- BOOST_MATH_INSTRUMENT_VARIABLE(result);
- result *= dt;
- if (result <= tol)
- {
- // More than half the digits in the result have cancelled,
- // Try direct integration... super slow but reliable as far as we can tell...
- if (delta < 0)
- {
- // reflect back:
- delta = -delta;
- t = -t;
- }
- result = non_central_t_pdf_integral(t, n, delta, pol);
- }
- return result;
- }
- template <class T, class Policy>
- T mean(T v, T delta, const Policy& pol)
- {
- if ((boost::math::isinf)(v))
- {
- return delta;
- }
- BOOST_MATH_STD_USING
- if (v > 1 / boost::math::tools::epsilon<T>() )
- {
- //normal_distribution<T, Policy> n(delta, 1);
- //return boost::math::mean(n);
- return delta;
- }
- else
- {
- return delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f), pol);
- }
- // Other moments use mean so using normal distribution is propagated.
- }
- template <class T, class Policy>
- T variance(T v, T delta, const Policy& pol)
- {
- if ((boost::math::isinf)(v))
- {
- return 1;
- }
- if (delta == 0)
- { // == Student's t
- return v / (v - 2);
- }
- T result = ((delta * delta + 1) * v) / (v - 2);
- T m = mean(v, delta, pol);
- result -= m * m;
- return result;
- }
- template <class T, class Policy>
- T skewness(T v, T delta, const Policy& pol)
- {
- BOOST_MATH_STD_USING
- if ((boost::math::isinf)(v))
- {
- return 0;
- }
- if(delta == 0)
- { // == Student's t
- return 0;
- }
- T mean = boost::math::detail::mean(v, delta, pol);
- T l2 = delta * delta;
- T var = ((l2 + 1) * v) / (v - 2) - mean * mean;
- T result = -2 * var;
- result += v * (l2 + 2 * v - 3) / ((v - 3) * (v - 2));
- result *= mean;
- result /= pow(var, T(1.5f));
- return result;
- }
- template <class T, class Policy>
- T kurtosis_excess(T v, T delta, const Policy& pol)
- {
- BOOST_MATH_STD_USING
- if ((boost::math::isinf)(v))
- {
- return 1;
- }
- if (delta == 0)
- { // == Student's t
- return 1;
- }
- T mean = boost::math::detail::mean(v, delta, pol);
- T l2 = delta * delta;
- T var = ((l2 + 1) * v) / (v - 2) - mean * mean;
- T result = -3 * var;
- result += v * (l2 * (v + 1) + 3 * (3 * v - 5)) / ((v - 3) * (v - 2));
- result *= -mean * mean;
- result += v * v * (l2 * l2 + 6 * l2 + 3) / ((v - 4) * (v - 2));
- result /= var * var;
- result -= static_cast<T>(3);
- return result;
- }
- #if 0
- //
- // This code is disabled, since there can be multiple answers to the
- // question, and it's not clear how to find the "right" one.
- //
- template <class RealType, class Policy>
- struct t_degrees_of_freedom_finder
- {
- t_degrees_of_freedom_finder(
- RealType delta_, RealType x_, RealType p_, bool c)
- : delta(delta_), x(x_), p(p_), comp(c) {}
- RealType operator()(const RealType& v)
- {
- non_central_t_distribution<RealType, Policy> d(v, delta);
- return comp ?
- p - cdf(complement(d, x))
- : cdf(d, x) - p;
- }
- private:
- RealType delta;
- RealType x;
- RealType p;
- bool comp;
- };
- template <class RealType, class Policy>
- inline RealType find_t_degrees_of_freedom(
- RealType delta, RealType x, RealType p, RealType q, const Policy& pol)
- {
- const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
- if((p == 0) || (q == 0))
- {
- //
- // Can't a thing if one of p and q is zero:
- //
- 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%", // LCOV_EXCL_LINE
- RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy()); // LCOV_EXCL_LINE
- }
- t_degrees_of_freedom_finder<RealType, Policy> f(delta, x, p < q ? p : q, p < q ? false : true);
- tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
- std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
- //
- // Pick an initial guess:
- //
- RealType guess = 200;
- std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
- f, guess, RealType(2), false, tol, max_iter, pol);
- RealType result = ir.first + (ir.second - ir.first) / 2;
- if(max_iter >= policies::get_max_root_iterations<Policy>())
- {
- return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:" // LCOV_EXCL_LINE
- " or there is no answer to problem. Current best guess is %1%", result, Policy()); // LCOV_EXCL_LINE
- }
- return result;
- }
- template <class RealType, class Policy>
- struct t_non_centrality_finder
- {
- t_non_centrality_finder(
- RealType v_, RealType x_, RealType p_, bool c)
- : v(v_), x(x_), p(p_), comp(c) {}
- RealType operator()(const RealType& delta)
- {
- non_central_t_distribution<RealType, Policy> d(v, delta);
- return comp ?
- p - cdf(complement(d, x))
- : cdf(d, x) - p;
- }
- private:
- RealType v;
- RealType x;
- RealType p;
- bool comp;
- };
- template <class RealType, class Policy>
- inline RealType find_t_non_centrality(
- RealType v, RealType x, RealType p, RealType q, const Policy& pol)
- {
- const char* function = "non_central_t<%1%>::find_t_non_centrality";
- if((p == 0) || (q == 0))
- {
- //
- // Can't do a thing if one of p and q is zero:
- //
- 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%", // LCOV_EXCL_LINE
- RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy()); // LCOV_EXCL_LINE
- }
- t_non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
- tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
- std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
- //
- // Pick an initial guess that we know is the right side of
- // zero:
- //
- RealType guess;
- if(f(0) < 0)
- guess = 1;
- else
- guess = -1;
- std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
- f, guess, RealType(2), false, tol, max_iter, pol);
- RealType result = ir.first + (ir.second - ir.first) / 2;
- if(max_iter >= policies::get_max_root_iterations<Policy>())
- {
- return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:" // LCOV_EXCL_LINE
- " or there is no answer to problem. Current best guess is %1%", result, Policy()); // LCOV_EXCL_LINE
- }
- return result;
- }
- #endif
- } // namespace detail ======================================================================
- template <class RealType = double, class Policy = policies::policy<> >
- class non_central_t_distribution
- {
- public:
- typedef RealType value_type;
- typedef Policy policy_type;
- non_central_t_distribution(RealType v_, RealType lambda) : v(v_), ncp(lambda)
- {
- const char* function = "boost::math::non_central_t_distribution<%1%>::non_central_t_distribution(%1%,%1%)";
- RealType r;
- detail::check_df_gt0_to_inf(
- function,
- v, &r, Policy());
- detail::check_non_centrality(
- function,
- static_cast<value_type>(lambda * lambda),
- &r,
- Policy());
- } // non_central_t_distribution constructor.
- RealType degrees_of_freedom() const
- { // Private data getter function.
- return v;
- }
- RealType non_centrality() const
- { // Private data getter function.
- return ncp;
- }
- #if 0
- //
- // This code is disabled, since there can be multiple answers to the
- // question, and it's not clear how to find the "right" one.
- //
- static RealType find_degrees_of_freedom(RealType delta, RealType x, RealType p)
- {
- const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- value_type result = detail::find_t_degrees_of_freedom(
- static_cast<value_type>(delta),
- static_cast<value_type>(x),
- static_cast<value_type>(p),
- static_cast<value_type>(1-p),
- forwarding_policy());
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- result,
- function);
- }
- template <class A, class B, class C>
- static RealType find_degrees_of_freedom(const complemented3_type<A,B,C>& c)
- {
- const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- value_type result = detail::find_t_degrees_of_freedom(
- static_cast<value_type>(c.dist),
- static_cast<value_type>(c.param1),
- static_cast<value_type>(1-c.param2),
- static_cast<value_type>(c.param2),
- forwarding_policy());
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- result,
- function);
- }
- static RealType find_non_centrality(RealType v, RealType x, RealType p)
- {
- const char* function = "non_central_t<%1%>::find_t_non_centrality";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- value_type result = detail::find_t_non_centrality(
- static_cast<value_type>(v),
- static_cast<value_type>(x),
- static_cast<value_type>(p),
- static_cast<value_type>(1-p),
- forwarding_policy());
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- result,
- function);
- }
- template <class A, class B, class C>
- static RealType find_non_centrality(const complemented3_type<A,B,C>& c)
- {
- const char* function = "non_central_t<%1%>::find_t_non_centrality";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- value_type result = detail::find_t_non_centrality(
- static_cast<value_type>(c.dist),
- static_cast<value_type>(c.param1),
- static_cast<value_type>(1-c.param2),
- static_cast<value_type>(c.param2),
- forwarding_policy());
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- result,
- function);
- }
- #endif
- private:
- // Data member, initialized by constructor.
- RealType v; // degrees of freedom
- RealType ncp; // non-centrality parameter
- }; // template <class RealType, class Policy> class non_central_t_distribution
- typedef non_central_t_distribution<double> non_central_t; // Reserved name of type double.
- #ifdef __cpp_deduction_guides
- template <class RealType>
- non_central_t_distribution(RealType,RealType)->non_central_t_distribution<typename boost::math::tools::promote_args<RealType>::type>;
- #endif
- // Non-member functions to give properties of the distribution.
- template <class RealType, class Policy>
- inline const std::pair<RealType, RealType> range(const non_central_t_distribution<RealType, Policy>& /* dist */)
- { // Range of permissible values for random variable k.
- using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
- }
- template <class RealType, class Policy>
- inline const std::pair<RealType, RealType> support(const non_central_t_distribution<RealType, Policy>& /* dist */)
- { // Range of supported values for random variable k.
- // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
- using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
- }
- template <class RealType, class Policy>
- inline RealType mode(const non_central_t_distribution<RealType, Policy>& dist)
- { // mode.
- static const char* function = "mode(non_central_t_distribution<%1%> const&)";
- RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df_gt0_to_inf(
- function,
- v, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- static_cast<RealType>(l * l),
- &r,
- Policy()))
- return static_cast<RealType>(r);
- BOOST_MATH_STD_USING
- RealType m = v < 3 ? 0 : detail::mean(v, l, Policy());
- RealType var = v < 4 ? 1 : detail::variance(v, l, Policy());
- return detail::generic_find_mode(
- dist,
- m,
- function,
- sqrt(var));
- }
- template <class RealType, class Policy>
- inline RealType mean(const non_central_t_distribution<RealType, Policy>& dist)
- {
- BOOST_MATH_STD_USING
- const char* function = "mean(const non_central_t_distribution<%1%>&)";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df_gt0_to_inf(
- function,
- v, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- static_cast<RealType>(l * l),
- &r,
- Policy()))
- return static_cast<RealType>(r);
- if(v <= 1)
- return policies::raise_domain_error<RealType>(
- function,
- "The non-central t distribution has no defined mean for degrees of freedom <= 1: got v=%1%.", v, Policy());
- // return l * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, RealType(0.5f));
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- detail::mean(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
- } // mean
- template <class RealType, class Policy>
- inline RealType variance(const non_central_t_distribution<RealType, Policy>& dist)
- { // variance.
- const char* function = "variance(const non_central_t_distribution<%1%>&)";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- BOOST_MATH_STD_USING
- RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df_gt0_to_inf(
- function,
- v, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- static_cast<RealType>(l * l),
- &r,
- Policy()))
- return static_cast<RealType>(r);
- if(v <= 2)
- return policies::raise_domain_error<RealType>(
- function,
- "The non-central t distribution has no defined variance for degrees of freedom <= 2: got v=%1%.", v, Policy());
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- detail::variance(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
- }
- // RealType standard_deviation(const non_central_t_distribution<RealType, Policy>& dist)
- // standard_deviation provided by derived accessors.
- template <class RealType, class Policy>
- inline RealType skewness(const non_central_t_distribution<RealType, Policy>& dist)
- { // skewness = sqrt(l).
- const char* function = "skewness(const non_central_t_distribution<%1%>&)";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df_gt0_to_inf(
- function,
- v, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- static_cast<RealType>(l * l),
- &r,
- Policy()))
- return static_cast<RealType>(r);
- if(v <= 3)
- return policies::raise_domain_error<RealType>(
- function,
- "The non-central t distribution has no defined skewness for degrees of freedom <= 3: got v=%1%.", v, Policy());;
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- detail::skewness(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
- }
- template <class RealType, class Policy>
- inline RealType kurtosis_excess(const non_central_t_distribution<RealType, Policy>& dist)
- {
- const char* function = "kurtosis_excess(const non_central_t_distribution<%1%>&)";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df_gt0_to_inf(
- function,
- v, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- static_cast<RealType>(l * l),
- &r,
- Policy()))
- return static_cast<RealType>(r);
- if(v <= 4)
- return policies::raise_domain_error<RealType>(
- function,
- "The non-central t distribution has no defined kurtosis for degrees of freedom <= 4: got v=%1%.", v, Policy());;
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- detail::kurtosis_excess(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
- } // kurtosis_excess
- template <class RealType, class Policy>
- inline RealType kurtosis(const non_central_t_distribution<RealType, Policy>& dist)
- {
- return kurtosis_excess(dist) + 3;
- }
- template <class RealType, class Policy>
- inline RealType pdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& t)
- { // Probability Density/Mass Function.
- const char* function = "pdf(non_central_t_distribution<%1%>, %1%)";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df_gt0_to_inf(
- function,
- v, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- static_cast<RealType>(l * l), // we need l^2 to be countable.
- &r,
- Policy())
- ||
- !detail::check_x(
- function,
- t,
- &r,
- Policy()))
- return static_cast<RealType>(r);
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- detail::non_central_t_pdf(static_cast<value_type>(v),
- static_cast<value_type>(l),
- static_cast<value_type>(t),
- Policy()),
- function);
- } // pdf
- template <class RealType, class Policy>
- RealType cdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& x)
- {
- const char* function = "boost::math::cdf(non_central_t_distribution<%1%>&, %1%)";
- // was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df_gt0_to_inf(
- function,
- v, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- static_cast<RealType>(l * l),
- &r,
- Policy())
- ||
- !detail::check_x(
- function,
- x,
- &r,
- Policy()))
- return static_cast<RealType>(r);
- if ((boost::math::isinf)(v))
- { // Infinite degrees of freedom, so use normal distribution located at delta.
- normal_distribution<RealType, Policy> n(l, 1);
- cdf(n, x);
- //return cdf(normal_distribution<RealType, Policy>(l, 1), x);
- }
- if(l == 0)
- { // NO non-centrality, so use Student's t instead.
- return cdf(students_t_distribution<RealType, Policy>(v), x);
- }
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- detail::non_central_t_cdf(
- static_cast<value_type>(v),
- static_cast<value_type>(l),
- static_cast<value_type>(x),
- false, Policy()),
- function);
- } // cdf
- template <class RealType, class Policy>
- RealType cdf(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
- { // Complemented Cumulative Distribution Function
- // was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
- const char* function = "boost::math::cdf(const complement(non_central_t_distribution<%1%>&), %1%)";
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- non_central_t_distribution<RealType, Policy> const& dist = c.dist;
- RealType x = c.param;
- RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality(); // aka delta
- RealType r;
- if(!detail::check_df_gt0_to_inf(
- function,
- v, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- static_cast<RealType>(l * l),
- &r,
- Policy())
- ||
- !detail::check_x(
- function,
- x,
- &r,
- Policy()))
- return static_cast<RealType>(r);
- if ((boost::math::isinf)(v))
- { // Infinite degrees of freedom, so use normal distribution located at delta.
- normal_distribution<RealType, Policy> n(l, 1);
- return cdf(complement(n, x));
- }
- if(l == 0)
- { // zero non-centrality so use Student's t distribution.
- return cdf(complement(students_t_distribution<RealType, Policy>(v), x));
- }
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- detail::non_central_t_cdf(
- static_cast<value_type>(v),
- static_cast<value_type>(l),
- static_cast<value_type>(x),
- true, Policy()),
- function);
- } // ccdf
- template <class RealType, class Policy>
- inline RealType quantile(const non_central_t_distribution<RealType, Policy>& dist, const RealType& p)
- { // Quantile (or Percent Point) function.
- static const char* function = "quantile(const non_central_t_distribution<%1%>, %1%)";
- RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
- return detail::non_central_t_quantile(function, v, l, p, RealType(1-p), Policy());
- } // quantile
- template <class RealType, class Policy>
- inline RealType quantile(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
- { // Quantile (or Percent Point) function.
- static const char* function = "quantile(const complement(non_central_t_distribution<%1%>, %1%))";
- non_central_t_distribution<RealType, Policy> const& dist = c.dist;
- RealType q = c.param;
- RealType v = dist.degrees_of_freedom();
- RealType l = dist.non_centrality();
- return detail::non_central_t_quantile(function, v, l, RealType(1-q), q, Policy());
- } // quantile complement.
- } // namespace math
- } // namespace boost
- // This include must be at the end, *after* the accessors
- // for this distribution have been defined, in order to
- // keep compilers that support two-phase lookup happy.
- #include <boost/math/distributions/detail/derived_accessors.hpp>
- #endif // BOOST_MATH_SPECIAL_NON_CENTRAL_T_HPP
|