beta.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,357 行 · 第 1/3 页
HPP
1,357 行
fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol); } } else { std::swap(a, b); std::swap(x, y); invert = !invert; if(y >= 0.3) { if(!invert) fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol); else { fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol); } } else { // Sidestep on a, and then use the series representation: T prefix; if(!normalised) { prefix = rising_factorial_ratio(a+b, a, 20); } else { prefix = 1; } fract = ibeta_a_step(a, b, x, y, 20, pol, normalised, p_derivative); if(!invert) fract = beta_small_b_large_a_series(a + 20, b, x, y, fract, prefix, pol, normalised); else { fract -= (normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; fract = -beta_small_b_large_a_series(a + 20, b, x, y, fract, prefix, pol, normalised); } } } } else { // One of a, b < 1 only: if((b <= 1) || ((x < 0.1) && (pow(b * x, a) <= 0.7))) { if(!invert) fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol); else { fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol); } } else { std::swap(a, b); std::swap(x, y); invert = !invert; if(y >= 0.3) { if(!invert) fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol); else { fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol); } } else if(a >= 15) { if(!invert) fract = beta_small_b_large_a_series(a, b, x, y, T(0), T(1), pol, normalised); else { fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; fract = -beta_small_b_large_a_series(a, b, x, y, fract, T(1), pol, normalised); } } else { // Sidestep to improve errors: T prefix; if(!normalised) { prefix = rising_factorial_ratio(a+b, a, 20); } else { prefix = 1; } fract = ibeta_a_step(a, b, x, y, 20, pol, normalised, p_derivative); if(!invert) fract = beta_small_b_large_a_series(a + 20, b, x, y, fract, prefix, pol, normalised); else { fract -= (normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; fract = -beta_small_b_large_a_series(a + 20, b, x, y, fract, prefix, pol, normalised); } } } } } else { // Both a,b >= 1: T lambda; if(a < b) { lambda = a - (a + b) * x; } else { lambda = (a + b) * y - b; } if(lambda < 0) { std::swap(a, b); std::swap(x, y); invert = !invert; } if(b < 40) { if((floor(a) == a) && (floor(b) == b)) { // relate to the binomial distribution and use a finite sum: T k = a - 1; T n = b + k; fract = binomial_ccdf(n, k, x, y); if(!normalised) fract *= boost::math::beta(a, b, pol); } else if(b * x <= 0.7) { if(!invert) fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol); else { fract = -(normalised ? 1 : boost::math::beta(a, b, pol)); invert = false; fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol); } } else if(a > 15) { // sidestep so we can use the series representation: int n = itrunc(floor(b), pol); if(n == b) --n; T bbar = b - n; T prefix; if(!normalised) { prefix = rising_factorial_ratio(a+bbar, bbar, n); } else { prefix = 1; } fract = ibeta_a_step(bbar, a, y, x, n, pol, normalised, static_cast<T*>(0)); fract = beta_small_b_large_a_series(a, bbar, x, y, fract, T(1), pol, normalised); fract /= prefix; } else if(normalised) { // the formula here for the non-normalised case is tricky to figure // out (for me!!), and requires two pochhammer calculations rather // than one, so leave it for now.... int n = itrunc(floor(b), pol); T bbar = b - n; if(bbar <= 0) { --n; bbar += 1; } fract = ibeta_a_step(bbar, a, y, x, n, pol, normalised, static_cast<T*>(0)); fract += ibeta_a_step(a, bbar, x, y, 20, pol, normalised, static_cast<T*>(0)); if(invert) fract -= (normalised ? 1 : boost::math::beta(a, b, pol)); //fract = ibeta_series(a+20, bbar, x, fract, l, normalised, p_derivative, y); fract = beta_small_b_large_a_series(a+20, bbar, x, y, fract, T(1), pol, normalised); if(invert) { fract = -fract; invert = false; } } else fract = ibeta_fraction2(a, b, x, y, pol, normalised, p_derivative); } else fract = ibeta_fraction2(a, b, x, y, pol, normalised, p_derivative); } if(p_derivative) { if(*p_derivative < 0) { *p_derivative = ibeta_power_terms(a, b, x, y, lanczos_type(), true, pol); } T div = y * x; if(*p_derivative != 0) { if((tools::max_value<T>() * div < *p_derivative)) { // overflow, return an arbitarily large value: *p_derivative = tools::max_value<T>() / 2; } else { *p_derivative /= div; } } } return invert ? (normalised ? 1 : boost::math::beta(a, b, pol)) - fract : fract;} // template <class T, class L>T ibeta_imp(T a, T b, T x, const L& l, bool inv, bool normalised)template <class T, class Policy>inline T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, bool normalised){ return ibeta_imp(a, b, x, pol, inv, normalised, static_cast<T*>(0));}template <class T, class Policy>T ibeta_derivative_imp(T a, T b, T x, const Policy& pol){ static const char* function = "ibeta_derivative<%1%>(%1%,%1%,%1%)"; // // start with the usual error checks: // if(a <= 0) policies::raise_domain_error<T>(function, "The argument a to the incomplete beta function must be greater than zero (got a=%1%).", a, pol); if(b <= 0) policies::raise_domain_error<T>(function, "The argument b to the incomplete beta function must be greater than zero (got b=%1%).", b, pol); if((x < 0) || (x > 1)) policies::raise_domain_error<T>(function, "Parameter x outside the range [0,1] in the incomplete beta function (got x=%1%).", x, pol); // // Now the corner cases: // if(x == 0) { return (a > 1) ? 0 : (a == 1) ? 1 / boost::math::beta(a, b, pol) : policies::raise_overflow_error<T>(function, 0, pol); } else if(x == 1) { return (b > 1) ? 0 : (b == 1) ? 1 / boost::math::beta(a, b, pol) : policies::raise_overflow_error<T>(function, 0, pol); } // // Now the regular cases: // typedef typename lanczos::lanczos<T, Policy>::type lanczos_type; T f1 = ibeta_power_terms(a, b, x, 1 - x, lanczos_type(), true, pol); T y = (1 - x) * x; if(f1 == 0) return 0; if((tools::max_value<T>() * y < f1)) { // overflow: return policies::raise_overflow_error<T>(function, 0, pol); } f1 /= y; return f1;}//// Some forwarding functions that dis-ambiguate the third argument type://template <class RT1, class RT2, class Policy>inline typename tools::promote_args<RT1, RT2>::type beta(RT1 a, RT2 b, const Policy&, const mpl::true_*){ BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args<RT1, RT2>::type result_type; typedef typename policies::evaluation<result_type, Policy>::type value_type; typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type; typedef typename policies::normalise< Policy, policies::promote_float<false>, policies::promote_double<false>, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::beta_imp(static_cast<value_type>(a), static_cast<value_type>(b), evaluation_type(), forwarding_policy()), "boost::math::beta<%1%>(%1%,%1%)");}template <class RT1, class RT2, class RT3>inline typename tools::promote_args<RT1, RT2, RT3>::type beta(RT1 a, RT2 b, RT3 x, const mpl::false_*){ return boost::math::beta(a, b, x, policies::policy<>());}} // namespace detail//// The actual function entry-points now follow, these just figure out// which Lanczos approximation to use// and forward to the implementation functions://template <class RT1, class RT2, class A>inline typename tools::promote_args<RT1, RT2, A>::type beta(RT1 a, RT2 b, A arg){ typedef typename policies::is_policy<A>::type tag; return boost::math::detail::beta(a, b, arg, static_cast<tag*>(0));}template <class RT1, class RT2>inline typename tools::promote_args<RT1, RT2>::type beta(RT1 a, RT2 b){ return boost::math::beta(a, b, policies::policy<>());}template <class RT1, class RT2, class RT3, class Policy>inline typename tools::promote_args<RT1, RT2, RT3>::type beta(RT1 a, RT2 b, RT3 x, const Policy&){ BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; typedef typename policies::evaluation<result_type, Policy>::type value_type; typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type; typedef typename policies::normalise< Policy, policies::promote_float<false>, policies::promote_double<false>, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::ibeta_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(x), forwarding_policy(), false, false), "boost::math::beta<%1%>(%1%,%1%,%1%)");}template <class RT1, class RT2, class RT3, class Policy>inline typename tools::promote_args<RT1, RT2, RT3>::type betac(RT1 a, RT2 b, RT3 x, const Policy&){ BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; typedef typename policies::evaluation<result_type, Policy>::type value_type; typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type; typedef typename policies::normalise< Policy, policies::promote_float<false>, policies::promote_double<false>, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::ibeta_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(x), forwarding_policy(), true, false), "boost::math::betac<%1%>(%1%,%1%,%1%)");}template <class RT1, class RT2, class RT3>inline typename tools::promote_args<RT1, RT2, RT3>::type betac(RT1 a, RT2 b, RT3 x){ return boost::math::betac(a, b, x, policies::policy<>());}template <class RT1, class RT2, class RT3, class Policy>inline typename tools::promote_args<RT1, RT2, RT3>::type ibeta(RT1 a, RT2 b, RT3 x, const Policy&){ BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; typedef typename policies::evaluation<result_type, 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; return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::ibeta_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(x), forwarding_policy(), false, true), "boost::math::ibeta<%1%>(%1%,%1%,%1%)");}template <class RT1, class RT2, class RT3>inline typename tools::promote_args<RT1, RT2, RT3>::type ibeta(RT1 a, RT2 b, RT3 x){ return boost::math::ibeta(a, b, x, policies::policy<>());}template <class RT1, class RT2, class RT3, class Policy>inline typename tools::promote_args<RT1, RT2, RT3>::type ibetac(RT1 a, RT2 b, RT3 x, const Policy&){ BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; typedef typename policies::evaluation<result_type, 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; return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::ibeta_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(x), forwarding_policy(), true, true), "boost::math::ibetac<%1%>(%1%,%1%,%1%)");}template <class RT1, class RT2, class RT3>inline typename tools::promote_args<RT1, RT2, RT3>::type ibetac(RT1 a, RT2 b, RT3 x){ return boost::math::ibetac(a, b, x, policies::policy<>());}template <class RT1, class RT2, class RT3, class Policy>inline typename tools::promote_args<RT1, RT2, RT3>::type ibeta_derivative(RT1 a, RT2 b, RT3 x, const Policy&){ BOOST_FPU_EXCEPTION_GUARD typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type; typedef typename policies::evaluation<result_type, 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; return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::ibeta_derivative_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(x), forwarding_policy()), "boost::math::ibeta_derivative<%1%>(%1%,%1%,%1%)");}template <class RT1, class RT2, class RT3>inline typename tools::promote_args<RT1, RT2, RT3>::type ibeta_derivative(RT1 a, RT2 b, RT3 x){ return boost::math::ibeta_derivative(a, b, x, policies::policy<>());}} // namespace math} // namespace boost#include <boost/math/special_functions/detail/ibeta_inverse.hpp>#include <boost/math/special_functions/detail/ibeta_inv_ab.hpp>#endif // BOOST_MATH_SPECIAL_BETA_HPP
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?