igamma_data.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. #include <boost/math/special_functions/gamma.hpp>
  6. #include <boost/math/constants/constants.hpp>
  7. #include <boost/lexical_cast.hpp>
  8. #include <fstream>
  9. #include <boost/math/tools/test_data.hpp>
  10. #include "mp_t.hpp"
  11. using namespace boost::math::tools;
  12. //
  13. // Force trunctation to float precision of input values:
  14. // we must ensure that the input values are exactly representable
  15. // in whatever type we are testing, or the output values will all
  16. // be thrown off:
  17. //
  18. float external_f;
  19. float force_truncate(const float* f)
  20. {
  21. external_f = *f;
  22. return external_f;
  23. }
  24. float truncate_to_float(mp_t r)
  25. {
  26. float f = boost::math::tools::real_cast<float>(r);
  27. return force_truncate(&f);
  28. }
  29. //
  30. // Our generator takes two arguments, but the second is interpreted
  31. // as an instruction not a value, the second argument won't be placed
  32. // in the output matrix by class test_data, so we add our algorithmically
  33. // derived second argument to the output.
  34. //
  35. struct igamma_data_generator
  36. {
  37. boost::math::tuple<mp_t, mp_t, mp_t, mp_t, mp_t> operator()(mp_t a, mp_t x)
  38. {
  39. // very naively calculate spots:
  40. mp_t z;
  41. switch((int)real_cast<float>(x))
  42. {
  43. case 1:
  44. z = truncate_to_float((std::min)(mp_t(1), a/100));
  45. break;
  46. case 2:
  47. z = truncate_to_float(a / 2);
  48. break;
  49. case 3:
  50. z = truncate_to_float((std::max)(0.9*a, a - 2));
  51. break;
  52. case 4:
  53. z = a;
  54. break;
  55. case 5:
  56. z = truncate_to_float((std::min)(1.1*a, a + 2));
  57. break;
  58. case 6:
  59. z = truncate_to_float(a * 2);
  60. break;
  61. case 7:
  62. z = truncate_to_float((std::max)(mp_t(100), a*100));
  63. break;
  64. default:
  65. BOOST_ASSERT(0 == "Can't get here!!");
  66. }
  67. //mp_t g = boost::math::tgamma(a);
  68. mp_t lg = boost::math::tgamma_lower(a, z);
  69. mp_t ug = boost::math::tgamma(a, z);
  70. mp_t rlg = boost::math::gamma_p(a, z);
  71. mp_t rug = boost::math::gamma_q(a, z);
  72. return boost::math::make_tuple(z, ug, rug, lg, rlg);
  73. }
  74. };
  75. struct gamma_inverse_generator
  76. {
  77. boost::math::tuple<mp_t, mp_t> operator()(const mp_t a, const mp_t p)
  78. {
  79. mp_t x1 = boost::math::gamma_p_inv(a, p);
  80. mp_t x2 = boost::math::gamma_q_inv(a, p);
  81. std::cout << "Inverse for " << a << " " << p << std::endl;
  82. return boost::math::make_tuple(x1, x2);
  83. }
  84. };
  85. struct gamma_inverse_generator_a
  86. {
  87. boost::math::tuple<mp_t, mp_t> operator()(const mp_t x, const mp_t p)
  88. {
  89. mp_t x1 = boost::math::gamma_p_inva(x, p);
  90. mp_t x2 = boost::math::gamma_q_inva(x, p);
  91. std::cout << "Inverse for " << x << " " << p << std::endl;
  92. return boost::math::make_tuple(x1, x2);
  93. }
  94. };
  95. int main(int argc, char*argv [])
  96. {
  97. bool cont;
  98. std::string line;
  99. parameter_info<mp_t> arg1, arg2;
  100. test_data<mp_t> data;
  101. if((argc >= 2) && (std::strcmp(argv[1], "-inverse") == 0))
  102. {
  103. std::cout << "Welcome.\n"
  104. "This program will generate spot tests for the inverse incomplete gamma function:\n"
  105. " gamma_p_inv(a, p) and gamma_q_inv(a, q)\n\n";
  106. do{
  107. get_user_parameter_info(arg1, "a");
  108. get_user_parameter_info(arg2, "p");
  109. data.insert(gamma_inverse_generator(), arg1, arg2);
  110. std::cout << "Any more data [y/n]?";
  111. std::getline(std::cin, line);
  112. boost::algorithm::trim(line);
  113. cont = (line == "y");
  114. }while(cont);
  115. }
  116. else if((argc >= 2) && (std::strcmp(argv[1], "-inverse_a") == 0))
  117. {
  118. std::cout << "Welcome.\n"
  119. "This program will generate spot tests for the inverse incomplete gamma function:\n"
  120. " gamma_p_inva(a, p) and gamma_q_inva(a, q)\n\n";
  121. do{
  122. get_user_parameter_info(arg1, "x");
  123. get_user_parameter_info(arg2, "p");
  124. data.insert(gamma_inverse_generator_a(), arg1, arg2);
  125. std::cout << "Any more data [y/n]?";
  126. std::getline(std::cin, line);
  127. boost::algorithm::trim(line);
  128. cont = (line == "y");
  129. }while(cont);
  130. }
  131. else
  132. {
  133. arg2 = make_periodic_param(mp_t(1), mp_t(8), 7);
  134. arg2.type |= boost::math::tools::dummy_param;
  135. std::cout << "Welcome.\n"
  136. "This program will generate spot tests for the incomplete gamma function:\n"
  137. " gamma(a, z)\n\n";
  138. do{
  139. get_user_parameter_info(arg1, "a");
  140. data.insert(igamma_data_generator(), arg1, arg2);
  141. std::cout << "Any more data [y/n]?";
  142. std::getline(std::cin, line);
  143. boost::algorithm::trim(line);
  144. cont = (line == "y");
  145. }while(cont);
  146. }
  147. std::cout << "Enter name of test data file [default=igamma_data.ipp]";
  148. std::getline(std::cin, line);
  149. boost::algorithm::trim(line);
  150. if(line == "")
  151. line = "igamma_data.ipp";
  152. std::ofstream ofs(line.c_str());
  153. ofs << std::scientific << std::setprecision(40);
  154. write_code(ofs, data, "igamma_data");
  155. return 0;
  156. }