101 gampl = 1.0 / std::tgamma(1.0 + mu);
102 gammi = 1.0 / std::tgamma(1.0 - mu);
103 gam2 = 0.5 * (gammi + gampl);
104 if (std::fabs(mu) < 0.01) {
106 static constexpr Real a2 = 0.5772156649015328606L, a4 = -0.0420026350340952355L, a6 = -0.0421977345555443367L,
107 a8 = 0.0072189432466630995L;
109 gam1 = -(a2 + muSq * (a4 + muSq * (a6 + muSq * a8)));
111 gam1 = (gammi - gampl) / (2 * mu);
123inline void besselIK(Real nu, Real x, Real &ri, Real &rk)
125 constexpr Real FPMIN = std::numeric_limits<Real>::min() / machineEpsilon<Real>;
126 constexpr Real XMIN = 2;
127 const int nl =
static_cast<int>(nu + 0.5);
128 const Real xmu = nu - nl, xmu2 = xmu * xmu;
129 const Real xi = 1 / x, xi2 = 2 * xi;
132 Real h = std::max(nu * xi, FPMIN);
133 Real b = xi2 * nu, d = 0, c = h;
140 if (std::fabs(del - 1) < machineEpsilon<Real>)
145 Real ril = FPMIN, ripl = h * ril;
146 const Real ril1 = ril;
148 for (
int l = nl - 1; l >= 0; --l) {
149 Real ritemp = fact * ril + ripl;
151 ripl = fact * ritemp + ril;
154 const Real f = ripl / ril;
156 Real rkmu = 0, rk1 = 0;
160 Real factor = (std::fabs(pimu) < machineEpsilon<Real>) ? Real{1} : pimu / std::sin(pimu);
161 Real dd = -std::log(x2), e = xmu * dd;
162 Real factor2 = (std::fabs(e) < machineEpsilon<Real>) ? Real{1} : std::sinh(e) / e;
163 Real gam1, gam2, gampl, gammi;
165 Real ff = factor * (gam1 * std::cosh(e) + gam2 * factor2 * dd);
168 Real p = Real{0.5} * e / gampl, q = Real{0.5} / (e * gammi), cc = 1, x2Sq = x2 * x2;
171 ff = (i * ff + p + q) / (i * i - xmu2);
177 sum1 += cc * (p - i * ff);
178 if (std::fabs(del) < std::fabs(sum) * machineEpsilon<Real>)
185 Real bb = 2 * (1 + x), dd = 1 / bb, hh = dd, delh = dd;
186 Real q1 = 0, q2 = 1, a1 = Real{0.25} - xmu2, q = a1, cc = a1, a = -a1;
187 Real s = 1 + q * delh;
190 cc = -a * cc / (i + 1.0);
191 Real qnew = (q1 - bb * q2) / a;
196 dd = 1.0 / (bb + a * dd);
197 delh = (bb * dd - 1.0) * delh;
199 Real dels = q * delh;
201 if (std::fabs(dels / s) < machineEpsilon<Real>)
206 rk1 = rkmu * (xmu + x + 0.5 - hh) * xi;
210 Real rkmup = xmu * xi * rkmu - rk1;
211 Real rimu = xi / (f * rkmu - rkmup);
212 ri = (rimu * ril1) / ril;
213 for (
int i = 1; i <= nl; ++i) {
214 Real rktemp = (xmu + i) * xi2 * rk1 + rkmu;
238inline Real
besselI(std::type_identity_t<Real> nu, Real x)
242 return (nu == 0.0) ? 1.0 : 0.0;
243 const Real overflowLimit = std::numeric_limits<Real>::max_exponent == std::numeric_limits<double>::max_exponent
245 : std::log(std::numeric_limits<Real>::max()) - Real{10};
246 if (x > overflowLimit) {
248 return std::numeric_limits<Real>::infinity();
250 if (x < 5.0 || x * x < 4.0 * (nu + 1.0)) {
252 Real y = Real{0.25} * x * x, term = 1, sum = 1;
254 term *= y / (k * (nu + k));
259 return std::exp(nu * std::log(0.5 * x) - std::lgamma(nu + 1.0)) * sum;
286 throw std::domain_error(
"Riemann zeta function: argument should be greater than 1, but it's equal to " +
289 return Real{1} + std::pow(Real{2}, -s) + std::pow(Real{3}, -s);
292 static constexpr int N = 20;
293 static constexpr Real B2jOverFact[] = {Real{1} / 12,
298 -Real{691} / Real{1307674368000},
299 Real{1} / Real{74724249600},
300 -Real{3617} / Real{10670622842880000},
301 Real{43867} / Real{5109094217170944000},
302 -Real{174611} /
static_cast<Real
>(802857662698291200000.0L)};
304 for (
int k = 1; k < N; ++k)
305 sum += std::pow(
static_cast<Real
>(k), -s);
306 Real nPow = std::pow(
static_cast<Real
>(N), -s);
307 sum += N * nPow / (s - 1) + Real{0.5} * nPow;
308 Real rising = s, term = nPow / N;
309 for (
int j = 0; j < 10; ++j) {
310 sum += B2jOverFact[j] * rising * term;
311 rising *= (s + 2 * j + 1) * (s + 2 * j + 2);
312 term /=
static_cast<Real
>(N) * N;
353 throw std::domain_error(
"Stirling correction: argument should be at least 10, but it's equal to " +
355 static constexpr Real c[] = {Real{1} / 12, -Real{1} / 360, Real{1} / 1260, -Real{1} / 1680,
356 Real{1} / 1188, -Real{691} / 360360, Real{1} / 156};
357 Real xInv = 1 / x, xInvSq = xInv * xInv;
359 for (
int i = 5; i >= 0; --i)
360 sum = sum * xInvSq + c[i];
void reciprocalGammaTerms(Real mu, Real &gam1, Real &gam2, Real &gampl, Real &gammi)
Values needed by Temme's series for |μ| ≤ 1/2: gam1 = (1/Γ(1-μ) - 1/Γ(1+μ)) / (2μ),...
Definition special_functions.hpp:99
void besselIK(Real nu, Real x, Real &ri, Real &rk)
Temme's method with Steed's continued fraction (Numerical Recipes, "bessik")
Definition special_functions.hpp:123