32#include <sycl/sycl.hpp>
34namespace dpnp::kernels::erfs::impl
37inline Tp polevl(Tp x,
const Tp *coeff,
int i)
48inline Tp p1evl(Tp x,
const Tp *coeff,
int i)
65 return -std::numeric_limits<Tp>::infinity();
68 return std::numeric_limits<Tp>::infinity();
70 else if (y0 < 0.0 || y0 > 1.0) {
71 return std::numeric_limits<Tp>::quiet_NaN();
75 constexpr Tp exp_minus2 = 0.13533528323661269189399949497248L;
76 if (y0 > (1.0 - exp_minus2)) {
86 constexpr Tp root_2_pi = 2.50662827463100050241576528481105L;
90 -5.99633501014107895267E1, 9.80010754185999661536E1,
91 -5.66762857469070293439E1, 1.39312609387279679503E1,
92 -1.23916583867381258016E0,
95 1.95448858338141759834E0, 4.67627912898881538453E0,
96 8.63602421390890590575E1, -2.25462687854119370527E2,
97 2.00260212380060660359E2, -8.20372256168333339912E1,
98 1.59056225126211695515E1, -1.18331621121330003142E0,
103 Tp x = y + y * (y2 * polevl(y2, p, 4) / p1evl(y2, q, 8));
104 return x * root_2_pi;
107 Tp x = sycl::sqrt(-2.0 * sycl::log(y));
108 Tp x0 = x - sycl::log(x) / x;
115 4.05544892305962419923E0, 3.15251094599893866154E1,
116 5.71628192246421288162E1, 4.40805073893200834700E1,
117 1.46849561928858024014E1, 2.18663306850790267539E0,
118 -1.40256079171354495875E-1, -3.50424626827848203418E-2,
119 -8.57456785154685413611E-4,
123 1.57799883256466749731E1, 4.53907635128879210584E1,
124 4.13172038254672030440E1, 1.50425385692907503408E1,
125 2.50464946208309415979E0, -1.42182922854787788574E-1,
126 -3.80806407691578277194E-2, -9.33259480895457427372E-4,
129 x1 = z * polevl(z, p, 8) / p1evl(z, q, 8);
134 3.23774891776946035970E0, 6.91522889068984211695E0,
135 3.93881025292474443415E0, 1.33303460815807542389E0,
136 2.01485389549179081538E-1, 1.23716634817820021358E-2,
137 3.01581553508235416007E-4, 2.65806974686737550832E-6,
138 6.23974539184983293730E-9,
142 6.02427039364742014255E0, 3.67983563856160859403E0,
143 1.37702099489081330271E0, 2.16236993594496635890E-1,
144 1.34204006088543189037E-2, 3.28014464682127739104E-4,
145 2.89247864745380683936E-6, 6.79019408009981274425E-9,
148 x1 = z * polevl(z, p, 8) / p1evl(z, q, 8);
158template <
typename Tp>
159inline Tp erfinv(Tp y)
161 static_assert(std::is_floating_point_v<Tp>,
162 "erfinv requires a floating-point type");
164 constexpr Tp lower = -1;
165 constexpr Tp upper = 1;
167 constexpr Tp thresh = 1e-7;
171 if ((-thresh < y) && (y < thresh)) {
173 constexpr Tp inv_sqrtpi = 1.1283791670955125738961589031215452L;
174 return y / inv_sqrtpi;
177 if ((lower < y) && (y < upper)) {
179 constexpr Tp one_div_root_2 = 0.7071067811865475244008443621048490L;
180 return ndtri(0.5 * (y + 1)) * one_div_root_2;
182 else if (y == lower) {
183 return -std::numeric_limits<Tp>::infinity();
185 else if (y == upper) {
186 return std::numeric_limits<Tp>::infinity();
188 else if (sycl::isnan(y)) {
191 return std::numeric_limits<Tp>::quiet_NaN();
194template <
typename Tp>
195inline Tp erfcinv(Tp y)
197 static_assert(std::is_floating_point_v<Tp>,
198 "erfcinv requires a floating-point type");
200 constexpr Tp lower = 0;
201 constexpr Tp upper = 2;
203 if ((lower < y) && (y < upper)) {
205 constexpr Tp one_div_root_2 = 0.7071067811865475244008443621048490L;
206 return -ndtri(0.5 * y) * one_div_root_2;
208 else if (y == lower) {
209 return std::numeric_limits<Tp>::infinity();
211 else if (y == upper) {
212 return -std::numeric_limits<Tp>::infinity();
214 else if (sycl::isnan(y)) {
217 return std::numeric_limits<Tp>::quiet_NaN();