gsl_specfunc__bessel_k.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /* specfunc/bessel_k.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_pow_int.h"
  24. #include "gsl_sf_gamma.h"
  25. #include "gsl_sf_bessel.h"
  26. #include "gsl_specfunc__error.h"
  27. #include "gsl_specfunc__check.h"
  28. #include "gsl_specfunc__bessel.h"
  29. /*-*-*-*-*-*-*-*-*-*-*-* Private Section *-*-*-*-*-*-*-*-*-*-*-*/
  30. /* [Abramowitz+Stegun, 10.2.4 + 10.2.6]
  31. * with lmax=15, precision ~ 15D for x < 3
  32. *
  33. * assumes l >= 1
  34. */
  35. static int bessel_kl_scaled_small_x(int l, const double x, gsl_sf_result * result)
  36. {
  37. gsl_sf_result num_fact;
  38. double den = gsl_sf_pow_int(x, l+1);
  39. int stat_df = gsl_sf_doublefact_e((unsigned int) (2*l-1), &num_fact);
  40. if(stat_df != GSL_SUCCESS || den == 0.0) {
  41. OVERFLOW_ERROR(result);
  42. }
  43. else {
  44. const int lmax = 50;
  45. gsl_sf_result ipos_term;
  46. double ineg_term;
  47. double sgn = (GSL_IS_ODD(l) ? -1.0 : 1.0);
  48. double ex = exp(x);
  49. double t = 0.5*x*x;
  50. double sum = 1.0;
  51. double t_coeff = 1.0;
  52. double t_power = 1.0;
  53. double delta;
  54. int stat_il;
  55. int i;
  56. for(i=1; i<lmax; i++) {
  57. t_coeff /= i*(2*(i-l) - 1);
  58. t_power *= t;
  59. delta = t_power*t_coeff;
  60. sum += delta;
  61. if(fabs(delta/sum) < GSL_DBL_EPSILON) break;
  62. }
  63. stat_il = gsl_sf_bessel_il_scaled_e(l, x, &ipos_term);
  64. ineg_term = sgn * num_fact.val/den * sum;
  65. result->val = -sgn * 0.5*M_PI * (ex*ipos_term.val - ineg_term);
  66. result->val *= ex;
  67. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  68. return stat_il;
  69. }
  70. }
  71. /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
  72. int gsl_sf_bessel_k0_scaled_e(const double x, gsl_sf_result * result)
  73. {
  74. /* CHECK_POINTER(result) */
  75. if(x <= 0.0) {
  76. DOMAIN_ERROR(result);
  77. }
  78. else {
  79. result->val = M_PI/(2.0*x);
  80. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  81. CHECK_UNDERFLOW(result);
  82. return GSL_SUCCESS;
  83. }
  84. }
  85. int gsl_sf_bessel_k1_scaled_e(const double x, gsl_sf_result * result)
  86. {
  87. /* CHECK_POINTER(result) */
  88. if(x <= 0.0) {
  89. DOMAIN_ERROR(result);
  90. }
  91. else if(x < (M_SQRTPI+1.0)/(M_SQRT2*GSL_SQRT_DBL_MAX)) {
  92. OVERFLOW_ERROR(result);
  93. }
  94. else {
  95. result->val = M_PI/(2.0*x) * (1.0 + 1.0/x);
  96. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  97. CHECK_UNDERFLOW(result);
  98. return GSL_SUCCESS;
  99. }
  100. }
  101. int gsl_sf_bessel_k2_scaled_e(const double x, gsl_sf_result * result)
  102. {
  103. /* CHECK_POINTER(result) */
  104. if(x <= 0.0) {
  105. DOMAIN_ERROR(result);
  106. }
  107. else if(x < 2.0/GSL_ROOT3_DBL_MAX) {
  108. OVERFLOW_ERROR(result);
  109. }
  110. else {
  111. result->val = M_PI/(2.0*x) * (1.0 + 3.0/x * (1.0 + 1.0/x));
  112. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  113. CHECK_UNDERFLOW(result);
  114. return GSL_SUCCESS;
  115. }
  116. }
  117. int gsl_sf_bessel_kl_scaled_e(int l, const double x, gsl_sf_result * result)
  118. {
  119. if(l < 0 || x <= 0.0) {
  120. DOMAIN_ERROR(result);
  121. }
  122. else if(l == 0) {
  123. return gsl_sf_bessel_k0_scaled_e(x, result);
  124. }
  125. else if(l == 1) {
  126. return gsl_sf_bessel_k1_scaled_e(x, result);
  127. }
  128. else if(l == 2) {
  129. return gsl_sf_bessel_k2_scaled_e(x, result);
  130. }
  131. else if(x < 3.0) {
  132. return bessel_kl_scaled_small_x(l, x, result);
  133. }
  134. else if(GSL_ROOT3_DBL_EPSILON * x > (l*l + l + 1)) {
  135. int status = gsl_sf_bessel_Knu_scaled_asympx_e(l + 0.5, x, result);
  136. double pre = sqrt((0.5*M_PI)/x);
  137. result->val *= pre;
  138. result->err *= pre;
  139. return status;
  140. }
  141. else if(GSL_MIN(0.29/(l*l+1.0), 0.5/(l*l+1.0+x*x)) < GSL_ROOT3_DBL_EPSILON) {
  142. int status = gsl_sf_bessel_Knu_scaled_asymp_unif_e(l + 0.5, x, result);
  143. double pre = sqrt((0.5*M_PI)/x);
  144. result->val *= pre;
  145. result->err *= pre;
  146. return status;
  147. }
  148. else {
  149. /* recurse upward */
  150. gsl_sf_result r_bk;
  151. gsl_sf_result r_bkm;
  152. int stat_1 = gsl_sf_bessel_k1_scaled_e(x, &r_bk);
  153. int stat_0 = gsl_sf_bessel_k0_scaled_e(x, &r_bkm);
  154. double bkp;
  155. double bk = r_bk.val;
  156. double bkm = r_bkm.val;
  157. int j;
  158. for(j=1; j<l; j++) {
  159. bkp = (2*j+1)/x*bk + bkm;
  160. bkm = bk;
  161. bk = bkp;
  162. }
  163. result->val = bk;
  164. result->err = fabs(bk) * (fabs(r_bk.err/r_bk.val) + fabs(r_bkm.err/r_bkm.val));
  165. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  166. return GSL_ERROR_SELECT_2(stat_1, stat_0);
  167. }
  168. }
  169. int
  170. gsl_sf_bessel_kl_scaled_array(const int lmax, const double x, double * result_array)
  171. {
  172. if(lmax < 0 || x <= 0.0) {
  173. GSL_ERROR("domain error", GSL_EDOM);
  174. } else if (lmax == 0) {
  175. gsl_sf_result result;
  176. int stat = gsl_sf_bessel_k0_scaled_e(x, &result);
  177. result_array[0] = result.val;
  178. return stat;
  179. } else {
  180. int ell;
  181. double kellp1, kell, kellm1;
  182. gsl_sf_result r_kell;
  183. gsl_sf_result r_kellm1;
  184. gsl_sf_bessel_k1_scaled_e(x, &r_kell);
  185. gsl_sf_bessel_k0_scaled_e(x, &r_kellm1);
  186. kell = r_kell.val;
  187. kellm1 = r_kellm1.val;
  188. result_array[0] = kellm1;
  189. result_array[1] = kell;
  190. for(ell = 1; ell < lmax; ell++) {
  191. kellp1 = (2*ell+1)/x * kell + kellm1;
  192. result_array[ell+1] = kellp1;
  193. kellm1 = kell;
  194. kell = kellp1;
  195. }
  196. return GSL_SUCCESS;
  197. }
  198. }
  199. /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
  200. #include "gsl_specfunc__eval.h"
  201. double gsl_sf_bessel_k0_scaled(const double x)
  202. {
  203. EVAL_RESULT(gsl_sf_bessel_k0_scaled_e(x, &result));
  204. }
  205. double gsl_sf_bessel_k1_scaled(const double x)
  206. {
  207. EVAL_RESULT(gsl_sf_bessel_k1_scaled_e(x, &result));
  208. }
  209. double gsl_sf_bessel_k2_scaled(const double x)
  210. {
  211. EVAL_RESULT(gsl_sf_bessel_k2_scaled_e(x, &result));
  212. }
  213. double gsl_sf_bessel_kl_scaled(const int l, const double x)
  214. {
  215. EVAL_RESULT(gsl_sf_bessel_kl_scaled_e(l, x, &result));
  216. }