📄 ellint.c
字号:
double lamda, alfa, beta; double epslon; gsl_sf_result rcresult; int rcstatus; mu = (xn + yn + zn + pn + pn) * 0.2; xndev = (mu - xn) / mu; yndev = (mu - yn) / mu; zndev = (mu - zn) / mu; pndev = (mu - pn) / mu; epslon = locMAX4(fabs(xndev), fabs(yndev), fabs(zndev), fabs(pndev)); if(epslon < errtol) break; xnroot = sqrt(xn); ynroot = sqrt(yn); znroot = sqrt(zn); lamda = xnroot * (ynroot + znroot) + ynroot * znroot; alfa = pn * (xnroot + ynroot + znroot) + xnroot * ynroot * znroot; alfa = alfa * alfa; beta = pn * (pn + lamda) * (pn + lamda); rcstatus = gsl_sf_ellint_RC_e(alfa, beta, mode, &rcresult); if(rcstatus != GSL_SUCCESS) { result->val = 0.0; result->err = 0.0; return rcstatus; } sigma += power4 * rcresult.val; power4 *= 0.25; xn = (xn + lamda) * 0.25; yn = (yn + lamda) * 0.25; zn = (zn + lamda) * 0.25; pn = (pn + lamda) * 0.25; } ea = xndev * (yndev + zndev) + yndev * zndev; eb = xndev * yndev * zndev; ec = pndev * pndev; e2 = ea - 3.0 * ec; e3 = eb + 2.0 * pndev * (ea - ec); s1 = 1.0 + e2 * (- c1 + 0.75 * c3 * e2 - 1.5 * c4 * e3); s2 = eb * (0.5 * c2 + pndev * (- c3 - c3 + pndev * c4)); s3 = pndev * ea * (c2 - pndev * c3) - c2 * pndev * ec; result->val = 3.0 * sigma + power4 * (s1 + s2 + s3) / (mu * sqrt(mu)); result->err = prec * fabs(result->val); return GSL_SUCCESS; } else { DOMAIN_ERROR(result); }}/* [Carlson, Numer. Math. 33 (1979) 1, (4.1)] */intgsl_sf_ellint_F_e(double phi, double k, gsl_mode_t mode, gsl_sf_result * result){ double sin_phi = sin(phi); double sin2_phi = sin_phi*sin_phi; double x = 1.0 - sin2_phi; double y = 1.0 - k*k*sin2_phi; gsl_sf_result rf; int status = gsl_sf_ellint_RF_e(x, y, 1.0, mode, &rf); result->val = sin_phi * rf.val; result->err = GSL_DBL_EPSILON * fabs(result->val) + fabs(sin_phi*rf.err); return status;}/* [Carlson, Numer. Math. 33 (1979) 1, (4.2)] */intgsl_sf_ellint_E_e(double phi, double k, gsl_mode_t mode, gsl_sf_result * result){ const double sin_phi = sin(phi); const double sin2_phi = sin_phi * sin_phi; const double x = 1.0 - sin2_phi; const double y = 1.0 - k*k*sin2_phi; if(x < GSL_DBL_EPSILON) { return gsl_sf_ellint_Ecomp_e(k, mode, result); } else { gsl_sf_result rf; gsl_sf_result rd; const double sin3_phi = sin2_phi * sin_phi; const int rfstatus = gsl_sf_ellint_RF_e(x, y, 1.0, mode, &rf); const int rdstatus = gsl_sf_ellint_RD_e(x, y, 1.0, mode, &rd); result->val = sin_phi * rf.val - k*k/3.0 * sin3_phi * rd.val; result->err = GSL_DBL_EPSILON * fabs(sin_phi * rf.val); result->err += fabs(sin_phi*rf.err); result->err += k*k/3.0 * GSL_DBL_EPSILON * fabs(sin3_phi * rd.val); result->err += k*k/3.0 * fabs(sin3_phi*rd.err); return GSL_ERROR_SELECT_2(rfstatus, rdstatus); }}/* [Carlson, Numer. Math. 33 (1979) 1, (4.3)] */intgsl_sf_ellint_P_e(double phi, double k, double n, gsl_mode_t mode, gsl_sf_result * result){ const double sin_phi = sin(phi); const double sin2_phi = sin_phi * sin_phi; const double sin3_phi = sin2_phi * sin_phi; const double x = 1.0 - sin2_phi; const double y = 1.0 - k*k*sin2_phi; gsl_sf_result rf; gsl_sf_result rj; const int rfstatus = gsl_sf_ellint_RF_e(x, y, 1.0, mode, &rf); const int rjstatus = gsl_sf_ellint_RJ_e(x, y, 1.0, 1.0 + n*sin2_phi, mode, &rj); result->val = sin_phi * rf.val - n/3.0*sin3_phi * rj.val; result->err = GSL_DBL_EPSILON * fabs(sin_phi * rf.val); result->err += n/3.0 * fabs(sin3_phi*rj.err); return GSL_ERROR_SELECT_2(rfstatus, rjstatus);}/* [Carlson, Numer. Math. 33 (1979) 1, (4.4)] */intgsl_sf_ellint_D_e(double phi, double k, double n, gsl_mode_t mode, gsl_sf_result * result){ const double sin_phi = sin(phi); const double sin2_phi = sin_phi * sin_phi; const double sin3_phi = sin2_phi * sin_phi; const double x = 1.0 - sin2_phi; const double y = 1.0 - k*k*sin2_phi; gsl_sf_result rd; const int status = gsl_sf_ellint_RD_e(x, y, 1.0, mode, &rd); result->val = sin3_phi/3.0 * rd.val; result->err = GSL_DBL_EPSILON * fabs(result->val) + fabs(sin3_phi/3.0 * rd.err); return status;}/* [Carlson, Numer. Math. 33 (1979) 1, (4.5)] */intgsl_sf_ellint_Kcomp_e(double k, gsl_mode_t mode, gsl_sf_result * result){ if(k*k >= 1.0) { DOMAIN_ERROR(result); } else if(k*k >= 1.0 - GSL_SQRT_DBL_EPSILON) { /* [Abramowitz+Stegun, 17.3.33] */ const double y = 1.0 - k*k; const double a[] = { 1.38629436112, 0.09666344259, 0.03590092383 }; const double b[] = { 0.5, 0.12498593597, 0.06880248576 }; const double ta = a[0] + y*(a[1] + y*a[2]); const double tb = -log(y) * (b[0] * y*(b[1] + y*b[2])); result->val = ta + tb; result->err = 2.0 * GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else { /* This was previously computed as, return gsl_sf_ellint_RF_e(0.0, 1.0 - k*k, 1.0, mode, result); but this underestimated the total error for small k, since the argument y=1-k^2 is not exact (there is an absolute error of GSL_DBL_EPSILON near y=0 due to cancellation in the subtraction). Taking the singular behavior of -log(y) above gives an error of 0.5*epsilon/y near y=0. (BJG) */ double y = 1.0 - k*k; int status = gsl_sf_ellint_RF_e(0.0, y, 1.0, mode, result); result->err += 0.5 * GSL_DBL_EPSILON / y; return status ; }}/* [Carlson, Numer. Math. 33 (1979) 1, (4.6)] */intgsl_sf_ellint_Ecomp_e(double k, gsl_mode_t mode, gsl_sf_result * result){ if(k*k >= 1.0) { DOMAIN_ERROR(result); } else if(k*k >= 1.0 - GSL_SQRT_DBL_EPSILON) { /* [Abramowitz+Stegun, 17.3.36] */ const double y = 1.0 - k*k; const double a[] = { 0.44325141463, 0.06260601220, 0.04757383546 }; const double b[] = { 0.24998368310, 0.09200180037, 0.04069697526 }; const double ta = 1.0 + y*(a[0] + y*(a[1] + a[2]*y)); const double tb = -y*log(y) * (b[0] + y*(b[1] + b[2]*y)); result->val = ta + tb; result->err = 2.0 * GSL_DBL_EPSILON * result->val; return GSL_SUCCESS; } else { gsl_sf_result rf; gsl_sf_result rd; const double y = 1.0 - k*k; const int rfstatus = gsl_sf_ellint_RF_e(0.0, y, 1.0, mode, &rf); const int rdstatus = gsl_sf_ellint_RD_e(0.0, y, 1.0, mode, &rd); result->val = rf.val - k*k/3.0 * rd.val; result->err = rf.err + k*k/3.0 * rd.err; return GSL_ERROR_SELECT_2(rfstatus, rdstatus); }}/*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/#include "eval.h"double gsl_sf_ellint_Kcomp(double k, gsl_mode_t mode){ EVAL_RESULT(gsl_sf_ellint_Kcomp_e(k, mode, &result));}double gsl_sf_ellint_Ecomp(double k, gsl_mode_t mode){ EVAL_RESULT(gsl_sf_ellint_Ecomp_e(k, mode, &result));}double gsl_sf_ellint_F(double phi, double k, gsl_mode_t mode){ EVAL_RESULT(gsl_sf_ellint_F_e(phi, k, mode, &result));}double gsl_sf_ellint_E(double phi, double k, gsl_mode_t mode){ EVAL_RESULT(gsl_sf_ellint_E_e(phi, k, mode, &result));}double gsl_sf_ellint_P(double phi, double k, double n, gsl_mode_t mode){ EVAL_RESULT(gsl_sf_ellint_P_e(phi, k, n, mode, &result));}double gsl_sf_ellint_D(double phi, double k, double n, gsl_mode_t mode){ EVAL_RESULT(gsl_sf_ellint_D_e(phi, k, n, mode, &result));}double gsl_sf_ellint_RC(double x, double y, gsl_mode_t mode){ EVAL_RESULT(gsl_sf_ellint_RC_e(x, y, mode, &result));}double gsl_sf_ellint_RD(double x, double y, double z, gsl_mode_t mode){ EVAL_RESULT(gsl_sf_ellint_RD_e(x, y, z, mode, &result));}double gsl_sf_ellint_RF(double x, double y, double z, gsl_mode_t mode){ EVAL_RESULT(gsl_sf_ellint_RF_e(x, y, z, mode, &result));}double gsl_sf_ellint_RJ(double x, double y, double z, double p, gsl_mode_t mode){ EVAL_RESULT(gsl_sf_ellint_RJ_e(x, y, z, p, mode, &result));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -