hypergeometric_cf.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright 2014 Anton Bikineev
  3. // Copyright 2014 Christopher Kormanyos
  4. // Copyright 2014 John Maddock
  5. // Copyright 2014 Paul Bristow
  6. // Distributed under the Boost
  7. // Software License, Version 1.0. (See accompanying file
  8. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_MATH_DETAIL_HYPERGEOMETRIC_CF_HPP
  11. #define BOOST_MATH_DETAIL_HYPERGEOMETRIC_CF_HPP
  12. namespace boost { namespace math { namespace detail {
  13. // primary template for term of continued fraction
  14. template <class T, unsigned p, unsigned q>
  15. struct hypergeometric_pFq_cf_term;
  16. // partial specialization for 0F1
  17. template <class T>
  18. struct hypergeometric_pFq_cf_term<T, 0u, 1u>
  19. {
  20. typedef std::pair<T,T> result_type;
  21. hypergeometric_pFq_cf_term(const T& b, const T& z):
  22. n(1), b(b), z(z),
  23. term(std::make_pair(T(0), T(1)))
  24. {
  25. }
  26. result_type operator()()
  27. {
  28. const result_type result = term;
  29. ++b; ++n;
  30. numer = -(z / (b * n));
  31. term = std::make_pair(numer, 1 - numer);
  32. return result;
  33. }
  34. private:
  35. unsigned n;
  36. T b;
  37. const T z;
  38. T numer;
  39. result_type term;
  40. };
  41. // partial specialization for 1F0
  42. template <class T>
  43. struct hypergeometric_pFq_cf_term<T, 1u, 0u>
  44. {
  45. typedef std::pair<T,T> result_type;
  46. hypergeometric_pFq_cf_term(const T& a, const T& z):
  47. n(1), a(a), z(z),
  48. term(std::make_pair(T(0), T(1)))
  49. {
  50. }
  51. result_type operator()()
  52. {
  53. const result_type result = term;
  54. ++a; ++n;
  55. numer = -((a * z) / n);
  56. term = std::make_pair(numer, 1 - numer);
  57. return result;
  58. }
  59. private:
  60. unsigned n;
  61. T a;
  62. const T z;
  63. T numer;
  64. result_type term;
  65. };
  66. // partial specialization for 1F1
  67. template <class T>
  68. struct hypergeometric_pFq_cf_term<T, 1u, 1u>
  69. {
  70. typedef std::pair<T,T> result_type;
  71. hypergeometric_pFq_cf_term(const T& a, const T& b, const T& z):
  72. n(1), a(a), b(b), z(z),
  73. term(std::make_pair(T(0), T(1)))
  74. {
  75. }
  76. result_type operator()()
  77. {
  78. const result_type result = term;
  79. ++a; ++b; ++n;
  80. numer = -((a * z) / (b * n));
  81. term = std::make_pair(numer, 1 - numer);
  82. return result;
  83. }
  84. private:
  85. unsigned n;
  86. T a, b;
  87. const T z;
  88. T numer;
  89. result_type term;
  90. };
  91. // partial specialization for 1f2
  92. template <class T>
  93. struct hypergeometric_pFq_cf_term<T, 1u, 2u>
  94. {
  95. typedef std::pair<T,T> result_type;
  96. hypergeometric_pFq_cf_term(const T& a, const T& b, const T& c, const T& z):
  97. n(1), a(a), b(b), c(c), z(z),
  98. term(std::make_pair(T(0), T(1)))
  99. {
  100. }
  101. result_type operator()()
  102. {
  103. const result_type result = term;
  104. ++a; ++b; ++c; ++n;
  105. numer = -((a * z) / ((b * c) * n));
  106. term = std::make_pair(numer, 1 - numer);
  107. return result;
  108. }
  109. private:
  110. unsigned n;
  111. T a, b, c;
  112. const T z;
  113. T numer;
  114. result_type term;
  115. };
  116. // partial specialization for 2f1
  117. template <class T>
  118. struct hypergeometric_pFq_cf_term<T, 2u, 1u>
  119. {
  120. typedef std::pair<T,T> result_type;
  121. hypergeometric_pFq_cf_term(const T& a, const T& b, const T& c, const T& z):
  122. n(1), a(a), b(b), c(c), z(z),
  123. term(std::make_pair(T(0), T(1)))
  124. {
  125. }
  126. result_type operator()()
  127. {
  128. const result_type result = term;
  129. ++a; ++b; ++c; ++n;
  130. numer = -(((a * b) * z) / (c * n));
  131. term = std::make_pair(numer, 1 - numer);
  132. return result;
  133. }
  134. private:
  135. unsigned n;
  136. T a, b, c;
  137. const T z;
  138. T numer;
  139. result_type term;
  140. };
  141. template <class T, unsigned p, unsigned q, class Policy>
  142. inline T compute_cf_pFq(detail::hypergeometric_pFq_cf_term<T, p, q>& term, const Policy& pol)
  143. {
  144. BOOST_MATH_STD_USING
  145. boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  146. const T result = tools::continued_fraction_b(
  147. term,
  148. boost::math::policies::get_epsilon<T, Policy>(),
  149. max_iter);
  150. boost::math::policies::check_series_iterations<T>(
  151. "boost::math::hypergeometric_pFq_cf<%1%>(%1%,%1%,%1%)",
  152. max_iter,
  153. pol);
  154. return result;
  155. }
  156. template <class T, class Policy>
  157. inline T hypergeometric_0F1_cf(const T& b, const T& z, const Policy& pol)
  158. {
  159. detail::hypergeometric_pFq_cf_term<T, 0u, 1u> f(b, z);
  160. T result = detail::compute_cf_pFq(f, pol);
  161. result = ((z / b) / result) + 1;
  162. return result;
  163. }
  164. template <class T, class Policy>
  165. inline T hypergeometric_1F0_cf(const T& a, const T& z, const Policy& pol)
  166. {
  167. detail::hypergeometric_pFq_cf_term<T, 1u, 0u> f(a, z);
  168. T result = detail::compute_cf_pFq(f, pol);
  169. result = ((a * z) / result) + 1;
  170. return result;
  171. }
  172. template <class T, class Policy>
  173. inline T hypergeometric_1F1_cf(const T& a, const T& b, const T& z, const Policy& pol)
  174. {
  175. detail::hypergeometric_pFq_cf_term<T, 1u, 1u> f(a, b, z);
  176. T result = detail::compute_cf_pFq(f, pol);
  177. result = (((a * z) / b) / result) + 1;
  178. return result;
  179. }
  180. template <class T, class Policy>
  181. inline T hypergeometric_1F2_cf(const T& a, const T& b, const T& c, const T& z, const Policy& pol)
  182. {
  183. detail::hypergeometric_pFq_cf_term<T, 1u, 2u> f(a, b, c, z);
  184. T result = detail::compute_cf_pFq(f, pol);
  185. result = (((a * z) / (b * c)) / result) + 1;
  186. return result;
  187. }
  188. template <class T, class Policy>
  189. inline T hypergeometric_2F1_cf(const T& a, const T& b, const T& c, const T& z, const Policy& pol)
  190. {
  191. detail::hypergeometric_pFq_cf_term<T, 2u, 1u> f(a, b, c, z);
  192. T result = detail::compute_cf_pFq(f, pol);
  193. result = ((((a * b) * z) / c) / result) + 1;
  194. return result;
  195. }
  196. } } } // namespaces
  197. #endif // BOOST_MATH_DETAIL_HYPERGEOMETRIC_CF_HPP