Coverage Report

Created: 2025-11-05 08:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/pxfm-0.1.25/src/err/erfcx.rs
Line
Count
Source
1
/*
2
 * // Copyright (c) Radzivon Bartoshyk 9/2025. All rights reserved.
3
 * //
4
 * // Redistribution and use in source and binary forms, with or without modification,
5
 * // are permitted provided that the following conditions are met:
6
 * //
7
 * // 1.  Redistributions of source code must retain the above copyright notice, this
8
 * // list of conditions and the following disclaimer.
9
 * //
10
 * // 2.  Redistributions in binary form must reproduce the above copyright notice,
11
 * // this list of conditions and the following disclaimer in the documentation
12
 * // and/or other materials provided with the distribution.
13
 * //
14
 * // 3.  Neither the name of the copyright holder nor the names of its
15
 * // contributors may be used to endorse or promote products derived from
16
 * // this software without specific prior written permission.
17
 * //
18
 * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
 * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
 * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
 * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
 * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
 * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
 * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29
use crate::double_double::DoubleDouble;
30
use crate::pow_exec::exp_dd_fast;
31
32
#[inline]
33
0
fn core_erfcx(x: f64) -> DoubleDouble {
34
0
    if x <= 8. {
35
        // Rational approximant for erfcx generated by Wolfram Mathematica:
36
        // <<FunctionApproximations`
37
        // ClearAll["Global`*"]
38
        // f[x_]:=Exp[x^2]Erfc[x]
39
        // {err0,approx,err1}=MiniMaxApproximation[f[z],{z,{1, 8},11,11},WorkingPrecision->75,MaxIterations->100]
40
        // num=Numerator[approx];
41
        // den=Denominator[approx];
42
        // coeffs=CoefficientList[num,z];
43
        // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]
44
        // coeffs=CoefficientList[den,z];
45
        // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]
46
        const P: [(u64, u64); 12] = [
47
            (0xbc836faeb9a312bb, 0x3ff000000000ee8e),
48
            (0x3c91842f891bec6a, 0x4002ca20a78aaf8f),
49
            (0x3c7916e8a1c30681, 0x4005e955f70aed5b),
50
            (0x3cabad150d828d82, 0x4000646f5807ad07),
51
            (0xbc6f482680d66d9c, 0x3ff1449e03ed381c),
52
            (0xbc7188796156ae19, 0x3fdaa7e997e3b034),
53
            (0xbc5c8af0642761e3, 0x3fbe836282058d4a),
54
            (0xbc372829be2d072f, 0x3f99a2b2adc2ec05),
55
            (0x3c020cc8b96000ab, 0x3f6e6cc3d120a955),
56
            (0x3bdd138e6c136806, 0x3f3743d6735eaf13),
57
            (0xbb9fbd22f0675122, 0x3ef1c1d36ebe29a2),
58
            (0xb89093cc981c934c, 0xbc43c18bc6385c74),
59
        ];
60
61
0
        let x2 = DoubleDouble::from_exact_mult(x, x);
62
0
        let x4 = x2 * x2;
63
0
        let x8 = x4 * x4;
64
65
0
        let e0 = DoubleDouble::mul_f64_add(
66
0
            DoubleDouble::from_bit_pair(P[1]),
67
0
            x,
68
0
            DoubleDouble::from_bit_pair(P[0]),
69
        );
70
0
        let e1 = DoubleDouble::mul_f64_add(
71
0
            DoubleDouble::from_bit_pair(P[3]),
72
0
            x,
73
0
            DoubleDouble::from_bit_pair(P[2]),
74
        );
75
0
        let e2 = DoubleDouble::mul_f64_add(
76
0
            DoubleDouble::from_bit_pair(P[5]),
77
0
            x,
78
0
            DoubleDouble::from_bit_pair(P[4]),
79
        );
80
0
        let e3 = DoubleDouble::mul_f64_add(
81
0
            DoubleDouble::from_bit_pair(P[7]),
82
0
            x,
83
0
            DoubleDouble::from_bit_pair(P[6]),
84
        );
85
0
        let e4 = DoubleDouble::mul_f64_add(
86
0
            DoubleDouble::from_bit_pair(P[9]),
87
0
            x,
88
0
            DoubleDouble::from_bit_pair(P[8]),
89
        );
90
0
        let e5 = DoubleDouble::mul_f64_add(
91
0
            DoubleDouble::from_bit_pair(P[11]),
92
0
            x,
93
0
            DoubleDouble::from_bit_pair(P[10]),
94
        );
95
96
0
        let f0 = DoubleDouble::mul_add(x2, e1, e0);
97
0
        let f1 = DoubleDouble::mul_add(x2, e3, e2);
98
0
        let f2 = DoubleDouble::mul_add(x2, e5, e4);
99
100
0
        let g0 = DoubleDouble::mul_add(x4, f1, f0);
101
102
0
        let p_num = DoubleDouble::mul_add(x8, f2, g0);
103
104
        const Q: [(u64, u64); 12] = [
105
            (0x0000000000000000, 0x3ff0000000000000),
106
            (0xbc95d65be031374e, 0x400bd10c4fb1dbe5),
107
            (0x3cb2d8f661db08a0, 0x4016a649ff973199),
108
            (0x3ca32cbcfdc0ea93, 0x4016daab399c1ffc),
109
            (0xbca2982868536578, 0x400fd61ab892d14c),
110
            (0xbca2e29199e17fd9, 0x40001f56c4d495a3),
111
            (0x3c412ce623a1790a, 0x3fe852b582135164),
112
            (0x3c61152eaf4b0dc5, 0x3fcb760564da7cde),
113
            (0xbc1b57ff91d81959, 0x3fa6e146988df835),
114
            (0x3c17183d8445f19a, 0x3f7b06599b5e912f),
115
            (0xbbd0ada61b85ff98, 0x3f449e39467b73d0),
116
            (0xbb658d84fc735e67, 0x3eff794442532b51),
117
        ];
118
119
0
        let e0 = DoubleDouble::mul_f64_add_f64(
120
0
            DoubleDouble::from_bit_pair(Q[1]),
121
0
            x,
122
0
            f64::from_bits(0x3ff0000000000000),
123
        );
124
0
        let e1 = DoubleDouble::mul_f64_add(
125
0
            DoubleDouble::from_bit_pair(Q[3]),
126
0
            x,
127
0
            DoubleDouble::from_bit_pair(Q[2]),
128
        );
129
0
        let e2 = DoubleDouble::mul_f64_add(
130
0
            DoubleDouble::from_bit_pair(Q[5]),
131
0
            x,
132
0
            DoubleDouble::from_bit_pair(Q[4]),
133
        );
134
0
        let e3 = DoubleDouble::mul_f64_add(
135
0
            DoubleDouble::from_bit_pair(Q[7]),
136
0
            x,
137
0
            DoubleDouble::from_bit_pair(Q[6]),
138
        );
139
0
        let e4 = DoubleDouble::mul_f64_add(
140
0
            DoubleDouble::from_bit_pair(Q[9]),
141
0
            x,
142
0
            DoubleDouble::from_bit_pair(Q[8]),
143
        );
144
0
        let e5 = DoubleDouble::mul_f64_add(
145
0
            DoubleDouble::from_bit_pair(Q[11]),
146
0
            x,
147
0
            DoubleDouble::from_bit_pair(Q[10]),
148
        );
149
150
0
        let f0 = DoubleDouble::mul_add(x2, e1, e0);
151
0
        let f1 = DoubleDouble::mul_add(x2, e3, e2);
152
0
        let f2 = DoubleDouble::mul_add(x2, e5, e4);
153
154
0
        let g0 = DoubleDouble::mul_add(x4, f1, f0);
155
156
0
        let p_den = DoubleDouble::mul_add(x8, f2, g0);
157
0
        return DoubleDouble::div(p_num, p_den);
158
0
    }
159
160
    // for large x erfcx(x) ~ 1/sqrt(pi) / x * R(1/x)
161
    const ONE_OVER_SQRT_PI: DoubleDouble =
162
        DoubleDouble::from_bit_pair((0x3c61ae3a914fed80, 0x3fe20dd750429b6d));
163
0
    let r = DoubleDouble::from_quick_recip(x);
164
    // Rational approximant generated by Wolfram:
165
    // <<FunctionApproximations`
166
    // ClearAll["Global`*"]
167
    // f[x_]:=Exp[1/x^2]Erfc[1/x]/x*Sqrt[Pi]
168
    // {err0,approx}=MiniMaxApproximation[f[z],{z,{2^-23,1/8},8,8},WorkingPrecision->75,MaxIterations->100]
169
    // num=Numerator[approx][[1]];
170
    // den=Denominator[approx][[1]];
171
    // coeffs=CoefficientList[num,z];
172
    // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]
173
    // coeffs=CoefficientList[den,z];
174
    // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]
175
    const P: [(u64, u64); 9] = [
176
        (0xbb1d2ee37e46a4cd, 0x3ff0000000000000),
177
        (0x3ca2e575a4ce3d30, 0x4001303ab00c8bac),
178
        (0xbccf38381e5ee521, 0x4030a97aeed54c9f),
179
        (0xbcc3a2842df0dd3d, 0x4036f7733c9fd2f9),
180
        (0xbcfeaf46506f16ed, 0x4051c5f382750553),
181
        (0x3ccbb9f5e11d176a, 0x404ac0081e0749e0),
182
        (0xbcf374f8966ae2a5, 0x4052082526d99a5c),
183
        (0x3cbb5530b924f224, 0x402feabbf6571c29),
184
        (0xbcbcdd50a3ca4776, 0x40118726e1f2d204),
185
    ];
186
    const Q: [(u64, u64); 9] = [
187
        (0x0000000000000000, 0x3ff0000000000000),
188
        (0x3ca2e4613c9e0017, 0x4001303ab00c8bac),
189
        (0xbcce5f17cf14e51d, 0x4031297aeed54c9f),
190
        (0xbcdf7e0fed176f92, 0x40380a76e7a09bb2),
191
        (0x3cfc57b67a2797af, 0x4053bb22e04faf3e),
192
        (0xbcd3e63b7410b46b, 0x404ff46317ae9483),
193
        (0xbce122c15db2653f, 0x405925ef8a428c36),
194
        (0x3ce174ebe3e52c8e, 0x4040f49acfe692e1),
195
        (0xbcda0e267ce6e2e6, 0x40351a07878bfbd3),
196
    ];
197
0
    let mut p_num = DoubleDouble::mul_add(
198
0
        DoubleDouble::from_bit_pair(P[8]),
199
0
        r,
200
0
        DoubleDouble::from_bit_pair(P[7]),
201
    );
202
0
    p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[6]));
203
0
    p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[5]));
204
0
    p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[4]));
205
0
    p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[3]));
206
0
    p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[2]));
207
0
    p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[1]));
208
0
    p_num = DoubleDouble::mul_add(p_num, r, DoubleDouble::from_bit_pair(P[0]));
209
210
0
    let mut p_den = DoubleDouble::mul_add(
211
0
        DoubleDouble::from_bit_pair(Q[8]),
212
0
        r,
213
0
        DoubleDouble::from_bit_pair(Q[7]),
214
    );
215
0
    p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[6]));
216
0
    p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[5]));
217
0
    p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[4]));
218
0
    p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[3]));
219
0
    p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[2]));
220
0
    p_den = DoubleDouble::mul_add(p_den, r, DoubleDouble::from_bit_pair(Q[1]));
221
0
    p_den = DoubleDouble::mul_add_f64(p_den, r, f64::from_bits(0x3ff0000000000000));
222
223
0
    let v0 = DoubleDouble::quick_mult(ONE_OVER_SQRT_PI, r);
224
0
    let v1 = DoubleDouble::div(p_num, p_den);
225
0
    DoubleDouble::quick_mult(v0, v1)
226
0
}
227
228
/// Scaled complementary error function (exp(x^2)*erfc(x))
229
0
pub fn f_erfcx(x: f64) -> f64 {
230
0
    let ux = x.to_bits().wrapping_shl(1);
231
232
0
    if ux >= 0x7ffu64 << 53 || ux <= 0x7960000000000000u64 {
233
        // x == NaN, x == inf, x == 0, |x| <= f64::EPSILON
234
0
        if x.is_nan() {
235
0
            return f64::NAN;
236
0
        }
237
0
        if x.to_bits().wrapping_shl(1) == 0 {
238
0
            return 1.;
239
0
        }
240
0
        if x.is_infinite() {
241
0
            return if x.is_sign_positive() {
242
0
                0.
243
            } else {
244
0
                f64::INFINITY
245
            };
246
0
        }
247
248
0
        if ux <= 0x7888f5c28f5c28f6u64 {
249
            // |x| <= 2.2204460492503131e-18
250
0
            return 1.;
251
0
        }
252
253
        // |x| <= f64::EPSILON
254
        use crate::common::f_fmla;
255
        const M_TWO_OVER_SQRT_PI: DoubleDouble =
256
            DoubleDouble::from_bit_pair((0xbc71ae3a914fed80, 0xbff20dd750429b6d));
257
0
        return f_fmla(
258
0
            M_TWO_OVER_SQRT_PI.lo,
259
0
            x,
260
0
            f_fmla(M_TWO_OVER_SQRT_PI.hi, x, 1.),
261
        );
262
0
    }
263
264
0
    if x.to_bits() >= 0xc03aa449ebc84dd6 {
265
        // x <= -sqrt(709.783) ~ -26.6417
266
0
        return f64::INFINITY;
267
0
    }
268
269
0
    let ax = x.to_bits() & 0x7fff_ffff_ffff_ffffu64;
270
271
0
    if ax <= 0x3ff0000000000000u64 {
272
        // |x| <= 1
273
        // Rational approximant generated by Wolfram Mathematica:
274
        // <<FunctionApproximations`
275
        // ClearAll["Global`*"]
276
        // f[x_]:=Exp[x^2]Erfc[x]
277
        // {err0,approx}=MiniMaxApproximation[f[z],{z,{-1, 1},10,10},WorkingPrecision->75,MaxIterations->100]
278
        // num=Numerator[approx][[1]];
279
        // den=Denominator[approx][[1]];
280
        // coeffs=CoefficientList[num,z];
281
        // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]
282
        // coeffs=CoefficientList[den,z];
283
        // TableForm[Table[Row[{"'",NumberForm[coeffs[[i+1]],{50,50},ExponentFunction->(Null&)],"',"}],{i,0,Length[coeffs]-1}]]
284
        const P: [(u64, u64); 11] = [
285
            (0xbb488611350b1950, 0x3ff0000000000000),
286
            (0xbc86ae482c7f2342, 0x3ff9c5d39e89602f),
287
            (0x3c6702d70b807254, 0x3ff5a4c406d6468b),
288
            (0x3c7fe41fc43cfed5, 0x3fe708e7f401bd0c),
289
            (0x3c73a4a355172c6d, 0x3fd0d9a0c1a7126c),
290
            (0x3c5f4c372faa270f, 0x3fb154722e30762e),
291
            (0xbc04c0227976379e, 0x3f88ecebb62ce646),
292
            (0xbbdc9ea151b9eb33, 0x3f580ea84143877b),
293
            (0xbb6dae7001a91491, 0x3f1c3c5f95579b0a),
294
            (0x3b6aca5e82c52897, 0x3ecea4db51968d9e),
295
            (0x3a41c4edd175d2af, 0x3dbc0dccea7fc8ed),
296
        ];
297
298
0
        let x2 = DoubleDouble::from_exact_mult(x, x);
299
0
        let x4 = x2 * x2;
300
0
        let x8 = x4 * x4;
301
302
0
        let q0 = DoubleDouble::mul_f64_add(
303
0
            DoubleDouble::from_bit_pair(P[1]),
304
0
            x,
305
0
            DoubleDouble::from_bit_pair(P[0]),
306
        );
307
0
        let q1 = DoubleDouble::mul_f64_add(
308
0
            DoubleDouble::from_bit_pair(P[3]),
309
0
            x,
310
0
            DoubleDouble::from_bit_pair(P[2]),
311
        );
312
0
        let q2 = DoubleDouble::mul_f64_add(
313
0
            DoubleDouble::from_bit_pair(P[5]),
314
0
            x,
315
0
            DoubleDouble::from_bit_pair(P[4]),
316
        );
317
0
        let q3 = DoubleDouble::mul_f64_add(
318
0
            DoubleDouble::from_bit_pair(P[7]),
319
0
            x,
320
0
            DoubleDouble::from_bit_pair(P[6]),
321
        );
322
0
        let q4 = DoubleDouble::mul_f64_add(
323
0
            DoubleDouble::from_bit_pair(P[9]),
324
0
            x,
325
0
            DoubleDouble::from_bit_pair(P[8]),
326
        );
327
328
0
        let r0 = DoubleDouble::mul_add(x2, q1, q0);
329
0
        let r1 = DoubleDouble::mul_add(x2, q3, q2);
330
331
0
        let s0 = DoubleDouble::mul_add(x4, r1, r0);
332
0
        let s1 = DoubleDouble::mul_add(x2, DoubleDouble::from_bit_pair(P[10]), q4);
333
0
        let p_num = DoubleDouble::mul_add(x8, s1, s0);
334
335
        const Q: [(u64, u64); 11] = [
336
            (0x0000000000000000, 0x3ff0000000000000),
337
            (0xbc7bae414cad99c8, 0x4005e9d57765fdce),
338
            (0x3c8fa553bed15758, 0x400b8c670b3fbcda),
339
            (0x3ca6c7ad610f1019, 0x4004f2ca59958153),
340
            (0x3c87787f336cc4e6, 0x3ff55c267090315a),
341
            (0xbc6ef55d4b2c4150, 0x3fde8b84b64b6f4e),
342
            (0x3c570d63c94be3a3, 0x3fbf0d5e36017482),
343
            (0x3c1882a745ef572e, 0x3f962f73633506c1),
344
            (0xbc0850bb6fc82764, 0x3f65593e0dc46acd),
345
            (0xbbb9dc0097d7d776, 0x3f290545603e2f94),
346
            (0xbb776e5781e3889d, 0x3edb29c49d18cf89),
347
        ];
348
349
0
        let q0 = DoubleDouble::mul_f64_add_f64(
350
0
            DoubleDouble::from_bit_pair(Q[1]),
351
0
            x,
352
0
            f64::from_bits(0x3ff0000000000000),
353
        );
354
0
        let q1 = DoubleDouble::mul_f64_add(
355
0
            DoubleDouble::from_bit_pair(Q[3]),
356
0
            x,
357
0
            DoubleDouble::from_bit_pair(Q[2]),
358
        );
359
0
        let q2 = DoubleDouble::mul_f64_add(
360
0
            DoubleDouble::from_bit_pair(Q[5]),
361
0
            x,
362
0
            DoubleDouble::from_bit_pair(Q[4]),
363
        );
364
0
        let q3 = DoubleDouble::mul_f64_add(
365
0
            DoubleDouble::from_bit_pair(Q[7]),
366
0
            x,
367
0
            DoubleDouble::from_bit_pair(Q[6]),
368
        );
369
0
        let q4 = DoubleDouble::mul_f64_add(
370
0
            DoubleDouble::from_bit_pair(Q[9]),
371
0
            x,
372
0
            DoubleDouble::from_bit_pair(Q[8]),
373
        );
374
375
0
        let r0 = DoubleDouble::mul_add(x2, q1, q0);
376
0
        let r1 = DoubleDouble::mul_add(x2, q3, q2);
377
378
0
        let s0 = DoubleDouble::mul_add(x4, r1, r0);
379
0
        let s1 = DoubleDouble::mul_add(x2, DoubleDouble::from_bit_pair(Q[10]), q4);
380
0
        let p_den = DoubleDouble::mul_add(x8, s1, s0);
381
382
0
        let v = DoubleDouble::div(p_num, p_den);
383
0
        return v.to_f64();
384
0
    }
385
386
0
    let mut erfcx_abs_x = core_erfcx(f64::from_bits(ax));
387
0
    if x < 0. {
388
        // exp(x^2)erfc(-x) = 2*exp(x^2) - erfcx(|x|)
389
0
        erfcx_abs_x = DoubleDouble::from_exact_add(erfcx_abs_x.hi, erfcx_abs_x.lo);
390
0
        let d2x = DoubleDouble::from_exact_mult(x, x);
391
0
        let expd2x = exp_dd_fast(d2x);
392
0
        return DoubleDouble::mul_f64_add(expd2x, 2., -erfcx_abs_x).to_f64();
393
0
    }
394
0
    erfcx_abs_x.to_f64()
395
0
}
396
397
#[cfg(test)]
398
mod tests {
399
    use crate::f_erfcx;
400
401
    #[test]
402
    fn test_erfcx() {
403
        assert_eq!(f_erfcx(2.2204460492503131e-18), 1.0);
404
        assert_eq!(f_erfcx(-2.2204460492503131e-18), 1.0);
405
        assert_eq!(f_erfcx(-f64::EPSILON), 1.0000000000000002);
406
        assert_eq!(f_erfcx(f64::EPSILON), 0.9999999999999998);
407
        assert_eq!(f_erfcx(-173.), f64::INFINITY);
408
        assert_eq!(f_erfcx(-9.4324165432), 8.718049147018359e38);
409
        assert_eq!(f_erfcx(9.4324165432), 0.059483265496416374);
410
        assert_eq!(f_erfcx(-1.32432512125), 11.200579112797806);
411
        assert_eq!(f_erfcx(1.32432512125), 0.3528722004785406);
412
        assert_eq!(f_erfcx(-0.532431235), 2.0560589406595384);
413
        assert_eq!(f_erfcx(0.532431235), 0.5994337293294584);
414
        assert_eq!(f_erfcx(1e-26), 1.0);
415
        assert_eq!(f_erfcx(-0.500000000023073), 1.952360489253639);
416
        assert_eq!(f_erfcx(-175.), f64::INFINITY);
417
        assert_eq!(f_erfcx(f64::INFINITY), 0.);
418
        assert_eq!(f_erfcx(f64::NEG_INFINITY), f64::INFINITY);
419
        assert!(f_erfcx(f64::NAN).is_nan());
420
    }
421
}