non_central_beta.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 846 行 · 第 1/3 页
HPP
846 行
T fb = fa; // // Set up invocation count: // boost::uintmax_t count = max_iter - 1; if((fa < 0) == (guess < 0 ? !rising : rising)) { // // Zero is to the right of b, so walk upwards // until we find it: // while((boost::math::sign)(fb) == (boost::math::sign)(fa)) { if(count == 0) { b = policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", b, pol); return std::make_pair(a, b); } // // Heuristic: every 20 iterations we double the growth factor in case the // initial guess was *really* bad ! // if((max_iter - count) % 20 == 0) factor *= 2; // // Now go ahead and move are guess by "factor", // we do this by reducing 1-guess by factor: // a = b; fa = fb; b = 1 - ((1 - b) / factor); fb = f(b); --count; BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count); } } else { // // Zero is to the left of a, so walk downwards // until we find it: // while((boost::math::sign)(fb) == (boost::math::sign)(fa)) { if(fabs(a) < tools::min_value<T>()) { // Escape route just in case the answer is zero! max_iter -= count; max_iter += 1; return a > 0 ? std::make_pair(T(0), T(a)) : std::make_pair(T(a), T(0)); } if(count == 0) { a = policies::raise_evaluation_error(function, "Unable to bracket root, last nearest value was %1%", a, pol); return std::make_pair(a, b); } // // Heuristic: every 20 iterations we double the growth factor in case the // initial guess was *really* bad ! // if((max_iter - count) % 20 == 0) factor *= 2; // // Now go ahead and move are guess by "factor": // b = a; fb = fa; a /= factor; fa = f(a); --count; BOOST_MATH_INSTRUMENT_CODE("a = " << a << " b = " << b << " fa = " << fa << " fb = " << fb << " count = " << count); } } max_iter -= count; max_iter += 1; std::pair<T, T> r = toms748_solve( f, (a < 0 ? b : a), (a < 0 ? a : b), (a < 0 ? fb : fa), (a < 0 ? fa : fb), tol, count, pol); max_iter += count; BOOST_MATH_INSTRUMENT_CODE("max_iter = " << max_iter << " count = " << count); return r; } template <class RealType, class Policy> RealType nc_beta_quantile(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& p, bool comp) { static const char* function = "quantile(non_central_beta_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; value_type a = dist.alpha(); value_type b = dist.beta(); value_type l = dist.non_centrality(); value_type r; if(!beta_detail::check_alpha( function, a, &r, Policy()) || !beta_detail::check_beta( function, b, &r, Policy()) || !detail::check_non_centrality( function, l, &r, Policy()) || !detail::check_probability( function, static_cast<value_type>(p), &r, Policy())) return (RealType)r; // // Special cases first: // if(p == 0) return comp ? 1.0f : 0.0f; if(p == 1) return !comp ? 1.0f : 0.0f; value_type c = a + b + l / 2; value_type mean = 1 - (b / c) * (1 + l / (2 * c * c)); /* // // Calculate a normal approximation to the quantile, // uses mean and variance approximations from: // Algorithm AS 310: // Computing the Non-Central Beta Distribution Function // R. Chattamvelli; R. Shanmugam // Applied Statistics, Vol. 46, No. 1. (1997), pp. 146-156. // // Unfortunately, when this is wrong it tends to be *very* // wrong, so it's disabled for now, even though it often // gets the initial guess quite close. Probably we could // do much better by factoring in the skewness if only // we could calculate it.... // value_type delta = l / 2; value_type delta2 = delta * delta; value_type delta3 = delta * delta2; value_type delta4 = delta2 * delta2; value_type G = c * (c + 1) + delta; value_type alpha = a + b; value_type alpha2 = alpha * alpha; value_type eta = (2 * alpha + 1) * (2 * alpha + 1) + 1; value_type H = 3 * alpha2 + 5 * alpha + 2; value_type F = alpha2 * (alpha + 1) + H * delta + (2 * alpha + 4) * delta2 + delta3; value_type P = (3 * alpha + 1) * (9 * alpha + 17) + 2 * alpha * (3 * alpha + 2) * (3 * alpha + 4) + 15; value_type Q = 54 * alpha2 + 162 * alpha + 130; value_type R = 6 * (6 * alpha + 11); value_type D = delta * (H * H + 2 * P * delta + Q * delta2 + R * delta3 + 9 * delta4); value_type variance = (b / G) * (1 + delta * (l * l + 3 * l + eta) / (G * G)) - (b * b / F) * (1 + D / (F * F)); value_type sd = sqrt(variance); value_type guess = comp ? quantile(complement(normal_distribution<RealType, Policy>(static_cast<RealType>(mean), static_cast<RealType>(sd)), p)) : quantile(normal_distribution<RealType, Policy>(static_cast<RealType>(mean), static_cast<RealType>(sd)), p); if(guess >= 1) guess = mean; if(guess <= tools::min_value<value_type>()) guess = mean; */ value_type guess = mean; detail::nc_beta_quantile_functor<value_type, Policy> f(non_central_beta_distribution<value_type, Policy>(a, b, l), p, comp); tools::eps_tolerance<value_type> tol(policies::digits<RealType, Policy>()); boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>(); std::pair<value_type, value_type> ir = bracket_and_solve_root_01( f, guess, value_type(2.5), true, tol, max_iter, Policy()); value_type 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:" " either there is no answer to quantile of the non central beta distribution" " or the answer is infinite. Current best guess is %1%", policies::checked_narrowing_cast<RealType, forwarding_policy>( result, function), Policy()); } return policies::checked_narrowing_cast<RealType, forwarding_policy>( result, function); } template <class T, class Policy> T non_central_beta_pdf(T a, T b, T lam, T x, T y, const Policy& pol) { BOOST_MATH_STD_USING using namespace boost::math; // // Variables come first: // boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); T errtol = ldexp(1.0f, -boost::math::policies::digits<T, Policy>()); T l2 = lam / 2; // // k is the starting point for iteration, and is the // maximum of the poisson weighting term: // int k = itrunc(l2); // Starting Poisson weight: T pois = gamma_p_derivative(T(k+1), l2, pol); // Starting beta term: T beta = x < y ? ibeta_derivative(a + k, b, x, pol) : ibeta_derivative(b, a + k, y, pol); T sum = 0; T poisf(pois); T betaf(beta); // // Stable backwards recursion first: // boost::uintmax_t count = k; for(int i = k; i >= 0; --i) { T term = beta * pois; sum += term; if((fabs(term/sum) < errtol) || (term == 0)) { count = k - i; break; } pois *= i / l2; beta *= (a + i - 1) / (x * (a + i + b - 1)); } for(int i = k + 1; ; ++i) { poisf *= l2 / i; betaf *= x * (a + b + i - 1) / (a + i - 1); T term = poisf * betaf; sum += term; if((fabs(term/sum) < errtol) || (term == 0)) { break; } if(static_cast<boost::uintmax_t>(count + i - k) > max_iter) { return policies::raise_evaluation_error( "pdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); } } return sum; } template <class RealType, class Policy> RealType nc_beta_pdf(const non_central_beta_distribution<RealType, Policy>& dist, const RealType& x) { BOOST_MATH_STD_USING static const char* function = "pdf(non_central_beta_distribution<%1%>, %1%)"; typedef typename policies::evaluation<RealType, Policy>::type value_type; typedef typename policies::normalise<
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?