@@ -1290,6 +1290,33 @@ BOOST_MATH_GPU_ENABLED T incomplete_tgamma_large_x(const T& a, const T& x, const
12901290 return result;
12911291}
12921292
1293+ template <class T >
1294+ struct incomplete_tgamma_lower_large_a_series
1295+ {
1296+ typedef T result_type;
1297+ BOOST_MATH_GPU_ENABLED incomplete_tgamma_lower_large_a_series (const T& a, const T& x)
1298+ : a_poch(a + 1 ), z(x), term(1 / a) {}
1299+ BOOST_MATH_GPU_ENABLED T operator ()()
1300+ {
1301+ T result = term;
1302+ term *= z / a_poch;
1303+ a_poch += 1 ;
1304+ return result;
1305+ }
1306+ T a_poch, z, term;
1307+ };
1308+
1309+ template <class T , class Policy >
1310+ T incomplete_tgamma_lower_large_a (const T& a, const T&x, const Policy & pol)
1311+ {
1312+ BOOST_MATH_STD_USING
1313+ incomplete_tgamma_lower_large_a_series<T> s (a, x);
1314+ boost::math::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
1315+ T result = boost::math::tools::sum_series (s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
1316+ boost::math::policies::check_series_iterations<T>(" boost::math::tgamma_p<%1%>(%1%,%1%)" , max_iter, pol);
1317+ return result;
1318+ }
1319+
12931320
12941321//
12951322// Main incomplete gamma entry point, handles all four incomplete gamma's:
@@ -1813,6 +1840,45 @@ BOOST_MATH_GPU_ENABLED T lgamma_incomplete_imp(T a, T x, const Policy& pol)
18131840 return log (gamma_q (a, x, pol));
18141841}
18151842
1843+ // Calculate log of incomplete gamma function
1844+ template <class T , class Policy >
1845+ BOOST_MATH_GPU_ENABLED T lgamma_incomplete_lower_imp (T a, T x, const Policy& pol)
1846+ {
1847+ using namespace boost ::math; // temporary until we're in the right namespace
1848+
1849+ BOOST_MATH_STD_USING_CORE
1850+
1851+ // Check for invalid inputs (a < 0 or x < 0)
1852+ constexpr auto function = " boost::math::lgamma_p<%1%>(%1%, %1%)" ;
1853+ if (a <= 0 )
1854+ return policies::raise_domain_error<T>(function, " Argument a to the incomplete gamma function must be greater than zero (got a=%1%)." , a, pol);
1855+ if (x < 0 )
1856+ return policies::raise_domain_error<T>(function, " Argument x to the incomplete gamma function must be >= 0 (got x=%1%)." , x, pol);
1857+
1858+ // Need to change this to be more appropriate!
1859+ if (a > 100 ){
1860+ return log (detail::incomplete_tgamma_lower_large_a (a, x, pol)) + a * log (x) - x - lgamma (a, pol);
1861+ }
1862+
1863+ //
1864+ // Can't do better than taking the log of P, but...
1865+ //
1866+ // Figure out whether we need P or Q, since if we calculate P and it's too close to unity
1867+ // we will lose precision in the result, selection logic here is extracted from gamma_incomplete_imp_final:
1868+ //
1869+ bool need_p = false ;
1870+ if ((x < 0.5 ) && (T (-0.4 ) / log (x) < a))
1871+ need_p = true ;
1872+ else if ((x < 1.1 ) && (x >= 0.5 ) && (x * 0 .75f < a))
1873+ need_p = true ;
1874+ else if ((x < a) && (x >= 1.1 ))
1875+ need_p = true ;
1876+
1877+ if (need_p)
1878+ return log (gamma_p (a, x, pol));
1879+ return log1p (-gamma_q (a, x, pol), pol);
1880+ }
1881+
18161882//
18171883// Ratios of two gamma functions:
18181884//
0 commit comments