test_nc_beta.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // (C) Copyright John Maddock 2007.
  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. #ifndef BOOST_MATH_OVERFLOW_ERROR_POLICY
  6. #define BOOST_MATH_OVERFLOW_ERROR_POLICY ignore_error
  7. #endif
  8. #include <boost/math/concepts/real_concept.hpp>
  9. #define BOOST_TEST_MAIN
  10. #include <boost/test/unit_test.hpp>
  11. #include <boost/test/tools/floating_point_comparison.hpp>
  12. #include <boost/math/distributions/non_central_beta.hpp>
  13. #include <boost/math/distributions/poisson.hpp>
  14. #include <boost/type_traits/is_floating_point.hpp>
  15. #include <boost/array.hpp>
  16. #include "functor.hpp"
  17. #include "handle_test_result.hpp"
  18. #include "table_type.hpp"
  19. #define BOOST_CHECK_CLOSE_EX(a, b, prec, i) \
  20. {\
  21. unsigned int failures = boost::unit_test::results_collector.results( boost::unit_test::framework::current_test_case().p_id ).p_assertions_failed;\
  22. BOOST_CHECK_CLOSE(a, b, prec); \
  23. if(failures != boost::unit_test::results_collector.results( boost::unit_test::framework::current_test_case().p_id ).p_assertions_failed)\
  24. {\
  25. std::cerr << "Failure was at row " << i << std::endl;\
  26. std::cerr << std::setprecision(35); \
  27. std::cerr << "{ " << data[i][0] << " , " << data[i][1] << " , " << data[i][2];\
  28. std::cerr << " , " << data[i][3] << " , " << data[i][4] << " } " << std::endl;\
  29. }\
  30. }
  31. #define BOOST_CHECK_EX(a, i) \
  32. {\
  33. unsigned int failures = boost::unit_test::results_collector.results( boost::unit_test::framework::current_test_case().p_id ).p_assertions_failed;\
  34. BOOST_CHECK(a); \
  35. if(failures != boost::unit_test::results_collector.results( boost::unit_test::framework::current_test_case().p_id ).p_assertions_failed)\
  36. {\
  37. std::cerr << "Failure was at row " << i << std::endl;\
  38. std::cerr << std::setprecision(35); \
  39. std::cerr << "{ " << data[i][0] << " , " << data[i][1] << " , " << data[i][2];\
  40. std::cerr << " , " << data[i][3] << " , " << data[i][4] << " } " << std::endl;\
  41. }\
  42. }
  43. template <class T>
  44. T nc_beta_cdf(T a, T b, T nc, T x)
  45. {
  46. #ifdef NC_BETA_CDF_FUNCTION_TO_TEST
  47. return NC_BETA_CDF_FUNCTION_TO_TEST(a, b, nc, x);
  48. #else
  49. return cdf(boost::math::non_central_beta_distribution<T>(a, b, nc), x);
  50. #endif
  51. }
  52. template <class T>
  53. T nc_beta_ccdf(T a, T b, T nc, T x)
  54. {
  55. #ifdef NC_BETA_CCDF_FUNCTION_TO_TEST
  56. return NC_BETA_CCDF_FUNCTION_TO_TEST(a, b, nc, x);
  57. #else
  58. return cdf(complement(boost::math::non_central_beta_distribution<T>(a, b, nc), x));
  59. #endif
  60. }
  61. template <typename Real, typename T>
  62. void do_test_nc_chi_squared(T& data, const char* type_name, const char* test)
  63. {
  64. typedef Real value_type;
  65. std::cout << "Testing: " << test << std::endl;
  66. value_type(*fp1)(value_type, value_type, value_type, value_type) = nc_beta_cdf;
  67. boost::math::tools::test_result<value_type> result;
  68. #if !(defined(ERROR_REPORTING_MODE) && !defined(NC_BETA_CDF_FUNCTION_TO_TEST))
  69. result = boost::math::tools::test_hetero<Real>(
  70. data,
  71. bind_func<Real>(fp1, 0, 1, 2, 3),
  72. extract_result<Real>(4));
  73. handle_test_result(result, data[result.worst()], result.worst(),
  74. type_name, "non central beta CDF", test);
  75. #endif
  76. #if !(defined(ERROR_REPORTING_MODE) && !defined(NC_BETA_CCDF_FUNCTION_TO_TEST))
  77. fp1 = nc_beta_ccdf;
  78. result = boost::math::tools::test_hetero<Real>(
  79. data,
  80. bind_func<Real>(fp1, 0, 1, 2, 3),
  81. extract_result<Real>(5));
  82. handle_test_result(result, data[result.worst()], result.worst(),
  83. type_name, "non central beta CDF complement", test);
  84. #endif
  85. std::cout << std::endl;
  86. }
  87. template <typename Real, typename T>
  88. void quantile_sanity_check(T& data, const char* type_name, const char* test)
  89. {
  90. #ifndef ERROR_REPORTING_MODE
  91. typedef Real value_type;
  92. //
  93. // Tests with type real_concept take rather too long to run, so
  94. // for now we'll disable them:
  95. //
  96. if(!boost::is_floating_point<value_type>::value)
  97. return;
  98. std::cout << "Testing: " << type_name << " quantile sanity check, with tests " << test << std::endl;
  99. //
  100. // These sanity checks test for a round trip accuracy of one half
  101. // of the bits in T, unless T is type float, in which case we check
  102. // for just one decimal digit. The problem here is the sensitivity
  103. // of the functions, not their accuracy. This test data was generated
  104. // for the forward functions, which means that when it is used as
  105. // the input to the inverses then it is necessarily inexact. This rounding
  106. // of the input is what makes the data unsuitable for use as an accuracy check,
  107. // and also demonstrates that you can't in general round-trip these functions.
  108. // It is however a useful sanity check.
  109. //
  110. value_type precision = static_cast<value_type>(ldexp(1.0, 1 - boost::math::policies::digits<value_type, boost::math::policies::policy<> >() / 2)) * 100;
  111. if(boost::math::policies::digits<value_type, boost::math::policies::policy<> >() < 50)
  112. precision = 1; // 1% or two decimal digits, all we can hope for when the input is truncated to float
  113. for(unsigned i = 0; i < data.size(); ++i)
  114. {
  115. //
  116. // Test case 493 fails at float precision: not enough bits to get
  117. // us back where we started:
  118. //
  119. if((i == 493) && boost::is_same<float, value_type>::value)
  120. continue;
  121. if(data[i][4] == 0)
  122. {
  123. BOOST_CHECK(0 == quantile(boost::math::non_central_beta_distribution<value_type>(data[i][0], data[i][1], data[i][2]), data[i][4]));
  124. }
  125. else if(data[i][4] < 0.9999f)
  126. {
  127. value_type p = quantile(boost::math::non_central_beta_distribution<value_type>(data[i][0], data[i][1], data[i][2]), data[i][4]);
  128. value_type pt = data[i][3];
  129. BOOST_CHECK_CLOSE_EX(pt, p, precision, i);
  130. }
  131. if(data[i][5] == 0)
  132. {
  133. BOOST_CHECK(1 == quantile(complement(boost::math::non_central_beta_distribution<value_type>(data[i][0], data[i][1], data[i][2]), data[i][5])));
  134. }
  135. else if(data[i][5] < 0.9999f)
  136. {
  137. value_type p = quantile(complement(boost::math::non_central_beta_distribution<value_type>(data[i][0], data[i][1], data[i][2]), data[i][5]));
  138. value_type pt = data[i][3];
  139. BOOST_CHECK_CLOSE_EX(pt, p, precision, i);
  140. }
  141. if(boost::math::tools::digits<value_type>() > 50)
  142. {
  143. //
  144. // Sanity check mode, accuracy of
  145. // the mode is at *best* the square root of the accuracy of the PDF:
  146. //
  147. value_type m = mode(boost::math::non_central_beta_distribution<value_type>(data[i][0], data[i][1], data[i][2]));
  148. if((m == 1) || (m == 0))
  149. break;
  150. value_type p = pdf(boost::math::non_central_beta_distribution<value_type>(data[i][0], data[i][1], data[i][2]), m);
  151. if(m * (1 + sqrt(precision) * 10) < 1)
  152. {
  153. BOOST_CHECK_EX(pdf(boost::math::non_central_beta_distribution<value_type>(data[i][0], data[i][1], data[i][2]), m * (1 + sqrt(precision) * 10)) <= p, i);
  154. }
  155. if(m * (1 - sqrt(precision)) * 10 > boost::math::tools::min_value<value_type>())
  156. {
  157. BOOST_CHECK_EX(pdf(boost::math::non_central_beta_distribution<value_type>(data[i][0], data[i][1], data[i][2]), m * (1 - sqrt(precision)) * 10) <= p, i);
  158. }
  159. }
  160. }
  161. #endif
  162. }
  163. template <typename T>
  164. void test_accuracy(T, const char* type_name)
  165. {
  166. #if !defined(TEST_DATA) || (TEST_DATA == 1)
  167. #include "ncbeta.ipp"
  168. do_test_nc_chi_squared<T>(ncbeta, type_name, "Non Central Beta, medium parameters");
  169. quantile_sanity_check<T>(ncbeta, type_name, "Non Central Beta, medium parameters");
  170. #endif
  171. #if !defined(TEST_DATA) || (TEST_DATA == 2)
  172. #include "ncbeta_big.ipp"
  173. do_test_nc_chi_squared<T>(ncbeta_big, type_name, "Non Central Beta, large parameters");
  174. // Takes too long to run:
  175. // quantile_sanity_check(ncbeta_big, type_name, "Non Central Beta, large parameters");
  176. #endif
  177. }