Chris@16
|
1 // Copyright (c) 2006 Xiaogang Zhang
|
Chris@16
|
2 // Use, modification and distribution are subject to the
|
Chris@16
|
3 // Boost Software License, Version 1.0. (See accompanying file
|
Chris@16
|
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #ifndef BOOST_MATH_BESSEL_JN_HPP
|
Chris@16
|
7 #define BOOST_MATH_BESSEL_JN_HPP
|
Chris@16
|
8
|
Chris@16
|
9 #ifdef _MSC_VER
|
Chris@16
|
10 #pragma once
|
Chris@16
|
11 #endif
|
Chris@16
|
12
|
Chris@16
|
13 #include <boost/math/special_functions/detail/bessel_j0.hpp>
|
Chris@16
|
14 #include <boost/math/special_functions/detail/bessel_j1.hpp>
|
Chris@16
|
15 #include <boost/math/special_functions/detail/bessel_jy.hpp>
|
Chris@16
|
16 #include <boost/math/special_functions/detail/bessel_jy_asym.hpp>
|
Chris@16
|
17 #include <boost/math/special_functions/detail/bessel_jy_series.hpp>
|
Chris@16
|
18
|
Chris@16
|
19 // Bessel function of the first kind of integer order
|
Chris@16
|
20 // J_n(z) is the minimal solution
|
Chris@16
|
21 // n < abs(z), forward recurrence stable and usable
|
Chris@16
|
22 // n >= abs(z), forward recurrence unstable, use Miller's algorithm
|
Chris@16
|
23
|
Chris@16
|
24 namespace boost { namespace math { namespace detail{
|
Chris@16
|
25
|
Chris@16
|
26 template <typename T, typename Policy>
|
Chris@16
|
27 T bessel_jn(int n, T x, const Policy& pol)
|
Chris@16
|
28 {
|
Chris@16
|
29 T value(0), factor, current, prev, next;
|
Chris@16
|
30
|
Chris@16
|
31 BOOST_MATH_STD_USING
|
Chris@16
|
32
|
Chris@16
|
33 //
|
Chris@16
|
34 // Reflection has to come first:
|
Chris@16
|
35 //
|
Chris@16
|
36 if (n < 0)
|
Chris@16
|
37 {
|
Chris@16
|
38 factor = (n & 0x1) ? -1 : 1; // J_{-n}(z) = (-1)^n J_n(z)
|
Chris@16
|
39 n = -n;
|
Chris@16
|
40 }
|
Chris@16
|
41 else
|
Chris@16
|
42 {
|
Chris@16
|
43 factor = 1;
|
Chris@16
|
44 }
|
Chris@16
|
45 if(x < 0)
|
Chris@16
|
46 {
|
Chris@16
|
47 factor *= (n & 0x1) ? -1 : 1; // J_{n}(-z) = (-1)^n J_n(z)
|
Chris@16
|
48 x = -x;
|
Chris@16
|
49 }
|
Chris@16
|
50 //
|
Chris@16
|
51 // Special cases:
|
Chris@16
|
52 //
|
Chris@16
|
53 if (n == 0)
|
Chris@16
|
54 {
|
Chris@16
|
55 return factor * bessel_j0(x);
|
Chris@16
|
56 }
|
Chris@16
|
57 if (n == 1)
|
Chris@16
|
58 {
|
Chris@16
|
59 return factor * bessel_j1(x);
|
Chris@16
|
60 }
|
Chris@16
|
61
|
Chris@16
|
62 if (x == 0) // n >= 2
|
Chris@16
|
63 {
|
Chris@16
|
64 return static_cast<T>(0);
|
Chris@16
|
65 }
|
Chris@16
|
66
|
Chris@16
|
67 if(asymptotic_bessel_large_x_limit(T(n), x))
|
Chris@16
|
68 return factor * asymptotic_bessel_j_large_x_2<T>(n, x);
|
Chris@16
|
69
|
Chris@16
|
70 BOOST_ASSERT(n > 1);
|
Chris@16
|
71 T scale = 1;
|
Chris@16
|
72 if (n < abs(x)) // forward recurrence
|
Chris@16
|
73 {
|
Chris@16
|
74 prev = bessel_j0(x);
|
Chris@16
|
75 current = bessel_j1(x);
|
Chris@16
|
76 policies::check_series_iterations<T>("boost::math::bessel_j_n<%1%>(%1%,%1%)", n, pol);
|
Chris@16
|
77 for (int k = 1; k < n; k++)
|
Chris@16
|
78 {
|
Chris@16
|
79 T fact = 2 * k / x;
|
Chris@16
|
80 //
|
Chris@16
|
81 // rescale if we would overflow or underflow:
|
Chris@16
|
82 //
|
Chris@16
|
83 if((fabs(fact) > 1) && ((tools::max_value<T>() - fabs(prev)) / fabs(fact) < fabs(current)))
|
Chris@16
|
84 {
|
Chris@16
|
85 scale /= current;
|
Chris@16
|
86 prev /= current;
|
Chris@16
|
87 current = 1;
|
Chris@16
|
88 }
|
Chris@16
|
89 value = fact * current - prev;
|
Chris@16
|
90 prev = current;
|
Chris@16
|
91 current = value;
|
Chris@16
|
92 }
|
Chris@16
|
93 }
|
Chris@16
|
94 else if((x < 1) || (n > x * x / 4) || (x < 5))
|
Chris@16
|
95 {
|
Chris@16
|
96 return factor * bessel_j_small_z_series(T(n), x, pol);
|
Chris@16
|
97 }
|
Chris@16
|
98 else // backward recurrence
|
Chris@16
|
99 {
|
Chris@16
|
100 T fn; int s; // fn = J_(n+1) / J_n
|
Chris@16
|
101 // |x| <= n, fast convergence for continued fraction CF1
|
Chris@16
|
102 boost::math::detail::CF1_jy(static_cast<T>(n), x, &fn, &s, pol);
|
Chris@16
|
103 prev = fn;
|
Chris@16
|
104 current = 1;
|
Chris@16
|
105 // Check recursion won't go on too far:
|
Chris@16
|
106 policies::check_series_iterations<T>("boost::math::bessel_j_n<%1%>(%1%,%1%)", n, pol);
|
Chris@16
|
107 for (int k = n; k > 0; k--)
|
Chris@16
|
108 {
|
Chris@16
|
109 T fact = 2 * k / x;
|
Chris@16
|
110 if((fabs(fact) > 1) && ((tools::max_value<T>() - fabs(prev)) / fabs(fact) < fabs(current)))
|
Chris@16
|
111 {
|
Chris@16
|
112 prev /= current;
|
Chris@16
|
113 scale /= current;
|
Chris@16
|
114 current = 1;
|
Chris@16
|
115 }
|
Chris@16
|
116 next = fact * current - prev;
|
Chris@16
|
117 prev = current;
|
Chris@16
|
118 current = next;
|
Chris@16
|
119 }
|
Chris@16
|
120 value = bessel_j0(x) / current; // normalization
|
Chris@16
|
121 scale = 1 / scale;
|
Chris@16
|
122 }
|
Chris@16
|
123 value *= factor;
|
Chris@16
|
124
|
Chris@16
|
125 if(tools::max_value<T>() * scale < fabs(value))
|
Chris@16
|
126 return policies::raise_overflow_error<T>("boost::math::bessel_jn<%1%>(%1%,%1%)", 0, pol);
|
Chris@16
|
127
|
Chris@16
|
128 return value / scale;
|
Chris@16
|
129 }
|
Chris@16
|
130
|
Chris@16
|
131 }}} // namespaces
|
Chris@16
|
132
|
Chris@16
|
133 #endif // BOOST_MATH_BESSEL_JN_HPP
|
Chris@16
|
134
|