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         int tmp_exponent = 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         int tmp_exponent = 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         int tmp_exponent = 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         int tmp_exponent = 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.