continued_fractions.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // (C) Copyright John Maddock 2018.
  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. #include <boost/math/tools/fraction.hpp>
  6. #include <iostream>
  7. #include <complex>
  8. #include <boost/multiprecision/cpp_complex.hpp>
  9. //[golden_ratio_1
  10. template <class T>
  11. struct golden_ratio_fraction
  12. {
  13. typedef T result_type;
  14. result_type operator()()
  15. {
  16. return 1;
  17. }
  18. };
  19. //]
  20. //[cf_tan_fraction
  21. template <class T>
  22. struct tan_fraction
  23. {
  24. private:
  25. T a, b;
  26. public:
  27. tan_fraction(T v)
  28. : a(-v * v), b(-1)
  29. {}
  30. typedef std::pair<T, T> result_type;
  31. std::pair<T, T> operator()()
  32. {
  33. b += 2;
  34. return std::make_pair(a, b);
  35. }
  36. };
  37. //]
  38. //[cf_tan
  39. template <class T>
  40. T tan(T a)
  41. {
  42. tan_fraction<T> fract(a);
  43. return a / continued_fraction_b(fract, std::numeric_limits<T>::epsilon());
  44. }
  45. //]
  46. //[cf_expint_fraction
  47. template <class T>
  48. struct expint_fraction
  49. {
  50. typedef std::pair<T, T> result_type;
  51. expint_fraction(unsigned n_, T z_) : b(z_ + T(n_)), i(-1), n(n_) {}
  52. std::pair<T, T> operator()()
  53. {
  54. std::pair<T, T> result = std::make_pair(-static_cast<T>((i + 1) * (n + i)), b);
  55. b += 2;
  56. ++i;
  57. return result;
  58. }
  59. private:
  60. T b;
  61. int i;
  62. unsigned n;
  63. };
  64. //]
  65. //[cf_expint
  66. template <class T>
  67. inline std::complex<T> expint_as_fraction(unsigned n, std::complex<T> const& z)
  68. {
  69. boost::uintmax_t max_iter = 1000;
  70. expint_fraction<std::complex<T> > f(n, z);
  71. std::complex<T> result = boost::math::tools::continued_fraction_b(
  72. f,
  73. std::complex<T>(std::numeric_limits<T>::epsilon()),
  74. max_iter);
  75. result = exp(-z) / result;
  76. return result;
  77. }
  78. //]
  79. //[cf_upper_gamma_fraction
  80. template <class T>
  81. struct upper_incomplete_gamma_fract
  82. {
  83. private:
  84. typedef typename T::value_type scalar_type;
  85. T z, a;
  86. int k;
  87. public:
  88. typedef std::pair<T, T> result_type;
  89. upper_incomplete_gamma_fract(T a1, T z1)
  90. : z(z1 - a1 + scalar_type(1)), a(a1), k(0)
  91. {
  92. }
  93. result_type operator()()
  94. {
  95. ++k;
  96. z += scalar_type(2);
  97. return result_type(scalar_type(k) * (a - scalar_type(k)), z);
  98. }
  99. };
  100. //]
  101. //[cf_gamma_Q
  102. template <class T>
  103. inline std::complex<T> gamma_Q_as_fraction(const std::complex<T>& a, const std::complex<T>& z)
  104. {
  105. upper_incomplete_gamma_fract<std::complex<T> > f(a, z);
  106. std::complex<T> eps(std::numeric_limits<T>::epsilon());
  107. return pow(z, a) / (exp(z) *(z - a + T(1) + boost::math::tools::continued_fraction_a(f, eps)));
  108. }
  109. //]
  110. inline boost::multiprecision::cpp_complex_50 gamma_Q_as_fraction(const boost::multiprecision::cpp_complex_50& a, const boost::multiprecision::cpp_complex_50& z)
  111. {
  112. upper_incomplete_gamma_fract<boost::multiprecision::cpp_complex_50> f(a, z);
  113. boost::multiprecision::cpp_complex_50 eps(std::numeric_limits<boost::multiprecision::cpp_complex_50::value_type>::epsilon());
  114. return pow(z, a) / (exp(z) * (z - a + 1 + boost::math::tools::continued_fraction_a(f, eps)));
  115. }
  116. int main()
  117. {
  118. using namespace boost::math::tools;
  119. //[cf_gr
  120. golden_ratio_fraction<double> func;
  121. double gr = continued_fraction_a(
  122. func,
  123. std::numeric_limits<double>::epsilon());
  124. std::cout << "The golden ratio is: " << gr << std::endl;
  125. //]
  126. std::cout << tan(0.5) << std::endl;
  127. std::complex<double> arg(3, 2);
  128. std::cout << expint_as_fraction(5, arg) << std::endl;
  129. std::complex<double> a(3, 3), z(3, 2);
  130. std::cout << gamma_Q_as_fraction(a, z) << std::endl;
  131. boost::multiprecision::cpp_complex_50 am(3, 3), zm(3, 2);
  132. std::cout << gamma_Q_as_fraction(am, zm) << std::endl;
  133. return 0;
  134. }