bessel.hpp 28 KB

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