gsl_specfunc__bessel_Jnu.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* specfunc/bessel_Jnu.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. #include "gsl__config.h"
  21. #include "gsl_math.h"
  22. #include "gsl_errno.h"
  23. #include "gsl_sf_bessel.h"
  24. #include "gsl_specfunc__error.h"
  25. #include "gsl_specfunc__bessel.h"
  26. #include "gsl_specfunc__bessel_olver.h"
  27. #include "gsl_specfunc__bessel_temme.h"
  28. /* Evaluate at large enough nu to apply asymptotic
  29. * results and apply backward recurrence.
  30. */
  31. #if 0
  32. static
  33. int
  34. bessel_J_recur_asymp(const double nu, const double x,
  35. gsl_sf_result * Jnu, gsl_sf_result * Jnup1)
  36. {
  37. const double nu_cut = 25.0;
  38. int n;
  39. int steps = ceil(nu_cut - nu) + 1;
  40. gsl_sf_result r_Jnp1;
  41. gsl_sf_result r_Jn;
  42. int stat_O1 = gsl_sf_bessel_Jnu_asymp_Olver_e(nu + steps + 1.0, x, &r_Jnp1);
  43. int stat_O2 = gsl_sf_bessel_Jnu_asymp_Olver_e(nu + steps, x, &r_Jn);
  44. double r_fe = fabs(r_Jnp1.err/r_Jnp1.val) + fabs(r_Jn.err/r_Jn.val);
  45. double Jnp1 = r_Jnp1.val;
  46. double Jn = r_Jn.val;
  47. double Jnm1;
  48. double Jnp1_save;
  49. for(n=steps; n>0; n--) {
  50. Jnm1 = 2.0*(nu+n)/x * Jn - Jnp1;
  51. Jnp1 = Jn;
  52. Jnp1_save = Jn;
  53. Jn = Jnm1;
  54. }
  55. Jnu->val = Jn;
  56. Jnu->err = (r_fe + GSL_DBL_EPSILON * (steps + 1.0)) * fabs(Jn);
  57. Jnup1->val = Jnp1_save;
  58. Jnup1->err = (r_fe + GSL_DBL_EPSILON * (steps + 1.0)) * fabs(Jnp1_save);
  59. return GSL_ERROR_SELECT_2(stat_O1, stat_O2);
  60. }
  61. #endif
  62. /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
  63. int
  64. gsl_sf_bessel_Jnu_e(const double nu, const double x, gsl_sf_result * result)
  65. {
  66. /* CHECK_POINTER(result) */
  67. if(x < 0.0 || nu < 0.0) {
  68. DOMAIN_ERROR(result);
  69. }
  70. else if(x == 0.0) {
  71. if(nu == 0.0) {
  72. result->val = 1.0;
  73. result->err = 0.0;
  74. }
  75. else {
  76. result->val = 0.0;
  77. result->err = 0.0;
  78. }
  79. return GSL_SUCCESS;
  80. }
  81. else if(x*x < 10.0*(nu+1.0)) {
  82. return gsl_sf_bessel_IJ_taylor_e(nu, x, -1, 100, GSL_DBL_EPSILON, result);
  83. }
  84. else if(nu > 50.0) {
  85. return gsl_sf_bessel_Jnu_asymp_Olver_e(nu, x, result);
  86. }
  87. else if(x > 1000.0)
  88. {
  89. /* We need this to avoid feeding large x to CF1; note that
  90. * due to the above check, we know that n <= 50. See similar
  91. * block in bessel_Jn.c.
  92. */
  93. return gsl_sf_bessel_Jnu_asympx_e(nu, x, result);
  94. }
  95. else {
  96. /* -1/2 <= mu <= 1/2 */
  97. int N = (int)(nu + 0.5);
  98. double mu = nu - N;
  99. /* Determine the J ratio at nu.
  100. */
  101. double Jnup1_Jnu;
  102. double sgn_Jnu;
  103. const int stat_CF1 = gsl_sf_bessel_J_CF1(nu, x, &Jnup1_Jnu, &sgn_Jnu);
  104. if(x < 2.0) {
  105. /* Determine Y_mu, Y_mup1 directly and recurse forward to nu.
  106. * Then use the CF1 information to solve for J_nu and J_nup1.
  107. */
  108. gsl_sf_result Y_mu, Y_mup1;
  109. const int stat_mu = gsl_sf_bessel_Y_temme(mu, x, &Y_mu, &Y_mup1);
  110. double Ynm1 = Y_mu.val;
  111. double Yn = Y_mup1.val;
  112. double Ynp1 = 0.0;
  113. int n;
  114. for(n=1; n<N; n++) {
  115. Ynp1 = 2.0*(mu+n)/x * Yn - Ynm1;
  116. Ynm1 = Yn;
  117. Yn = Ynp1;
  118. }
  119. result->val = 2.0/(M_PI*x) / (Jnup1_Jnu*Yn - Ynp1);
  120. result->err = GSL_DBL_EPSILON * (N + 2.0) * fabs(result->val);
  121. return GSL_ERROR_SELECT_2(stat_mu, stat_CF1);
  122. }
  123. else {
  124. /* Recurse backward from nu to mu, determining the J ratio
  125. * at mu. Use this together with a Steed method CF2 to
  126. * determine the actual J_mu, and thus obtain the normalization.
  127. */
  128. double Jmu;
  129. double Jmup1_Jmu;
  130. double sgn_Jmu;
  131. double Jmuprime_Jmu;
  132. double P, Q;
  133. const int stat_CF2 = gsl_sf_bessel_JY_steed_CF2(mu, x, &P, &Q);
  134. double gamma;
  135. double Jnp1 = sgn_Jnu * GSL_SQRT_DBL_MIN * Jnup1_Jnu;
  136. double Jn = sgn_Jnu * GSL_SQRT_DBL_MIN;
  137. double Jnm1;
  138. int n;
  139. for(n=N; n>0; n--) {
  140. Jnm1 = 2.0*(mu+n)/x * Jn - Jnp1;
  141. Jnp1 = Jn;
  142. Jn = Jnm1;
  143. }
  144. Jmup1_Jmu = Jnp1/Jn;
  145. sgn_Jmu = GSL_SIGN(Jn);
  146. Jmuprime_Jmu = mu/x - Jmup1_Jmu;
  147. gamma = (P - Jmuprime_Jmu)/Q;
  148. Jmu = sgn_Jmu * sqrt(2.0/(M_PI*x) / (Q + gamma*(P-Jmuprime_Jmu)));
  149. result->val = Jmu * (sgn_Jnu * GSL_SQRT_DBL_MIN) / Jn;
  150. result->err = 2.0 * GSL_DBL_EPSILON * (N + 2.0) * fabs(result->val);
  151. return GSL_ERROR_SELECT_2(stat_CF2, stat_CF1);
  152. }
  153. }
  154. }
  155. /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
  156. #include "gsl_specfunc__eval.h"
  157. double gsl_sf_bessel_Jnu(const double nu, const double x)
  158. {
  159. EVAL_RESULT(gsl_sf_bessel_Jnu_e(nu, x, &result));
  160. }