1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
|
/* Double precision version of routines in ERF from the netlib SPECFUN */
/* library. Translated by f2c and modified. */
#include "xlisp.h"
#include "xlstat.h"
#include "linalg.h"
static VOID calerf P3C(double, arg, double *, result, int, jint)
{
/* ------------------------------------------------------------------ */
/* This packet evaluates erf(x), erfc(x), and exp(x*x)*erfc(x) */
/* for a real argument x. It contains three FUNCTION type */
/* subprograms: ERF, ERFC, and ERFCX (or DERF, DERFC, and DERFCX), */
/* and one SUBROUTINE type subprogram, CALERF. The calling */
/* statements for the primary entries are: */
/* Y=ERF(X) (or Y=DERF(X)), */
/* Y=ERFC(X) (or Y=DERFC(X)), */
/* and */
/* Y=ERFCX(X) (or Y=DERFCX(X)). */
/* The routine CALERF is intended for internal packet use only, */
/* all computations within the packet being concentrated in this */
/* routine. The function subprograms invoke CALERF with the */
/* statement */
/* CALL CALERF(ARG,RESULT,JINT) */
/* where the parameter usage is as follows */
/* Function Parameters for CALERF */
/* call ARG Result JINT */
/* ERF(ARG) ANY REAL ARGUMENT ERF(ARG) 0 */
/* ERFC(ARG) ABS(ARG) .LT. XBIG ERFC(ARG) 1 */
/* ERFCX(ARG) XNEG .LT. ARG .LT. XMAX ERFCX(ARG) 2 */
/* 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. */
/* ******************************************************************* */
/* ******************************************************************* */
/* Explanation of machine-dependent constants */
/* XMIN = the smallest positive floating-point number. */
/* XINF = the largest positive finite floating-point number. */
/* XNEG = the largest negative argument acceptable to ERFCX; */
/* the negative of the solution to the equation */
/* 2*exp(x*x) = XINF. */
/* XSMALL = argument below which erf(x) may be represented by */
/* 2*x/sqrt(pi) and above which x*x will not underflow. */
/* A conservative value is the largest machine number X */
/* such that 1.0 + X = 1.0 to machine precision. */
/* XBIG = largest argument acceptable to ERFC; solution to */
/* the equation: W(x) * (1-0.5/x**2) = XMIN, where */
/* W(x) = exp(-x*x)/[x*sqrt(pi)]. */
/* XHUGE = argument above which 1.0 - 1/(2*x*x) = 1.0 to */
/* machine precision. A conservative value is */
/* 1/[2*sqrt(XSMALL)] */
/* XMAX = largest acceptable argument to ERFCX; the minimum */
/* of XINF and 1/[sqrt(pi)*XMIN]. */
/* Approximate values for some important machines are: */
/* XMIN XINF XNEG XSMALL */
/* CDC 7600 (S.P.) 3.13E-294 1.26E+322 -27.220 7.11E-15 */
/* CRAY-1 (S.P.) 4.58E-2467 5.45E+2465 -75.345 7.11E-15 */
/* IEEE (IBM/XT, */
/* SUN, etc.) (S.P.) 1.18E-38 3.40E+38 -9.382 5.96E-8 */
/* IEEE (IBM/XT, */
/* SUN, etc.) (D.P.) 2.23D-308 1.79D+308 -26.628 1.11D-16 */
/* IBM 195 (D.P.) 5.40D-79 7.23E+75 -13.190 1.39D-17 */
/* UNIVAC 1108 (D.P.) 2.78D-309 8.98D+307 -26.615 1.73D-18 */
/* VAX D-Format (D.P.) 2.94D-39 1.70D+38 -9.345 1.39D-17 */
/* VAX G-Format (D.P.) 5.56D-309 8.98D+307 -26.615 1.11D-16 */
/* XBIG XHUGE XMAX */
/* CDC 7600 (S.P.) 25.922 8.39E+6 1.80X+293 */
/* CRAY-1 (S.P.) 75.326 8.39E+6 5.45E+2465 */
/* IEEE (IBM/XT, */
/* SUN, etc.) (S.P.) 9.194 2.90E+3 4.79E+37 */
/* IEEE (IBM/XT, */
/* SUN, etc.) (D.P.) 26.543 6.71D+7 2.53D+307 */
/* IBM 195 (D.P.) 13.306 1.90D+8 7.23E+75 */
/* UNIVAC 1108 (D.P.) 26.582 5.37D+8 8.98D+307 */
/* VAX D-Format (D.P.) 9.269 1.90D+8 1.70D+38 */
/* VAX G-Format (D.P.) 26.569 6.71D+7 8.98D+307 */
/* ******************************************************************* */
/* ******************************************************************* */
/* Error returns */
/* The program returns ERFC = 0 for ARG .GE. XBIG; */
/* ERFCX = XINF for ARG .LT. XNEG; */
/* and */
/* ERFCX = 0 for ARG .GE. XMAX. */
/* Intrinsic functions required are: */
/* ABS, AINT, EXP */
/* Author: W. J. Cody */
/* Mathematics and Computer Science Division */
/* Argonne National Laboratory */
/* Argonne, IL 60439 */
/* Latest modification: March 19, 1990 */
/* ------------------------------------------------------------------ */
double xden, xnum;
int i;
double x, y, del, ysq;
/* ------------------------------------------------------------------ */
/* Mathematical constants */
/* ------------------------------------------------------------------ */
static double four = 4.;
static double one = 1.;
static double half = .5;
static double two = 2.;
static double zero = 0.;
static double sqrpi = .56418958354775628695;
static double thresh = .46875;
static double sixten = 16.;
/* ------------------------------------------------------------------ */
/* Machine-dependent constants */
/* ------------------------------------------------------------------ */
#ifdef IEEEFP
static double xinf = 1.79e308;
static double xneg = -26.628;
static double xsmall = 1.11e-16;
static double xbig = 26.543;
static double xhuge = 6.71e7;
static double xmax = 2.53e307;
#else
#ifdef CRAYCC
static double xinf = 5.45e2465;
static double xneg = -75.345;
static double xsmall = 7.11e-15;
static double xbig = 75.326;
static double xhuge = 8.39e6;
static double xmax = 5.45e2465;
#else /* use IBM 196 values */
static double xinf = 7.23e75;
static double xneg = -13.190;
static double xsmall = 1.39e-17;
static double xbig = 13.306;
static double xhuge = 1.90e8;
static double xmax = 7.23e75;
#endif /* CRAYCC */
#endif /* IEEEFP */
/* ------------------------------------------------------------------ */
/* Coefficients for approximation to erf in first interval */
/* ------------------------------------------------------------------ */
static double a[5] = { 3.1611237438705656,113.864154151050156,
377.485237685302021,3209.37758913846947,
.185777706184603153 };
static double b[4] = { 23.6012909523441209,244.024637934444173,
1282.61652607737228,2844.23683343917062 };
/* ------------------------------------------------------------------ */
/* Coefficients for approximation to erfc in second interval */
/* ------------------------------------------------------------------ */
static double c[9] = { .564188496988670089,8.88314979438837594,
66.1191906371416295,298.635138197400131,
881.95222124176909,1712.04761263407058,
2051.07837782607147,1230.33935479799725,
2.15311535474403846e-8 };
static double d[8] = { 15.7449261107098347,117.693950891312499,
537.181101862009858,1621.38957456669019,
3290.79923573345963,4362.61909014324716,
3439.36767414372164,1230.33935480374942 };
/* ------------------------------------------------------------------ */
/* Coefficients for approximation to erfc in third interval */
/* ------------------------------------------------------------------ */
static double p[6] = { .305326634961232344,.360344899949804439,
.125781726111229246,.0160837851487422766,
6.58749161529837803e-4,.0163153871373020978 };
static double q[5] = { 2.56852019228982242,1.87295284992346047,
.527905102951428412,.0605183413124413191,
.00233520497626869185 };
/* ------------------------------------------------------------------ */
x = arg;
y = abs(x);
if (y <= thresh) {
/* ------------------------------------------------------------------ */
/* Evaluate erf for |X| <= 0.46875 */
/* ------------------------------------------------------------------ */
ysq = zero;
if (y > xsmall) {
ysq = y * y;
}
xnum = a[4] * ysq;
xden = ysq;
for (i = 1; i <= 3; ++i) {
xnum = (xnum + a[i - 1]) * ysq;
xden = (xden + b[i - 1]) * ysq;
}
*result = x * (xnum + a[3]) / (xden + b[3]);
if (jint != 0) {
*result = one - *result;
}
if (jint == 2) {
*result = exp(ysq) * *result;
}
return;
/* ------------------------------------------------------------------ */
/* Evaluate erfc for 0.46875 <= |X| <= 4.0 */
/* ------------------------------------------------------------------ */
}
else if (y <= four) {
xnum = c[8] * y;
xden = y;
for (i = 1; i <= 7; ++i) {
xnum = (xnum + c[i - 1]) * y;
xden = (xden + d[i - 1]) * y;
}
*result = (xnum + c[7]) / (xden + d[7]);
if (jint != 2) {
ysq = floor(y * sixten) / sixten;
del = (y - ysq) * (y + ysq);
*result = exp(-ysq * ysq) * exp(-del) * *result;
}
/* ------------------------------------------------------------------ */
/* Evaluate erfc for |X| > 4.0 */
/* ------------------------------------------------------------------ */
}
else {
*result = zero;
if (y >= xbig) {
if (jint != 2 || y >= xmax) {
goto L300;
}
if (y >= xhuge) {
*result = sqrpi / y;
goto L300;
}
}
ysq = one / (y * y);
xnum = p[5] * ysq;
xden = ysq;
for (i = 1; i <= 4; ++i) {
xnum = (xnum + p[i - 1]) * ysq;
xden = (xden + q[i - 1]) * ysq;
}
*result = ysq * (xnum + p[4]) / (xden + q[4]);
*result = (sqrpi - *result) / y;
if (jint != 2) {
ysq = floor(y * sixten) / sixten;
del = (y - ysq) * (y + ysq);
*result = exp(-ysq * ysq) * exp(-del) * *result;
}
}
/* ------------------------------------------------------------------ */
/* Fix up for negative argument, erf, etc. */
/* ------------------------------------------------------------------ */
L300:
if (jint == 0) {
*result = half - *result + half;
if (x < zero) {
*result = -(*result);
}
}
else if (jint == 1) {
if (x < zero) {
*result = two - *result;
}
}
else {
if (x < zero) {
if (x < xneg) {
*result = xinf;
}
else {
ysq = -floor(-(x * sixten)) / sixten;
del = (x - ysq) * (x + ysq);
y = exp(ysq * ysq) * exp(del);
*result = y + y - *result;
}
}
}
return;
}
#ifdef DEBUG
double derf_ P1C(double *, x)
{
int jint;
double result;
/* This subprogram computes approximate values for erf(x). */
/* (see comments heading CALERF). */
/* Author/date: W. J. Cody, January 8, 1985 */
jint = 0;
calerf(*x, &result, jint);
return result;
}
double derfc_ P1C(double *, x)
{
int jint;
double result;
/* This subprogram computes approximate values for erfc(x). */
/* (see comments heading CALERF). */
/* Author/date: W. J. Cody, January 8, 1985 */
jint = 1;
calerf(*x, &result, jint);
return result;
}
double derfcx_ (double *, x)
{
int jint;
double result;
/* This subprogram computes approximate values for exp(x*x) * erfc(x). */
/* (see comments heading CALERF). */
/* Author/date: W. J. Cody, March 30, 1987 */
jint = 2;
calerf(*x, &result, jint);
return result;
}
#endif /* DEBUG */
#define SQRT2 1.414213562373095049
VOID normbase P2C(double *, x, double *, phi)
{
double y;
y = *x / SQRT2;
if (y < 0) {
calerf(-y, phi, 1);
*phi = 0.5 * *phi;
}
else {
calerf(y, phi, 1);
*phi = 1.0 - 0.5 * *phi;
}
}
|