Boost-Geometry-Utils
view release on metacpan or search on metacpan
src/boost/math/special_functions/detail/igamma_inverse.hpp view on Meta::CPAN
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
BOOST_MATH_STD_USING // For ADL of std functions.
T f, f1;
value_type ft;
f = static_cast<T>(boost::math::detail::gamma_incomplete_imp(
static_cast<value_type>(a),
static_cast<value_type>(x),
true, invert,
forwarding_policy(), &ft));
f1 = static_cast<T>(ft);
T f2;
T div = (a - x - 1) / x;
f2 = f1;
if((fabs(div) > 1) && (tools::max_value<T>() / fabs(div) < f2))
{
// overflow:
f2 = -tools::max_value<T>() / 2;
}
else
{
f2 *= div;
}
if(invert)
{
f1 = -f1;
f2 = -f2;
}
return boost::math::make_tuple(static_cast<T>(f - p), f1, f2);
}
private:
T a, p;
bool invert;
};
template <class T, class Policy>
T gamma_p_inv_imp(T a, T p, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std functions.
static const char* function = "boost::math::gamma_p_inv<%1%>(%1%, %1%)";
BOOST_MATH_INSTRUMENT_VARIABLE(a);
BOOST_MATH_INSTRUMENT_VARIABLE(p);
if(a <= 0)
policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol);
if((p < 0) || (p > 1))
policies::raise_domain_error<T>(function, "Probabilty must be in the range [0,1] in the incomplete gamma function inverse (got p=%1%).", p, pol);
if(p == 1)
return tools::max_value<T>();
if(p == 0)
return 0;
bool has_10_digits;
T guess = detail::find_inverse_gamma<T>(a, p, 1 - p, pol, &has_10_digits);
if((policies::digits<T, Policy>() <= 36) && has_10_digits)
return guess;
T lower = tools::min_value<T>();
if(guess <= lower)
guess = tools::min_value<T>();
BOOST_MATH_INSTRUMENT_VARIABLE(guess);
//
// Work out how many digits to converge to, normally this is
// 2/3 of the digits in T, but if the first derivative is very
// large convergence is slow, so we'll bump it up to full
// precision to prevent premature termination of the root-finding routine.
//
unsigned digits = policies::digits<T, Policy>();
if(digits < 30)
{
digits *= 2;
digits /= 3;
}
else
{
digits /= 2;
digits -= 1;
}
if((a < 0.125) && (fabs(gamma_p_derivative(a, guess, pol)) > 1 / sqrt(tools::epsilon<T>())))
digits = policies::digits<T, Policy>() - 2;
//
// Go ahead and iterate:
//
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
guess = tools::halley_iterate(
detail::gamma_p_inverse_func<T, Policy>(a, p, false),
guess,
lower,
tools::max_value<T>(),
digits,
max_iter);
policies::check_root_iterations<T>(function, max_iter, pol);
BOOST_MATH_INSTRUMENT_VARIABLE(guess);
if(guess == lower)
guess = policies::raise_underflow_error<T>(function, "Expected result known to be non-zero, but is smaller than the smallest available number.", pol);
return guess;
}
template <class T, class Policy>
T gamma_q_inv_imp(T a, T q, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std functions.
static const char* function = "boost::math::gamma_q_inv<%1%>(%1%, %1%)";
if(a <= 0)
policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol);
if((q < 0) || (q > 1))
policies::raise_domain_error<T>(function, "Probabilty must be in the range [0,1] in the incomplete gamma function inverse (got q=%1%).", q, pol);
if(q == 0)
return tools::max_value<T>();
if(q == 1)
return 0;
bool has_10_digits;
T guess = detail::find_inverse_gamma<T>(a, 1 - q, q, pol, &has_10_digits);
if((policies::digits<T, Policy>() <= 36) && has_10_digits)
return guess;
T lower = tools::min_value<T>();
if(guess <= lower)
guess = tools::min_value<T>();
//
// Work out how many digits to converge to, normally this is
// 2/3 of the digits in T, but if the first derivative is very
// large convergence is slow, so we'll bump it up to full
// precision to prevent premature termination of the root-finding routine.
//
unsigned digits = policies::digits<T, Policy>();
if(digits < 30)
{
digits *= 2;
digits /= 3;
}
else
{
digits /= 2;
digits -= 1;
}
if((a < 0.125) && (fabs(gamma_p_derivative(a, guess, pol)) > 1 / sqrt(tools::epsilon<T>())))
digits = policies::digits<T, Policy>();
//
// Go ahead and iterate:
//
boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
guess = tools::halley_iterate(
detail::gamma_p_inverse_func<T, Policy>(a, q, true),
guess,
lower,
tools::max_value<T>(),
digits,
max_iter);
policies::check_root_iterations<T>(function, max_iter, pol);
if(guess == lower)
guess = policies::raise_underflow_error<T>(function, "Expected result known to be non-zero, but is smaller than the smallest available number.", pol);
return guess;
}
} // namespace detail
template <class T1, class T2, class Policy>
inline typename tools::promote_args<T1, T2>::type
gamma_p_inv(T1 a, T2 p, const Policy& pol)
{
typedef typename tools::promote_args<T1, T2>::type result_type;
return detail::gamma_p_inv_imp(
static_cast<result_type>(a),
static_cast<result_type>(p), pol);
}
template <class T1, class T2, class Policy>
inline typename tools::promote_args<T1, T2>::type
gamma_q_inv(T1 a, T2 p, const Policy& pol)
{
typedef typename tools::promote_args<T1, T2>::type result_type;
return detail::gamma_q_inv_imp(
static_cast<result_type>(a),
static_cast<result_type>(p), pol);
}
template <class T1, class T2>
inline typename tools::promote_args<T1, T2>::type
gamma_p_inv(T1 a, T2 p)
{
return gamma_p_inv(a, p, policies::policy<>());
}
template <class T1, class T2>
inline typename tools::promote_args<T1, T2>::type
gamma_q_inv(T1 a, T2 p)
{
return gamma_q_inv(a, p, policies::policy<>());
}
} // namespace math
} // namespace boost
#endif // BOOST_MATH_SPECIAL_FUNCTIONS_IGAMMA_INVERSE_HPP
( run in 1.002 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )