/* Evaluate bessel_J(nu, x), allowing nu < 0. * This is fine here because we do not not allow * nu to be a negative integer. * x > 0. */ static int hyperg_0F1_bessel_J(const double nu, const double x, gsl_sf_result * result) { if(nu < 0.0) { const double anu = -nu; const double s = sin(anu*M_PI); const double c = cos(anu*M_PI); gsl_sf_result J; gsl_sf_result Y; int stat_J = gsl_sf_bessel_Jnu_e(anu, x, &J); int stat_Y = gsl_sf_bessel_Ynu_e(anu, x, &Y); result->val = c * J.val - s * Y.val; result->err = fabs(c * J.err) + fabs(s * Y.err); result->err += fabs(anu * M_PI) * GSL_DBL_EPSILON * fabs(J.val + Y.val); return GSL_ERROR_SELECT_2(stat_Y, stat_J); } else { return gsl_sf_bessel_Jnu_e(nu, x, result); } }
/// Cylindrical Bessel functions (of the first kind). double cyl_bessel_j(double nu, double x) { gsl_sf_result result; int stat = gsl_sf_bessel_Jnu_e(nu, x, &result); if (stat != GSL_SUCCESS) { std::ostringstream msg("Error in cyl_bessel_j:"); msg << " nu=" << nu << " x=" << x; throw std::runtime_error(msg.str()); } else return result.val; }
double gsl_sf_bessel_Jnu(const double nu, const double x) { EVAL_RESULT(gsl_sf_bessel_Jnu_e(nu, x, &result)); }
int gsl_sf_bessel_sequence_Jnu_e(double nu, gsl_mode_t mode, size_t size, double * v) { /* CHECK_POINTER(v) */ if(nu < 0.0) { GSL_ERROR ("domain error", GSL_EDOM); } else if(size == 0) { GSL_ERROR ("error", GSL_EINVAL); } else { const gsl_prec_t goal = GSL_MODE_PREC(mode); const double dx_array[] = { 0.001, 0.03, 0.1 }; /* double, single, approx */ const double dx_nominal = dx_array[goal]; const int cnu = (int) ceil(nu); const double nu13 = pow(nu,1.0/3.0); const double smalls[] = { 0.01, 0.02, 0.4, 0.7, 1.3, 2.0, 2.5, 3.2, 3.5, 4.5, 6.0 }; const double x_small = ( nu >= 10.0 ? nu - nu13 : smalls[cnu] ); gsl_sf_result J0, J1; double Jp, J; double x; size_t i = 0; /* Calculate the first point. */ x = v[0]; gsl_sf_bessel_Jnu_e(nu, x, &J0); v[0] = J0.val; ++i; /* Step over the idiot case where the * first point was actually zero. */ if(x == 0.0) { if(v[1] <= x) { /* Strict ordering failure. */ GSL_ERROR ("error", GSL_EFAILED); } x = v[1]; gsl_sf_bessel_Jnu_e(nu, x, &J0); v[1] = J0.val; ++i; } /* Calculate directly as long as the argument * is small. This is necessary because the * integration is not very good there. */ while(v[i] < x_small && i < size) { if(v[i] <= x) { /* Strict ordering failure. */ GSL_ERROR ("error", GSL_EFAILED); } x = v[i]; gsl_sf_bessel_Jnu_e(nu, x, &J0); v[i] = J0.val; ++i; } /* At this point we are ready to integrate. * The value of x is the last calculated * point, which has the value J0; v[i] is * the next point we need to calculate. We * calculate nu+1 at x as well to get * the derivative, then we go forward. */ gsl_sf_bessel_Jnu_e(nu+1.0, x, &J1); J = J0.val; Jp = -J1.val + nu/x * J0.val; while(i < size) { const double dv = v[i] - x; const int Nd = (int) ceil(dv/dx_nominal); const double dx = dv / Nd; double xj; int j; if(v[i] <= x) { /* Strict ordering failure. */ GSL_ERROR ("error", GSL_EFAILED); } /* Integrate over interval up to next sample point. */ for(j=0, xj=x; j<Nd; j++, xj += dx) { rk_step(nu, xj, dx, &Jp, &J); } /* Go to next interval. */ x = v[i]; v[i] = J; ++i; } return GSL_SUCCESS; } }