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

📄 hyperg_1f1.c

📁 math library from gnu
💻 C
📖 第 1 页 / 共 5 页
字号:
        double Ma0np1 = r_Ma0np1.val;        double Ma0n   = r_Ma0n.val;        double Ma0nm1;        err_rat = fabs(r_Ma0np1.err/r_Ma0np1.val) + fabs(r_Ma0n.err/r_Ma0n.val);        for(n=a0+epsb-1.0; n>b+0.1; n -= 1.0) {          Ma0nm1 = (-n*(1-n-x)*Ma0n - x*(n-a0)*Ma0np1)/(n*(n-1.0));          Ma0np1 = Ma0n;          Ma0n = Ma0nm1;        }        Ma0bp1 = Ma0np1;        Ma0b   = Ma0n;        Ma0p1b = (b*(a0+x)*Ma0b+x*(a0-b)*Ma0bp1)/(a0*b); /* right-down hook */        stat_a0 = GSL_ERROR_SELECT_2(stat_0, stat_1);      }                /* Initialise the recurrence correctly BJG */      if (a0 >= a - 0.1)        {           Mn = Ma0b;        }      else if (a0 + 1>= a - 0.1)        {          Mn = Ma0p1b;        }      else        {          Mnm1 = Ma0b;          Mn   = Ma0p1b;          for(n=a0+1.0; n<a-0.1; n += 1.0) {            Mnp1 = ((b-n)*Mnm1 + (2*n-b+x)*Mn)/n;            Mnm1 = Mn;            Mn   = Mnp1;          }        }      result->val = Mn;      result->err = (err_rat + GSL_DBL_EPSILON) * (fabs(b-a)+1.0) * fabs(Mn);      return stat_a0;    }  }}/* Assumes b != integer * Assumes a != integer when x > 0 * Assumes b-a != neg integer when x < 0 */staticinthyperg_1F1_ab_neg(const double a, const double b, const double x,                  gsl_sf_result * result){  const double bma = b - a;  const double abs_x = fabs(x);  const double abs_a = fabs(a);  const double abs_b = fabs(b);  const double size_a = GSL_MAX(abs_a, 1.0);  const double size_b = GSL_MAX(abs_b, 1.0);  const int bma_integer = ( bma - floor(bma+0.5) < _1F1_INT_THRESHOLD );  if(   (abs_a < 10.0 && abs_b < 10.0 && abs_x < 5.0)     || (b > 0.8*GSL_MAX(fabs(a),1.0)*fabs(x))    ) {    return gsl_sf_hyperg_1F1_series_e(a, b, x, result);  }  else if(   x > 0.0          && size_b > size_a          && size_a*log(M_E*x/size_b) < GSL_LOG_DBL_EPSILON+7.0    ) {    /* Series terms are positive definite up until     * there is a sign change. But by then the     * terms are small due to the last condition.     */    return gsl_sf_hyperg_1F1_series_e(a, b, x, result);  }  else if(   (abs_x < 5.0 && fabs(bma) < 10.0 && abs_b < 10.0)          || (b > 0.8*GSL_MAX_DBL(fabs(bma),1.0)*abs_x)    ) {    /* Use Kummer transformation to render series safe.     */    gsl_sf_result Kummer_1F1;    int stat_K = gsl_sf_hyperg_1F1_series_e(bma, b, -x, &Kummer_1F1);    int stat_e = gsl_sf_exp_mult_err_e(x, GSL_DBL_EPSILON * fabs(x),                                      Kummer_1F1.val, Kummer_1F1.err,                                      result);    return GSL_ERROR_SELECT_2(stat_e, stat_K);  }  else if(   x < -30.0          && GSL_MAX_DBL(fabs(a),1.0)*GSL_MAX_DBL(fabs(1.0+a-b),1.0) < 0.99*fabs(x)    ) {    /* Large negative x asymptotic.     * Note that we do not check if b-a is a negative integer.     */    return hyperg_1F1_asymp_negx(a, b, x, result);  }  else if(   x > 100.0          && GSL_MAX_DBL(fabs(bma),1.0)*GSL_MAX_DBL(fabs(1.0-a),1.0) < 0.99*fabs(x)    ) {    /* Large positive x asymptotic.     * Note that we do not check if a is a negative integer.     */    return hyperg_1F1_asymp_posx(a, b, x, result);  }  else if(x > 0.0 && !(bma_integer && bma > 0.0)) {    return hyperg_1F1_U(a, b, x, result);  }  else {    /* FIXME:  if all else fails, try the series... BJG */    if (x < 0.0) {      /* Apply Kummer Transformation */      int status = gsl_sf_hyperg_1F1_series_e(b-a, b, -x, result);      double K_factor = exp(x);      result->val *= K_factor;      result->err *= K_factor;      return status;    } else {      int status = gsl_sf_hyperg_1F1_series_e(a, b, x, result);      return status;    }    /* Sadness... */    /* result->val = 0.0; */    /* result->err = 0.0; */    /* GSL_ERROR ("error", GSL_EUNIMPL); */  }}/*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/intgsl_sf_hyperg_1F1_int_e(const int a, const int b, const double x, gsl_sf_result * result){  /* CHECK_POINTER(result) */  if(x == 0.0) {    result->val = 1.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(a == b) {    return gsl_sf_exp_e(x, result);  }  else if(b == 0) {    DOMAIN_ERROR(result);  }  else if(a == 0) {    result->val = 1.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(b < 0 && (a < b || a > 0)) {    /* Standard domain error due to singularity. */    DOMAIN_ERROR(result);  }  else if(x > 100.0  && GSL_MAX_DBL(1.0,fabs(b-a))*GSL_MAX_DBL(1.0,fabs(1-a)) < 0.5 * x) {    /* x -> +Inf asymptotic */    return hyperg_1F1_asymp_posx(a, b, x, result);  }  else if(x < -100.0 && GSL_MAX_DBL(1.0,fabs(a))*GSL_MAX_DBL(1.0,fabs(1+a-b)) < 0.5 * fabs(x)) {    /* x -> -Inf asymptotic */    return hyperg_1F1_asymp_negx(a, b, x, result);  }  else if(a < 0 && b < 0) {    return hyperg_1F1_ab_negint(a, b, x, result);  }  else if(a < 0 && b > 0) {    /* Use Kummer to reduce it to the positive integer case.     * Note that b > a, strictly, since we already trapped b = a.     */    gsl_sf_result Kummer_1F1;    int stat_K = hyperg_1F1_ab_posint(b-a, b, -x, &Kummer_1F1);    int stat_e = gsl_sf_exp_mult_err_e(x, GSL_DBL_EPSILON * fabs(x),                                      Kummer_1F1.val, Kummer_1F1.err,                                      result);     return GSL_ERROR_SELECT_2(stat_e, stat_K);  }  else {    /* a > 0 and b > 0 */    return hyperg_1F1_ab_posint(a, b, x, result);  }}intgsl_sf_hyperg_1F1_e(const double a, const double b, const double x,                       gsl_sf_result * result                       ){  const double bma = b - a;  const double rinta = floor(a + 0.5);  const double rintb = floor(b + 0.5);  const double rintbma = floor(bma + 0.5);  const int a_integer   = ( fabs(a-rinta) < _1F1_INT_THRESHOLD && rinta > INT_MIN && rinta < INT_MAX );  const int b_integer   = ( fabs(b-rintb) < _1F1_INT_THRESHOLD && rintb > INT_MIN && rintb < INT_MAX );  const int bma_integer = ( fabs(bma-rintbma) < _1F1_INT_THRESHOLD && rintbma > INT_MIN && rintbma < INT_MAX );  const int b_neg_integer   = ( b < -0.1 && b_integer );  const int a_neg_integer   = ( a < -0.1 && a_integer );  const int bma_neg_integer = ( bma < -0.1 &&  bma_integer );  /* CHECK_POINTER(result) */  if(x == 0.0) {    /* Testing for this before testing a and b     * is somewhat arbitrary. The result is that     * we have 1F1(a,0,0) = 1.     */    result->val = 1.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(b == 0.0) {    DOMAIN_ERROR(result);  }  else if(a == 0.0) {    result->val = 1.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(a == b) {    /* case: a==b; exp(x)     * It's good to test exact equality now.     * We also test approximate equality later.     */    return gsl_sf_exp_e(x, result);  } else if(fabs(b) < _1F1_INT_THRESHOLD && fabs(a) < _1F1_INT_THRESHOLD) {    /* a and b near zero: 1 + a/b (exp(x)-1)     */    /* Note that neither a nor b is zero, since     * we eliminated that with the above tests.     */        gsl_sf_result exm1;    int stat_e = gsl_sf_expm1_e(x, &exm1);    double sa = ( a > 0.0 ? 1.0 : -1.0 );    double sb = ( b > 0.0 ? 1.0 : -1.0 );    double lnab = log(fabs(a/b)); /* safe */    gsl_sf_result hx;    int stat_hx = gsl_sf_exp_mult_err_e(lnab, GSL_DBL_EPSILON * fabs(lnab),                                        sa * sb * exm1.val, exm1.err,                                        &hx);    result->val = (hx.val == GSL_DBL_MAX ? hx.val : 1.0 + hx.val);  /* FIXME: excessive paranoia ? what is DBL_MAX+1 ?*/    result->err = hx.err;    return GSL_ERROR_SELECT_2(stat_hx, stat_e);  } else if (fabs(b) < _1F1_INT_THRESHOLD && fabs(x*a) < 1) {      /* b near zero and a not near zero       */      const double m_arg = 1.0/(0.5*b);      gsl_sf_result F_renorm;      int stat_F = hyperg_1F1_renorm_b0(a, x, &F_renorm);      int stat_m = gsl_sf_multiply_err_e(m_arg, 2.0 * GSL_DBL_EPSILON * m_arg,                                            0.5*F_renorm.val, 0.5*F_renorm.err,                                            result);      return GSL_ERROR_SELECT_2(stat_m, stat_F);  }  else if(a_integer && b_integer) {    /* Check for reduction to the integer case.     * Relies on the arbitrary "near an integer" test.     */    return gsl_sf_hyperg_1F1_int_e((int)rinta, (int)rintb, x, result);  }  else if(b_neg_integer && !(a_neg_integer && a > b)) {    /* Standard domain error due to     * uncancelled singularity.     */    DOMAIN_ERROR(result);  }  else if(a_neg_integer) {    return hyperg_1F1_a_negint_lag((int)rinta, b, x, result);  }  else if(b > 0.0) {    if(-1.0 <= a && a <= 1.0) {      /* Handle small a explicitly.       */      return hyperg_1F1_small_a_bgt0(a, b, x, result);    }    else if(bma_neg_integer) {      /* Catch this now, to avoid problems in the       * generic evaluation code.       */      gsl_sf_result Kummer_1F1;      int stat_K = hyperg_1F1_a_negint_lag((int)rintbma, b, -x, &Kummer_1F1);      int stat_e = gsl_sf_exp_mult_err_e(x, GSL_DBL_EPSILON * fabs(x),                                            Kummer_1F1.val, Kummer_1F1.err,                                            result);      return GSL_ERROR_SELECT_2(stat_e, stat_K);    }    else if(a < 0.0 && fabs(x) < 100.0) {      /* Use Kummer to reduce it to the generic positive case.       * Note that b > a, strictly, since we already trapped b = a.       * Also b-(b-a)=a, and a is not a negative integer here,       * so the generic evaluation is safe.       */      gsl_sf_result Kummer_1F1;      int stat_K = hyperg_1F1_ab_pos(b-a, b, -x, &Kummer_1F1);      int stat_e = gsl_sf_exp_mult_err_e(x, GSL_DBL_EPSILON * fabs(x),                                            Kummer_1F1.val, Kummer_1F1.err,                                            result);      return GSL_ERROR_SELECT_2(stat_e, stat_K);    }    else if (a > 0) {      /* a > 0.0 */      return hyperg_1F1_ab_pos(a, b, x, result);    } else {      return gsl_sf_hyperg_1F1_series_e(a, b, x, result);    }  }  else {    /* b < 0.0 */    if(bma_neg_integer && x < 0.0) {      /* Handle this now to prevent problems       * in the generic evaluation.       */      gsl_sf_result K;      int stat_K;      int stat_e;      if(a < 0.0) {        /* Kummer transformed version of safe polynomial.         * The condition a < 0 is equivalent to b < b-a,         * which is the condition required for the series         * to be positive definite here.         */        stat_K = hyperg_1F1_a_negint_poly((int)rintbma, b, -x, &K);      }      else {        /* Generic eval for negative integer a. */        stat_K = hyperg_1F1_a_negint_lag((int)rintbma, b, -x, &K);      }      stat_e = gsl_sf_exp_mult_err_e(x, GSL_DBL_EPSILON * fabs(x),                                        K.val, K.err,                                        result);      return GSL_ERROR_SELECT_2(stat_e, stat_K);    }    else if(a > 0.0) {      /* Use Kummer to reduce it to the generic negative case.       */      gsl_sf_result K;      int stat_K = hyperg_1F1_ab_neg(b-a, b, -x, &K);      int stat_e = gsl_sf_exp_mult_err_e(x, GSL_DBL_EPSILON * fabs(x),                                            K.val, K.err,                                            result);      return GSL_ERROR_SELECT_2(stat_e, stat_K);    }    else {      return hyperg_1F1_ab_neg(a, b, x, result);    }  }}  #if 0      /* Luke in the canonical case.   */  if(x < 0.0 && !a_neg_integer && !bma_neg_integer) {    double prec;    return hyperg_1F1_luke(a, b, x, result, &prec);  }  /* Luke with Kummer transformation.   */  if(x > 0.0 && !a_neg_integer && !bma_neg_integer) {    double prec;    double Kummer_1F1;    double ex;    int stat_F = hyperg_1F1_luke(b-a, b, -x, &Kummer_1F1, &prec);    int stat_e = gsl_sf_exp_e(x, &ex);    if(stat_F == GSL_SUCCESS && stat_e == GSL_SUCCESS) {      double lnr = log(fabs(Kummer_1F1)) + x;      if(lnr < GSL_LOG_DBL_MAX) {        *result = ex * Kummer_1F1;        return GSL_SUCCESS;      }      else {        *result = GSL_POSINF;         GSL_ERROR ("overflow", GSL_EOVRFLW);      }    }    else if(stat_F != GSL_SUCCESS) {      *result = 0.0;      return stat_F;    }    else {      *result = 0.0;      return stat_e;    }  }#endif/*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/#include "eval.h"double gsl_sf_hyperg_1F1_int(const int m, const int n, double x){  EVAL_RESULT(gsl_sf_hyperg_1F1_int_e(m, n, x, &result));}double gsl_sf_hyperg_1F1(double a, double b, double x){  EVAL_RESULT(gsl_sf_hyperg_1F1_e(a, b, x, &result));}

⌨️ 快捷键说明

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