test_pFq_precision.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. // (C) Copyright John Maddock 2006.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #define BOOST_TEST_MAIN
  6. #include <boost/test/unit_test.hpp>
  7. #include <boost/test/tools/floating_point_comparison.hpp>
  8. #include <boost/math/tools/stats.hpp>
  9. #include <boost/math/tools/test.hpp>
  10. #include <boost/math/tools/big_constant.hpp>
  11. #include <boost/math/constants/constants.hpp>
  12. #include <boost/type_traits/is_floating_point.hpp>
  13. #include <boost/array.hpp>
  14. #include "functor.hpp"
  15. #include "handle_test_result.hpp"
  16. #include "table_type.hpp"
  17. #include <boost/math/special_functions/hypergeometric_pFq.hpp>
  18. #include <boost/multiprecision/mpfr.hpp>
  19. #include <boost/math/special_functions/relative_difference.hpp>
  20. #ifdef BOOST_MSVC
  21. #pragma warning(disable:4127)
  22. #endif
  23. #ifndef SC_
  24. #define SC_(x) BOOST_MATH_BIG_CONSTANT(mp_type, 1000000, x)
  25. #endif
  26. typedef boost::multiprecision::mpfr_float mp_type;
  27. void test_spots_1F0()
  28. {
  29. using std::pow;
  30. mp_type tolerance = 2e-20;
  31. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(-3) }, {}, mp_type(2), 20), mp_type(-1), tolerance);
  32. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(-3) }, {}, mp_type(4), 20), mp_type(-27), tolerance);
  33. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(-3) }, {}, mp_type(0.5), 20), mp_type(0.125), tolerance);
  34. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(3) }, {}, mp_type(0.5), 20), mp_type(8), tolerance);
  35. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(3) }, {}, mp_type(2), 20), mp_type(-1), tolerance);
  36. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(3) }, {}, mp_type(4), 20), mp_type(mp_type(-1) / 27), tolerance);
  37. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(3) }, {}, mp_type(-0.5), 20), pow(mp_type(1.5), -3), tolerance);
  38. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(3) }, {}, mp_type(-2), 20), mp_type(1 / mp_type(27)), tolerance);
  39. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(3) }, {}, mp_type(-4), 20), mp_type(mp_type(1) / 125), tolerance);
  40. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(-3) }, {}, mp_type(-0.5), 20), pow(mp_type(1.5), 3), tolerance);
  41. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(-3) }, {}, mp_type(-2), 20), mp_type(27), tolerance);
  42. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({ mp_type(-3) }, {}, mp_type(-4), 20), mp_type(125), tolerance);
  43. BOOST_CHECK_THROW(boost::math::hypergeometric_pFq_precision({ mp_type(3) }, {}, mp_type(1), 20), std::domain_error);
  44. BOOST_CHECK_THROW(boost::math::hypergeometric_pFq_precision({ mp_type(3.25) }, {}, mp_type(1), 20), std::domain_error);
  45. BOOST_CHECK_THROW(boost::math::hypergeometric_pFq_precision({ mp_type(3.25) }, {}, mp_type(2), 20), std::domain_error);
  46. BOOST_CHECK_THROW(boost::math::hypergeometric_pFq_precision({ mp_type(-3.25) }, {}, mp_type(2), 20), std::domain_error);
  47. }
  48. void test_spots_0F1()
  49. {
  50. mp_type tolerance = 2e-20;
  51. BOOST_CHECK_EQUAL(boost::math::hypergeometric_pFq_precision({}, { mp_type(3) }, mp_type(0), 20), 1);
  52. BOOST_CHECK_EQUAL(boost::math::hypergeometric_pFq_precision({}, { mp_type(-3) }, mp_type(0), 20), 1);
  53. //BOOST_CHECK_EQUAL(boost::math::hypergeometric_pFq_precision({}, { mp_type(0) }, mp_type(0), 20), 1);
  54. BOOST_CHECK_THROW(boost::math::hypergeometric_pFq_precision({}, { mp_type(0) }, mp_type(-1), 20), std::domain_error);
  55. BOOST_CHECK_THROW(boost::math::hypergeometric_pFq_precision({}, { mp_type(-1) }, mp_type(-1), 20), std::domain_error);
  56. BOOST_CHECK_THROW(boost::math::hypergeometric_pFq_precision({}, { mp_type(-10) }, mp_type(-5), 20), std::domain_error);
  57. static const boost::array<boost::array<mp_type, 3>, 35> hypergeometric_pFq_integer_data = { {
  58. { SC_(4.0), SC_(-20.0), SC_(-0.012889714201783047561923257996127233830940165138385) },
  59. { SC_(8.0), SC_(-20.0), SC_(0.046498609282365144223175012935939437508273248399881) },
  60. { SC_(12.0), SC_(-20.0), SC_(0.16608847431869756642136191351311569335145459224622) },
  61. { SC_(16.0), SC_(-20.0), SC_(0.27230484709157170329168048388841880599105216477631) },
  62. //{ SC_(20.0), SC_(-20.0), SC_(0.35865872656868844615709101792040025253126126604266) },
  63. { SC_(4.0), SC_(-16.0), SC_(-0.027293644412433023379286103818840667403690937153604) },
  64. { SC_(8.0), SC_(-16.0), SC_(0.098618710511372349330666801041676087431136532039702) },
  65. { SC_(12.0), SC_(-16.0), SC_(0.24360114226383905073379763460037817885919457531523) },
  66. //{ SC_(16.0), SC_(-16.0), SC_(0.35635186318802906043824855864337727878754460163525) },
  67. //{ SC_(20.0), SC_(-16.0), SC_(0.44218381382689101428948260613085371477815110358789) },
  68. { SC_(4.0), SC_(-12.0), SC_(-0.021743572290699436419371120781513860006290363262907) },
  69. { SC_(8.0), SC_(-12.0), SC_(0.19025625754362006866949730683824627505504067855043) },
  70. //{ SC_(12.0), SC_(-12.0), SC_(0.35251228238278927379621049815222218665165551016489) },
  71. //{ SC_(16.0), SC_(-12.0), SC_(0.46415411486674623230458980010115972932474705884865) },
  72. //{ SC_(20.0), SC_(-12.0), SC_(0.54394918325286018927327004362535051310016558628741) },
  73. { SC_(4.0), SC_(-8.0), SC_(0.056818744289274872033266550620647787396712125304880) },
  74. //{ SC_(8.0), SC_(-8.0), SC_(0.34487371876996263249797701802458885718691612997456) },
  75. //{ SC_(12.0), SC_(-8.0), SC_(0.50411654015891701804499796523449656998841355305043) },
  76. //{ SC_(16.0), SC_(-8.0), SC_(0.60191459981670594041254437708158847428118361245442) },
  77. //{ SC_(20.0), SC_(-8.0), SC_(0.66770752550930138035694866478078941681114294465418) },
  78. //{ SC_(4.0), SC_(-4.0), SC_(0.32262860540671645526863760914000166725449779629143) },
  79. //{ SC_(8.0), SC_(-4.0), SC_(0.59755773349355150397404772151441126513126998265958) },
  80. //{ SC_(12.0), SC_(-4.0), SC_(0.71337465206009117934071859694314971137807212605147) },
  81. //{ SC_(16.0), SC_(-4.0), SC_(0.77734333649378860739496954157535257278092349684783) },
  82. //{ SC_(20.0), SC_(-4.0), SC_(0.81794177985447769150469288350369205683856312760890) },
  83. { SC_(4.0), SC_(4.0), SC_(2.5029568338152582758923890008139391395035041790831) },
  84. { SC_(8.0), SC_(4.0), SC_(1.6273673128576761227855719910743734060605725722129) },
  85. { SC_(12.0), SC_(4.0), SC_(1.3898419290864057799739567227851793491657442624207) },
  86. { SC_(16.0), SC_(4.0), SC_(1.2817098157957427946677711269410726972209834860612) },
  87. { SC_(20.0), SC_(4.0), SC_(1.2202539302152377230940386181201477276788392792437) },
  88. { SC_(4.0), SC_(8.0), SC_(5.5616961007411965409200003309686924059253894118586) },
  89. { SC_(8.0), SC_(8.0), SC_(2.5877053985451664722152913482683136948296873738479) },
  90. { SC_(12.0), SC_(8.0), SC_(1.9166410733572697158003086323981583993970490592046) },
  91. { SC_(16.0), SC_(8.0), SC_(1.6370675016890669952237854163997946987362497613701) },
  92. { SC_(20.0), SC_(8.0), SC_(1.4862852701827990444915220582410007454379891584086) },
  93. { SC_(4.0), SC_(12.0), SC_(11.419268276211177842169936131590385979116019595164) },
  94. { SC_(8.0), SC_(12.0), SC_(4.0347215359576567066789638314925802225312840819037) },
  95. { SC_(12.0), SC_(12.0), SC_(2.6242497527837800417573064942486918368886996538285) },
  96. { SC_(16.0), SC_(12.0), SC_(2.0840468784170876805932772732753387258909164486511) },
  97. { SC_(20.0), SC_(12.0), SC_(1.8071042457762091748544382847762106786633952487005) },
  98. { SC_(4.0), SC_(16.0), SC_(22.132051970576036053853444648907108439504682530918) },
  99. { SC_(8.0), SC_(16.0), SC_(6.1850485247748975008808779795786699492711191898792) },
  100. { SC_(12.0), SC_(16.0), SC_(3.5694322843488018916484224923627864928705138154372) },
  101. { SC_(16.0), SC_(16.0), SC_(2.6447371137201451261118187672029372265909501355722) },
  102. { SC_(20.0), SC_(16.0), SC_(2.1934058398888071720297525592515838555602675797235) },
  103. { SC_(4.0), SC_(20.0), SC_(41.021743268279206331672552645354782698296383424328) },
  104. { SC_(8.0), SC_(20.0), SC_(9.3414225299809886395081381945971250426599939097753) },
  105. { SC_(12.0), SC_(20.0), SC_(4.8253866205826406499959001774187695527272168375992) },
  106. { SC_(16.0), SC_(20.0), SC_(3.3462305133519485784864062004430532216764447939942) },
  107. { SC_(20.0), SC_(20.0), SC_(2.6578698872220394617444624241257799193518140676691) },
  108. } };
  109. for (auto row = hypergeometric_pFq_integer_data.begin(); row != hypergeometric_pFq_integer_data.end(); ++row)
  110. {
  111. BOOST_CHECK_CLOSE_FRACTION(boost::math::hypergeometric_pFq_precision({}, { (*row)[0] }, (*row)[1], 20), (*row)[2], tolerance);
  112. }
  113. }
  114. void test_spots_1F1()
  115. {
  116. typedef mp_type T;
  117. #include "hypergeometric_1F1.ipp"
  118. mp_type tolerance = 2e-20;
  119. for (auto row = hypergeometric_1F1.begin(); row != hypergeometric_1F1.end(); ++row)
  120. {
  121. try {
  122. mp_type norm;
  123. mp_type result = boost::math::hypergeometric_pFq_precision({ (*row)[0] }, { (*row)[1] }, (*row)[2], 20);
  124. BOOST_CHECK_CLOSE_FRACTION(result, (*row)[3], tolerance);
  125. }
  126. catch (const boost::math::evaluation_error&) {}
  127. }
  128. }
  129. void test_spots_1F1_b()
  130. {
  131. typedef mp_type T;
  132. #include "hypergeometric_1F1_big.ipp"
  133. mp_type tolerance = 2e-20;
  134. for (auto row = hypergeometric_1F1_big.begin(); row != hypergeometric_1F1_big.end(); ++row)
  135. {
  136. try {
  137. mp_type result = boost::math::hypergeometric_pFq_precision({ (*row)[0] }, { (*row)[1] }, (*row)[2], 20);
  138. BOOST_CHECK_CLOSE_FRACTION(result, (*row)[3], tolerance);
  139. }
  140. catch (const boost::math::evaluation_error&) {}
  141. }
  142. }
  143. void test_spots_2F1()
  144. {
  145. typedef mp_type T;
  146. #include "hypergeometric_2F1.ipp"
  147. mp_type tolerance = 2e-20;
  148. for (auto row = hypergeometric_2F1.begin(); row != hypergeometric_2F1.end(); ++row)
  149. {
  150. try {
  151. mp_type result = boost::math::hypergeometric_pFq_precision({ (*row)[0], (*row)[1] }, { (*row)[2] }, (*row)[3], 20);
  152. BOOST_CHECK_CLOSE_FRACTION(result, (*row)[4], tolerance);
  153. }
  154. catch (const boost::math::evaluation_error&) {}
  155. }
  156. }
  157. void test_spots_0F2()
  158. {
  159. typedef mp_type T;
  160. #include "hypergeometric_0F2.ipp"
  161. mp_type tolerance = 2e-20;
  162. for (auto row = hypergeometric_0F2.begin(); row != hypergeometric_0F2.end(); ++row)
  163. {
  164. try {
  165. T result = boost::math::hypergeometric_pFq_precision({}, { (*row)[0], (*row)[1] }, (*row)[2], 20);
  166. BOOST_CHECK_CLOSE_FRACTION(result, (*row)[3], tolerance);
  167. }
  168. catch (const boost::math::evaluation_error&) {}
  169. }
  170. }
  171. void test_spots_1F2()
  172. {
  173. typedef mp_type T;
  174. #include "hypergeometric_1F2.ipp"
  175. mp_type tolerance = 2e-20;
  176. for (auto row = hypergeometric_1F2.begin(); row != hypergeometric_1F2.end(); ++row)
  177. {
  178. try {
  179. mp_type result = boost::math::hypergeometric_pFq_precision({ (*row)[0] }, { (*row)[1], (*row)[2] }, (*row)[3], 20);
  180. BOOST_CHECK_CLOSE_FRACTION(result, (*row)[4], tolerance);
  181. }
  182. catch (const boost::math::evaluation_error&) {}
  183. }
  184. }
  185. void test_spots_2F2()
  186. {
  187. typedef mp_type T;
  188. #include "hypergeometric_2F2.ipp"
  189. mp_type tolerance = 2e-20;
  190. for (auto row = hypergeometric_2F2.begin(); row != hypergeometric_2F2.end(); ++row)
  191. {
  192. try {
  193. mp_type result = boost::math::hypergeometric_pFq_precision({ (*row)[0], (*row)[1] }, { (*row)[2], (*row)[3] }, (*row)[4], 20);
  194. BOOST_CHECK_CLOSE_FRACTION(result, (*row)[5], tolerance);
  195. }
  196. catch (const boost::math::evaluation_error&) {}
  197. }
  198. }
  199. BOOST_AUTO_TEST_CASE( test_main )
  200. {
  201. test_spots_1F0();
  202. test_spots_0F1();
  203. test_spots_1F1();
  204. test_spots_1F1_b();
  205. test_spots_2F1();
  206. test_spots_0F2();
  207. test_spots_1F2();
  208. test_spots_2F2();
  209. mpfr_free_cache();
  210. }