chebyshev.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // (C) Copyright Nick Thompson 2017.
  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_SPECIAL_CHEBYSHEV_HPP
  6. #define BOOST_MATH_SPECIAL_CHEBYSHEV_HPP
  7. #include <cmath>
  8. #include <boost/math/constants/constants.hpp>
  9. #if (__cplusplus > 201103) || (defined(_CPPLIB_VER) && (_CPPLIB_VER >= 610))
  10. # define BOOST_MATH_CHEB_USE_STD_ACOSH
  11. #endif
  12. #ifndef BOOST_MATH_CHEB_USE_STD_ACOSH
  13. # include <boost/math/special_functions/acosh.hpp>
  14. #endif
  15. namespace boost { namespace math {
  16. template<class T1, class T2, class T3>
  17. inline typename tools::promote_args<T1, T2, T3>::type chebyshev_next(T1 const & x, T2 const & Tn, T3 const & Tn_1)
  18. {
  19. return 2*x*Tn - Tn_1;
  20. }
  21. namespace detail {
  22. template<class Real, bool second>
  23. inline Real chebyshev_imp(unsigned n, Real const & x)
  24. {
  25. #ifdef BOOST_MATH_CHEB_USE_STD_ACOSH
  26. using std::acosh;
  27. #else
  28. using boost::math::acosh;
  29. #endif
  30. using std::cosh;
  31. using std::pow;
  32. using std::sqrt;
  33. Real T0 = 1;
  34. Real T1;
  35. if (second)
  36. {
  37. if (x > 1 || x < -1)
  38. {
  39. Real t = sqrt(x*x -1);
  40. return static_cast<Real>((pow(x+t, (int)(n+1)) - pow(x-t, (int)(n+1)))/(2*t));
  41. }
  42. T1 = 2*x;
  43. }
  44. else
  45. {
  46. if (x > 1)
  47. {
  48. return cosh(n*acosh(x));
  49. }
  50. if (x < -1)
  51. {
  52. if (n & 1)
  53. {
  54. return -cosh(n*acosh(-x));
  55. }
  56. else
  57. {
  58. return cosh(n*acosh(-x));
  59. }
  60. }
  61. T1 = x;
  62. }
  63. if (n == 0)
  64. {
  65. return T0;
  66. }
  67. unsigned l = 1;
  68. while(l < n)
  69. {
  70. std::swap(T0, T1);
  71. T1 = boost::math::chebyshev_next(x, T0, T1);
  72. ++l;
  73. }
  74. return T1;
  75. }
  76. } // namespace detail
  77. template <class Real, class Policy>
  78. inline typename tools::promote_args<Real>::type
  79. chebyshev_t(unsigned n, Real const & x, const Policy&)
  80. {
  81. typedef typename tools::promote_args<Real>::type result_type;
  82. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  83. return policies::checked_narrowing_cast<result_type, Policy>(detail::chebyshev_imp<value_type, false>(n, static_cast<value_type>(x)), "boost::math::chebyshev_t<%1%>(unsigned, %1%)");
  84. }
  85. template<class Real>
  86. inline typename tools::promote_args<Real>::type chebyshev_t(unsigned n, Real const & x)
  87. {
  88. return chebyshev_t(n, x, policies::policy<>());
  89. }
  90. template <class Real, class Policy>
  91. inline typename tools::promote_args<Real>::type
  92. chebyshev_u(unsigned n, Real const & x, const Policy&)
  93. {
  94. typedef typename tools::promote_args<Real>::type result_type;
  95. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  96. return policies::checked_narrowing_cast<result_type, Policy>(detail::chebyshev_imp<value_type, true>(n, static_cast<value_type>(x)), "boost::math::chebyshev_u<%1%>(unsigned, %1%)");
  97. }
  98. template<class Real>
  99. inline typename tools::promote_args<Real>::type chebyshev_u(unsigned n, Real const & x)
  100. {
  101. return chebyshev_u(n, x, policies::policy<>());
  102. }
  103. template <class Real, class Policy>
  104. inline typename tools::promote_args<Real>::type
  105. chebyshev_t_prime(unsigned n, Real const & x, const Policy&)
  106. {
  107. typedef typename tools::promote_args<Real>::type result_type;
  108. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  109. if (n == 0)
  110. {
  111. return result_type(0);
  112. }
  113. return policies::checked_narrowing_cast<result_type, Policy>(n * detail::chebyshev_imp<value_type, true>(n - 1, static_cast<value_type>(x)), "boost::math::chebyshev_t_prime<%1%>(unsigned, %1%)");
  114. }
  115. template<class Real>
  116. inline typename tools::promote_args<Real>::type chebyshev_t_prime(unsigned n, Real const & x)
  117. {
  118. return chebyshev_t_prime(n, x, policies::policy<>());
  119. }
  120. /*
  121. * This is Algorithm 3.1 of
  122. * Gil, Amparo, Javier Segura, and Nico M. Temme.
  123. * Numerical methods for special functions.
  124. * Society for Industrial and Applied Mathematics, 2007.
  125. * https://www.siam.org/books/ot99/OT99SampleChapter.pdf
  126. * However, our definition of c0 differs by a factor of 1/2, as stated in the docs. . .
  127. */
  128. template<class Real, class T2>
  129. inline Real chebyshev_clenshaw_recurrence(const Real* const c, size_t length, const T2& x)
  130. {
  131. using boost::math::constants::half;
  132. if (length < 2)
  133. {
  134. if (length == 0)
  135. {
  136. return 0;
  137. }
  138. return c[0]/2;
  139. }
  140. Real b2 = 0;
  141. Real b1 = c[length -1];
  142. for(size_t j = length - 2; j >= 1; --j)
  143. {
  144. Real tmp = 2*x*b1 - b2 + c[j];
  145. b2 = b1;
  146. b1 = tmp;
  147. }
  148. return x*b1 - b2 + half<Real>()*c[0];
  149. }
  150. }}
  151. #endif