airy_ai_bi_zero.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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 BOOST_MATH_AIRY_AI_BI_ZERO_2013_01_20_HPP_
  14. #define BOOST_MATH_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, class Policy>
  32. T equation_as_10_4_105(const T& z, const Policy& pol)
  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, pol));
  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, class Policy>
  50. T initial_guess(const int m, const Policy& pol)
  51. {
  52. T guess;
  53. switch(m)
  54. {
  55. case 0:
  56. guess = T(0);
  57. break;
  58. case 1:
  59. guess = T(-2.33810741045976703849);
  60. break;
  61. case 2:
  62. guess = T(-4.08794944413097061664);
  63. break;
  64. case 3:
  65. guess = T(-5.52055982809555105913);
  66. break;
  67. case 4:
  68. guess = T(-6.78670809007175899878);
  69. break;
  70. case 5:
  71. guess = T(-7.94413358712085312314);
  72. break;
  73. case 6:
  74. guess = T(-9.02265085334098038016);
  75. break;
  76. case 7:
  77. guess = T(-10.0401743415580859306);
  78. break;
  79. case 8:
  80. guess = T(-11.0085243037332628932);
  81. break;
  82. case 9:
  83. guess = T(-11.9360155632362625170);
  84. break;
  85. case 10:
  86. guess = T(-12.8287767528657572004);
  87. break;
  88. default:
  89. const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 1)) / 8);
  90. guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t, pol);
  91. break;
  92. }
  93. return guess;
  94. }
  95. template<class T, class Policy>
  96. class function_object_ai_and_ai_prime
  97. {
  98. public:
  99. explicit function_object_ai_and_ai_prime(const Policy& pol) : my_pol(pol) { }
  100. function_object_ai_and_ai_prime(const function_object_ai_and_ai_prime&) = default;
  101. boost::math::tuple<T, T> operator()(const T& x) const
  102. {
  103. // Return a tuple containing both Ai(x) and Ai'(x).
  104. return boost::math::make_tuple(
  105. boost::math::detail::airy_ai_imp (x, my_pol),
  106. boost::math::detail::airy_ai_prime_imp(x, my_pol));
  107. }
  108. private:
  109. const Policy& my_pol;
  110. const function_object_ai_and_ai_prime& operator=(const function_object_ai_and_ai_prime&) = delete;
  111. };
  112. } // namespace airy_ai_zero_detail
  113. namespace airy_bi_zero_detail
  114. {
  115. template<class T, class Policy>
  116. T initial_guess(const int m, const Policy& pol)
  117. {
  118. T guess;
  119. switch(m)
  120. {
  121. case 0:
  122. guess = T(0);
  123. break;
  124. case 1:
  125. guess = T(-1.17371322270912792492);
  126. break;
  127. case 2:
  128. guess = T(-3.27109330283635271568);
  129. break;
  130. case 3:
  131. guess = T(-4.83073784166201593267);
  132. break;
  133. case 4:
  134. guess = T(-6.16985212831025125983);
  135. break;
  136. case 5:
  137. guess = T(-7.37676207936776371360);
  138. break;
  139. case 6:
  140. guess = T(-8.49194884650938801345);
  141. break;
  142. case 7:
  143. guess = T(-9.53819437934623888663);
  144. break;
  145. case 8:
  146. guess = T(-10.5299135067053579244);
  147. break;
  148. case 9:
  149. guess = T(-11.4769535512787794379);
  150. break;
  151. case 10:
  152. guess = T(-12.3864171385827387456);
  153. break;
  154. default:
  155. const T t(((boost::math::constants::pi<T>() * 3) * ((T(m) * 4) - 3)) / 8);
  156. guess = -boost::math::detail::airy_zero::equation_as_10_4_105(t, pol);
  157. break;
  158. }
  159. return guess;
  160. }
  161. template<class T, class Policy>
  162. class function_object_bi_and_bi_prime
  163. {
  164. public:
  165. explicit function_object_bi_and_bi_prime(const Policy& pol) : my_pol(pol) { }
  166. function_object_bi_and_bi_prime(const function_object_bi_and_bi_prime&) = default;
  167. boost::math::tuple<T, T> operator()(const T& x) const
  168. {
  169. // Return a tuple containing both Bi(x) and Bi'(x).
  170. return boost::math::make_tuple(
  171. boost::math::detail::airy_bi_imp (x, my_pol),
  172. boost::math::detail::airy_bi_prime_imp(x, my_pol));
  173. }
  174. private:
  175. const Policy& my_pol;
  176. const function_object_bi_and_bi_prime& operator=(const function_object_bi_and_bi_prime&) = delete;
  177. };
  178. } // namespace airy_bi_zero_detail
  179. } // namespace airy_zero
  180. } // namespace detail
  181. } // namespace math
  182. } // namespaces boost
  183. #endif // BOOST_MATH_AIRY_AI_BI_ZERO_2013_01_20_HPP_