bessel_jy_derivatives_asym.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright (c) 2013 Anton Bikineev
  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. //
  6. // This is a partial header, do not include on it's own!!!
  7. //
  8. // Contains asymptotic expansions for derivatives of Bessel J(v,x) and Y(v,x)
  9. // functions, as x -> INF.
  10. #ifndef BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
  11. #define BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP
  12. #ifdef _MSC_VER
  13. #pragma once
  14. #endif
  15. namespace boost{ namespace math{ namespace detail{
  16. template <class T>
  17. inline T asymptotic_bessel_derivative_amplitude(T v, T x)
  18. {
  19. // Calculate the amplitude for J'(v,x) and I'(v,x)
  20. // for large x: see A&S 9.2.30.
  21. BOOST_MATH_STD_USING
  22. T s = 1;
  23. const T mu = 4 * v * v;
  24. T txq = 2 * x;
  25. txq *= txq;
  26. s -= (mu - 3) / (2 * txq);
  27. s -= ((mu - 1) * (mu - 45)) / (txq * txq * 8);
  28. return sqrt(s * 2 / (boost::math::constants::pi<T>() * x));
  29. }
  30. template <class T>
  31. inline T asymptotic_bessel_derivative_phase_mx(T v, T x)
  32. {
  33. // Calculate the phase of J'(v, x) and Y'(v, x) for large x.
  34. // See A&S 9.2.31.
  35. // Note that the result returned is the phase less (x - PI(v/2 - 1/4))
  36. // which we'll factor in later when we calculate the sines/cosines of the result:
  37. const T mu = 4 * v * v;
  38. const T mu2 = mu * mu;
  39. const T mu3 = mu2 * mu;
  40. T denom = 4 * x;
  41. T denom_mult = denom * denom;
  42. T s = 0;
  43. s += (mu + 3) / (2 * denom);
  44. denom *= denom_mult;
  45. s += (mu2 + (46 * mu) - 63) / (6 * denom);
  46. denom *= denom_mult;
  47. s += (mu3 + (185 * mu2) - (2053 * mu) + 1899) / (5 * denom);
  48. return s;
  49. }
  50. template <class T, class Policy>
  51. inline T asymptotic_bessel_y_derivative_large_x_2(T v, T x, const Policy& pol)
  52. {
  53. // See A&S 9.2.20.
  54. BOOST_MATH_STD_USING
  55. // Get the phase and amplitude:
  56. const T ampl = asymptotic_bessel_derivative_amplitude(v, x);
  57. const T phase = asymptotic_bessel_derivative_phase_mx(v, x);
  58. BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
  59. BOOST_MATH_INSTRUMENT_VARIABLE(phase);
  60. //
  61. // Calculate the sine of the phase, using
  62. // sine/cosine addition rules to factor in
  63. // the x - PI(v/2 - 1/4) term not added to the
  64. // phase when we calculated it.
  65. //
  66. const T cx = cos(x);
  67. const T sx = sin(x);
  68. const T vd2shifted = (v / 2) - 0.25f;
  69. const T ci = cos_pi(vd2shifted, pol);
  70. const T si = sin_pi(vd2shifted, pol);
  71. const T sin_phase = sin(phase) * (cx * ci + sx * si) + cos(phase) * (sx * ci - cx * si);
  72. BOOST_MATH_INSTRUMENT_CODE(sin(phase));
  73. BOOST_MATH_INSTRUMENT_CODE(cos(x));
  74. BOOST_MATH_INSTRUMENT_CODE(cos(phase));
  75. BOOST_MATH_INSTRUMENT_CODE(sin(x));
  76. return sin_phase * ampl;
  77. }
  78. template <class T, class Policy>
  79. inline T asymptotic_bessel_j_derivative_large_x_2(T v, T x, const Policy& pol)
  80. {
  81. // See A&S 9.2.20.
  82. BOOST_MATH_STD_USING
  83. // Get the phase and amplitude:
  84. const T ampl = asymptotic_bessel_derivative_amplitude(v, x);
  85. const T phase = asymptotic_bessel_derivative_phase_mx(v, x);
  86. BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
  87. BOOST_MATH_INSTRUMENT_VARIABLE(phase);
  88. //
  89. // Calculate the sine of the phase, using
  90. // sine/cosine addition rules to factor in
  91. // the x - PI(v/2 - 1/4) term not added to the
  92. // phase when we calculated it.
  93. //
  94. BOOST_MATH_INSTRUMENT_CODE(cos(phase));
  95. BOOST_MATH_INSTRUMENT_CODE(cos(x));
  96. BOOST_MATH_INSTRUMENT_CODE(sin(phase));
  97. BOOST_MATH_INSTRUMENT_CODE(sin(x));
  98. const T cx = cos(x);
  99. const T sx = sin(x);
  100. const T vd2shifted = (v / 2) - 0.25f;
  101. const T ci = cos_pi(vd2shifted, pol);
  102. const T si = sin_pi(vd2shifted, pol);
  103. const T sin_phase = cos(phase) * (cx * ci + sx * si) - sin(phase) * (sx * ci - cx * si);
  104. BOOST_MATH_INSTRUMENT_VARIABLE(sin_phase);
  105. return sin_phase * ampl;
  106. }
  107. template <class T>
  108. inline bool asymptotic_bessel_derivative_large_x_limit(const T& v, const T& x)
  109. {
  110. BOOST_MATH_STD_USING
  111. //
  112. // This function is the copy of math::asymptotic_bessel_large_x_limit
  113. // It means that we use the same rules for determining how x is large
  114. // compared to v.
  115. //
  116. // Determines if x is large enough compared to v to take the asymptotic
  117. // forms above. From A&S 9.2.28 we require:
  118. // v < x * eps^1/8
  119. // and from A&S 9.2.29 we require:
  120. // v^12/10 < 1.5 * x * eps^1/10
  121. // using the former seems to work OK in practice with broadly similar
  122. // error rates either side of the divide for v < 10000.
  123. // At double precision eps^1/8 ~= 0.01.
  124. //
  125. return (std::max)(T(fabs(v)), T(1)) < x * sqrt(boost::math::tools::forth_root_epsilon<T>());
  126. }
  127. }}} // namespaces
  128. #endif // BOOST_MATH_SF_DETAIL_BESSEL_JY_DERIVATIVES_ASYM_HPP