annotate DEPENDENCIES/generic/include/boost/math/special_functions/airy.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
Chris@16 1 // Copyright John Maddock 2012.
Chris@16 2 // Use, modification and distribution are subject to the
Chris@16 3 // Boost Software License, Version 1.0.
Chris@16 4 // (See accompanying file LICENSE_1_0.txt
Chris@16 5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6
Chris@16 7 #ifndef BOOST_MATH_AIRY_HPP
Chris@16 8 #define BOOST_MATH_AIRY_HPP
Chris@16 9
Chris@16 10 #include <boost/math/special_functions/bessel.hpp>
Chris@16 11 #include <boost/math/special_functions/cbrt.hpp>
Chris@16 12 #include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp>
Chris@16 13 #include <boost/math/tools/roots.hpp>
Chris@16 14
Chris@16 15 namespace boost{ namespace math{
Chris@16 16
Chris@16 17 namespace detail{
Chris@16 18
Chris@16 19 template <class T, class Policy>
Chris@16 20 T airy_ai_imp(T x, const Policy& pol)
Chris@16 21 {
Chris@16 22 BOOST_MATH_STD_USING
Chris@16 23
Chris@16 24 if(x < 0)
Chris@16 25 {
Chris@16 26 T p = (-x * sqrt(-x) * 2) / 3;
Chris@16 27 T v = T(1) / 3;
Chris@16 28 T j1 = boost::math::cyl_bessel_j(v, p, pol);
Chris@16 29 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
Chris@16 30 T ai = sqrt(-x) * (j1 + j2) / 3;
Chris@16 31 //T bi = sqrt(-x / 3) * (j2 - j1);
Chris@16 32 return ai;
Chris@16 33 }
Chris@16 34 else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
Chris@16 35 {
Chris@16 36 T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
Chris@16 37 T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
Chris@16 38 //T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg);
Chris@16 39 return ai;
Chris@16 40 }
Chris@16 41 else
Chris@16 42 {
Chris@16 43 T p = 2 * x * sqrt(x) / 3;
Chris@16 44 T v = T(1) / 3;
Chris@16 45 //T j1 = boost::math::cyl_bessel_i(-v, p, pol);
Chris@16 46 //T j2 = boost::math::cyl_bessel_i(v, p, pol);
Chris@16 47 //
Chris@16 48 // Note that although we can calculate ai from j1 and j2, the accuracy is horrible
Chris@16 49 // as we're subtracting two very large values, so use the Bessel K relation instead:
Chris@16 50 //
Chris@16 51 T ai = cyl_bessel_k(v, p, pol) * sqrt(x / 3) / boost::math::constants::pi<T>(); //sqrt(x) * (j1 - j2) / 3;
Chris@16 52 //T bi = sqrt(x / 3) * (j1 + j2);
Chris@16 53 return ai;
Chris@16 54 }
Chris@16 55 }
Chris@16 56
Chris@16 57 template <class T, class Policy>
Chris@16 58 T airy_bi_imp(T x, const Policy& pol)
Chris@16 59 {
Chris@16 60 BOOST_MATH_STD_USING
Chris@16 61
Chris@16 62 if(x < 0)
Chris@16 63 {
Chris@16 64 T p = (-x * sqrt(-x) * 2) / 3;
Chris@16 65 T v = T(1) / 3;
Chris@16 66 T j1 = boost::math::cyl_bessel_j(v, p, pol);
Chris@16 67 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
Chris@16 68 //T ai = sqrt(-x) * (j1 + j2) / 3;
Chris@16 69 T bi = sqrt(-x / 3) * (j2 - j1);
Chris@16 70 return bi;
Chris@16 71 }
Chris@16 72 else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
Chris@16 73 {
Chris@16 74 T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
Chris@16 75 //T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
Chris@16 76 T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg);
Chris@16 77 return bi;
Chris@16 78 }
Chris@16 79 else
Chris@16 80 {
Chris@16 81 T p = 2 * x * sqrt(x) / 3;
Chris@16 82 T v = T(1) / 3;
Chris@16 83 T j1 = boost::math::cyl_bessel_i(-v, p, pol);
Chris@16 84 T j2 = boost::math::cyl_bessel_i(v, p, pol);
Chris@16 85 T bi = sqrt(x / 3) * (j1 + j2);
Chris@16 86 return bi;
Chris@16 87 }
Chris@16 88 }
Chris@16 89
Chris@16 90 template <class T, class Policy>
Chris@16 91 T airy_ai_prime_imp(T x, const Policy& pol)
Chris@16 92 {
Chris@16 93 BOOST_MATH_STD_USING
Chris@16 94
Chris@16 95 if(x < 0)
Chris@16 96 {
Chris@16 97 T p = (-x * sqrt(-x) * 2) / 3;
Chris@16 98 T v = T(2) / 3;
Chris@16 99 T j1 = boost::math::cyl_bessel_j(v, p, pol);
Chris@16 100 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
Chris@16 101 T aip = -x * (j1 - j2) / 3;
Chris@16 102 return aip;
Chris@16 103 }
Chris@16 104 else if(fabs(x * x) / 2 < tools::epsilon<T>())
Chris@16 105 {
Chris@16 106 T tg = boost::math::tgamma(constants::third<T>(), pol);
Chris@16 107 T aip = 1 / (boost::math::cbrt(T(3)) * tg);
Chris@16 108 return -aip;
Chris@16 109 }
Chris@16 110 else
Chris@16 111 {
Chris@16 112 T p = 2 * x * sqrt(x) / 3;
Chris@16 113 T v = T(2) / 3;
Chris@16 114 //T j1 = boost::math::cyl_bessel_i(-v, p, pol);
Chris@16 115 //T j2 = boost::math::cyl_bessel_i(v, p, pol);
Chris@16 116 //
Chris@16 117 // Note that although we can calculate ai from j1 and j2, the accuracy is horrible
Chris@16 118 // as we're subtracting two very large values, so use the Bessel K relation instead:
Chris@16 119 //
Chris@16 120 T aip = -cyl_bessel_k(v, p, pol) * x / (boost::math::constants::root_three<T>() * boost::math::constants::pi<T>());
Chris@16 121 return aip;
Chris@16 122 }
Chris@16 123 }
Chris@16 124
Chris@16 125 template <class T, class Policy>
Chris@16 126 T airy_bi_prime_imp(T x, const Policy& pol)
Chris@16 127 {
Chris@16 128 BOOST_MATH_STD_USING
Chris@16 129
Chris@16 130 if(x < 0)
Chris@16 131 {
Chris@16 132 T p = (-x * sqrt(-x) * 2) / 3;
Chris@16 133 T v = T(2) / 3;
Chris@16 134 T j1 = boost::math::cyl_bessel_j(v, p, pol);
Chris@16 135 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
Chris@16 136 T aip = -x * (j1 + j2) / constants::root_three<T>();
Chris@16 137 return aip;
Chris@16 138 }
Chris@16 139 else if(fabs(x * x) / 2 < tools::epsilon<T>())
Chris@16 140 {
Chris@16 141 T tg = boost::math::tgamma(constants::third<T>(), pol);
Chris@16 142 T bip = sqrt(boost::math::cbrt(T(3))) / tg;
Chris@16 143 return bip;
Chris@16 144 }
Chris@16 145 else
Chris@16 146 {
Chris@16 147 T p = 2 * x * sqrt(x) / 3;
Chris@16 148 T v = T(2) / 3;
Chris@16 149 T j1 = boost::math::cyl_bessel_i(-v, p, pol);
Chris@16 150 T j2 = boost::math::cyl_bessel_i(v, p, pol);
Chris@16 151 T aip = x * (j1 + j2) / boost::math::constants::root_three<T>();
Chris@16 152 return aip;
Chris@16 153 }
Chris@16 154 }
Chris@16 155
Chris@16 156 template <class T, class Policy>
Chris@16 157 T airy_ai_zero_imp(unsigned m, const Policy& pol)
Chris@16 158 {
Chris@16 159 BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
Chris@16 160
Chris@16 161 // Handle case when the zero'th zero is requested.
Chris@16 162 if(m == 0U)
Chris@16 163 {
Chris@16 164 return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%,%1%)",
Chris@16 165 "The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
Chris@16 166 }
Chris@16 167
Chris@16 168 // Set up the initial guess for the upcoming root-finding.
Chris@16 169 const T guess_root = boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m);
Chris@16 170
Chris@16 171 // Select the maximum allowed iterations, being at least 24.
Chris@16 172 boost::uintmax_t number_of_iterations = (std::max)(24, int(std::numeric_limits<T>::digits10));
Chris@16 173
Chris@16 174 // Select the desired number of binary digits of precision.
Chris@16 175 // Account for the radix of number representations having non-two radix!
Chris@16 176 const int my_digits2 = int(float(std::numeric_limits<T>::digits)
Chris@16 177 * ( log(float(std::numeric_limits<T>::radix))
Chris@16 178 / log(2.0F)));
Chris@16 179
Chris@16 180 // Use a dynamic tolerance because the roots get closer the higher m gets.
Chris@16 181 T tolerance;
Chris@16 182
Chris@16 183 if (m <= 10U) { tolerance = T(0.3F); }
Chris@16 184 else if(m <= 100U) { tolerance = T(0.1F); }
Chris@16 185 else if(m <= 1000U) { tolerance = T(0.05F); }
Chris@16 186 else { tolerance = T(1) / sqrt(T(m)); }
Chris@16 187
Chris@16 188 // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
Chris@16 189 const T am =
Chris@16 190 boost::math::tools::newton_raphson_iterate(
Chris@16 191 boost::math::detail::airy_zero::airy_ai_zero_detail::function_object_ai_and_ai_prime<T, Policy>(pol),
Chris@16 192 guess_root,
Chris@16 193 T(guess_root - tolerance),
Chris@16 194 T(guess_root + tolerance),
Chris@16 195 my_digits2,
Chris@16 196 number_of_iterations);
Chris@16 197
Chris@16 198 static_cast<void>(number_of_iterations);
Chris@16 199
Chris@16 200 return am;
Chris@16 201 }
Chris@16 202
Chris@16 203 template <class T, class Policy>
Chris@16 204 T airy_bi_zero_imp(unsigned m, const Policy& pol)
Chris@16 205 {
Chris@16 206 BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
Chris@16 207
Chris@16 208 // Handle case when the zero'th zero is requested.
Chris@16 209 if(m == 0U)
Chris@16 210 {
Chris@16 211 return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%,%1%)",
Chris@16 212 "The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
Chris@16 213 }
Chris@16 214 // Set up the initial guess for the upcoming root-finding.
Chris@16 215 const T guess_root = boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m);
Chris@16 216
Chris@16 217 // Select the maximum allowed iterations, being at least 24.
Chris@16 218 boost::uintmax_t number_of_iterations = (std::max)(24, int(std::numeric_limits<T>::digits10));
Chris@16 219
Chris@16 220 // Select the desired number of binary digits of precision.
Chris@16 221 // Account for the radix of number representations having non-two radix!
Chris@16 222 const int my_digits2 = int(float(std::numeric_limits<T>::digits)
Chris@16 223 * ( log(float(std::numeric_limits<T>::radix))
Chris@16 224 / log(2.0F)));
Chris@16 225
Chris@16 226 // Use a dynamic tolerance because the roots get closer the higher m gets.
Chris@16 227 T tolerance;
Chris@16 228
Chris@16 229 if (m <= 10U) { tolerance = T(0.3F); }
Chris@16 230 else if(m <= 100U) { tolerance = T(0.1F); }
Chris@16 231 else if(m <= 1000U) { tolerance = T(0.05F); }
Chris@16 232 else { tolerance = T(1) / sqrt(T(m)); }
Chris@16 233
Chris@16 234 // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
Chris@16 235 const T bm =
Chris@16 236 boost::math::tools::newton_raphson_iterate(
Chris@16 237 boost::math::detail::airy_zero::airy_bi_zero_detail::function_object_bi_and_bi_prime<T, Policy>(pol),
Chris@16 238 guess_root,
Chris@16 239 T(guess_root - tolerance),
Chris@16 240 T(guess_root + tolerance),
Chris@16 241 my_digits2,
Chris@16 242 number_of_iterations);
Chris@16 243
Chris@16 244 static_cast<void>(number_of_iterations);
Chris@16 245
Chris@16 246 return bm;
Chris@16 247 }
Chris@16 248
Chris@16 249 } // namespace detail
Chris@16 250
Chris@16 251 template <class T, class Policy>
Chris@16 252 inline typename tools::promote_args<T>::type airy_ai(T x, const Policy&)
Chris@16 253 {
Chris@16 254 BOOST_FPU_EXCEPTION_GUARD
Chris@16 255 typedef typename tools::promote_args<T>::type result_type;
Chris@16 256 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 257 typedef typename policies::normalise<
Chris@16 258 Policy,
Chris@16 259 policies::promote_float<false>,
Chris@16 260 policies::promote_double<false>,
Chris@16 261 policies::discrete_quantile<>,
Chris@16 262 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 263
Chris@16 264 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%)");
Chris@16 265 }
Chris@16 266
Chris@16 267 template <class T>
Chris@16 268 inline typename tools::promote_args<T>::type airy_ai(T x)
Chris@16 269 {
Chris@16 270 return airy_ai(x, policies::policy<>());
Chris@16 271 }
Chris@16 272
Chris@16 273 template <class T, class Policy>
Chris@16 274 inline typename tools::promote_args<T>::type airy_bi(T x, const Policy&)
Chris@16 275 {
Chris@16 276 BOOST_FPU_EXCEPTION_GUARD
Chris@16 277 typedef typename tools::promote_args<T>::type result_type;
Chris@16 278 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 279 typedef typename policies::normalise<
Chris@16 280 Policy,
Chris@16 281 policies::promote_float<false>,
Chris@16 282 policies::promote_double<false>,
Chris@16 283 policies::discrete_quantile<>,
Chris@16 284 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 285
Chris@16 286 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%)");
Chris@16 287 }
Chris@16 288
Chris@16 289 template <class T>
Chris@16 290 inline typename tools::promote_args<T>::type airy_bi(T x)
Chris@16 291 {
Chris@16 292 return airy_bi(x, policies::policy<>());
Chris@16 293 }
Chris@16 294
Chris@16 295 template <class T, class Policy>
Chris@16 296 inline typename tools::promote_args<T>::type airy_ai_prime(T x, const Policy&)
Chris@16 297 {
Chris@16 298 BOOST_FPU_EXCEPTION_GUARD
Chris@16 299 typedef typename tools::promote_args<T>::type result_type;
Chris@16 300 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 301 typedef typename policies::normalise<
Chris@16 302 Policy,
Chris@16 303 policies::promote_float<false>,
Chris@16 304 policies::promote_double<false>,
Chris@16 305 policies::discrete_quantile<>,
Chris@16 306 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 307
Chris@16 308 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%)");
Chris@16 309 }
Chris@16 310
Chris@16 311 template <class T>
Chris@16 312 inline typename tools::promote_args<T>::type airy_ai_prime(T x)
Chris@16 313 {
Chris@16 314 return airy_ai_prime(x, policies::policy<>());
Chris@16 315 }
Chris@16 316
Chris@16 317 template <class T, class Policy>
Chris@16 318 inline typename tools::promote_args<T>::type airy_bi_prime(T x, const Policy&)
Chris@16 319 {
Chris@16 320 BOOST_FPU_EXCEPTION_GUARD
Chris@16 321 typedef typename tools::promote_args<T>::type result_type;
Chris@16 322 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 323 typedef typename policies::normalise<
Chris@16 324 Policy,
Chris@16 325 policies::promote_float<false>,
Chris@16 326 policies::promote_double<false>,
Chris@16 327 policies::discrete_quantile<>,
Chris@16 328 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 329
Chris@16 330 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%)");
Chris@16 331 }
Chris@16 332
Chris@16 333 template <class T>
Chris@16 334 inline typename tools::promote_args<T>::type airy_bi_prime(T x)
Chris@16 335 {
Chris@16 336 return airy_bi_prime(x, policies::policy<>());
Chris@16 337 }
Chris@16 338
Chris@16 339 template <class T, class Policy>
Chris@16 340 inline T airy_ai_zero(unsigned m, const Policy& /*pol*/)
Chris@16 341 {
Chris@16 342 BOOST_FPU_EXCEPTION_GUARD
Chris@16 343 typedef typename policies::evaluation<T, Policy>::type value_type;
Chris@16 344 typedef typename policies::normalise<
Chris@16 345 Policy,
Chris@16 346 policies::promote_float<false>,
Chris@16 347 policies::promote_double<false>,
Chris@16 348 policies::discrete_quantile<>,
Chris@16 349 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 350 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<T>::is_integer, "Airy return type must be a floating-point type.");
Chris@16 351 return policies::checked_narrowing_cast<T, Policy>(detail::airy_ai_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_ai_zero<%1%>(unsigned)");
Chris@16 352 }
Chris@16 353
Chris@16 354 template <class T>
Chris@16 355 inline T airy_ai_zero(unsigned m)
Chris@16 356 {
Chris@16 357 return airy_ai_zero<T>(m, policies::policy<>());
Chris@16 358 }
Chris@16 359
Chris@16 360 template <class T, class OutputIterator, class Policy>
Chris@16 361 inline OutputIterator airy_ai_zero(
Chris@16 362 unsigned start_index,
Chris@16 363 unsigned number_of_zeros,
Chris@16 364 OutputIterator out_it,
Chris@16 365 const Policy& pol)
Chris@16 366 {
Chris@16 367 typedef T result_type;
Chris@16 368 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<result_type>::is_integer, "Airy return type must be a floating-point type.");
Chris@16 369
Chris@16 370 for(unsigned i = 0; i < number_of_zeros; ++i)
Chris@16 371 {
Chris@16 372 *out_it = boost::math::airy_ai_zero<result_type>(start_index + i, pol);
Chris@16 373 ++out_it;
Chris@16 374 }
Chris@16 375 return out_it;
Chris@16 376 }
Chris@16 377
Chris@16 378 template <class T, class OutputIterator>
Chris@16 379 inline OutputIterator airy_ai_zero(
Chris@16 380 unsigned start_index,
Chris@16 381 unsigned number_of_zeros,
Chris@16 382 OutputIterator out_it)
Chris@16 383 {
Chris@16 384 return airy_ai_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
Chris@16 385 }
Chris@16 386
Chris@16 387 template <class T, class Policy>
Chris@16 388 inline T airy_bi_zero(unsigned m, const Policy& /*pol*/)
Chris@16 389 {
Chris@16 390 BOOST_FPU_EXCEPTION_GUARD
Chris@16 391 typedef typename policies::evaluation<T, Policy>::type value_type;
Chris@16 392 typedef typename policies::normalise<
Chris@16 393 Policy,
Chris@16 394 policies::promote_float<false>,
Chris@16 395 policies::promote_double<false>,
Chris@16 396 policies::discrete_quantile<>,
Chris@16 397 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 398 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<T>::is_integer, "Airy return type must be a floating-point type.");
Chris@16 399 return policies::checked_narrowing_cast<T, Policy>(detail::airy_bi_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_bi_zero<%1%>(unsigned)");
Chris@16 400 }
Chris@16 401
Chris@16 402 template <typename T>
Chris@16 403 inline T airy_bi_zero(unsigned m)
Chris@16 404 {
Chris@16 405 return airy_bi_zero<T>(m, policies::policy<>());
Chris@16 406 }
Chris@16 407
Chris@16 408 template <class T, class OutputIterator, class Policy>
Chris@16 409 inline OutputIterator airy_bi_zero(
Chris@16 410 unsigned start_index,
Chris@16 411 unsigned number_of_zeros,
Chris@16 412 OutputIterator out_it,
Chris@16 413 const Policy& pol)
Chris@16 414 {
Chris@16 415 typedef T result_type;
Chris@16 416 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<result_type>::is_integer, "Airy return type must be a floating-point type.");
Chris@16 417
Chris@16 418 for(unsigned i = 0; i < number_of_zeros; ++i)
Chris@16 419 {
Chris@16 420 *out_it = boost::math::airy_bi_zero<result_type>(start_index + i, pol);
Chris@16 421 ++out_it;
Chris@16 422 }
Chris@16 423 return out_it;
Chris@16 424 }
Chris@16 425
Chris@16 426 template <class T, class OutputIterator>
Chris@16 427 inline OutputIterator airy_bi_zero(
Chris@16 428 unsigned start_index,
Chris@16 429 unsigned number_of_zeros,
Chris@16 430 OutputIterator out_it)
Chris@16 431 {
Chris@16 432 return airy_bi_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
Chris@16 433 }
Chris@16 434
Chris@16 435 }} // namespaces
Chris@16 436
Chris@16 437 #endif // BOOST_MATH_AIRY_HPP