// Copyright (c) 2013 Anton Bikineev // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_MATH_BESSEL_DERIVATIVES_HPP #define BOOST_MATH_BESSEL_DERIVATIVES_HPP #ifdef _MSC_VER # pragma once #endif #include #include #include #include #include namespace boost{ namespace math{ namespace detail{ template inline T cyl_bessel_j_prime_imp(T v, T x, const Policy& pol) { static const char* const function = "boost::math::cyl_bessel_j_prime<%1%>(%1%,%1%)"; BOOST_MATH_STD_USING // // Prevent complex result: // if (x < 0 && floor(v) != v) return boost::math::policies::raise_domain_error( function, "Got x = %1%, but function requires x >= 0", x, pol); // // Special cases for x == 0: // if (x == 0) { if (v == 1) return 0.5; else if (v == -1) return -0.5; else if (floor(v) == v || v > 1) return 0; else return boost::math::policies::raise_domain_error( function, "Got x = %1%, but function is indeterminate for this order", x, pol); } // // Special case for large x: use asymptotic expansion: // if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x)) return boost::math::detail::asymptotic_bessel_j_derivative_large_x_2(v, x, pol); // // Special case for small x: use Taylor series: // if ((abs(x) < 5) || (abs(v) > x * x / 4)) { bool inversed = false; if (floor(v) == v && v < 0) { v = -v; if (itrunc(v, pol) & 1) inversed = true; } T r = boost::math::detail::bessel_j_derivative_small_z_series(v, x, pol); return inversed ? T(-r) : r; } // // Special case for v == 0: // if (v == 0) return -boost::math::detail::cyl_bessel_j_imp(1, x, Tag(), pol); // // Default case: // return boost::math::detail::bessel_j_derivative_linear(v, x, Tag(), pol); } template inline T sph_bessel_j_prime_imp(unsigned v, T x, const Policy& pol) { static const char* const function = "boost::math::sph_bessel_prime<%1%>(%1%,%1%)"; // // Prevent complex result: // if (x < 0) return boost::math::policies::raise_domain_error( function, "Got x = %1%, but function requires x >= 0.", x, pol); // // Special case for v == 0: // if (v == 0) return (x == 0) ? boost::math::policies::raise_overflow_error(function, 0, pol) : static_cast(-boost::math::detail::sph_bessel_j_imp(1, x, pol)); // // Special case for x == 0 and v > 0: // if (x == 0) return boost::math::policies::raise_domain_error( function, "Got x = %1%, but function is indeterminate for this order", x, pol); // // Default case: // return boost::math::detail::sph_bessel_j_derivative_linear(v, x, pol); } template inline T cyl_bessel_i_prime_imp(T v, T x, const Policy& pol) { static const char* const function = "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)"; BOOST_MATH_STD_USING // // Prevent complex result: // if (x < 0 && floor(v) != v) return boost::math::policies::raise_domain_error( function, "Got x = %1%, but function requires x >= 0", x, pol); // // Special cases for x == 0: // if (x == 0) { if (v == 1 || v == -1) return 0.5; else if (floor(v) == v || v > 1) return 0; else return boost::math::policies::raise_domain_error( function, "Got x = %1%, but function is indeterminate for this order", x, pol); } // // Special case for v == 0: // if (v == 0) return boost::math::detail::cyl_bessel_i_imp(1, x, pol); // // Default case: // return boost::math::detail::bessel_i_derivative_linear(v, x, pol); } template inline T cyl_bessel_k_prime_imp(T v, T x, const Policy& pol) { // // Prevent complex and indeterminate results: // if (x <= 0) return boost::math::policies::raise_domain_error( "boost::math::cyl_bessel_k_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0", x, pol); // // Special case for v == 0: // if (v == 0) return -boost::math::detail::cyl_bessel_k_imp(1, x, Tag(), pol); // // Default case: // return boost::math::detail::bessel_k_derivative_linear(v, x, Tag(), pol); } template inline T cyl_neumann_prime_imp(T v, T x, const Policy& pol) { BOOST_MATH_STD_USING // // Prevent complex and indeterminate results: // if (x <= 0) return boost::math::policies::raise_domain_error( "boost::math::cyl_neumann_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0", x, pol); // // Special case for large x: use asymptotic expansion: // if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x)) return boost::math::detail::asymptotic_bessel_y_derivative_large_x_2(v, x, pol); // // Special case for small x: use Taylor series: // if (v > 0 && floor(v) != v) { const T eps = boost::math::policies::get_epsilon(); if (log(eps / 2) > v * log((x * x) / (v * 4))) return boost::math::detail::bessel_y_derivative_small_z_series(v, x, pol); } // // Special case for v == 0: // if (v == 0) return -boost::math::detail::cyl_neumann_imp(1, x, Tag(), pol); // // Default case: // return boost::math::detail::bessel_y_derivative_linear(v, x, Tag(), pol); } template inline T sph_neumann_prime_imp(unsigned v, T x, const Policy& pol) { // // Prevent complex and indeterminate result: // if (x <= 0) return boost::math::policies::raise_domain_error( "boost::math::sph_neumann_prime<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0.", x, pol); // // Special case for v == 0: // if (v == 0) return -boost::math::detail::sph_neumann_imp(1, x, pol); // // Default case: // return boost::math::detail::sph_neumann_derivative_linear(v, x, pol); } } // namespace detail template inline typename detail::bessel_traits::result_type cyl_bessel_j_prime(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD typedef typename detail::bessel_traits::result_type result_type; typedef typename detail::bessel_traits::optimisation_tag tag_type; typedef typename policies::evaluation::type value_type; typedef typename policies::normalise< Policy, policies::promote_float, policies::promote_double, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; return policies::checked_narrowing_cast(detail::cyl_bessel_j_prime_imp(static_cast(v), static_cast(x), forwarding_policy()), "boost::math::cyl_bessel_j_prime<%1%,%1%>(%1%,%1%)"); } template inline typename detail::bessel_traits >::result_type cyl_bessel_j_prime(T1 v, T2 x) { return cyl_bessel_j_prime(v, x, policies::policy<>()); } template inline typename detail::bessel_traits::result_type sph_bessel_prime(unsigned v, T x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD typedef typename detail::bessel_traits::result_type result_type; typedef typename policies::evaluation::type value_type; typedef typename policies::normalise< Policy, policies::promote_float, policies::promote_double, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; return policies::checked_narrowing_cast(detail::sph_bessel_j_prime_imp(v, static_cast(x), forwarding_policy()), "boost::math::sph_bessel_j_prime<%1%>(%1%,%1%)"); } template inline typename detail::bessel_traits >::result_type sph_bessel_prime(unsigned v, T x) { return sph_bessel_prime(v, x, policies::policy<>()); } template inline typename detail::bessel_traits::result_type cyl_bessel_i_prime(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD typedef typename detail::bessel_traits::result_type result_type; typedef typename policies::evaluation::type value_type; typedef typename policies::normalise< Policy, policies::promote_float, policies::promote_double, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; return policies::checked_narrowing_cast(detail::cyl_bessel_i_prime_imp(static_cast(v), static_cast(x), forwarding_policy()), "boost::math::cyl_bessel_i_prime<%1%>(%1%,%1%)"); } template inline typename detail::bessel_traits >::result_type cyl_bessel_i_prime(T1 v, T2 x) { return cyl_bessel_i_prime(v, x, policies::policy<>()); } template inline typename detail::bessel_traits::result_type cyl_bessel_k_prime(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD typedef typename detail::bessel_traits::result_type result_type; typedef typename detail::bessel_traits::optimisation_tag tag_type; typedef typename policies::evaluation::type value_type; typedef typename policies::normalise< Policy, policies::promote_float, policies::promote_double, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; return policies::checked_narrowing_cast(detail::cyl_bessel_k_prime_imp(static_cast(v), static_cast(x), forwarding_policy()), "boost::math::cyl_bessel_k_prime<%1%,%1%>(%1%,%1%)"); } template inline typename detail::bessel_traits >::result_type cyl_bessel_k_prime(T1 v, T2 x) { return cyl_bessel_k_prime(v, x, policies::policy<>()); } template inline typename detail::bessel_traits::result_type cyl_neumann_prime(T1 v, T2 x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD typedef typename detail::bessel_traits::result_type result_type; typedef typename detail::bessel_traits::optimisation_tag tag_type; typedef typename policies::evaluation::type value_type; typedef typename policies::normalise< Policy, policies::promote_float, policies::promote_double, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; return policies::checked_narrowing_cast(detail::cyl_neumann_prime_imp(static_cast(v), static_cast(x), forwarding_policy()), "boost::math::cyl_neumann_prime<%1%,%1%>(%1%,%1%)"); } template inline typename detail::bessel_traits >::result_type cyl_neumann_prime(T1 v, T2 x) { return cyl_neumann_prime(v, x, policies::policy<>()); } template inline typename detail::bessel_traits::result_type sph_neumann_prime(unsigned v, T x, const Policy& /* pol */) { BOOST_FPU_EXCEPTION_GUARD typedef typename detail::bessel_traits::result_type result_type; typedef typename policies::evaluation::type value_type; typedef typename policies::normalise< Policy, policies::promote_float, policies::promote_double, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; return policies::checked_narrowing_cast(detail::sph_neumann_prime_imp(v, static_cast(x), forwarding_policy()), "boost::math::sph_neumann_prime<%1%>(%1%,%1%)"); } template inline typename detail::bessel_traits >::result_type sph_neumann_prime(unsigned v, T x) { return sph_neumann_prime(v, x, policies::policy<>()); } } // namespace math } // namespace boost #endif // BOOST_MATH_BESSEL_DERIVATIVES_HPP