⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gamma_inc.c

📁 该文件为c++的数学函数库!是一个非常有用的编程工具.它含有各种数学函数,为科学计算、工程应用等程序编写提供方便!
💻 C
📖 第 1 页 / 共 2 页
字号:
                       * ( 3.041323283529310 + lnx)                       * ( 8.295966556941250 + lnx);    const double c9 = -2.75573192239859e-6                       * (-2.8243487670469080 + lnx)                       * (-2.3798494322701120 + lnx)                       * (-1.9143674728689960 + lnx)                       * (-1.3814529102920370 + lnx)                       * (-0.7294312810261694 + lnx)                       * ( 0.1299079285269565 + lnx)                       * ( 1.3873333251885240 + lnx)                       * ( 3.5857258865210760 + lnx)                       * ( 9.3214237073814600 + lnx);    const double c10 = -2.75573192239859e-7                       * (-2.9540329644556910 + lnx)                       * (-2.5491366926991850 + lnx)                       * (-2.1348279229279880 + lnx)                       * (-1.6741881076349450 + lnx)                       * (-1.1325949616098420 + lnx)                       * (-0.4590034650618494 + lnx)                       * ( 0.4399352987435699 + lnx)                       * ( 1.7702236517651670 + lnx)                       * ( 4.1231539047474080 + lnx)                       * ( 10.342627908148680 + lnx);    term1 = a*(c1+a*(c2+a*(c3+a*(c4+a*(c5+a*(c6+a*(c7+a*(c8+a*(c9+a*c10)))))))));  }  {    /* Evaluate the sum.     */    const int nmax = 5000;    double t = 1.0;    int n;    sum = 1.0;    for(n=1; n<nmax; n++) {      t *= -x/(n+1.0);      sum += (a+1.0)/(a+n+1.0)*t;      if(fabs(t/sum) < GSL_DBL_EPSILON) break;    }        if(n == nmax)      stat_sum = GSL_EMAXITER;    else      stat_sum = GSL_SUCCESS;  }  term2 = (1.0 - term1) * a/(a+1.0) * x * sum;  result->val  = term1 + term2;  result->err  = GSL_DBL_EPSILON * (fabs(term1) + 2.0*fabs(term2));  result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);  return stat_sum;}/* series for small a and x, but not defined for a == 0 */static intgamma_inc_series(double a, double x, gsl_sf_result * result){  gsl_sf_result Q;  gsl_sf_result G;  const int stat_Q = gamma_inc_Q_series(a, x, &Q);  const int stat_G = gsl_sf_gamma_e(a, &G);  result->val = Q.val * G.val;  result->err = fabs(Q.val * G.err) + fabs(Q.err * G.val);  result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);  return GSL_ERROR_SELECT_2(stat_Q, stat_G);}static intgamma_inc_a_gt_0(double a, double x, gsl_sf_result * result){  /* x > 0 and a > 0; use result for Q */  gsl_sf_result Q;  gsl_sf_result G;  const int stat_Q = gsl_sf_gamma_inc_Q_e(a, x, &Q);  const int stat_G = gsl_sf_gamma_e(a, &G);  result->val = G.val * Q.val;  result->err = fabs(G.val * Q.err) + fabs(G.err * Q.val);  result->err += 2.0*GSL_DBL_EPSILON * fabs(result->val);  return GSL_ERROR_SELECT_2(stat_G, stat_Q);}static intgamma_inc_CF(double a, double x, gsl_sf_result * result){  gsl_sf_result F;  gsl_sf_result pre;  const int stat_F = gamma_inc_F_CF(a, x, &F);  const int stat_E = gsl_sf_exp_e((a-1.0)*log(x) - x, &pre);  result->val = F.val * pre.val;  result->err = fabs(F.err * pre.val) + fabs(F.val * pre.err);  result->err += (2.0 + fabs(a)) * GSL_DBL_EPSILON * fabs(result->val);  return GSL_ERROR_SELECT_2(stat_F, stat_E);}/* evaluate Gamma(0,x), x > 0 */#define GAMMA_INC_A_0(x, result) gsl_sf_expint_E1_e(x, result)/*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/intgsl_sf_gamma_inc_Q_e(const double a, const double x, gsl_sf_result * result){  if(a < 0.0 || x < 0.0) {    DOMAIN_ERROR(result);  }  else if(x == 0.0) {    result->val = 1.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(a == 0.0)  {    result->val = 0.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(x <= 0.5*a) {    /* If the series is quick, do that. It is     * robust and simple.     */    gsl_sf_result P;    int stat_P = gamma_inc_P_series(a, x, &P);    result->val  = 1.0 - P.val;    result->err  = P.err;    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);    return stat_P;  }  else if(a >= 1.0e+06 && (x-a)*(x-a) < a) {    /* Then try the difficult asymptotic regime.     * This is the only way to do this region.     */    return gamma_inc_Q_asymp_unif(a, x, result);  }  else if(a < 0.2 && x < 5.0) {    /* Cancellations at small a must be handled     * analytically; x should not be too big     * either since the series terms grow     * with x and log(x).     */    return gamma_inc_Q_series(a, x, result);  }  else if(a <= x) {    if(x <= 1.0e+06) {      /* Continued fraction is excellent for x >~ a.       * We do not let x be too large when x > a since       * it is somewhat pointless to try this there;       * the function is rapidly decreasing for       * x large and x > a, and it will just       * underflow in that region anyway. We        * catch that case in the standard       * large-x method.       */      return gamma_inc_Q_CF(a, x, result);    }    else {      return gamma_inc_Q_large_x(a, x, result);    }  }  else {    if(a < 0.8*x) {      /* Continued fraction again. The convergence       * is a little slower here, but that is fine.       * We have to trade that off against the slow       * convergence of the series, which is the       * only other option.       */      return gamma_inc_Q_CF(a, x, result);    }    else {      gsl_sf_result P;      int stat_P = gamma_inc_P_series(a, x, &P);      result->val  = 1.0 - P.val;      result->err  = P.err;      result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);      return stat_P;    }  }}intgsl_sf_gamma_inc_P_e(const double a, const double x, gsl_sf_result * result){  if(a <= 0.0 || x < 0.0) {    DOMAIN_ERROR(result);  }  else if(x == 0.0) {    result->val = 0.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(x < 20.0 || x < 0.5*a) {    /* Do the easy series cases. Robust and quick.     */    return gamma_inc_P_series(a, x, result);  }  else if(a > 1.0e+06 && (x-a)*(x-a) < a) {    /* Crossover region. Note that Q and P are     * roughly the same order of magnitude here,     * so the subtraction is stable.     */    gsl_sf_result Q;    int stat_Q = gamma_inc_Q_asymp_unif(a, x, &Q);    result->val  = 1.0 - Q.val;    result->err  = Q.err;    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);    return stat_Q;  }  else if(a <= x) {    /* Q <~ P in this area, so the     * subtractions are stable.     */    gsl_sf_result Q;    int stat_Q;    if(a > 0.2*x) {      stat_Q = gamma_inc_Q_CF(a, x, &Q);    }    else {      stat_Q = gamma_inc_Q_large_x(a, x, &Q);    }    result->val  = 1.0 - Q.val;    result->err  = Q.err;    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);    return stat_Q;  }  else {    if((x-a)*(x-a) < a) {      /* This condition is meant to insure       * that Q is not very close to 1,       * so the subtraction is stable.       */      gsl_sf_result Q;      int stat_Q = gamma_inc_Q_CF(a, x, &Q);      result->val  = 1.0 - Q.val;      result->err  = Q.err;      result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);      return stat_Q;    }    else {      return gamma_inc_P_series(a, x, result);    }  }}intgsl_sf_gamma_inc_e(const double a, const double x, gsl_sf_result * result){    if(x < 0.0) {    DOMAIN_ERROR(result);  }  else if(x == 0.0) {    return gsl_sf_gamma_e(a, result);  }  else if(a == 0.0)  {    return GAMMA_INC_A_0(x, result);  }  else if(a > 0.0)  {    return gamma_inc_a_gt_0(a, x, result);  }  else if(x > 0.25)  {    /* continued fraction seems to fail for x too small; otherwise       it is ok, independent of the value of |x/a|, because of the       non-oscillation in the expansion, i.e. the CF is       un-conditionally convergent for a < 0 and x > 0     */    return gamma_inc_CF(a, x, result);  }  else if(fabs(a) < 0.5)  {    return gamma_inc_series(a, x, result);  }  else  {    /* a = fa + da; da >= 0 */    const double fa = floor(a);    const double da = a - fa;    gsl_sf_result g_da;    const int stat_g_da = ( da > 0.0 ? gamma_inc_a_gt_0(da, x, &g_da)                                     : GAMMA_INC_A_0(x, &g_da));    double alpha = da;    double gax = g_da.val;    /* Gamma(alpha-1,x) = 1/(alpha-1) (Gamma(a,x) - x^(alpha-1) e^-x) */    do    {      const double shift = exp(-x + (alpha-1.0)*log(x));      gax = (gax - shift) / (alpha - 1.0);      alpha -= 1.0;    } while(alpha > a);    result->val = gax;    result->err = 2.0*(1.0 + fabs(a))*GSL_DBL_EPSILON*fabs(gax);    return stat_g_da;  }}/*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/#include "eval.h"double gsl_sf_gamma_inc_P(const double a, const double x){  EVAL_RESULT(gsl_sf_gamma_inc_P_e(a, x, &result));}double gsl_sf_gamma_inc_Q(const double a, const double x){  EVAL_RESULT(gsl_sf_gamma_inc_Q_e(a, x, &result));}double gsl_sf_gamma_inc(const double a, const double x){   EVAL_RESULT(gsl_sf_gamma_inc_e(a, x, &result));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -