| 216 | } |
| 217 | |
| 218 | static XlaOp ErfcImpl64(XlaOp x) { |
| 219 | // Coefficients for erfc(f64), from Cephes. |
| 220 | const double kMaxlog = 7.09782712893383996843E2; |
| 221 | // erfc(x) = exp(-x^2) P(|x|) / Q(|x|), 1 < x < 8 |
| 222 | static const std::array<double, 9> kErfcPCoefficient{ |
| 223 | 2.46196981473530512524E-10, 5.64189564831068821977E-1, |
| 224 | 7.46321056442269912687E0, 4.86371970985681366614E1, |
| 225 | 1.96520832956077098242E2, 5.26445194995477358631E2, |
| 226 | 9.34528527171957607540E2, 1.02755188689515710272E3, |
| 227 | 5.57535335369399327526E2}; |
| 228 | static const std::array<double, 9> kErfcQCoefficient{ |
| 229 | 1.00000000000000000000E0, 1.32281951154744992508E1, |
| 230 | 8.67072140885989742329E1, 3.54937778887819891062E2, |
| 231 | 9.75708501743205489753E2, 1.82390916687909736289E3, |
| 232 | 2.24633760818710981792E3, 1.65666309194161350182E3, |
| 233 | 5.57535340817727675546E2}; |
| 234 | |
| 235 | // erfc(x) = exp(-x^2) R(|x|) / S(|x|), 8 <= x < kMaxlog |
| 236 | static const std::array<double, 6> kErfcRCoefficient{ |
| 237 | 5.64189583547755073984E-1, 1.27536670759978104416E0, |
| 238 | 5.01905042251180477414E0, 6.16021097993053585195E0, |
| 239 | 7.40974269950448939160E0, 2.97886665372100240670E0}; |
| 240 | static const std::array<double, 7> kErfcSCoefficient{ |
| 241 | 1.00000000000000000000E0, 2.26052863220117276590E0, |
| 242 | 9.39603524938001434673E0, 1.20489539808096656605E1, |
| 243 | 1.70814450747565897222E1, 9.60896809063285878198E0, |
| 244 | 3.36907645100081516050E0}; |
| 245 | |
| 246 | XlaOp z = -x * x; |
| 247 | XlaOp abs_x = Abs(x); |
| 248 | XlaOp y = |
| 249 | Select(Lt(abs_x, ScalarLike(x, 8.0)), |
| 250 | Exp(z) * EvaluatePolynomial<double>(abs_x, kErfcPCoefficient) / |
| 251 | EvaluatePolynomial<double>(abs_x, kErfcQCoefficient), |
| 252 | Exp(z) * EvaluatePolynomial<double>(abs_x, kErfcRCoefficient) / |
| 253 | EvaluatePolynomial<double>(abs_x, kErfcSCoefficient)); |
| 254 | XlaOp y_clamp = Select(Lt(z, ScalarLike(x, -kMaxlog)), ScalarLike(x, 0), y); |
| 255 | return Select(Lt(x, ScalarLike(x, 0)), ScalarLike(x, 2.0) - y_clamp, y_clamp); |
| 256 | } |
| 257 | |
| 258 | // Compute a polynomial approximation of the error function. |
| 259 | // |