/* [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; }
static int delta(int ta, int tb, int tc, gsl_sf_result * d) { gsl_sf_result f1, f2, f3, f4; int status = 0; status += gsl_sf_fact_e((ta + tb - tc)/2, &f1); status += gsl_sf_fact_e((ta + tc - tb)/2, &f2); status += gsl_sf_fact_e((tb + tc - ta)/2, &f3); status += gsl_sf_fact_e((ta + tb + tc)/2 + 1, &f4); if(status != 0) { OVERFLOW_ERROR(d); } d->val = f1.val * f2.val * f3.val / f4.val; d->err = 4.0 * GSL_DBL_EPSILON * fabs(d->val); return GSL_SUCCESS; }
/// Factorial. double factorial(unsigned int n) { gsl_sf_result result; int stat = gsl_sf_fact_e(n, &result); if (stat != GSL_SUCCESS) { std::ostringstream msg("Error in factorial:"); msg << " n=" << n; throw std::runtime_error(msg.str()); } else return result.val; }
int gsl_sf_coupling_6j_e(int two_ja, int two_jb, int two_jc, int two_jd, int two_je, int two_jf, gsl_sf_result * result) { /* CHECK_POINTER(result) */ if( two_ja < 0 || two_jb < 0 || two_jc < 0 || two_jd < 0 || two_je < 0 || two_jf < 0 ) { DOMAIN_ERROR(result); } else if( triangle_selection_fails(two_ja, two_jb, two_jc) || triangle_selection_fails(two_ja, two_je, two_jf) || triangle_selection_fails(two_jb, two_jd, two_jf) || triangle_selection_fails(two_je, two_jd, two_jc) ) { result->val = 0.0; result->err = 0.0; return GSL_SUCCESS; } else { gsl_sf_result n1; gsl_sf_result d1, d2, d3, d4, d5, d6; double norm; int tk, tkmin, tkmax; double phase; double sum_pos = 0.0; double sum_neg = 0.0; double sumsq_err = 0.0; int status = 0; status += delta(two_ja, two_jb, two_jc, &d1); status += delta(two_ja, two_je, two_jf, &d2); status += delta(two_jb, two_jd, two_jf, &d3); status += delta(two_je, two_jd, two_jc, &d4); if(status != GSL_SUCCESS) { OVERFLOW_ERROR(result); } norm = sqrt(d1.val) * sqrt(d2.val) * sqrt(d3.val) * sqrt(d4.val); tkmin = locMax3(0, two_ja + two_jd - two_jc - two_jf, two_jb + two_je - two_jc - two_jf); tkmax = locMin5(two_ja + two_jb + two_je + two_jd + 2, two_ja + two_jb - two_jc, two_je + two_jd - two_jc, two_ja + two_je - two_jf, two_jb + two_jd - two_jf); phase = GSL_IS_ODD((two_ja + two_jb + two_je + two_jd + tkmin)/2) ? -1.0 : 1.0; for(tk=tkmin; tk<=tkmax; tk += 2) { double term; double term_err; gsl_sf_result den_1, den_2; gsl_sf_result d1_a, d1_b; status = 0; status += gsl_sf_fact_e((two_ja + two_jb + two_je + two_jd - tk)/2 + 1, &n1); status += gsl_sf_fact_e(tk/2, &d1_a); status += gsl_sf_fact_e((two_jc + two_jf - two_ja - two_jd + tk)/2, &d1_b); status += gsl_sf_fact_e((two_jc + two_jf - two_jb - two_je + tk)/2, &d2); status += gsl_sf_fact_e((two_ja + two_jb - two_jc - tk)/2, &d3); status += gsl_sf_fact_e((two_je + two_jd - two_jc - tk)/2, &d4); status += gsl_sf_fact_e((two_ja + two_je - two_jf - tk)/2, &d5); status += gsl_sf_fact_e((two_jb + two_jd - two_jf - tk)/2, &d6); if(status != GSL_SUCCESS) { OVERFLOW_ERROR(result); } d1.val = d1_a.val * d1_b.val; d1.err = d1_a.err * fabs(d1_b.val) + fabs(d1_a.val) * d1_b.err; den_1.val = d1.val*d2.val*d3.val; den_1.err = d1.err * fabs(d2.val*d3.val); den_1.err += d2.err * fabs(d1.val*d3.val); den_1.err += d3.err * fabs(d1.val*d2.val); den_2.val = d4.val*d5.val*d6.val; den_2.err = d4.err * fabs(d5.val*d6.val); den_2.err += d5.err * fabs(d4.val*d6.val); den_2.err += d6.err * fabs(d4.val*d5.val); term = phase * n1.val / den_1.val / den_2.val; phase = -phase; term_err = n1.err / fabs(den_1.val) / fabs(den_2.val); term_err += fabs(term / den_1.val) * den_1.err; term_err += fabs(term / den_2.val) * den_2.err; if(term >= 0.0) { sum_pos += norm*term; } else { sum_neg -= norm*term; } sumsq_err += norm*norm * term_err*term_err; } result->val = sum_pos - sum_neg; result->err = 2.0 * GSL_DBL_EPSILON * (sum_pos + sum_neg); result->err += sqrt(sumsq_err / (0.5*(tkmax-tkmin)+1.0)); result->err += 2.0 * GSL_DBL_EPSILON * (tkmax - tkmin + 2.0) * fabs(result->val); return GSL_SUCCESS; } }
/* series of hypergeometric functions for integer j > 0, x > 0 * [Goano (7)] */ static int fd_UMseries_int(const int j, const double x, gsl_sf_result * result) { const int nmax = 2000; double pre; double lnpre_val; double lnpre_err; double sum_even_val = 1.0; double sum_even_err = 0.0; double sum_odd_val = 0.0; double sum_odd_err = 0.0; int stat_sum; int stat_e; int stat_h = GSL_SUCCESS; int n; if(x < 500.0 && j < 80) { double p = gsl_sf_pow_int(x, j+1); gsl_sf_result g; gsl_sf_fact_e(j+1, &g); /* Gamma(j+2) */ lnpre_val = 0.0; lnpre_err = 0.0; pre = p/g.val; } else { double lnx = log(x); gsl_sf_result lg; gsl_sf_lngamma_e(j + 2.0, &lg); lnpre_val = (j+1.0)*lnx - lg.val; lnpre_err = 2.0 * GSL_DBL_EPSILON * fabs((j+1.0)*lnx) + lg.err; pre = 1.0; } /* Add up the odd terms of the sum. */ for(n=1; n<nmax; n+=2) { double del_val; double del_err; gsl_sf_result U; gsl_sf_result M; int stat_h_U = gsl_sf_hyperg_U_int_e(1, j+2, n*x, &U); int stat_h_F = gsl_sf_hyperg_1F1_int_e(1, j+2, -n*x, &M); stat_h = GSL_ERROR_SELECT_3(stat_h, stat_h_U, stat_h_F); del_val = ((j+1.0)*U.val - M.val); del_err = (fabs(j+1.0)*U.err + M.err); sum_odd_val += del_val; sum_odd_err += del_err; if(fabs(del_val/sum_odd_val) < GSL_DBL_EPSILON) break; } /* Add up the even terms of the sum. */ for(n=2; n<nmax; n+=2) { double del_val; double del_err; gsl_sf_result U; gsl_sf_result M; int stat_h_U = gsl_sf_hyperg_U_int_e(1, j+2, n*x, &U); int stat_h_F = gsl_sf_hyperg_1F1_int_e(1, j+2, -n*x, &M); stat_h = GSL_ERROR_SELECT_3(stat_h, stat_h_U, stat_h_F); del_val = ((j+1.0)*U.val - M.val); del_err = (fabs(j+1.0)*U.err + M.err); sum_even_val -= del_val; sum_even_err += del_err; if(fabs(del_val/sum_even_val) < GSL_DBL_EPSILON) break; } stat_sum = ( n >= nmax ? GSL_EMAXITER : GSL_SUCCESS ); stat_e = gsl_sf_exp_mult_err_e(lnpre_val, lnpre_err, pre*(sum_even_val + sum_odd_val), pre*(sum_even_err + sum_odd_err), result); result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val); return GSL_ERROR_SELECT_3(stat_e, stat_h, stat_sum); }
/* Series evaluation for small x > 0, integer j > 0; x < Pi. * [Goano (8)] */ static int fd_series_int(const int j, const double x, gsl_sf_result * result) { int n; double sum = 0.0; double del; double pow_factor = 1.0; gsl_sf_result eta_factor; gsl_sf_eta_int_e(j + 1, &eta_factor); del = pow_factor * eta_factor.val; sum += del; /* Sum terms where the argument * of eta() is positive. */ for(n=1; n<=j+2; n++) { gsl_sf_eta_int_e(j+1-n, &eta_factor); pow_factor *= x/n; del = pow_factor * eta_factor.val; sum += del; if(fabs(del/sum) < GSL_DBL_EPSILON) break; } /* Now sum the terms where eta() is negative. * The argument of eta() must be odd as well, * so it is convenient to transform the series * as follows: * * Sum[ eta(j+1-n) x^n / n!, {n,j+4,Infinity}] * = x^j / j! Sum[ eta(1-2m) x^(2m) j! / (2m+j)! , {m,2,Infinity}] * * We do not need to do this sum if j is large enough. */ if(j < 32) { int m; gsl_sf_result jfact; double sum2; double pre2; gsl_sf_fact_e((unsigned int)j, &jfact); pre2 = gsl_sf_pow_int(x, j) / jfact.val; gsl_sf_eta_int_e(-3, &eta_factor); pow_factor = x*x*x*x / ((j+4)*(j+3)*(j+2)*(j+1)); sum2 = eta_factor.val * pow_factor; for(m=3; m<24; m++) { gsl_sf_eta_int_e(1-2*m, &eta_factor); pow_factor *= x*x / ((j+2*m)*(j+2*m-1)); sum2 += eta_factor.val * pow_factor; } sum += pre2 * sum2; } result->val = sum; result->err = 2.0 * GSL_DBL_EPSILON * fabs(sum); return GSL_SUCCESS; }