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

📄 legendre_h3d.c

📁 开放gsl矩阵运算
💻 C
📖 第 1 页 / 共 2 页
字号:
  const double xi    = fabs(eta*lambda);  const double lsq   = lambda*lambda;  const double lsqp1 = lsq + 1.0;  /* CHECK_POINTER(result) */  if(eta < 0.0) {    DOMAIN_ERROR(result);  }  else if(eta == 0.0 || lambda == 0.0) {    result->val = 0.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(xi < GSL_ROOT5_DBL_EPSILON && eta < GSL_ROOT5_DBL_EPSILON) {    double etasq = eta*eta;    double xisq  = xi*xi;    double term1 = (etasq + xisq)/3.0;    double term2 = -(2.0*etasq*etasq + 5.0*etasq*xisq + 3.0*xisq*xisq)/90.0;    double sinh_term = 1.0 - eta*eta/6.0 * (1.0 - 7.0/60.0*eta*eta);    double pre = sinh_term/sqrt(lsqp1) / eta;    result->val  = pre * (term1 + term2);    result->err  = pre * GSL_DBL_EPSILON * (fabs(term1) + fabs(term2));    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);    return GSL_SUCCESS;  }  else {    double sin_term;     /*  Sin(xi)/xi     */    double cos_term;     /*  Cos(xi)        */    double coth_term;    /*  eta/Tanh(eta)  */    double sinh_term;    /*  eta/Sinh(eta)  */    double sin_term_err;    double cos_term_err;    double t1;    double pre_val;    double pre_err;    double term1;    double term2;    if(xi < GSL_ROOT5_DBL_EPSILON) {      sin_term = 1.0 - xi*xi/6.0 * (1.0 - xi*xi/20.0);      cos_term = 1.0 - 0.5*xi*xi * (1.0 - xi*xi/12.0);      sin_term_err = GSL_DBL_EPSILON;      cos_term_err = GSL_DBL_EPSILON;    }    else {      gsl_sf_result sin_xi_result;      gsl_sf_result cos_xi_result;      gsl_sf_sin_e(xi, &sin_xi_result);      gsl_sf_cos_e(xi, &cos_xi_result);      sin_term = sin_xi_result.val/xi;      cos_term = cos_xi_result.val;      sin_term_err = sin_xi_result.err/fabs(xi);      cos_term_err = cos_xi_result.err;    }    if(eta < GSL_ROOT5_DBL_EPSILON) {      coth_term = 1.0 + eta*eta/3.0 * (1.0 - eta*eta/15.0);      sinh_term = 1.0 - eta*eta/6.0 * (1.0 - 7.0/60.0*eta*eta);    }    else {      coth_term = eta/tanh(eta);      sinh_term = eta/sinh(eta);    }    t1 = sqrt(lsqp1) * eta;    pre_val = sinh_term/t1;    pre_err = 2.0 * GSL_DBL_EPSILON * fabs(pre_val);    term1 = sin_term*coth_term;    term2 = cos_term;    result->val  = pre_val * (term1 - term2);    result->err  = pre_err * fabs(term1 - term2);    result->err += pre_val * (sin_term_err * coth_term + cos_term_err);    result->err += pre_val * fabs(term1-term2) * (fabs(eta) + 1.0) * GSL_DBL_EPSILON;    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);    return GSL_SUCCESS;  }}intgsl_sf_legendre_H3d_e(const int ell, const double lambda, const double eta,                         gsl_sf_result * result){  const double abs_lam = fabs(lambda);  const double lsq     = abs_lam*abs_lam;  const double xi      = abs_lam * eta;  const double cosh_eta = cosh(eta);  /* CHECK_POINTER(result) */  if(eta < 0.0) {    DOMAIN_ERROR(result);  }  else if(eta > GSL_LOG_DBL_MAX) {    /* cosh(eta) is too big. */    OVERFLOW_ERROR(result);  }  else if(ell == 0) {    return gsl_sf_legendre_H3d_0_e(lambda, eta, result);  }  else if(ell == 1) {    return gsl_sf_legendre_H3d_1_e(lambda, eta, result);  }  else if(eta == 0.0) {    result->val = 0.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(xi < 1.0) {    return legendre_H3d_series(ell, lambda, eta, result);  }  else if((ell*ell+lsq)/sqrt(1.0+lsq)/(cosh_eta*cosh_eta) < 5.0*GSL_ROOT3_DBL_EPSILON) {    /* Large argument.     */    gsl_sf_result P;    double lm;    int stat_P = gsl_sf_conicalP_large_x_e(-ell-0.5, lambda, cosh_eta, &P, &lm);    if(P.val == 0.0) {      result->val = 0.0;      result->err = 0.0;      return stat_P;    }    else {      double lnN;      gsl_sf_result lnsh;      double ln_abslam;      double lnpre_val, lnpre_err;      int stat_e;      gsl_sf_lnsinh_e(eta, &lnsh);      legendre_H3d_lnnorm(ell, lambda, &lnN);      ln_abslam = log(abs_lam);      lnpre_val  = 0.5*(M_LNPI + lnN - M_LN2 - lnsh.val) - ln_abslam;      lnpre_err  = lnsh.err;      lnpre_err += 2.0 * GSL_DBL_EPSILON * (0.5*(M_LNPI + M_LN2 + fabs(lnN)) + fabs(ln_abslam));      lnpre_err += 2.0 * GSL_DBL_EPSILON * fabs(lnpre_val);      stat_e = gsl_sf_exp_mult_err_e(lnpre_val + lm, lnpre_err, P.val, P.err, result);      return GSL_ERROR_SELECT_2(stat_e, stat_P);    }  }  else if(abs_lam > 1000.0*ell*ell) {    /* Large degree.     */    gsl_sf_result P;    double lm;    int stat_P = gsl_sf_conicalP_xgt1_neg_mu_largetau_e(ell+0.5,                                                           lambda,                                                           cosh_eta, eta,                                                           &P, &lm);    if(P.val == 0.0) {      result->val = 0.0;      result->err = 0.0;      return stat_P;    }    else {      double lnN;      gsl_sf_result lnsh;      double ln_abslam;      double lnpre_val, lnpre_err;      int stat_e;      gsl_sf_lnsinh_e(eta, &lnsh);      legendre_H3d_lnnorm(ell, lambda, &lnN);      ln_abslam = log(abs_lam);      lnpre_val  = 0.5*(M_LNPI + lnN - M_LN2 - lnsh.val) - ln_abslam;      lnpre_err  = lnsh.err;      lnpre_err += GSL_DBL_EPSILON * (0.5*(M_LNPI + M_LN2 + fabs(lnN)) + fabs(ln_abslam));      lnpre_err += 2.0 * GSL_DBL_EPSILON * fabs(lnpre_val);      stat_e = gsl_sf_exp_mult_err_e(lnpre_val + lm, lnpre_err, P.val, P.err, result);      return GSL_ERROR_SELECT_2(stat_e, stat_P);    }  }  else {    /* Backward recurrence.     */    const double coth_eta = 1.0/tanh(eta);    const double coth_err_mult = fabs(eta) + 1.0;    gsl_sf_result rH;    int stat_CF1 = legendre_H3d_CF1_ser(ell, lambda, coth_eta, &rH);    double Hlm1;    double Hl    = GSL_SQRT_DBL_MIN;    double Hlp1  = rH.val * Hl;    int lp;    for(lp=ell; lp>0; lp--) {      double root_term_0 = sqrt(lambda*lambda + (double)lp*lp);      double root_term_1 = sqrt(lambda*lambda + (lp+1.0)*(lp+1.0));      Hlm1 = ((2.0*lp + 1.0)*coth_eta*Hl - root_term_1 * Hlp1)/root_term_0;      Hlp1 = Hl;      Hl   = Hlm1;    }    if(fabs(Hl) > fabs(Hlp1)) {      gsl_sf_result H0;      int stat_H0 = gsl_sf_legendre_H3d_0_e(lambda, eta, &H0);      result->val  = GSL_SQRT_DBL_MIN/Hl * H0.val;      result->err  = GSL_SQRT_DBL_MIN/fabs(Hl) * H0.err;      result->err += fabs(rH.err/rH.val) * (ell+1.0) * coth_err_mult * fabs(result->val);      result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);      return GSL_ERROR_SELECT_2(stat_H0, stat_CF1);    }    else {      gsl_sf_result H1;      int stat_H1 = gsl_sf_legendre_H3d_1_e(lambda, eta, &H1);      result->val  = GSL_SQRT_DBL_MIN/Hlp1 * H1.val;      result->err  = GSL_SQRT_DBL_MIN/fabs(Hlp1) * H1.err;      result->err += fabs(rH.err/rH.val) * (ell+1.0) * coth_err_mult * fabs(result->val);      result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);      return GSL_ERROR_SELECT_2(stat_H1, stat_CF1);    }  }}intgsl_sf_legendre_H3d_array(const int lmax, const double lambda, const double eta, double * result_array){  /* CHECK_POINTER(result_array) */ if(eta < 0.0 || lmax < 0) {    int ell;    for(ell=0; ell<=lmax; ell++) result_array[ell] = 0.0;    GSL_ERROR ("domain error", GSL_EDOM);  }  else if(eta > GSL_LOG_DBL_MAX) {    /* cosh(eta) is too big. */    int ell;    for(ell=0; ell<=lmax; ell++) result_array[ell] = 0.0;    GSL_ERROR ("overflow", GSL_EOVRFLW);  }  else if(lmax == 0) {    gsl_sf_result H0;    int stat = gsl_sf_legendre_H3d_e(0, lambda, eta, &H0);    result_array[0] = H0.val;    return stat;  }  else {    /* Not the most efficient method. But what the hell... it's simple.     */    gsl_sf_result r_Hlp1;    gsl_sf_result r_Hl;    int stat_lmax   = gsl_sf_legendre_H3d_e(lmax,   lambda, eta, &r_Hlp1);    int stat_lmaxm1 = gsl_sf_legendre_H3d_e(lmax-1, lambda, eta, &r_Hl);    int stat_max = GSL_ERROR_SELECT_2(stat_lmax, stat_lmaxm1);    const double coth_eta = 1.0/tanh(eta);    int stat_recursion = GSL_SUCCESS;    double Hlp1 = r_Hlp1.val;    double Hl   = r_Hl.val;    double Hlm1;    int ell;    result_array[lmax]   = Hlp1;    result_array[lmax-1] = Hl;    for(ell=lmax-1; ell>0; ell--) {      double root_term_0 = sqrt(lambda*lambda + (double)ell*ell);      double root_term_1 = sqrt(lambda*lambda + (ell+1.0)*(ell+1.0));      Hlm1 = ((2.0*ell + 1.0)*coth_eta*Hl - root_term_1 * Hlp1)/root_term_0;      result_array[ell-1] = Hlm1;      if(!(Hlm1 < GSL_DBL_MAX)) stat_recursion = GSL_EOVRFLW;      Hlp1 = Hl;      Hl   = Hlm1;    }    return GSL_ERROR_SELECT_2(stat_recursion, stat_max);  }}  /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/#include "eval.h"double gsl_sf_legendre_H3d_0(const double lambda, const double eta){  EVAL_RESULT(gsl_sf_legendre_H3d_0_e(lambda, eta, &result));}double gsl_sf_legendre_H3d_1(const double lambda, const double eta){  EVAL_RESULT(gsl_sf_legendre_H3d_1_e(lambda, eta, &result));}double gsl_sf_legendre_H3d(const int l, const double lambda, const double eta){  EVAL_RESULT(gsl_sf_legendre_H3d_e(l, lambda, eta, &result));}

⌨️ 快捷键说明

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