bessel_prime.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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. #ifndef BOOST_MATH_BESSEL_DERIVATIVES_HPP
  7. #define BOOST_MATH_BESSEL_DERIVATIVES_HPP
  8. #ifdef _MSC_VER
  9. # pragma once
  10. #endif
  11. #include <boost/math/special_functions/math_fwd.hpp>
  12. #include <boost/math/special_functions/bessel.hpp>
  13. #include <boost/math/special_functions/detail/bessel_jy_derivatives_asym.hpp>
  14. #include <boost/math/special_functions/detail/bessel_jy_derivatives_series.hpp>
  15. #include <boost/math/special_functions/detail/bessel_derivatives_linear.hpp>
  16. namespace boost{ namespace math{
  17. namespace detail{
  18. template <class Tag, class T, class Policy>
  19. inline T cyl_bessel_j_prime_imp(T v, T x, const Policy& pol)
  20. {
  21. static const char* const function = "boost::math::cyl_bessel_j_prime<%1%>(%1%,%1%)";
  22. BOOST_MATH_STD_USING
  23. //
  24. // Prevent complex result:
  25. //
  26. if ((x < 0) && (floor(v) != v))
  27. return boost::math::policies::raise_domain_error<T>(function, "Got x = %1%, but function requires x >= 0", x, pol);
  28. //
  29. // Special cases for x == 0:
  30. //
  31. if (x == 0)
  32. {
  33. if (v == 1)
  34. return static_cast<T>(0.5);
  35. else if (v == -1)
  36. return static_cast<T>(-0.5);
  37. else if (floor(v) == v || v > 1)
  38. return 0;
  39. else
  40. return boost::math::policies::raise_domain_error<T>(function, "Got x = %1%, but function is indeterminate for this order", x, pol);
  41. }
  42. //
  43. // Special case for large x: use asymptotic expansion:
  44. //
  45. if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x))
  46. return boost::math::detail::asymptotic_bessel_j_derivative_large_x_2(v, x, pol);
  47. //
  48. // Special case for small x: use Taylor series:
  49. //
  50. if ((abs(x) < 5) || (abs(v) > x * x / 4))
  51. {
  52. bool inversed = false;
  53. if (floor(v) == v && v < 0)
  54. {
  55. v = -v;
  56. if (itrunc(v, pol) & 1)
  57. inversed = true;
  58. }
  59. T r = boost::math::detail::bessel_j_derivative_small_z_series(v, x, pol);
  60. return inversed ? T(-r) : r;
  61. }
  62. //
  63. // Special case for v == 0:
  64. //
  65. if (v == 0)
  66. return -boost::math::detail::cyl_bessel_j_imp<T>(1, x, Tag(), pol);
  67. //
  68. // Default case:
  69. //
  70. return boost::math::detail::bessel_j_derivative_linear(v, x, Tag(), pol);
  71. }
  72. template <class T, class Policy>
  73. inline T sph_bessel_j_prime_imp(unsigned v, T x, const Policy& pol)
  74. {
  75. static const char* const function = "boost::math::sph_bessel_prime<%1%>(%1%,%1%)";
  76. //
  77. // Prevent complex result:
  78. //
  79. if (x < 0)
  80. return boost::math::policies::raise_domain_error<T>(function, "Got x = %1%, but function requires x >= 0.", x, pol);
  81. //
  82. // Special case for v == 0:
  83. //
  84. if (v == 0)
  85. return (x == 0) ? boost::math::policies::raise_overflow_error<T>(function, nullptr, pol)
  86. : static_cast<T>(-boost::math::detail::sph_bessel_j_imp<T>(1, x, pol));
  87. //
  88. // Special case for x == 0 and v > 0:
  89. //
  90. if (x == 0)
  91. return boost::math::policies::raise_domain_error<T>(function, "Got x = %1%, but function is indeterminate for this order", x, pol);
  92. //
  93. // Default case:
  94. //
  95. return boost::math::detail::sph_bessel_j_derivative_linear(v, x, pol);
  96. }
  97. template <class T, class Policy>
  98. inline T cyl_bessel_i_prime_imp(T v, T x, const Policy& pol)
  99. {
  100. static const char* const function = "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)";
  101. BOOST_MATH_STD_USING
  102. //
  103. // Prevent complex result:
  104. //
  105. if (x < 0 && floor(v) != v)
  106. return boost::math::policies::raise_domain_error<T>(function, "Got x = %1%, but function requires x >= 0", x, pol);
  107. //
  108. // Special cases for x == 0:
  109. //
  110. if (x == 0)
  111. {
  112. if (v == 1 || v == -1)
  113. return static_cast<T>(0.5);
  114. else if (floor(v) == v || v > 1)
  115. return 0;
  116. else
  117. return boost::math::policies::raise_domain_error<T>(function, "Got x = %1%, but function is indeterminate for this order", x, pol);
  118. }
  119. //
  120. // Special case for v == 0:
  121. //
  122. if (v == 0)
  123. return boost::math::detail::cyl_bessel_i_imp<T>(1, x, pol);
  124. //
  125. // Default case:
  126. //
  127. return boost::math::detail::bessel_i_derivative_linear(v, x, pol);
  128. }
  129. template <class Tag, class T, class Policy>
  130. inline T cyl_bessel_k_prime_imp(T v, T x, const Policy& pol)
  131. {
  132. //
  133. // Prevent complex and indeterminate results:
  134. //
  135. if (x <= 0)
  136. return boost::math::policies::raise_domain_error<T>("boost::math::cyl_bessel_k_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0", x, pol);
  137. //
  138. // Special case for v == 0:
  139. //
  140. if (v == 0)
  141. return -boost::math::detail::cyl_bessel_k_imp<T>(1, x, Tag(), pol);
  142. //
  143. // Default case:
  144. //
  145. return boost::math::detail::bessel_k_derivative_linear(v, x, Tag(), pol);
  146. }
  147. template <class Tag, class T, class Policy>
  148. inline T cyl_neumann_prime_imp(T v, T x, const Policy& pol)
  149. {
  150. BOOST_MATH_STD_USING
  151. //
  152. // Prevent complex and indeterminate results:
  153. //
  154. if (x <= 0)
  155. return boost::math::policies::raise_domain_error<T>("boost::math::cyl_neumann_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0", x, pol);
  156. //
  157. // Special case for large x: use asymptotic expansion:
  158. //
  159. if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x))
  160. return boost::math::detail::asymptotic_bessel_y_derivative_large_x_2(v, x, pol);
  161. //
  162. // Special case for small x: use Taylor series:
  163. //
  164. if (v > 0 && floor(v) != v)
  165. {
  166. const T eps = boost::math::policies::get_epsilon<T, Policy>();
  167. if (log(eps / 2) > v * log((x * x) / (v * 4)))
  168. return boost::math::detail::bessel_y_derivative_small_z_series(v, x, pol);
  169. }
  170. //
  171. // Special case for v == 0:
  172. //
  173. if (v == 0)
  174. return -boost::math::detail::cyl_neumann_imp<T>(1, x, Tag(), pol);
  175. //
  176. // Default case:
  177. //
  178. return boost::math::detail::bessel_y_derivative_linear(v, x, Tag(), pol);
  179. }
  180. template <class T, class Policy>
  181. inline T sph_neumann_prime_imp(unsigned v, T x, const Policy& pol)
  182. {
  183. //
  184. // Prevent complex and indeterminate result:
  185. //
  186. if (x <= 0)
  187. return boost::math::policies::raise_domain_error<T>("boost::math::sph_neumann_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0.", x, pol);
  188. //
  189. // Special case for v == 0:
  190. //
  191. if (v == 0)
  192. return -boost::math::detail::sph_neumann_imp<T>(1, x, pol);
  193. //
  194. // Default case:
  195. //
  196. return boost::math::detail::sph_neumann_derivative_linear(v, x, pol);
  197. }
  198. } // namespace detail
  199. template <class T1, class T2, class Policy>
  200. inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j_prime(T1 v, T2 x, const Policy& /* pol */)
  201. {
  202. BOOST_FPU_EXCEPTION_GUARD
  203. typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
  204. typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
  205. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  206. typedef typename policies::normalise<
  207. Policy,
  208. policies::promote_float<false>,
  209. policies::promote_double<false>,
  210. policies::discrete_quantile<>,
  211. policies::assert_undefined<> >::type forwarding_policy;
  212. return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_prime_imp<tag_type, value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_j_prime<%1%,%1%>(%1%,%1%)");
  213. }
  214. template <class T1, class T2>
  215. inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j_prime(T1 v, T2 x)
  216. {
  217. return cyl_bessel_j_prime(v, x, policies::policy<>());
  218. }
  219. template <class T, class Policy>
  220. inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel_prime(unsigned v, T x, const Policy& /* pol */)
  221. {
  222. BOOST_FPU_EXCEPTION_GUARD
  223. typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
  224. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  225. typedef typename policies::normalise<
  226. Policy,
  227. policies::promote_float<false>,
  228. policies::promote_double<false>,
  229. policies::discrete_quantile<>,
  230. policies::assert_undefined<> >::type forwarding_policy;
  231. return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_prime_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_bessel_j_prime<%1%>(%1%,%1%)");
  232. }
  233. template <class T>
  234. inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel_prime(unsigned v, T x)
  235. {
  236. return sph_bessel_prime(v, x, policies::policy<>());
  237. }
  238. template <class T1, class T2, class Policy>
  239. inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i_prime(T1 v, T2 x, const Policy& /* pol */)
  240. {
  241. BOOST_FPU_EXCEPTION_GUARD
  242. typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
  243. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  244. typedef typename policies::normalise<
  245. Policy,
  246. policies::promote_float<false>,
  247. policies::promote_double<false>,
  248. policies::discrete_quantile<>,
  249. policies::assert_undefined<> >::type forwarding_policy;
  250. return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_prime_imp<value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)");
  251. }
  252. template <class T1, class T2>
  253. inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i_prime(T1 v, T2 x)
  254. {
  255. return cyl_bessel_i_prime(v, x, policies::policy<>());
  256. }
  257. template <class T1, class T2, class Policy>
  258. inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k_prime(T1 v, T2 x, const Policy& /* pol */)
  259. {
  260. BOOST_FPU_EXCEPTION_GUARD
  261. typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
  262. typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
  263. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  264. typedef typename policies::normalise<
  265. Policy,
  266. policies::promote_float<false>,
  267. policies::promote_double<false>,
  268. policies::discrete_quantile<>,
  269. policies::assert_undefined<> >::type forwarding_policy;
  270. return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_prime_imp<tag_type, value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_k_prime<%1%,%1%>(%1%,%1%)");
  271. }
  272. template <class T1, class T2>
  273. inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k_prime(T1 v, T2 x)
  274. {
  275. return cyl_bessel_k_prime(v, x, policies::policy<>());
  276. }
  277. template <class T1, class T2, class Policy>
  278. inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann_prime(T1 v, T2 x, const Policy& /* pol */)
  279. {
  280. BOOST_FPU_EXCEPTION_GUARD
  281. typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
  282. typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
  283. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  284. typedef typename policies::normalise<
  285. Policy,
  286. policies::promote_float<false>,
  287. policies::promote_double<false>,
  288. policies::discrete_quantile<>,
  289. policies::assert_undefined<> >::type forwarding_policy;
  290. return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_prime_imp<tag_type, value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_neumann_prime<%1%,%1%>(%1%,%1%)");
  291. }
  292. template <class T1, class T2>
  293. inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann_prime(T1 v, T2 x)
  294. {
  295. return cyl_neumann_prime(v, x, policies::policy<>());
  296. }
  297. template <class T, class Policy>
  298. inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann_prime(unsigned v, T x, const Policy& /* pol */)
  299. {
  300. BOOST_FPU_EXCEPTION_GUARD
  301. typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
  302. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  303. typedef typename policies::normalise<
  304. Policy,
  305. policies::promote_float<false>,
  306. policies::promote_double<false>,
  307. policies::discrete_quantile<>,
  308. policies::assert_undefined<> >::type forwarding_policy;
  309. return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_prime_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_neumann_prime<%1%>(%1%,%1%)");
  310. }
  311. template <class T>
  312. inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann_prime(unsigned v, T x)
  313. {
  314. return sph_neumann_prime(v, x, policies::policy<>());
  315. }
  316. } // namespace math
  317. } // namespace boost
  318. #endif // BOOST_MATH_BESSEL_DERIVATIVES_HPP