comparison DEPENDENCIES/generic/include/boost/math/special_functions/bessel.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
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
14 #ifdef _MSC_VER
15 # pragma once
16 #endif
17
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
37 namespace boost{ namespace math{
38
39 namespace detail{
40
41 template <class T, class Policy>
42 struct sph_bessel_j_small_z_series_term
43 {
44 typedef T result_type;
45
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
74 template <class T, class Policy>
75 inline T sph_bessel_j_small_z_series(unsigned v, T x, const Policy& pol)
76 {
77 BOOST_MATH_STD_USING // ADL of std names
78 sph_bessel_j_small_z_series_term<T, Policy> s(v, x);
79 boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
80 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
81 T zero = 0;
82 T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
83 #else
84 T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
85 #endif
86 policies::check_series_iterations<T>("boost::math::sph_bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
87 return result * sqrt(constants::pi<T>() / 4);
88 }
89
90 template <class T, class Policy>
91 T cyl_bessel_j_imp(T v, T x, const bessel_no_int_tag& t, const Policy& pol)
92 {
93 BOOST_MATH_STD_USING
94 static const char* function = "boost::math::bessel_j<%1%>(%1%,%1%)";
95 if(x < 0)
96 {
97 // better have integer v:
98 if(floor(v) == v)
99 {
100 T r = cyl_bessel_j_imp(v, T(-x), t, pol);
101 if(iround(v, pol) & 1)
102 r = -r;
103 return r;
104 }
105 else
106 return policies::raise_domain_error<T>(
107 function,
108 "Got x = %1%, but we need x >= 0", x, pol);
109 }
110
111 T j, y;
112 bessel_jy(v, x, &j, &y, need_j, pol);
113 return j;
114 }
115
116 template <class T, class Policy>
117 inline T cyl_bessel_j_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
118 {
119 BOOST_MATH_STD_USING // ADL of std names.
120 int ival = detail::iconv(v, pol);
121 // If v is an integer, use the integer recursion
122 // method, both that and Steeds method are O(v):
123 if((0 == v - ival))
124 {
125 return bessel_jn(ival, x, pol);
126 }
127 return cyl_bessel_j_imp(v, x, bessel_no_int_tag(), pol);
128 }
129
130 template <class T, class Policy>
131 inline T cyl_bessel_j_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
132 {
133 BOOST_MATH_STD_USING
134 return bessel_jn(v, x, pol);
135 }
136
137 template <class T, class Policy>
138 inline T sph_bessel_j_imp(unsigned n, T x, const Policy& pol)
139 {
140 BOOST_MATH_STD_USING // ADL of std names
141 if(x < 0)
142 return policies::raise_domain_error<T>(
143 "boost::math::sph_bessel_j<%1%>(%1%,%1%)",
144 "Got x = %1%, but function requires x > 0.", x, pol);
145 //
146 // Special case, n == 0 resolves down to the sinus cardinal of x:
147 //
148 if(n == 0)
149 return boost::math::sinc_pi(x, pol);
150 //
151 // Special case for x == 0:
152 //
153 if(x == 0)
154 return 0;
155 //
156 // When x is small we may end up with 0/0, use series evaluation
157 // instead, especially as it converges rapidly:
158 //
159 if(x < 1)
160 return sph_bessel_j_small_z_series(n, x, pol);
161 //
162 // Default case is just a naive evaluation of the definition:
163 //
164 return sqrt(constants::pi<T>() / (2 * x))
165 * cyl_bessel_j_imp(T(T(n)+T(0.5f)), x, bessel_no_int_tag(), pol);
166 }
167
168 template <class T, class Policy>
169 T cyl_bessel_i_imp(T v, T x, const Policy& pol)
170 {
171 //
172 // This handles all the bessel I functions, note that we don't optimise
173 // for integer v, other than the v = 0 or 1 special cases, as Millers
174 // algorithm is at least as inefficient as the general case (the general
175 // case has better error handling too).
176 //
177 BOOST_MATH_STD_USING
178 if(x < 0)
179 {
180 // better have integer v:
181 if(floor(v) == v)
182 {
183 T r = cyl_bessel_i_imp(v, T(-x), pol);
184 if(iround(v, pol) & 1)
185 r = -r;
186 return r;
187 }
188 else
189 return policies::raise_domain_error<T>(
190 "boost::math::cyl_bessel_i<%1%>(%1%,%1%)",
191 "Got x = %1%, but we need x >= 0", x, pol);
192 }
193 if(x == 0)
194 {
195 return (v == 0) ? 1 : 0;
196 }
197 if(v == 0.5f)
198 {
199 // common special case, note try and avoid overflow in exp(x):
200 if(x >= tools::log_max_value<T>())
201 {
202 T e = exp(x / 2);
203 return e * (e / sqrt(2 * x * constants::pi<T>()));
204 }
205 return sqrt(2 / (x * constants::pi<T>())) * sinh(x);
206 }
207 if(policies::digits<T, Policy>() <= 64)
208 {
209 if(v == 0)
210 {
211 return bessel_i0(x);
212 }
213 if(v == 1)
214 {
215 return bessel_i1(x);
216 }
217 }
218 if((v > 0) && (x / v < 0.25))
219 return bessel_i_small_z_series(v, x, pol);
220 T I, K;
221 bessel_ik(v, x, &I, &K, need_i, pol);
222 return I;
223 }
224
225 template <class T, class Policy>
226 inline T cyl_bessel_k_imp(T v, T x, const bessel_no_int_tag& /* t */, const Policy& pol)
227 {
228 static const char* function = "boost::math::cyl_bessel_k<%1%>(%1%,%1%)";
229 BOOST_MATH_STD_USING
230 if(x < 0)
231 {
232 return policies::raise_domain_error<T>(
233 function,
234 "Got x = %1%, but we need x > 0", x, pol);
235 }
236 if(x == 0)
237 {
238 return (v == 0) ? policies::raise_overflow_error<T>(function, 0, pol)
239 : policies::raise_domain_error<T>(
240 function,
241 "Got x = %1%, but we need x > 0", x, pol);
242 }
243 T I, K;
244 bessel_ik(v, x, &I, &K, need_k, pol);
245 return K;
246 }
247
248 template <class T, class Policy>
249 inline T cyl_bessel_k_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
250 {
251 BOOST_MATH_STD_USING
252 if((floor(v) == v))
253 {
254 return bessel_kn(itrunc(v), x, pol);
255 }
256 return cyl_bessel_k_imp(v, x, bessel_no_int_tag(), pol);
257 }
258
259 template <class T, class Policy>
260 inline T cyl_bessel_k_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
261 {
262 return bessel_kn(v, x, pol);
263 }
264
265 template <class T, class Policy>
266 inline T cyl_neumann_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol)
267 {
268 static const char* function = "boost::math::cyl_neumann<%1%>(%1%,%1%)";
269
270 BOOST_MATH_INSTRUMENT_VARIABLE(v);
271 BOOST_MATH_INSTRUMENT_VARIABLE(x);
272
273 if(x <= 0)
274 {
275 return (v == 0) && (x == 0) ?
276 policies::raise_overflow_error<T>(function, 0, pol)
277 : policies::raise_domain_error<T>(
278 function,
279 "Got x = %1%, but result is complex for x <= 0", x, pol);
280 }
281 T j, y;
282 bessel_jy(v, x, &j, &y, need_y, pol);
283 //
284 // Post evaluation check for internal overflow during evaluation,
285 // can occur when x is small and v is large, in which case the result
286 // is -INF:
287 //
288 if(!(boost::math::isfinite)(y))
289 return -policies::raise_overflow_error<T>(function, 0, pol);
290 return y;
291 }
292
293 template <class T, class Policy>
294 inline T cyl_neumann_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
295 {
296 BOOST_MATH_STD_USING
297
298 BOOST_MATH_INSTRUMENT_VARIABLE(v);
299 BOOST_MATH_INSTRUMENT_VARIABLE(x);
300
301 if(floor(v) == v)
302 {
303 if(asymptotic_bessel_large_x_limit(v, x))
304 {
305 T r = asymptotic_bessel_y_large_x_2(static_cast<T>(abs(v)), x);
306 if((v < 0) && (itrunc(v, pol) & 1))
307 r = -r;
308 BOOST_MATH_INSTRUMENT_VARIABLE(r);
309 return r;
310 }
311 else
312 {
313 T r = bessel_yn(itrunc(v, pol), x, pol);
314 BOOST_MATH_INSTRUMENT_VARIABLE(r);
315 return r;
316 }
317 }
318 T r = cyl_neumann_imp<T>(v, x, bessel_no_int_tag(), pol);
319 BOOST_MATH_INSTRUMENT_VARIABLE(r);
320 return r;
321 }
322
323 template <class T, class Policy>
324 inline T cyl_neumann_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
325 {
326 BOOST_MATH_STD_USING
327
328 BOOST_MATH_INSTRUMENT_VARIABLE(v);
329 BOOST_MATH_INSTRUMENT_VARIABLE(x);
330
331 if(asymptotic_bessel_large_x_limit(T(v), x))
332 {
333 T r = asymptotic_bessel_y_large_x_2(static_cast<T>(abs(v)), x);
334 if((v < 0) && (v & 1))
335 r = -r;
336 return r;
337 }
338 else
339 return bessel_yn(v, x, pol);
340 }
341
342 template <class T, class Policy>
343 inline T sph_neumann_imp(unsigned v, T x, const Policy& pol)
344 {
345 BOOST_MATH_STD_USING // ADL of std names
346 static const char* function = "boost::math::sph_neumann<%1%>(%1%,%1%)";
347 //
348 // Nothing much to do here but check for errors, and
349 // evaluate the function's definition directly:
350 //
351 if(x < 0)
352 return policies::raise_domain_error<T>(
353 function,
354 "Got x = %1%, but function requires x > 0.", x, pol);
355
356 if(x < 2 * tools::min_value<T>())
357 return -policies::raise_overflow_error<T>(function, 0, pol);
358
359 T result = cyl_neumann_imp(T(T(v)+0.5f), x, bessel_no_int_tag(), pol);
360 T tx = sqrt(constants::pi<T>() / (2 * x));
361
362 if((tx > 1) && (tools::max_value<T>() / tx < result))
363 return -policies::raise_overflow_error<T>(function, 0, pol);
364
365 return result * tx;
366 }
367
368 template <class T, class Policy>
369 inline T cyl_bessel_j_zero_imp(T v, int m, const Policy& pol)
370 {
371 BOOST_MATH_STD_USING // ADL of std names, needed for floor.
372
373 static const char* function = "boost::math::cyl_bessel_j_zero<%1%>(%1%, int)";
374
375 const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
376
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
383 // Handle negative rank.
384 if(m < 0)
385 {
386 // Zeros of Jv(x) with negative rank are not defined and requesting one raises a domain error.
387 return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", m, pol);
388 }
389
390 // Get the absolute value of the order.
391 const bool order_is_negative = (v < 0);
392 const T vv((!order_is_negative) ? v : T(-v));
393
394 // Check if the order is very close to zero or very close to an integer.
395 const bool order_is_zero = (vv < half_epsilon);
396 const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
397
398 if(m == 0)
399 {
400 if(order_is_zero)
401 {
402 // The zero'th zero of J0(x) is not defined and requesting it raises a domain error.
403 return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of J0, but the rank must be > 0 !", m, pol);
404 }
405
406 // The zero'th zero of Jv(x) for v < 0 is not defined
407 // unless the order is a negative integer.
408 if(order_is_negative && (!order_is_integer))
409 {
410 // For non-integer, negative order, requesting the zero'th zero raises a domain error.
411 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);
412 }
413
414 // The zero'th zero does exist and its value is zero.
415 return T(0);
416 }
417
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_bessel_j_zero_detail::initial_guess<T, Policy>((order_is_integer ? vv : v), m, pol);
422
423 // Select the maximum allowed iterations from the policy.
424 boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
425
426 // Select the desired number of binary digits of precision.
427 // Account for the radix of number representations having non-two radix!
428 const int my_digits2 = policies::digits<T, Policy>();
429
430 const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
431
432 // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
433 const T jvm =
434 boost::math::tools::newton_raphson_iterate(
435 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),
436 guess_root,
437 T(guess_root - delta_lo),
438 T(guess_root + 0.2F),
439 my_digits2,
440 number_of_iterations);
441
442 if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
443 {
444 policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
445 " Current best guess is %1%", jvm, Policy());
446 }
447
448 return jvm;
449 }
450
451 template <class T, class Policy>
452 inline T cyl_neumann_zero_imp(T v, int m, const Policy& pol)
453 {
454 BOOST_MATH_STD_USING // ADL of std names, needed for floor.
455
456 static const char* function = "boost::math::cyl_neumann_zero<%1%>(%1%, int)";
457
458 // Handle non-finite order.
459 if (!(boost::math::isfinite)(v) )
460 {
461 return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
462 }
463
464 // Handle negative rank.
465 if(m < 0)
466 {
467 return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", m, pol);
468 }
469
470 const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
471
472 // Get the absolute value of the order.
473 const bool order_is_negative = (v < 0);
474 const T vv((!order_is_negative) ? v : T(-v));
475
476 const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
477
478 // For negative integers, use reflection to positive integer order.
479 if(order_is_negative && order_is_integer)
480 return boost::math::detail::cyl_neumann_zero_imp(vv, m, pol);
481
482 // Check if the order is very close to a negative half-integer.
483 const T delta_half_integer(vv - (floor(vv) + 0.5F));
484
485 const bool order_is_negative_half_integer =
486 (order_is_negative && ((delta_half_integer > -half_epsilon) && (delta_half_integer < +half_epsilon)));
487
488 // The zero'th zero of Yv(x) for v < 0 is not defined
489 // unless the order is a negative integer.
490 if((m == 0) && (!order_is_negative_half_integer))
491 {
492 // For non-integer, negative order, requesting the zero'th zero raises a domain error.
493 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);
494 }
495
496 // For negative half-integers, use the corresponding
497 // spherical Bessel function of positive half-integer order.
498 if(order_is_negative_half_integer)
499 return boost::math::detail::cyl_bessel_j_zero_imp(vv, m, pol);
500
501 // Set up the initial guess for the upcoming root-finding.
502 // If the order is a negative integer, then use the corresponding
503 // positive integer for the order.
504 const T guess_root = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess<T, Policy>(v, m, pol);
505
506 // Select the maximum allowed iterations from the policy.
507 boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
508
509 // Select the desired number of binary digits of precision.
510 // Account for the radix of number representations having non-two radix!
511 const int my_digits2 = policies::digits<T, Policy>();
512
513 const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
514
515 // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
516 const T yvm =
517 boost::math::tools::newton_raphson_iterate(
518 boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv_and_yv_prime<T, Policy>(v, pol),
519 guess_root,
520 T(guess_root - delta_lo),
521 T(guess_root + 0.2F),
522 my_digits2,
523 number_of_iterations);
524
525 if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
526 {
527 policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
528 " Current best guess is %1%", yvm, Policy());
529 }
530
531 return yvm;
532 }
533
534 } // namespace detail
535
536 template <class T1, class T2, class Policy>
537 inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j(T1 v, T2 x, const Policy& /* pol */)
538 {
539 BOOST_FPU_EXCEPTION_GUARD
540 typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
541 typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
542 typedef typename policies::evaluation<result_type, Policy>::type value_type;
543 typedef typename policies::normalise<
544 Policy,
545 policies::promote_float<false>,
546 policies::promote_double<false>,
547 policies::discrete_quantile<>,
548 policies::assert_undefined<> >::type forwarding_policy;
549 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%)");
550 }
551
552 template <class T1, class T2>
553 inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j(T1 v, T2 x)
554 {
555 return cyl_bessel_j(v, x, policies::policy<>());
556 }
557
558 template <class T, class Policy>
559 inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel(unsigned v, T x, const Policy& /* pol */)
560 {
561 BOOST_FPU_EXCEPTION_GUARD
562 typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
563 typedef typename policies::evaluation<result_type, Policy>::type value_type;
564 typedef typename policies::normalise<
565 Policy,
566 policies::promote_float<false>,
567 policies::promote_double<false>,
568 policies::discrete_quantile<>,
569 policies::assert_undefined<> >::type forwarding_policy;
570 return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_bessel<%1%>(%1%,%1%)");
571 }
572
573 template <class T>
574 inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel(unsigned v, T x)
575 {
576 return sph_bessel(v, x, policies::policy<>());
577 }
578
579 template <class T1, class T2, class Policy>
580 inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i(T1 v, T2 x, const Policy& /* pol */)
581 {
582 BOOST_FPU_EXCEPTION_GUARD
583 typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
584 typedef typename policies::evaluation<result_type, Policy>::type value_type;
585 typedef typename policies::normalise<
586 Policy,
587 policies::promote_float<false>,
588 policies::promote_double<false>,
589 policies::discrete_quantile<>,
590 policies::assert_undefined<> >::type forwarding_policy;
591 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%)");
592 }
593
594 template <class T1, class T2>
595 inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i(T1 v, T2 x)
596 {
597 return cyl_bessel_i(v, x, policies::policy<>());
598 }
599
600 template <class T1, class T2, class Policy>
601 inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k(T1 v, T2 x, const Policy& /* pol */)
602 {
603 BOOST_FPU_EXCEPTION_GUARD
604 typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
605 typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
606 typedef typename policies::evaluation<result_type, Policy>::type value_type;
607 typedef typename policies::normalise<
608 Policy,
609 policies::promote_float<false>,
610 policies::promote_double<false>,
611 policies::discrete_quantile<>,
612 policies::assert_undefined<> >::type forwarding_policy;
613 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%)");
614 }
615
616 template <class T1, class T2>
617 inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k(T1 v, T2 x)
618 {
619 return cyl_bessel_k(v, x, policies::policy<>());
620 }
621
622 template <class T1, class T2, class Policy>
623 inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann(T1 v, T2 x, const Policy& /* pol */)
624 {
625 BOOST_FPU_EXCEPTION_GUARD
626 typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
627 typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
628 typedef typename policies::evaluation<result_type, Policy>::type value_type;
629 typedef typename policies::normalise<
630 Policy,
631 policies::promote_float<false>,
632 policies::promote_double<false>,
633 policies::discrete_quantile<>,
634 policies::assert_undefined<> >::type forwarding_policy;
635 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%)");
636 }
637
638 template <class T1, class T2>
639 inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann(T1 v, T2 x)
640 {
641 return cyl_neumann(v, x, policies::policy<>());
642 }
643
644 template <class T, class Policy>
645 inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann(unsigned v, T x, const Policy& /* pol */)
646 {
647 BOOST_FPU_EXCEPTION_GUARD
648 typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
649 typedef typename policies::evaluation<result_type, Policy>::type value_type;
650 typedef typename policies::normalise<
651 Policy,
652 policies::promote_float<false>,
653 policies::promote_double<false>,
654 policies::discrete_quantile<>,
655 policies::assert_undefined<> >::type forwarding_policy;
656 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%)");
657 }
658
659 template <class T>
660 inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann(unsigned v, T x)
661 {
662 return sph_neumann(v, x, policies::policy<>());
663 }
664
665 template <class T, class Policy>
666 inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_bessel_j_zero(T v, int m, const Policy& /* pol */)
667 {
668 BOOST_FPU_EXCEPTION_GUARD
669 typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
670 typedef typename policies::evaluation<result_type, Policy>::type value_type;
671 typedef typename policies::normalise<
672 Policy,
673 policies::promote_float<false>,
674 policies::promote_double<false>,
675 policies::discrete_quantile<>,
676 policies::assert_undefined<> >::type forwarding_policy;
677 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<value_type>::is_integer, "Order must be a floating-point type.");
678 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%)");
679 }
680
681 template <class T>
682 inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_bessel_j_zero(T v, int m)
683 {
684 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<T>::is_integer, "Order must be a floating-point type.");
685 return cyl_bessel_j_zero<T, policies::policy<> >(v, m, policies::policy<>());
686 }
687
688 template <class T, class OutputIterator, class Policy>
689 inline OutputIterator cyl_bessel_j_zero(T v,
690 int start_index,
691 unsigned number_of_zeros,
692 OutputIterator out_it,
693 const Policy& pol)
694 {
695 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<T>::is_integer, "Order must be a floating-point type.");
696 for(unsigned i = 0; i < number_of_zeros; ++i)
697 {
698 *out_it = boost::math::cyl_bessel_j_zero(v, start_index + i, pol);
699 ++out_it;
700 }
701 return out_it;
702 }
703
704 template <class T, class OutputIterator>
705 inline OutputIterator cyl_bessel_j_zero(T v,
706 int start_index,
707 unsigned number_of_zeros,
708 OutputIterator out_it)
709 {
710 return cyl_bessel_j_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
711 }
712
713 template <class T, class Policy>
714 inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_neumann_zero(T v, int m, const Policy& /* pol */)
715 {
716 BOOST_FPU_EXCEPTION_GUARD
717 typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
718 typedef typename policies::evaluation<result_type, Policy>::type value_type;
719 typedef typename policies::normalise<
720 Policy,
721 policies::promote_float<false>,
722 policies::promote_double<false>,
723 policies::discrete_quantile<>,
724 policies::assert_undefined<> >::type forwarding_policy;
725 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<value_type>::is_integer, "Order must be a floating-point type.");
726 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%)");
727 }
728
729 template <class T>
730 inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_neumann_zero(T v, int m)
731 {
732 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<T>::is_integer, "Order must be a floating-point type.");
733 return cyl_neumann_zero<T, policies::policy<> >(v, m, policies::policy<>());
734 }
735
736 template <class T, class OutputIterator, class Policy>
737 inline OutputIterator cyl_neumann_zero(T v,
738 int start_index,
739 unsigned number_of_zeros,
740 OutputIterator out_it,
741 const Policy& pol)
742 {
743 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<T>::is_integer, "Order must be a floating-point type.");
744 for(unsigned i = 0; i < number_of_zeros; ++i)
745 {
746 *out_it = boost::math::cyl_neumann_zero(v, start_index + i, pol);
747 ++out_it;
748 }
749 return out_it;
750 }
751
752 template <class T, class OutputIterator>
753 inline OutputIterator cyl_neumann_zero(T v,
754 int start_index,
755 unsigned number_of_zeros,
756 OutputIterator out_it)
757 {
758 return cyl_neumann_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
759 }
760
761 } // namespace math
762 } // namespace boost
763
764 #endif // BOOST_MATH_BESSEL_HPP
765
766