gsl_specfunc__bessel_temme.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* specfunc/bessel_temme.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. /* Author: G. Jungman */
  20. /* Calculate series for Y_nu and K_nu for small x and nu.
  21. * This is applicable for x < 2 and |nu|<=1/2.
  22. * These functions assume x > 0.
  23. */
  24. #include "gsl__config.h"
  25. #include "gsl_math.h"
  26. #include "gsl_errno.h"
  27. #include "gsl_mode.h"
  28. #include "gsl_specfunc__bessel_temme.h"
  29. #include "gsl_specfunc__chebyshev.h"
  30. #include "gsl_specfunc__cheb_eval.c"
  31. /* nu = (x+1)/4, -1<x<1, 1/(2nu)(1/Gamma[1-nu]-1/Gamma[1+nu]) */
  32. static double g1_dat[14] = {
  33. -1.14516408366268311786898152867,
  34. 0.00636085311347084238122955495,
  35. 0.00186245193007206848934643657,
  36. 0.000152833085873453507081227824,
  37. 0.000017017464011802038795324732,
  38. -6.4597502923347254354668326451e-07,
  39. -5.1819848432519380894104312968e-08,
  40. 4.5189092894858183051123180797e-10,
  41. 3.2433227371020873043666259180e-11,
  42. 6.8309434024947522875432400828e-13,
  43. 2.8353502755172101513119628130e-14,
  44. -7.9883905769323592875638087541e-16,
  45. -3.3726677300771949833341213457e-17,
  46. -3.6586334809210520744054437104e-20
  47. };
  48. static cheb_series g1_cs = {
  49. g1_dat,
  50. 13,
  51. -1, 1,
  52. 7
  53. };
  54. /* nu = (x+1)/4, -1<x<1, 1/2 (1/Gamma[1-nu]+1/Gamma[1+nu]) */
  55. static double g2_dat[15] =
  56. {
  57. 1.882645524949671835019616975350,
  58. -0.077490658396167518329547945212,
  59. -0.018256714847324929419579340950,
  60. 0.0006338030209074895795923971731,
  61. 0.0000762290543508729021194461175,
  62. -9.5501647561720443519853993526e-07,
  63. -8.8927268107886351912431512955e-08,
  64. -1.9521334772319613740511880132e-09,
  65. -9.4003052735885162111769579771e-11,
  66. 4.6875133849532393179290879101e-12,
  67. 2.2658535746925759582447545145e-13,
  68. -1.1725509698488015111878735251e-15,
  69. -7.0441338200245222530843155877e-17,
  70. -2.4377878310107693650659740228e-18,
  71. -7.5225243218253901727164675011e-20
  72. };
  73. static cheb_series g2_cs = {
  74. g2_dat,
  75. 14,
  76. -1, 1,
  77. 8
  78. };
  79. static
  80. int
  81. gsl_sf_temme_gamma(const double nu, double * g_1pnu, double * g_1mnu, double * g1, double * g2)
  82. {
  83. const double anu = fabs(nu); /* functions are even */
  84. const double x = 4.0*anu - 1.0;
  85. gsl_sf_result r_g1;
  86. gsl_sf_result r_g2;
  87. cheb_eval_e(&g1_cs, x, &r_g1);
  88. cheb_eval_e(&g2_cs, x, &r_g2);
  89. *g1 = r_g1.val;
  90. *g2 = r_g2.val;
  91. *g_1mnu = 1.0/(r_g2.val + nu * r_g1.val);
  92. *g_1pnu = 1.0/(r_g2.val - nu * r_g1.val);
  93. return GSL_SUCCESS;
  94. }
  95. int
  96. gsl_sf_bessel_Y_temme(const double nu, const double x,
  97. gsl_sf_result * Ynu,
  98. gsl_sf_result * Ynup1)
  99. {
  100. const int max_iter = 15000;
  101. const double half_x = 0.5 * x;
  102. const double ln_half_x = log(half_x);
  103. const double half_x_nu = exp(nu*ln_half_x);
  104. const double pi_nu = M_PI * nu;
  105. const double alpha = pi_nu / 2.0;
  106. const double sigma = -nu * ln_half_x;
  107. const double sinrat = (fabs(pi_nu) < GSL_DBL_EPSILON ? 1.0 : pi_nu/sin(pi_nu));
  108. const double sinhrat = (fabs(sigma) < GSL_DBL_EPSILON ? 1.0 : sinh(sigma)/sigma);
  109. const double sinhalf = (fabs(alpha) < GSL_DBL_EPSILON ? 1.0 : sin(alpha)/alpha);
  110. const double sin_sqr = nu*M_PI*M_PI*0.5 * sinhalf*sinhalf;
  111. double sum0, sum1;
  112. double fk, pk, qk, hk, ck;
  113. int k = 0;
  114. int stat_iter;
  115. double g_1pnu, g_1mnu, g1, g2;
  116. int stat_g = gsl_sf_temme_gamma(nu, &g_1pnu, &g_1mnu, &g1, &g2);
  117. fk = 2.0/M_PI * sinrat * (cosh(sigma)*g1 - sinhrat*ln_half_x*g2);
  118. pk = 1.0/M_PI /half_x_nu * g_1pnu;
  119. qk = 1.0/M_PI *half_x_nu * g_1mnu;
  120. hk = pk;
  121. ck = 1.0;
  122. sum0 = fk + sin_sqr * qk;
  123. sum1 = pk;
  124. while(k < max_iter) {
  125. double del0;
  126. double del1;
  127. double gk;
  128. k++;
  129. fk = (k*fk + pk + qk)/(k*k-nu*nu);
  130. ck *= -half_x*half_x/k;
  131. pk /= (k - nu);
  132. qk /= (k + nu);
  133. gk = fk + sin_sqr * qk;
  134. hk = -k*gk + pk;
  135. del0 = ck * gk;
  136. del1 = ck * hk;
  137. sum0 += del0;
  138. sum1 += del1;
  139. if(fabs(del0) < 0.5*(1.0 + fabs(sum0))*GSL_DBL_EPSILON) break;
  140. }
  141. Ynu->val = -sum0;
  142. Ynu->err = (2.0 + 0.5*k) * GSL_DBL_EPSILON * fabs(Ynu->val);
  143. Ynup1->val = -sum1 * 2.0/x;
  144. Ynup1->err = (2.0 + 0.5*k) * GSL_DBL_EPSILON * fabs(Ynup1->val);
  145. stat_iter = ( k >= max_iter ? GSL_EMAXITER : GSL_SUCCESS );
  146. return GSL_ERROR_SELECT_2(stat_iter, stat_g);
  147. }
  148. int
  149. gsl_sf_bessel_K_scaled_temme(const double nu, const double x,
  150. double * K_nu, double * K_nup1, double * Kp_nu)
  151. {
  152. const int max_iter = 15000;
  153. const double half_x = 0.5 * x;
  154. const double ln_half_x = log(half_x);
  155. const double half_x_nu = exp(nu*ln_half_x);
  156. const double pi_nu = M_PI * nu;
  157. const double sigma = -nu * ln_half_x;
  158. const double sinrat = (fabs(pi_nu) < GSL_DBL_EPSILON ? 1.0 : pi_nu/sin(pi_nu));
  159. const double sinhrat = (fabs(sigma) < GSL_DBL_EPSILON ? 1.0 : sinh(sigma)/sigma);
  160. const double ex = exp(x);
  161. double sum0, sum1;
  162. double fk, pk, qk, hk, ck;
  163. int k = 0;
  164. int stat_iter;
  165. double g_1pnu, g_1mnu, g1, g2;
  166. int stat_g = gsl_sf_temme_gamma(nu, &g_1pnu, &g_1mnu, &g1, &g2);
  167. fk = sinrat * (cosh(sigma)*g1 - sinhrat*ln_half_x*g2);
  168. pk = 0.5/half_x_nu * g_1pnu;
  169. qk = 0.5*half_x_nu * g_1mnu;
  170. hk = pk;
  171. ck = 1.0;
  172. sum0 = fk;
  173. sum1 = hk;
  174. while(k < max_iter) {
  175. double del0;
  176. double del1;
  177. k++;
  178. fk = (k*fk + pk + qk)/(k*k-nu*nu);
  179. ck *= half_x*half_x/k;
  180. pk /= (k - nu);
  181. qk /= (k + nu);
  182. hk = -k*fk + pk;
  183. del0 = ck * fk;
  184. del1 = ck * hk;
  185. sum0 += del0;
  186. sum1 += del1;
  187. if(fabs(del0) < 0.5*fabs(sum0)*GSL_DBL_EPSILON) break;
  188. }
  189. *K_nu = sum0 * ex;
  190. *K_nup1 = sum1 * 2.0/x * ex;
  191. *Kp_nu = - *K_nup1 + nu/x * *K_nu;
  192. stat_iter = ( k == max_iter ? GSL_EMAXITER : GSL_SUCCESS );
  193. return GSL_ERROR_SELECT_2(stat_iter, stat_g);
  194. }