non_central_beta.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 846 行 · 第 1/3 页
HPP
846 行
// boost\math\distributions\non_central_beta.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_BETA_HPP#define BOOST_MATH_SPECIAL_NON_CENTRAL_BETA_HPP#include <boost/math/distributions/fwd.hpp>#include <boost/math/special_functions/beta.hpp> // for incomplete gamma. gamma_q#include <boost/math/distributions/complement.hpp> // complements#include <boost/math/distributions/beta.hpp> // central distribution#include <boost/math/distributions/detail/generic_mode.hpp>#include <boost/math/distributions/detail/common_error_handling.hpp> // error checks#include <boost/math/special_functions/fpclassify.hpp> // isnan.#include <boost/math/tools/roots.hpp> // for root finding.namespace boost{ namespace math { template <class RealType, class Policy> class non_central_beta_distribution; namespace detail{ template <class T, class Policy> T non_central_beta_p(T a, T b, T lam, T x, T y, const Policy& pol, T init_val = 0) { 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); if(k == 0) k = 1; // Starting Poisson weight: T pois = gamma_p_derivative(T(k+1), l2, pol); if(pois == 0) return init_val; // Starting beta term: T beta = x < y ? ibeta(a + k, b, x, pol) : ibetac(b, a + k, y, pol); // recurance term: T xterm = x < y ? ibeta_derivative(a + k, b, x, pol) : ibeta_derivative(b, a + k, y, pol); xterm *= y / (a + b + k - 1); T poisf(pois), betaf(beta), xtermf(xterm); T sum = init_val; if((beta == 0) && (xterm == 0)) return init_val; // // Backwards recursion first, this is the stable // direction for recursion: // T last_term = 0; boost::uintmax_t count = k; for(int i = k; i >= 0; --i) { T term = beta * pois; sum += term; if(((fabs(term/sum) < errtol) && (last_term >= term)) || (term == 0)) { count = k - i; break; } pois *= i / l2; beta += xterm; xterm *= (a + i - 1) / (x * (a + b + i - 2)); last_term = term; } for(int i = k + 1; ; ++i) { poisf *= l2 / i; xtermf *= (x * (a + b + i - 2)) / (a + i - 1); betaf -= xtermf; 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( "cdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); } } return sum; } template <class T, class Policy> T non_central_beta_q(T a, T b, T lam, T x, T y, const Policy& pol, T init_val = 0) { 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); if(k == 0) k = 1; // Starting Poisson weight: T pois = gamma_p_derivative(T(k+1), l2, pol); if(pois == 0) return init_val; // Starting beta term: T beta = x < y ? ibetac(a + k, b, x, pol) : ibeta(b, a + k, y, pol); // recurance term: T xterm = x < y ? ibeta_derivative(a + k, b, x, pol) : ibeta_derivative(b, a + k, y, pol); xterm *= y / (a + b + k - 1); T poisf(pois), betaf(beta), xtermf(xterm); T sum = init_val; if((beta == 0) && (xterm == 0)) return init_val; // // Forwards recursion first, this is the stable // direction for recursion, and the location // of the bulk of the sum: // T last_term = 0; boost::uintmax_t count = 0; for(int i = k + 1; ; ++i) { poisf *= l2 / i; xtermf *= (x * (a + b + i - 2)) / (a + i - 1); betaf += xtermf; T term = poisf * betaf; sum += term; if((fabs(term/sum) < errtol) && (last_term >= term)) { count = i - k; break; } if(static_cast<boost::uintmax_t>(i - k) > max_iter) { return policies::raise_evaluation_error( "cdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); } last_term = term; } for(int i = k; i >= 0; --i) { T term = beta * pois; sum += term; if(fabs(term/sum) < errtol) { break; } if(static_cast<boost::uintmax_t>(count + k - i) > max_iter) { return policies::raise_evaluation_error( "cdf(non_central_beta_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); } pois *= i / l2; beta -= xterm; xterm *= (a + i - 1) / (x * (a + b + i - 2)); } return sum; } template <class RealType, class Policy> inline RealType non_central_beta_cdf(RealType x, RealType y, RealType a, RealType b, RealType l, bool invert, const Policy&) { 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 if(x == 0) return invert ? 1.0f : 0.0f; if(y == 0) return invert ? 0.0f : 1.0f; value_type result; value_type c = a + b + l / 2; value_type cross = 1 - (b / c) * (1 + l / (2 * c * c)); if(l == 0) result = cdf(boost::math::beta_distribution<RealType, Policy>(a, b), x); else if(x > cross) { // Complement is the smaller of the two: result = detail::non_central_beta_q( static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(l), static_cast<value_type>(x), static_cast<value_type>(y), forwarding_policy(), static_cast<value_type>(invert ? 0 : -1)); invert = !invert; } else { result = detail::non_central_beta_p( static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(l), static_cast<value_type>(x), static_cast<value_type>(y), forwarding_policy(), static_cast<value_type>(invert ? -1 : 0)); } if(invert) result = -result; return policies::checked_narrowing_cast<RealType, forwarding_policy>( result, "boost::math::non_central_beta_cdf<%1%>(%1%, %1%, %1%)"); } template <class T, class Policy> struct nc_beta_quantile_functor { nc_beta_quantile_functor(const non_central_beta_distribution<T,Policy>& d, T t, bool c) : dist(d), target(t), comp(c) {} T operator()(const T& x) { return comp ? target - cdf(complement(dist, x)) : cdf(dist, x) - target; } private: non_central_beta_distribution<T,Policy> dist; T target; bool comp; }; // // This is more or less a copy of bracket_and_solve_root, but // modified to search only the interval [0,1] using similar // heuristics. // template <class F, class T, class Tol, class Policy> std::pair<T, T> bracket_and_solve_root_01(F f, const T& guess, T factor, bool rising, Tol tol, boost::uintmax_t& max_iter, const Policy& pol) { BOOST_MATH_STD_USING static const char* function = "boost::math::tools::bracket_and_solve_root_01<%1%>"; // // Set up inital brackets: // T a = guess; T b = a; T fa = f(a);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?