airy_ai_bi_zero.hpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright (c) 2013 Christopher Kormanyos
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. //
  6. // This work is based on an earlier work:
  7. // "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations",
  8. // in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469
  9. //
  10. // This header contains implementation details for estimating the zeros
  11. // of the Airy functions airy_ai and airy_bi on the negative real axis.
  12. //
  13. #ifndef _AIRY_AI_BI_ZERO_2013_01_20_HPP_
  14. #define _AIRY_AI_BI_ZERO_2013_01_20_HPP_
  15. #include <boost/math/constants/constants.hpp>
  16. #include <boost/math/special_functions/cbrt.hpp>
  17. namespace boost { namespace math {
  18. namespace detail
  19. {
  20. // Forward declarations of the needed Airy function implementations.
  21. template <class T, class Policy>
  22. T airy_ai_imp(T x, const Policy& pol);
  23. template <class T, class Policy>
  24. T airy_bi_imp(T x, const Policy& pol);
  25. template <class T, class Policy>
  26. T airy_ai_prime_imp(T x, const Policy& pol);
  27. template <class T, class Policy>
  28. T airy_bi_prime_imp(T x, const Policy& pol);
  29. namespace airy_zero
  30. {
  31. template<class T>
  32. T equation_as_10_4_105(const T& z)
  33. {
  34. const T one_over_z (T(1) / z);
  35. const T one_over_z_squared(one_over_z * one_over_z);
  36. const T z_pow_third (boost::math::cbrt(z));
  37. const T z_pow_two_thirds(z_pow_third * z_pow_third);
  38. // Implement the top line of Eq. 10.4.105.
  39. const T fz(z_pow_two_thirds * ((((( + (T(162375596875.0) / 334430208UL)
  40. * one_over_z_squared - ( T(108056875.0) / 6967296UL))
  41. * one_over_z_squared + ( T(77125UL) / 82944UL))
  42. * one_over_z_squared - ( T(5U) / 36U))
  43. * one_over_z_squared + ( T(5U) / 48U))
  44. * one_over_z_squared + (1)));
  45. return fz;
  46. }
  47. namespace airy_ai_zero_detail
  48. {
  49. template<class T>
  50. T initial_guess(const int m)
  51. {
  52. T guess;
  53. switch(m)
  54. {
  55. case 0: { guess = T(0); break; }
  56. case 1: { guess = T(-2.33810741045976703849); break; }
  57. case 2: { guess = T(-4.08794944413097061664); break; }
  58. case 3: { guess = T(-5.52055982809555105913); break; }
  59. case 4: { guess = T(-6.78670809007175899878); break; }
  60. case 5: { guess = T(-7.94413358712085312314); break; }
  61. case 6: { guess = T(-9.02265085334098038016); break; }
  62. case 7: { guess = T(-10.0401743415580859306); break; }
  63. case 8: { guess = T(-11.0085243037332628932); break; }
  64. case 9: { guess = T(-11.9360155632362625170); break; }
  65. case 10:{ guess = T(-12.8287767528657572004); break; }
  66. default:
  67. {
  68. const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 1)) / 8);
  69. guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t);
  70. break;
  71. }
  72. }
  73. return guess;
  74. }
  75. template<class T, class Policy>
  76. class function_object_ai_and_ai_prime
  77. {
  78. public:
  79. function_object_ai_and_ai_prime(const Policy& pol) : my_pol(pol) { }
  80. boost::math::tuple<T, T> operator()(const T& x) const
  81. {
  82. // Return a tuple containing both Ai(x) and Ai'(x).
  83. return boost::math::make_tuple(
  84. boost::math::detail::airy_ai_imp (x, my_pol),
  85. boost::math::detail::airy_ai_prime_imp(x, my_pol));
  86. }
  87. private:
  88. const Policy& my_pol;
  89. const function_object_ai_and_ai_prime& operator=(const function_object_ai_and_ai_prime&);
  90. };
  91. } // namespace airy_ai_zero_detail
  92. namespace airy_bi_zero_detail
  93. {
  94. template<class T>
  95. T initial_guess(const int m)
  96. {
  97. T guess;
  98. switch(m)
  99. {
  100. case 0: { guess = T(0); break; }
  101. case 1: { guess = T(-1.17371322270912792492); break; }
  102. case 2: { guess = T(-3.27109330283635271568); break; }
  103. case 3: { guess = T(-4.83073784166201593267); break; }
  104. case 4: { guess = T(-6.16985212831025125983); break; }
  105. case 5: { guess = T(-7.37676207936776371360); break; }
  106. case 6: { guess = T(-8.49194884650938801345); break; }
  107. case 7: { guess = T(-9.53819437934623888663); break; }
  108. case 8: { guess = T(-10.5299135067053579244); break; }
  109. case 9: { guess = T(-11.4769535512787794379); break; }
  110. case 10: { guess = T(-12.3864171385827387456); break; }
  111. default:
  112. {
  113. const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 3)) / 8);
  114. guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t);
  115. break;
  116. }
  117. }
  118. return guess;
  119. }
  120. template<class T, class Policy>
  121. class function_object_bi_and_bi_prime
  122. {
  123. public:
  124. function_object_bi_and_bi_prime(const Policy& pol) : my_pol(pol) { }
  125. boost::math::tuple<T, T> operator()(const T& x) const
  126. {
  127. // Return a tuple containing both Bi(x) and Bi'(x).
  128. return boost::math::make_tuple(
  129. boost::math::detail::airy_bi_imp (x, my_pol),
  130. boost::math::detail::airy_bi_prime_imp(x, my_pol));
  131. }
  132. private:
  133. const Policy& my_pol;
  134. const function_object_bi_and_bi_prime& operator=(const function_object_bi_and_bi_prime&);
  135. };
  136. } // namespace airy_bi_zero_detail
  137. } // namespace airy_zero
  138. } // namespace detail
  139. } // namespace math
  140. } // namespaces boost
  141. #endif // _AIRY_AI_BI_ZERO_2013_01_20_HPP_