/* monotl.c Floating point function test vectors for real functions of two variables..
Arguments and function values are synthesized for NPTS points in the vicinity of each given tabulated test point. The points are chosen to be near and on either side of the likely function algorithm domain boundaries. Since the function programs change their methods at these points, major coding errors or monotonicity failures might be detected.
August, 1998
S. L. Moshier */
/* Unit of error tolerance in test[i].thresh. */ staticlongdouble MACHEPL =
5.42101086242752217003726400434970855712890625E-20L; /* How many times the above error to allow before printing a complaint.
If TOL < 0, consider absolute error instead of relative error. */ #define TOL 8 /* Number of test points to generate on each side of tabulated point. */ #define NPTS 10
#include <stdio.h>
/* Avoid including math.h. */ longdouble frexpl (longdouble, int *); longdouble ldexpl (longdouble, int); longdouble fabsl (longdouble);
/* Power function, a = x^y, da/dx = y x^(y-1), da/dy = x^y ln(x). */ longdouble powl (longdouble, longdouble); /* Arctan, a=atan(y,x), da/dx = -y/(z x^2), da/dy = 1/(z x), z = (y/x)^2 + 1 */ longdouble atan2l (longdouble, longdouble);
/* Data structure of the test parameters. */ struct oneargument
{ char *name; /* Name of the function. */ longdouble (*func) (longdouble, longdouble); /* Function call. */ longdouble argx; /* Function argument, assumed exact. */ longdouble argy; /* Function argument, assumed exact. */ longdouble answer1; /* Exact number, close to function value. */ longdouble answer2; /* answer1 + answer2 has extended precision. */ longdouble derivx; /* da/dx evaluated at x = argx, y = argy. */ longdouble derivy; /* da/dy evaluated at x = argx, y = argy. */ /* Error report threshold. 2 => 1 ulp approximately
if thresh < 0 then consider absolute error instead of relative error. */ int thresh;
};
/* Return the next nearest floating point value to X in the direction of UPDOWN (+1 or -1).
(Might fail if X is denormalized.) */
longdouble
nextval (x, updown) longdouble x; int updown;
{ longdouble m; int i;
volat1 = x;
m = 0.25L * MACHEPL * volat1 * updown;
volat2 = volat1 + m; if (volat2 != volat1)
printf ("successor failed\n");
for (i = 2; i < 10; i++)
{
volat2 = volat1 + i * m; if (volat1 != volat2) return volat2;
}
printf ("nextval failed\n"); return volat1;
}
int
main ()
{ longdouble (*fun1) (longdouble, longdouble); int i, jx, jy, errs, tests, err_thresh; int idir, direction, itest; longdouble x, x0, dx, y, y0, dy, a, da, err;
errs = 0;
tests = 0;
itest = 0;
for (;;)
{ /* Function call reference. */
fun1 = test1[itest].func; if (fun1 == NULL) break;
/* Make lookup tables of all x arguments and all y arguments to be used. The arguments scan from slightly below to slightly
above x0 and y0. */ for (idir = 0; idir < 2; idir++)
{ if (idir == 0)
direction = 1; else
direction = -1;
volat1 = test1[itest].argx;
x0 = volat1;
x = volat1;
argsx[NPTS] = x0;
volat1 = test1[itest].argy;
y0 = volat1;
y = volat1;
argsy[NPTS] = y0; for (i = 1; i <= NPTS; i++)
{
x = nextval (x, direction);
argsx[NPTS + i * direction] = x;
y = nextval (y, direction);
argsy[NPTS + i * direction] = y;
}
}
/* Test at all points (x,y) in the lookup tables. */ for (jx = 0; jx <= 2*NPTS; jx++)
{ /* delta x */
x = argsx[jx];
volat1 = x - x0;
dx = volat1; for (jy = 0; jy <= 2*NPTS; jy++)
{ /* delta y */
y = argsy[jy];
volat1 = y - y0;
dy = volat1; /* Estimated delta answer */
da = dx * test1[itest].derivx + dy * test1[itest].derivy; /* a + delta a */
a = test1[itest].answer2 + da;
volat1 = test1[itest].answer1 + a;
a = volat1; /* Run the function under test. */
volat2 = (*(fun1)) (x, y); if (volat2 != volat1)
{ /* Estimate difference between program result
and extended precision function value. */
err = volat2 - test1[itest].answer1;
err = err - (test1[itest].answer2 + da); /* Compare difference with reporting threshold. */
err_thresh = test1[itest].thresh; if (err_thresh >= 0)
err = err / volat1; /* relative error */ else
{
err_thresh = -err_thresh; /* absolute error */ /* ...but relative error if function value > 1 */ if (fabsl(volat1) > 1.0L)
err = err / volat1;
} if (fabsl (err) > (err_thresh * MACHEPL))
{
printf ("%s(%.20Le, %.20Le)\n", test1[itest].name, x, y);
printf (" = %.20Le, s.b. %.20Le, %.3Le\n",
volat2, volat1, err);
errs += 1;
}
}
tests += 1;
}
}
itest += 1;
}
printf ("%d errors in %d tests\n", errs, tests); exit (0);
}
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.