1818#include < boost/type_traits/is_floating_point.hpp>
1919#include < boost/array.hpp>
2020#include " functor.hpp"
21-
2221#include " handle_test_result.hpp"
2322#include " table_type.hpp"
2423
@@ -141,8 +140,9 @@ void test_gamma(T, const char* name)
141140}
142141
143142template <class T >
144- void test_spots (T)
143+ void test_spots (T, const char * name = nullptr )
145144{
145+ std::cout << " Testing spot values with type " << name << std::endl;
146146 //
147147 // basic sanity checks, tolerance is 10 epsilon expressed as a percentage:
148148 //
@@ -256,6 +256,38 @@ void test_spots(T)
256256 BOOST_CHECK_EQUAL (::boost::math::gamma_q (static_cast <T>(1770 ), static_cast <T>(1e-12 )), 1 );
257257 BOOST_CHECK_EQUAL (::boost::math::gamma_p (static_cast <T>(1770 ), static_cast <T>(1e-12 )), 0 );
258258 //
259+ // Check that lgamma_q returns correct values with spot values calculated via wolframalpha log(Q[a, x])
260+ //
261+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(5 ), static_cast <T>(100 )), static_cast <T>(-84 .71697591169848944613823640968965801339401810393519310714864307L ), tolerance);
262+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(22.5 ), static_cast <T>(2000 )), static_cast <T>(-1883 .489773203771543025750308264545743305089849873060383828767138L ), tolerance);
263+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(501.25 ), static_cast <T>(2000 )), static_cast <T>(-810 .2453406781655559126505101822969531699112391075198076300675402L ), tolerance);
264+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(20 ), static_cast <T>(0.25 )), static_cast <T>(-2 .946458104491857816330873290969917497748067639461638294404e-31L ), tolerance);
265+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(40 ), static_cast <T>(0.75 )), static_cast <T>(-5 .930604927955460343652485525435087275997461623988991819824e-54L ), tolerance);
266+ #if defined(__CYGWIN__) || defined(__MINGW32__)
267+ T gcc_win_mul = 2 ;
268+ #else
269+ T gcc_win_mul = 1 ;
270+ #endif
271+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(50 ), static_cast <T>(2 )), static_cast <T>(-5 .214301903317168085381693412994550732094621576607843973832e-51L ), tolerance * gcc_win_mul);
272+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(500 ), static_cast <T>(10 )), static_cast <T>(-3 .79666711621207197039397438773960431648625558027046365463e-639L ), tolerance * 3 * gcc_win_mul);
273+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(5 ), static_cast <T>(1000 )), static_cast <T>(-975 .5430287171020511929200293377669175923128826278957569928895945L ), tolerance);
274+ // Pairs of tests that bisect the crossover condition in our code at double and then quad precision:
275+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(10 ), static_cast <T>(698.75 )), static_cast <T>(-652 .5952453102824132865663191324423994628428404928732148525545721L ), tolerance);
276+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(10 ), static_cast <T>(699.25 )), static_cast <T>(-653 .0888168445921483147208556398158677077537551419551652934287016L ), tolerance);
277+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(10 ), static_cast <T>(999.75 )), static_cast <T>(-950 .3752463850600415679327136010171192193400042422096029239012176L ), tolerance);
278+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(10 ), static_cast <T>(1000.25 )), static_cast <T>(-950 .8707509166152482936275883547176592196662090187561681198668099L ), tolerance);
279+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(50 ), static_cast <T>(698.75 )), static_cast <T>(-522 .3277960730837166223131189587863209730608668858212533099139269L ), tolerance);
280+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(50 ), static_cast <T>(699.25 )), static_cast <T>(-522 .7927997457481265511084805522296021540768033975669071565674196L ), tolerance);
281+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(50 ), static_cast <T>(999.75 )), static_cast <T>(-805 .7977867938474339107474131612354353193501692041340771552419902L ), tolerance);
282+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(50 ), static_cast <T>(1000.25 )), static_cast <T>(-806 .2733124989172792095030711884568388681331032891850662521501582L ), tolerance);
283+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(800 ), static_cast <T>(999.75 )), static_cast <T>(-24 .33274293617739453303937714319703386675839030466670622049929011L ), tolerance * 2 );
284+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(800 ), static_cast <T>(1000.25 )), static_cast <T>(-24 .43514173634027477093666725985191846106997808357863808910970142L ), tolerance * (boost::math::tools::digits<T>() > 54 ? 20 : 1 ));
285+ // Once we get large a,x then error start to accumulate no matter what we do:
286+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(1200 ), static_cast <T>(1249.75 )), static_cast <T>(-2 .565496161584661216769813239648606145255794643472303927896044375L ), tolerance * (std::is_floating_point<T>::value ? 1 : 4 ));
287+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(1200 ), static_cast <T>(1250.25 )), static_cast <T>(-2 .591934862117586205519309712218581885256650074210410262843591453L ), tolerance * ((std::numeric_limits<T>::max_digits10 >= 36 || std::is_same<T, boost::math::concepts::real_concept>::value) ? 750 : (std::is_same<T, float >::value ? 1 : 50 ))); // Test fails on ARM64 and s390x long doubles and real_concept types unless tolerance is adjusted
288+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(2200 ), static_cast <T>(2249.75 )), static_cast <T>(-1 .933779894897391651410597618307863427927461116308937004149240320L ), tolerance * (std::is_floating_point<T>::value ? 1 : 10 ));
289+ BOOST_CHECK_CLOSE (::boost::math::lgamma_q (static_cast <T>(2200 ), static_cast <T>(2250.25 )), static_cast <T>(-1 .950346484067948344620463026377077515919992808640737320057812268L ), tolerance * (std::is_same<T, float >::value ? 1 : (std::is_floating_point<T>::value ? 100 : 200 )));
290+ //
259291 // Coverage:
260292 //
261293#ifndef BOOST_MATH_NO_EXCEPTIONS
@@ -265,6 +297,11 @@ void test_spots(T)
265297 BOOST_CHECK_THROW (boost::math::gamma_q (static_cast <T>(1 ), static_cast <T>(-2 )), std::domain_error);
266298 BOOST_CHECK_THROW (boost::math::gamma_p (static_cast <T>(0 ), static_cast <T>(2 )), std::domain_error);
267299 BOOST_CHECK_THROW (boost::math::gamma_q (static_cast <T>(0 ), static_cast <T>(2 )), std::domain_error);
300+
301+ BOOST_CHECK_THROW (boost::math::lgamma_q (static_cast <T>(-1 ), static_cast <T>(2 )), std::domain_error);
302+ BOOST_CHECK_THROW (boost::math::lgamma_q (static_cast <T>(1 ), static_cast <T>(-2 )), std::domain_error);
303+ BOOST_CHECK_THROW (boost::math::lgamma_q (static_cast <T>(0 ), static_cast <T>(2 )), std::domain_error);
304+
268305 BOOST_CHECK_THROW (boost::math::gamma_p_derivative (static_cast <T>(-1 ), static_cast <T>(2 )), std::domain_error);
269306 BOOST_CHECK_THROW (boost::math::gamma_p_derivative (static_cast <T>(1 ), static_cast <T>(-2 )), std::domain_error);
270307 BOOST_CHECK_THROW (boost::math::gamma_p_derivative (static_cast <T>(0 ), static_cast <T>(2 )), std::domain_error);
@@ -275,6 +312,11 @@ void test_spots(T)
275312 BOOST_CHECK ((boost::math::isnan)(boost::math::gamma_q (static_cast <T>(1 ), static_cast <T>(-2 ))));
276313 BOOST_CHECK ((boost::math::isnan)(boost::math::gamma_p (static_cast <T>(0 ), static_cast <T>(2 ))));
277314 BOOST_CHECK ((boost::math::isnan)(boost::math::gamma_q (static_cast <T>(0 ), static_cast <T>(2 ))));
315+
316+ BOOST_CHECK ((boost::math::isnan)(boost::math::lgamma_q (static_cast <T>(-1 ), static_cast <T>(2 ))));
317+ BOOST_CHECK ((boost::math::isnan)(boost::math::lgamma_q (static_cast <T>(1 ), static_cast <T>(-2 ))));
318+ BOOST_CHECK ((boost::math::isnan)(boost::math::lgamma_q (static_cast <T>(0 ), static_cast <T>(2 ))));
319+
278320 BOOST_CHECK ((boost::math::isnan)(boost::math::gamma_p_derivative (static_cast <T>(-1 ), static_cast <T>(2 ))));
279321 BOOST_CHECK ((boost::math::isnan)(boost::math::gamma_p_derivative (static_cast <T>(1 ), static_cast <T>(-2 ))));
280322 BOOST_CHECK ((boost::math::isnan)(boost::math::gamma_p_derivative (static_cast <T>(0 ), static_cast <T>(2 ))));
0 commit comments