legendre_stieltjes_test.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright Nick Thompson 2017.
  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. #define BOOST_TEST_MAIN
  7. #include <boost/test/unit_test.hpp>
  8. #include <boost/math/special_functions/legendre.hpp>
  9. #include <boost/math/special_functions/legendre_stieltjes.hpp>
  10. #include <boost/math/constants/constants.hpp>
  11. #include <boost/multiprecision/cpp_bin_float.hpp>
  12. using boost::math::legendre_stieltjes;
  13. using boost::math::legendre_p;
  14. using boost::multiprecision::cpp_bin_float_quad;
  15. template<class Real>
  16. void test_legendre_stieltjes()
  17. {
  18. std::cout << std::setprecision(std::numeric_limits<Real>::digits10);
  19. using std::sqrt;
  20. using std::abs;
  21. using boost::math::constants::third;
  22. using boost::math::constants::half;
  23. Real tol = std::numeric_limits<Real>::epsilon();
  24. legendre_stieltjes<Real> ls1(1);
  25. legendre_stieltjes<Real> ls2(2);
  26. legendre_stieltjes<Real> ls3(3);
  27. legendre_stieltjes<Real> ls4(4);
  28. legendre_stieltjes<Real> ls5(5);
  29. legendre_stieltjes<Real> ls8(8);
  30. Real x = -1;
  31. while(x <= 1)
  32. {
  33. BOOST_CHECK_CLOSE_FRACTION(ls1(x), x, tol);
  34. BOOST_CHECK_CLOSE_FRACTION(ls1.prime(x), 1, tol);
  35. Real p2 = legendre_p(2, x);
  36. BOOST_CHECK_CLOSE_FRACTION(ls2(x), p2 - 2/static_cast<Real>(5), tol);
  37. BOOST_CHECK_CLOSE_FRACTION(ls2.prime(x), 3*x, tol);
  38. Real p3 = legendre_p(3, x);
  39. BOOST_CHECK_CLOSE_FRACTION(ls3(x), p3 - 9*x/static_cast<Real>(14), 600*tol);
  40. BOOST_CHECK_CLOSE_FRACTION(ls3.prime(x), 15*x*x*half<Real>() -3*half<Real>()-9/static_cast<Real>(14), 100*tol);
  41. Real p4 = legendre_p(4, x);
  42. //-20P_2(x)/27 + 14P_0(x)/891
  43. Real E4 = p4 - 20*p2/static_cast<Real>(27) + 14/static_cast<Real>(891);
  44. BOOST_CHECK_CLOSE_FRACTION(ls4(x), E4, 250*tol);
  45. BOOST_CHECK_CLOSE_FRACTION(ls4.prime(x), 35*x*(9*x*x -5)/static_cast<Real>(18), 250*tol);
  46. Real p5 = legendre_p(5, x);
  47. Real E5 = p5 - 35*p3/static_cast<Real>(44) + 135*x/static_cast<Real>(12584);
  48. BOOST_CHECK_CLOSE_FRACTION(ls5(x), E5, 29000*tol);
  49. Real E5prime = (315*(123 + 143*x*x*(11*x*x-9)))/static_cast<Real>(12584);
  50. BOOST_CHECK_CLOSE_FRACTION(ls5.prime(x), E5prime, 29000*tol);
  51. x += 1/static_cast<Real>(1 << 9);
  52. }
  53. // Test norm:
  54. // E_1 = x
  55. Real expected_norm_sq = 2*third<Real>();
  56. BOOST_CHECK_CLOSE_FRACTION(expected_norm_sq, ls1.norm_sq(), tol);
  57. // E_2 = P[sub 2](x) - 2P[sup 0](x)/5
  58. expected_norm_sq = 2/static_cast<Real>(5) + 8/static_cast<Real>(25);
  59. BOOST_CHECK_CLOSE_FRACTION(expected_norm_sq, ls2.norm_sq(), tol);
  60. // E_3 = P[sub 3](x) - 9P[sub 1]/14
  61. expected_norm_sq = 2/static_cast<Real>(7) + 9*9*2*third<Real>()/static_cast<Real>(14*14);
  62. BOOST_CHECK_CLOSE_FRACTION(expected_norm_sq, ls3.norm_sq(), tol);
  63. // E_4 = P[sub 4](x) -20P[sub 2](x)/27 + 14P[sub 0](x)/891
  64. expected_norm_sq = static_cast<Real>(2)/static_cast<Real>(9) + static_cast<Real>(20*20*2)/static_cast<Real>(27*27*5) + 14*14*2/static_cast<Real>(891*891);
  65. BOOST_CHECK_CLOSE_FRACTION(expected_norm_sq, ls4.norm_sq(), tol);
  66. // E_5 = P[sub 5](x) - 35P[sub 3](x)/44 + 135P[sub 1](x)/12584
  67. expected_norm_sq = 2/static_cast<Real>(11) + (35*35/static_cast<Real>(44*44))*(2/static_cast<Real>(7)) + (135*135/static_cast<Real>(12584*12584))*2*third<Real>();
  68. BOOST_CHECK_CLOSE_FRACTION(expected_norm_sq, ls5.norm_sq(), tol);
  69. // Only zero of E1 is 0:
  70. std::vector<Real> zeros = ls1.zeros();
  71. BOOST_CHECK(zeros.size() == 1);
  72. BOOST_CHECK_SMALL(zeros[0], tol);
  73. BOOST_CHECK_SMALL(ls1(zeros[0]), tol);
  74. zeros = ls2.zeros();
  75. BOOST_CHECK(zeros.size() == 1);
  76. BOOST_CHECK_CLOSE_FRACTION(zeros[0], sqrt(3/static_cast<Real>(5)), tol);
  77. BOOST_CHECK_SMALL(ls2(zeros[0]), tol);
  78. zeros = ls3.zeros();
  79. BOOST_CHECK(zeros.size() == 2);
  80. BOOST_CHECK_SMALL(zeros[0], tol);
  81. BOOST_CHECK_CLOSE_FRACTION(zeros[1], sqrt(6/static_cast<Real>(7)), tol);
  82. zeros = ls4.zeros();
  83. BOOST_CHECK(zeros.size() == 2);
  84. Real expected = sqrt( (55 - 2*sqrt(static_cast<Real>(330)))/static_cast<Real>(11) )/static_cast<Real>(3);
  85. BOOST_CHECK_CLOSE_FRACTION(zeros[0], expected, tol);
  86. expected = sqrt( (55 + 2*sqrt(static_cast<Real>(330)))/static_cast<Real>(11) )/static_cast<Real>(3);
  87. BOOST_CHECK_CLOSE_FRACTION(zeros[1], expected, 10*tol);
  88. zeros = ls5.zeros();
  89. BOOST_CHECK(zeros.size() == 3);
  90. BOOST_CHECK_SMALL(zeros[0], tol);
  91. expected = sqrt( ( 195 - sqrt(static_cast<Real>(6045)) )/static_cast<Real>(286));
  92. BOOST_CHECK_CLOSE_FRACTION(zeros[1], expected, tol);
  93. expected = sqrt( ( 195 + sqrt(static_cast<Real>(6045)) )/static_cast<Real>(286));
  94. BOOST_CHECK_CLOSE_FRACTION(zeros[2], expected, tol);
  95. for (size_t i = 6; i < 50; ++i)
  96. {
  97. legendre_stieltjes<Real> En(i);
  98. zeros = En.zeros();
  99. for(auto const & zero : zeros)
  100. {
  101. BOOST_CHECK_SMALL(En(zero), 50*tol);
  102. }
  103. }
  104. }
  105. BOOST_AUTO_TEST_CASE(LegendreStieltjesZeros)
  106. {
  107. test_legendre_stieltjes<double>();
  108. test_legendre_stieltjes<long double>();
  109. test_legendre_stieltjes<cpp_bin_float_quad>();
  110. //test_legendre_stieltjes<boost::multiprecision::cpp_bin_float_100>();
  111. }