jacobi.hpp 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // (C) Copyright Nick Thompson 2019.
  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_JACOBI_HPP
  6. #define BOOST_MATH_SPECIAL_JACOBI_HPP
  7. #include <limits>
  8. #include <stdexcept>
  9. namespace boost { namespace math {
  10. template<typename Real>
  11. Real jacobi(unsigned n, Real alpha, Real beta, Real x)
  12. {
  13. static_assert(!std::is_integral<Real>::value, "Jacobi polynomials do not work with integer arguments.");
  14. if (n == 0) {
  15. return Real(1);
  16. }
  17. Real y0 = 1;
  18. Real y1 = (alpha+1) + (alpha+beta+2)*(x-1)/Real(2);
  19. Real yk = y1;
  20. Real k = 2;
  21. Real k_max = n*(1+std::numeric_limits<Real>::epsilon());
  22. while(k < k_max)
  23. {
  24. // Hoping for lots of common subexpression elimination by the compiler:
  25. Real denom = 2*k*(k+alpha+beta)*(2*k+alpha+beta-2);
  26. Real gamma1 = (2*k+alpha+beta-1)*( (2*k+alpha+beta)*(2*k+alpha+beta-2)*x + alpha*alpha -beta*beta);
  27. Real gamma0 = -2*(k+alpha-1)*(k+beta-1)*(2*k+alpha+beta);
  28. yk = (gamma1*y1 + gamma0*y0)/denom;
  29. y0 = y1;
  30. y1 = yk;
  31. k += 1;
  32. }
  33. return yk;
  34. }
  35. template<typename Real>
  36. Real jacobi_derivative(unsigned n, Real alpha, Real beta, Real x, unsigned k)
  37. {
  38. if (k > n) {
  39. return Real(0);
  40. }
  41. Real scale = 1;
  42. for(unsigned j = 1; j <= k; ++j) {
  43. scale *= (alpha + beta + n + j)/2;
  44. }
  45. return scale*jacobi<Real>(n-k, alpha + k, beta+k, x);
  46. }
  47. template<typename Real>
  48. Real jacobi_prime(unsigned n, Real alpha, Real beta, Real x)
  49. {
  50. return jacobi_derivative<Real>(n, alpha, beta, x, 1);
  51. }
  52. template<typename Real>
  53. Real jacobi_double_prime(unsigned n, Real alpha, Real beta, Real x)
  54. {
  55. return jacobi_derivative<Real>(n, alpha, beta, x, 2);
  56. }
  57. }}
  58. #endif