whittaker_shannon_test.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * Copyright Nick Thompson, 2019
  3. * Use, modification and distribution are subject to the
  4. * Boost Software License, Version 1.0. (See accompanying file
  5. * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. #include "math_unit_test.hpp"
  8. #include <numeric>
  9. #include <utility>
  10. #include <random>
  11. #include <boost/core/demangle.hpp>
  12. #include <boost/math/interpolators/whittaker_shannon.hpp>
  13. #ifdef BOOST_HAS_FLOAT128
  14. #include <boost/multiprecision/float128.hpp>
  15. using boost::multiprecision::float128;
  16. #endif
  17. using boost::math::interpolators::whittaker_shannon;
  18. template<class Real>
  19. void test_trivial()
  20. {
  21. Real t0 = 0;
  22. Real h = Real(1)/Real(16);
  23. std::vector<Real> v{1.5};
  24. std::vector<Real> v_copy = v;
  25. auto ws = whittaker_shannon<decltype(v)>(std::move(v), t0, h);
  26. Real expected = 0;
  27. if(!CHECK_MOLLIFIED_CLOSE(expected, ws.prime(0), 10*std::numeric_limits<Real>::epsilon())) {
  28. std::cerr << " Problem occured at abscissa " << 0 << "\n";
  29. }
  30. expected = -v_copy[0]/h;
  31. if(!CHECK_MOLLIFIED_CLOSE(expected, ws.prime(h), 10*std::numeric_limits<Real>::epsilon())) {
  32. std::cerr << " Problem occured at abscissa " << 0 << "\n";
  33. }
  34. }
  35. template<class Real>
  36. void test_knots()
  37. {
  38. Real t0 = 0;
  39. Real h = Real(1)/Real(16);
  40. size_t n = 512;
  41. std::vector<Real> v(n);
  42. std::mt19937 gen(323723);
  43. std::uniform_real_distribution<Real> dis(1.0, 2.0);
  44. for(size_t i = 0; i < n; ++i) {
  45. v[i] = static_cast<Real>(dis(gen));
  46. }
  47. auto ws = whittaker_shannon<decltype(v)>(std::move(v), t0, h);
  48. size_t i = 0;
  49. while (i < n) {
  50. Real t = t0 + i*h;
  51. Real expected = ws[i];
  52. Real computed = ws(t);
  53. CHECK_ULP_CLOSE(expected, computed, 16);
  54. ++i;
  55. }
  56. }
  57. template<class Real>
  58. void test_bump()
  59. {
  60. using std::exp;
  61. using std::abs;
  62. using std::sqrt;
  63. auto bump = [](Real x) { if (abs(x) >= 1) { return Real(0); } return exp(-Real(1)/(Real(1)-x*x)); };
  64. auto bump_prime = [&bump](Real x) { Real z = 1-x*x; return -2*x*bump(x)/(z*z); };
  65. Real t0 = -1;
  66. size_t n = 2049;
  67. Real h = Real(2)/Real(n-1);
  68. std::vector<Real> v(n);
  69. for(size_t i = 0; i < n; ++i) {
  70. Real t = t0 + i*h;
  71. v[i] = bump(t);
  72. }
  73. std::vector<Real> v_copy = v;
  74. auto ws = whittaker_shannon<decltype(v)>(std::move(v), t0, h);
  75. // Test the knots:
  76. for(size_t i = v_copy.size()/4; i < 3*v_copy.size()/4; ++i) {
  77. Real t = t0 + i*h;
  78. Real expected = v_copy[i];
  79. Real computed = ws(t);
  80. if(!CHECK_MOLLIFIED_CLOSE(expected, computed, 10*std::numeric_limits<Real>::epsilon())) {
  81. std::cerr << " Problem occured at abscissa " << t << "\n";
  82. }
  83. Real expected_prime = bump_prime(t);
  84. Real computed_prime = ws.prime(t);
  85. if(!CHECK_MOLLIFIED_CLOSE(expected_prime, computed_prime, 1000*std::numeric_limits<Real>::epsilon())) {
  86. std::cerr << " Problem occured at abscissa " << t << "\n";
  87. }
  88. }
  89. std::mt19937 gen(323723);
  90. std::uniform_real_distribution<long double> dis(-0.85, 0.85);
  91. size_t i = 0;
  92. while (i++ < 1000)
  93. {
  94. Real t = static_cast<Real>(dis(gen));
  95. Real expected = bump(t);
  96. Real computed = ws(t);
  97. if(!CHECK_MOLLIFIED_CLOSE(expected, computed, 10*std::numeric_limits<Real>::epsilon())) {
  98. std::cerr << " Problem occured at abscissa " << t << "\n";
  99. }
  100. Real expected_prime = bump_prime(t);
  101. Real computed_prime = ws.prime(t);
  102. if(!CHECK_MOLLIFIED_CLOSE(expected_prime, computed_prime, sqrt(std::numeric_limits<Real>::epsilon()))) {
  103. std::cerr << " Problem occured at abscissa " << t << "\n";
  104. }
  105. }
  106. }
  107. int main()
  108. {
  109. test_knots<float>();
  110. test_knots<double>();
  111. test_knots<long double>();
  112. test_bump<double>();
  113. test_bump<long double>();
  114. test_trivial<float>();
  115. test_trivial<double>();
  116. return boost::math::test::report_errors();
  117. }