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

📄 legendre_con.c

📁 开放gsl矩阵运算
💻 C
📖 第 1 页 / 共 3 页
字号:
    double im_tmp = im_multiplier*re_term + re_multiplier*im_term;    double asum = fabs(re_sum) + fabs(im_sum);    re_term = y/k * re_tmp;    im_term = y/k * im_tmp;    if(fabs(re_term/asum) < GSL_DBL_EPSILON && fabs(im_term/asum) < GSL_DBL_EPSILON) break;    re_sum += re_term;    im_sum += im_term;  }  *reF = re_sum;  *imF = im_sum;  if(k == kmax)    GSL_ERROR ("error", GSL_EMAXITER);  else      return GSL_SUCCESS;}/* P^{mu}_{-1/2 + I tau} * x->Inf */intgsl_sf_conicalP_large_x_e(const double mu, const double tau, const double x,                             gsl_sf_result * result, double * ln_multiplier){  /* 2F1 term   */  double y = ( x < 0.5*GSL_SQRT_DBL_MAX ? 1.0/(x*x) : 0.0 );  double reF, imF;  int stat_F = conicalP_hyperg_large_x(mu, tau, y, &reF, &imF);  /* f = Gamma(+i tau)/Gamma(1/2 - mu + i tau)   * FIXME: shift so it's better for tau-> 0   */  gsl_sf_result lgr_num, lgth_num;  gsl_sf_result lgr_den, lgth_den;  int stat_gn = gsl_sf_lngamma_complex_e(0.0,tau,&lgr_num,&lgth_num);  int stat_gd = gsl_sf_lngamma_complex_e(0.5-mu,tau,&lgr_den,&lgth_den);  double angle = lgth_num.val - lgth_den.val + atan2(imF,reF);  double lnx   = log(x);  double lnxp1 = log(x+1.0);  double lnxm1 = log(x-1.0);  double lnpre_const = 0.5*M_LN2 - 0.5*M_LNPI;  double lnpre_comm = (mu-0.5)*lnx - 0.5*mu*(lnxp1 + lnxm1);  double lnpre_err  =   GSL_DBL_EPSILON * (0.5*M_LN2 + 0.5*M_LNPI)                      + GSL_DBL_EPSILON * fabs((mu-0.5)*lnx)		      + GSL_DBL_EPSILON * fabs(0.5*mu)*(fabs(lnxp1)+fabs(lnxm1));  /*  result = pre*|F|*|f| * cos(angle - tau * (log(x)+M_LN2))   */  gsl_sf_result cos_result;  int stat_cos = gsl_sf_cos_e(angle + tau*(log(x) + M_LN2), &cos_result);  int status = GSL_ERROR_SELECT_4(stat_cos, stat_gd, stat_gn, stat_F);  if(cos_result.val == 0.0) {    result->val = 0.0;    result->err = 0.0;    return status;  }  else {    double lnFf_val = 0.5*log(reF*reF+imF*imF) + lgr_num.val - lgr_den.val;    double lnFf_err = lgr_num.err + lgr_den.err + GSL_DBL_EPSILON * fabs(lnFf_val);    double lnnoc_val = lnpre_const + lnpre_comm + lnFf_val;    double lnnoc_err = lnpre_err + lnFf_err + GSL_DBL_EPSILON * fabs(lnnoc_val);    int stat_e = gsl_sf_exp_mult_err_e(lnnoc_val, lnnoc_err,                                          cos_result.val, cos_result.err,                                          result);    if(stat_e == GSL_SUCCESS) {      *ln_multiplier = 0.0;    }    else {      result->val  = cos_result.val;      result->err  = cos_result.err;      result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);      *ln_multiplier = lnnoc_val;    }    return status;  }}/* P^{mu}_{-1/2 + I tau}  first hypergeometric representation * -1 < x < 1 * This is more effective for |x| small, however it will work w/o * reservation for any x < 0 because everything is positive * definite in that case. * * [Kolbig,   (3)] (note typo in args of gamma functions) * [Bateman, (22)] (correct form) */staticintconicalP_xlt1_hyperg_A(double mu, double tau, double x, gsl_sf_result * result){  double x2 = x*x;  double err_amp = 1.0 + 1.0/(GSL_DBL_EPSILON + fabs(1.0-fabs(x)));  double pre_val = M_SQRTPI / pow(0.5*sqrt(1-x2), mu);  double pre_err = err_amp * GSL_DBL_EPSILON * (fabs(mu)+1.0) * fabs(pre_val) ;  gsl_sf_result ln_g1, ln_g2, arg_g1, arg_g2;  gsl_sf_result F1, F2;  gsl_sf_result pre1, pre2;  double t1_val, t1_err;  double t2_val, t2_err;  int stat_F1 = gsl_sf_hyperg_2F1_conj_e(0.25 - 0.5*mu, 0.5*tau, 0.5, x2, &F1);  int stat_F2 = gsl_sf_hyperg_2F1_conj_e(0.75 - 0.5*mu, 0.5*tau, 1.5, x2, &F2);  int status = GSL_ERROR_SELECT_2(stat_F1, stat_F2);  gsl_sf_lngamma_complex_e(0.75 - 0.5*mu, -0.5*tau, &ln_g1, &arg_g1);  gsl_sf_lngamma_complex_e(0.25 - 0.5*mu, -0.5*tau, &ln_g2, &arg_g2);  gsl_sf_exp_err_e(-2.0*ln_g1.val, 2.0*ln_g1.err, &pre1);  gsl_sf_exp_err_e(-2.0*ln_g2.val, 2.0*ln_g2.err, &pre2);  pre2.val *= -2.0*x;  pre2.err *=  2.0*fabs(x);  pre2.err +=  GSL_DBL_EPSILON * fabs(pre2.val);  t1_val = pre1.val * F1.val;  t1_err = fabs(pre1.val) * F1.err + pre1.err * fabs(F1.val);  t2_val = pre2.val * F2.val;  t2_err = fabs(pre2.val) * F2.err + pre2.err * fabs(F2.val);  result->val  = pre_val * (t1_val + t2_val);  result->err  = pre_val * (t1_err + t2_err);  result->err += pre_err * fabs(t1_val + t2_val);  result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);  return status;}/* P^{mu}_{-1/2 + I tau} * defining hypergeometric representation * [Abramowitz+Stegun, 8.1.2] * 1 < x < 3 * effective for x near 1 * */#if 0staticintconicalP_def_hyperg(double mu, double tau, double x, double * result){  double F;  int stat_F = gsl_sf_hyperg_2F1_conj_renorm_e(0.5, tau, 1.0-mu, 0.5*(1.0-x), &F);  *result = pow((x+1.0)/(x-1.0), 0.5*mu) * F;  return stat_F;}#endif /* 0 *//* P^{mu}_{-1/2 + I tau}  second hypergeometric representation * [Zhurina+Karmazina, (3.1)]  * -1 < x < 3 * effective for x near 1 * */#if 0staticintconicalP_xnear1_hyperg_C(double mu, double tau, double x, double * result){  double ln_pre, arg_pre;  double ln_g1, arg_g1;  double ln_g2, arg_g2;  double F;  int stat_F = gsl_sf_hyperg_2F1_conj_renorm_e(0.5+mu, tau, 1.0+mu, 0.5*(1.0-x), &F);  gsl_sf_lngamma_complex_e(0.5+mu, tau, &ln_g1, &arg_g1);  gsl_sf_lngamma_complex_e(0.5-mu, tau, &ln_g2, &arg_g2);  ln_pre  = mu*M_LN2 - 0.5*mu*log(fabs(x*x-1.0)) + ln_g1 - ln_g2;  arg_pre = arg_g1 - arg_g2;  *result = exp(ln_pre) * F;  return stat_F;}#endif /* 0 *//* V0, V1 from Kolbig, m = 0 */staticintconicalP_0_V(const double t, const double f, const double tau, const double sgn,             double * V0, double * V1){  double C[8];  double T[8];  double H[8];  double V[12];  int i;  T[0] = 1.0;  H[0] = 1.0;  V[0] = 1.0;  for(i=1; i<=7; i++) {    T[i] = T[i-1] * t;    H[i] = H[i-1] * (t*f);  }  for(i=1; i<=11; i++) {    V[i] = V[i-1] * tau;  }  C[0] = 1.0;  C[1] = (H[1]-1.0)/(8.0*T[1]);  C[2] = (9.0*H[2] + 6.0*H[1] - 15.0 - sgn*8.0*T[2])/(128.0*T[2]);  C[3] = 5.0*(15.0*H[3] + 27.0*H[2] + 21.0*H[1] - 63.0 - sgn*T[2]*(16.0*H[1]+24.0))/(1024.0*T[3]);  C[4] = 7.0*(525.0*H[4] + 1500.0*H[3] + 2430.0*H[2] + 1980.0*H[1] - 6435.0              + 192.0*T[4] - sgn*T[2]*(720.0*H[2]+1600.0*H[1]+2160.0)              ) / (32768.0*T[4]);  C[5] = 21.0*(2835.0*H[5] + 11025.0*H[4] + 24750.0*H[3] + 38610.0*H[2]               + 32175.0*H[1] - 109395.0 + T[4]*(1984.0*H[1]+4032.0)               - sgn*T[2]*(4800.0*H[3]+15120.0*H[2]+26400.0*H[1]+34320.0)	       ) / (262144.0*T[5]);  C[6] = 11.0*(218295.0*H[6] + 1071630.0*H[5] + 3009825.0*H[4] + 6142500.0*H[3]               + 9398025.0*H[2] + 7936110.0*H[1] - 27776385.0	       + T[4]*(254016.0*H[2]+749952.0*H[1]+1100736.0)	       - sgn*T[2]*(441000.0*H[4] + 1814400.0*H[3] + 4127760.0*H[2]	                 + 6552000.0*H[1] + 8353800.0 + 31232.0*T[4]			 )               ) / (4194304.0*T[6]);  *V0 = C[0] + (-4.0*C[3]/T[1]+C[4])/V[4]             + (-192.0*C[5]/T[3]+144.0*C[6]/T[2])/V[8]             + sgn * (-C[2]/V[2]	              + (-24.0*C[4]/T[2]+12.0*C[5]/T[1]-C[6])/V[6] 	              + (-1920.0*C[6]/T[4])/V[10]		      );  *V1 = C[1]/V[1] + (8.0*(C[3]/T[2]-C[4]/T[1])+C[5])/V[5]                  + (384.0*C[5]/T[4] - 768.0*C[6]/T[3])/V[9]                  + sgn * ((2.0*C[2]/T[1]-C[3])/V[3]		           + (48.0*C[4]/T[3]-72.0*C[5]/T[2] + 18.0*C[6]/T[1])/V[7]		           + (3840.0*C[6]/T[5])/V[11]		           );  return GSL_SUCCESS;}/* V0, V1 from Kolbig, m = 1 */staticintconicalP_1_V(const double t, const double f, const double tau, const double sgn,             double * V0, double * V1){  double Cm1;  double C[8];  double T[8];  double H[8];  double V[12];  int i;  T[0] = 1.0;  H[0] = 1.0;  V[0] = 1.0;  for(i=1; i<=7; i++) {    T[i] = T[i-1] * t;    H[i] = H[i-1] * (t*f);  }  for(i=1; i<=11; i++) {    V[i] = V[i-1] * tau;  }  Cm1  = -1.0;  C[0] = 3.0*(1.0-H[1])/(8.0*T[1]);  C[1] = (-15.0*H[2]+6.0*H[1]+9.0+sgn*8.0*T[2])/(128.0*T[2]);  C[2] = 3.0*(-35.0*H[3] - 15.0*H[2] + 15.0*H[1] + 35.0 + sgn*T[2]*(32.0*H[1]+8.0))/(1024.0*T[3]);  C[3] = (-4725.0*H[4] - 6300.0*H[3] - 3150.0*H[2] + 3780.0*H[1] + 10395.0          -1216.0*T[4] + sgn*T[2]*(6000.0*H[2]+5760.0*H[1]+1680.0)) / (32768.0*T[4]);  C[4] = 7.0*(-10395.0*H[5] - 23625.0*H[4] - 28350.0*H[3] - 14850.0*H[2]              +19305.0*H[1] + 57915.0 - T[4]*(6336.0*H[1]+6080.0)	      + sgn*T[2]*(16800.0*H[3] + 30000.0*H[2] + 25920.0*H[1] + 7920.0)	      ) / (262144.0*T[5]);  C[5] = (-2837835.0*H[6] - 9168390.0*H[5] - 16372125.0*H[4] - 18918900*H[3]          -10135125.0*H[2] + 13783770.0*H[1] + 43648605.0	  -T[4]*(3044160.0*H[2] + 5588352.0*H[1] + 4213440.0)	  +sgn*T[2]*(5556600.0*H[4] + 14817600.0*H[3] + 20790000.0*H[2]	             + 17297280.0*H[1] + 5405400.0 + 323072.0*T[4]		     )          ) / (4194304.0*T[6]);  C[6] = 0.0;  *V0 = C[0] + (-4.0*C[3]/T[1]+C[4])/V[4]             + (-192.0*C[5]/T[3]+144.0*C[6]/T[2])/V[8]             + sgn * (-C[2]/V[2]	              + (-24.0*C[4]/T[2]+12.0*C[5]/T[1]-C[6])/V[6] 		      );  *V1 = C[1]/V[1] + (8.0*(C[3]/T[2]-C[4]/T[1])+C[5])/V[5]                  + (384.0*C[5]/T[4] - 768.0*C[6]/T[3])/V[9]                  + sgn * (Cm1*V[1] + (2.0*C[2]/T[1]-C[3])/V[3]		           + (48.0*C[4]/T[3]-72.0*C[5]/T[2] + 18.0*C[6]/T[1])/V[7]		           );  return GSL_SUCCESS;}/*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*//* P^0_{-1/2 + I lambda} */intgsl_sf_conicalP_0_e(const double lambda, const double x, gsl_sf_result * result){  /* CHECK_POINTER(result) */  if(x <= -1.0) {    DOMAIN_ERROR(result);  }  else if(x == 1.0) {    result->val = 1.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else if(lambda == 0.0) {    gsl_sf_result K;    int stat_K;    if(x < 1.0) {      const double th = acos(x);      const double s  = sin(0.5*th);      stat_K = gsl_sf_ellint_Kcomp_e(s, GSL_MODE_DEFAULT, &K);      result->val  = 2.0/M_PI * K.val;      result->err  = 2.0/M_PI * K.err;      result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);      return stat_K;    }    else {      const double xi = acosh(x);      const double c  = cosh(0.5*xi);      const double t  = tanh(0.5*xi);      stat_K = gsl_sf_ellint_Kcomp_e(t, GSL_MODE_DEFAULT, &K);      result->val  = 2.0/M_PI / c * K.val;      result->err  = 2.0/M_PI / c * K.err;      result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);      return stat_K;    }  }  else if(   (x <= 0.0 && lambda < 1000.0)          || (x <  0.1 && lambda < 17.0)	  || (x <  0.2 && lambda < 5.0 )    ) {    return conicalP_xlt1_hyperg_A(0.0, lambda, x, result);  }  else if(   (x <= 0.2 && lambda < 17.0)          || (x <= 1.5 && lambda < 20.0)    ) {    return gsl_sf_hyperg_2F1_conj_e(0.5, lambda, 1.0, (1.0-x)/2, result);  }  else if(1.5 < x && lambda < GSL_MAX(x,20.0)) {    gsl_sf_result P;    double lm;    int stat_P = gsl_sf_conicalP_large_x_e(0.0, lambda, x,                                              &P, &lm                                              );    int stat_e = gsl_sf_exp_mult_err_e(lm, 2.0*GSL_DBL_EPSILON * fabs(lm),    					  P.val, P.err,    					  result);    return GSL_ERROR_SELECT_2(stat_e, stat_P);  }  else {    double V0, V1;    if(x < 1.0) {      double th  = acos(x);      double sth = sqrt(1.0-x*x);  /* sin(th) */      gsl_sf_result I0, I1;      int stat_I0 = gsl_sf_bessel_I0_scaled_e(th * lambda, &I0);      int stat_I1 = gsl_sf_bessel_I1_scaled_e(th * lambda, &I1);      int stat_I  = GSL_ERROR_SELECT_2(stat_I0, stat_I1);      int stat_V  = conicalP_0_V(th, x/sth, lambda, -1.0, &V0, &V1);      double bessterm = V0 * I0.val + V1 * I1.val;      double besserr  = fabs(V0) * I0.err + fabs(V1) * I1.err;      double arg1 = th*lambda;      double sqts = sqrt(th/sth);      int stat_e = gsl_sf_exp_mult_err_e(arg1, 4.0 * GSL_DBL_EPSILON * fabs(arg1),                                            sqts * bessterm, sqts * besserr,					    result);      return GSL_ERROR_SELECT_3(stat_e, stat_V, stat_I);    }    else {      double sh = sqrt(x-1.0)*sqrt(x+1.0);  /* sinh(xi)      */      double xi = log(x + sh);              /* xi = acosh(x) */      gsl_sf_result J0, J1;      int stat_J0 = gsl_sf_bessel_J0_e(xi * lambda, &J0);      int stat_J1 = gsl_sf_bessel_J1_e(xi * lambda, &J1);      int stat_J  = GSL_ERROR_SELECT_2(stat_J0, stat_J1);      int stat_V  = conicalP_0_V(xi, x/sh, lambda, 1.0, &V0, &V1);      double bessterm = V0 * J0.val + V1 * J1.val;      double besserr  = fabs(V0) * J0.err + fabs(V1) * J1.err;      double pre_val = sqrt(xi/sh);      double pre_err = 2.0 * fabs(pre_val);      result->val  = pre_val * bessterm;      result->err  = pre_val * besserr;      result->err += pre_err * fabs(bessterm);      result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);      return GSL_ERROR_SELECT_2(stat_V, stat_J);    }  }}/* P^1_{-1/2 + I lambda} */intgsl_sf_conicalP_1_e(const double lambda, const double x, gsl_sf_result * result){  /* CHECK_POINTER(result) */  if(x <= -1.0) {    DOMAIN_ERROR(result);  }  else if(lambda == 0.0) {    gsl_sf_result K, E;    int stat_K, stat_E;    if(x == 1.0) {      result->val = 0.0;      result->err = 0.0;      return GSL_SUCCESS;    }    else if(x < 1.0) {      if(1.0-x < GSL_SQRT_DBL_EPSILON) {        double err_amp = GSL_MAX_DBL(1.0, 1.0/(GSL_DBL_EPSILON + fabs(1.0-x)));        result->val = 0.25/M_SQRT2 * sqrt(1.0-x) * (1.0 + 5.0/16.0 * (1.0-x));	result->err = err_amp * 3.0 * GSL_DBL_EPSILON * fabs(result->val);	return GSL_SUCCESS;      }      else {        const double th = acos(x);        const double s  = sin(0.5*th);        const double c2 = 1.0 - s*s;        const double sth = sin(th);	const double pre = 2.0/(M_PI*sth);        stat_K = gsl_sf_ellint_Kcomp_e(s, GSL_MODE_DEFAULT, &K);        stat_E = gsl_sf_ellint_Ecomp_e(s, GSL_MODE_DEFAULT, &E);        result->val  = pre * (E.val - c2 * K.val);	result->err  = pre * (E.err + fabs(c2) * K.err);	result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);        return stat_K;      }    }    else {      if(x-1.0 < GSL_SQRT_DBL_EPSILON) {        double err_amp = GSL_MAX_DBL(1.0, 1.0/(GSL_DBL_EPSILON + fabs(1.0-x)));        result->val = -0.25/M_SQRT2 * sqrt(x-1.0) * (1.0 - 5.0/16.0 * (x-1.0));	result->err = err_amp * 3.0 * GSL_DBL_EPSILON * fabs(result->val);	return GSL_SUCCESS;      }      else {        const double xi = acosh(x);        const double c  = cosh(0.5*xi);        const double t  = tanh(0.5*xi);        const double sxi = sinh(xi);	const double pre = 2.0/(M_PI*sxi) * c;        stat_K = gsl_sf_ellint_Kcomp_e(t, GSL_MODE_DEFAULT, &K);        stat_E = gsl_sf_ellint_Ecomp_e(t, GSL_MODE_DEFAULT, &E);

⌨️ 快捷键说明

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