bessel.hpp 28 KB

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