bessel.hpp 27 KB

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