|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once |
|
|
|
#include "cephes/lanczos.h" |
|
#include "cephes/polevl.h" |
|
#include "cephes/rgamma.h" |
|
#include "config.h" |
|
#include "digamma.h" |
|
#include "error.h" |
|
|
|
namespace xsf { |
|
|
|
namespace detail { |
|
|
|
constexpr double rgamma_zero = 178.47241115886637; |
|
|
|
XSF_HOST_DEVICE inline double exp_rgamma(double x, double y) { |
|
|
|
|
|
|
|
|
|
|
|
return std::exp(x + (1 - std::log(y + cephes::lanczos_g - 0.5)) * (y - 0.5)) / |
|
cephes::lanczos_sum_expg_scaled(y); |
|
} |
|
|
|
XSF_HOST_DEVICE inline double wb_series(double a, double b, double x, unsigned int nstart, unsigned int nstop) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double xk_k = std::pow(x, nstart) * cephes::rgamma(nstart + 1); |
|
double res = xk_k * cephes::rgamma(nstart * a + b); |
|
|
|
if (nstop > nstart) { |
|
|
|
unsigned int k_max = std::floor((rgamma_zero - b) / a); |
|
if (nstop > k_max) { |
|
nstop = k_max; |
|
} |
|
for (unsigned int k = nstart + 1; k < nstop; k++) { |
|
xk_k *= x / k; |
|
res += xk_k * cephes::rgamma(a * k + b); |
|
} |
|
} |
|
return res; |
|
} |
|
|
|
template<bool log_wb> |
|
XSF_HOST_DEVICE inline double wb_large_a(double a, double b, double x, int n) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int k_max = static_cast<int>(std::pow(std::pow(a, -a) * x, 1.0 / (1 + a))); |
|
|
|
int nstart = k_max - n / 2; |
|
if (nstart < 0) { |
|
nstart = 0; |
|
} |
|
|
|
double res = 0; |
|
double lnx = std::log(x); |
|
|
|
|
|
double max_exponent = std::fmax(0, k_max * lnx - cephes::lgam(k_max + 1) - cephes::lgam(a * k_max + b)); |
|
for (int k = nstart; k < nstart + n; k++) { |
|
res += std::exp(k * lnx - cephes::lgam(k + 1) - cephes::lgam(a * k + b) - max_exponent); |
|
} |
|
|
|
if (!log_wb) { |
|
res *= std::exp(max_exponent); |
|
} else { |
|
|
|
res = max_exponent + std::log(res); |
|
} |
|
return res; |
|
} |
|
|
|
template<bool log_wb> |
|
XSF_HOST_DEVICE inline double wb_small_a(double a, double b, double x, int order) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double A[6]; |
|
double B[6]; |
|
constexpr double C[5] = { |
|
1.0000000000000000, |
|
1.1544313298030657, |
|
-3.9352684291215233, |
|
-1.0080632408182857, |
|
19.984633365874979, |
|
}; |
|
double X[6] = { |
|
1, |
|
x, |
|
x * (x + 1), |
|
x * (x * (x + 3) + 1), |
|
x * (x * (x * (x + 6) + 7) + 1), |
|
x * (x * (x * (x * (x + 10) + 25) + 15) + 1), |
|
}; |
|
double res; |
|
|
|
if (b <= 1E-3) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
B[0] = 1.; |
|
for (int k = 1; k < 5; k++) { |
|
B[k] = b / k * B[k - 1]; |
|
} |
|
|
|
A[5] = cephes::rgamma(b); |
|
A[4] = X[1] * (C[0] + C[1] * b + C[2] * B[2] + C[3] * B[3] + C[4] * B[4]); |
|
A[3] = X[2] / 2. * (C[1] + C[2] * b + C[3] * B[2] + C[4] * B[3]); |
|
A[2] = X[3] / 6. * (C[2] + C[3] * b + C[4] * B[2]); |
|
A[1] = X[4] / 24. * (C[3] + C[4] * b); |
|
A[0] = X[5] / 120. * C[4]; |
|
|
|
if (!log_wb) { |
|
res = exp(x) * cephes::polevl(a, A, 5); |
|
} else { |
|
|
|
res = x + std::log(cephes::polevl(a, A, 5)); |
|
} |
|
} else { |
|
|
|
|
|
|
|
|
|
double dg = digamma(b); |
|
|
|
double pg1 = cephes::zeta(2, b); |
|
if (order <= 2) { |
|
res = 1 + a * x * (-dg + 0.5 * a * (1 + x) * (dg * dg - pg1)); |
|
} else { |
|
if (order > 5) { |
|
order = 5; |
|
} |
|
|
|
double pg2 = -2 * cephes::zeta(3, b); |
|
B[0] = 1; |
|
B[1] = -dg; |
|
B[2] = dg * dg - pg1; |
|
B[3] = (-dg * dg + 3 * pg1) * dg - pg2; |
|
A[order] = 1; |
|
A[order - 1] = X[1] * B[1]; |
|
A[order - 2] = X[2] * B[2] / 2.; |
|
A[order - 3] = X[3] * B[3] / 6.; |
|
if (order >= 4) { |
|
|
|
double pg3 = 6 * cephes::zeta(4, b); |
|
B[4] = ((dg * dg - 6 * pg1) * dg + 4 * pg2) * dg + 3 * pg1 * pg1 - pg3; |
|
A[order - 4] = X[4] * B[4] / 24.; |
|
if (order >= 5) { |
|
|
|
double pg4 = -24 * cephes::zeta(5, b); |
|
B[5] = |
|
((((-dg * dg + 10 * pg1) * dg - 10 * pg2) * dg - 15 * pg1 * pg1 + 5 * pg3) * dg + |
|
10 * pg1 * pg2 - pg4); |
|
A[order - 5] = X[5] * B[5] / 120.; |
|
} |
|
} |
|
res = cephes::polevl(a, A, order); |
|
} |
|
|
|
if (!log_wb) { |
|
res *= exp_rgamma(x, b); |
|
} else { |
|
|
|
res = x - cephes::lgam(b) + std::log(res); |
|
} |
|
} |
|
return res; |
|
} |
|
|
|
template<bool log_wb> |
|
XSF_HOST_DEVICE inline double wb_asymptotic(double a, double b, double x) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double A[15]; |
|
double B[17]; |
|
double Ap1[9]; |
|
double C[9]; |
|
|
|
A[0] = 1.; |
|
B[0] = 1.; |
|
Ap1[0] = 1.; |
|
for (int k = 1; k < 15; k++) { |
|
A[k] = A[k - 1] * a; |
|
} |
|
for (int k = 1; k < 17; k++) { |
|
B[k] = B[k - 1] * b; |
|
} |
|
for (int k = 1; k < 9; k++) { |
|
Ap1[k] = Ap1[k - 1] * (1 + a); |
|
} |
|
|
|
C[0] = 1. / std::sqrt(2. * M_PI * Ap1[1]); |
|
|
|
C[1] = C[0] / (24 * Ap1[1]); |
|
C[1] *= (2 * a + 1) * (2 + a) - 12 * b * (1 + a - b); |
|
|
|
C[2] = C[0] / (1152 * Ap1[2]); |
|
C[2] *= |
|
(144 * B[4] - 96 * B[3] * (5 * a + 1) + 24 * B[2] * (20 * A[2] + 5 * a - 4) - |
|
24 * b * Ap1[1] * (6 * A[2] - 7 * a - 2) + (a + 2) * (2 * a + 1) * (2 * A[2] - 19 * a + 2)); |
|
|
|
C[3] = C[0] / (414720 * Ap1[3]); |
|
C[3] *= |
|
(8640 * B[6] - 8640 * B[5] * (7 * a - 1) + 10800 * B[4] * (14 * A[2] - 7 * a - 2) - |
|
1440 * B[3] * (112 * A[3] - 147 * A[2] - 63 * a + 8) + |
|
180 * B[2] * (364 * A[4] - 1288 * A[3] - 567 * A[2] + 392 * a + 76) - |
|
180 * b * Ap1[1] * (20 * A[4] - 516 * A[3] + 417 * A[2] + 172 * a - 12) - |
|
(a + 2) * (2 * a + 1) * (556 * A[4] + 1628 * A[3] - 9093 * A[2] + 1628 * a + 556)); |
|
|
|
C[4] = C[0] / (39813120 * Ap1[4]); |
|
C[4] *= |
|
(103680 * B[8] - 414720 * B[7] * (3 * a - 1) + 725760 * B[6] * a * (8 * a - 7) - |
|
48384 * B[5] * (274 * A[3] - 489 * A[2] + 39 * a + 26) + |
|
30240 * B[4] * (500 * A[4] - 1740 * A[3] + 495 * A[2] + 340 * a - 12) - |
|
2880 * B[3] * (2588 * A[5] - 19780 * A[4] + 14453 * A[3] + 9697 * A[2] - 1892 * a - 404) + |
|
48 * B[2] * |
|
(11488 * A[6] - 547836 * A[5] + 1007484 * A[4] + 593353 * A[3] - 411276 * A[2] - 114396 * a + 4288) + |
|
48 * b * Ap1[1] * |
|
(7784 * A[6] + 48180 * A[5] - 491202 * A[4] + 336347 * A[3] + 163734 * A[2] - 28908 * a - 5560) - |
|
(a + 2) * (2 * a + 1) * |
|
(4568 * A[6] - 226668 * A[5] - 465702 * A[4] + 2013479 * A[3] - 465702 * A[2] - 226668 * a + 4568)); |
|
|
|
C[5] = C[0] / (6688604160. * Ap1[5]); |
|
C[5] *= |
|
(1741824 * B[10] - 2903040 * B[9] * (11 * a - 5) + 2177280 * B[8] * (110 * A[2] - 121 * a + 14) - |
|
580608 * B[7] * (1628 * A[3] - 3333 * A[2] + 1023 * a + 52) + |
|
169344 * B[6] * (12364 * A[4] - 43648 * A[3] + 26763 * A[2] + 1232 * a - 788) - |
|
24192 * B[5] * (104852 * A[5] - 646624 * A[4] + 721391 * A[3] - 16841 * A[2] - 74096 * a + 148) + |
|
2016 * B[4] * |
|
(710248 * A[6] - 8878716 * A[5] + 17928834 * A[4] - 3333407 * A[3] - 4339566 * A[2] + 287364 * a + |
|
89128) - |
|
1344 * B[3] * |
|
(87824 * A[7] - 7150220 * A[6] + 29202756 * A[5] - 15113527 * A[4] - 14223011 * A[3] + 3462492 * A[2] + |
|
1137092 * a - 18896) - |
|
84 * B[2] * |
|
(1690480 * A[8] + 14139136 * A[7] - 232575464 * A[6] + 296712592 * A[5] + 215856619 * A[4] - |
|
152181392 * A[3] - 47718440 * A[2] + 5813632 * a + 943216) + |
|
84 * b * Ap1[1] * |
|
(82224 * A[8] - 5628896 * A[7] - 26466520 * A[6] + 168779208 * A[5] - 104808005 * A[4] - |
|
56259736 * A[3] + 15879912 * A[2] + 4020640 * a - 63952) + |
|
(a + 2) * (2 * a + 1) * |
|
(2622064 * A[8] + 12598624 * A[7] - 167685080 * A[6] - 302008904 * A[5] + 1115235367. * A[4] - |
|
302008904 * A[3] - 167685080 * A[2] + 12598624 * a + 2622064)); |
|
|
|
C[6] = C[0] / (4815794995200. * Ap1[6]); |
|
C[6] *= |
|
(104509440 * B[12] - 209018880 * B[11] * (13 * a - 7) + 574801920 * B[10] * (52 * A[2] - 65 * a + 12) - |
|
63866880 * B[9] * (2834 * A[3] - 6279 * A[2] + 2769 * a - 134) + |
|
23950080 * B[8] * (27404 * A[4] - 98228 * A[3] + 78663 * A[2] - 10868 * a - 1012) - |
|
13685760 * B[7] * (105612 * A[5] - 599196 * A[4] + 791843 * A[3] - 224913 * A[2] - 27612 * a + 4540) + |
|
2661120 * B[6] * |
|
(693680 * A[6] - 6473532 * A[5] + 13736424 * A[4] - 7047469 * A[3] - 723840 * A[2] + 471588 * a + 7376 |
|
) - |
|
2661120 * B[5] * |
|
(432536 * A[7] - 7850804 * A[6] + 27531114 * A[5] - 24234457 * A[4] - 703001 * A[3] + 3633474 * A[2] - |
|
36244 * a - 45128) + |
|
166320 * B[4] * |
|
(548912 * A[8] - 75660832 * A[7] + 502902712 * A[6] - 764807992 * A[5] + 91248287 * A[4] + |
|
217811464 * A[3] - 20365384 * A[2] - 9776416 * a + 37936) + |
|
10080 * B[3] * |
|
(18759728 * A[9] + 165932208 * A[8] - 4710418440. * A[7] + 13686052536. * A[6] - 5456818809. * A[5] - |
|
6834514245. * A[4] + 1919299512. * A[3] + 752176152 * A[2] - 45661200 * a - 8616848) - |
|
360 * B[2] * |
|
(32743360 * A[10] - 3381871792. * A[9] - 21488827776. * A[8] + 200389923864. * A[7] - |
|
198708005340. * A[6] - 171633799779. * A[5] + 123124874028. * A[4] + 40072774872. * A[3] - |
|
9137993280. * A[2] - 1895843248. * a + 18929728) - |
|
360 * b * Ap1[1] * |
|
(57685408 * A[10] + 406929456 * A[9] - 6125375760. * A[8] - 27094918920. * A[7] + |
|
128752249410. * A[6] - 74866710561. * A[5] - 42917416470. * A[4] + 16256951352. * A[3] + |
|
4375268400. * A[2] - 316500688 * a - 47197152) + |
|
(a + 2) * (2 * a + 1) * |
|
(167898208 * A[10] - 22774946512. * A[9] - 88280004528. * A[8] + 611863976472. * A[7] + |
|
1041430242126. * A[6] - 3446851131657. * A[5] + 1041430242126. * A[4] + 611863976472. * A[3] - |
|
88280004528. * A[2] - 22774946512. * a + 167898208)); |
|
|
|
C[7] = C[0] / (115579079884800. * Ap1[7]); |
|
C[7] *= |
|
(179159040 * B[14] - 1254113280. * B[13] * (5 * a - 3) + 1358622720. * B[12] * (70 * A[2] - 95 * a + 22) - |
|
905748480 * B[11] * (904 * A[3] - 2109 * A[2] + 1119 * a - 112) + |
|
1245404160. * B[10] * (3532 * A[4] - 12824 * A[3] + 11829 * A[2] - 2824 * a + 44) - |
|
59304960 * B[9] * (256820 * A[5] - 1397680 * A[4] + 2025545 * A[3] - 869495 * A[2] + 52000 * a + 8788) + |
|
14826240 * B[8] * |
|
(2274536 * A[6] - 18601572 * A[5] + 40698318 * A[4] - 28230079 * A[3] + 3916398 * A[2] + 832668 * a - |
|
65176) - |
|
59304960 * B[7] * |
|
(760224 * A[7] - 9849164 * A[6] + 32495784 * A[5] - 34813869 * A[4] + 9175207 * A[3] + 1898688 * A[2] - |
|
469788 * a - 13184) + |
|
25945920 * B[6] * |
|
(1167504 * A[8] - 28779840 * A[7] + 149752856 * A[6] - 246026112 * A[5] + 111944073 * A[4] + |
|
18341600 * A[3] - 12131496 * A[2] - 274368 * a + 102800) - |
|
157248 * B[5] * |
|
(12341872 * A[9] - 3122991216. * A[8] + 29900054232. * A[7] - 78024816720. * A[6] + |
|
58914656739. * A[5] + 4637150811. * A[4] - 11523402480. * A[3] + 236218968 * A[2] + 337923216 * a + |
|
1592048) - |
|
28080 * B[4] * |
|
(265154912 * A[10] + 2276098704. * A[9] - 105569461008. * A[8] + 496560666360. * A[7] - |
|
627891462858. * A[6] + 41935358025. * A[5] + 203913875814. * A[4] - 23984801544. * A[3] - |
|
13869306000. * A[2] + 372786832 * a + 103532640) + |
|
1440 * B[3] * |
|
(310292864 * A[11] - 55169117872. * A[10] - 358957020112. * A[9] + 5714152556088. * A[8] - |
|
13241597459352. * A[7] + 4220720097141. * A[6] + 6845418090249. * A[5] - 2129559215808. * A[4] - |
|
909225098472. * A[3] + 107518582576. * A[2] + 25619444368. * a - 113832704) + |
|
12 * B[2] * |
|
(135319651136. * A[12] + 1119107842176. * A[11] - 22193518174320. * A[10] - 133421793595520. * A[9] + |
|
860103051087996. * A[8] - 703353374803080. * A[7] - 704240127687381. * A[6] + |
|
513111704637960. * A[5] + 166909061348316. * A[4] - 57671564069120. * A[3] - 12453426246000. * A[2] + |
|
695901207936. * a + 93786157376.) - |
|
12 * b * Ap1[1] * |
|
(4365353408. * A[12] - 720248637504. * A[11] - 4222331152560. * A[10] + 29413934270560. * A[9] + |
|
132123980710980. * A[8] - 511247376962820. * A[7] + 283403639131779. * A[6] + |
|
170415792320940. * A[5] - 79274388426588. * A[4] - 21009953050400. * A[3] + 3284035340880. * A[2] + |
|
589294339776. * a - 3693760576.) - |
|
(a + 2) * (2 * a + 1) * |
|
(34221025984. * A[12] + 226022948160. * A[11] - 5067505612464. * A[10] - 18868361443936. * A[9] + |
|
86215425028308. * A[8] + 143500920544692. * A[7] - 437682618704613. * A[6] + 143500920544692. * A[5] + |
|
86215425028308. * A[4] - 18868361443936. * A[3] - 5067505612464. * A[2] + 226022948160. * a + |
|
34221025984.)); |
|
|
|
C[8] = C[0] / (22191183337881600. * Ap1[8]); |
|
C[8] *= |
|
(2149908480. * B[16] - 5733089280. * B[15] * (17 * a - 11) + |
|
7166361600. * B[14] * (272 * A[2] - 391 * a + 104) - |
|
3344302080. * B[13] * (6766 * A[3] - 16371 * A[2] + 9741 * a - 1306) + |
|
1811496960. * B[12] * (93092 * A[4] - 341564 * A[3] + 344199 * A[2] - 104924 * a + 6308) - |
|
517570560 * B[11] * |
|
(1626220 * A[5] - 8641508 * A[4] + 13274773 * A[3] - 6952303 * A[2] + 1007420 * a + 5564) + |
|
284663808 * B[10] * |
|
(9979136 * A[6] - 75766892 * A[5] + 169256148 * A[4] - 136824959 * A[3] + 35714348 * A[2] - |
|
463692 * a - 293664) - |
|
1423319040. * B[9] * |
|
(4466648 * A[7] - 49231116 * A[6] + 157507414 * A[5] - 187114257 * A[4] + 78372295 * A[3] - |
|
4470082 * A[2] - 1913996 * a + 82424) + |
|
266872320 * B[8] * |
|
(33133136 * A[8] - 564264544 * A[7] + 2618606424. * A[6] - 4491310104. * A[5] + 2853943765. * A[4] - |
|
374694552 * A[3] - 135365288 * A[2] + 17623968 * a + 696912) - |
|
2156544 * B[7] * |
|
(2914256144. * A[9] - 93491712432. * A[8] + 664876176984. * A[7] - 1661362937880. * A[6] + |
|
1563719627313. * A[5] - 382840842843. * A[4] - 115399415640. * A[3] + 34565562936. * A[2] + |
|
1609337232. * a - 217321904) + |
|
179712 * B[6] * |
|
(1266018560. * A[10] - 789261834512. * A[9] + 10186841596896. * A[8] - 38877799073352. * A[7] + |
|
54334425968952. * A[6] - 22529574889533. * A[5] - 5132942328000. * A[4] + 3438377465592. * A[3] + |
|
84287641248. * A[2] - 72493479440. * a - 807415936) + |
|
13824 * B[5] * |
|
(156356794976. * A[11] + 1180898077328. * A[10] - 90615270907936. * A[9] + 609258947056248. * A[8] - |
|
1312655191366722. * A[7] + 885900509321745. * A[6] + 112162151855265. * A[5] - |
|
212803071513258. * A[4] + 6805217831352. * A[3] + 10051742651296. * A[2] - 55035924848. * a - |
|
52946379296.) - |
|
576 * B[4] * |
|
(143943926464. * A[12] - 60115486481856. * A[11] - 376366989757200. * A[10] + |
|
9534223075576160. * A[9] - 35603777465262396. * A[8] + 39375990156664980. * A[7] - |
|
868175004137259. * A[6] - 14279180718355020. * A[5] + 1985747535239364. * A[4] + |
|
1264001337603680. * A[3] - 75972792514320. * A[2] - 23855850572736. * a - 4996648256.) - |
|
384 * B[3] * |
|
(2038525473856. * A[13] + 16057322146112. * A[12] - 502133360559024. * A[11] - |
|
2985686417468080. * A[10] + 32418922182093292. * A[9] - 63665380623022452. * A[8] + |
|
16481208821092575. * A[7] + 34161547357596099. * A[6] - 11490298497454932. * A[5] - |
|
5117272758337156. * A[4] + 933703210750480. * A[3] + 234855186762000. * A[2] - 7860524600000. * a - |
|
1226607567040.) + |
|
96 * B[2] * |
|
(324439754752. * A[14] - 77231415197120. * A[13] - 539102931841856. * A[12] + |
|
4618258299956336. * A[11] + 28588485529469792. * A[10] - 141383982651179428. * A[9] + |
|
98783147840417772. * A[8] + 112831723492305801. * A[7] - 83329761150975036. * A[6] - |
|
26553582937192900. * A[5] + 12469117738765952. * A[4] + 2587165396642160. * A[3] - |
|
340406368038080. * A[2] - 53659641606080. * a + 219671272960.) + |
|
96 * b * Ap1[1] * |
|
(1026630779520. * A[14] + 8781958472768. * A[13] - 210659786204384. * A[12] - |
|
1222283505284208. * A[11] + 5064251967491416. * A[10] + 24013052207628140. * A[9] - |
|
79710880160087370. * A[8] + 42596558293213227. * A[7] + 26570293386695790. * A[6] - |
|
14407831324576884. * A[5] - 3617322833922440. * A[4] + 950664948554384. * A[3] + |
|
172358006894496. * A[2] - 7430887938496. * a - 889746675584.) - |
|
(a + 2) * (2 * a + 1) * |
|
(573840801152. * A[14] - 156998277198784. * A[13] - 898376974770592. * A[12] + |
|
8622589006459984. * A[11] + 32874204024803560. * A[10] - 111492707520083828. * A[9] - |
|
184768503480287646. * A[8] + 528612016938984183. * A[7] - 184768503480287646. * A[6] - |
|
111492707520083828. * A[5] + 32874204024803560. * A[4] + 8622589006459984. * A[3] - |
|
898376974770592. * A[2] - 156998277198784. * a + 573840801152.)); |
|
|
|
double Z = std::pow(a * x, 1 / Ap1[1]); |
|
double Zp = 1.; |
|
double res = C[0]; |
|
for (int k = 1; k < 9; k++) { |
|
Zp /= Z; |
|
res += (k % 2 == 0 ? 1 : -1) * C[k] * Zp; |
|
} |
|
if (!log_wb) { |
|
res *= std::pow(Z, 0.5 - b) * std::exp(Ap1[1] / a * Z); |
|
} else { |
|
|
|
res = std::log(Z) * (0.5 - b) + Ap1[1] / a * Z + std::log(res); |
|
} |
|
return res; |
|
} |
|
|
|
XSF_HOST_DEVICE inline double wb_Kmod(double exp_term, double eps, double a, double b, double x, double r) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double x_r_a = x * std::pow(r + eps, -a); |
|
return std::exp(x_r_a * cephes::cospi(a) + exp_term) * std::pow(r + eps, -b) * |
|
std::sin(x_r_a * cephes::sinpi(a) + M_PI * b); |
|
} |
|
|
|
XSF_HOST_DEVICE inline double wb_P(double exp_term, double eps, double a, double b, double x, double phi) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double x_eps_a = x * std::pow(eps, -a); |
|
return std::exp(eps * std::cos(phi) + x_eps_a * std::cos(a * phi) + exp_term) * |
|
std::cos(eps * std::sin(phi) - x_eps_a * std::sin(a * phi) + (1 - b) * phi); |
|
} |
|
|
|
|
|
|
|
|
|
constexpr double wb_x_laguerre[] = { |
|
0.02863051833937908, 0.1508829356769337, 0.3709487815348964, 0.6890906998810479, 1.105625023539913, |
|
1.620961751102501, 2.23561037591518, 2.950183366641835, 3.765399774405782, 4.682089387559285, |
|
5.70119757478489, 6.823790909794551, 8.051063669390792, 9.384345308258407, 10.82510903154915, |
|
12.37498160875746, 14.03575459982991, 15.80939719784467, 17.69807093335025, 19.70414653546156, |
|
21.83022330657825, 24.0791514444115, 26.45405784125298, 28.95837601193738, 31.59588095662286, |
|
34.37072996309045, 37.28751061055049, 40.35129757358607, 43.56772026999502, 46.94304399160304, |
|
50.48426796312992, 54.19924488016862, 58.09682801724853, 62.18705417568891, 66.48137387844482, |
|
70.99294482661949, 75.73701154772731, 80.73140480247769, 85.99721113646323, 91.55969041253388, |
|
97.44956561485056, 103.7048912366923, 110.3738588076403, 117.5191982031112, 125.2254701334734, |
|
133.6120279227287, 142.8583254892541, 153.2603719726036, 165.3856433166825, 180.6983437092145 |
|
}; |
|
|
|
|
|
constexpr double wb_w_laguerre[] = { |
|
0.07140472613518988, 0.1471486069645884, 0.1856716275748313, 0.1843853825273539, |
|
0.1542011686063556, 0.1116853699022688, 0.07105288549019586, 0.04002027691150833, |
|
0.02005062308007171, 0.008960851203646281, 0.00357811241531566, 0.00127761715678905, |
|
0.0004080302449837189, 0.0001165288322309724, 2.974170493694165e-5, 6.777842526542028e-6, |
|
1.37747950317136e-6, 2.492886181720092e-7, 4.010354350427827e-8, 5.723331748141425e-9, |
|
7.229434249182665e-10, 8.061710142281779e-11, 7.913393099943723e-12, 6.81573661767678e-13, |
|
5.13242671658949e-14, 3.365624762437814e-15, 1.913476326965035e-16, 9.385589781827253e-18, |
|
3.950069964503411e-19, 1.417749517827512e-20, 4.309970276292175e-22, 1.101257519845548e-23, |
|
2.344617755608987e-25, 4.11854415463823e-27, 5.902246763596448e-29, 6.812008916553065e-31, |
|
6.237449498812102e-33, 4.452440579683377e-35, 2.426862352250487e-37, 9.852971481049686e-40, |
|
2.891078872318428e-42, 5.906162708112361e-45, 8.01287459750397e-48, 6.789575424396417e-51, |
|
3.308173010849252e-54, 8.250964876440456e-58, 8.848728128298018e-62, 3.064894889844417e-66, |
|
1.988708229330752e-71, 6.049567152238783e-78 |
|
}; |
|
|
|
|
|
constexpr double wb_x_legendre[] = { |
|
-0.998866404420071, -0.9940319694320907, -0.9853540840480059, -0.9728643851066921, -0.9566109552428079, |
|
-0.9366566189448779, -0.9130785566557919, -0.885967979523613, -0.8554297694299461, -0.8215820708593359, |
|
-0.7845558329003993, -0.7444943022260685, -0.7015524687068223, -0.6558964656854394, -0.6077029271849502, |
|
-0.5571583045146501, -0.5044581449074642, -0.4498063349740388, -0.3934143118975651, -0.3355002454194374, |
|
-0.276288193779532, -0.2160072368760418, -0.1548905899981459, -0.09317470156008614, -0.03109833832718888, |
|
0.03109833832718888, 0.09317470156008614, 0.1548905899981459, 0.2160072368760418, 0.276288193779532, |
|
0.3355002454194374, 0.3934143118975651, 0.4498063349740388, 0.5044581449074642, 0.5571583045146501, |
|
0.6077029271849502, 0.6558964656854394, 0.7015524687068223, 0.7444943022260685, 0.7845558329003993, |
|
0.8215820708593359, 0.8554297694299461, 0.885967979523613, 0.9130785566557919, 0.9366566189448779, |
|
0.9566109552428079, 0.9728643851066921, 0.9853540840480059, 0.9940319694320907, 0.998866404420071 |
|
}; |
|
|
|
|
|
constexpr double wb_w_legendre[] = { |
|
0.002908622553155141, 0.006759799195745401, 0.01059054838365097, 0.01438082276148557, 0.01811556071348939, |
|
0.02178024317012479, 0.02536067357001239, 0.0288429935805352, 0.03221372822357802, 0.03545983561514615, |
|
0.03856875661258768, 0.0415284630901477, 0.04432750433880328, 0.04695505130394843, 0.04940093844946632, |
|
0.05165570306958114, 0.05371062188899625, 0.05555774480621252, 0.05718992564772838, 0.05860084981322245, |
|
0.05978505870426546, 0.06073797084177022, 0.06145589959031666, 0.06193606742068324, 0.06217661665534726, |
|
0.06217661665534726, 0.06193606742068324, 0.06145589959031666, 0.06073797084177022, 0.05978505870426546, |
|
0.05860084981322245, 0.05718992564772838, 0.05555774480621252, 0.05371062188899625, 0.05165570306958114, |
|
0.04940093844946632, 0.04695505130394843, 0.04432750433880328, 0.0415284630901477, 0.03856875661258768, |
|
0.03545983561514615, 0.03221372822357802, 0.0288429935805352, 0.02536067357001239, 0.02178024317012479, |
|
0.01811556071348939, 0.01438082276148557, 0.01059054838365097, 0.006759799195745401, 0.002908622553155141 |
|
}; |
|
|
|
|
|
constexpr double wb_A[] = {0.41037, 0.30833, 6.9952, 18.382, -2.8566, 2.1122}; |
|
|
|
template<bool log_wb> |
|
XSF_HOST_DEVICE inline double wright_bessel_integral(double a, double b, double x) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double eps = |
|
(wb_A[0] * b * std::exp(-0.5 * a) + |
|
std::exp( |
|
wb_A[1] + 1 / (1 + a) * std::log(x) - wb_A[2] * std::exp(-wb_A[3] * a) + |
|
wb_A[4] / (1 + std::exp(wb_A[5] * a)) |
|
)); |
|
|
|
if (a >= 4 && x >= 100) { |
|
eps += 1; |
|
} |
|
|
|
|
|
if (b >= 8) { |
|
|
|
|
|
eps = std::fmax(eps, std::pow(b, -b / (1. - b)) + 0.1 * b); |
|
} |
|
|
|
|
|
eps = std::fmin(eps, 150.); |
|
eps = std::fmax(eps, 3.); |
|
|
|
|
|
|
|
double exp_term = 0; |
|
|
|
double r = wb_x_laguerre[50-1]; |
|
double x_r_a = x * std::pow(r + eps, -a); |
|
exp_term = std::fmax(exp_term, x_r_a * cephes::cospi(a)); |
|
|
|
double x_eps_a = x * std::pow(eps, -a); |
|
|
|
exp_term = std::fmax(exp_term, eps + x_eps_a); |
|
|
|
exp_term = std::fmax(exp_term, -eps + x_eps_a * cephes::cospi(a)); |
|
|
|
double res1 = 0; |
|
double res2 = 0; |
|
|
|
double y; |
|
for (int k = 0; k < 50; k++) { |
|
res1 += wb_w_laguerre[k] * wb_Kmod(-exp_term, eps, a, b, x, wb_x_laguerre[k]); |
|
|
|
y = M_PI * (wb_x_legendre[k] + 1) / 2.0; |
|
res2 += wb_w_legendre[k] * wb_P(-exp_term, eps, a, b, x, y); |
|
} |
|
res1 *= std::exp(-eps); |
|
|
|
res2 *= M_PI / 2.0; |
|
res2 *= std::pow(eps, 1 - b); |
|
|
|
if (!log_wb) { |
|
|
|
return std::exp(exp_term) / M_PI * (res1 + res2); |
|
} else { |
|
|
|
return exp_term + std::log((res1 + res2) / M_PI); |
|
} |
|
} |
|
} |
|
|
|
template<bool log_wb> |
|
XSF_HOST_DEVICE inline double wright_bessel_t(double a, double b, double x) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (std::isnan(a) || std::isnan(b) || std::isnan(x)) { |
|
return std::numeric_limits<double>::quiet_NaN(); |
|
} |
|
if (a < 0 || b < 0 || x < 0) { |
|
set_error("wright_bessel", SF_ERROR_DOMAIN, NULL); |
|
return std::numeric_limits<double>::quiet_NaN(); |
|
} |
|
if (std::isinf(x)) { |
|
if (std::isinf(a) || std::isinf(b)) { |
|
return std::numeric_limits<double>::quiet_NaN(); |
|
} |
|
return std::numeric_limits<double>::infinity(); |
|
} |
|
if (std::isinf(a) || std::isinf(b)) { |
|
return std::numeric_limits<double>::quiet_NaN(); |
|
} |
|
if (a >= detail::rgamma_zero || b >= detail::rgamma_zero) { |
|
set_error("wright_bessel", SF_ERROR_OVERFLOW, NULL); |
|
return std::numeric_limits<double>::quiet_NaN(); |
|
} |
|
if (x == 0) { |
|
|
|
if (!log_wb) { |
|
return cephes::rgamma(b); |
|
} else { |
|
|
|
return -cephes::lgam(b); |
|
} |
|
} |
|
if (a == 0) { |
|
|
|
if (!log_wb) { |
|
return detail::exp_rgamma(x, b); |
|
} else { |
|
|
|
return x - cephes::lgam(b); |
|
} |
|
} |
|
|
|
constexpr double exp_inf = 709.78271289338403; |
|
int order; |
|
if ((a <= 1e-3 && b <= 50 && x <= 9) || (a <= 1e-4 && b <= 70 && x <= 100) || |
|
(a <= 1e-5 && b <= 170 && (x < exp_inf || (log_wb && x <= 1e3)))) { |
|
|
|
|
|
|
|
if (a <= 1e-5) { |
|
if (x <= 1) { |
|
order = 2; |
|
} else if (x <= 10) { |
|
order = 3; |
|
} else if (x <= 100) { |
|
order = 4; |
|
} else { |
|
order = 5; |
|
} |
|
} else if (a <= 1e-4) { |
|
if (x <= 1e-2) { |
|
order = 2; |
|
} else if (x <= 1) { |
|
order = 3; |
|
} else if (x <= 10) { |
|
order = 4; |
|
} else { |
|
order = 5; |
|
} |
|
} else { |
|
if (x <= 1e-5) { |
|
order = 2; |
|
} else if (x <= 1e-1) { |
|
order = 3; |
|
} else if (x <= 1) { |
|
order = 4; |
|
} else { |
|
order = 5; |
|
} |
|
} |
|
|
|
return detail::wb_small_a<log_wb>(a, b, x, order); |
|
} |
|
|
|
if (x <= 1) { |
|
|
|
double res = detail::wb_series(a, b, x, 0, 18); |
|
if (log_wb) res = std::log(res); |
|
return res; |
|
} |
|
if (x <= 2) { |
|
|
|
double res = detail::wb_series(a, b, x, 0, 20); |
|
if (log_wb) res = std::log(res); |
|
return res; |
|
} |
|
if (a >= 5) { |
|
|
|
|
|
if (a >= 10) { |
|
if (x <= 1e11) { |
|
order = 6; |
|
} else { |
|
order = static_cast<int>(std::fmin(std::log10(x) - 5 + b / 10, 30)); |
|
} |
|
} else { |
|
if (x <= 1e4) { |
|
order = 6; |
|
} else if (x <= 1e8) { |
|
order = static_cast<int>(2 * std::log10(x)); |
|
} else if (x <= 1e10) { |
|
order = static_cast<int>(4 * std::log10(x) - 16); |
|
} else { |
|
order = static_cast<int>(std::fmin(6 * std::log10(x) - 36, 100)); |
|
} |
|
} |
|
return detail::wb_large_a<log_wb>(a, b, x, order); |
|
} |
|
if (std::pow(a * x, 1 / (1. + a)) >= 14 + b * b / (2 * (1 + a))) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
return detail::wb_asymptotic<log_wb>(a, b, x); |
|
} |
|
if (0.5 <= a && a <= 1.8 && 100 <= b && 1e5 <= x) { |
|
|
|
|
|
return std::numeric_limits<double>::quiet_NaN(); |
|
} |
|
return detail::wright_bessel_integral<log_wb>(a, b, x); |
|
} |
|
|
|
|
|
XSF_HOST_DEVICE inline double wright_bessel(double a, double b, double x) { |
|
return wright_bessel_t<false>(a, b, x); |
|
} |
|
|
|
XSF_HOST_DEVICE inline float wright_bessel(float a, float b, float x) { |
|
return wright_bessel(static_cast<double>(a), static_cast<double>(b), static_cast<double>(x)); |
|
} |
|
|
|
XSF_HOST_DEVICE inline double log_wright_bessel(double a, double b, double x) { |
|
return wright_bessel_t<true>(a, b, x); |
|
} |
|
|
|
XSF_HOST_DEVICE inline float log_wright_bessel(float a, float b, float x) { |
|
return log_wright_bessel(static_cast<double>(a), static_cast<double>(b), static_cast<double>(x)); |
|
} |
|
|
|
} |
|
|