123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- /* Implementation of the ERFC_SCALED intrinsic, to be included by erfc_scaled.c
- Copyright (C) 2008-2015 Free Software Foundation, Inc.
- This file is part of the GNU Fortran runtime library (libgfortran).
- Libgfortran is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
- Libgfortran is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR a PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
- /* This implementation of ERFC_SCALED is based on the netlib algorithm
- available at http://www.netlib.org/specfun/erf */
- #define TYPE KIND_SUFFIX(GFC_REAL_,KIND)
- #define CONCAT(x,y) x ## y
- #define KIND_SUFFIX(x,y) CONCAT(x,y)
- #if (KIND == 4)
- # define EXP(x) expf(x)
- # define TRUNC(x) truncf(x)
- #elif (KIND == 8)
- # define EXP(x) exp(x)
- # define TRUNC(x) trunc(x)
- #elif (KIND == 10)
- # ifdef HAVE_EXPL
- # define EXP(x) expl(x)
- # endif
- # ifdef HAVE_TRUNCL
- # define TRUNC(x) truncl(x)
- # endif
- #else
- # error "What exactly is it that you want me to do?"
- #endif
- #if defined(EXP) && defined(TRUNC)
- extern TYPE KIND_SUFFIX(erfc_scaled_r,KIND) (TYPE);
- export_proto(KIND_SUFFIX(erfc_scaled_r,KIND));
- TYPE
- KIND_SUFFIX(erfc_scaled_r,KIND) (TYPE x)
- {
- /* The main computation evaluates near-minimax approximations
- from "Rational Chebyshev approximations for the error function"
- by W. J. Cody, Math. Comp., 1969, PP. 631-638. This
- transportable program uses rational functions that theoretically
- approximate erf(x) and erfc(x) to at least 18 significant
- decimal digits. The accuracy achieved depends on the arithmetic
- system, the compiler, the intrinsic functions, and proper
- selection of the machine-dependent constants. */
- int i;
- TYPE del, res, xden, xnum, y, ysq;
- #if (KIND == 4)
- static TYPE xneg = -9.382, xsmall = 5.96e-8,
- xbig = 9.194, xhuge = 2.90e+3, xmax = 4.79e+37;
- #else
- static TYPE xneg = -26.628, xsmall = 1.11e-16,
- xbig = 26.543, xhuge = 6.71e+7, xmax = 2.53e+307;
- #endif
- #define SQRPI ((TYPE) 0.56418958354775628695L)
- #define THRESH ((TYPE) 0.46875L)
- static TYPE a[5] = { 3.16112374387056560l, 113.864154151050156l,
- 377.485237685302021l, 3209.37758913846947l, 0.185777706184603153l };
- static TYPE b[4] = { 23.6012909523441209l, 244.024637934444173l,
- 1282.61652607737228l, 2844.23683343917062l };
- static TYPE c[9] = { 0.564188496988670089l, 8.88314979438837594l,
- 66.1191906371416295l, 298.635138197400131l, 881.952221241769090l,
- 1712.04761263407058l, 2051.07837782607147l, 1230.33935479799725l,
- 2.15311535474403846e-8l };
- static TYPE d[8] = { 15.7449261107098347l, 117.693950891312499l,
- 537.181101862009858l, 1621.38957456669019l, 3290.79923573345963l,
- 4362.61909014324716l, 3439.36767414372164l, 1230.33935480374942l };
- static TYPE p[6] = { 0.305326634961232344l, 0.360344899949804439l,
- 0.125781726111229246l, 0.0160837851487422766l,
- 0.000658749161529837803l, 0.0163153871373020978l };
- static TYPE q[5] = { 2.56852019228982242l, 1.87295284992346047l,
- 0.527905102951428412l, 0.0605183413124413191l,
- 0.00233520497626869185l };
- y = (x > 0 ? x : -x);
- if (y <= THRESH)
- {
- ysq = 0;
- if (y > xsmall)
- ysq = y * y;
- xnum = a[4]*ysq;
- xden = ysq;
- for (i = 0; i <= 2; i++)
- {
- xnum = (xnum + a[i]) * ysq;
- xden = (xden + b[i]) * ysq;
- }
- res = x * (xnum + a[3]) / (xden + b[3]);
- res = 1 - res;
- res = EXP(ysq) * res;
- return res;
- }
- else if (y <= 4)
- {
- xnum = c[8]*y;
- xden = y;
- for (i = 0; i <= 6; i++)
- {
- xnum = (xnum + c[i]) * y;
- xden = (xden + d[i]) * y;
- }
- res = (xnum + c[7]) / (xden + d[7]);
- }
- else
- {
- res = 0;
- if (y >= xbig)
- {
- if (y >= xmax)
- goto finish;
- if (y >= xhuge)
- {
- res = SQRPI / y;
- goto finish;
- }
- }
- ysq = ((TYPE) 1) / (y * y);
- xnum = p[5]*ysq;
- xden = ysq;
- for (i = 0; i <= 3; i++)
- {
- xnum = (xnum + p[i]) * ysq;
- xden = (xden + q[i]) * ysq;
- }
- res = ysq *(xnum + p[4]) / (xden + q[4]);
- res = (SQRPI - res) / y;
- }
- finish:
- if (x < 0)
- {
- if (x < xneg)
- res = __builtin_inf ();
- else
- {
- ysq = TRUNC (x*((TYPE) 16))/((TYPE) 16);
- del = (x-ysq)*(x+ysq);
- y = EXP(ysq*ysq) * EXP(del);
- res = (y+y) - res;
- }
- }
- return res;
- }
- #endif
- #undef EXP
- #undef TRUNC
- #undef CONCAT
- #undef TYPE
- #undef KIND_SUFFIX
|