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

📄 bessel.c

📁 开放gsl矩阵运算
💻 C
📖 第 1 页 / 共 2 页
字号:
      const int stat_Y0 = gsl_sf_bessel_Ynu_asympx_e(mu,     x, Ymu);      const int stat_Y1 = gsl_sf_bessel_Ynu_asympx_e(mu+1.0, x, Ymup1);      stat_J = GSL_ERROR_SELECT_2(stat_J0, stat_J1);      stat_Y = GSL_ERROR_SELECT_2(stat_Y0, stat_Y1);      return GSL_ERROR_SELECT_2(stat_J, stat_Y);    }  }}intgsl_sf_bessel_J_CF1(const double nu, const double x,                    double * ratio, double * sgn){  const double RECUR_BIG = GSL_SQRT_DBL_MAX;  const int maxiter = 10000;  int n = 1;  double Anm2 = 1.0;  double Bnm2 = 0.0;  double Anm1 = 0.0;  double Bnm1 = 1.0;  double a1 = x/(2.0*(nu+1.0));  double An = Anm1 + a1*Anm2;  double Bn = Bnm1 + a1*Bnm2;  double an;  double fn = An/Bn;  double dn = a1;  double s  = 1.0;  while(n < maxiter) {    double old_fn;    double del;    n++;    Anm2 = Anm1;    Bnm2 = Bnm1;    Anm1 = An;    Bnm1 = Bn;    an = -x*x/(4.0*(nu+n-1.0)*(nu+n));    An = Anm1 + an*Anm2;    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;    dn = 1.0 / (2.0*(nu+n)/x - dn);    if(dn < 0.0) s = -s;    if(fabs(del - 1.0) < 2.0*GSL_DBL_EPSILON) break;  }  *ratio = fn;  *sgn   = s;  if(n >= maxiter)    GSL_ERROR ("error", GSL_EMAXITER);  else    return GSL_SUCCESS;}/* Evaluate the continued fraction CF1 for J_{nu+1}/J_nu * using Gautschi (Euler) equivalent series. * This exhibits an annoying problem because the * a_k are not positive definite (in fact they are all negative). * There are cases when rho_k blows up. Example: nu=1,x=4. */#if 0intgsl_sf_bessel_J_CF1_ser(const double nu, const double x,                        double * ratio, double * sgn){  const int maxk = 20000;  double tk   = 1.0;  double sum  = 1.0;  double rhok = 0.0;  double dk = 0.0;  double s  = 1.0;  int k;  for(k=1; k<maxk; k++) {    double ak = -0.25 * (x/(nu+k)) * x/(nu+k+1.0);    rhok = -ak*(1.0 + rhok)/(1.0 + ak*(1.0 + rhok));    tk  *= rhok;    sum += tk;    dk = 1.0 / (2.0/x - (nu+k-1.0)/(nu+k) * dk);    if(dk < 0.0) s = -s;    if(fabs(tk/sum) < GSL_DBL_EPSILON) break;  }  *ratio = x/(2.0*(nu+1.0)) * sum;  *sgn   = s;  if(k == maxk)    GSL_ERROR ("error", GSL_EMAXITER);  else    return GSL_SUCCESS;}#endif/* Evaluate the continued fraction CF1 for I_{nu+1}/I_nu * using Gautschi (Euler) equivalent series. */intgsl_sf_bessel_I_CF1_ser(const double nu, const double x, double * ratio){  const int maxk = 20000;  double tk   = 1.0;  double sum  = 1.0;  double rhok = 0.0;  int k;  for(k=1; k<maxk; k++) {    double ak = 0.25 * (x/(nu+k)) * x/(nu+k+1.0);    rhok = -ak*(1.0 + rhok)/(1.0 + ak*(1.0 + rhok));    tk  *= rhok;    sum += tk;    if(fabs(tk/sum) < GSL_DBL_EPSILON) break;  }  *ratio = x/(2.0*(nu+1.0)) * sum;  if(k == maxk)    GSL_ERROR ("error", GSL_EMAXITER);  else    return GSL_SUCCESS;}intgsl_sf_bessel_JY_steed_CF2(const double nu, const double x,                           double * P, double * Q){  const int max_iter = 10000;  const double SMALL = 1.0e-100;  int i = 1;  double x_inv = 1.0/x;  double a = 0.25 - nu*nu;  double p = -0.5*x_inv;  double q = 1.0;  double br = 2.0*x;  double bi = 2.0;  double fact = a*x_inv/(p*p + q*q);  double cr = br + q*fact;  double ci = bi + p*fact;  double den = br*br + bi*bi;  double dr = br/den;  double di = -bi/den;  double dlr = cr*dr - ci*di;  double dli = cr*di + ci*dr;  double temp = p*dlr - q*dli;  q = p*dli + q*dlr;  p = temp;  for (i=2; i<=max_iter; i++) {    a  += 2*(i-1);    bi += 2.0;    dr = a*dr + br;    di = a*di + bi;    if(fabs(dr)+fabs(di) < SMALL) dr = SMALL;    fact = a/(cr*cr+ci*ci);    cr = br + cr*fact;    ci = bi - ci*fact;    if(fabs(cr)+fabs(ci) < SMALL) cr = SMALL;    den = dr*dr + di*di;    dr /= den;    di /= -den;    dlr = cr*dr - ci*di;    dli = cr*di + ci*dr;    temp = p*dlr - q*dli;    q = p*dli + q*dlr;    p = temp;    if(fabs(dlr-1.0)+fabs(dli) < GSL_DBL_EPSILON) break;  }  *P = p;  *Q = q;  if(i == max_iter)    GSL_ERROR ("error", GSL_EMAXITER);  else    return GSL_SUCCESS;}/* Evaluate continued fraction CF2, using Thompson-Barnett-Temme method, * to obtain values of exp(x)*K_nu and exp(x)*K_{nu+1}. * * This is unstable for small x; x > 2 is a good cutoff. * Also requires |nu| < 1/2. */intgsl_sf_bessel_K_scaled_steed_temme_CF2(const double nu, const double x,                                       double * K_nu, double * K_nup1,                                       double * Kp_nu){  const int maxiter = 10000;  int i = 1;  double bi = 2.0*(1.0 + x);  double di = 1.0/bi;  double delhi = di;  double hi    = di;  double qi   = 0.0;  double qip1 = 1.0;  double ai = -(0.25 - nu*nu);  double a1 = ai;  double ci = -ai;  double Qi = -ai;  double s = 1.0 + Qi*delhi;  for(i=2; i<=maxiter; i++) {    double dels;    double tmp;    ai -= 2.0*(i-1);    ci  = -ai*ci/i;    tmp  = (qi - bi*qip1)/ai;    qi   = qip1;    qip1 = tmp;    Qi += ci*qip1;    bi += 2.0;    di  = 1.0/(bi + ai*di);    delhi = (bi*di - 1.0) * delhi;    hi += delhi;    dels = Qi*delhi;    s += dels;    if(fabs(dels/s) < GSL_DBL_EPSILON) break;  }    hi *= -a1;    *K_nu   = sqrt(M_PI/(2.0*x)) / s;  *K_nup1 = *K_nu * (nu + x + 0.5 - hi)/x;  *Kp_nu  = - *K_nup1 + nu/x * *K_nu;  if(i == maxiter)    GSL_ERROR ("error", GSL_EMAXITER);  else    return GSL_SUCCESS;}int gsl_sf_bessel_cos_pi4_e(double y, double eps, gsl_sf_result * result){  const double sy = sin(y);  const double cy = cos(y);  const double s = sy + cy;  const double d = sy - cy;  const double abs_sum = fabs(cy) + fabs(sy);  double seps;  double ceps;  if(fabs(eps) < GSL_ROOT5_DBL_EPSILON) {    const double e2 = eps*eps;    seps = eps * (1.0 - e2/6.0 * (1.0 - e2/20.0));    ceps = 1.0 - e2/2.0 * (1.0 - e2/12.0);  }  else {    seps = sin(eps);    ceps = cos(eps);  }  result->val = (ceps * s - seps * d)/ M_SQRT2;  result->err = 2.0 * GSL_DBL_EPSILON * (fabs(ceps) + fabs(seps)) * abs_sum / M_SQRT2;  /* Try to account for error in evaluation of sin(y), cos(y).   * This is a little sticky because we don't really know   * how the library routines are doing their argument reduction.   * However, we will make a reasonable guess.   * FIXME ?   */  if(y > 1.0/GSL_DBL_EPSILON) {    result->err *= 0.5 * y;  }  else if(y > 1.0/GSL_SQRT_DBL_EPSILON) {    result->err *= 256.0 * y * GSL_SQRT_DBL_EPSILON;  }  return GSL_SUCCESS;}int gsl_sf_bessel_sin_pi4_e(double y, double eps, gsl_sf_result * result){  const double sy = sin(y);  const double cy = cos(y);  const double s = sy + cy;  const double d = sy - cy;  const double abs_sum = fabs(cy) + fabs(sy);  double seps;  double ceps;  if(fabs(eps) < GSL_ROOT5_DBL_EPSILON) {    const double e2 = eps*eps;    seps = eps * (1.0 - e2/6.0 * (1.0 - e2/20.0));    ceps = 1.0 - e2/2.0 * (1.0 - e2/12.0);  }  else {    seps = sin(eps);    ceps = cos(eps);  }  result->val = (ceps * d + seps * s)/ M_SQRT2;  result->err = 2.0 * GSL_DBL_EPSILON * (fabs(ceps) + fabs(seps)) * abs_sum / M_SQRT2;  /* Try to account for error in evaluation of sin(y), cos(y).   * See above.   * FIXME ?   */  if(y > 1.0/GSL_DBL_EPSILON) {    result->err *= 0.5 * y;  }  else if(y > 1.0/GSL_SQRT_DBL_EPSILON) {    result->err *= 256.0 * y * GSL_SQRT_DBL_EPSILON;  }  return GSL_SUCCESS;}/************************************************************************ *                                                                      *  Asymptotic approximations 8.11.5, 8.12.5, and 8.42.7 from  G.N.Watson, A Treatise on the Theory of Bessel Functions,  2nd Edition (Cambridge University Press, 1944).  Higher terms in expansion for x near l given by  Airey in Phil. Mag. 31, 520 (1916).  This approximation is accurate to near 0.1% at the boundaries  between the asymptotic regions; well away from the boundaries  the accuracy is better than 10^{-5}. *                                                                      * ************************************************************************/#if 0double besselJ_meissel(double nu, double x){  double beta = pow(nu, 0.325);  double result;  /* Fitted matching points.   */  double llimit = 1.1 * beta;  double ulimit = 1.3 * beta;  double nu2 = nu * nu;  if (nu < 5. && x < 1.)    {      /* Small argument and order. Use a Taylor expansion. */      int k;      double xo2 = 0.5 * x;      double gamfactor = pow(nu,nu) * exp(-nu) * sqrt(nu * 2. * M_PI)	* (1. + 1./(12.*nu) + 1./(288.*nu*nu));      double prefactor = pow(xo2, nu) / gamfactor;      double C[5];      C[0] = 1.;      C[1] = -C[0] / (nu+1.);      C[2] = -C[1] / (2.*(nu+2.));      C[3] = -C[2] / (3.*(nu+3.));      C[4] = -C[3] / (4.*(nu+4.));            result = 0.;      for(k=0; k<5; k++)	result += C[k] * pow(xo2, 2.*k);      result *= prefactor;    }  else if(x < nu - llimit)    {      /* Small x region: x << l.    */      double z = x / nu;      double z2 = z*z;      double rtomz2 = sqrt(1.-z2);      double omz2_2 = (1.-z2)*(1.-z2);      /* Calculate Meissel exponent. */      double term1 = 1./(24.*nu) * ((2.+3.*z2)/((1.-z2)*rtomz2) -2.);      double term2 = - z2*(4. + z2)/(16.*nu2*(1.-z2)*omz2_2);      double V_nu = term1 + term2;            /* Calculate the harmless prefactor. */      double sterlingsum = 1. + 1./(12.*nu) + 1./(288*nu2);      double harmless = 1. / (sqrt(rtomz2*2.*M_PI*nu) * sterlingsum);      /* Calculate the logarithm of the nu dependent prefactor. */      double ln_nupre = rtomz2 + log(z) - log(1. + rtomz2);      result = harmless * exp(nu*ln_nupre - V_nu);    }   else if(x < nu + ulimit)    {               /* Intermediate region 1: x near nu. */      double eps = 1.-nu/x;      double eps_x = eps * x;      double eps_x_2 = eps_x * eps_x;      double xo6 = x/6.;      double B[6];      static double gam[6] = {2.67894, 1.35412, 1., 0.89298, 0.902745, 1.};      static double sf[6] = {0.866025, 0.866025, 0., -0.866025, -0.866025, 0.};            /* Some terms are identically zero, because sf[] can be zero.       * Some terms do not appear in the result.       */      B[0] = 1.;      B[1] = eps_x;      /* B[2] = 0.5 * eps_x_2 - 1./20.; */      B[3] = eps_x * (eps_x_2/6. - 1./15.);      B[4] = eps_x_2 * (eps_x_2 - 1.)/24. + 1./280.;      /* B[5] = eps_x * (eps_x_2*(0.5*eps_x_2 - 1.)/60. + 43./8400.); */      result  = B[0] * gam[0] * sf[0] / pow(xo6, 1./3.);      result += B[1] * gam[1] * sf[1] / pow(xo6, 2./3.);      result += B[3] * gam[3] * sf[3] / pow(xo6, 4./3.);      result += B[4] * gam[4] * sf[4] / pow(xo6, 5./3.);      result /= (3.*M_PI);    }  else     {      /* Region of very large argument. Use expansion       * for x>>l, and we need not be very exacting.       */      double secb = x/nu;      double sec2b= secb*secb;            double cotb = 1./sqrt(sec2b-1.);      /* cotb=cot(beta) */      double beta = acos(nu/x);      double trigarg = nu/cotb - nu*beta - 0.25 * M_PI;            double cot3b = cotb * cotb * cotb;      double cot6b = cot3b * cot3b;      double sum1, sum2, expterm, prefactor, trigcos;      sum1  = 2.0 + 3.0 * sec2b;      trigarg -= sum1 * cot3b / (24.0 * nu);      trigcos = cos(trigarg);      sum2 = 4.0 + sec2b;      expterm = sum2 * sec2b * cot6b / (16.0 * nu2);      expterm = exp(-expterm);      prefactor = sqrt(2. * cotb / (nu * M_PI));            result = prefactor * expterm * trigcos;    }  return  result;}#endif

⌨️ 快捷键说明

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