mirror of
https://github.com/boostorg/math.git
synced 2026-02-24 16:12:15 +00:00
Merge pull request #1349 from JacobHass8/log-lower-incomplete-gamma
Implementation of the log of the lower incomplete gamma function
This commit is contained in:
@@ -1290,7 +1290,6 @@ BOOST_MATH_GPU_ENABLED T incomplete_tgamma_large_x(const T& a, const T& x, const
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Main incomplete gamma entry point, handles all four incomplete gamma's:
|
||||
//
|
||||
@@ -1813,6 +1812,46 @@ BOOST_MATH_GPU_ENABLED T lgamma_incomplete_imp(T a, T x, const Policy& pol)
|
||||
return log(gamma_q(a, x, pol));
|
||||
}
|
||||
|
||||
// Calculate log of incomplete gamma function
|
||||
template <class T, class Policy>
|
||||
BOOST_MATH_GPU_ENABLED T lgamma_incomplete_lower_imp(T a, T x, const Policy& pol)
|
||||
{
|
||||
using namespace boost::math; // temporary until we're in the right namespace
|
||||
|
||||
BOOST_MATH_STD_USING_CORE
|
||||
|
||||
// Check for invalid inputs (a < 0 or x < 0)
|
||||
constexpr auto function = "boost::math::lgamma_p<%1%>(%1%, %1%)";
|
||||
if(a <= 0)
|
||||
return policies::raise_domain_error<T>(function, "Argument a to the incomplete gamma function must be greater than zero (got a=%1%).", a, pol);
|
||||
if(x < 0)
|
||||
return policies::raise_domain_error<T>(function, "Argument x to the incomplete gamma function must be >= 0 (got x=%1%).", x, pol);
|
||||
|
||||
// Taken from conditions on Line 1709. There are also
|
||||
// conditions on Line 1368, but didn't implement that one here.
|
||||
// The second condition ensures floats do not return -inf for small
|
||||
// values of x.
|
||||
if (((a > 4 * x) && (a >= max_factorial<T>::value)) || ((T(-0.4) / log(x) < a) && (x < T(1.0)))){
|
||||
return log(detail::lower_gamma_series(a, x, pol)) - log(a) + a * log(x) - x - lgamma(a, pol);
|
||||
}
|
||||
|
||||
//
|
||||
// Can't do better than taking the log of P, but...
|
||||
//
|
||||
// Figure out whether we need P or Q, since if we calculate P and it's too close to unity
|
||||
// we will lose precision in the result, selection logic here is extracted from gamma_incomplete_imp_final:
|
||||
//
|
||||
bool need_p = false;
|
||||
if ((x < 1.1) && (x >= 0.5) && (x * 0.75f < a))
|
||||
need_p = true;
|
||||
else if ((x < a) && (x >= 1.1))
|
||||
need_p = true;
|
||||
|
||||
if (need_p)
|
||||
return log(gamma_p(a, x, pol));
|
||||
return log1p(-gamma_q(a, x, pol), pol);
|
||||
}
|
||||
|
||||
//
|
||||
// Ratios of two gamma functions:
|
||||
//
|
||||
@@ -2454,6 +2493,29 @@ BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T1, T2> lgamma_q(T1 a, T2 z)
|
||||
{
|
||||
return lgamma_q(a, z, policies::policy<>());
|
||||
}
|
||||
|
||||
template <class T1, class T2, class Policy>
|
||||
BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T1, T2> lgamma_p(T1 a, T2 z, const Policy& /* pol */)
|
||||
{
|
||||
typedef tools::promote_args_t<T1, T2> 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::lgamma_incomplete_lower_imp(static_cast<value_type>(a),
|
||||
static_cast<value_type>(z), forwarding_policy()), "lgamma_p<%1%>(%1%, %1%)");
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
BOOST_MATH_GPU_ENABLED inline tools::promote_args_t<T1, T2> lgamma_p(T1 a, T2 z)
|
||||
{
|
||||
return lgamma_p(a, z, policies::policy<>());
|
||||
}
|
||||
//
|
||||
// Regularised lower incomplete gamma:
|
||||
//
|
||||
|
||||
@@ -567,6 +567,12 @@ namespace boost
|
||||
template <class RT1, class RT2, class Policy>
|
||||
BOOST_MATH_GPU_ENABLED tools::promote_args_t<RT1, RT2> lgamma_q(RT1 a, RT2 z, const Policy&);
|
||||
|
||||
template <class RT1, class RT2>
|
||||
BOOST_MATH_GPU_ENABLED tools::promote_args_t<RT1, RT2> lgamma_p(RT1 a, RT2 z);
|
||||
|
||||
template <class RT1, class RT2, class Policy>
|
||||
BOOST_MATH_GPU_ENABLED tools::promote_args_t<RT1, RT2> lgamma_p(RT1 a, RT2 z, const Policy&);
|
||||
|
||||
template <class RT1, class RT2>
|
||||
BOOST_MATH_GPU_ENABLED tools::promote_args_t<RT1, RT2> gamma_p(RT1 a, RT2 z);
|
||||
|
||||
@@ -1525,6 +1531,9 @@ namespace boost
|
||||
\
|
||||
template <class RT1, class RT2>\
|
||||
BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t<RT1, RT2> lgamma_q(RT1 a, RT2 z){ return boost::math::lgamma_q(a, z, Policy()); }\
|
||||
\
|
||||
template <class RT1, class RT2>\
|
||||
BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t<RT1, RT2> lgamma_p(RT1 a, RT2 z){ return boost::math::lgamma_p(a, z, Policy()); }\
|
||||
\
|
||||
template <class RT1, class RT2>\
|
||||
BOOST_MATH_GPU_ENABLED inline boost::math::tools::promote_args_t<RT1, RT2> gamma_p(RT1 a, RT2 z){ return boost::math::gamma_p(a, z, Policy()); }\
|
||||
|
||||
Reference in New Issue
Block a user