bessel_i1_errors.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright 2017 John Maddock
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #include <boost/math/special_functions/bessel.hpp>
  7. #include <boost/math/special_functions/relative_difference.hpp>
  8. #include <boost/multiprecision/cpp_bin_float.hpp>
  9. #include <boost/random.hpp>
  10. #include <boost/svg_plot/svg_2d_plot.hpp>
  11. #include <sstream>
  12. #ifdef BOOST_HAS_FLOAT128
  13. #include <boost/multiprecision/float128.hpp>
  14. #endif
  15. typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<256, boost::multiprecision::backends::digit_base_2>, boost::multiprecision::et_on> mp_type;
  16. template <class T>
  17. void test_type(const char* name)
  18. {
  19. typedef boost::math::policies::policy<
  20. boost::math::policies::promote_double<false>,
  21. boost::math::policies::promote_float<false>,
  22. boost::math::policies::overflow_error<boost::math::policies::ignore_error>
  23. > policy_type;
  24. boost::random::mt19937 dist;
  25. boost::random::uniform_real_distribution<T> ur(0, 7.75);
  26. boost::random::uniform_real_distribution<T> ur2(0, 1 / 7.75);
  27. float max_err = 0;
  28. std::map<double, double> small, medium, large;
  29. for(unsigned i = 0; i < 1000; ++i)
  30. {
  31. T input = ur(dist);
  32. mp_type input2(input);
  33. T result = boost::math::cyl_bessel_i(1, input, policy_type());
  34. mp_type result2 = boost::math::cyl_bessel_i(1, input2);
  35. mp_type err = boost::math::relative_difference(result2, mp_type(result)) / mp_type(std::numeric_limits<T>::epsilon());
  36. if(result2 < mp_type(result))
  37. err = -err;
  38. if(fabs(err) > max_err)
  39. {
  40. /*
  41. std::cout << std::setprecision(34) << input << std::endl;
  42. std::cout << std::setprecision(34) << input2 << std::endl;
  43. std::cout << std::setprecision(34) << result << std::endl;
  44. std::cout << std::setprecision(34) << result2 << std::endl;
  45. std::cout << "New max error at x = " << input << " expected " << result2 << " got " << result << " error " << err << std::endl;
  46. */
  47. max_err = static_cast<float>(fabs(err));
  48. }
  49. if(fabs(err) <= 1)
  50. small[static_cast<double>(input)] = static_cast<double>(err);
  51. else if(fabs(err) <= 2)
  52. medium[static_cast<double>(input)] = static_cast<double>(err);
  53. else
  54. large[static_cast<double>(input)] = static_cast<double>(err);
  55. }
  56. int y_interval = static_cast<int>(ceil(max_err / 5));
  57. std::stringstream ss;
  58. ss << "cyl_bessel_i&lt;" << name << "&gt;(1, x) over [0, 7.75]\n(max error = " << std::setprecision(2) << max_err << ")" << std::endl;
  59. boost::svg::svg_2d_plot my_plot;
  60. // Size of SVG image and X and Y range settings.
  61. my_plot.x_range(0, 7.75).image_x_size(700).legend_border_color(boost::svg::lightgray).plot_border_color(boost::svg::lightgray).background_border_color(boost::svg::lightgray)
  62. .y_range(-(int)ceil(max_err), (int)ceil(max_err)).x_label("x").title(ss.str()).y_major_interval(y_interval).x_major_interval(1.0).legend_on(true).plot_window_on(true);
  63. my_plot.plot(small, "&lt; 1eps").stroke_color(boost::svg::green).fill_color(boost::svg::green).size(2);
  64. if(max_err > 1)
  65. {
  66. my_plot.plot(medium, "&lt; 2eps").stroke_color(boost::svg::orange).fill_color(boost::svg::orange).size(2);
  67. if(max_err > 2)
  68. my_plot.plot(large, "&gt; 2eps").stroke_color(boost::svg::red).fill_color(boost::svg::red).size(2);
  69. }
  70. std::string filename("bessel_i1_0_7_");
  71. filename += name;
  72. filename += ".svg";
  73. my_plot.write(filename);
  74. std::cout << "Maximum error for type " << name << " was: " << max_err << std::endl;
  75. max_err = 0;
  76. for(unsigned i = 0; i < 1000; ++i)
  77. {
  78. T input = 1 / ur2(dist);
  79. mp_type input2(input);
  80. T result = boost::math::cyl_bessel_i(1, input, policy_type());
  81. mp_type result2 = boost::math::cyl_bessel_i(1, input2);
  82. mp_type err = boost::math::relative_difference(result2, mp_type(result)) / mp_type(std::numeric_limits<T>::epsilon());
  83. if(boost::math::isinf(result))
  84. {
  85. if(result2 > mp_type((std::numeric_limits<T>::max)()))
  86. err = 0;
  87. else
  88. std::cout << "Bad result at x = " << input << " result = " << result << " true result = " << result2 << std::endl;
  89. }
  90. if(result2 < mp_type(result))
  91. err = -err;
  92. if(fabs(err) > max_err)
  93. {
  94. max_err = static_cast<float>(fabs(err));
  95. }
  96. if(fabs(err) <= 1)
  97. small[1 / static_cast<double>(input)] = static_cast<double>(err);
  98. else if(fabs(err) <= 2)
  99. medium[1 / static_cast<double>(input)] = static_cast<double>(err);
  100. else
  101. large[1 / static_cast<double>(input)] = static_cast<double>(err);
  102. }
  103. y_interval = static_cast<int>(ceil(max_err / 5));
  104. ss.str("");
  105. ss << "cyl_bessel_i&lt;" << name << "&gt;(1, x) over [0, 7.75]\n(max error = " << std::setprecision(2) << max_err << ")" << std::endl;
  106. boost::svg::svg_2d_plot my_plot2;
  107. // Size of SVG image and X and Y range settings.
  108. my_plot2.x_range(0, 1 / 7.75).image_x_size(700).legend_border_color(boost::svg::lightgray).plot_border_color(boost::svg::lightgray).background_border_color(boost::svg::lightgray)
  109. .y_range(-(int)ceil(max_err), (int)ceil(max_err)).x_label("1 / x").title(ss.str()).y_major_interval(y_interval).x_major_interval(0.01).legend_on(true).plot_window_on(true);
  110. my_plot2.plot(small, "&lt; 1eps").stroke_color(boost::svg::green).fill_color(boost::svg::green).size(2);
  111. if(max_err > 1)
  112. {
  113. my_plot2.plot(medium, "&lt; 2eps").stroke_color(boost::svg::orange).fill_color(boost::svg::orange).size(2);
  114. if(max_err > 2)
  115. my_plot2.plot(large, "&gt; 2eps").stroke_color(boost::svg::red).fill_color(boost::svg::red).size(2);
  116. }
  117. filename = "bessel_i1_7_inf_";
  118. filename += name;
  119. filename += ".svg";
  120. my_plot2.write(filename);
  121. std::cout << "Maximum error for type " << name << " was: " << max_err << std::endl;
  122. }
  123. int main()
  124. {
  125. test_type<float>("float");
  126. test_type<double>("double");
  127. #if LDBL_MANT_DIG == 64
  128. test_type<long double>("long double");
  129. #else
  130. test_type<boost::multiprecision::cpp_bin_float_double_extended>("double-extended");
  131. #endif
  132. #ifdef BOOST_HAS_FLOAT128
  133. test_type<boost::multiprecision::float128>("float128");
  134. #else
  135. test_type<boost::multiprecision::cpp_bin_float_quad>("quad");
  136. #endif
  137. return 0;
  138. }