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

📄 hyperg_1f1.c

📁 math library from gnu
💻 C
📖 第 1 页 / 共 5 页
字号:
inthyperg_1F1_renorm_b0(const double a, const double x, gsl_sf_result * result){  double eta = a*x;  if(eta > 0.0) {    double root_eta = sqrt(eta);    gsl_sf_result I1_scaled;    int stat_I = gsl_sf_bessel_I1_scaled_e(2.0*root_eta, &I1_scaled);    if(I1_scaled.val <= 0.0) {      result->val = 0.0;      result->err = 0.0;      return GSL_ERROR_SELECT_2(stat_I, GSL_EDOM);    }    else {      /* Note that 13.3.7 contains higher terms which are zeroth order         in b.  These make a non-negligible contribution to the sum.         With the first correction term, the I1 above is replaced by         I1 + (2/3)*a*(x/(4a))**(3/2)*I2(2*root_eta).  We will add         this as part of the result and error estimate. */      const double corr1 =(2.0/3.0)*a*pow(x/(4.0*a),1.5)*gsl_sf_bessel_In_scaled(2, 2.0*root_eta) ;      const double lnr_val = 0.5*x + 0.5*log(eta) + fabs(2.0*root_eta) + log(I1_scaled.val+corr1);      const double lnr_err = GSL_DBL_EPSILON * (1.5*fabs(x) + 1.0) + fabs((I1_scaled.err+corr1)/I1_scaled.val);      return gsl_sf_exp_err_e(lnr_val, lnr_err, result);    }  }  else if(eta == 0.0) {    result->val = 0.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else {    /* eta < 0 */    double root_eta = sqrt(-eta);    gsl_sf_result J1;    int stat_J = gsl_sf_bessel_J1_e(2.0*root_eta, &J1);    if(J1.val <= 0.0) {      result->val = 0.0;      result->err = 0.0;      return GSL_ERROR_SELECT_2(stat_J, GSL_EDOM);    }    else {      const double t1 = 0.5*x;      const double t2 = 0.5*log(-eta);      const double t3 = fabs(x);      const double t4 = log(J1.val);      const double lnr_val = t1 + t2 + t3 + t4;      const double lnr_err = GSL_DBL_EPSILON * (1.5*fabs(x) + 1.0) + fabs(J1.err/J1.val);      gsl_sf_result ex;      int stat_e = gsl_sf_exp_err_e(lnr_val, lnr_err, &ex);      result->val = -ex.val;      result->err =  ex.err;      return stat_e;    }  }  }/* 1F1'(a,b,x)/1F1(a,b,x) * Uses Gautschi's version of the CF. * [Gautschi, Math. Comp. 31, 994 (1977)] * * Supposedly this suffers from the "anomalous convergence" * problem when b < x. I have seen anomalous convergence * in several of the continued fractions associated with * 1F1(a,b,x). This particular CF formulation seems stable * for b > x. However, it does display a painful artifact * of the anomalous convergence; the convergence plateaus * unless b >>> x. For example, even for b=1000, x=1, this * method locks onto a ratio which is only good to about * 4 digits. Apparently the rest of the digits are hiding * way out on the plateau, but finite-precision lossage * means you will never get them. */#if 0staticinthyperg_1F1_CF1_p(const double a, const double b, const double x, double * result){  const double RECUR_BIG = GSL_SQRT_DBL_MAX;  const int maxiter = 5000;  int n = 1;  double Anm2 = 1.0;  double Bnm2 = 0.0;  double Anm1 = 0.0;  double Bnm1 = 1.0;  double a1 = 1.0;  double b1 = 1.0;  double An = b1*Anm1 + a1*Anm2;  double Bn = b1*Bnm1 + a1*Bnm2;  double an, bn;  double fn = An/Bn;  while(n < maxiter) {    double old_fn;    double del;    n++;    Anm2 = Anm1;    Bnm2 = Bnm1;    Anm1 = An;    Bnm1 = Bn;    an = (a+n)*x/((b-x+n-1)*(b-x+n));    bn = 1.0;    An = bn*Anm1 + an*Anm2;    Bn = bn*Bnm1 + an*Bnm2;    if(fabs(An) > RECUR_BIG || fabs(Bn) > RECUR_BIG) {      An /= RECUR_BIG;      Bn /= RECUR_BIG;      Anm1 /= RECUR_BIG;      Bnm1 /= RECUR_BIG;      Anm2 /= RECUR_BIG;      Bnm2 /= RECUR_BIG;    }    old_fn = fn;    fn = An/Bn;    del = old_fn/fn;        if(fabs(del - 1.0) < 10.0*GSL_DBL_EPSILON) break;  }  *result = a/(b-x) * fn;  if(n == maxiter)    GSL_ERROR ("error", GSL_EMAXITER);  else    return GSL_SUCCESS;}#endif /* 0 *//* 1F1'(a,b,x)/1F1(a,b,x) * Uses Gautschi's series transformation of the * continued fraction. This is apparently the best * method for getting this ratio in the stable region. * The convergence is monotone and supergeometric * when b > x. * Assumes a >= -1. */staticinthyperg_1F1_CF1_p_ser(const double a, const double b, const double x, double * result){  if(a == 0.0) {    *result = 0.0;    return GSL_SUCCESS;  }  else {    const int maxiter = 5000;    double sum  = 1.0;    double pk   = 1.0;    double rhok = 0.0;    int k;    for(k=1; k<maxiter; k++) {      double ak = (a + k)*x/((b-x+k-1.0)*(b-x+k));      rhok = -ak*(1.0 + rhok)/(1.0 + ak*(1.0+rhok));      pk  *= rhok;      sum += pk;      if(fabs(pk/sum) < 2.0*GSL_DBL_EPSILON) break;    }    *result = a/(b-x) * sum;    if(k == maxiter)      GSL_ERROR ("error", GSL_EMAXITER);    else      return GSL_SUCCESS;  }}/* 1F1(a+1,b,x)/1F1(a,b,x) * * I think this suffers from typical "anomalous convergence". * I could not find a region where it was truly useful. */#if 0staticinthyperg_1F1_CF1(const double a, const double b, const double x, double * result){  const double RECUR_BIG = GSL_SQRT_DBL_MAX;  const int maxiter = 5000;  int n = 1;  double Anm2 = 1.0;  double Bnm2 = 0.0;  double Anm1 = 0.0;  double Bnm1 = 1.0;  double a1 = b - a - 1.0;  double b1 = b - x - 2.0*(a+1.0);  double An = b1*Anm1 + a1*Anm2;  double Bn = b1*Bnm1 + a1*Bnm2;  double an, bn;  double fn = An/Bn;  while(n < maxiter) {    double old_fn;    double del;    n++;    Anm2 = Anm1;    Bnm2 = Bnm1;    Anm1 = An;    Bnm1 = Bn;    an = (a + n - 1.0) * (b - a - n);    bn = b - x - 2.0*(a+n);    An = bn*Anm1 + an*Anm2;    Bn = bn*Bnm1 + an*Bnm2;    if(fabs(An) > RECUR_BIG || fabs(Bn) > RECUR_BIG) {      An /= RECUR_BIG;      Bn /= RECUR_BIG;      Anm1 /= RECUR_BIG;      Bnm1 /= RECUR_BIG;      Anm2 /= RECUR_BIG;      Bnm2 /= RECUR_BIG;    }    old_fn = fn;    fn = An/Bn;    del = old_fn/fn;        if(fabs(del - 1.0) < 10.0*GSL_DBL_EPSILON) break;  }  *result = fn;  if(n == maxiter)    GSL_ERROR ("error", GSL_EMAXITER);  else    return GSL_SUCCESS;}#endif /* 0 *//* 1F1(a,b+1,x)/1F1(a,b,x) * * This seemed to suffer from "anomalous convergence". * However, I have no theory for this recurrence. */#if 0staticinthyperg_1F1_CF1_b(const double a, const double b, const double x, double * result){  const double RECUR_BIG = GSL_SQRT_DBL_MAX;  const int maxiter = 5000;  int n = 1;  double Anm2 = 1.0;  double Bnm2 = 0.0;  double Anm1 = 0.0;  double Bnm1 = 1.0;  double a1 = b + 1.0;  double b1 = (b + 1.0) * (b - x);  double An = b1*Anm1 + a1*Anm2;  double Bn = b1*Bnm1 + a1*Bnm2;  double an, bn;  double fn = An/Bn;  while(n < maxiter) {    double old_fn;    double del;    n++;    Anm2 = Anm1;    Bnm2 = Bnm1;    Anm1 = An;    Bnm1 = Bn;    an = (b + n) * (b + n - 1.0 - a) * x;    bn = (b + n) * (b + n - 1.0 - x);    An = bn*Anm1 + an*Anm2;    Bn = bn*Bnm1 + an*Bnm2;    if(fabs(An) > RECUR_BIG || fabs(Bn) > RECUR_BIG) {      An /= RECUR_BIG;      Bn /= RECUR_BIG;      Anm1 /= RECUR_BIG;      Bnm1 /= RECUR_BIG;      Anm2 /= RECUR_BIG;      Bnm2 /= RECUR_BIG;    }    old_fn = fn;    fn = An/Bn;    del = old_fn/fn;        if(fabs(del - 1.0) < 10.0*GSL_DBL_EPSILON) break;  }  *result = fn;  if(n == maxiter)    GSL_ERROR ("error", GSL_EMAXITER);  else    return GSL_SUCCESS;}#endif /* 0 *//* 1F1(a,b,x) * |a| <= 1, b > 0 */staticinthyperg_1F1_small_a_bgt0(const double a, const double b, const double x, gsl_sf_result * result){  const double bma = b-a;  const double oma = 1.0-a;  const double ap1mb = 1.0+a-b;  const double abs_bma = fabs(bma);  const double abs_oma = fabs(oma);  const double abs_ap1mb = fabs(ap1mb);  const double ax = fabs(x);  if(a == 0.0) {    result->val = 1.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(a == 1.0 && b >= 1.0) {    return hyperg_1F1_1(b, x, result);  }  else if(a == -1.0) {    result->val  = 1.0 + a/b * x;    result->err  = GSL_DBL_EPSILON * (1.0 + fabs(a/b * x));    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);    return GSL_SUCCESS;  }  else if(b >= 1.4*ax) {    return gsl_sf_hyperg_1F1_series_e(a, b, x, result);  }  else if(x > 0.0) {    if(x > 100.0 && abs_bma*abs_oma < 0.5*x) {      return hyperg_1F1_asymp_posx(a, b, x, result);    }    else if(b < 5.0e+06) {      /* Recurse backward on b from       * a suitably high point.       */      const double b_del = ceil(1.4*x-b) + 1.0;      double bp = b + b_del;      gsl_sf_result r_Mbp1;      gsl_sf_result r_Mb;      double Mbp1;      double Mb;      double Mbm1;      int stat_0 = gsl_sf_hyperg_1F1_series_e(a, bp+1.0, x, &r_Mbp1);      int stat_1 = gsl_sf_hyperg_1F1_series_e(a, bp,     x, &r_Mb);      const double err_rat = fabs(r_Mbp1.err/r_Mbp1.val) + fabs(r_Mb.err/r_Mb.val);      Mbp1 = r_Mbp1.val;      Mb   = r_Mb.val;      while(bp > b+0.1) {        /* Do backward recursion. */        Mbm1 = ((x+bp-1.0)*Mb - x*(bp-a)/bp*Mbp1)/(bp-1.0);        bp -= 1.0;        Mbp1 = Mb;        Mb   = Mbm1;      }      result->val  = Mb;      result->err  = err_rat * (fabs(b_del)+1.0) * fabs(Mb);      result->err += 2.0 * GSL_DBL_EPSILON * fabs(Mb);      return GSL_ERROR_SELECT_2(stat_0, stat_1);    }    else if (fabs(x) < fabs(b) && fabs(a*x) < sqrt(fabs(b)) * fabs(b-x)) {      return hyperg_1F1_largebx(a, b, x, result);    } else {      return hyperg_1F1_large2bm4a(a, b, x, result);    }  }  else {    /* x < 0 and b not large compared to |x|     */    if(ax < 10.0 && b < 10.0) {      return gsl_sf_hyperg_1F1_series_e(a, b, x, result);    }    else if(ax >= 100.0 && GSL_MAX(abs_ap1mb,1.0) < 0.99*ax) {      return hyperg_1F1_asymp_negx(a, b, x, result);    }    else {      return hyperg_1F1_luke(a, b, x, result);    }  }}/* 1F1(b+eps,b,x) * |eps|<=1, b > 0 */staticinthyperg_1F1_beps_bgt0(const double eps, const double b, const double x, gsl_sf_result * result){  if(b > fabs(x) && fabs(eps) < GSL_SQRT_DBL_EPSILON) {    /* If b-a is very small and x/b is not too large we can     * use this explicit approximation.     *     * 1F1(b+eps,b,x) = exp(ax/b) (1 - eps x^2 (v2 + v3 x + ...) + ...)     *     *   v2 = a/(2b^2(b+1))     *   v3 = a(b-2a)/(3b^3(b+1)(b+2))     *   ...     *     * See [Luke, Mathematical Functions and Their Approximations, p.292]     *     * This cannot be used for b near a negative integer or zero.     * Also, if x/b is large the deviation from exp(x) behaviour grows.     */    double a = b + eps;    gsl_sf_result exab;    int stat_e = gsl_sf_exp_e(a*x/b, &exab);    double v2 = a/(2.0*b*b*(b+1.0));    double v3 = a*(b-2.0*a)/(3.0*b*b*b*(b+1.0)*(b+2.0));    double v  = v2 + v3 * x;    double f  = (1.0 - eps*x*x*v);    result->val  = exab.val * f;

⌨️ 快捷键说明

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