bessel_jy_asym.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright (c) 2007 John Maddock
  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 Bessel J(v,x) and Y(v,x)
  9. // functions, as x -> INF.
  10. //
  11. #ifndef BOOST_MATH_SF_DETAIL_BESSEL_JY_ASYM_HPP
  12. #define BOOST_MATH_SF_DETAIL_BESSEL_JY_ASYM_HPP
  13. #ifdef _MSC_VER
  14. #pragma once
  15. #endif
  16. #include <boost/math/special_functions/factorials.hpp>
  17. namespace boost{ namespace math{ namespace detail{
  18. template <class T>
  19. inline T asymptotic_bessel_amplitude(T v, T x)
  20. {
  21. // Calculate the amplitude of J(v, x) and Y(v, x) for large
  22. // x: see A&S 9.2.28.
  23. BOOST_MATH_STD_USING
  24. T s = 1;
  25. T mu = 4 * v * v;
  26. T txq = 2 * x;
  27. txq *= txq;
  28. s += (mu - 1) / (2 * txq);
  29. s += 3 * (mu - 1) * (mu - 9) / (txq * txq * 8);
  30. s += 15 * (mu - 1) * (mu - 9) * (mu - 25) / (txq * txq * txq * 8 * 6);
  31. return sqrt(s * 2 / (constants::pi<T>() * x));
  32. }
  33. template <class T>
  34. T asymptotic_bessel_phase_mx(T v, T x)
  35. {
  36. //
  37. // Calculate the phase of J(v, x) and Y(v, x) for large x.
  38. // See A&S 9.2.29.
  39. // Note that the result returned is the phase less (x - PI(v/2 + 1/4))
  40. // which we'll factor in later when we calculate the sines/cosines of the result:
  41. //
  42. T mu = 4 * v * v;
  43. T denom = 4 * x;
  44. T denom_mult = denom * denom;
  45. T s = 0;
  46. s += (mu - 1) / (2 * denom);
  47. denom *= denom_mult;
  48. s += (mu - 1) * (mu - 25) / (6 * denom);
  49. denom *= denom_mult;
  50. s += (mu - 1) * (mu * mu - 114 * mu + 1073) / (5 * denom);
  51. denom *= denom_mult;
  52. s += (mu - 1) * (5 * mu * mu * mu - 1535 * mu * mu + 54703 * mu - 375733) / (14 * denom);
  53. return s;
  54. }
  55. template <class T, class Policy>
  56. inline T asymptotic_bessel_y_large_x_2(T v, T x, const Policy& pol)
  57. {
  58. // See A&S 9.2.19.
  59. BOOST_MATH_STD_USING
  60. // Get the phase and amplitude:
  61. T ampl = asymptotic_bessel_amplitude(v, x);
  62. if (0 == ampl)
  63. return ampl;
  64. T phase = asymptotic_bessel_phase_mx(v, x);
  65. BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
  66. BOOST_MATH_INSTRUMENT_VARIABLE(phase);
  67. //
  68. // Calculate the sine of the phase, using
  69. // sine/cosine addition rules to factor in
  70. // the x - PI(v/2 + 1/4) term not added to the
  71. // phase when we calculated it.
  72. //
  73. T cx = cos(x);
  74. T sx = sin(x);
  75. T ci = boost::math::cos_pi(v / 2 + 0.25f, pol);
  76. T si = boost::math::sin_pi(v / 2 + 0.25f, pol);
  77. T sin_phase = sin(phase) * (cx * ci + sx * si) + cos(phase) * (sx * ci - cx * si);
  78. BOOST_MATH_INSTRUMENT_CODE(sin(phase));
  79. BOOST_MATH_INSTRUMENT_CODE(cos(x));
  80. BOOST_MATH_INSTRUMENT_CODE(cos(phase));
  81. BOOST_MATH_INSTRUMENT_CODE(sin(x));
  82. return sin_phase * ampl;
  83. }
  84. template <class T, class Policy>
  85. inline T asymptotic_bessel_j_large_x_2(T v, T x, const Policy& pol)
  86. {
  87. // See A&S 9.2.19.
  88. BOOST_MATH_STD_USING
  89. // Get the phase and amplitude:
  90. T ampl = asymptotic_bessel_amplitude(v, x);
  91. if (0 == ampl)
  92. return ampl; // shortcut.
  93. T phase = asymptotic_bessel_phase_mx(v, x);
  94. BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
  95. BOOST_MATH_INSTRUMENT_VARIABLE(phase);
  96. //
  97. // Calculate the sine of the phase, using
  98. // sine/cosine addition rules to factor in
  99. // the x - PI(v/2 + 1/4) term not added to the
  100. // phase when we calculated it.
  101. //
  102. BOOST_MATH_INSTRUMENT_CODE(cos(phase));
  103. BOOST_MATH_INSTRUMENT_CODE(cos(x));
  104. BOOST_MATH_INSTRUMENT_CODE(sin(phase));
  105. BOOST_MATH_INSTRUMENT_CODE(sin(x));
  106. T cx = cos(x);
  107. T sx = sin(x);
  108. T ci = boost::math::cos_pi(v / 2 + 0.25f, pol);
  109. T si = boost::math::sin_pi(v / 2 + 0.25f, pol);
  110. T sin_phase = cos(phase) * (cx * ci + sx * si) - sin(phase) * (sx * ci - cx * si);
  111. BOOST_MATH_INSTRUMENT_VARIABLE(sin_phase);
  112. return sin_phase * ampl;
  113. }
  114. template <class T>
  115. inline bool asymptotic_bessel_large_x_limit(int v, const T& x)
  116. {
  117. BOOST_MATH_STD_USING
  118. //
  119. // Determines if x is large enough compared to v to take the asymptotic
  120. // forms above. From A&S 9.2.28 we require:
  121. // v < x * eps^1/8
  122. // and from A&S 9.2.29 we require:
  123. // v^12/10 < 1.5 * x * eps^1/10
  124. // using the former seems to work OK in practice with broadly similar
  125. // error rates either side of the divide for v < 10000.
  126. // At double precision eps^1/8 ~= 0.01.
  127. //
  128. BOOST_MATH_ASSERT(v >= 0);
  129. return (v ? v : 1) < x * 0.004f;
  130. }
  131. template <class T>
  132. inline bool asymptotic_bessel_large_x_limit(const T& v, const T& x)
  133. {
  134. BOOST_MATH_STD_USING
  135. //
  136. // Determines if x is large enough compared to v to take the asymptotic
  137. // forms above. From A&S 9.2.28 we require:
  138. // v < x * eps^1/8
  139. // and from A&S 9.2.29 we require:
  140. // v^12/10 < 1.5 * x * eps^1/10
  141. // using the former seems to work OK in practice with broadly similar
  142. // error rates either side of the divide for v < 10000.
  143. // At double precision eps^1/8 ~= 0.01.
  144. //
  145. return (std::max)(T(fabs(v)), T(1)) < x * sqrt(tools::forth_root_epsilon<T>());
  146. }
  147. template <class T, class Policy>
  148. void temme_asymptotic_y_small_x(T v, T x, T* Y, T* Y1, const Policy& pol)
  149. {
  150. T c = 1;
  151. T p = (v / boost::math::sin_pi(v, pol)) * pow(x / 2, -v) / boost::math::tgamma(1 - v, pol);
  152. T q = (v / boost::math::sin_pi(v, pol)) * pow(x / 2, v) / boost::math::tgamma(1 + v, pol);
  153. T f = (p - q) / v;
  154. T g_prefix = boost::math::sin_pi(v / 2, pol);
  155. g_prefix *= g_prefix * 2 / v;
  156. T g = f + g_prefix * q;
  157. T h = p;
  158. T c_mult = -x * x / 4;
  159. T y(c * g), y1(c * h);
  160. for(int k = 1; k < policies::get_max_series_iterations<Policy>(); ++k)
  161. {
  162. f = (k * f + p + q) / (k*k - v*v);
  163. p /= k - v;
  164. q /= k + v;
  165. c *= c_mult / k;
  166. T c1 = pow(-x * x / 4, T(k)) / factorial<T>(k, pol);
  167. g = f + g_prefix * q;
  168. h = -k * g + p;
  169. y += c * g;
  170. y1 += c * h;
  171. if(c * g / tools::epsilon<T>() < y)
  172. break;
  173. }
  174. *Y = -y;
  175. *Y1 = (-2 / x) * y1;
  176. }
  177. template <class T, class Policy>
  178. T asymptotic_bessel_i_large_x(T v, T x, const Policy& pol)
  179. {
  180. BOOST_MATH_STD_USING // ADL of std names
  181. T s = 1;
  182. T mu = 4 * v * v;
  183. T ex = 8 * x;
  184. T num = mu - 1;
  185. T denom = ex;
  186. s -= num / denom;
  187. num *= mu - 9;
  188. denom *= ex * 2;
  189. s += num / denom;
  190. num *= mu - 25;
  191. denom *= ex * 3;
  192. s -= num / denom;
  193. // Try and avoid overflow to the last minute:
  194. T e = exp(x/2);
  195. s = e * (e * s / sqrt(2 * x * constants::pi<T>()));
  196. return (boost::math::isfinite)(s) ?
  197. s : policies::raise_overflow_error<T>("boost::math::asymptotic_bessel_i_large_x<%1%>(%1%,%1%)", nullptr, pol);
  198. }
  199. }}} // namespaces
  200. #endif