int gsl_sf_multiply_e(const double x, const double y, gsl_sf_result * result) { const double ax = fabs(x); const double ay = fabs(y); if(x == 0.0 || y == 0.0) { /* It is necessary to eliminate this immediately. */ result->val = 0.0; result->err = 0.0; return GSL_SUCCESS; } else if((ax <= 1.0 && ay >= 1.0) || (ay <= 1.0 && ax >= 1.0)) { /* Straddling 1.0 is always safe. */ result->val = x*y; result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val); return GSL_SUCCESS; } else { const double f = 1.0 - 2.0 * GSL_DBL_EPSILON; const double min = GSL_MIN_DBL(fabs(x), fabs(y)); const double max = GSL_MAX_DBL(fabs(x), fabs(y)); if(max < 0.9 * GSL_SQRT_DBL_MAX || min < (f * DBL_MAX)/max) { result->val = GSL_COERCE_DBL(x*y); result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val); CHECK_UNDERFLOW(result); return GSL_SUCCESS; } else { OVERFLOW_ERROR(result); } } }
int gsl_sf_hydrogenicR_e(const int n, const int l, const double Z, const double r, gsl_sf_result * result) { if(n < 1 || l > n-1 || Z <= 0.0 || r < 0.0) { DOMAIN_ERROR(result); } else { double A = 2.0*Z/n; gsl_sf_result norm; int stat_norm = R_norm(n, l, Z, &norm); double rho = A*r; double ea = exp(-0.5*rho); double pp = gsl_sf_pow_int(rho, l); gsl_sf_result lag; int stat_lag = gsl_sf_laguerre_n_e(n-l-1, 2*l+1, rho, &lag); double W_val = norm.val * ea * pp; double W_err = norm.err * ea * pp; W_err += norm.val * ((0.5*rho + 1.0) * GSL_DBL_EPSILON) * ea * pp; W_err += norm.val * ea * ((l+1.0) * GSL_DBL_EPSILON) * pp; result->val = W_val * lag.val; result->err = W_val * lag.err + W_err * fabs(lag.val); result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val); if ((l == 0 || (r > 0 && l > 0)) && lag.val != 0.0 && stat_lag == GSL_SUCCESS && stat_norm == GSL_SUCCESS) { CHECK_UNDERFLOW(result); }; return GSL_ERROR_SELECT_2(stat_lag, stat_norm); } }
int gsl_sf_debye_6_e(const double x, gsl_sf_result * result) { const double val_infinity = 4356.06887828990661194792541535 ; const double xcut = -GSL_LOG_DBL_MIN; /* CHECK_POINTER(result) */ if(x < 0.0) { DOMAIN_ERROR(result); } else if(x < 2.0*M_SQRT2*GSL_SQRT_DBL_EPSILON) { result->val = 1.0 - 3.0*x/7.0 + x*x/16.0; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else if(x <= 4.0) { const double t = x*x/8.0 - 1.0; gsl_sf_result c; cheb_eval_e(&adeb6_cs, t, &c); result->val = c.val - 3.0*x/7.0; result->err = c.err + GSL_DBL_EPSILON * 3.0*x/7.0; return GSL_SUCCESS; } else if(x < -(M_LN2 + GSL_LOG_DBL_EPSILON)) { const int nexp = floor(xcut/x); const double ex = exp(-x); double xk = nexp * x; double rk = nexp; double sum = 0.0; int i; for(i=nexp; i>=1; i--) { double xk_inv = 1.0/xk; sum *= ex; sum += ((((((720.0*xk_inv + 720.0)*xk_inv + 360.0)*xk_inv + 120.0)*xk_inv + 30.0)*xk_inv+ 6.0)*xk_inv+ 1.0) / rk; rk -= 1.0; xk -= x; } result->val = val_infinity/(x*x*x*x*x*x) - 6.0 * sum * ex; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else if(x < xcut) { const double x2 = x*x; const double x4 = x2*x2; const double x6 = x4*x2; const double sum = 720.0 + 720.0*x + 360.0*x2 + 120.0*x2*x + 30.0*x4 + 6.0*x4*x +x6 ; result->val = (val_infinity - 6.0 * sum * exp(-x)) / x6; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else { result->val = (((((val_infinity/x)/x)/x)/x)/x)/x ; result->err = GSL_DBL_EPSILON * result->val; CHECK_UNDERFLOW(result); return GSL_SUCCESS; } }
int gsl_sf_debye_5_e(const double x, gsl_sf_result * result) { const double val_infinity = 610.405837190669483828710757875 ; const double xcut = -GSL_LOG_DBL_MIN; /* CHECK_POINTER(result) */ if(x < 0.0) { DOMAIN_ERROR(result); } else if(x < 2.0*M_SQRT2*GSL_SQRT_DBL_EPSILON) { result->val = 1.0 - 5.0*x/12.0 + 5.0*x*x/84.0; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else if(x <= 4.0) { const double t = x*x/8.0 - 1.0; gsl_sf_result c; cheb_eval_e(&adeb5_cs, t, &c); result->val = c.val - 5.0*x/12.0; result->err = c.err + GSL_DBL_EPSILON * 5.0*x/12.0; return GSL_SUCCESS; } else if(x < -(M_LN2 + GSL_LOG_DBL_EPSILON)) { const int nexp = floor(xcut/x); const double ex = exp(-x); double xk = nexp * x; double rk = nexp; double sum = 0.0; int i; for(i=nexp; i>=1; i--) { double xk_inv = 1.0/xk; sum *= ex; sum += (((((120.0*xk_inv + 120.0)*xk_inv + 60.0)*xk_inv + 20.0)*xk_inv + 5.0)*xk_inv+ 1.0) / rk; rk -= 1.0; xk -= x; } result->val = val_infinity/(x*x*x*x*x) - 5.0 * sum * ex; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else if(x < xcut) { const double x2 = x*x; const double x4 = x2*x2; const double x5 = x4*x; const double sum = 120.0 + 120.0*x + 60.0*x2 + 20.0*x2*x + 5.0*x4 + x5; result->val = (val_infinity - 5.0 * sum * exp(-x)) / x5; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else { result->val = ((((val_infinity/x)/x)/x)/x)/x; result->err = GSL_DBL_EPSILON * result->val; CHECK_UNDERFLOW(result); return GSL_SUCCESS; } }
int gsl_sf_debye_4_e(const double x, gsl_sf_result * result) { const double val_infinity = 99.5450644937635129; const double xcut = -GSL_LOG_DBL_MIN; /* CHECK_POINTER(result) */ if(x < 0.0) { DOMAIN_ERROR(result); } else if(x < 2.0*M_SQRT2*GSL_SQRT_DBL_EPSILON) { result->val = 1.0 - 2.0*x/5.0 + x*x/18.0; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else if(x <= 4.0) { const double t = x*x/8.0 - 1.0; gsl_sf_result c; cheb_eval_e(&adeb4_cs, t, &c); result->val = c.val - 2.0*x/5.0; result->err = c.err + GSL_DBL_EPSILON * 2.0*x/5.0; return GSL_SUCCESS; } else if(x < -(M_LN2 + GSL_LOG_DBL_EPSILON)) { const int nexp = floor(xcut/x); const double ex = exp(-x); double xk = nexp * x; double rk = nexp; double sum = 0.0; int i; for(i=nexp; i>=1; i--) { double xk_inv = 1.0/xk; sum *= ex; sum += ((((24.0*xk_inv + 24.0)*xk_inv + 12.0)*xk_inv + 4.0)*xk_inv + 1.0) / rk; rk -= 1.0; xk -= x; } result->val = val_infinity/(x*x*x*x) - 4.0 * sum * ex; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else if(x < xcut) { const double x2 = x*x; const double x4 = x2*x2; const double sum = 24.0 + 24.0*x + 12.0*x2 + 4.0*x2*x + x4; result->val = (val_infinity - 4.0 * sum * exp(-x)) / x4; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else { result->val = (((val_infinity/x)/x)/x)/x; result->err = GSL_DBL_EPSILON * result->val; CHECK_UNDERFLOW(result); return GSL_SUCCESS; } }
int gsl_sf_debye_3_e(const double x, gsl_sf_result * result) { const double val_infinity = 19.4818182068004875; const double xcut = -GSL_LOG_DBL_MIN; /* CHECK_POINTER(result) */ if(x < 0.0) { DOMAIN_ERROR(result); } else if(x < 2.0*M_SQRT2*GSL_SQRT_DBL_EPSILON) { result->val = 1.0 - 3.0*x/8.0 + x*x/20.0; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else if(x <= 4.0) { const double t = x*x/8.0 - 1.0; gsl_sf_result c; cheb_eval_e(&adeb3_cs, t, &c); result->val = c.val - 0.375*x; result->err = c.err + GSL_DBL_EPSILON * 0.375*x; return GSL_SUCCESS; } else if(x < -(M_LN2 + GSL_LOG_DBL_EPSILON)) { const int nexp = floor(xcut/x); const double ex = exp(-x); double xk = nexp * x; double rk = nexp; double sum = 0.0; int i; for(i=nexp; i>=1; i--) { double xk_inv = 1.0/xk; sum *= ex; sum += (((6.0*xk_inv + 6.0)*xk_inv + 3.0)*xk_inv + 1.0) / rk; rk -= 1.0; xk -= x; } result->val = val_infinity/(x*x*x) - 3.0 * sum * ex; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else if(x < xcut) { const double x3 = x*x*x; const double sum = 6.0 + 6.0*x + 3.0*x*x + x3; result->val = (val_infinity - 3.0 * sum * exp(-x)) / x3; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else { result->val = ((val_infinity/x)/x)/x; result->err = GSL_DBL_EPSILON * result->val; CHECK_UNDERFLOW(result); return GSL_SUCCESS; } }
int gsl_sf_debye_2_e(const double x, gsl_sf_result * result) { const double val_infinity = 4.80822761263837714; const double xcut = -GSL_LOG_DBL_MIN; /* CHECK_POINTER(result) */ if(x < 0.0) { DOMAIN_ERROR(result); } else if(x < 2.0*M_SQRT2*GSL_SQRT_DBL_EPSILON) { result->val = 1.0 - x/3.0 + x*x/24.0; result->err = GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else if(x <= 4.0) { const double t = x*x/8.0 - 1.0; gsl_sf_result c; cheb_eval_e(&adeb2_cs, t, &c); result->val = c.val - x/3.0; result->err = c.err + GSL_DBL_EPSILON * x/3.0; return GSL_SUCCESS; } else if(x < -(M_LN2 + GSL_LOG_DBL_EPSILON)) { const int nexp = floor(xcut/x); const double ex = exp(-x); double xk = nexp * x; double rk = nexp; double sum = 0.0; int i; for(i=nexp; i>=1; i--) { sum *= ex; sum += (1.0 + 2.0/xk + 2.0/(xk*xk)) / rk; rk -= 1.0; xk -= x; } result->val = val_infinity/(x*x) - 2.0 * sum * ex; result->err = GSL_DBL_EPSILON * fabs(result->val); return GSL_SUCCESS; } else if(x < xcut) { const double x2 = x*x; const double sum = 2.0 + 2.0*x + x2; result->val = (val_infinity - 2.0 * sum * exp(-x)) / x2; result->err = GSL_DBL_EPSILON * fabs(result->val); return GSL_SUCCESS; } else { result->val = (val_infinity/x)/x; result->err = GSL_DBL_EPSILON * result->val; CHECK_UNDERFLOW(result); return GSL_SUCCESS; } }
static int expint_En_impl(const int n, const double x, gsl_sf_result * result, const int scale) { if (n < 0) { DOMAIN_ERROR(result); } else if (n == 0) { if (x == 0) { DOMAIN_ERROR(result); } else { result->val = (scale ? 1.0 : exp(-x)) / x; result->err = 2 * GSL_DBL_EPSILON * fabs(result->val); CHECK_UNDERFLOW(result); return GSL_SUCCESS; } } else if (n == 1) { return expint_E1_impl(x, result, scale); } else if (n == 2) { return expint_E2_impl(x, result, scale); } else { if(x < 0) { DOMAIN_ERROR(result); } if (x == 0) { result->val = (scale ? exp(x) : 1 ) * (1/(n-1.0)); result->err = 2 * GSL_DBL_EPSILON * fabs(result->val); CHECK_UNDERFLOW(result); return GSL_SUCCESS; } else { gsl_sf_result result_g; double prefactor = pow(x, n-1); int status = gsl_sf_gamma_inc_e (1-n, x, &result_g); double scale_factor = ( scale ? exp(x) : 1.0 ); result->val = scale_factor * prefactor * result_g.val; result->err = 2 * GSL_DBL_EPSILON * fabs(result->val); result->err += 2 * fabs(scale_factor * prefactor * result_g.err); if (status == GSL_SUCCESS) CHECK_UNDERFLOW(result); return status; } } }
int gsl_sf_bessel_k0_scaled_e(const double x, gsl_sf_result * result) { /* CHECK_POINTER(result) */ if(x <= 0.0) { DOMAIN_ERROR(result); } else { result->val = M_PI/(2.0*x); result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val); CHECK_UNDERFLOW(result); return GSL_SUCCESS; } }
int gsl_sf_hydrogenicR_1_e(const double Z, const double r, gsl_sf_result * result) { if(Z > 0.0 && r >= 0.0) { double A = 2.0*Z; double norm = A*sqrt(Z); double ea = exp(-Z*r); result->val = norm*ea; result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val) * fabs(Z*r); CHECK_UNDERFLOW(result); return GSL_SUCCESS; } else { DOMAIN_ERROR(result); } }
int gsl_sf_bessel_k1_scaled_e(const double x, gsl_sf_result * result) { /* CHECK_POINTER(result) */ if(x <= 0.0) { DOMAIN_ERROR(result); } else if(x < (M_SQRTPI+1.0)/(M_SQRT2*GSL_SQRT_DBL_MAX)) { OVERFLOW_ERROR(result); } else { result->val = M_PI/(2.0*x) * (1.0 + 1.0/x); result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val); CHECK_UNDERFLOW(result); return GSL_SUCCESS; } }
int gsl_sf_beta_inc_e( const double a, const double b, const double x, gsl_sf_result * result ) { if(a <= 0.0 || b <= 0.0 || x < 0.0 || x > 1.0) { DOMAIN_ERROR(result); } else if(x == 0.0) { result->val = 0.0; result->err = 0.0; return GSL_SUCCESS; } else if(x == 1.0) { result->val = 1.0; result->err = 0.0; return GSL_SUCCESS; } else { gsl_sf_result ln_beta; gsl_sf_result ln_x; gsl_sf_result ln_1mx; gsl_sf_result prefactor; const int stat_ln_beta = gsl_sf_lnbeta_e(a, b, &ln_beta); const int stat_ln_1mx = gsl_sf_log_1plusx_e(-x, &ln_1mx); const int stat_ln_x = gsl_sf_log_e(x, &ln_x); const int stat_ln = GSL_ERROR_SELECT_3(stat_ln_beta, stat_ln_1mx, stat_ln_x); const double ln_pre_val = -ln_beta.val + a * ln_x.val + b * ln_1mx.val; const double ln_pre_err = ln_beta.err + fabs(a*ln_x.err) + fabs(b*ln_1mx.err); const int stat_exp = gsl_sf_exp_err_e(ln_pre_val, ln_pre_err, &prefactor); if(stat_ln != GSL_SUCCESS) { result->val = 0.0; result->err = 0.0; GSL_ERROR ("error", GSL_ESANITY); } if(x < (a + 1.0)/(a+b+2.0)) { /* Apply continued fraction directly. */ gsl_sf_result cf; const int stat_cf = beta_cont_frac(a, b, x, &cf); int stat; result->val = prefactor.val * cf.val / a; result->err = (fabs(prefactor.err * cf.val) + fabs(prefactor.val * cf.err))/a; stat = GSL_ERROR_SELECT_2(stat_exp, stat_cf); if(stat == GSL_SUCCESS) { CHECK_UNDERFLOW(result); } return stat; } else { /* Apply continued fraction after hypergeometric transformation. */ gsl_sf_result cf; const int stat_cf = beta_cont_frac(b, a, 1.0-x, &cf); int stat; const double term = prefactor.val * cf.val / b; result->val = 1.0 - term; result->err = fabs(prefactor.err * cf.val)/b; result->err += fabs(prefactor.val * cf.err)/b; result->err += 2.0 * GSL_DBL_EPSILON * (1.0 + fabs(term)); stat = GSL_ERROR_SELECT_2(stat_exp, stat_cf); if(stat == GSL_SUCCESS) { CHECK_UNDERFLOW(result); } return stat; } } }