|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once |
|
|
|
#include "../config.h" |
|
#include "../error.h" |
|
|
|
#include "const.h" |
|
#include "polevl.h" |
|
|
|
namespace xsf { |
|
namespace cephes { |
|
|
|
namespace detail { |
|
|
|
constexpr double j0_PP[7] = { |
|
7.96936729297347051624E-4, 8.28352392107440799803E-2, 1.23953371646414299388E0, 5.44725003058768775090E0, |
|
8.74716500199817011941E0, 5.30324038235394892183E0, 9.99999999999999997821E-1, |
|
}; |
|
|
|
constexpr double j0_PQ[7] = { |
|
9.24408810558863637013E-4, 8.56288474354474431428E-2, 1.25352743901058953537E0, 5.47097740330417105182E0, |
|
8.76190883237069594232E0, 5.30605288235394617618E0, 1.00000000000000000218E0, |
|
}; |
|
|
|
constexpr double j0_QP[8] = { |
|
-1.13663838898469149931E-2, -1.28252718670509318512E0, -1.95539544257735972385E1, -9.32060152123768231369E1, |
|
-1.77681167980488050595E2, -1.47077505154951170175E2, -5.14105326766599330220E1, -6.05014350600728481186E0, |
|
}; |
|
|
|
constexpr double j0_QQ[7] = { |
|
|
|
6.43178256118178023184E1, 8.56430025976980587198E2, 3.88240183605401609683E3, 7.24046774195652478189E3, |
|
5.93072701187316984827E3, 2.06209331660327847417E3, 2.42005740240291393179E2, |
|
}; |
|
|
|
constexpr double j0_YP[8] = { |
|
1.55924367855235737965E4, -1.46639295903971606143E7, 5.43526477051876500413E9, |
|
-9.82136065717911466409E11, 8.75906394395366999549E13, -3.46628303384729719441E15, |
|
4.42733268572569800351E16, -1.84950800436986690637E16, |
|
}; |
|
|
|
constexpr double j0_YQ[7] = { |
|
|
|
1.04128353664259848412E3, 6.26107330137134956842E5, 2.68919633393814121987E8, 8.64002487103935000337E10, |
|
2.02979612750105546709E13, 3.17157752842975028269E15, 2.50596256172653059228E17, |
|
}; |
|
|
|
|
|
constexpr double j0_DR1 = 5.78318596294678452118E0; |
|
|
|
|
|
constexpr double j0_DR2 = 3.04712623436620863991E1; |
|
|
|
constexpr double j0_RP[4] = { |
|
-4.79443220978201773821E9, |
|
1.95617491946556577543E12, |
|
-2.49248344360967716204E14, |
|
9.70862251047306323952E15, |
|
}; |
|
|
|
constexpr double j0_RQ[8] = { |
|
|
|
4.99563147152651017219E2, 1.73785401676374683123E5, 4.84409658339962045305E7, 1.11855537045356834862E10, |
|
2.11277520115489217587E12, 3.10518229857422583814E14, 3.18121955943204943306E16, 1.71086294081043136091E18, |
|
}; |
|
|
|
} |
|
|
|
XSF_HOST_DEVICE inline double j0(double x) { |
|
double w, z, p, q, xn; |
|
|
|
if (x < 0) { |
|
x = -x; |
|
} |
|
|
|
if (x <= 5.0) { |
|
z = x * x; |
|
if (x < 1.0e-5) { |
|
return (1.0 - z / 4.0); |
|
} |
|
|
|
p = (z - detail::j0_DR1) * (z - detail::j0_DR2); |
|
p = p * polevl(z, detail::j0_RP, 3) / p1evl(z, detail::j0_RQ, 8); |
|
return (p); |
|
} |
|
|
|
w = 5.0 / x; |
|
q = 25.0 / (x * x); |
|
p = polevl(q, detail::j0_PP, 6) / polevl(q, detail::j0_PQ, 6); |
|
q = polevl(q, detail::j0_QP, 7) / p1evl(q, detail::j0_QQ, 7); |
|
xn = x - M_PI_4; |
|
p = p * std::cos(xn) - w * q * std::sin(xn); |
|
return (p * detail::SQRT2OPI / std::sqrt(x)); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XSF_HOST_DEVICE inline double y0(double x) { |
|
double w, z, p, q, xn; |
|
|
|
if (x <= 5.0) { |
|
if (x == 0.0) { |
|
set_error("y0", SF_ERROR_SINGULAR, NULL); |
|
return -std::numeric_limits<double>::infinity(); |
|
} else if (x < 0.0) { |
|
set_error("y0", SF_ERROR_DOMAIN, NULL); |
|
return std::numeric_limits<double>::quiet_NaN(); |
|
} |
|
z = x * x; |
|
w = polevl(z, detail::j0_YP, 7) / p1evl(z, detail::j0_YQ, 7); |
|
w += M_2_PI * std::log(x) * j0(x); |
|
return (w); |
|
} |
|
|
|
w = 5.0 / x; |
|
z = 25.0 / (x * x); |
|
p = polevl(z, detail::j0_PP, 6) / polevl(z, detail::j0_PQ, 6); |
|
q = polevl(z, detail::j0_QP, 7) / p1evl(z, detail::j0_QQ, 7); |
|
xn = x - M_PI_4; |
|
p = p * std::sin(xn) + w * q * std::cos(xn); |
|
return (p * detail::SQRT2OPI / std::sqrt(x)); |
|
} |
|
|
|
} |
|
} |
|
|