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

📄 hyperg_2f1.c

📁 开放gsl矩阵运算
💻 C
📖 第 1 页 / 共 2 页
字号:
      double psi_val = psi_1 + psi_1pd.val - psi_apd1.val - psi_bpd1.val - ln_omx;      double psi_err = psi_1pd.err + psi_apd1.err + psi_bpd1.err;      double fact = 1.0;      double sum2_val = psi_val;      double sum2_err = psi_err;      double ln_pre2_val = lng_c.val + d1*ln_omx - lng_ad2.val - lng_bd2.val;      double ln_pre2_err = lng_c.val + lng_ad2.val + lng_bd2.val + GSL_DBL_EPSILON * fabs(ln_pre2_val);      int stat_e;      /* Do F2 sum.       */      for(i=1; i<maxiter; i++) {        int j = i-1;	double term1 = 1.0/(1.0+j)  + 1.0/(1.0+ad+j);	double term2 = 1.0/(a+d1+j) + 1.0/(b+d1+j);        psi_val += term1 - term2;        psi_err += GSL_DBL_EPSILON * (fabs(term1) + fabs(term2));        fact *= (a+d1+j)*(b+d1+j)/(ad+j)/i * (1.0-x);        sum2_val += fact * psi_val;        sum2_err += fabs(fact * psi_err);      }      if(i == maxiter) stat_F2 = GSL_EMAXITER;      if(sum2_val == 0.0) {        F2.val = 0.0;	F2.err = 0.0;      }      else {        stat_e = gsl_sf_exp_mult_err_e(ln_pre2_val, ln_pre2_err,	                                  sum2_val, sum2_err,					  &F2);        if(stat_e == GSL_EOVRFLW) {          result->val = 0.0;	  result->err = 0.0;	  GSL_ERROR ("error", GSL_EOVRFLW);        }      }      stat_F2 = GSL_ERROR_SELECT_2(stat_F2, stat_dall);    }    else {      /* Gamma functions in the denominator not ok.       * So the F2 term is zero.       */      F2.val = 0.0;      F2.err = 0.0;    } /* end F2 evaluation */    sgn_2 = ( GSL_IS_ODD(intd) ? -1.0 : 1.0 );    result->val  = F1.val + sgn_2 * F2.val;    result->err  = F1.err + F2. err;    result->err += 2.0 * GSL_DBL_EPSILON * (fabs(F1.val) + fabs(F2.val));    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);    return stat_F2;  }  else {    /* d not an integer */    gsl_sf_result pre1, pre2;    double sgn1, sgn2;    gsl_sf_result F1, F2;    int status_F1, status_F2;    /* These gamma functions appear in the denominator, so we     * catch their harmless domain errors and set the terms to zero.     */    gsl_sf_result ln_g1ca,  ln_g1cb,  ln_g2a,  ln_g2b;    double sgn_g1ca, sgn_g1cb, sgn_g2a, sgn_g2b;    int stat_1ca = gsl_sf_lngamma_sgn_e(c-a, &ln_g1ca, &sgn_g1ca);    int stat_1cb = gsl_sf_lngamma_sgn_e(c-b, &ln_g1cb, &sgn_g1cb);    int stat_2a  = gsl_sf_lngamma_sgn_e(a, &ln_g2a, &sgn_g2a);    int stat_2b  = gsl_sf_lngamma_sgn_e(b, &ln_g2b, &sgn_g2b);    int ok1 = (stat_1ca == GSL_SUCCESS && stat_1cb == GSL_SUCCESS);    int ok2 = (stat_2a  == GSL_SUCCESS && stat_2b  == GSL_SUCCESS);        gsl_sf_result ln_gc,  ln_gd,  ln_gmd;    double sgn_gc, sgn_gd, sgn_gmd;    gsl_sf_lngamma_sgn_e( c, &ln_gc,  &sgn_gc);    gsl_sf_lngamma_sgn_e( d, &ln_gd,  &sgn_gd);    gsl_sf_lngamma_sgn_e(-d, &ln_gmd, &sgn_gmd);        sgn1 = sgn_gc * sgn_gd  * sgn_g1ca * sgn_g1cb;    sgn2 = sgn_gc * sgn_gmd * sgn_g2a  * sgn_g2b;    if(ok1 && ok2) {      double ln_pre1_val = ln_gc.val + ln_gd.val  - ln_g1ca.val - ln_g1cb.val;      double ln_pre2_val = ln_gc.val + ln_gmd.val - ln_g2a.val  - ln_g2b.val + d*log(1.0-x);      double ln_pre1_err = ln_gc.err + ln_gd.err + ln_g1ca.err + ln_g1cb.err;      double ln_pre2_err = ln_gc.err + ln_gmd.err + ln_g2a.err  + ln_g2b.err;      if(ln_pre1_val < GSL_LOG_DBL_MAX && ln_pre2_val < GSL_LOG_DBL_MAX) {        gsl_sf_exp_err_e(ln_pre1_val, ln_pre1_err, &pre1);	gsl_sf_exp_err_e(ln_pre2_val, ln_pre2_err, &pre2);        pre1.val *= sgn1;        pre2.val *= sgn2;      }      else {        OVERFLOW_ERROR(result);      }    }    else if(ok1 && !ok2) {      double ln_pre1_val = ln_gc.val + ln_gd.val - ln_g1ca.val - ln_g1cb.val;      double ln_pre1_err = ln_gc.err + ln_gd.err + ln_g1ca.err + ln_g1cb.err;      if(ln_pre1_val < GSL_LOG_DBL_MAX) {        gsl_sf_exp_err_e(ln_pre1_val, ln_pre1_err, &pre1);        pre1.val *= sgn1;        pre2.val = 0.0;	pre2.err = 0.0;      }      else {        OVERFLOW_ERROR(result);      }    }    else if(!ok1 && ok2) {      double ln_pre2_val = ln_gc.val + ln_gmd.val - ln_g2a.val - ln_g2b.val + d*log(1.0-x);      double ln_pre2_err = ln_gc.err + ln_gmd.err + ln_g2a.err + ln_g2b.err;      if(ln_pre2_val < GSL_LOG_DBL_MAX) {        pre1.val = 0.0;        pre1.err = 0.0;        gsl_sf_exp_err_e(ln_pre2_val, ln_pre2_err, &pre2);        pre2.val *= sgn2;      }      else {        OVERFLOW_ERROR(result);      }    }    else {      pre1.val = 0.0;      pre2.val = 0.0;      UNDERFLOW_ERROR(result);    }    status_F1 = hyperg_2F1_series(  a,   b, 1.0-d, 1.0-x, &F1);    status_F2 = hyperg_2F1_series(c-a, c-b, 1.0+d, 1.0-x, &F2);    result->val  = pre1.val*F1.val + pre2.val*F2.val;    result->err  = fabs(pre1.val*F1.err) + fabs(pre2.val*F2.err);    result->err += fabs(pre1.err*F1.val) + fabs(pre2.err*F2.val);    result->err += 2.0 * GSL_DBL_EPSILON * (fabs(pre1.val*F1.val) + fabs(pre2.val*F2.val));    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);    return GSL_SUCCESS;  }}static int pow_omx(const double x, const double p, gsl_sf_result * result){  double ln_omx;  double ln_result;  if(fabs(x) < GSL_ROOT5_DBL_EPSILON) {    ln_omx = -x*(1.0 + x*(1.0/2.0 + x*(1.0/3.0 + x/4.0 + x*x/5.0)));  }  else {    ln_omx = log(1.0-x);  }  ln_result = p * ln_omx;  return gsl_sf_exp_err_e(ln_result, GSL_DBL_EPSILON * fabs(ln_result), result);}/*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/intgsl_sf_hyperg_2F1_e(double a, double b, const double c,                       const double x,                       gsl_sf_result * result){  const double d = c - a - b;  const double rinta = floor(a + 0.5);  const double rintb = floor(b + 0.5);  const double rintc = floor(c + 0.5);  const int a_neg_integer = ( a < 0.0  &&  fabs(a - rinta) < locEPS );  const int b_neg_integer = ( b < 0.0  &&  fabs(b - rintb) < locEPS );  const int c_neg_integer = ( c < 0.0  &&  fabs(c - rintc) < locEPS );  result->val = 0.0;  result->err = 0.0;  if(x < -1.0 || 1.0 <= x) {    DOMAIN_ERROR(result);  }  if(c_neg_integer) {    if(! (a_neg_integer && a > c + 0.1)) DOMAIN_ERROR(result);    if(! (b_neg_integer && b > c + 0.1)) DOMAIN_ERROR(result);  }  if(fabs(c-b) < locEPS || fabs(c-a) < locEPS) {    return pow_omx(x, d, result);  /* (1-x)^(c-a-b) */  }  if(a >= 0.0 && b >= 0.0 && c >=0.0 && x >= 0.0) {    /* Series has all positive definite terms.     */    return hyperg_2F1_series(a, b, c, x, result);  }  if(fabs(a) < 10.0 && fabs(b) < 10.0) {    /* a and b are not too large, so we attempt     * variations on the series summation.     */    if(a_neg_integer) {      return hyperg_2F1_series(rinta, b, c, x, result);    }    if(b_neg_integer) {      return hyperg_2F1_series(a, rintb, c, x, result);    }    if(x < -0.25) {      return hyperg_2F1_luke(a, b, c, x, result);    }    else if(x < 0.5) {      return hyperg_2F1_series(a, b, c, x, result);    }    else {      if(fabs(c) > 10.0) {        return hyperg_2F1_series(a, b, c, x, result);      }      else {        return hyperg_2F1_reflect(a, b, c, x, result);      }    }  }  else {    /* Either a or b or both large.     * Introduce some new variables ap,bp so that bp is     * the larger in magnitude.     */    double ap, bp;     if(fabs(a) > fabs(b)) {      bp = a;      ap = b;    }    else {      bp = b;      ap = a;    }    if(x < 0.0) {      /* What the hell, maybe Luke will converge.       */      return hyperg_2F1_luke(a, b, c, x, result);    }    if(GSL_MAX_DBL(fabs(a),1.0)*fabs(bp)*fabs(x) < 2.0*fabs(c)) {      /* If c is large enough or x is small enough,       * we can attempt the series anyway.       */      return hyperg_2F1_series(a, b, c, x, result);    }    if(fabs(bp*bp*x*x) < 0.001*fabs(bp) && fabs(a) < 10.0) {      /* The famous but nearly worthless "large b" asymptotic.       */      int stat = gsl_sf_hyperg_1F1_e(a, c, bp*x, result);      result->err = 0.001 * fabs(result->val);      return stat;    }    /* We give up. */    result->val = 0.0;    result->err = 0.0;    GSL_ERROR ("error", GSL_EUNIMPL);  }}intgsl_sf_hyperg_2F1_conj_e(const double aR, const double aI, const double c,                            const double x,                            gsl_sf_result * result){  const double ax = fabs(x);  const double rintc = floor(c + 0.5);  const int c_neg_integer = ( c < 0.0  &&  fabs(c - rintc) < locEPS );  result->val = 0.0;  result->err = 0.0;  if(ax >= 1.0 || c_neg_integer || c == 0.0) {    DOMAIN_ERROR(result);  }  if(   (ax < 0.25 && fabs(aR) < 20.0 && fabs(aI) < 20.0)     || (c > 0.0 && x > 0.0)    ) {    return hyperg_2F1_conj_series(aR, aI, c, x, result);  }  else if(fabs(aR) < 10.0 && fabs(aI) < 10.0) {    if(x < -0.25) {      return hyperg_2F1_conj_luke(aR, aI, c, x, result);    }    else {      return hyperg_2F1_conj_series(aR, aI, c, x, result);    }  }  else {    if(x < 0.0) {      /* What the hell, maybe Luke will converge.       */      return hyperg_2F1_conj_luke(aR, aI, c, x, result);     }    /* Give up. */    result->val = 0.0;    result->err = 0.0;    GSL_ERROR ("error", GSL_EUNIMPL);  }}intgsl_sf_hyperg_2F1_renorm_e(const double a, const double b, const double c,                              const double x,			      gsl_sf_result * result			      ){  const double rinta = floor(a + 0.5);  const double rintb = floor(b + 0.5);  const double rintc = floor(c + 0.5);  const int a_neg_integer = ( a < 0.0  &&  fabs(a - rinta) < locEPS );  const int b_neg_integer = ( b < 0.0  &&  fabs(b - rintb) < locEPS );  const int c_neg_integer = ( c < 0.0  &&  fabs(c - rintc) < locEPS );    if(c_neg_integer) {    if((a_neg_integer && a > c+0.1) || (b_neg_integer && b > c+0.1)) {      /* 2F1 terminates early */      result->val = 0.0;      result->err = 0.0;      return GSL_SUCCESS;    }    else {      /* 2F1 does not terminate early enough, so something survives */      /* [Abramowitz+Stegun, 15.1.2] */      gsl_sf_result g1, g2, g3, g4, g5;      double s1, s2, s3, s4, s5;      int stat = 0;      stat += gsl_sf_lngamma_sgn_e(a-c+1, &g1, &s1);      stat += gsl_sf_lngamma_sgn_e(b-c+1, &g2, &s2);      stat += gsl_sf_lngamma_sgn_e(a, &g3, &s3);      stat += gsl_sf_lngamma_sgn_e(b, &g4, &s4);      stat += gsl_sf_lngamma_sgn_e(-c+2, &g5, &s5);      if(stat != 0) {        DOMAIN_ERROR(result);      }      else {        gsl_sf_result F;        int stat_F = gsl_sf_hyperg_2F1_e(a-c+1, b-c+1, -c+2, x, &F);        double ln_pre_val = g1.val + g2.val - g3.val - g4.val - g5.val;	double ln_pre_err = g1.err + g2.err + g3.err + g4.err + g5.err;	double sg  = s1 * s2 * s3 * s4 * s5;	int stat_e = gsl_sf_exp_mult_err_e(ln_pre_val, ln_pre_err,	                                      sg * F.val, F.err,					      result);	return GSL_ERROR_SELECT_2(stat_e, stat_F);      }    }  }  else {    /* generic c */    gsl_sf_result F;    gsl_sf_result lng;    double sgn;    int stat_g = gsl_sf_lngamma_sgn_e(c, &lng, &sgn);    int stat_F = gsl_sf_hyperg_2F1_e(a, b, c, x, &F);    int stat_e = gsl_sf_exp_mult_err_e(-lng.val, lng.err,                                          sgn*F.val, F.err,					  result);    return GSL_ERROR_SELECT_3(stat_e, stat_F, stat_g);  }}intgsl_sf_hyperg_2F1_conj_renorm_e(const double aR, const double aI, const double c,                                   const double x,			           gsl_sf_result * result			           ){  const double rintc = floor(c  + 0.5);  const double rinta = floor(aR + 0.5);  const int a_neg_integer = ( aR < 0.0 && fabs(aR-rinta) < locEPS && aI == 0.0);  const int c_neg_integer = (  c < 0.0 && fabs(c - rintc) < locEPS );  if(c_neg_integer) {    if(a_neg_integer && aR > c+0.1) {      /* 2F1 terminates early */      result->val = 0.0;      result->err = 0.0;      return GSL_SUCCESS;    }    else {      /* 2F1 does not terminate early enough, so something survives */      /* [Abramowitz+Stegun, 15.1.2] */      gsl_sf_result g1, g2;      gsl_sf_result g3;      gsl_sf_result a1, a2;      int stat = 0;      stat += gsl_sf_lngamma_complex_e(aR-c+1, aI, &g1, &a1);      stat += gsl_sf_lngamma_complex_e(aR, aI, &g2, &a2);      stat += gsl_sf_lngamma_e(-c+2.0, &g3);      if(stat != 0) {        DOMAIN_ERROR(result);      }      else {        gsl_sf_result F;        int stat_F = gsl_sf_hyperg_2F1_conj_e(aR-c+1, aI, -c+2, x, &F);        double ln_pre_val = 2.0*(g1.val - g2.val) - g3.val;	double ln_pre_err = 2.0 * (g1.err + g2.err) + g3.err;	int stat_e = gsl_sf_exp_mult_err_e(ln_pre_val, ln_pre_err,                                              F.val, F.err,                                              result);	return GSL_ERROR_SELECT_2(stat_e, stat_F);      }    }  }  else {    /* generic c */    gsl_sf_result F;    gsl_sf_result lng;    double sgn;    int stat_g = gsl_sf_lngamma_sgn_e(c, &lng, &sgn);    int stat_F = gsl_sf_hyperg_2F1_conj_e(aR, aI, c, x, &F);    int stat_e = gsl_sf_exp_mult_err_e(-lng.val, lng.err,                                          sgn*F.val, F.err,                                          result);    return GSL_ERROR_SELECT_3(stat_e, stat_F, stat_g);  }}/*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/#include "eval.h"double gsl_sf_hyperg_2F1(double a, double b, double c, double x){  EVAL_RESULT(gsl_sf_hyperg_2F1_e(a, b, c, x, &result));}double gsl_sf_hyperg_2F1_conj(double aR, double aI, double c, double x){  EVAL_RESULT(gsl_sf_hyperg_2F1_conj_e(aR, aI, c, x, &result));}double gsl_sf_hyperg_2F1_renorm(double a, double b, double c, double x){  EVAL_RESULT(gsl_sf_hyperg_2F1_renorm_e(a, b, c, x, &result));}double gsl_sf_hyperg_2F1_conj_renorm(double aR, double aI, double c, double x){  EVAL_RESULT(gsl_sf_hyperg_2F1_conj_renorm_e(aR, aI, c, x, &result));}

⌨️ 快捷键说明

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