/* Evaluate bessel_I(nu, x), allowing nu < 0. * This is fine here because we do not not allow * nu to be a negative integer. * x > 0. */ static int hyperg_0F1_bessel_I(const double nu, const double x, gsl_sf_result * result) { if(x > GSL_LOG_DBL_MAX) { OVERFLOW_ERROR(result); } if(nu < 0.0) { const double anu = -nu; const double s = 2.0/M_PI * sin(anu*M_PI); const double ex = exp(x); gsl_sf_result I; gsl_sf_result K; int stat_I = gsl_sf_bessel_Inu_scaled_e(anu, x, &I); int stat_K = gsl_sf_bessel_Knu_scaled_e(anu, x, &K); result->val = ex * I.val + s * (K.val / ex); result->err = ex * I.err + fabs(s * K.err/ex); result->err += fabs(s * (K.val/ex)) * GSL_DBL_EPSILON * anu * M_PI; return GSL_ERROR_SELECT_2(stat_K, stat_I); } else { const double ex = exp(x); gsl_sf_result I; int stat_I = gsl_sf_bessel_Inu_scaled_e(nu, x, &I); result->val = ex * I.val; result->err = ex * I.err + GSL_DBL_EPSILON * fabs(result->val); return stat_I; } }
int gsl_sf_bessel_lnKnu_e(const double nu, const double x, gsl_sf_result * result) { /* CHECK_POINTER(result) */ if(x <= 0.0 || nu < 0.0) { DOMAIN_ERROR(result); } else if(nu == 0.0) { gsl_sf_result K_scaled; /* This cannot underflow, and * it will not throw GSL_EDOM * since that is already checked. */ gsl_sf_bessel_K0_scaled_e(x, &K_scaled); result->val = -x + log(fabs(K_scaled.val)); result->err = GSL_DBL_EPSILON * fabs(x) + fabs(K_scaled.err/K_scaled.val); result->err += GSL_DBL_EPSILON * fabs(result->val); return GSL_SUCCESS; } else if(x < 2.0 && nu > 1.0) { /* Make use of the inequality * Knu(x) <= 1/2 (2/x)^nu Gamma(nu), * which follows from the integral representation * [Abramowitz+Stegun, 9.6.23 (2)]. With this * we decide whether or not there is an overflow * problem because x is small. */ double ln_bound; gsl_sf_result lg_nu; gsl_sf_lngamma_e(nu, &lg_nu); ln_bound = -M_LN2 - nu*log(0.5*x) + lg_nu.val; if(ln_bound > GSL_LOG_DBL_MAX - 20.0) { /* x must be very small or nu very large (or both). */ double xi = 0.25*x*x; double sum = 1.0 - xi/(nu-1.0); if(nu > 2.0) sum += (xi/(nu-1.0)) * (xi/(nu-2.0)); result->val = ln_bound + log(sum); result->err = lg_nu.err; result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val); return GSL_SUCCESS; } /* can drop-through here */ } { /* We passed the above tests, so no problem. * Evaluate as usual. Note the possible drop-through * in the above code! */ gsl_sf_result K_scaled; gsl_sf_bessel_Knu_scaled_e(nu, x, &K_scaled); result->val = -x + log(fabs(K_scaled.val)); result->err = GSL_DBL_EPSILON * fabs(x) + fabs(K_scaled.err/K_scaled.val); result->err += GSL_DBL_EPSILON * fabs(result->val); return GSL_SUCCESS; } }
int gsl_sf_bessel_Knu_e(const double nu, const double x, gsl_sf_result * result) { gsl_sf_result b; int stat_K = gsl_sf_bessel_Knu_scaled_e(nu, x, &b); int stat_e = gsl_sf_exp_mult_err_e(-x, 0.0, b.val, b.err, result); return GSL_ERROR_SELECT_2(stat_e, stat_K); }
double gsl_sf_bessel_Knu_scaled(const double nu, const double x) { EVAL_RESULT(gsl_sf_bessel_Knu_scaled_e(nu, x, &result)); }