File indexing completed on 2025-09-15 08:40:08
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MATH_AIRY_HPP
0009 #define BOOST_MATH_AIRY_HPP
0010
0011 #include <boost/math/tools/config.hpp>
0012 #include <boost/math/tools/numeric_limits.hpp>
0013 #include <boost/math/tools/precision.hpp>
0014 #include <boost/math/tools/cstdint.hpp>
0015 #include <boost/math/special_functions/math_fwd.hpp>
0016 #include <boost/math/special_functions/bessel.hpp>
0017 #include <boost/math/special_functions/cbrt.hpp>
0018 #include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp>
0019 #include <boost/math/tools/roots.hpp>
0020 #include <boost/math/policies/error_handling.hpp>
0021 #include <boost/math/constants/constants.hpp>
0022
0023 namespace boost{ namespace math{
0024
0025 namespace detail{
0026
0027 template <class T, class Policy>
0028 BOOST_MATH_GPU_ENABLED T airy_ai_imp(T x, const Policy& pol)
0029 {
0030 BOOST_MATH_STD_USING
0031
0032 if(x < 0)
0033 {
0034 T p = (-x * sqrt(-x) * 2) / 3;
0035 T v = T(1) / 3;
0036 T j1 = boost::math::cyl_bessel_j(v, p, pol);
0037 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
0038 T ai = sqrt(-x) * (j1 + j2) / 3;
0039
0040 return ai;
0041 }
0042 else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
0043 {
0044 T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
0045 T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
0046
0047 return ai;
0048 }
0049 else
0050 {
0051 T p = 2 * x * sqrt(x) / 3;
0052 T v = T(1) / 3;
0053
0054
0055
0056
0057
0058
0059 T ai = cyl_bessel_k(v, p, pol) * sqrt(x / 3) / boost::math::constants::pi<T>();
0060
0061 return ai;
0062 }
0063 }
0064
0065 template <class T, class Policy>
0066 BOOST_MATH_GPU_ENABLED T airy_bi_imp(T x, const Policy& pol)
0067 {
0068 BOOST_MATH_STD_USING
0069
0070 if(x < 0)
0071 {
0072 T p = (-x * sqrt(-x) * 2) / 3;
0073 T v = T(1) / 3;
0074 T j1 = boost::math::cyl_bessel_j(v, p, pol);
0075 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
0076
0077 T bi = sqrt(-x / 3) * (j2 - j1);
0078 return bi;
0079 }
0080 else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
0081 {
0082 T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
0083
0084 T bi = 1 / (sqrt(boost::math::cbrt(T(3), pol)) * tg);
0085 return bi;
0086 }
0087 else
0088 {
0089 T p = 2 * x * sqrt(x) / 3;
0090 T v = T(1) / 3;
0091 T j1 = boost::math::cyl_bessel_i(-v, p, pol);
0092 T j2 = boost::math::cyl_bessel_i(v, p, pol);
0093 T bi = sqrt(x / 3) * (j1 + j2);
0094 return bi;
0095 }
0096 }
0097
0098 template <class T, class Policy>
0099 BOOST_MATH_GPU_ENABLED T airy_ai_prime_imp(T x, const Policy& pol)
0100 {
0101 BOOST_MATH_STD_USING
0102
0103 if(x < 0)
0104 {
0105 T p = (-x * sqrt(-x) * 2) / 3;
0106 T v = T(2) / 3;
0107 T j1 = boost::math::cyl_bessel_j(v, p, pol);
0108 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
0109 T aip = -x * (j1 - j2) / 3;
0110 return aip;
0111 }
0112 else if(fabs(x * x) / 2 < tools::epsilon<T>())
0113 {
0114 T tg = boost::math::tgamma(constants::third<T>(), pol);
0115 T aip = 1 / (boost::math::cbrt(T(3), pol) * tg);
0116 return -aip;
0117 }
0118 else
0119 {
0120 T p = 2 * x * sqrt(x) / 3;
0121 T v = T(2) / 3;
0122
0123
0124
0125
0126
0127
0128 T aip = -cyl_bessel_k(v, p, pol) * x / (boost::math::constants::root_three<T>() * boost::math::constants::pi<T>());
0129 return aip;
0130 }
0131 }
0132
0133 template <class T, class Policy>
0134 BOOST_MATH_GPU_ENABLED T airy_bi_prime_imp(T x, const Policy& pol)
0135 {
0136 BOOST_MATH_STD_USING
0137
0138 if(x < 0)
0139 {
0140 T p = (-x * sqrt(-x) * 2) / 3;
0141 T v = T(2) / 3;
0142 T j1 = boost::math::cyl_bessel_j(v, p, pol);
0143 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
0144 T aip = -x * (j1 + j2) / constants::root_three<T>();
0145 return aip;
0146 }
0147 else if(fabs(x * x) / 2 < tools::epsilon<T>())
0148 {
0149 T tg = boost::math::tgamma(constants::third<T>(), pol);
0150 T bip = sqrt(boost::math::cbrt(T(3), pol)) / tg;
0151 return bip;
0152 }
0153 else
0154 {
0155 T p = 2 * x * sqrt(x) / 3;
0156 T v = T(2) / 3;
0157 T j1 = boost::math::cyl_bessel_i(-v, p, pol);
0158 T j2 = boost::math::cyl_bessel_i(v, p, pol);
0159 T aip = x * (j1 + j2) / boost::math::constants::root_three<T>();
0160 return aip;
0161 }
0162 }
0163
0164 template <class T, class Policy>
0165 BOOST_MATH_GPU_ENABLED T airy_ai_zero_imp(int m, const Policy& pol)
0166 {
0167 BOOST_MATH_STD_USING
0168
0169
0170 if(m < 0)
0171 {
0172 return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%, int)",
0173 "Requested the %1%'th zero, but the rank must be 1 or more !", static_cast<T>(m), pol);
0174 }
0175
0176
0177 if(m == 0U)
0178 {
0179 return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%,%1%)",
0180 "The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
0181 }
0182
0183
0184 const T guess_root = boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m, pol);
0185
0186
0187
0188 const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
0189
0190 const std::uintmax_t iterations_allowed = static_cast<std::uintmax_t>((std::max)(12, my_digits10 * 2));
0191
0192 std::uintmax_t iterations_used = iterations_allowed;
0193
0194
0195 T tolerance;
0196
0197 if (m <= 10) { tolerance = T(0.3F); }
0198 else if(m <= 100) { tolerance = T(0.1F); }
0199 else if(m <= 1000) { tolerance = T(0.05F); }
0200 else { tolerance = T(1) / sqrt(T(m)); }
0201
0202
0203 const T am =
0204 boost::math::tools::newton_raphson_iterate(
0205 boost::math::detail::airy_zero::airy_ai_zero_detail::function_object_ai_and_ai_prime<T, Policy>(pol),
0206 guess_root,
0207 T(guess_root - tolerance),
0208 T(guess_root + tolerance),
0209 policies::digits<T, Policy>(),
0210 iterations_used);
0211
0212 static_cast<void>(iterations_used);
0213
0214 return am;
0215 }
0216
0217 template <class T, class Policy>
0218 BOOST_MATH_GPU_ENABLED T airy_bi_zero_imp(int m, const Policy& pol)
0219 {
0220 BOOST_MATH_STD_USING
0221
0222
0223 if(m < 0)
0224 {
0225 return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%, int)",
0226 "Requested the %1%'th zero, but the rank must 1 or more !", static_cast<T>(m), pol);
0227 }
0228
0229
0230 if(m == 0U)
0231 {
0232 return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%,%1%)",
0233 "The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
0234 }
0235
0236 const T guess_root = boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m, pol);
0237
0238
0239
0240 const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
0241
0242 const std::uintmax_t iterations_allowed = static_cast<std::uintmax_t>((std::max)(12, my_digits10 * 2));
0243
0244 std::uintmax_t iterations_used = iterations_allowed;
0245
0246
0247 T tolerance;
0248
0249 if (m <= 10) { tolerance = T(0.3F); }
0250 else if(m <= 100) { tolerance = T(0.1F); }
0251 else if(m <= 1000) { tolerance = T(0.05F); }
0252 else { tolerance = T(1) / sqrt(T(m)); }
0253
0254
0255 const T bm =
0256 boost::math::tools::newton_raphson_iterate(
0257 boost::math::detail::airy_zero::airy_bi_zero_detail::function_object_bi_and_bi_prime<T, Policy>(pol),
0258 guess_root,
0259 T(guess_root - tolerance),
0260 T(guess_root + tolerance),
0261 policies::digits<T, Policy>(),
0262 iterations_used);
0263
0264 static_cast<void>(iterations_used);
0265
0266 return bm;
0267 }
0268
0269 }
0270
0271 template <class T, class Policy>
0272 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type airy_ai(T x, const Policy&)
0273 {
0274 BOOST_FPU_EXCEPTION_GUARD
0275 typedef typename tools::promote_args<T>::type result_type;
0276 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0277 typedef typename policies::normalise<
0278 Policy,
0279 policies::promote_float<false>,
0280 policies::promote_double<false>,
0281 policies::discrete_quantile<>,
0282 policies::assert_undefined<> >::type forwarding_policy;
0283
0284 return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_ai_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
0285 }
0286
0287 template <class T>
0288 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type airy_ai(T x)
0289 {
0290 return airy_ai(x, policies::policy<>());
0291 }
0292
0293 template <class T, class Policy>
0294 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type airy_bi(T x, const Policy&)
0295 {
0296 BOOST_FPU_EXCEPTION_GUARD
0297 typedef typename tools::promote_args<T>::type result_type;
0298 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0299 typedef typename policies::normalise<
0300 Policy,
0301 policies::promote_float<false>,
0302 policies::promote_double<false>,
0303 policies::discrete_quantile<>,
0304 policies::assert_undefined<> >::type forwarding_policy;
0305
0306 return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_bi_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
0307 }
0308
0309 template <class T>
0310 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type airy_bi(T x)
0311 {
0312 return airy_bi(x, policies::policy<>());
0313 }
0314
0315 template <class T, class Policy>
0316 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type airy_ai_prime(T x, const Policy&)
0317 {
0318 BOOST_FPU_EXCEPTION_GUARD
0319 typedef typename tools::promote_args<T>::type result_type;
0320 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0321 typedef typename policies::normalise<
0322 Policy,
0323 policies::promote_float<false>,
0324 policies::promote_double<false>,
0325 policies::discrete_quantile<>,
0326 policies::assert_undefined<> >::type forwarding_policy;
0327
0328 return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_ai_prime_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
0329 }
0330
0331 template <class T>
0332 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type airy_ai_prime(T x)
0333 {
0334 return airy_ai_prime(x, policies::policy<>());
0335 }
0336
0337 template <class T, class Policy>
0338 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type airy_bi_prime(T x, const Policy&)
0339 {
0340 BOOST_FPU_EXCEPTION_GUARD
0341 typedef typename tools::promote_args<T>::type result_type;
0342 typedef typename policies::evaluation<result_type, Policy>::type value_type;
0343 typedef typename policies::normalise<
0344 Policy,
0345 policies::promote_float<false>,
0346 policies::promote_double<false>,
0347 policies::discrete_quantile<>,
0348 policies::assert_undefined<> >::type forwarding_policy;
0349
0350 return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_bi_prime_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
0351 }
0352
0353 template <class T>
0354 BOOST_MATH_GPU_ENABLED inline typename tools::promote_args<T>::type airy_bi_prime(T x)
0355 {
0356 return airy_bi_prime(x, policies::policy<>());
0357 }
0358
0359 template <class T, class Policy>
0360 BOOST_MATH_GPU_ENABLED inline T airy_ai_zero(int m, const Policy& )
0361 {
0362 BOOST_FPU_EXCEPTION_GUARD
0363 typedef typename policies::evaluation<T, Policy>::type value_type;
0364 typedef typename policies::normalise<
0365 Policy,
0366 policies::promote_float<false>,
0367 policies::promote_double<false>,
0368 policies::discrete_quantile<>,
0369 policies::assert_undefined<> >::type forwarding_policy;
0370
0371 static_assert( false == std::numeric_limits<T>::is_specialized
0372 || ( true == std::numeric_limits<T>::is_specialized
0373 && false == std::numeric_limits<T>::is_integer),
0374 "Airy value type must be a floating-point type.");
0375
0376 return policies::checked_narrowing_cast<T, Policy>(detail::airy_ai_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_ai_zero<%1%>(unsigned)");
0377 }
0378
0379 template <class T>
0380 BOOST_MATH_GPU_ENABLED inline T airy_ai_zero(int m)
0381 {
0382 return airy_ai_zero<T>(m, policies::policy<>());
0383 }
0384
0385 template <class T, class OutputIterator, class Policy>
0386 BOOST_MATH_GPU_ENABLED inline OutputIterator airy_ai_zero(
0387 int start_index,
0388 unsigned number_of_zeros,
0389 OutputIterator out_it,
0390 const Policy& pol)
0391 {
0392 typedef T result_type;
0393
0394 static_assert( false == std::numeric_limits<T>::is_specialized
0395 || ( true == std::numeric_limits<T>::is_specialized
0396 && false == std::numeric_limits<T>::is_integer),
0397 "Airy value type must be a floating-point type.");
0398
0399 for(unsigned i = 0; i < number_of_zeros; ++i)
0400 {
0401 *out_it = boost::math::airy_ai_zero<result_type>(start_index + i, pol);
0402 ++out_it;
0403 }
0404 return out_it;
0405 }
0406
0407 template <class T, class OutputIterator>
0408 BOOST_MATH_GPU_ENABLED inline OutputIterator airy_ai_zero(
0409 int start_index,
0410 unsigned number_of_zeros,
0411 OutputIterator out_it)
0412 {
0413 return airy_ai_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
0414 }
0415
0416 template <class T, class Policy>
0417 BOOST_MATH_GPU_ENABLED inline T airy_bi_zero(int m, const Policy& )
0418 {
0419 BOOST_FPU_EXCEPTION_GUARD
0420 typedef typename policies::evaluation<T, Policy>::type value_type;
0421 typedef typename policies::normalise<
0422 Policy,
0423 policies::promote_float<false>,
0424 policies::promote_double<false>,
0425 policies::discrete_quantile<>,
0426 policies::assert_undefined<> >::type forwarding_policy;
0427
0428 static_assert( false == std::numeric_limits<T>::is_specialized
0429 || ( true == std::numeric_limits<T>::is_specialized
0430 && false == std::numeric_limits<T>::is_integer),
0431 "Airy value type must be a floating-point type.");
0432
0433 return policies::checked_narrowing_cast<T, Policy>(detail::airy_bi_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_bi_zero<%1%>(unsigned)");
0434 }
0435
0436 template <typename T>
0437 BOOST_MATH_GPU_ENABLED inline T airy_bi_zero(int m)
0438 {
0439 return airy_bi_zero<T>(m, policies::policy<>());
0440 }
0441
0442 template <class T, class OutputIterator, class Policy>
0443 BOOST_MATH_GPU_ENABLED inline OutputIterator airy_bi_zero(
0444 int start_index,
0445 unsigned number_of_zeros,
0446 OutputIterator out_it,
0447 const Policy& pol)
0448 {
0449 typedef T result_type;
0450
0451 static_assert( false == std::numeric_limits<T>::is_specialized
0452 || ( true == std::numeric_limits<T>::is_specialized
0453 && false == std::numeric_limits<T>::is_integer),
0454 "Airy value type must be a floating-point type.");
0455
0456 for(unsigned i = 0; i < number_of_zeros; ++i)
0457 {
0458 *out_it = boost::math::airy_bi_zero<result_type>(start_index + i, pol);
0459 ++out_it;
0460 }
0461 return out_it;
0462 }
0463
0464 template <class T, class OutputIterator>
0465 BOOST_MATH_GPU_ENABLED inline OutputIterator airy_bi_zero(
0466 int start_index,
0467 unsigned number_of_zeros,
0468 OutputIterator out_it)
0469 {
0470 return airy_bi_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
0471 }
0472
0473 }}
0474
0475 #endif