diff options
Diffstat (limited to 'tools/regression')
-rw-r--r-- | tools/regression/lib/msun/Makefile | 2 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-cexp.c | 213 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-conj.c | 23 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-csqrt.c | 102 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-ctrig.c | 285 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-exponential.c | 16 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-fma.c | 27 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-fmaxmin.c | 16 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-invctrig.c | 78 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-invtrig.c | 38 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-logarithm.c | 16 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-nearbyint.c | 26 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-next.c | 6 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-trig.c | 18 | ||||
-rw-r--r-- | tools/regression/lib/msun/test-utils.h | 174 |
15 files changed, 412 insertions, 628 deletions
diff --git a/tools/regression/lib/msun/Makefile b/tools/regression/lib/msun/Makefile index 9559bb175b2e..dbf582fadb8d 100644 --- a/tools/regression/lib/msun/Makefile +++ b/tools/regression/lib/msun/Makefile @@ -5,7 +5,7 @@ TESTS= test-cexp test-conj test-csqrt test-ctrig \ test-fmaxmin test-ilogb test-invtrig test-invctrig \ test-logarithm test-lrint \ test-lround test-nan test-nearbyint test-next test-rem test-trig -CFLAGS+= -O0 -lm +CFLAGS+= -O0 -lm -Wno-unknown-pragmas .PHONY: tests tests: ${TESTS} diff --git a/tools/regression/lib/msun/test-cexp.c b/tools/regression/lib/msun/test-cexp.c index 51e91444847c..78c3f1a32044 100644 --- a/tools/regression/lib/msun/test-cexp.c +++ b/tools/regression/lib/msun/test-cexp.c @@ -38,11 +38,7 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) -#define FLT_ULP() ldexpl(1.0, 1 - FLT_MANT_DIG) -#define DBL_ULP() ldexpl(1.0, 1 - DBL_MANT_DIG) -#define LDBL_ULP() ldexpl(1.0, 1 - LDBL_MANT_DIG) +#include "test-utils.h" #define N(i) (sizeof(i) / sizeof((i)[0])) @@ -50,23 +46,6 @@ __FBSDID("$FreeBSD$"); #pragma STDC CX_LIMITED_RANGE OFF /* - * XXX gcc implements complex multiplication incorrectly. In - * particular, it implements it as if the CX_LIMITED_RANGE pragma - * were ON. Consequently, we need this function to form numbers - * such as x + INFINITY * I, since gcc evalutes INFINITY * I as - * NaN + INFINITY * I. - */ -static inline long double complex -cpackl(long double x, long double y) -{ - long double complex z; - - __real__ z = x; - __imag__ z = y; - return (z); -} - -/* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several @@ -83,14 +62,15 @@ cpackl(long double x, long double y) #define test(func, z, result, exceptmask, excepts, checksign) do { \ volatile long double complex _d = z; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(cfpequal((func)(_d), (result), (checksign))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(cfpequal_cs((func)(_d), (result), (checksign))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* Test within a given tolerance. */ #define test_tol(func, z, result, tol) do { \ volatile long double complex _d = z; \ - assert(cfpequal_tol((func)(_d), (result), (tol))); \ + assert(cfpequal_tol((func)(_d), (result), (tol), \ + FPE_ABS_ZERO | CS_BOTH)); \ } while (0) /* Test all the functions that compute cexp(x). */ @@ -112,67 +92,6 @@ cpackl(long double x, long double y) static const float finites[] = { -42.0e20, -1.0, -1.0e-10, -0.0, 0.0, 1.0e-10, 1.0, 42.0e20 }; -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - * If checksign is 0, we compare the absolute values instead. - */ -static int -fpequal(long double x, long double y, int checksign) -{ - if (isnan(x) || isnan(y)) - return (1); - if (checksign) - return (x == y && !signbit(x) == !signbit(y)); - else - return (fabsl(x) == fabsl(y)); -} - -static int -fpequal_tol(long double x, long double y, long double tol) -{ - fenv_t env; - int ret; - - if (isnan(x) && isnan(y)) - return (1); - if (!signbit(x) != !signbit(y)) - return (0); - if (x == y) - return (1); - if (tol == 0) - return (0); - - /* Hard case: need to check the tolerance. */ - feholdexcept(&env); - /* - * For our purposes here, if y=0, we interpret tol as an absolute - * tolerance. This is to account for roundoff in the input, e.g., - * cos(Pi/2) ~= 0. - */ - if (y == 0.0) - ret = fabsl(x - y) <= fabsl(tol); - else - ret = fabsl(x - y) <= fabsl(y * tol); - fesetenv(&env); - return (ret); -} - -static int -cfpequal(long double complex x, long double complex y, int checksign) -{ - return (fpequal(creal(x), creal(y), checksign) - && fpequal(cimag(x), cimag(y), checksign)); -} - -static int -cfpequal_tol(long double complex x, long double complex y, long double tol) -{ - return (fpequal_tol(creal(x), creal(y), tol) - && fpequal_tol(cimag(x), cimag(y), tol)); -} - /* Tests for 0 */ void @@ -182,8 +101,8 @@ test_zero(void) /* cexp(0) = 1, no exceptions raised */ testall(0.0, 1.0, ALL_STD_EXCEPT, 0, 1); testall(-0.0, 1.0, ALL_STD_EXCEPT, 0, 1); - testall(cpackl(0.0, -0.0), cpackl(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); - testall(cpackl(-0.0, -0.0), cpackl(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); + testall(CMPLXL(0.0, -0.0), CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); + testall(CMPLXL(-0.0, -0.0), CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); } /* @@ -198,27 +117,27 @@ test_nan() /* cexp(x + NaNi) = NaN + NaNi and optionally raises invalid */ /* cexp(NaN + yi) = NaN + NaNi and optionally raises invalid (|y|>0) */ for (i = 0; i < N(finites); i++) { - testall(cpackl(finites[i], NAN), cpackl(NAN, NAN), + testall(CMPLXL(finites[i], NAN), CMPLXL(NAN, NAN), ALL_STD_EXCEPT & ~FE_INVALID, 0, 0); if (finites[i] == 0.0) continue; /* XXX FE_INEXACT shouldn't be raised here */ - testall(cpackl(NAN, finites[i]), cpackl(NAN, NAN), + testall(CMPLXL(NAN, finites[i]), CMPLXL(NAN, NAN), ALL_STD_EXCEPT & ~(FE_INVALID | FE_INEXACT), 0, 0); } /* cexp(NaN +- 0i) = NaN +- 0i */ - testall(cpackl(NAN, 0.0), cpackl(NAN, 0.0), ALL_STD_EXCEPT, 0, 1); - testall(cpackl(NAN, -0.0), cpackl(NAN, -0.0), ALL_STD_EXCEPT, 0, 1); + testall(CMPLXL(NAN, 0.0), CMPLXL(NAN, 0.0), ALL_STD_EXCEPT, 0, 1); + testall(CMPLXL(NAN, -0.0), CMPLXL(NAN, -0.0), ALL_STD_EXCEPT, 0, 1); /* cexp(inf + NaN i) = inf + nan i */ - testall(cpackl(INFINITY, NAN), cpackl(INFINITY, NAN), + testall(CMPLXL(INFINITY, NAN), CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); /* cexp(-inf + NaN i) = 0 */ - testall(cpackl(-INFINITY, NAN), cpackl(0.0, 0.0), + testall(CMPLXL(-INFINITY, NAN), CMPLXL(0.0, 0.0), ALL_STD_EXCEPT, 0, 0); /* cexp(NaN + NaN i) = NaN + NaN i */ - testall(cpackl(NAN, NAN), cpackl(NAN, NAN), + testall(CMPLXL(NAN, NAN), CMPLXL(NAN, NAN), ALL_STD_EXCEPT, 0, 0); } @@ -229,37 +148,37 @@ test_inf(void) /* cexp(x + inf i) = NaN + NaNi and raises invalid */ for (i = 0; i < N(finites); i++) { - testall(cpackl(finites[i], INFINITY), cpackl(NAN, NAN), + testall(CMPLXL(finites[i], INFINITY), CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 1); } /* cexp(-inf + yi) = 0 * (cos(y) + sin(y)i) */ /* XXX shouldn't raise an inexact exception */ - testall(cpackl(-INFINITY, M_PI_4), cpackl(0.0, 0.0), + testall(CMPLXL(-INFINITY, M_PI_4), CMPLXL(0.0, 0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - testall(cpackl(-INFINITY, 3 * M_PI_4), cpackl(-0.0, 0.0), + testall(CMPLXL(-INFINITY, 3 * M_PI_4), CMPLXL(-0.0, 0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - testall(cpackl(-INFINITY, 5 * M_PI_4), cpackl(-0.0, -0.0), + testall(CMPLXL(-INFINITY, 5 * M_PI_4), CMPLXL(-0.0, -0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - testall(cpackl(-INFINITY, 7 * M_PI_4), cpackl(0.0, -0.0), + testall(CMPLXL(-INFINITY, 7 * M_PI_4), CMPLXL(0.0, -0.0), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - testall(cpackl(-INFINITY, 0.0), cpackl(0.0, 0.0), + testall(CMPLXL(-INFINITY, 0.0), CMPLXL(0.0, 0.0), ALL_STD_EXCEPT, 0, 1); - testall(cpackl(-INFINITY, -0.0), cpackl(0.0, -0.0), + testall(CMPLXL(-INFINITY, -0.0), CMPLXL(0.0, -0.0), ALL_STD_EXCEPT, 0, 1); /* cexp(inf + yi) = inf * (cos(y) + sin(y)i) (except y=0) */ /* XXX shouldn't raise an inexact exception */ - testall(cpackl(INFINITY, M_PI_4), cpackl(INFINITY, INFINITY), + testall(CMPLXL(INFINITY, M_PI_4), CMPLXL(INFINITY, INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - testall(cpackl(INFINITY, 3 * M_PI_4), cpackl(-INFINITY, INFINITY), + testall(CMPLXL(INFINITY, 3 * M_PI_4), CMPLXL(-INFINITY, INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - testall(cpackl(INFINITY, 5 * M_PI_4), cpackl(-INFINITY, -INFINITY), + testall(CMPLXL(INFINITY, 5 * M_PI_4), CMPLXL(-INFINITY, -INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - testall(cpackl(INFINITY, 7 * M_PI_4), cpackl(INFINITY, -INFINITY), + testall(CMPLXL(INFINITY, 7 * M_PI_4), CMPLXL(INFINITY, -INFINITY), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); /* cexp(inf + 0i) = inf + 0i */ - testall(cpackl(INFINITY, 0.0), cpackl(INFINITY, 0.0), + testall(CMPLXL(INFINITY, 0.0), CMPLXL(INFINITY, 0.0), ALL_STD_EXCEPT, 0, 1); - testall(cpackl(INFINITY, -0.0), cpackl(INFINITY, -0.0), + testall(CMPLXL(INFINITY, -0.0), CMPLXL(INFINITY, -0.0), ALL_STD_EXCEPT, 0, 1); } @@ -270,17 +189,17 @@ test_reals(void) for (i = 0; i < N(finites); i++) { /* XXX could check exceptions more meticulously */ - test(cexp, cpackl(finites[i], 0.0), - cpackl(exp(finites[i]), 0.0), + test(cexp, CMPLXL(finites[i], 0.0), + CMPLXL(exp(finites[i]), 0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); - test(cexp, cpackl(finites[i], -0.0), - cpackl(exp(finites[i]), -0.0), + test(cexp, CMPLXL(finites[i], -0.0), + CMPLXL(exp(finites[i]), -0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); - test(cexpf, cpackl(finites[i], 0.0), - cpackl(expf(finites[i]), 0.0), + test(cexpf, CMPLXL(finites[i], 0.0), + CMPLXL(expf(finites[i]), 0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); - test(cexpf, cpackl(finites[i], -0.0), - cpackl(expf(finites[i]), -0.0), + test(cexpf, CMPLXL(finites[i], -0.0), + CMPLXL(expf(finites[i]), -0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); } } @@ -291,17 +210,17 @@ test_imaginaries(void) int i; for (i = 0; i < N(finites); i++) { - test(cexp, cpackl(0.0, finites[i]), - cpackl(cos(finites[i]), sin(finites[i])), + test(cexp, CMPLXL(0.0, finites[i]), + CMPLXL(cos(finites[i]), sin(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - test(cexp, cpackl(-0.0, finites[i]), - cpackl(cos(finites[i]), sin(finites[i])), + test(cexp, CMPLXL(-0.0, finites[i]), + CMPLXL(cos(finites[i]), sin(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - test(cexpf, cpackl(0.0, finites[i]), - cpackl(cosf(finites[i]), sinf(finites[i])), + test(cexpf, CMPLXL(0.0, finites[i]), + CMPLXL(cosf(finites[i]), sinf(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - test(cexpf, cpackl(-0.0, finites[i]), - cpackl(cosf(finites[i]), sinf(finites[i])), + test(cexpf, CMPLXL(-0.0, finites[i]), + CMPLXL(cosf(finites[i]), sinf(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); } } @@ -326,12 +245,12 @@ test_small(void) b = tests[i + 1]; x = tests[i + 2]; y = tests[i + 3]; - test_tol(cexp, cpackl(a, b), cpackl(x, y), 3 * DBL_ULP()); + test_tol(cexp, CMPLXL(a, b), CMPLXL(x, y), 3 * DBL_ULP()); /* float doesn't have enough precision to pass these tests */ if (x == 0 || y == 0) continue; - test_tol(cexpf, cpackl(a, b), cpackl(x, y), 1 * FLT_ULP()); + test_tol(cexpf, CMPLXL(a, b), CMPLXL(x, y), 1 * FLT_ULP()); } } @@ -340,27 +259,27 @@ void test_large(void) { - test_tol(cexp, cpackl(709.79, 0x1p-1074), - cpackl(INFINITY, 8.94674309915433533273e-16), DBL_ULP()); - test_tol(cexp, cpackl(1000, 0x1p-1074), - cpackl(INFINITY, 9.73344457300016401328e+110), DBL_ULP()); - test_tol(cexp, cpackl(1400, 0x1p-1074), - cpackl(INFINITY, 5.08228858149196559681e+284), DBL_ULP()); - test_tol(cexp, cpackl(900, 0x1.23456789abcdep-1020), - cpackl(INFINITY, 7.42156649354218408074e+83), DBL_ULP()); - test_tol(cexp, cpackl(1300, 0x1.23456789abcdep-1020), - cpackl(INFINITY, 3.87514844965996756704e+257), DBL_ULP()); - - test_tol(cexpf, cpackl(88.73, 0x1p-149), - cpackl(INFINITY, 4.80265603e-07), 2 * FLT_ULP()); - test_tol(cexpf, cpackl(90, 0x1p-149), - cpackl(INFINITY, 1.7101492622e-06f), 2 * FLT_ULP()); - test_tol(cexpf, cpackl(192, 0x1p-149), - cpackl(INFINITY, 3.396809344e+38f), 2 * FLT_ULP()); - test_tol(cexpf, cpackl(120, 0x1.234568p-120), - cpackl(INFINITY, 1.1163382522e+16f), 2 * FLT_ULP()); - test_tol(cexpf, cpackl(170, 0x1.234568p-120), - cpackl(INFINITY, 5.7878851079e+37f), 2 * FLT_ULP()); + test_tol(cexp, CMPLXL(709.79, 0x1p-1074), + CMPLXL(INFINITY, 8.94674309915433533273e-16), DBL_ULP()); + test_tol(cexp, CMPLXL(1000, 0x1p-1074), + CMPLXL(INFINITY, 9.73344457300016401328e+110), DBL_ULP()); + test_tol(cexp, CMPLXL(1400, 0x1p-1074), + CMPLXL(INFINITY, 5.08228858149196559681e+284), DBL_ULP()); + test_tol(cexp, CMPLXL(900, 0x1.23456789abcdep-1020), + CMPLXL(INFINITY, 7.42156649354218408074e+83), DBL_ULP()); + test_tol(cexp, CMPLXL(1300, 0x1.23456789abcdep-1020), + CMPLXL(INFINITY, 3.87514844965996756704e+257), DBL_ULP()); + + test_tol(cexpf, CMPLXL(88.73, 0x1p-149), + CMPLXL(INFINITY, 4.80265603e-07), 2 * FLT_ULP()); + test_tol(cexpf, CMPLXL(90, 0x1p-149), + CMPLXL(INFINITY, 1.7101492622e-06f), 2 * FLT_ULP()); + test_tol(cexpf, CMPLXL(192, 0x1p-149), + CMPLXL(INFINITY, 3.396809344e+38f), 2 * FLT_ULP()); + test_tol(cexpf, CMPLXL(120, 0x1.234568p-120), + CMPLXL(INFINITY, 1.1163382522e+16f), 2 * FLT_ULP()); + test_tol(cexpf, CMPLXL(170, 0x1.234568p-120), + CMPLXL(INFINITY, 5.7878851079e+37f), 2 * FLT_ULP()); } int diff --git a/tools/regression/lib/msun/test-conj.c b/tools/regression/lib/msun/test-conj.c index 909e810802e9..c261f60160b7 100644 --- a/tools/regression/lib/msun/test-conj.c +++ b/tools/regression/lib/msun/test-conj.c @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> +#include "test-utils.h" + #pragma STDC CX_LIMITED_RANGE off /* Make sure gcc doesn't use builtin versions of these or honor __pure2. */ @@ -50,27 +52,6 @@ static float (*libcimagf)(float complex) = cimagf; static double (*libcimag)(double complex) = cimag; static long double (*libcimagl)(long double complex) = cimagl; -/* - * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. - * Fail an assertion if they differ. - */ -static int -fpequal(long double d1, long double d2) -{ - - if (d1 != d2) - return (isnan(d1) && isnan(d2)); - return (copysignl(1.0, d1) == copysignl(1.0, d2)); -} - -static int -cfpequal(long double complex d1, long double complex d2) -{ - - return (fpequal(creall(d1), creall(d2)) && - fpequal(cimagl(d1), cimagl(d2))); -} - static const double tests[] = { /* a + bI */ 0.0, 0.0, diff --git a/tools/regression/lib/msun/test-csqrt.c b/tools/regression/lib/msun/test-csqrt.c index 9877b9d07d66..39176eb68e51 100644 --- a/tools/regression/lib/msun/test-csqrt.c +++ b/tools/regression/lib/msun/test-csqrt.c @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> +#include "test-utils.h" + #define N(i) (sizeof(i) / sizeof((i)[0])) /* @@ -63,23 +65,6 @@ _csqrt(long double complex d) #pragma STDC CX_LIMITED_RANGE off /* - * XXX gcc implements complex multiplication incorrectly. In - * particular, it implements it as if the CX_LIMITED_RANGE pragma - * were ON. Consequently, we need this function to form numbers - * such as x + INFINITY * I, since gcc evalutes INFINITY * I as - * NaN + INFINITY * I. - */ -static inline long double complex -cpackl(long double x, long double y) -{ - long double complex z; - - __real__ z = x; - __imag__ z = y; - return (z); -} - -/* * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. * Fail an assertion if they differ. */ @@ -87,20 +72,7 @@ static void assert_equal(long double complex d1, long double complex d2) { - if (isnan(creall(d1))) { - assert(isnan(creall(d2))); - } else { - assert(creall(d1) == creall(d2)); - assert(copysignl(1.0, creall(d1)) == - copysignl(1.0, creall(d2))); - } - if (isnan(cimagl(d1))) { - assert(isnan(cimagl(d2))); - } else { - assert(cimagl(d1) == cimagl(d2)); - assert(copysignl(1.0, cimagl(d1)) == - copysignl(1.0, cimagl(d2))); - } + assert(cfpequal(d1, d2)); } /* @@ -161,7 +133,7 @@ test_finite() b = tests[i + 1] * mults[j] * mults[j]; x = tests[i + 2] * mults[j]; y = tests[i + 3] * mults[j]; - assert(t_csqrt(cpackl(a, b)) == cpackl(x, y)); + assert(t_csqrt(CMPLXL(a, b)) == CMPLXL(x, y)); } } @@ -174,10 +146,10 @@ static void test_zeros() { - assert_equal(t_csqrt(cpackl(0.0, 0.0)), cpackl(0.0, 0.0)); - assert_equal(t_csqrt(cpackl(-0.0, 0.0)), cpackl(0.0, 0.0)); - assert_equal(t_csqrt(cpackl(0.0, -0.0)), cpackl(0.0, -0.0)); - assert_equal(t_csqrt(cpackl(-0.0, -0.0)), cpackl(0.0, -0.0)); + assert_equal(t_csqrt(CMPLXL(0.0, 0.0)), CMPLXL(0.0, 0.0)); + assert_equal(t_csqrt(CMPLXL(-0.0, 0.0)), CMPLXL(0.0, 0.0)); + assert_equal(t_csqrt(CMPLXL(0.0, -0.0)), CMPLXL(0.0, -0.0)); + assert_equal(t_csqrt(CMPLXL(-0.0, -0.0)), CMPLXL(0.0, -0.0)); } /* @@ -199,15 +171,15 @@ test_infinities() for (i = 0; i < N(vals); i++) { if (isfinite(vals[i])) { - assert_equal(t_csqrt(cpackl(-INFINITY, vals[i])), - cpackl(0.0, copysignl(INFINITY, vals[i]))); - assert_equal(t_csqrt(cpackl(INFINITY, vals[i])), - cpackl(INFINITY, copysignl(0.0, vals[i]))); + assert_equal(t_csqrt(CMPLXL(-INFINITY, vals[i])), + CMPLXL(0.0, copysignl(INFINITY, vals[i]))); + assert_equal(t_csqrt(CMPLXL(INFINITY, vals[i])), + CMPLXL(INFINITY, copysignl(0.0, vals[i]))); } - assert_equal(t_csqrt(cpackl(vals[i], INFINITY)), - cpackl(INFINITY, INFINITY)); - assert_equal(t_csqrt(cpackl(vals[i], -INFINITY)), - cpackl(INFINITY, -INFINITY)); + assert_equal(t_csqrt(CMPLXL(vals[i], INFINITY)), + CMPLXL(INFINITY, INFINITY)); + assert_equal(t_csqrt(CMPLXL(vals[i], -INFINITY)), + CMPLXL(INFINITY, -INFINITY)); } } @@ -218,26 +190,26 @@ static void test_nans() { - assert(creall(t_csqrt(cpackl(INFINITY, NAN))) == INFINITY); - assert(isnan(cimagl(t_csqrt(cpackl(INFINITY, NAN))))); - - assert(isnan(creall(t_csqrt(cpackl(-INFINITY, NAN))))); - assert(isinf(cimagl(t_csqrt(cpackl(-INFINITY, NAN))))); - - assert_equal(t_csqrt(cpackl(NAN, INFINITY)), - cpackl(INFINITY, INFINITY)); - assert_equal(t_csqrt(cpackl(NAN, -INFINITY)), - cpackl(INFINITY, -INFINITY)); - - assert_equal(t_csqrt(cpackl(0.0, NAN)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(-0.0, NAN)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(42.0, NAN)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(-42.0, NAN)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(NAN, 0.0)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(NAN, -0.0)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(NAN, 42.0)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(NAN, -42.0)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(NAN, NAN)), cpackl(NAN, NAN)); + assert(creall(t_csqrt(CMPLXL(INFINITY, NAN))) == INFINITY); + assert(isnan(cimagl(t_csqrt(CMPLXL(INFINITY, NAN))))); + + assert(isnan(creall(t_csqrt(CMPLXL(-INFINITY, NAN))))); + assert(isinf(cimagl(t_csqrt(CMPLXL(-INFINITY, NAN))))); + + assert_equal(t_csqrt(CMPLXL(NAN, INFINITY)), + CMPLXL(INFINITY, INFINITY)); + assert_equal(t_csqrt(CMPLXL(NAN, -INFINITY)), + CMPLXL(INFINITY, -INFINITY)); + + assert_equal(t_csqrt(CMPLXL(0.0, NAN)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(-0.0, NAN)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(42.0, NAN)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(-42.0, NAN)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(NAN, 0.0)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(NAN, -0.0)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(NAN, 42.0)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(NAN, -42.0)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(NAN, NAN)), CMPLXL(NAN, NAN)); } /* @@ -254,7 +226,7 @@ test_overflow(int maxexp) a = ldexpl(115 * 0x1p-8, maxexp); b = ldexpl(252 * 0x1p-8, maxexp); - result = t_csqrt(cpackl(a, b)); + result = t_csqrt(CMPLXL(a, b)); assert(creall(result) == ldexpl(14 * 0x1p-4, maxexp / 2)); assert(cimagl(result) == ldexpl(9 * 0x1p-4, maxexp / 2)); } diff --git a/tools/regression/lib/msun/test-ctrig.c b/tools/regression/lib/msun/test-ctrig.c index ed7866184304..e12bb48c91b1 100644 --- a/tools/regression/lib/msun/test-ctrig.c +++ b/tools/regression/lib/msun/test-ctrig.c @@ -38,46 +38,12 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) -#define OPT_INVALID (ALL_STD_EXCEPT & ~FE_INVALID) -#define OPT_INEXACT (ALL_STD_EXCEPT & ~FE_INEXACT) -#define FLT_ULP() ldexpl(1.0, 1 - FLT_MANT_DIG) -#define DBL_ULP() ldexpl(1.0, 1 - DBL_MANT_DIG) -#define LDBL_ULP() ldexpl(1.0, 1 - LDBL_MANT_DIG) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON #pragma STDC CX_LIMITED_RANGE OFF /* - * XXX gcc implements complex multiplication incorrectly. In - * particular, it implements it as if the CX_LIMITED_RANGE pragma - * were ON. Consequently, we need this function to form numbers - * such as x + INFINITY * I, since gcc evalutes INFINITY * I as - * NaN + INFINITY * I. - */ -static inline long double complex -cpackl(long double x, long double y) -{ - long double complex z; - - __real__ z = x; - __imag__ z = y; - return (z); -} - -/* Flags that determine whether to check the signs of the result. */ -#define CS_REAL 1 -#define CS_IMAG 2 -#define CS_BOTH (CS_REAL | CS_IMAG) - -#ifdef DEBUG -#define debug(...) printf(__VA_ARGS__) -#else -#define debug(...) (void)0 -#endif - -/* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several @@ -95,8 +61,8 @@ cpackl(long double x, long double y) debug(" testing %s(%Lg + %Lg I) == %Lg + %Lg I\n", #func, \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(cfpequal((func)(_d), (result), (checksign))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(cfpequal_cs((func)(_d), (result), (checksign))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* @@ -108,7 +74,7 @@ cpackl(long double x, long double y) volatile long double complex _d = z; \ debug(" testing %s(%Lg + %Lg I) ~= %Lg + %Lg I\n", #func, \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \ - assert(cfpequal_tol((func)(_d), (result), (tol))); \ + assert(cfpequal_tol((func)(_d), (result), (tol), FPE_ABS_ZERO)); \ } while (0) /* These wrappers apply the identities f(conj(z)) = conj(f(z)). */ @@ -152,79 +118,18 @@ cpackl(long double x, long double y) test_tol(func, -x, result, tol * DBL_ULP()); \ } while (0) -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - * If checksign is 0, we compare the absolute values instead. - */ -static int -fpequal(long double x, long double y, int checksign) -{ - if (isnan(x) && isnan(y)) - return (1); - if (checksign) - return (x == y && !signbit(x) == !signbit(y)); - else - return (fabsl(x) == fabsl(y)); -} - -static int -fpequal_tol(long double x, long double y, long double tol) -{ - fenv_t env; - int ret; - - if (isnan(x) && isnan(y)) - return (1); - if (!signbit(x) != !signbit(y) && tol == 0) - return (0); - if (x == y) - return (1); - if (tol == 0) - return (0); - - /* Hard case: need to check the tolerance. */ - feholdexcept(&env); - /* - * For our purposes here, if y=0, we interpret tol as an absolute - * tolerance. This is to account for roundoff in the input, e.g., - * cos(Pi/2) ~= 0. - */ - if (y == 0.0) - ret = fabsl(x - y) <= fabsl(tol); - else - ret = fabsl(x - y) <= fabsl(y * tol); - fesetenv(&env); - return (ret); -} - -static int -cfpequal(long double complex x, long double complex y, int checksign) -{ - return (fpequal(creal(x), creal(y), checksign & CS_REAL) - && fpequal(cimag(x), cimag(y), checksign & CS_IMAG)); -} - -static int -cfpequal_tol(long double complex x, long double complex y, long double tol) -{ - return (fpequal_tol(creal(x), creal(y), tol) - && fpequal_tol(cimag(x), cimag(y), tol)); -} - /* Tests for 0 */ void test_zero(void) { - long double complex zero = cpackl(0.0, 0.0); + long double complex zero = CMPLXL(0.0, 0.0); /* csinh(0) = ctanh(0) = 0; ccosh(0) = 1 (no exceptions raised) */ testall_odd(csinh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(csin, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_even(ccosh, zero, 1.0, ALL_STD_EXCEPT, 0, CS_BOTH); - testall_even(ccos, zero, cpackl(1.0, -0.0), ALL_STD_EXCEPT, 0, CS_BOTH); + testall_even(ccos, zero, CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(ctanh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(ctan, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); } @@ -235,7 +140,7 @@ test_zero(void) void test_nan() { - long double complex nan_nan = cpackl(NAN, NAN); + long double complex nan_nan = CMPLXL(NAN, NAN); long double complex z; /* @@ -256,7 +161,7 @@ test_nan() testall_even(ccos, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall_odd(ctan, z, nan_nan, ALL_STD_EXCEPT, 0, 0); - z = cpackl(42, NAN); + z = CMPLXL(42, NAN); testall_odd(csinh, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccosh, z, nan_nan, OPT_INVALID, 0, 0); /* XXX We allow a spurious inexact exception here. */ @@ -265,7 +170,7 @@ test_nan() testall_even(ccos, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctan, z, nan_nan, OPT_INVALID, 0, 0); - z = cpackl(NAN, 42); + z = CMPLXL(NAN, 42); testall_odd(csinh, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccosh, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctanh, z, nan_nan, OPT_INVALID, 0, 0); @@ -274,38 +179,38 @@ test_nan() /* XXX We allow a spurious inexact exception here. */ testall_odd(ctan, z, nan_nan, OPT_INVALID & ~FE_INEXACT, 0, 0); - z = cpackl(NAN, INFINITY); + z = CMPLXL(NAN, INFINITY); testall_odd(csinh, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccosh, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctanh, z, nan_nan, OPT_INVALID, 0, 0); - testall_odd(csin, z, cpackl(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); - testall_even(ccos, z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, + testall_odd(csin, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); + testall_even(ccos, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_IMAG); - testall_odd(ctan, z, cpackl(0, 1), ALL_STD_EXCEPT, 0, CS_IMAG); + testall_odd(ctan, z, CMPLXL(0, 1), ALL_STD_EXCEPT, 0, CS_IMAG); - z = cpackl(INFINITY, NAN); - testall_odd(csinh, z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); - testall_even(ccosh, z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, + z = CMPLXL(INFINITY, NAN); + testall_odd(csinh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); + testall_even(ccosh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); - testall_odd(ctanh, z, cpackl(1, 0), ALL_STD_EXCEPT, 0, CS_REAL); + testall_odd(ctanh, z, CMPLXL(1, 0), ALL_STD_EXCEPT, 0, CS_REAL); testall_odd(csin, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccos, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctan, z, nan_nan, OPT_INVALID, 0, 0); - z = cpackl(0, NAN); - testall_odd(csinh, z, cpackl(0, NAN), ALL_STD_EXCEPT, 0, 0); - testall_even(ccosh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, 0); + z = CMPLXL(0, NAN); + testall_odd(csinh, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, 0, 0); + testall_even(ccosh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); testall_odd(ctanh, z, nan_nan, OPT_INVALID, 0, 0); - testall_odd(csin, z, cpackl(0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); - testall_even(ccos, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, 0); - testall_odd(ctan, z, cpackl(0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); - - z = cpackl(NAN, 0); - testall_odd(csinh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); - testall_even(ccosh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, 0); - testall_odd(ctanh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); - testall_odd(csin, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, 0); - testall_even(ccos, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, 0); + testall_odd(csin, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + testall_even(ccos, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); + testall_odd(ctan, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + + z = CMPLXL(NAN, 0); + testall_odd(csinh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); + testall_even(ccosh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); + testall_odd(ctanh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); + testall_odd(csin, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); + testall_even(ccos, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); testall_odd(ctan, z, nan_nan, OPT_INVALID, 0, 0); } @@ -325,53 +230,53 @@ test_inf(void) * 0,Inf +-0,NaN inval NaN,+-0 inval NaN,NaN inval * finite,Inf NaN,NaN inval NaN,NaN inval NaN,NaN inval */ - z = cpackl(INFINITY, INFINITY); - testall_odd(csinh, z, cpackl(INFINITY, NAN), + z = CMPLXL(INFINITY, INFINITY); + testall_odd(csinh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccosh, z, cpackl(INFINITY, NAN), + testall_even(ccosh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_odd(ctanh, z, cpackl(1, 0), ALL_STD_EXCEPT, 0, CS_REAL); - testall_odd(csin, z, cpackl(NAN, INFINITY), + testall_odd(ctanh, z, CMPLXL(1, 0), ALL_STD_EXCEPT, 0, CS_REAL); + testall_odd(csin, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccos, z, cpackl(INFINITY, NAN), + testall_even(ccos, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_odd(ctan, z, cpackl(0, 1), ALL_STD_EXCEPT, 0, CS_REAL); + testall_odd(ctan, z, CMPLXL(0, 1), ALL_STD_EXCEPT, 0, CS_REAL); /* XXX We allow spurious inexact exceptions here (hard to avoid). */ for (i = 0; i < sizeof(finites) / sizeof(finites[0]); i++) { - z = cpackl(INFINITY, finites[i]); + z = CMPLXL(INFINITY, finites[i]); c = INFINITY * cosl(finites[i]); s = finites[i] == 0 ? finites[i] : INFINITY * sinl(finites[i]); - testall_odd(csinh, z, cpackl(c, s), OPT_INEXACT, 0, CS_BOTH); - testall_even(ccosh, z, cpackl(c, s), OPT_INEXACT, 0, CS_BOTH); - testall_odd(ctanh, z, cpackl(1, 0 * sin(finites[i] * 2)), + testall_odd(csinh, z, CMPLXL(c, s), OPT_INEXACT, 0, CS_BOTH); + testall_even(ccosh, z, CMPLXL(c, s), OPT_INEXACT, 0, CS_BOTH); + testall_odd(ctanh, z, CMPLXL(1, 0 * sin(finites[i] * 2)), OPT_INEXACT, 0, CS_BOTH); - z = cpackl(finites[i], INFINITY); - testall_odd(csin, z, cpackl(s, c), OPT_INEXACT, 0, CS_BOTH); - testall_even(ccos, z, cpackl(c, -s), OPT_INEXACT, 0, CS_BOTH); - testall_odd(ctan, z, cpackl(0 * sin(finites[i] * 2), 1), + z = CMPLXL(finites[i], INFINITY); + testall_odd(csin, z, CMPLXL(s, c), OPT_INEXACT, 0, CS_BOTH); + testall_even(ccos, z, CMPLXL(c, -s), OPT_INEXACT, 0, CS_BOTH); + testall_odd(ctan, z, CMPLXL(0 * sin(finites[i] * 2), 1), OPT_INEXACT, 0, CS_BOTH); } - z = cpackl(0, INFINITY); - testall_odd(csinh, z, cpackl(0, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccosh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_odd(ctanh, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - z = cpackl(INFINITY, 0); - testall_odd(csin, z, cpackl(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccos, z, cpackl(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_odd(ctan, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - - z = cpackl(42, INFINITY); - testall_odd(csinh, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccosh, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + z = CMPLXL(0, INFINITY); + testall_odd(csinh, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_even(ccosh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_odd(ctanh, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + z = CMPLXL(INFINITY, 0); + testall_odd(csin, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_even(ccos, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_odd(ctan, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + + z = CMPLXL(42, INFINITY); + testall_odd(csinh, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_even(ccosh, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); /* XXX We allow a spurious inexact exception here. */ - testall_odd(ctanh, z, cpackl(NAN, NAN), OPT_INEXACT, FE_INVALID, 0); - z = cpackl(INFINITY, 42); - testall_odd(csin, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccos, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_odd(ctanh, z, CMPLXL(NAN, NAN), OPT_INEXACT, FE_INVALID, 0); + z = CMPLXL(INFINITY, 42); + testall_odd(csin, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_even(ccos, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); /* XXX We allow a spurious inexact exception here. */ - testall_odd(ctan, z, cpackl(NAN, NAN), OPT_INEXACT, FE_INVALID, 0); + testall_odd(ctan, z, CMPLXL(NAN, NAN), OPT_INEXACT, FE_INVALID, 0); } /* Tests along the real and imaginary axes. */ @@ -387,26 +292,26 @@ test_axes(void) for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) { /* Real axis */ - z = cpackl(nums[i], 0.0); - testall_odd_tol(csinh, z, cpackl(sinh(nums[i]), 0), 0); - testall_even_tol(ccosh, z, cpackl(cosh(nums[i]), 0), 0); - testall_odd_tol(ctanh, z, cpackl(tanh(nums[i]), 0), 1); - testall_odd_tol(csin, z, cpackl(sin(nums[i]), + z = CMPLXL(nums[i], 0.0); + testall_odd_tol(csinh, z, CMPLXL(sinh(nums[i]), 0), 0); + testall_even_tol(ccosh, z, CMPLXL(cosh(nums[i]), 0), 0); + testall_odd_tol(ctanh, z, CMPLXL(tanh(nums[i]), 0), 1); + testall_odd_tol(csin, z, CMPLXL(sin(nums[i]), copysign(0, cos(nums[i]))), 0); - testall_even_tol(ccos, z, cpackl(cos(nums[i]), + testall_even_tol(ccos, z, CMPLXL(cos(nums[i]), -copysign(0, sin(nums[i]))), 0); - testall_odd_tol(ctan, z, cpackl(tan(nums[i]), 0), 1); + testall_odd_tol(ctan, z, CMPLXL(tan(nums[i]), 0), 1); /* Imaginary axis */ - z = cpackl(0.0, nums[i]); - testall_odd_tol(csinh, z, cpackl(copysign(0, cos(nums[i])), + z = CMPLXL(0.0, nums[i]); + testall_odd_tol(csinh, z, CMPLXL(copysign(0, cos(nums[i])), sin(nums[i])), 0); - testall_even_tol(ccosh, z, cpackl(cos(nums[i]), + testall_even_tol(ccosh, z, CMPLXL(cos(nums[i]), copysign(0, sin(nums[i]))), 0); - testall_odd_tol(ctanh, z, cpackl(0, tan(nums[i])), 1); - testall_odd_tol(csin, z, cpackl(0, sinh(nums[i])), 0); - testall_even_tol(ccos, z, cpackl(cosh(nums[i]), -0.0), 0); - testall_odd_tol(ctan, z, cpackl(0, tanh(nums[i])), 1); + testall_odd_tol(ctanh, z, CMPLXL(0, tan(nums[i])), 1); + testall_odd_tol(csin, z, CMPLXL(0, sinh(nums[i])), 0); + testall_even_tol(ccos, z, CMPLXL(cosh(nums[i]), -0.0), 0); + testall_odd_tol(ctan, z, CMPLXL(0, tanh(nums[i])), 1); } } @@ -462,13 +367,13 @@ test_small(void) int i; for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { - z = cpackl(tests[i].a, tests[i].b); + z = CMPLXL(tests[i].a, tests[i].b); testall_odd_tol(csinh, z, - cpackl(tests[i].sinh_a, tests[i].sinh_b), 1.1); + CMPLXL(tests[i].sinh_a, tests[i].sinh_b), 1.1); testall_even_tol(ccosh, z, - cpackl(tests[i].cosh_a, tests[i].cosh_b), 1.1); + CMPLXL(tests[i].cosh_a, tests[i].cosh_b), 1.1); testall_odd_tol(ctanh, z, - cpackl(tests[i].tanh_a, tests[i].tanh_b), 1.1); + CMPLXL(tests[i].tanh_a, tests[i].tanh_b), 1.1); } } @@ -479,36 +384,36 @@ test_large(void) long double complex z; /* tanh() uses a threshold around x=22, so check both sides. */ - z = cpackl(21, 0.78539816339744830961566084581987572L); + z = CMPLXL(21, 0.78539816339744830961566084581987572L); testall_odd_tol(ctanh, z, - cpackl(1.0, 1.14990445285871196133287617611468468e-18L), 1); + CMPLXL(1.0, 1.14990445285871196133287617611468468e-18L), 1); z++; testall_odd_tol(ctanh, z, - cpackl(1.0, 1.55622644822675930314266334585597964e-19L), 1); + CMPLXL(1.0, 1.55622644822675930314266334585597964e-19L), 1); - z = cpackl(355, 0.78539816339744830961566084581987572L); + z = CMPLXL(355, 0.78539816339744830961566084581987572L); testall_odd_tol(ctanh, z, - cpackl(1.0, 8.95257245135025991216632140458264468e-309L), 1); - z = cpackl(30, 0x1p1023L); + CMPLXL(1.0, 8.95257245135025991216632140458264468e-309L), 1); + z = CMPLXL(30, 0x1p1023L); testall_odd_tol(ctanh, z, - cpackl(1.0, -1.62994325413993477997492170229268382e-26L), 1); - z = cpackl(1, 0x1p1023L); + CMPLXL(1.0, -1.62994325413993477997492170229268382e-26L), 1); + z = CMPLXL(1, 0x1p1023L); testall_odd_tol(ctanh, z, - cpackl(0.878606311888306869546254022621986509L, + CMPLXL(0.878606311888306869546254022621986509L, -0.225462792499754505792678258169527424L), 1); - z = cpackl(710.6, 0.78539816339744830961566084581987572L); + z = CMPLXL(710.6, 0.78539816339744830961566084581987572L); testall_odd_tol(csinh, z, - cpackl(1.43917579766621073533185387499658944e308L, + CMPLXL(1.43917579766621073533185387499658944e308L, 1.43917579766621073533185387499658944e308L), 1); testall_even_tol(ccosh, z, - cpackl(1.43917579766621073533185387499658944e308L, + CMPLXL(1.43917579766621073533185387499658944e308L, 1.43917579766621073533185387499658944e308L), 1); - z = cpackl(1500, 0.78539816339744830961566084581987572L); - testall_odd(csinh, z, cpackl(INFINITY, INFINITY), OPT_INEXACT, + z = CMPLXL(1500, 0.78539816339744830961566084581987572L); + testall_odd(csinh, z, CMPLXL(INFINITY, INFINITY), OPT_INEXACT, FE_OVERFLOW, CS_BOTH); - testall_even(ccosh, z, cpackl(INFINITY, INFINITY), OPT_INEXACT, + testall_even(ccosh, z, CMPLXL(INFINITY, INFINITY), OPT_INEXACT, FE_OVERFLOW, CS_BOTH); } diff --git a/tools/regression/lib/msun/test-exponential.c b/tools/regression/lib/msun/test-exponential.c index 53a61165479a..010e0fd893ed 100644 --- a/tools/regression/lib/msun/test-exponential.c +++ b/tools/regression/lib/msun/test-exponential.c @@ -41,8 +41,7 @@ __FBSDID("$FreeBSD$"); #include <ieeefp.h> #endif -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON @@ -63,7 +62,7 @@ __FBSDID("$FreeBSD$"); volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* Test all the functions that compute b^x. */ @@ -81,17 +80,6 @@ __FBSDID("$FreeBSD$"); test(expm1f, x, result, exceptmask, excepts); \ } while (0) -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - */ -int -fpequal(long double x, long double y) -{ - return ((x == y && !signbit(x) == !signbit(y)) || isnan(x) && isnan(y)); -} - void run_generic_tests(void) { diff --git a/tools/regression/lib/msun/test-fma.c b/tools/regression/lib/msun/test-fma.c index c17ef459eabd..1fcf88916080 100644 --- a/tools/regression/lib/msun/test-fma.c +++ b/tools/regression/lib/msun/test-fma.c @@ -37,8 +37,7 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON @@ -53,14 +52,17 @@ __FBSDID("$FreeBSD$"); * meaningful error messages. */ #define test(func, x, y, z, result, exceptmask, excepts) do { \ + volatile long double _vx = (x), _vy = (y), _vz = (z); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(fpequal((func)((x), (y), (z)), (result))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(fpequal((func)(_vx, _vy, _vz), (result))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) #define testall(x, y, z, result, exceptmask, excepts) do { \ - test(fma, (x), (y), (z), (double)(result), (exceptmask), (excepts)); \ - test(fmaf, (x), (y), (z), (float)(result), (exceptmask), (excepts)); \ + test(fma, (double)(x), (double)(y), (double)(z), \ + (double)(result), (exceptmask), (excepts)); \ + test(fmaf, (float)(x), (float)(y), (float)(z), \ + (float)(result), (exceptmask), (excepts)); \ test(fmal, (x), (y), (z), (result), (exceptmask), (excepts)); \ } while (0) @@ -82,19 +84,6 @@ __FBSDID("$FreeBSD$"); */ volatile double one = 1.0; -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - */ -int -fpequal(long double x, long double y) -{ - - return ((x == y && !signbit(x) == !signbit(y)) - || (isnan(x) && isnan(y))); -} - static void test_zeroes(void) { diff --git a/tools/regression/lib/msun/test-fmaxmin.c b/tools/regression/lib/msun/test-fmaxmin.c index fdba52934722..7ddcc87a4ed4 100644 --- a/tools/regression/lib/msun/test-fmaxmin.c +++ b/tools/regression/lib/msun/test-fmaxmin.c @@ -36,25 +36,11 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON /* - * Test for equality with two special rules: - * fpequal(NaN, NaN) is true - * fpequal(+0.0, -0.0) is false - */ -static inline int -fpequal(long double x, long double y) -{ - - return ((x == y && !signbit(x) == !signbit(y)) - || (isnan(x) && isnan(y))); -} - -/* * Test whether func(x, y) has the expected result, and make sure no * exceptions are raised. */ diff --git a/tools/regression/lib/msun/test-invctrig.c b/tools/regression/lib/msun/test-invctrig.c index 6f0fe58a5611..e78c26b7423f 100644 --- a/tools/regression/lib/msun/test-invctrig.c +++ b/tools/regression/lib/msun/test-invctrig.c @@ -38,28 +38,11 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) -#define OPT_INVALID (ALL_STD_EXCEPT & ~FE_INVALID) -#define OPT_INEXACT (ALL_STD_EXCEPT & ~FE_INEXACT) -#define FLT_ULP() ldexpl(1.0, 1 - FLT_MANT_DIG) -#define DBL_ULP() ldexpl(1.0, 1 - DBL_MANT_DIG) -#define LDBL_ULP() ldexpl(1.0, 1 - LDBL_MANT_DIG) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON #pragma STDC CX_LIMITED_RANGE OFF -/* Flags that determine whether to check the signs of the result. */ -#define CS_REAL 1 -#define CS_IMAG 2 -#define CS_BOTH (CS_REAL | CS_IMAG) - -#ifdef DEBUG -#define debug(...) printf(__VA_ARGS__) -#else -#define debug(...) (void)0 -#endif - /* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which @@ -78,8 +61,8 @@ __FBSDID("$FreeBSD$"); debug(" testing %s(%Lg + %Lg I) == %Lg + %Lg I\n", #func, \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(cfpequal((func)(_d), (result), (checksign))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(cfpequal_cs((func)(_d), (result), (checksign))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* @@ -90,7 +73,7 @@ __FBSDID("$FreeBSD$"); volatile long double complex _d = z; \ debug(" testing %s(%Lg + %Lg I) ~= %Lg + %Lg I\n", #func, \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \ - assert(cfpequal_tol((func)(_d), (result), (tol))); \ + assert(cfpequal_tol((func)(_d), (result), (tol), CS_BOTH)); \ } while (0) /* These wrappers apply the identities f(conj(z)) = conj(f(z)). */ @@ -138,59 +121,6 @@ static const long double pi = 3.14159265358979323846264338327950280L, c3pi = 9.42477796076937971538793014983850839L; -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - * If checksign is 0, we compare the absolute values instead. - */ -static int -fpequal(long double x, long double y, int checksign) -{ - if (isnan(x) && isnan(y)) - return (1); - if (checksign) - return (x == y && !signbit(x) == !signbit(y)); - else - return (fabsl(x) == fabsl(y)); -} - -static int -fpequal_tol(long double x, long double y, long double tol) -{ - fenv_t env; - int ret; - - if (isnan(x) && isnan(y)) - return (1); - if (!signbit(x) != !signbit(y)) - return (0); - if (x == y) - return (1); - if (tol == 0 || y == 0.0) - return (0); - - /* Hard case: need to check the tolerance. */ - feholdexcept(&env); - ret = fabsl(x - y) <= fabsl(y * tol); - fesetenv(&env); - return (ret); -} - -static int -cfpequal(long double complex x, long double complex y, int checksign) -{ - return (fpequal(creal(x), creal(y), checksign & CS_REAL) - && fpequal(cimag(x), cimag(y), checksign & CS_IMAG)); -} - -static int -cfpequal_tol(long double complex x, long double complex y, long double tol) -{ - return (fpequal_tol(creal(x), creal(y), tol) - && fpequal_tol(cimag(x), cimag(y), tol)); -} - /* Tests for 0 */ void diff --git a/tools/regression/lib/msun/test-invtrig.c b/tools/regression/lib/msun/test-invtrig.c index 05d310fe1590..2523d59e4aab 100644 --- a/tools/regression/lib/msun/test-invtrig.c +++ b/tools/regression/lib/msun/test-invtrig.c @@ -39,8 +39,7 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #define LEN(a) (sizeof(a) / sizeof((a)[0])) @@ -58,8 +57,8 @@ __FBSDID("$FreeBSD$"); #define test_tol(func, x, result, tol, excepts) do { \ volatile long double _in = (x), _out = (result); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(fpequal(func(_in), _out, (tol))); \ - assert((func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ + assert(fpequal_tol(func(_in), _out, (tol), CS_BOTH)); \ + assert(((void)func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ } while (0) #define test(func, x, result, excepts) \ test_tol(func, (x), (result), 0, (excepts)) @@ -78,8 +77,8 @@ __FBSDID("$FreeBSD$"); #define test2_tol(func, y, x, result, tol, excepts) do { \ volatile long double _iny = (y), _inx = (x), _out = (result); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(fpequal(func(_iny, _inx), _out, (tol))); \ - assert((func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ + assert(fpequal_tol(func(_iny, _inx), _out, (tol), CS_BOTH)); \ + assert(((void)func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ } while (0) #define test2(func, y, x, result, excepts) \ test2_tol(func, (y), (x), (result), 0, (excepts)) @@ -104,33 +103,6 @@ c7pi = 2.19911485751285526692385036829565196e+01L, c5pio3 = 5.23598775598298873077107230546583851e+00L, sqrt2m1 = 4.14213562373095048801688724209698081e-01L; -/* - * Determine whether x and y are equal to within a relative error of tol, - * with two special rules: - * +0.0 != -0.0 - * NaN == NaN - */ -int -fpequal(long double x, long double y, long double tol) -{ - fenv_t env; - int ret; - - if (isnan(x) && isnan(y)) - return (1); - if (!signbit(x) != !signbit(y)) - return (0); - if (x == y) - return (1); - if (tol == 0) - return (0); - - /* Hard case: need to check the tolerance. */ - feholdexcept(&env); - ret = fabsl(x - y) <= fabsl(y * tol); - fesetenv(&env); - return (ret); -} /* * Test special case inputs in asin(), acos() and atan(): signed diff --git a/tools/regression/lib/msun/test-logarithm.c b/tools/regression/lib/msun/test-logarithm.c index 258c5141305e..c5f23b8705bb 100644 --- a/tools/regression/lib/msun/test-logarithm.c +++ b/tools/regression/lib/msun/test-logarithm.c @@ -41,8 +41,7 @@ __FBSDID("$FreeBSD$"); #include <ieeefp.h> #endif -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON @@ -63,7 +62,7 @@ __FBSDID("$FreeBSD$"); volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* Test all the functions that compute log(x). */ @@ -82,17 +81,6 @@ __FBSDID("$FreeBSD$"); test(log1pf, x, result, exceptmask, excepts); \ } while (0) -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - */ -int -fpequal(long double x, long double y) -{ - return ((x == y && !signbit(x) == !signbit(y)) || isnan(x) && isnan(y)); -} - void run_generic_tests(void) { diff --git a/tools/regression/lib/msun/test-nearbyint.c b/tools/regression/lib/msun/test-nearbyint.c index 7251acb6e0e5..602ea2afecf1 100644 --- a/tools/regression/lib/msun/test-nearbyint.c +++ b/tools/regression/lib/msun/test-nearbyint.c @@ -40,8 +40,7 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" static int testnum; @@ -49,6 +48,14 @@ static const int rmodes[] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO, }; +/* Make sure we're testing the library, not some broken compiler built-ins. */ +double (*libnearbyint)(double) = nearbyint; +float (*libnearbyintf)(float) = nearbyintf; +long double (*libnearbyintl)(long double) = nearbyintl; +#define nearbyintf libnearbyintf +#define nearbyint libnearbyint +#define nearbyintl libnearbyintl + static const struct { float in; float out[3]; /* one answer per rounding mode except towardzero */ @@ -64,19 +71,6 @@ static const struct { static const int ntests = sizeof(tests) / sizeof(tests[0]); -/* - * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. - * Fail an assertion if they differ. - */ -static int -fpequal(long double d1, long double d2) -{ - - if (d1 != d2) - return (isnan(d1) && isnan(d2)); - return (copysignl(1.0, d1) == copysignl(1.0, d2)); -} - /* Get the appropriate result for the current rounding mode. */ static float get_output(int testindex, int rmodeindex, int negative) @@ -107,7 +101,7 @@ test_nearby(int testindex) in = tests[testindex].in; out = get_output(testindex, i, 0); - assert(fpequal(out, nearbyintf(in))); + assert(fpequal(out, libnearbyintf(in))); assert(fpequal(out, nearbyint(in))); assert(fpequal(out, nearbyintl(in))); assert(fetestexcept(ALL_STD_EXCEPT) == 0); diff --git a/tools/regression/lib/msun/test-next.c b/tools/regression/lib/msun/test-next.c index 68e4361581cc..d16fa772b83d 100644 --- a/tools/regression/lib/msun/test-next.c +++ b/tools/regression/lib/msun/test-next.c @@ -41,8 +41,8 @@ __FBSDID("$FreeBSD$"); #include <ieeefp.h> #endif -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID |\ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" + #define test(exp, ans, ex) do { \ double __ans = (ans); \ feclearexcept(ALL_STD_EXCEPT); \ @@ -235,7 +235,7 @@ _testl(const char *exp, int line, long double actual, long double expected, int actual_except; actual_except = fetestexcept(ALL_STD_EXCEPT); - if (actual != expected && !(isnan(actual) && isnan(expected))) { + if (!fpequal(actual, expected)) { fprintf(stderr, "%d: %s returned %La, expecting %La\n", line, exp, actual, expected); abort(); diff --git a/tools/regression/lib/msun/test-trig.c b/tools/regression/lib/msun/test-trig.c index 1ac78734027e..80f1aefa2296 100644 --- a/tools/regression/lib/msun/test-trig.c +++ b/tools/regression/lib/msun/test-trig.c @@ -42,8 +42,7 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #define LEN(a) (sizeof(a) / sizeof((a)[0])) @@ -66,7 +65,7 @@ __FBSDID("$FreeBSD$"); volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) #define testall(prefix, x, result, exceptmask, excepts) do { \ @@ -80,19 +79,6 @@ __FBSDID("$FreeBSD$"); test(prefix##f, x, (float)result, exceptmask, excepts); \ } while (0) - - -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - */ -int -fpequal(long double x, long double y) -{ - return ((x == y && !signbit(x) == !signbit(y)) || isnan(x) && isnan(y)); -} - /* * Test special cases in sin(), cos(), and tan(). */ diff --git a/tools/regression/lib/msun/test-utils.h b/tools/regression/lib/msun/test-utils.h new file mode 100644 index 000000000000..bf0d6dee85e7 --- /dev/null +++ b/tools/regression/lib/msun/test-utils.h @@ -0,0 +1,174 @@ +/*- + * Copyright (c) 2005-2013 David Schultz <das@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _TEST_UTILS_H_ +#define _TEST_UTILS_H_ + +#include <complex.h> +#include <fenv.h> + +/* + * Implementations are permitted to define additional exception flags + * not specified in the standard, so it is not necessarily true that + * FE_ALL_EXCEPT == ALL_STD_EXCEPT. + */ +#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ + FE_OVERFLOW | FE_UNDERFLOW) +#define OPT_INVALID (ALL_STD_EXCEPT & ~FE_INVALID) +#define OPT_INEXACT (ALL_STD_EXCEPT & ~FE_INEXACT) +#define FLT_ULP() ldexpl(1.0, 1 - FLT_MANT_DIG) +#define DBL_ULP() ldexpl(1.0, 1 - DBL_MANT_DIG) +#define LDBL_ULP() ldexpl(1.0, 1 - LDBL_MANT_DIG) + +/* + * Flags that control the behavior of various fpequal* functions. + * XXX This is messy due to merging various notions of "close enough" + * that are best suited for different functions. + * + * CS_REAL + * CS_IMAG + * CS_BOTH + * (cfpequal_cs, fpequal_tol, cfpequal_tol) Whether to check the sign of + * the real part of the result, the imaginary part, or both. + * + * FPE_ABS_ZERO + * (fpequal_tol, cfpequal_tol) If set, treats the tolerance as an absolute + * tolerance when the expected value is 0. This is useful when there is + * round-off error in the input, e.g., cos(Pi/2) ~= 0. + */ +#define CS_REAL 0x01 +#define CS_IMAG 0x02 +#define CS_BOTH (CS_REAL | CS_IMAG) +#define FPE_ABS_ZERO 0x04 + +#ifdef DEBUG +#define debug(...) printf(__VA_ARGS__) +#else +#define debug(...) (void)0 +#endif + +/* + * XXX The ancient version of gcc in the base system doesn't support CMPLXL, + * but we can fake it most of the time. + */ +#ifndef CMPLXL +static inline long double complex +CMPLXL(long double x, long double y) +{ + long double complex z; + + __real__ z = x; + __imag__ z = y; + return (z); +} +#endif + +/* + * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. + * Fail an assertion if they differ. + */ +static int +fpequal(long double d1, long double d2) +{ + + if (d1 != d2) + return (isnan(d1) && isnan(d2)); + return (copysignl(1.0, d1) == copysignl(1.0, d2)); +} + +/* + * Determine whether x and y are equal, with two special rules: + * +0.0 != -0.0 + * NaN == NaN + * If checksign is 0, we compare the absolute values instead. + */ +static int +fpequal_cs(long double x, long double y, int checksign) +{ + if (isnan(x) && isnan(y)) + return (1); + if (checksign) + return (x == y && !signbit(x) == !signbit(y)); + else + return (fabsl(x) == fabsl(y)); +} + +static int +fpequal_tol(long double x, long double y, long double tol, unsigned int flags) +{ + fenv_t env; + int ret; + + if (isnan(x) && isnan(y)) + return (1); + if (!signbit(x) != !signbit(y) && (flags & CS_BOTH)) + return (0); + if (x == y) + return (1); + if (tol == 0) + return (0); + + /* Hard case: need to check the tolerance. */ + feholdexcept(&env); + /* + * For our purposes here, if y=0, we interpret tol as an absolute + * tolerance. This is to account for roundoff in the input, e.g., + * cos(Pi/2) ~= 0. + */ + if ((flags & FPE_ABS_ZERO) && y == 0.0) + ret = fabsl(x - y) <= fabsl(tol); + else + ret = fabsl(x - y) <= fabsl(y * tol); + fesetenv(&env); + return (ret); +} + +static int +cfpequal(long double complex d1, long double complex d2) +{ + + return (fpequal(creall(d1), creall(d2)) && + fpequal(cimagl(d1), cimagl(d2))); +} + +static int +cfpequal_cs(long double complex x, long double complex y, int checksign) +{ + return (fpequal_cs(creal(x), creal(y), checksign) + && fpequal_cs(cimag(x), cimag(y), checksign)); +} + +static int +cfpequal_tol(long double complex x, long double complex y, long double tol, + unsigned int flags) +{ + return (fpequal_tol(creal(x), creal(y), tol, flags) + && fpequal_tol(cimag(x), cimag(y), tol, flags)); +} + +#endif /* _TEST_UTILS_H_ */ |