bessel.hpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. // Copyright (c) 2007, 2013 John Maddock
  2. // Copyright Christopher Kormanyos 2013.
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // This header just defines the function entry points, and adds dispatch
  8. // to the right implementation method. Most of the implementation details
  9. // are in separate headers and copyright Xiaogang Zhang.
  10. //
  11. #ifndef BOOST_MATH_BESSEL_HPP
  12. #define BOOST_MATH_BESSEL_HPP
  13. #ifdef _MSC_VER
  14. # pragma once
  15. #endif
  16. #include <boost/math/tools/config.hpp>
  17. #include <boost/math/tools/rational.hpp>
  18. #include <boost/math/tools/promotion.hpp>
  19. #include <boost/math/tools/series.hpp>
  20. #include <boost/math/tools/roots.hpp>
  21. #include <boost/math/tools/numeric_limits.hpp>
  22. #include <boost/math/tools/type_traits.hpp>
  23. #include <boost/math/tools/cstdint.hpp>
  24. #include <boost/math/special_functions/detail/bessel_jy.hpp>
  25. #include <boost/math/special_functions/detail/bessel_jn.hpp>
  26. #include <boost/math/special_functions/detail/bessel_yn.hpp>
  27. #include <boost/math/special_functions/detail/bessel_jy_zero.hpp>
  28. #include <boost/math/special_functions/detail/bessel_ik.hpp>
  29. #include <boost/math/special_functions/detail/bessel_i0.hpp>
  30. #include <boost/math/special_functions/detail/bessel_i1.hpp>
  31. #include <boost/math/special_functions/detail/bessel_kn.hpp>
  32. #include <boost/math/special_functions/detail/iconv.hpp>
  33. #include <boost/math/special_functions/sin_pi.hpp>
  34. #include <boost/math/special_functions/cos_pi.hpp>
  35. #include <boost/math/special_functions/sinc.hpp>
  36. #include <boost/math/special_functions/trunc.hpp>
  37. #include <boost/math/special_functions/round.hpp>
  38. #include <boost/math/policies/error_handling.hpp>
  39. #include <boost/math/special_functions/math_fwd.hpp>
  40. #ifdef _MSC_VER
  41. # pragma warning(push)
  42. # pragma warning(disable: 6326) // potential comparison of a constant with another constant
  43. #endif
  44. namespace boost{ namespace math{
  45. namespace detail{
  46. template <class T, class Policy>
  47. struct sph_bessel_j_small_z_series_term
  48. {
  49. typedef T result_type;
  50. BOOST_MATH_GPU_ENABLED sph_bessel_j_small_z_series_term(unsigned v_, T x)
  51. : N(0), v(v_)
  52. {
  53. BOOST_MATH_STD_USING
  54. mult = x / 2;
  55. if(v + 3 > max_factorial<T>::value)
  56. {
  57. term = v * log(mult) - boost::math::lgamma(v+1+T(0.5f), Policy());
  58. term = exp(term);
  59. }
  60. else
  61. term = pow(mult, T(v)) / boost::math::tgamma(v+1+T(0.5f), Policy());
  62. mult *= -mult;
  63. }
  64. BOOST_MATH_GPU_ENABLED T operator()()
  65. {
  66. T r = term;
  67. ++N;
  68. term *= mult / (N * T(N + v + 0.5f));
  69. return r;
  70. }
  71. private:
  72. unsigned N;
  73. unsigned v;
  74. T mult;
  75. T term;
  76. };
  77. template <class T, class Policy>
  78. BOOST_MATH_GPU_ENABLED inline T sph_bessel_j_small_z_series(unsigned v, T x, const Policy& pol)
  79. {
  80. BOOST_MATH_STD_USING // ADL of std names
  81. sph_bessel_j_small_z_series_term<T, Policy> s(v, x);
  82. boost::math::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  83. T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
  84. policies::check_series_iterations<T>("boost::math::sph_bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
  85. return result * sqrt(constants::pi<T>() / 4);
  86. }
  87. template <class T, class Policy>
  88. BOOST_MATH_GPU_ENABLED T cyl_bessel_j_imp_final(T v, T x, const bessel_no_int_tag&, const Policy& pol)
  89. {
  90. BOOST_MATH_STD_USING
  91. T result_J, y; // LCOV_EXCL_LINE
  92. bessel_jy(v, x, &result_J, &y, need_j, pol);
  93. return result_J;
  94. }
  95. // Dispatch funtion to avoid recursion
  96. template <class T, class Policy>
  97. BOOST_MATH_GPU_ENABLED T cyl_bessel_j_imp(T v, T x, const bessel_no_int_tag& t, const Policy& pol)
  98. {
  99. BOOST_MATH_STD_USING
  100. if(x < 0)
  101. {
  102. // better have integer v:
  103. if (floor(v) == v)
  104. {
  105. // LCOV_EXCL_START
  106. // This branch is hit by multiprecision types only, and is
  107. // tested by our real_concept tests, but thee are excluded from coverage
  108. // due to time constraints.
  109. T r = cyl_bessel_j_imp_final(T(v), T(-x), t, pol);
  110. if (iround(v, pol) & 1)
  111. {
  112. r = -r;
  113. }
  114. return r;
  115. // LCOV_EXCL_STOP
  116. }
  117. else
  118. {
  119. constexpr auto function = "boost::math::bessel_j<%1%>(%1%,%1%)";
  120. return policies::raise_domain_error<T>(function, "Got x = %1%, but we need x >= 0", x, pol);
  121. }
  122. }
  123. return cyl_bessel_j_imp_final(T(v), T(x), t, pol);
  124. }
  125. template <class T, class Policy>
  126. BOOST_MATH_GPU_ENABLED inline T cyl_bessel_j_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
  127. {
  128. BOOST_MATH_STD_USING // ADL of std names.
  129. int ival = detail::iconv(v, pol);
  130. // If v is an integer, use the integer recursion
  131. // method, both that and Steeds method are O(v):
  132. if((0 == v - ival))
  133. {
  134. return bessel_jn(ival, x, pol);
  135. }
  136. return cyl_bessel_j_imp(v, x, bessel_no_int_tag(), pol);
  137. }
  138. template <class T, class Policy>
  139. BOOST_MATH_GPU_ENABLED inline T cyl_bessel_j_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
  140. {
  141. BOOST_MATH_STD_USING
  142. return bessel_jn(v, x, pol);
  143. }
  144. template <class T, class Policy>
  145. BOOST_MATH_GPU_ENABLED inline T sph_bessel_j_imp(unsigned n, T x, const Policy& pol)
  146. {
  147. BOOST_MATH_STD_USING // ADL of std names
  148. if(x < 0)
  149. return policies::raise_domain_error<T>("boost::math::sph_bessel_j<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0.", x, pol);
  150. //
  151. // Special case, n == 0 resolves down to the sinus cardinal of x:
  152. //
  153. if(n == 0)
  154. return (boost::math::isinf)(x) ? T(0) : boost::math::sinc_pi(x, pol);
  155. //
  156. // Special case for x == 0:
  157. //
  158. if(x == 0)
  159. return 0;
  160. //
  161. // When x is small we may end up with 0/0, use series evaluation
  162. // instead, especially as it converges rapidly:
  163. //
  164. if(x < 1)
  165. return sph_bessel_j_small_z_series(n, x, pol);
  166. //
  167. // Default case is just a naive evaluation of the definition:
  168. //
  169. return sqrt(constants::pi<T>() / (2 * x))
  170. * cyl_bessel_j_imp(T(T(n)+T(0.5f)), x, bessel_no_int_tag(), pol);
  171. }
  172. template <class T, class Policy>
  173. BOOST_MATH_GPU_ENABLED T cyl_bessel_i_imp_final(T v, T x, const Policy& pol)
  174. {
  175. //
  176. // This handles all the bessel I functions, note that we don't optimise
  177. // for integer v, other than the v = 0 or 1 special cases, as Millers
  178. // algorithm is at least as inefficient as the general case (the general
  179. // case has better error handling too).
  180. //
  181. BOOST_MATH_STD_USING
  182. constexpr auto function = "boost::math::cyl_bessel_i<%1%>(%1%,%1%)";
  183. if(x == 0)
  184. {
  185. if(v < 0)
  186. return floor(v) == v ? static_cast<T>(0) : policies::raise_overflow_error<T>(function, nullptr, pol);
  187. return (v == 0) ? static_cast<T>(1) : static_cast<T>(0);
  188. }
  189. if(v == 0.5f)
  190. {
  191. // common special case, note try and avoid overflow in exp(x):
  192. if(x >= tools::log_max_value<T>())
  193. {
  194. T e = exp(x / 2);
  195. return e * (e / sqrt(2 * x * constants::pi<T>()));
  196. }
  197. return sqrt(2 / (x * constants::pi<T>())) * sinh(x);
  198. }
  199. if((policies::digits<T, Policy>() <= 113) && (boost::math::numeric_limits<T>::digits <= 113) && (boost::math::numeric_limits<T>::radix == 2))
  200. {
  201. if(v == 0)
  202. {
  203. return bessel_i0(x);
  204. }
  205. if(v == 1)
  206. {
  207. return bessel_i1(x);
  208. }
  209. }
  210. if((v > 0) && (x / v < 0.25))
  211. return bessel_i_small_z_series(v, x, pol);
  212. T result_I, result_K; // LCOV_EXCL_LINE
  213. bessel_ik(v, x, &result_I, &result_K, need_i, pol);
  214. return result_I;
  215. }
  216. // Additional dispatch function to get the GPU impls happy
  217. template <class T, class Policy>
  218. BOOST_MATH_GPU_ENABLED T cyl_bessel_i_imp(T v, T x, const Policy& pol)
  219. {
  220. BOOST_MATH_STD_USING
  221. constexpr auto function = "boost::math::cyl_bessel_i<%1%>(%1%,%1%)";
  222. if(x < 0)
  223. {
  224. // better have integer v:
  225. if(floor(v) == v)
  226. {
  227. T r = cyl_bessel_i_imp_final(T(v), T(-x), pol);
  228. if(iround(v, pol) & 1)
  229. {
  230. r = -r;
  231. }
  232. return r;
  233. }
  234. else
  235. {
  236. return policies::raise_domain_error<T>(function, "Got x = %1%, but we need x >= 0", x, pol);
  237. }
  238. }
  239. return cyl_bessel_i_imp_final(T(v), T(x), pol);
  240. }
  241. template <class T, class Policy>
  242. BOOST_MATH_GPU_ENABLED inline T cyl_bessel_k_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol)
  243. {
  244. constexpr auto function = "boost::math::cyl_bessel_k<%1%>(%1%,%1%)";
  245. BOOST_MATH_STD_USING
  246. if(x < 0)
  247. {
  248. return policies::raise_domain_error<T>(function, "Got x = %1%, but we need x > 0", x, pol);
  249. }
  250. if(x == 0)
  251. {
  252. return (v == 0) ? policies::raise_overflow_error<T>(function, nullptr, pol)
  253. : policies::raise_domain_error<T>(function, "Got x = %1%, but we need x > 0", x, pol);
  254. }
  255. T result_I, result_K; // LCOV_EXCL_LINE
  256. bessel_ik(v, x, &result_I, &result_K, need_k, pol);
  257. return result_K;
  258. }
  259. template <class T, class Policy>
  260. BOOST_MATH_GPU_ENABLED inline T cyl_bessel_k_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
  261. {
  262. BOOST_MATH_STD_USING
  263. if((floor(v) == v))
  264. {
  265. return bessel_kn(itrunc(v), x, pol);
  266. }
  267. return cyl_bessel_k_imp(v, x, bessel_no_int_tag(), pol);
  268. }
  269. template <class T, class Policy>
  270. BOOST_MATH_GPU_ENABLED inline T cyl_bessel_k_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
  271. {
  272. return bessel_kn(v, x, pol);
  273. }
  274. template <class T, class Policy>
  275. BOOST_MATH_GPU_ENABLED inline T cyl_neumann_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol)
  276. {
  277. constexpr auto function = "boost::math::cyl_neumann<%1%>(%1%,%1%)";
  278. BOOST_MATH_INSTRUMENT_VARIABLE(v);
  279. BOOST_MATH_INSTRUMENT_VARIABLE(x);
  280. if(x <= 0)
  281. {
  282. return (v == 0) && (x == 0) ?
  283. -policies::raise_overflow_error<T>(function, nullptr, pol) // LCOV_EXCL_LINE MP case only here, not tested in code coverage as it takes too long.
  284. : policies::raise_domain_error<T>(function, "Got x = %1%, but result is complex for x <= 0", x, pol);
  285. }
  286. T result_J, y; // LCOV_EXCL_LINE
  287. bessel_jy(v, x, &result_J, &y, need_y, pol);
  288. //
  289. // Post evaluation check for internal overflow during evaluation,
  290. // can occur when x is small and v is large, in which case the result
  291. // is -INF:
  292. //
  293. if(!(boost::math::isfinite)(y))
  294. return -policies::raise_overflow_error<T>(function, nullptr, pol); // LCOV_EXCL_LINE defensive programming? Might be dead code now...
  295. return y;
  296. }
  297. template <class T, class Policy>
  298. BOOST_MATH_GPU_ENABLED inline T cyl_neumann_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
  299. {
  300. BOOST_MATH_STD_USING
  301. BOOST_MATH_INSTRUMENT_VARIABLE(v);
  302. BOOST_MATH_INSTRUMENT_VARIABLE(x);
  303. if(floor(v) == v)
  304. {
  305. T r = bessel_yn(itrunc(v, pol), x, pol);
  306. BOOST_MATH_INSTRUMENT_VARIABLE(r);
  307. return r;
  308. }
  309. T r = cyl_neumann_imp<T>(v, x, bessel_no_int_tag(), pol);
  310. BOOST_MATH_INSTRUMENT_VARIABLE(r);
  311. return r;
  312. }
  313. template <class T, class Policy>
  314. BOOST_MATH_GPU_ENABLED inline T cyl_neumann_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
  315. {
  316. return bessel_yn(v, x, pol);
  317. }
  318. template <class T, class Policy>
  319. BOOST_MATH_GPU_ENABLED inline T sph_neumann_imp(unsigned v, T x, const Policy& pol)
  320. {
  321. BOOST_MATH_STD_USING // ADL of std names
  322. constexpr auto function = "boost::math::sph_neumann<%1%>(%1%,%1%)";
  323. //
  324. // Nothing much to do here but check for errors, and
  325. // evaluate the function's definition directly:
  326. //
  327. if(x < 0)
  328. return policies::raise_domain_error<T>(function, "Got x = %1%, but function requires x > 0.", x, pol);
  329. if(x < 2 * tools::min_value<T>())
  330. return -policies::raise_overflow_error<T>(function, nullptr, pol);
  331. T result = cyl_neumann_imp(T(T(v)+0.5f), x, bessel_no_int_tag(), pol);
  332. T tx = sqrt(constants::pi<T>() / (2 * x));
  333. if((tx > 1) && (tools::max_value<T>() / tx < fabs(result)))
  334. return -policies::raise_overflow_error<T>(function, nullptr, pol);
  335. return result * tx;
  336. }
  337. template <class T, class Policy>
  338. BOOST_MATH_GPU_ENABLED inline T cyl_bessel_j_zero_imp(T v, int m, const Policy& pol)
  339. {
  340. BOOST_MATH_STD_USING // ADL of std names, needed for floor.
  341. constexpr auto function = "boost::math::cyl_bessel_j_zero<%1%>(%1%, int)";
  342. const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
  343. // Handle non-finite order.
  344. if (!(boost::math::isfinite)(v) )
  345. {
  346. return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
  347. }
  348. // Handle negative rank.
  349. if(m < 0)
  350. {
  351. // Zeros of Jv(x) with negative rank are not defined and requesting one raises a domain error.
  352. return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", static_cast<T>(m), pol);
  353. }
  354. // Get the absolute value of the order.
  355. const bool order_is_negative = (v < 0);
  356. const T vv((!order_is_negative) ? v : T(-v));
  357. // Check if the order is very close to zero or very close to an integer.
  358. const bool order_is_zero = (vv < half_epsilon);
  359. const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
  360. if(m == 0)
  361. {
  362. if(order_is_zero)
  363. {
  364. // The zero'th zero of J0(x) is not defined and requesting it raises a domain error.
  365. return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of J0, but the rank must be > 0 !", static_cast<T>(m), pol);
  366. }
  367. // The zero'th zero of Jv(x) for v < 0 is not defined
  368. // unless the order is a negative integer.
  369. if(order_is_negative && (!order_is_integer))
  370. {
  371. // For non-integer, negative order, requesting the zero'th zero raises a domain error.
  372. return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of Jv for negative, non-integer order, but the rank must be > 0 !", static_cast<T>(m), pol);
  373. }
  374. // The zero'th zero does exist and its value is zero.
  375. return T(0);
  376. }
  377. // Set up the initial guess for the upcoming root-finding.
  378. // If the order is a negative integer, then use the corresponding
  379. // positive integer for the order.
  380. const T guess_root = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess<T, Policy>((order_is_integer ? vv : v), m, pol);
  381. // Select the maximum allowed iterations from the policy.
  382. boost::math::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
  383. const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
  384. // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
  385. const T jvm =
  386. boost::math::tools::newton_raphson_iterate(
  387. boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv_and_jv_prime<T, Policy>((order_is_integer ? vv : v), order_is_zero, pol),
  388. guess_root,
  389. T(guess_root - delta_lo),
  390. T(guess_root + 0.2F),
  391. policies::digits<T, Policy>(),
  392. number_of_iterations);
  393. if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
  394. {
  395. return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time: Current best guess is %1%", jvm, Policy()); // LCOV_EXCL_LINE
  396. }
  397. return jvm;
  398. }
  399. template <class T, class Policy>
  400. BOOST_MATH_GPU_ENABLED inline T cyl_neumann_zero_imp(T v, int m, const Policy& pol)
  401. {
  402. BOOST_MATH_STD_USING // ADL of std names, needed for floor.
  403. constexpr auto function = "boost::math::cyl_neumann_zero<%1%>(%1%, int)";
  404. // Handle non-finite order.
  405. if (!(boost::math::isfinite)(v) )
  406. {
  407. return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
  408. }
  409. // Handle negative rank.
  410. if(m < 0)
  411. {
  412. return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", static_cast<T>(m), pol);
  413. }
  414. const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
  415. // Get the absolute value of the order.
  416. const bool order_is_negative = (v < 0);
  417. const T vv((!order_is_negative) ? v : T(-v));
  418. const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
  419. // For negative integers, use reflection to positive integer order.
  420. if(order_is_negative && order_is_integer)
  421. return boost::math::detail::cyl_neumann_zero_imp(vv, m, pol);
  422. // Check if the order is very close to a negative half-integer.
  423. const T delta_half_integer(vv - (floor(vv) + 0.5F));
  424. const bool order_is_negative_half_integer =
  425. (order_is_negative && ((delta_half_integer > -half_epsilon) && (delta_half_integer < +half_epsilon)));
  426. // The zero'th zero of Yv(x) for v < 0 is not defined
  427. // unless the order is a negative integer.
  428. if((m == 0) && (!order_is_negative_half_integer))
  429. {
  430. // For non-integer, negative order, requesting the zero'th zero raises a domain error.
  431. return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of Yv for negative, non-half-integer order, but the rank must be > 0 !", static_cast<T>(m), pol);
  432. }
  433. // For negative half-integers, use the corresponding
  434. // spherical Bessel function of positive half-integer order.
  435. if(order_is_negative_half_integer)
  436. return boost::math::detail::cyl_bessel_j_zero_imp(vv, m, pol);
  437. // Set up the initial guess for the upcoming root-finding.
  438. // If the order is a negative integer, then use the corresponding
  439. // positive integer for the order.
  440. const T guess_root = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess<T, Policy>(v, m, pol);
  441. // Select the maximum allowed iterations from the policy.
  442. boost::math::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
  443. const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
  444. // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
  445. const T yvm =
  446. boost::math::tools::newton_raphson_iterate(
  447. boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv_and_yv_prime<T, Policy>(v, pol),
  448. guess_root,
  449. T(guess_root - delta_lo),
  450. T(guess_root + 0.2F),
  451. policies::digits<T, Policy>(),
  452. number_of_iterations);
  453. if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
  454. {
  455. return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time: Current best guess is %1%", yvm, Policy()); // LCOV_EXCL_LINE
  456. }
  457. return yvm;
  458. }
  459. } // namespace detail
  460. template <class T1, class T2, class Policy>
  461. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j(T1 v, T2 x, const Policy& /* pol */)
  462. {
  463. BOOST_FPU_EXCEPTION_GUARD
  464. typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
  465. typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
  466. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  467. typedef typename policies::normalise<
  468. Policy,
  469. policies::promote_float<false>,
  470. policies::promote_double<false>,
  471. policies::discrete_quantile<>,
  472. policies::assert_undefined<> >::type forwarding_policy;
  473. return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_bessel_j<%1%>(%1%,%1%)");
  474. }
  475. template <class T1, class T2>
  476. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j(T1 v, T2 x)
  477. {
  478. return cyl_bessel_j(v, x, policies::policy<>());
  479. }
  480. template <class T, class Policy>
  481. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel(unsigned v, T x, const Policy& /* pol */)
  482. {
  483. BOOST_FPU_EXCEPTION_GUARD
  484. typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
  485. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  486. typedef typename policies::normalise<
  487. Policy,
  488. policies::promote_float<false>,
  489. policies::promote_double<false>,
  490. policies::discrete_quantile<>,
  491. policies::assert_undefined<> >::type forwarding_policy;
  492. return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_bessel<%1%>(%1%,%1%)");
  493. }
  494. template <class T>
  495. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel(unsigned v, T x)
  496. {
  497. return sph_bessel(v, x, policies::policy<>());
  498. }
  499. template <class T1, class T2, class Policy>
  500. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i(T1 v, T2 x, const Policy& /* pol */)
  501. {
  502. BOOST_FPU_EXCEPTION_GUARD
  503. typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
  504. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  505. typedef typename policies::normalise<
  506. Policy,
  507. policies::promote_float<false>,
  508. policies::promote_double<false>,
  509. policies::discrete_quantile<>,
  510. policies::assert_undefined<> >::type forwarding_policy;
  511. return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_imp<value_type>(static_cast<value_type>(v), static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_i<%1%>(%1%,%1%)");
  512. }
  513. template <class T1, class T2>
  514. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i(T1 v, T2 x)
  515. {
  516. return cyl_bessel_i(v, x, policies::policy<>());
  517. }
  518. template <class T1, class T2, class Policy>
  519. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k(T1 v, T2 x, const Policy& /* pol */)
  520. {
  521. BOOST_FPU_EXCEPTION_GUARD
  522. typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
  523. typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag128 tag_type;
  524. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  525. typedef typename policies::normalise<
  526. Policy,
  527. policies::promote_float<false>,
  528. policies::promote_double<false>,
  529. policies::discrete_quantile<>,
  530. policies::assert_undefined<> >::type forwarding_policy;
  531. return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_bessel_k<%1%>(%1%,%1%)");
  532. }
  533. template <class T1, class T2>
  534. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k(T1 v, T2 x)
  535. {
  536. return cyl_bessel_k(v, x, policies::policy<>());
  537. }
  538. template <class T1, class T2, class Policy>
  539. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann(T1 v, T2 x, const Policy& /* pol */)
  540. {
  541. BOOST_FPU_EXCEPTION_GUARD
  542. typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
  543. typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
  544. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  545. typedef typename policies::normalise<
  546. Policy,
  547. policies::promote_float<false>,
  548. policies::promote_double<false>,
  549. policies::discrete_quantile<>,
  550. policies::assert_undefined<> >::type forwarding_policy;
  551. return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_neumann<%1%>(%1%,%1%)");
  552. }
  553. template <class T1, class T2>
  554. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann(T1 v, T2 x)
  555. {
  556. return cyl_neumann(v, x, policies::policy<>());
  557. }
  558. template <class T, class Policy>
  559. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann(unsigned v, T x, const Policy& /* pol */)
  560. {
  561. BOOST_FPU_EXCEPTION_GUARD
  562. typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
  563. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  564. typedef typename policies::normalise<
  565. Policy,
  566. policies::promote_float<false>,
  567. policies::promote_double<false>,
  568. policies::discrete_quantile<>,
  569. policies::assert_undefined<> >::type forwarding_policy;
  570. return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_neumann<%1%>(%1%,%1%)");
  571. }
  572. template <class T>
  573. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann(unsigned v, T x)
  574. {
  575. return sph_neumann(v, x, policies::policy<>());
  576. }
  577. template <class T, class Policy>
  578. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_bessel_j_zero(T v, int m, const Policy& /* pol */)
  579. {
  580. BOOST_FPU_EXCEPTION_GUARD
  581. typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
  582. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  583. typedef typename policies::normalise<
  584. Policy,
  585. policies::promote_float<false>,
  586. policies::promote_double<false>,
  587. policies::discrete_quantile<>,
  588. policies::assert_undefined<> >::type forwarding_policy;
  589. static_assert( false == boost::math::numeric_limits<T>::is_specialized
  590. || ( true == boost::math::numeric_limits<T>::is_specialized
  591. && false == boost::math::numeric_limits<T>::is_integer),
  592. "Order must be a floating-point type.");
  593. return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_zero_imp<value_type>(v, m, forwarding_policy()), "boost::math::cyl_bessel_j_zero<%1%>(%1%,%1%)");
  594. }
  595. template <class T>
  596. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_bessel_j_zero(T v, int m)
  597. {
  598. static_assert( false == boost::math::numeric_limits<T>::is_specialized
  599. || ( true == boost::math::numeric_limits<T>::is_specialized
  600. && false == boost::math::numeric_limits<T>::is_integer),
  601. "Order must be a floating-point type.");
  602. return cyl_bessel_j_zero<T, policies::policy<> >(v, m, policies::policy<>());
  603. }
  604. template <class T, class OutputIterator, class Policy>
  605. BOOST_MATH_GPU_ENABLED inline OutputIterator cyl_bessel_j_zero(T v,
  606. int start_index,
  607. unsigned number_of_zeros,
  608. OutputIterator out_it,
  609. const Policy& pol)
  610. {
  611. static_assert( false == boost::math::numeric_limits<T>::is_specialized
  612. || ( true == boost::math::numeric_limits<T>::is_specialized
  613. && false == boost::math::numeric_limits<T>::is_integer),
  614. "Order must be a floating-point type.");
  615. for(int i = 0; i < static_cast<int>(number_of_zeros); ++i)
  616. {
  617. *out_it = boost::math::cyl_bessel_j_zero(v, start_index + i, pol);
  618. ++out_it;
  619. }
  620. return out_it;
  621. }
  622. template <class T, class OutputIterator>
  623. BOOST_MATH_GPU_ENABLED inline OutputIterator cyl_bessel_j_zero(T v,
  624. int start_index,
  625. unsigned number_of_zeros,
  626. OutputIterator out_it)
  627. {
  628. return cyl_bessel_j_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
  629. }
  630. template <class T, class Policy>
  631. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_neumann_zero(T v, int m, const Policy& /* pol */)
  632. {
  633. BOOST_FPU_EXCEPTION_GUARD
  634. typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
  635. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  636. typedef typename policies::normalise<
  637. Policy,
  638. policies::promote_float<false>,
  639. policies::promote_double<false>,
  640. policies::discrete_quantile<>,
  641. policies::assert_undefined<> >::type forwarding_policy;
  642. static_assert( false == boost::math::numeric_limits<T>::is_specialized
  643. || ( true == boost::math::numeric_limits<T>::is_specialized
  644. && false == boost::math::numeric_limits<T>::is_integer),
  645. "Order must be a floating-point type.");
  646. return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_zero_imp<value_type>(v, m, forwarding_policy()), "boost::math::cyl_neumann_zero<%1%>(%1%,%1%)");
  647. }
  648. template <class T>
  649. BOOST_MATH_GPU_ENABLED inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_neumann_zero(T v, int m)
  650. {
  651. static_assert( false == boost::math::numeric_limits<T>::is_specialized
  652. || ( true == boost::math::numeric_limits<T>::is_specialized
  653. && false == boost::math::numeric_limits<T>::is_integer),
  654. "Order must be a floating-point type.");
  655. return cyl_neumann_zero<T, policies::policy<> >(v, m, policies::policy<>());
  656. }
  657. template <class T, class OutputIterator, class Policy>
  658. BOOST_MATH_GPU_ENABLED inline OutputIterator cyl_neumann_zero(T v,
  659. int start_index,
  660. unsigned number_of_zeros,
  661. OutputIterator out_it,
  662. const Policy& pol)
  663. {
  664. static_assert( false == boost::math::numeric_limits<T>::is_specialized
  665. || ( true == boost::math::numeric_limits<T>::is_specialized
  666. && false == boost::math::numeric_limits<T>::is_integer),
  667. "Order must be a floating-point type.");
  668. for(int i = 0; i < static_cast<int>(number_of_zeros); ++i)
  669. {
  670. *out_it = boost::math::cyl_neumann_zero(v, start_index + i, pol);
  671. ++out_it;
  672. }
  673. return out_it;
  674. }
  675. template <class T, class OutputIterator>
  676. BOOST_MATH_GPU_ENABLED inline OutputIterator cyl_neumann_zero(T v,
  677. int start_index,
  678. unsigned number_of_zeros,
  679. OutputIterator out_it)
  680. {
  681. return cyl_neumann_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
  682. }
  683. } // namespace math
  684. } // namespace boost
  685. #ifdef _MSC_VER
  686. # pragma warning(pop)
  687. #endif
  688. #endif // BOOST_MATH_BESSEL_HPP