1 /* Implementation of the ERFC_SCALED intrinsic.
2 Copyright (C) 2008-2017 Free Software Foundation, Inc.
4 This file is part of the GNU Fortran runtime library (libgfortran).
6 Libgfortran is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public
8 License as published by the Free Software Foundation; either
9 version 3 of the License, or (at your option) any later version.
11 Libgfortran is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
25 #include "libgfortran.h"
27 /* This implementation of ERFC_SCALED is based on the netlib algorithm
28 available at http://www.netlib.org/specfun/erf */
30 #ifdef HAVE_GFC_REAL_4
33 #include "erfc_scaled_inc.c"
36 #ifdef HAVE_GFC_REAL_8
39 #include "erfc_scaled_inc.c"
42 #ifdef HAVE_GFC_REAL_10
45 #include "erfc_scaled_inc.c"
48 #ifdef HAVE_GFC_REAL_16
50 /* For quadruple-precision, netlib's implementation is
51 not accurate enough. We provide another one. */
53 #ifdef GFC_REAL_16_IS_FLOAT128
55 # define _THRESH -106.566990228185312813205074546585730Q
56 # define _M_2_SQRTPI M_2_SQRTPIq
57 # define _INF __builtin_infq()
58 # define _ERFC(x) erfcq(x)
59 # define _EXP(x) expq(x)
63 # define _THRESH -106.566990228185312813205074546585730L
65 # define M_2_SQRTPIl 1.128379167095512573896158903121545172L
67 # define _M_2_SQRTPI M_2_SQRTPIl
68 # define _INF __builtin_infl()
70 # define _ERFC(x) erfcl(x)
73 # define _EXP(x) expl(x)
78 #if defined(_ERFC) && defined(_EXP)
80 extern GFC_REAL_16
erfc_scaled_r16 (GFC_REAL_16
);
81 export_proto(erfc_scaled_r16
);
84 erfc_scaled_r16 (GFC_REAL_16 x
)
92 /* Compute directly as ERFC_SCALED(x) = ERFC(x) * EXP(X**2).
93 This is not perfect, but much better than netlib. */
94 return _ERFC(x
) * _EXP(x
* x
);
98 /* Calculate ERFC_SCALED(x) using a power series in 1/x:
99 ERFC_SCALED(x) = 1 / (x * sqrt(pi))
100 * (1 + Sum_n (-1)**n * (1 * 3 * 5 * ... * (2n-1))
103 GFC_REAL_16 sum
= 0, oldsum
;
104 GFC_REAL_16 inv2x2
= 1 / (2 * x
* x
);
110 fac
*= - (2*n
- 1) * inv2x2
;
120 return (1 + sum
) / x
* (_M_2_SQRTPI
/ 2);