Пример #1
0
int
gsl_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);
  }
}
Пример #2
0
/// Hypergeometric functions.
double
hyperg(double a, double b, double c, double x)
{
  gsl_sf_result result;
  int stat = gsl_sf_hyperg_2F1_e(a, b, c, x, &result);
  if (stat != GSL_SUCCESS)
    {
      std::ostringstream msg("Error in hyperg:");
      msg << " a=" << a << " b=" << b << " c=" << c << " x=" << x;
      throw std::runtime_error(msg.str());
    }
  else
    return result.val;
}
Пример #3
0
int
gsl_sf_beta_inc_e(
    const double a,
    const double b,
    const double x,
    gsl_sf_result * result
)
{
    if(x < 0.0 || x > 1.0) {
        DOMAIN_ERROR(result);
    } else if (isnegint(a) || isnegint(b)) {
        DOMAIN_ERROR(result);
    } else if (isnegint(a+b)) {
        DOMAIN_ERROR(result);
    } else if(x == 0.0) {
        result->val = 0.0;
        result->err = 0.0;
        return GSL_SUCCESS;
    }
    else if(x == 1.0) {
        result->val = 1.0;
        result->err = 0.0;
        return GSL_SUCCESS;
    } else if (a <= 0 || b <= 0) {
        gsl_sf_result f, beta;
        int stat;
        const int stat_f = gsl_sf_hyperg_2F1_e(a, 1-b, a+1, x, &f);
        const int stat_beta = gsl_sf_beta_e(a, b, &beta);
        double prefactor = (pow(x, a) / a);
        result->val = prefactor * f.val / beta.val;
        result->err = fabs(prefactor) * f.err/ fabs(beta.val) + fabs(result->val/beta.val) * beta.err;

        stat = GSL_ERROR_SELECT_2(stat_f, stat_beta);
        if(stat == GSL_SUCCESS) {
            CHECK_UNDERFLOW(result);
        }
        return stat;
    } else {
        gsl_sf_result ln_beta;
        gsl_sf_result ln_x;
        gsl_sf_result ln_1mx;
        gsl_sf_result prefactor;
        const int stat_ln_beta = gsl_sf_lnbeta_e(a, b, &ln_beta);
        const int stat_ln_1mx = gsl_sf_log_1plusx_e(-x, &ln_1mx);
        const int stat_ln_x = gsl_sf_log_e(x, &ln_x);
        const int stat_ln = GSL_ERROR_SELECT_3(stat_ln_beta, stat_ln_1mx, stat_ln_x);

        const double ln_pre_val = -ln_beta.val + a * ln_x.val + b * ln_1mx.val;
        const double ln_pre_err =  ln_beta.err + fabs(a*ln_x.err) + fabs(b*ln_1mx.err);
        const int stat_exp = gsl_sf_exp_err_e(ln_pre_val, ln_pre_err, &prefactor);

        if(stat_ln != GSL_SUCCESS) {
            result->val = 0.0;
            result->err = 0.0;
            GSL_ERROR ("error", GSL_ESANITY);
        }

        if(x < (a + 1.0)/(a+b+2.0)) {
            /* Apply continued fraction directly. */
            gsl_sf_result cf;
            const int stat_cf = beta_cont_frac(a, b, x, &cf);
            int stat;
            result->val = prefactor.val * cf.val / a;
            result->err = (fabs(prefactor.err * cf.val) + fabs(prefactor.val * cf.err))/a;

            stat = GSL_ERROR_SELECT_2(stat_exp, stat_cf);
            if(stat == GSL_SUCCESS) {
                CHECK_UNDERFLOW(result);
            }
            return stat;
        }
        else {
            /* Apply continued fraction after hypergeometric transformation. */
            gsl_sf_result cf;
            const int stat_cf = beta_cont_frac(b, a, 1.0-x, &cf);
            int stat;
            const double term = prefactor.val * cf.val / b;
            result->val  = 1.0 - term;
            result->err  = fabs(prefactor.err * cf.val)/b;
            result->err += fabs(prefactor.val * cf.err)/b;
            result->err += 2.0 * GSL_DBL_EPSILON * (1.0 + fabs(term));
            stat = GSL_ERROR_SELECT_2(stat_exp, stat_cf);
            if(stat == GSL_SUCCESS) {
                CHECK_UNDERFLOW(result);
            }
            return stat;
        }
    }
}
Пример #4
0
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));
}