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