/* specfunc/bessel_temme.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Author: G. Jungman */ /* Calculate series for Y_nu and K_nu for small x and nu. * This is applicable for x < 2 and |nu|<=1/2. * These functions assume x > 0. */ #include #include #include #include #include "bessel_temme.h" #include "chebyshev.h" #include "cheb_eval.c" /* nu = (x+1)/4, -1val = -sum0; Ynu->err = (2.0 + 0.5*k) * GSL_DBL_EPSILON * fabs(Ynu->val); Ynup1->val = -sum1 * 2.0/x; Ynup1->err = (2.0 + 0.5*k) * GSL_DBL_EPSILON * fabs(Ynup1->val); stat_iter = ( k >= max_iter ? GSL_EMAXITER : GSL_SUCCESS ); return GSL_ERROR_SELECT_2(stat_iter, stat_g); } int gsl_sf_bessel_K_scaled_temme(const double nu, const double x, double * K_nu, double * K_nup1, double * Kp_nu) { const int max_iter = 15000; const double half_x = 0.5 * x; const double ln_half_x = log(half_x); const double half_x_nu = exp(nu*ln_half_x); const double pi_nu = M_PI * nu; const double sigma = -nu * ln_half_x; const double sinrat = (fabs(pi_nu) < GSL_DBL_EPSILON ? 1.0 : pi_nu/sin(pi_nu)); const double sinhrat = (fabs(sigma) < GSL_DBL_EPSILON ? 1.0 : sinh(sigma)/sigma); const double ex = exp(x); double sum0, sum1; double fk, pk, qk, hk, ck; int k = 0; int stat_iter; double g_1pnu, g_1mnu, g1, g2; int stat_g = gsl_sf_temme_gamma(nu, &g_1pnu, &g_1mnu, &g1, &g2); fk = sinrat * (cosh(sigma)*g1 - sinhrat*ln_half_x*g2); pk = 0.5/half_x_nu * g_1pnu; qk = 0.5*half_x_nu * g_1mnu; hk = pk; ck = 1.0; sum0 = fk; sum1 = hk; while(k < max_iter) { double del0; double del1; k++; fk = (k*fk + pk + qk)/(k*k-nu*nu); ck *= half_x*half_x/k; pk /= (k - nu); qk /= (k + nu); hk = -k*fk + pk; del0 = ck * fk; del1 = ck * hk; sum0 += del0; sum1 += del1; if(fabs(del0) < 0.5*fabs(sum0)*GSL_DBL_EPSILON) break; } *K_nu = sum0 * ex; *K_nup1 = sum1 * 2.0/x * ex; *Kp_nu = - *K_nup1 + nu/x * *K_nu; stat_iter = ( k == max_iter ? GSL_EMAXITER : GSL_SUCCESS ); return GSL_ERROR_SELECT_2(stat_iter, stat_g); }