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