/* [Abramowitz+Stegun, 9.6.11] * assumes n >= 1 */ static int bessel_Kn_scaled_small_x(const int n, const double x, gsl_sf_result * result) { int k; double y = 0.25 * x * x; double ln_x_2 = log(0.5*x); double ex = exp(x); gsl_sf_result ln_nm1_fact; double k_term; double term1, sum1, ln_pre1; double term2, sum2, pre2; gsl_sf_lnfact_e((unsigned int)(n-1), &ln_nm1_fact); ln_pre1 = -n*ln_x_2 + ln_nm1_fact.val; if(ln_pre1 > GSL_LOG_DBL_MAX - 3.0) GSL_ERROR ("error", GSL_EOVRFLW); sum1 = 1.0; k_term = 1.0; for(k=1; k<=n-1; k++) { k_term *= -y/(k * (n-k)); sum1 += k_term; } term1 = 0.5 * exp(ln_pre1) * sum1; pre2 = 0.5 * exp(n*ln_x_2); if(pre2 > 0.0) { const int KMAX = 20; gsl_sf_result psi_n; gsl_sf_result npk_fact; double yk = 1.0; double k_fact = 1.0; double psi_kp1 = -M_EULER; double psi_npkp1; gsl_sf_psi_int_e(n, &psi_n); gsl_sf_fact_e((unsigned int)n, &npk_fact); psi_npkp1 = psi_n.val + 1.0/n; sum2 = (psi_kp1 + psi_npkp1 - 2.0*ln_x_2)/npk_fact.val; for(k=1; k<KMAX; k++) { psi_kp1 += 1.0/k; psi_npkp1 += 1.0/(n+k); k_fact *= k; npk_fact.val *= n+k; yk *= y; k_term = yk*(psi_kp1 + psi_npkp1 - 2.0*ln_x_2)/(k_fact*npk_fact.val); sum2 += k_term; } term2 = ( GSL_IS_ODD(n) ? -1.0 : 1.0 ) * pre2 * sum2; } else { term2 = 0.0; } result->val = ex * (term1 + term2); result->err = ex * GSL_DBL_EPSILON * (fabs(ln_pre1)*fabs(term1) + fabs(term2)); result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val); return GSL_SUCCESS; }
double gsl_sf_psi_int(const int n) { EVAL_RESULT(gsl_sf_psi_int_e(n, &result)); }