T cyl_bessel_j_imp(T v, T x, const bessel_no_int_tag& t, const Policy& pol) { BOOST_MATH_STD_USING static const char* function = "boost::math::bessel_j<%1%>(%1%,%1%)"; if(x < 0) { // better have integer v: if(floor(v) == v) { T r = cyl_bessel_j_imp(v, T(-x), t, pol); if(iround(v, pol) & 1) r = -r; return r; } else return policies::raise_domain_error<T>( function, "Got x = %1%, but we need x >= 0", x, pol); } if(x == 0) return (v == 0) ? 1 : (v > 0) ? 0 : policies::raise_domain_error<T>( function, "Got v = %1%, but require v >= 0 or a negative integer: the result would be complex.", v, pol); if((v >= 0) && ((x < 1) || (v > x * x / 4))) { return bessel_j_small_z_series(v, x, pol); } T j, y; bessel_jy(v, x, &j, &y, need_j, pol); return j; }
T cyl_bessel_j_imp(T v, T x, const bessel_no_int_tag& t, const Policy& pol) { BOOST_MATH_STD_USING static const char* function = "boost::math::bessel_j<%1%>(%1%,%1%)"; if(x < 0) { // better have integer v: if(floor(v) == v) { T r = cyl_bessel_j_imp(v, T(-x), t, pol); if(iround(v, pol) & 1) r = -r; return r; } else return policies::raise_domain_error<T>( function, "Got x = %1%, but we need x >= 0", x, pol); } if(x == 0) return (v == 0) ? 1 : (v > 0) ? 0 : policies::raise_domain_error<T>( function, "Got v = %1%, but require v >= 0 or a negative integer: the result would be complex.", v, pol); if((v >= 0) && ((x < 1) || (v > x * x / 4) || (x < 5))) { // // This series will actually converge rapidly for all small // x - say up to x < 20 - but the first few terms are large // and divergent which leads to large errors :-( // return bessel_j_small_z_series(v, x, pol); } T j, y; bessel_jy(v, x, &j, &y, need_j, pol); return j; }
T bessel_jn(int n, T x, const Policy& pol) { T value(0), factor, current, prev, next; BOOST_MATH_STD_USING // // Reflection has to come first: // if (n < 0) { factor = static_cast<T>((n & 0x1) ? -1 : 1); // J_{-n}(z) = (-1)^n J_n(z) n = -n; } else { factor = 1; } if(x < 0) { factor *= (n & 0x1) ? -1 : 1; // J_{n}(-z) = (-1)^n J_n(z) x = -x; } // // Special cases: // if(asymptotic_bessel_large_x_limit(T(n), x)) return factor * asymptotic_bessel_j_large_x_2<T>(T(n), x); if (n == 0) { return factor * bessel_j0(x); } if (n == 1) { return factor * bessel_j1(x); } if (x == 0) // n >= 2 { return static_cast<T>(0); } BOOST_ASSERT(n > 1); T scale = 1; if (n < abs(x)) // forward recurrence { prev = bessel_j0(x); current = bessel_j1(x); policies::check_series_iterations<T>("boost::math::bessel_j_n<%1%>(%1%,%1%)", n, pol); for (int k = 1; k < n; k++) { T fact = 2 * k / x; // // rescale if we would overflow or underflow: // if((fabs(fact) > 1) && ((tools::max_value<T>() - fabs(prev)) / fabs(fact) < fabs(current))) { scale /= current; prev /= current; current = 1; } value = fact * current - prev; prev = current; current = value; } } else if((x < 1) || (n > x * x / 4) || (x < 5)) { return factor * bessel_j_small_z_series(T(n), x, pol); } else // backward recurrence { T fn; int s; // fn = J_(n+1) / J_n // |x| <= n, fast convergence for continued fraction CF1 boost::math::detail::CF1_jy(static_cast<T>(n), x, &fn, &s, pol); prev = fn; current = 1; // Check recursion won't go on too far: policies::check_series_iterations<T>("boost::math::bessel_j_n<%1%>(%1%,%1%)", n, pol); for (int k = n; k > 0; k--) { T fact = 2 * k / x; if((fabs(fact) > 1) && ((tools::max_value<T>() - fabs(prev)) / fabs(fact) < fabs(current))) { prev /= current; scale /= current; current = 1; } next = fact * current - prev; prev = current; current = next; } value = bessel_j0(x) / current; // normalization scale = 1 / scale; } value *= factor; if(tools::max_value<T>() * scale < fabs(value)) return policies::raise_overflow_error<T>("boost::math::bessel_jn<%1%>(%1%,%1%)", 0, pol); return value / scale; }