Automatic Differentiation
 
Loading...
Searching...
No Matches
erfcx.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_OPENCL_KERNELS_DEVICE_FUNCTIONS_ERFCX_HPP
2#define STAN_MATH_OPENCL_KERNELS_DEVICE_FUNCTIONS_ERFCX_HPP
3#ifdef STAN_OPENCL
4
6#include <string>
7
8namespace stan {
9namespace math {
10namespace opencl_kernels {
11
12// \cond
13static constexpr const char* erfcx_device_function
14 = "\n"
15 "#ifndef STAN_MATH_OPENCL_KERNELS_DEVICE_FUNCTIONS_ERFCX\n"
16 "#define STAN_MATH_OPENCL_KERNELS_DEVICE_FUNCTIONS_ERFCX\n" STRINGIFY(
17 // \endcond
29 double erfcx_tail_correction(double u) {
30 double p = 0.0163153871373020978498;
31 p = 0.305326634961232344035 + u * p;
32 p = 0.360344899949804439429 + u * p;
33 p = 0.125781726111229246204 + u * p;
34 p = 0.0160837851487422766278 + u * p;
35 p = 0.000658749161529837803157 + u * p;
36 double q = -1.0;
37 q = -2.56852019228982242072 + u * q;
38 q = -1.87295284992346047209 + u * q;
39 q = -0.527905102951428412248 + u * q;
40 q = -0.0605183413124413191178 + u * q;
41 q = -0.00233520497626869185443 + u * q;
42 return p / q;
43 }
44
52 double erfcx_cody_tail(double x) {
53 double u = 1.0 / (x * x);
54 return (M_2_SQRTPI * 0.5 + u * erfcx_tail_correction(u)) / x;
55 }
56
76 double erfcx_derivative(double x, double value) {
77 if (x < 4.0) {
78 return 2.0 * x * value - M_2_SQRTPI;
79 }
80 double u = 1.0 / (x * x);
81 if (x < 30.0) {
82 return 2.0 * u * erfcx_tail_correction(u);
83 }
84 // -sqrt(pi) * x^2 * erfcx'(x), asymptotic, ascending in u
85 const double s[8]
86 = {1.0, -1.5, 3.75, -13.125,
87 59.0625, -324.84375, 2111.484375, -15836.1328125};
88 double series = s[7];
89 for (int i = 6; i >= 0; --i) {
90 series = series * u + s[i];
91 }
92 return -(0.5 * M_2_SQRTPI) * u * series;
93 }
94
104 double erfcx_cody_middle(double y) {
105 double p = 2.15311535474403846e-8 * y;
106 p = (p + 5.64188496988670089e-1) * y;
107 p = (p + 8.88314979438837594) * y;
108 p = (p + 66.1191906371416295) * y;
109 p = (p + 298.635138197400131) * y;
110 p = (p + 881.952221241769090) * y;
111 p = (p + 1712.04761263407058) * y;
112 p = (p + 2051.07837782607147) * y;
113 double q = y;
114 q = (q + 15.7449261107098347) * y;
115 q = (q + 117.693950891312499) * y;
116 q = (q + 537.181101862009858) * y;
117 q = (q + 1621.38957456669019) * y;
118 q = (q + 3290.79923573345963) * y;
119 q = (q + 4362.61909014324716) * y;
120 q = (q + 3439.36767414372164) * y;
121 return (p + 1230.33935479799725) / (q + 1230.33935480374942);
122 }
123
133 double erfcx_small(double x) {
134 double p = 3.05977060678449757e-06;
135 p = -9.35890030086883823e-06 + x * p;
136 p = 2.46655529768908249e-05 + x * p;
137 p = -7.08163358203131886e-05 + x * p;
138 p = 1.98445679338826757e-04 + x * p;
139 p = -5.34506929034156810e-04 + x * p;
140 p = 1.38888415444527033e-03 + x * p;
141 p = -3.47359067853470795e-03 + x * p;
142 p = 8.33333374332981443e-03 + x * p;
143 p = -1.91048337772546720e-02 + x * p;
144 p = 4.16666666458337179e-02 + x * p;
145 p = -8.59717459974174147e-02 + x * p;
146 p = 1.66666666667239644e-01 + x * p;
147 p = -3.00901111227312890e-01 + x * p;
148 p = 4.99999999999992839e-01 + x * p;
149 p = -7.52252778063651983e-01 + x * p;
150 p = 1.0 + x * p;
151 p = -1.12837916709551256 + x * p;
152 return 1.0 + x * p;
153 }
154
177 double erfcx(double x) {
178 if (x >= 4.0) {
179 return erfcx_cody_tail(x);
180 } else if (x >= 0.46875) {
181 return erfcx_cody_middle(x);
182 } else if (x > -0.46875) {
183 return erfcx_small(x);
184 } else if (x < -27.0) {
185 return INFINITY;
186 }
187 double h = x * x;
188 double two_exp_x2 = 2.0 * exp(h) * (1.0 + fma(x, x, -h));
189 if (x < -6.1) {
190 return two_exp_x2;
191 }
192 double y = -x;
193 return two_exp_x2
194 - (y >= 4.0 ? erfcx_cody_tail(y) : erfcx_cody_middle(y));
195 }
196 // \cond
197 ) "\n#endif\n"; // NOLINT
198// \endcond
199
200} // namespace opencl_kernels
201} // namespace math
202} // namespace stan
203
204#endif
205#endif
double erfcx_cody_tail(double x)
Cody (1969) third-interval rational, for x >= 4.
Definition erfcx.hpp:52
double erfcx(double x)
Return the scaled complementary error function exp(x * x) * erfc(x) of the kernel generator expressio...
Definition erfcx.hpp:177
double erfcx_small(double x)
Degree-18 Chebyshev-economized expansion of erfcx about zero, for |x| < 0.46875.
Definition erfcx.hpp:133
double erfcx_tail_correction(double u)
Correction factor of the Cody (1969) third-interval rational: erfcx(x) = (INV_SQRT_PI + u * correctio...
Definition erfcx.hpp:29
double erfcx_cody_middle(double y)
Cody (1969) second-interval rational, for 0.46875 <= x <= 4.
Definition erfcx.hpp:104
double erfcx_derivative(double x, double value)
Derivative of erfcx, 2 * x * erfcx(x) - 2 / sqrt(pi).
Definition erfcx.hpp:76
fvar< return_type_t< T1, T2, T3 > > fma(const fvar< T1 > &x1, const fvar< T2 > &x2, const fvar< T3 > &x3)
The fused multiply-add operation (C99).
Definition fma.hpp:60
fvar< T > exp(const fvar< T > &x)
Definition exp.hpp:15
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
#define STRINGIFY(...)
Definition stringify.hpp:9