1#ifndef STAN_MATH_PRIM_FUN_ERFCX_HPP
2#define STAN_MATH_PRIM_FUN_ERFCX_HPP
19 0.000658749161529837803157, 0.0160837851487422766278,
20 0.125781726111229246204, 0.360344899949804439429,
21 0.305326634961232344035, 0.0163153871373020978498};
23 -0.00233520497626869185443, -0.0605183413124413191178,
24 -0.527905102951428412248, -1.87295284992346047209,
25 -2.56852019228982242072, -1.0};
32 1230.33935479799725, 2051.07837782607147, 1712.04761263407058,
33 881.952221241769090, 298.635138197400131, 66.1191906371416295,
34 8.88314979438837594, 5.64188496988670089e-1, 2.15311535474403846e-8};
36 1230.33935480374942, 3439.36767414372164, 4362.61909014324716,
37 3290.79923573345963, 1621.38957456669019, 537.181101862009858,
38 117.693950891312499, 15.7449261107098347, 1.0};
52template <std::
size_t N,
typename T,
typename It>
56 for (std::size_t i = 1; i < N; ++i) {
57 numerator = numerator * t + *++p;
58 denominator = denominator * t + *++q;
60 return {numerator, denominator};
74template <
typename T, std::
size_t N>
77 int j =
static_cast<int>(N) - (N % 2 ? 3 : 4);
78 T r = N % 2 ? T(c[N - 1]) : T(c[N - 2] + c[N - 1] * y);
79 for (; j >= 0; j -= 2) {
80 r = r * y2 + (c[j] + c[j + 1] * y);
99 const double s = x * x;
102 return (
INV_SQRT_PI + pq.first / (s * pq.second)) / x;
136 return 2.0 * pq.first / (x2 * pq.second);
138 const T u = 1.0 / x2;
139 static constexpr std::array<double, 8> series_coefficients{
140 1.0, -1.5, 3.75, -13.125,
141 59.0625, -324.84375, 2111.484375, -15836.1328125};
157 const double y2 = y * y;
177 static constexpr std::array<double, 19> c{1.0,
178 -1.12837916709551256,
180 -7.52252778063651983e-01,
181 4.99999999999992839e-01,
182 -3.00901111227312890e-01,
183 1.66666666667239644e-01,
184 -8.59717459974174147e-02,
185 4.16666666458337179e-02,
186 -1.91048337772546720e-02,
187 8.33333374332981443e-03,
188 -3.47359067853470795e-03,
189 1.38888415444527033e-03,
190 -5.34506929034156810e-04,
191 1.98445679338826757e-04,
192 -7.08163358203131886e-05,
193 2.46655529768908249e-05,
194 -9.35890030086883823e-06,
195 3.05977060678449757e-06};
196 const double x2 = x * x;
197 const double x4 = x2 * x2;
198 const double x8 = x4 * x4;
199 std::array<double, 4> quad;
200 for (
int i = 0; i < 4; ++i) {
201 const int j = 4 * i + 2;
202 quad[i] = (c[j] + c[j + 1] * x) + (c[j + 2] + c[j + 3] * x) * x2;
205 = (quad[0] + quad[1] * x4) + (quad[2] + quad[3] * x4 + c[18] * x8) * x8;
206 return (c[0] + c[1] * x) + x2 * rest;
267template <
typename T, require_arithmetic_t<T>* =
nullptr>
269 const double x =
static_cast<double>(xx);
270 constexpr double cody_min = 4.0;
271 constexpr double middle_min = 0.46875;
272 constexpr double overflow_max = -27.0;
275 }
else if (x >= middle_min) {
277 }
else if (x > -middle_min) {
279 }
else if (x < overflow_max) {
282 const double h = x * x;
283 const double two_exp_x2 = 2.0 * std::exp(h) * (1.0 + std::fma(x, x, -h));
284 constexpr double reflect_min = -6.1;
285 if (x < reflect_min) {
302 template <
typename T>
303 static inline auto fun(T&& x) {
304 return erfcx(std::forward<T>(x));
require_t< is_container< std::decay_t< T > > > require_container_t
Require type satisfies is_container.
require_all_not_t< is_nonscalar_prim_or_rev_kernel_expression< std::decay_t< Types > >... > require_all_not_nonscalar_prim_or_rev_kernel_expression_t
Require none of the types satisfy is_nonscalar_prim_or_rev_kernel_expression.
require_not_t< is_var_matrix< std::decay_t< T > > > require_not_var_matrix_t
Require type does not satisfy is_var_matrix.
double erfcx_cody_tail(double x)
Cody (1969) third-interval rational, valid for x >= 4.
constexpr std::array< double, 6 > erfcx_tail_p
constexpr double erfcx_tail_leading_only
constexpr std::array< double, 9 > erfcx_middle_p
T erfcx_derivative(const T &x, const T &value)
Derivative of erfcx, 2 * x * erfcx(x) - 2 / sqrt(pi).
T erfcx_paired_horner(const std::array< double, N > &c, const T &y, const T &y2)
Horner in y^2 over adjacent coefficient pairs, so the two halves of the chain are independent.
double erfcx_cody_middle(double y)
Cody (1969) second-interval rational, valid for 0.46875 <= x <= 4.
constexpr std::array< double, 6 > erfcx_tail_q
std::pair< T, T > erfcx_tail_polynomials(It p, It q, const T &t)
The two tail polynomials, taking the coefficients in the order the iterators give them as descending ...
double erfcx_small(double x)
Degree-18 polynomial for |x| < 0.46875.
constexpr std::array< double, 9 > erfcx_middle_q
fvar< T > erfcx(const fvar< T > &x)
Return the scaled complementary error function of the argument.
static constexpr double INV_SQRT_PI
The value of 1 over the square root of , .
static constexpr double TWO_OVER_SQRT_PI
The value of 2 over the square root of , .
static constexpr double INFTY
Positive infinity.
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Base template class for vectorization of unary scalar functions defined by a template class F to a sc...
Structure to wrap erfcx() so that it can be vectorized.