File indexing completed on 2025-01-18 09:40:00
0001
0002
0003
0004
0005
0006 #ifndef BOOST_MATH_BESSEL_JN_SERIES_HPP
0007 #define BOOST_MATH_BESSEL_JN_SERIES_HPP
0008
0009 #ifdef _MSC_VER
0010 #pragma once
0011 #endif
0012
0013 #include <cmath>
0014 #include <cstdint>
0015 #include <boost/math/tools/config.hpp>
0016 #include <boost/math/tools/assert.hpp>
0017
0018 namespace boost { namespace math { namespace detail{
0019
0020 template <class T, class Policy>
0021 struct bessel_j_small_z_series_term
0022 {
0023 typedef T result_type;
0024
0025 bessel_j_small_z_series_term(T v_, T x)
0026 : N(0), v(v_)
0027 {
0028 BOOST_MATH_STD_USING
0029 mult = x / 2;
0030 mult *= -mult;
0031 term = 1;
0032 }
0033 T operator()()
0034 {
0035 T r = term;
0036 ++N;
0037 term *= mult / (N * (N + v));
0038 return r;
0039 }
0040 private:
0041 unsigned N;
0042 T v;
0043 T mult;
0044 T term;
0045 };
0046
0047
0048
0049
0050
0051 template <class T, class Policy>
0052 inline T bessel_j_small_z_series(T v, T x, const Policy& pol)
0053 {
0054 BOOST_MATH_STD_USING
0055 T prefix;
0056 if(v < max_factorial<T>::value)
0057 {
0058 prefix = pow(x / 2, v) / boost::math::tgamma(v+1, pol);
0059 }
0060 else
0061 {
0062 prefix = v * log(x / 2) - boost::math::lgamma(v+1, pol);
0063 prefix = exp(prefix);
0064 }
0065 if(0 == prefix)
0066 return prefix;
0067
0068 bessel_j_small_z_series_term<T, Policy> s(v, x);
0069 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0070
0071 T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
0072
0073 policies::check_series_iterations<T>("boost::math::bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
0074 return prefix * result;
0075 }
0076
0077 template <class T, class Policy>
0078 struct bessel_y_small_z_series_term_a
0079 {
0080 typedef T result_type;
0081
0082 bessel_y_small_z_series_term_a(T v_, T x)
0083 : N(0), v(v_)
0084 {
0085 BOOST_MATH_STD_USING
0086 mult = x / 2;
0087 mult *= -mult;
0088 term = 1;
0089 }
0090 T operator()()
0091 {
0092 BOOST_MATH_STD_USING
0093 T r = term;
0094 ++N;
0095 term *= mult / (N * (N - v));
0096 return r;
0097 }
0098 private:
0099 unsigned N;
0100 T v;
0101 T mult;
0102 T term;
0103 };
0104
0105 template <class T, class Policy>
0106 struct bessel_y_small_z_series_term_b
0107 {
0108 typedef T result_type;
0109
0110 bessel_y_small_z_series_term_b(T v_, T x)
0111 : N(0), v(v_)
0112 {
0113 BOOST_MATH_STD_USING
0114 mult = x / 2;
0115 mult *= -mult;
0116 term = 1;
0117 }
0118 T operator()()
0119 {
0120 T r = term;
0121 ++N;
0122 term *= mult / (N * (N + v));
0123 return r;
0124 }
0125 private:
0126 unsigned N;
0127 T v;
0128 T mult;
0129 T term;
0130 };
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 template <class T, class Policy>
0141 inline T bessel_y_small_z_series(T v, T x, T* pscale, const Policy& pol)
0142 {
0143 BOOST_MATH_STD_USING
0144 static const char* function = "bessel_y_small_z_series<%1%>(%1%,%1%)";
0145 T prefix;
0146 T gam;
0147 T p = log(x / 2);
0148 T scale = 1;
0149 bool need_logs = (v >= max_factorial<T>::value) || (tools::log_max_value<T>() / v < fabs(p));
0150 if(!need_logs)
0151 {
0152 gam = boost::math::tgamma(v, pol);
0153 p = pow(x / 2, v);
0154 if(tools::max_value<T>() * p < gam)
0155 {
0156 scale /= gam;
0157 gam = 1;
0158 if(tools::max_value<T>() * p < gam)
0159 {
0160 return -policies::raise_overflow_error<T>(function, nullptr, pol);
0161 }
0162 }
0163 prefix = -gam / (constants::pi<T>() * p);
0164 }
0165 else
0166 {
0167 gam = boost::math::lgamma(v, pol);
0168 p = v * p;
0169 prefix = gam - log(constants::pi<T>()) - p;
0170 if(tools::log_max_value<T>() < prefix)
0171 {
0172 prefix -= log(tools::max_value<T>() / 4);
0173 scale /= (tools::max_value<T>() / 4);
0174 if(tools::log_max_value<T>() < prefix)
0175 {
0176 return -policies::raise_overflow_error<T>(function, nullptr, pol);
0177 }
0178 }
0179 prefix = -exp(prefix);
0180 }
0181 bessel_y_small_z_series_term_a<T, Policy> s(v, x);
0182 std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
0183 *pscale = scale;
0184
0185 T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
0186
0187 policies::check_series_iterations<T>("boost::math::bessel_y_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
0188 result *= prefix;
0189
0190 if(!need_logs)
0191 {
0192 prefix = boost::math::tgamma(-v, pol) * boost::math::cos_pi(v, pol) * p / constants::pi<T>();
0193 }
0194 else
0195 {
0196 int sgn {};
0197 prefix = boost::math::lgamma(-v, &sgn, pol) + p;
0198 prefix = exp(prefix) * sgn / constants::pi<T>();
0199 }
0200 bessel_y_small_z_series_term_b<T, Policy> s2(v, x);
0201 max_iter = policies::get_max_series_iterations<Policy>();
0202
0203 T b = boost::math::tools::sum_series(s2, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
0204
0205 result -= scale * prefix * b;
0206 return result;
0207 }
0208
0209 template <class T, class Policy>
0210 T bessel_yn_small_z(int n, T z, T* scale, const Policy& pol)
0211 {
0212
0213
0214
0215
0216
0217 BOOST_MATH_STD_USING
0218 BOOST_MATH_ASSERT(n >= 0);
0219 BOOST_MATH_ASSERT((z < policies::get_epsilon<T, Policy>()));
0220
0221 if(n == 0)
0222 {
0223 return (2 / constants::pi<T>()) * (log(z / 2) + constants::euler<T>());
0224 }
0225 else if(n == 1)
0226 {
0227 return (z / constants::pi<T>()) * log(z / 2)
0228 - 2 / (constants::pi<T>() * z)
0229 - (z / (2 * constants::pi<T>())) * (1 - 2 * constants::euler<T>());
0230 }
0231 else if(n == 2)
0232 {
0233 return (z * z) / (4 * constants::pi<T>()) * log(z / 2)
0234 - (4 / (constants::pi<T>() * z * z))
0235 - ((z * z) / (8 * constants::pi<T>())) * (T(3)/2 - 2 * constants::euler<T>());
0236 }
0237 else
0238 {
0239 #if (defined(__GNUC__) && __GNUC__ == 13)
0240 auto p = static_cast<T>(pow(z / 2, T(n)));
0241 #else
0242 auto p = static_cast<T>(pow(z / 2, n));
0243 #endif
0244
0245 T result = -((boost::math::factorial<T>(n - 1, pol) / constants::pi<T>()));
0246 if(p * tools::max_value<T>() < result)
0247 {
0248 T div = tools::max_value<T>() / 8;
0249 result /= div;
0250 *scale /= div;
0251 if(p * tools::max_value<T>() < result)
0252 {
0253 return -policies::raise_overflow_error<T>("bessel_yn_small_z<%1%>(%1%,%1%)", nullptr, pol);
0254 }
0255 }
0256 return result / p;
0257 }
0258 }
0259
0260 }}}
0261
0262 #endif
0263