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 + -
显示快捷键?