17 #ifndef KOKKOS_MATHEMATICAL_SPECIAL_FUNCTIONS_HPP
18 #define KOKKOS_MATHEMATICAL_SPECIAL_FUNCTIONS_HPP
19 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
20 #define KOKKOS_IMPL_PUBLIC_INCLUDE
21 #define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_MATHSPECFUNCTIONS
24 #include <Kokkos_Macros.hpp>
27 #include <type_traits>
28 #include <Kokkos_MathematicalConstants.hpp>
29 #include <Kokkos_MathematicalFunctions.hpp>
30 #include <Kokkos_NumericTraits.hpp>
31 #include <Kokkos_Complex.hpp>
34 namespace Experimental {
37 template <
class RealType>
38 KOKKOS_INLINE_FUNCTION RealType expint1(RealType x) {
45 using Kokkos::Experimental::epsilon;
46 using Kokkos::Experimental::infinity;
51 e1 = -infinity<RealType>::value;
52 }
else if (x == 0.0) {
53 e1 = infinity<RealType>::value;
54 }
else if (x <= 1.0) {
57 for (
int k = 1; k <= 25; k++) {
58 RealType k_real =
static_cast<RealType
>(k);
59 r = -r * k_real * x / pow(k_real + 1.0, 2.0);
61 if (fabs(r) <= fabs(e1) * epsilon<RealType>::value)
break;
63 e1 = -0.5772156649015328 - log(x) + x * e1;
65 int m = 20 +
static_cast<int>(80.0 / x);
67 for (
int k = m; k >= 1; k--) {
68 RealType k_real =
static_cast<RealType
>(k);
69 t0 = k_real / (1.0 + k_real / (x + t0));
71 e1 = exp(-x) * (1.0 / (x + t0));
77 template <
class RealType>
99 using Kokkos::Experimental::epsilon_v;
100 using Kokkos::Experimental::infinity_v;
101 using Kokkos::numbers::pi_v;
105 constexpr
auto inf = infinity_v<RealType>;
106 constexpr
auto tol = epsilon_v<RealType>;
108 const RealType fnorm = 1.12837916709551;
109 const RealType gnorm = 0.564189583547756;
110 const RealType eh = 0.606530659712633;
111 const RealType ef = 0.778800783071405;
113 constexpr
auto pi = pi_v<RealType>;
117 RealType az = Kokkos::abs(z);
119 CmplxType cz = z * z;
120 CmplxType accum = CmplxType(1.0, 0.0);
121 CmplxType term = accum;
123 for (
int i = 1; i <= 35; i++) {
124 term = term * cz / ak;
125 accum = accum + term;
126 if (Kokkos::abs(term) <= tol)
break;
130 RealType er = cz.real();
131 RealType ei = cz.imag();
132 accum = accum * z * fnorm;
133 cz = exp(er) * CmplxType(cos(ei), sin(ei));
138 if (z.real() < 0.0) zp = -z;
139 CmplxType cz = zp * zp;
140 RealType xp = zp.real();
141 RealType yp = zp.imag();
144 int n =
static_cast<int>(100.0 / az + 5.0);
147 for (
int i = 1; i <= n; i++) {
148 RealType fnh = fn - 0.5;
149 term = cz + (fnh * term) / (fn + term);
152 if (Kokkos::abs(cz) > 670.0)
return CmplxType(inf, inf);
154 RealType er = cz.real();
155 RealType ei = cz.imag();
156 cz = exp(er) * CmplxType(cos(ei), sin(ei));
157 CmplxType accum = zp * gnorm * cz;
158 cans = 1.0 - accum / term;
159 if (z.real() < 0.0) cans = -cans;
166 RealType x2 = xp * xp;
167 RealType fx2 = 4.0 * x2;
168 RealType tx = xp + xp;
169 RealType xy = xp * yp;
170 RealType sxyh = sin(xy);
171 RealType sxy = sin(xy + xy);
172 RealType cxy = cos(xy + xy);
175 RealType ey = exp(yp);
180 for (
int i = 1; i <= 50; i++) {
181 RealType ren = 1.0 / en;
182 RealType csh = en + ren;
183 RealType tm = xp * csh;
184 RealType ssh = en - ren;
185 RealType tmp = fnh * ssh;
186 RealType rn = tx - tm * cxy + tmp * sxy;
187 RealType ain = tm * sxy + tmp * cxy;
188 RealType cf = un / (vn + fx2);
193 if ((fabs(rn) + fabs(ain)) < tol * (fabs(s1) + fabs(s2)))
break;
197 vn = vn + fn + fn + 1.0;
206 s1 = s1 + sxyh * sxyh / xp;
213 for (
int i = 1; i <= 17; i++) {
216 if (tm <= tol)
break;
219 RealType ex = exp(-x2);
220 w = w * xp * fnorm * ex;
221 RealType cf = ex / pi;
224 cans = CmplxType(s1, s2);
225 if (z.real() < 0.0) cans = -cans;
229 CmplxType rcz = 0.5 / cz;
230 CmplxType accum = CmplxType(1.0, 0.0);
231 CmplxType term = accum;
233 for (
int i = 1; i <= 35; i++) {
234 term = -term * ak * rcz;
235 accum = accum + term;
236 if (Kokkos::abs(term) / Kokkos::abs(accum) <= tol)
break;
239 accum = accum * gnorm / zp;
241 RealType er = cz.real();
242 if (fabs(er) > 670.0)
return CmplxType(inf, inf);
243 RealType ei = cz.imag();
244 cz = exp(er) * CmplxType(cos(ei), sin(ei));
245 cans = 1.0 - accum * cz;
246 if (z.real() < 0.0) cans = -cans;
255 template <
class RealType>
278 using Kokkos::Experimental::epsilon_v;
279 using Kokkos::Experimental::infinity_v;
280 using Kokkos::numbers::inv_sqrtpi_v;
281 using Kokkos::numbers::pi_v;
285 constexpr
auto inf = infinity_v<RealType>;
286 constexpr
auto tol = epsilon_v<RealType>;
288 const RealType fnorm = 1.12837916709551;
289 constexpr
auto gnorm = inv_sqrtpi_v<RealType>;
290 const RealType eh = 0.606530659712633;
291 const RealType ef = 0.778800783071405;
293 constexpr
auto pi = pi_v<RealType>;
297 if ((isinf(z.
real())) && (z.
real() > 0)) {
298 cans = CmplxType(0.0, 0.0);
301 if ((isinf(z.
real())) && (z.
real() < 0)) {
302 cans = CmplxType(inf, inf);
306 RealType az = Kokkos::abs(z);
308 CmplxType cz = z * z;
309 CmplxType accum = CmplxType(1.0, 0.0);
310 CmplxType term = accum;
312 for (
int i = 1; i <= 35; i++) {
313 term = term * cz / ak;
314 accum = accum + term;
315 if (Kokkos::abs(term) <= tol)
break;
319 RealType er = cz.real();
320 RealType ei = cz.imag();
321 accum = accum * z * fnorm;
322 cz = exp(er) * CmplxType(cos(ei), sin(ei));
323 cans = 1.0 / cz - accum;
327 if (z.real() < 0.0) zp = -z;
328 CmplxType cz = zp * zp;
329 RealType xp = zp.real();
330 RealType yp = zp.imag();
333 int n =
static_cast<int>(100.0 / az + 5.0);
336 for (
int i = 1; i <= n; i++) {
337 RealType fnh = fn - 0.5;
338 term = cz + (fnh * term) / (fn + term);
341 cans = zp * gnorm / term;
342 if (z.real() >= 0.0)
return cans;
343 if (Kokkos::abs(cz) > 670.0)
return CmplxType(inf, inf);
346 RealType er = cz.real();
347 RealType ei = cz.imag();
348 cz = exp(er) * CmplxType(cos(ei), sin(ei));
350 cans = cz + cz - cans;
357 RealType x2 = xp * xp;
358 RealType fx2 = 4.0 * x2;
359 RealType tx = xp + xp;
360 RealType xy = xp * yp;
361 RealType sxyh = sin(xy);
362 RealType sxy = sin(xy + xy);
363 RealType cxy = cos(xy + xy);
366 RealType ey = exp(yp);
371 for (
int i = 1; i <= 50; i++) {
372 RealType ren = 1.0 / en;
373 RealType csh = en + ren;
374 RealType tm = xp * csh;
375 RealType ssh = en - ren;
376 RealType tmp = fnh * ssh;
377 RealType rn = tx - tm * cxy + tmp * sxy;
378 RealType ain = tm * sxy + tmp * cxy;
379 RealType cf = un / (vn + fx2);
384 if ((fabs(rn) + fabs(ain)) < tol * (fabs(s1) + fabs(s2)))
break;
388 vn = vn + fn + fn + 1.0;
397 s1 = s1 + sxyh * sxyh / xp;
404 for (
int i = 1; i <= 17; i++) {
407 if (tm <= tol)
break;
410 RealType ex = exp(-x2);
411 w = w * xp * fnorm * ex;
412 CmplxType rcz = CmplxType(cxy, sxy);
413 RealType y2 = yp * yp;
414 cz = exp(x2 - y2) * rcz;
415 rcz = exp(-y2) * rcz;
417 cans = cz * (1.0 - w) - rcz * CmplxType(s1, s2) / pi;
419 cans = cz * (1.0 + w) + rcz * CmplxType(s1, s2) / pi;
423 CmplxType rcz = 0.5 / cz;
424 CmplxType accum = CmplxType(1.0, 0.0);
425 CmplxType term = accum;
427 for (
int i = 1; i <= 35; i++) {
428 term = -term * ak * rcz;
429 accum = accum + term;
430 if (Kokkos::abs(term) / Kokkos::abs(accum) <= tol)
break;
433 accum = accum * gnorm / zp;
434 if (z.real() < 0.0) accum = -accum;
444 template <
class RealType>
445 KOKKOS_INLINE_FUNCTION RealType erfcx(RealType x) {
449 CmplxType zin = CmplxType(x, 0.0);
450 CmplxType zout = erfcx(zin);
456 template <
class CmplxType,
class RealType,
class IntType>
457 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_j0(
const CmplxType& z,
458 const RealType& joint_val = 25,
459 const IntType& bw_start = 70) {
470 using Kokkos::numbers::pi_v;
473 constexpr
auto pi = pi_v<RealType>;
474 const RealType a[12] = {
475 -0.703125e-01, 0.112152099609375e+00, -0.5725014209747314e+00,
476 0.6074042001273483e+01, -0.1100171402692467e+03, 0.3038090510922384e+04,
477 -0.1188384262567832e+06, 0.6252951493434797e+07, -0.4259392165047669e+09,
478 0.3646840080706556e+11, -0.3833534661393944e+13, 0.4854014686852901e+15};
479 const RealType b[12] = {0.732421875e-01, -0.2271080017089844e+00,
480 0.1727727502584457e+01, -0.2438052969955606e+02,
481 0.5513358961220206e+03, -0.1825775547429318e+05,
482 0.8328593040162893e+06, -0.5006958953198893e+08,
483 0.3836255180230433e+10, -0.3649010818849833e+12,
484 0.4218971570284096e+14, -0.5827244631566907e+16};
486 RealType r2p = 2.0 / pi;
487 RealType a0 = Kokkos::abs(z);
488 RealType y0 = fabs(z.imag());
492 cbj0 = CmplxType(1.0, 0.0);
494 if (z.real() < 0.0) z1 = -z;
495 if (a0 <= joint_val) {
497 CmplxType cbs = CmplxType(0.0, 0.0);
498 CmplxType csu = CmplxType(0.0, 0.0);
499 CmplxType csv = CmplxType(0.0, 0.0);
500 CmplxType cf2 = CmplxType(0.0, 0.0);
501 CmplxType cf1 = CmplxType(1e-100, 0.0);
503 for (
int k = bw_start; k >= 0; k--) {
505 cf = 2.0 * (k + 1.0) / z * cf1 - cf2;
506 RealType tmp_exponent =
static_cast<RealType
>(k / 2);
507 if (k == 0) cbj0 = cf;
508 if ((k == 2 * (k / 2)) && (k != 0)) {
510 cbs = cbs + 2.0 * cf;
512 cbs = cbs + pow(-1.0, tmp_exponent) * 2.0 * cf;
513 csu = csu + pow(-1.0, tmp_exponent) * cf / k;
515 csv = csv + pow(-1.0, tmp_exponent) * k / (k * k - 1.0) * cf;
523 cs0 = (cbs + cf) / Kokkos::cos(z);
527 CmplxType ct1 = z1 - 0.25 * pi;
528 CmplxType cp0 = CmplxType(1.0, 0.0);
529 for (
int k = 1; k <= 12; k++) {
530 cp0 = cp0 + a[k - 1] * Kokkos::pow(z1, -2.0 * k);
532 CmplxType cq0 = -0.125 / z1;
533 for (
int k = 1; k <= 12; k++) {
534 cq0 = cq0 + b[k - 1] * Kokkos::pow(z1, -2.0 * k - 1);
536 CmplxType cu = Kokkos::sqrt(r2p / z1);
537 cbj0 = cu * (cp0 * Kokkos::cos(ct1) - cq0 * Kokkos::sin(ct1));
545 template <
class CmplxType,
class RealType,
class IntType>
546 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_y0(
const CmplxType& z,
547 const RealType& joint_val = 25,
548 const IntType& bw_start = 70) {
559 using Kokkos::Experimental::infinity_v;
560 using Kokkos::numbers::egamma_v;
561 using Kokkos::numbers::pi_v;
563 constexpr
auto inf = infinity_v<RealType>;
565 CmplxType cby0, cbj0;
566 constexpr
auto pi = pi_v<RealType>;
567 constexpr
auto el = egamma_v<RealType>;
568 const RealType a[12] = {
569 -0.703125e-01, 0.112152099609375e+00, -0.5725014209747314e+00,
570 0.6074042001273483e+01, -0.1100171402692467e+03, 0.3038090510922384e+04,
571 -0.1188384262567832e+06, 0.6252951493434797e+07, -0.4259392165047669e+09,
572 0.3646840080706556e+11, -0.3833534661393944e+13, 0.4854014686852901e+15};
573 const RealType b[12] = {0.732421875e-01, -0.2271080017089844e+00,
574 0.1727727502584457e+01, -0.2438052969955606e+02,
575 0.5513358961220206e+03, -0.1825775547429318e+05,
576 0.8328593040162893e+06, -0.5006958953198893e+08,
577 0.3836255180230433e+10, -0.3649010818849833e+12,
578 0.4218971570284096e+14, -0.5827244631566907e+16};
580 RealType r2p = 2.0 / pi;
581 RealType a0 = Kokkos::abs(z);
582 RealType y0 = fabs(z.imag());
583 CmplxType ci = CmplxType(0.0, 1.0);
587 cby0 = -CmplxType(inf, 0.0);
589 if (z.real() < 0.0) z1 = -z;
590 if (a0 <= joint_val) {
592 CmplxType cbs = CmplxType(0.0, 0.0);
593 CmplxType csu = CmplxType(0.0, 0.0);
594 CmplxType csv = CmplxType(0.0, 0.0);
595 CmplxType cf2 = CmplxType(0.0, 0.0);
596 CmplxType cf1 = CmplxType(1e-100, 0.0);
597 CmplxType cf, cs0, ce;
598 for (
int k = bw_start; k >= 0; k--) {
600 cf = 2.0 * (k + 1.0) / z * cf1 - cf2;
601 RealType tmp_exponent =
static_cast<RealType
>(k / 2);
602 if (k == 0) cbj0 = cf;
603 if ((k == 2 * (k / 2)) && (k != 0)) {
605 cbs = cbs + 2.0 * cf;
607 cbs = cbs + pow(-1.0, tmp_exponent) * 2.0 * cf;
608 csu = csu + pow(-1.0, tmp_exponent) * cf / k;
610 csv = csv + pow(-1.0, tmp_exponent) * k / (k * k - 1.0) * cf;
618 cs0 = (cbs + cf) / Kokkos::cos(z);
620 ce = Kokkos::log(z / 2.0) + el;
621 cby0 = r2p * (ce * cbj0 - 4.0 * csu / cs0);
624 CmplxType ct1 = z1 - 0.25 * pi;
625 CmplxType cp0 = CmplxType(1.0, 0.0);
626 for (
int k = 1; k <= 12; k++) {
627 cp0 = cp0 + a[k - 1] * Kokkos::pow(z1, -2.0 * k);
629 CmplxType cq0 = -0.125 / z1;
630 for (
int k = 1; k <= 12; k++) {
631 cq0 = cq0 + b[k - 1] * Kokkos::pow(z1, -2.0 * k - 1);
633 CmplxType cu = Kokkos::sqrt(r2p / z1);
634 cbj0 = cu * (cp0 * Kokkos::cos(ct1) - cq0 * Kokkos::sin(ct1));
635 cby0 = cu * (cp0 * Kokkos::sin(ct1) + cq0 * Kokkos::cos(ct1));
637 if (z.real() < 0.0) {
638 if (z.imag() < 0.0) cby0 = cby0 - 2.0 * ci * cbj0;
639 if (z.imag() >= 0.0) cby0 = cby0 + 2.0 * ci * cbj0;
648 template <
class CmplxType,
class RealType,
class IntType>
649 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_j1(
const CmplxType& z,
650 const RealType& joint_val = 25,
651 const IntType& bw_start = 70) {
662 using Kokkos::numbers::pi_v;
665 constexpr
auto pi = pi_v<RealType>;
666 const RealType a1[12] = {0.1171875e+00, -0.144195556640625e+00,
667 0.6765925884246826e+00, -0.6883914268109947e+01,
668 0.1215978918765359e+03, -0.3302272294480852e+04,
669 0.1276412726461746e+06, -0.6656367718817688e+07,
670 0.4502786003050393e+09, -0.3833857520742790e+11,
671 0.4011838599133198e+13, -0.5060568503314727e+15};
672 const RealType b1[12] = {
673 -0.1025390625e+00, 0.2775764465332031e+00, -0.1993531733751297e+01,
674 0.2724882731126854e+02, -0.6038440767050702e+03, 0.1971837591223663e+05,
675 -0.8902978767070678e+06, 0.5310411010968522e+08, -0.4043620325107754e+10,
676 0.3827011346598605e+12, -0.4406481417852278e+14, 0.6065091351222699e+16};
678 RealType r2p = 2.0 / pi;
679 RealType a0 = Kokkos::abs(z);
680 RealType y0 = fabs(z.imag());
684 cbj1 = CmplxType(0.0, 0.0);
686 if (z.real() < 0.0) z1 = -z;
687 if (a0 <= joint_val) {
689 CmplxType cbs = CmplxType(0.0, 0.0);
690 CmplxType csu = CmplxType(0.0, 0.0);
691 CmplxType csv = CmplxType(0.0, 0.0);
692 CmplxType cf2 = CmplxType(0.0, 0.0);
693 CmplxType cf1 = CmplxType(1e-100, 0.0);
695 for (
int k = bw_start; k >= 0; k--) {
697 cf = 2.0 * (k + 1.0) / z * cf1 - cf2;
698 RealType tmp_exponent =
static_cast<RealType
>(k / 2);
699 if (k == 1) cbj1 = cf;
700 if ((k == 2 * (k / 2)) && (k != 0)) {
702 cbs = cbs + 2.0 * cf;
704 cbs = cbs + pow(-1.0, tmp_exponent) * 2.0 * cf;
705 csu = csu + pow(-1.0, tmp_exponent) * cf / k;
707 csv = csv + pow(-1.0, tmp_exponent) * k / (k * k - 1.0) * cf;
715 cs0 = (cbs + cf) / Kokkos::cos(z);
719 CmplxType ct2 = z1 - 0.75 * pi;
720 CmplxType cp1 = CmplxType(1.0, 0.0);
721 for (
int k = 1; k <= 12; k++) {
722 cp1 = cp1 + a1[k - 1] * Kokkos::pow(z1, -2.0 * k);
724 CmplxType cq1 = 0.375 / z1;
725 for (
int k = 1; k <= 12; k++) {
726 cq1 = cq1 + b1[k - 1] * Kokkos::pow(z1, -2.0 * k - 1);
728 CmplxType cu = Kokkos::sqrt(r2p / z1);
729 cbj1 = cu * (cp1 * Kokkos::cos(ct2) - cq1 * Kokkos::sin(ct2));
741 template <
class CmplxType,
class RealType,
class IntType>
742 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_y1(
const CmplxType& z,
743 const RealType& joint_val = 25,
744 const IntType& bw_start = 70) {
755 using Kokkos::Experimental::infinity_v;
756 using Kokkos::numbers::egamma_v;
757 using Kokkos::numbers::pi_v;
759 constexpr
auto inf = infinity_v<RealType>;
761 CmplxType cby1, cbj0, cbj1, cby0;
762 constexpr
auto pi = pi_v<RealType>;
763 constexpr
auto el = egamma_v<RealType>;
764 const RealType a1[12] = {0.1171875e+00, -0.144195556640625e+00,
765 0.6765925884246826e+00, -0.6883914268109947e+01,
766 0.1215978918765359e+03, -0.3302272294480852e+04,
767 0.1276412726461746e+06, -0.6656367718817688e+07,
768 0.4502786003050393e+09, -0.3833857520742790e+11,
769 0.4011838599133198e+13, -0.5060568503314727e+15};
770 const RealType b1[12] = {
771 -0.1025390625e+00, 0.2775764465332031e+00, -0.1993531733751297e+01,
772 0.2724882731126854e+02, -0.6038440767050702e+03, 0.1971837591223663e+05,
773 -0.8902978767070678e+06, 0.5310411010968522e+08, -0.4043620325107754e+10,
774 0.3827011346598605e+12, -0.4406481417852278e+14, 0.6065091351222699e+16};
776 RealType r2p = 2.0 / pi;
777 RealType a0 = Kokkos::abs(z);
778 RealType y0 = fabs(z.imag());
779 CmplxType ci = CmplxType(0.0, 1.0);
783 cby1 = -CmplxType(inf, 0.0);
785 if (z.real() < 0.0) z1 = -z;
786 if (a0 <= joint_val) {
788 CmplxType cbs = CmplxType(0.0, 0.0);
789 CmplxType csu = CmplxType(0.0, 0.0);
790 CmplxType csv = CmplxType(0.0, 0.0);
791 CmplxType cf2 = CmplxType(0.0, 0.0);
792 CmplxType cf1 = CmplxType(1e-100, 0.0);
793 CmplxType cf, cs0, ce;
794 for (
int k = bw_start; k >= 0; k--) {
796 cf = 2.0 * (k + 1.0) / z * cf1 - cf2;
797 RealType tmp_exponent =
static_cast<RealType
>(k / 2);
798 if (k == 1) cbj1 = cf;
799 if (k == 0) cbj0 = cf;
800 if ((k == 2 * (k / 2)) && (k != 0)) {
802 cbs = cbs + 2.0 * cf;
804 cbs = cbs + pow(-1.0, tmp_exponent) * 2.0 * cf;
805 csu = csu + pow(-1.0, tmp_exponent) * cf / k;
807 csv = csv + pow(-1.0, tmp_exponent) * k / (k * k - 1.0) * cf;
815 cs0 = (cbs + cf) / Kokkos::cos(z);
817 ce = Kokkos::log(z / 2.0) + el;
818 cby0 = r2p * (ce * cbj0 - 4.0 * csu / cs0);
820 cby1 = (cbj1 * cby0 - 2.0 / (pi * z)) / cbj0;
823 CmplxType ct2 = z1 - 0.75 * pi;
824 CmplxType cp1 = CmplxType(1.0, 0.0);
825 for (
int k = 1; k <= 12; k++) {
826 cp1 = cp1 + a1[k - 1] * Kokkos::pow(z1, -2.0 * k);
828 CmplxType cq1 = 0.375 / z1;
829 for (
int k = 1; k <= 12; k++) {
830 cq1 = cq1 + b1[k - 1] * Kokkos::pow(z1, -2.0 * k - 1);
832 CmplxType cu = Kokkos::sqrt(r2p / z1);
833 cbj1 = cu * (cp1 * Kokkos::cos(ct2) - cq1 * Kokkos::sin(ct2));
834 cby1 = cu * (cp1 * Kokkos::sin(ct2) + cq1 * Kokkos::cos(ct2));
836 if (z.real() < 0.0) {
837 if (z.imag() < 0.0) cby1 = -(cby1 - 2.0 * ci * cbj1);
838 if (z.imag() >= 0.0) cby1 = -(cby1 + 2.0 * ci * cbj1);
847 template <
class CmplxType,
class RealType,
class IntType>
848 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_i0(
const CmplxType& z,
849 const RealType& joint_val = 18,
850 const IntType& n_terms = 50) {
860 CmplxType cbi0(1.0, 0.0);
861 RealType a0 = Kokkos::abs(z);
865 if (z.real() < 0.0) z1 = -z;
866 if (a0 <= joint_val) {
868 CmplxType cr = CmplxType(1.0e+00, 0.0e+00);
869 CmplxType z2 = z * z;
870 for (
int k = 1; k < n_terms; ++k) {
871 cr = RealType(.25) * cr * z2 / CmplxType(k * k);
873 if (Kokkos::abs(cr / cbi0) < RealType(1.e-15))
continue;
877 const RealType a[12] = {0.125,
890 for (
int k = 1; k <= 12; k++) {
891 cbi0 += a[k - 1] * Kokkos::pow(z1, -k);
893 cbi0 *= Kokkos::exp(z1) /
894 Kokkos::sqrt(2.0 * Kokkos::numbers::pi_v<RealType> * z1);
902 template <
class CmplxType,
class RealType,
class IntType>
903 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_k0(
const CmplxType& z,
904 const RealType& joint_val = 9,
905 const IntType& bw_start = 30) {
917 using Kokkos::Experimental::infinity_v;
918 using Kokkos::numbers::egamma_v;
919 using Kokkos::numbers::pi_v;
921 constexpr
auto inf = infinity_v<RealType>;
923 CmplxType cbk0, cbi0;
924 constexpr
auto pi = pi_v<RealType>;
925 constexpr
auto el = egamma_v<RealType>;
927 RealType a0 = Kokkos::abs(z);
928 CmplxType ci = CmplxType(0.0, 1.0);
932 cbk0 = CmplxType(inf, 0.0);
934 if (z.real() < 0.0) z1 = -z;
935 if (a0 <= joint_val) {
937 CmplxType cbs = CmplxType(0.0, 0.0);
938 CmplxType csk0 = CmplxType(0.0, 0.0);
939 CmplxType cf0 = CmplxType(0.0, 0.0);
940 CmplxType cf1 = CmplxType(1e-100, 0.0);
942 for (
int k = bw_start; k >= 0; k--) {
944 cf = 2.0 * (k + 1.0) * cf1 / z1 + cf0;
945 if (k == 0) cbi0 = cf;
946 if ((k == 2 * (k / 2)) && (k != 0)) {
947 csk0 = csk0 + 4.0 * cf /
static_cast<RealType
>(k);
949 cbs = cbs + 2.0 * cf;
953 cs0 = Kokkos::exp(z1) / (cbs - cf);
955 cbk0 = -(Kokkos::log(0.5 * z1) + el) * cbi0 + cs0 * csk0;
958 CmplxType ca0 = Kokkos::sqrt(pi / (2.0 * z1)) * Kokkos::exp(-z1);
959 CmplxType cbkl = CmplxType(1.0, 0.0);
960 CmplxType cr = CmplxType(1.0, 0.0);
961 for (
int k = 1; k <= 30; k++) {
962 cr = 0.125 * cr * (0.0 - pow(2.0 * k - 1.0, 2.0)) / (k * z1);
967 if (z.real() < 0.0) {
969 cbk0 = cbk0 + ci * pi * cyl_bessel_i0<CmplxType, RealType, IntType>(z);
971 cbk0 = cbk0 - ci * pi * cyl_bessel_i0<CmplxType, RealType, IntType>(z);
979 template <
class CmplxType,
class RealType,
class IntType>
980 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_i1(
const CmplxType& z,
981 const RealType& joint_val = 25,
982 const IntType& bw_start = 70) {
991 using Kokkos::numbers::pi_v;
994 constexpr
auto pi = pi_v<RealType>;
995 const RealType b[12] = {-0.375,
1000 -6.7659258842468e-1,
1006 -3.3022722944809e3};
1008 RealType a0 = Kokkos::abs(z);
1012 cbi1 = CmplxType(0.0, 0.0);
1014 if (z.real() < 0.0) z1 = -z;
1015 if (a0 <= joint_val) {
1017 CmplxType cbs = CmplxType(0.0, 0.0);
1019 CmplxType cf0 = CmplxType(0.0, 0.0);
1020 CmplxType cf1 = CmplxType(1e-100, 0.0);
1022 for (
int k = bw_start; k >= 0; k--) {
1024 cf = 2.0 * (k + 1.0) * cf1 / z1 + cf0;
1025 if (k == 1) cbi1 = cf;
1029 cbs = cbs + 2.0 * cf;
1033 cs0 = Kokkos::exp(z1) / (cbs - cf);
1037 CmplxType ca = Kokkos::exp(z1) / Kokkos::sqrt(2.0 * pi * z1);
1038 cbi1 = CmplxType(1.0, 0.0);
1039 CmplxType zr = 1.0 / z1;
1040 for (
int k = 1; k <= 12; k++) {
1041 cbi1 = cbi1 + b[k - 1] * Kokkos::pow(zr, 1.0 * k);
1045 if (z.real() < 0.0) {
1054 template <
class CmplxType,
class RealType,
class IntType>
1055 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_k1(
const CmplxType& z,
1056 const RealType& joint_val = 9,
1057 const IntType& bw_start = 30) {
1067 using Kokkos::Experimental::infinity_v;
1068 using Kokkos::numbers::egamma_v;
1069 using Kokkos::numbers::pi_v;
1071 constexpr
auto inf = infinity_v<RealType>;
1073 CmplxType cbk0, cbi0, cbk1, cbi1;
1074 constexpr
auto pi = pi_v<RealType>;
1075 constexpr
auto el = egamma_v<RealType>;
1077 RealType a0 = Kokkos::abs(z);
1078 CmplxType ci = CmplxType(0.0, 1.0);
1082 cbk1 = CmplxType(inf, 0.0);
1084 if (z.real() < 0.0) z1 = -z;
1085 if (a0 <= joint_val) {
1087 CmplxType cbs = CmplxType(0.0, 0.0);
1088 CmplxType csk0 = CmplxType(0.0, 0.0);
1089 CmplxType cf0 = CmplxType(0.0, 0.0);
1090 CmplxType cf1 = CmplxType(1e-100, 0.0);
1092 for (
int k = bw_start; k >= 0; k--) {
1094 cf = 2.0 * (k + 1.0) * cf1 / z1 + cf0;
1095 if (k == 1) cbi1 = cf;
1096 if (k == 0) cbi0 = cf;
1097 if ((k == 2 * (k / 2)) && (k != 0)) {
1098 csk0 = csk0 + 4.0 * cf /
static_cast<RealType
>(k);
1100 cbs = cbs + 2.0 * cf;
1104 cs0 = Kokkos::exp(z1) / (cbs - cf);
1107 cbk0 = -(Kokkos::log(0.5 * z1) + el) * cbi0 + cs0 * csk0;
1108 cbk1 = (1.0 / z1 - cbi1 * cbk0) / cbi0;
1111 CmplxType ca0 = Kokkos::sqrt(pi / (2.0 * z1)) * Kokkos::exp(-z1);
1112 CmplxType cbkl = CmplxType(1.0, 0.0);
1113 CmplxType cr = CmplxType(1.0, 0.0);
1114 for (
int k = 1; k <= 30; k++) {
1115 cr = 0.125 * cr * (4.0 - pow(2.0 * k - 1.0, 2.0)) / (k * z1);
1120 if (z.real() < 0.0) {
1122 cbk1 = -cbk1 - ci * pi * cyl_bessel_i1<CmplxType, RealType, IntType>(z);
1123 if (z.imag() >= 0.0)
1124 cbk1 = -cbk1 + ci * pi * cyl_bessel_i1<CmplxType, RealType, IntType>(z);
1132 template <
class CmplxType>
1133 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_h10(
const CmplxType& z) {
1137 using RealType =
typename CmplxType::value_type;
1138 using Kokkos::Experimental::infinity_v;
1139 using Kokkos::numbers::pi_v;
1141 constexpr
auto inf = infinity_v<RealType>;
1143 CmplxType ch10, cbk0, cbj0, cby0;
1144 constexpr
auto pi = pi_v<RealType>;
1145 CmplxType ci = CmplxType(0.0, 1.0);
1147 if ((z.real() == 0.0) && (z.imag() == 0.0)) {
1148 ch10 = CmplxType(1.0, -inf);
1149 }
else if (z.imag() <= 0.0) {
1150 cbj0 = cyl_bessel_j0<CmplxType, RealType, int>(z);
1151 cby0 = cyl_bessel_y0<CmplxType, RealType, int>(z);
1152 ch10 = cbj0 + ci * cby0;
1154 cbk0 = cyl_bessel_k0<CmplxType, RealType, int>(-ci * z, 18.0, 70);
1155 ch10 = 2.0 / (pi * ci) * cbk0;
1163 template <
class CmplxType>
1164 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_h11(
const CmplxType& z) {
1168 using RealType =
typename CmplxType::value_type;
1169 using Kokkos::Experimental::infinity_v;
1170 using Kokkos::numbers::pi_v;
1172 constexpr
auto inf = infinity_v<RealType>;
1174 CmplxType ch11, cbk1, cbj1, cby1;
1175 constexpr
auto pi = pi_v<RealType>;
1176 CmplxType ci = CmplxType(0.0, 1.0);
1178 if ((z.real() == 0.0) && (z.imag() == 0.0)) {
1179 ch11 = CmplxType(0.0, -inf);
1180 }
else if (z.imag() <= 0.0) {
1181 cbj1 = cyl_bessel_j1<CmplxType, RealType, int>(z);
1182 cby1 = cyl_bessel_y1<CmplxType, RealType, int>(z);
1183 ch11 = cbj1 + ci * cby1;
1185 cbk1 = cyl_bessel_k1<CmplxType, RealType, int>(-ci * z, 18.0, 70);
1186 ch11 = -2.0 / pi * cbk1;
1194 template <
class CmplxType>
1195 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_h20(
const CmplxType& z) {
1199 using RealType =
typename CmplxType::value_type;
1200 using Kokkos::Experimental::infinity_v;
1201 using Kokkos::numbers::pi_v;
1203 constexpr
auto inf = infinity_v<RealType>;
1205 CmplxType ch20, cbk0, cbj0, cby0;
1206 constexpr
auto pi = pi_v<RealType>;
1207 CmplxType ci = CmplxType(0.0, 1.0);
1209 if ((z.real() == 0.0) && (z.imag() == 0.0)) {
1210 ch20 = CmplxType(1.0, inf);
1211 }
else if (z.imag() >= 0.0) {
1212 cbj0 = cyl_bessel_j0<CmplxType, RealType, int>(z);
1213 cby0 = cyl_bessel_y0<CmplxType, RealType, int>(z);
1214 ch20 = cbj0 - ci * cby0;
1216 cbk0 = cyl_bessel_k0<CmplxType, RealType, int>(ci * z, 18.0, 70);
1217 ch20 = 2.0 / pi * ci * cbk0;
1225 template <
class CmplxType>
1226 KOKKOS_INLINE_FUNCTION CmplxType cyl_bessel_h21(
const CmplxType& z) {
1230 using RealType =
typename CmplxType::value_type;
1231 using Kokkos::Experimental::infinity_v;
1232 using Kokkos::numbers::pi_v;
1234 constexpr
auto inf = infinity_v<RealType>;
1236 CmplxType ch21, cbk1, cbj1, cby1;
1237 constexpr
auto pi = pi_v<RealType>;
1238 CmplxType ci = CmplxType(0.0, 1.0);
1240 if ((z.real() == 0.0) && (z.imag() == 0.0)) {
1241 ch21 = CmplxType(0.0, inf);
1242 }
else if (z.imag() >= 0.0) {
1243 cbj1 = cyl_bessel_j1<CmplxType, RealType, int>(z);
1244 cby1 = cyl_bessel_y1<CmplxType, RealType, int>(z);
1245 ch21 = cbj1 - ci * cby1;
1247 cbk1 = cyl_bessel_k1<CmplxType, RealType, int>(ci * z, 18.0, 70);
1248 ch21 = -2.0 / pi * cbk1;
1257 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_MATHSPECFUNCTIONS
1258 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
1259 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_MATHSPECFUNCTIONS
Partial reimplementation of std::complex that works as the result of a Kokkos::parallel_reduce.
KOKKOS_INLINE_FUNCTION constexpr RealType & real() noexcept
The real part of this complex number.