Convert the msun tests to ATF

This provides better error messages that just an assertion failure and
also makes it easier to mark individual tests as XFAIL.
It was also helpful when coming up with D28786 and D28787.

Differential Revision: https://reviews.freebsd.org/D28798
This commit is contained in:
Alex Richardson 2021-03-22 11:15:13 +00:00
parent aa05775ef0
commit 133bc64507
22 changed files with 859 additions and 860 deletions

View File

@ -52,30 +52,28 @@ NETBSD_ATF_TESTS_C+= sqrt_test
NETBSD_ATF_TESTS_C+= tan_test NETBSD_ATF_TESTS_C+= tan_test
NETBSD_ATF_TESTS_C+= tanh_test NETBSD_ATF_TESTS_C+= tanh_test
TAP_TESTS_C+= cexp_test ATF_TESTS_C+= cexp_test
TAP_TESTS_C+= conj_test ATF_TESTS_C+= conj_test
.if ${MACHINE_CPUARCH} != "aarch64" .if ${MACHINE_CPUARCH} != "aarch64"
# Hits an assert in llvm when building for arm64: # Hits an assert in llvm when building for arm64:
# https://llvm.org/bugs/show_bug.cgi?id=26081 # https://llvm.org/bugs/show_bug.cgi?id=26081
TAP_TESTS_C+= csqrt_test ATF_TESTS_C+= csqrt_test
.endif .endif
ATF_TESTS_C+= ctrig_test ATF_TESTS_C+= ctrig_test
TAP_TESTS_C+= exponential_test ATF_TESTS_C+= exponential_test
TAP_TESTS_C+= fenv_test ATF_TESTS_C+= fenv_test
TAP_TESTS_C+= fma_test ATF_TESTS_C+= fma_test
TAP_TESTS_C+= fmaxmin_test ATF_TESTS_C+= fmaxmin_test
TAP_TESTS_C+= ilogb2_test ATF_TESTS_C+= ilogb2_test
TAP_TESTS_C+= invtrig_test ATF_TESTS_C+= invtrig_test
TAP_TESTS_C+= invctrig_test ATF_TESTS_C+= invctrig_test
TAP_TESTS_C+= logarithm_test ATF_TESTS_C+= logarithm_test
TAP_TESTS_C+= lrint_test ATF_TESTS_C+= lrint_test
# XXX: the testcase crashes on all platforms, but only on head ATF_TESTS_C+= lround_test
# (bug 205451) ATF_TESTS_C+= nan_test
#TAP_TESTS_C+= lround_test ATF_TESTS_C+= nearbyint_test
TAP_TESTS_C+= nan_test ATF_TESTS_C+= next_test
TAP_TESTS_C+= nearbyint_test ATF_TESTS_C+= rem_test
TAP_TESTS_C+= next_test
TAP_TESTS_C+= rem_test
ATF_TESTS_C+= trig_test ATF_TESTS_C+= trig_test
.if !empty(PROG) && !empty(TAP_TESTS_C:M${PROG}) .if !empty(PROG) && !empty(TAP_TESTS_C:M${PROG})

View File

@ -33,7 +33,6 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <assert.h>
#include <complex.h> #include <complex.h>
#include <fenv.h> #include <fenv.h>
#include <float.h> #include <float.h>
@ -63,9 +62,10 @@ __FBSDID("$FreeBSD$");
do { \ do { \
volatile long double complex _d = z; \ volatile long double complex _d = z; \
volatile type complex _r = result; \ volatile type complex _r = result; \
assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT)); \
assert(cfpequal_cs((func)(_d), (_r), (checksign))); \ ATF_CHECK(cfpequal_cs((func)(_d), (_r), (checksign))); \
assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ CHECK_FP_EXCEPTIONS_MSG(excepts, exceptmask, "for %s(%s)", \
#func, #z); \
} while (0) } while (0)
#define test(func, z, result, exceptmask, excepts, checksign) \ #define test(func, z, result, exceptmask, excepts, checksign) \
@ -77,7 +77,7 @@ do { \
/* Test within a given tolerance. */ /* Test within a given tolerance. */
#define test_tol(func, z, result, tol) do { \ #define test_tol(func, z, result, tol) do { \
volatile long double complex _d = z; \ volatile long double complex _d = z; \
assert(cfpequal_tol((func)(_d), (result), (tol), \ ATF_CHECK(cfpequal_tol((func)(_d), (result), (tol), \
FPE_ABS_ZERO | CS_BOTH)); \ FPE_ABS_ZERO | CS_BOTH)); \
} while (0) } while (0)
@ -102,8 +102,8 @@ static const float finites[] =
/* Tests for 0 */ /* Tests for 0 */
static void ATF_TC_WITHOUT_HEAD(zero);
test_zero(void) ATF_TC_BODY(zero, tc)
{ {
/* cexp(0) = 1, no exceptions raised */ /* cexp(0) = 1, no exceptions raised */
@ -117,15 +117,14 @@ test_zero(void)
* Tests for NaN. The signs of the results are indeterminate unless the * Tests for NaN. The signs of the results are indeterminate unless the
* imaginary part is 0. * imaginary part is 0.
*/ */
static void ATF_TC_WITHOUT_HEAD(nan);
test_nan(void) ATF_TC_BODY(nan, tc)
{ {
unsigned i; unsigned i;
/* cexp(x + NaNi) = NaN + NaNi and optionally raises invalid */ /* cexp(x + NaNi) = NaN + NaNi and optionally raises invalid */
/* cexp(NaN + yi) = NaN + NaNi and optionally raises invalid (|y|>0) */ /* cexp(NaN + yi) = NaN + NaNi and optionally raises invalid (|y|>0) */
for (i = 0; i < nitems(finites); i++) { for (i = 0; i < nitems(finites); i++) {
printf("# Run %d..\n", i);
testall(CMPLXL(finites[i], NAN), CMPLXL(NAN, NAN), testall(CMPLXL(finites[i], NAN), CMPLXL(NAN, NAN),
ALL_STD_EXCEPT & ~FE_INVALID, 0, 0); ALL_STD_EXCEPT & ~FE_INVALID, 0, 0);
if (finites[i] == 0.0) if (finites[i] == 0.0)
@ -150,14 +149,13 @@ test_nan(void)
ALL_STD_EXCEPT, 0, 0); ALL_STD_EXCEPT, 0, 0);
} }
static void ATF_TC_WITHOUT_HEAD(inf);
test_inf(void) ATF_TC_BODY(inf, tc)
{ {
unsigned i; unsigned i;
/* cexp(x + inf i) = NaN + NaNi and raises invalid */ /* cexp(x + inf i) = NaN + NaNi and raises invalid */
for (i = 0; i < nitems(finites); i++) { for (i = 0; i < nitems(finites); i++) {
printf("# Run %d..\n", i);
testall(CMPLXL(finites[i], INFINITY), CMPLXL(NAN, NAN), testall(CMPLXL(finites[i], INFINITY), CMPLXL(NAN, NAN),
ALL_STD_EXCEPT, FE_INVALID, 1); ALL_STD_EXCEPT, FE_INVALID, 1);
} }
@ -192,14 +190,13 @@ test_inf(void)
ALL_STD_EXCEPT, 0, 1); ALL_STD_EXCEPT, 0, 1);
} }
static void ATF_TC_WITHOUT_HEAD(reals);
test_reals(void) ATF_TC_BODY(reals, tc)
{ {
unsigned i; unsigned i;
for (i = 0; i < nitems(finites); i++) { for (i = 0; i < nitems(finites); i++) {
/* XXX could check exceptions more meticulously */ /* XXX could check exceptions more meticulously */
printf("# Run %d..\n", i);
test(cexp, CMPLXL(finites[i], 0.0), test(cexp, CMPLXL(finites[i], 0.0),
CMPLXL(exp(finites[i]), 0.0), CMPLXL(exp(finites[i]), 0.0),
FE_INVALID | FE_DIVBYZERO, 0, 1); FE_INVALID | FE_DIVBYZERO, 0, 1);
@ -215,13 +212,12 @@ test_reals(void)
} }
} }
static void ATF_TC_WITHOUT_HEAD(imaginaries);
test_imaginaries(void) ATF_TC_BODY(imaginaries, tc)
{ {
unsigned i; unsigned i;
for (i = 0; i < nitems(finites); i++) { for (i = 0; i < nitems(finites); i++) {
printf("# Run %d..\n", i);
test(cexp, CMPLXL(0.0, finites[i]), test(cexp, CMPLXL(0.0, finites[i]),
CMPLXL(cos(finites[i]), sin(finites[i])), CMPLXL(cos(finites[i]), sin(finites[i])),
ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1);
@ -237,8 +233,8 @@ test_imaginaries(void)
} }
} }
static void ATF_TC_WITHOUT_HEAD(small);
test_small(void) ATF_TC_BODY(small, tc)
{ {
static const double tests[] = { static const double tests[] = {
/* csqrt(a + bI) = x + yI */ /* csqrt(a + bI) = x + yI */
@ -253,7 +249,6 @@ test_small(void)
unsigned i; unsigned i;
for (i = 0; i < nitems(tests); i += 4) { for (i = 0; i < nitems(tests); i += 4) {
printf("# Run %d..\n", i);
a = tests[i]; a = tests[i];
b = tests[i + 1]; b = tests[i + 1];
x = tests[i + 2]; x = tests[i + 2];
@ -268,8 +263,8 @@ test_small(void)
} }
/* Test inputs with a real part r that would overflow exp(r). */ /* Test inputs with a real part r that would overflow exp(r). */
static void ATF_TC_WITHOUT_HEAD(large);
test_large(void) ATF_TC_BODY(large, tc)
{ {
test_tol(cexp, CMPLXL(709.79, 0x1p-1074), test_tol(cexp, CMPLXL(709.79, 0x1p-1074),
@ -295,32 +290,15 @@ test_large(void)
CMPLXL(INFINITY, 5.7878851079e+37f), 2 * FLT_ULP()); CMPLXL(INFINITY, 5.7878851079e+37f), 2 * FLT_ULP());
} }
int ATF_TP_ADD_TCS(tp)
main(void)
{ {
ATF_TP_ADD_TC(tp, zero);
ATF_TP_ADD_TC(tp, nan);
ATF_TP_ADD_TC(tp, inf);
ATF_TP_ADD_TC(tp, reals);
ATF_TP_ADD_TC(tp, imaginaries);
ATF_TP_ADD_TC(tp, small);
ATF_TP_ADD_TC(tp, large);
printf("1..7\n"); return (atf_no_error());
test_zero();
printf("ok 1 - cexp zero\n");
test_nan();
printf("ok 2 - cexp nan\n");
test_inf();
printf("ok 3 - cexp inf\n");
test_reals();
printf("ok 4 - cexp reals\n");
test_imaginaries();
printf("ok 5 - cexp imaginaries\n");
test_small();
printf("ok 6 - cexp small\n");
test_large();
printf("ok 7 - cexp large\n");
return (0);
} }

View File

@ -31,7 +31,6 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <assert.h>
#include <complex.h> #include <complex.h>
#include <fenv.h> #include <fenv.h>
#include <math.h> #include <math.h>
@ -70,70 +69,54 @@ static const double tests[] = {
-INFINITY, INFINITY, -INFINITY, INFINITY,
}; };
int ATF_TC_WITHOUT_HEAD(main);
main(void) ATF_TC_BODY(main, tc)
{ {
static const int ntests = sizeof(tests) / sizeof(tests[0]) / 2; static const int ntests = sizeof(tests) / sizeof(tests[0]) / 2;
complex float in; complex float in;
complex long double expected; complex long double expected;
int i; int i;
printf("1..%d\n", ntests * 3);
for (i = 0; i < ntests; i++) { for (i = 0; i < ntests; i++) {
__real__ expected = __real__ in = tests[2 * i]; __real__ expected = __real__ in = tests[2 * i];
__imag__ in = tests[2 * i + 1]; __imag__ in = tests[2 * i + 1];
__imag__ expected = -cimag(in); __imag__ expected = -cimag(in);
assert(fpequal(libcrealf(in), __real__ in)); ATF_REQUIRE(fpequal(libcrealf(in), __real__ in));
assert(fpequal(libcreal(in), __real__ in)); ATF_REQUIRE(fpequal(libcreal(in), __real__ in));
assert(fpequal(libcreall(in), __real__ in)); ATF_REQUIRE(fpequal(libcreall(in), __real__ in));
assert(fpequal(libcimagf(in), __imag__ in)); ATF_REQUIRE(fpequal(libcimagf(in), __imag__ in));
assert(fpequal(libcimag(in), __imag__ in)); ATF_REQUIRE(fpequal(libcimag(in), __imag__ in));
assert(fpequal(libcimagl(in), __imag__ in)); ATF_REQUIRE(fpequal(libcimagl(in), __imag__ in));
feclearexcept(FE_ALL_EXCEPT); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
if (!cfpequal(libconjf(in), expected)) { ATF_REQUIRE_MSG(
printf("not ok %d\t# conjf(%#.2g + %#.2gI): " cfpequal(libconjf(in), expected),
"wrong value\n", "conjf(%#.2g + %#.2gI): wrong value", creal(in), cimag(in)
3 * i + 1, creal(in), cimag(in)); );
} else if (fetestexcept(FE_ALL_EXCEPT)) { ATF_REQUIRE_EQ_MSG(0, fetestexcept(FE_ALL_EXCEPT),
printf("not ok %d\t# conjf(%#.2g + %#.2gI): " "conj(%#.2g + %#.2gI): threw an exception: %#x", creal(in),
"threw an exception\n", cimag(in), fetestexcept(FE_ALL_EXCEPT));
3 * i + 1, creal(in), cimag(in));
} else {
printf("ok %d\t\t# conjf(%#.2g + %#.2gI)\n",
3 * i + 1, creal(in), cimag(in));
}
feclearexcept(FE_ALL_EXCEPT); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
if (!cfpequal(libconj(in), expected)) { ATF_REQUIRE_MSG(cfpequal(libconj(in), expected),
printf("not ok %d\t# conj(%#.2g + %#.2gI): " "conj(%#.2g + %#.2gI): wrong value", creal(in), cimag(in));
"wrong value\n", ATF_REQUIRE_EQ_MSG(0, fetestexcept(FE_ALL_EXCEPT),
3 * i + 2, creal(in), cimag(in)); "conj(%#.2g + %#.2gI): threw an exception: %#x", creal(in),
} else if (fetestexcept(FE_ALL_EXCEPT)) { cimag(in), fetestexcept(FE_ALL_EXCEPT));
printf("not ok %d\t# conj(%#.2g + %#.2gI): "
"threw an exception\n",
3 * i + 2, creal(in), cimag(in));
} else {
printf("ok %d\t\t# conj(%#.2g + %#.2gI)\n",
3 * i + 2, creal(in), cimag(in));
}
feclearexcept(FE_ALL_EXCEPT); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
if (!cfpequal(libconjl(in), expected)) { ATF_REQUIRE_MSG(cfpequal(libconjl(in), expected),
printf("not ok %d\t# conjl(%#.2g + %#.2gI): " "conjl(%#.2g + %#.2gI): wrong value", creal(in), cimag(in));
"wrong value\n", ATF_REQUIRE_EQ_MSG(0, fetestexcept(FE_ALL_EXCEPT),
3 * i + 3, creal(in), cimag(in)); "conjl(%#.2g + %#.2gI): threw an exception: %#x", creal(in),
} else if (fetestexcept(FE_ALL_EXCEPT)) { cimag(in), fetestexcept(FE_ALL_EXCEPT));
printf("not ok %d\t# conjl(%#.2g + %#.2gI): "
"threw an exception\n",
3 * i + 3, creal(in), cimag(in));
} else {
printf("ok %d\t\t# conjl(%#.2g + %#.2gI)\n",
3 * i + 3, creal(in), cimag(in));
}
} }
}
return (0);
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, main);
return (atf_no_error());
} }

View File

@ -33,7 +33,6 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <assert.h>
#include <complex.h> #include <complex.h>
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
@ -72,7 +71,7 @@ static void
assert_equal(long double complex d1, long double complex d2) assert_equal(long double complex d1, long double complex d2)
{ {
assert(cfpequal(d1, d2)); ATF_CHECK(cfpequal(d1, d2));
} }
/* /*
@ -133,7 +132,7 @@ test_finite(void)
b = tests[i + 1] * mults[j] * mults[j]; b = tests[i + 1] * mults[j] * mults[j];
x = tests[i + 2] * mults[j]; x = tests[i + 2] * mults[j];
y = tests[i + 3] * mults[j]; y = tests[i + 3] * mults[j];
assert(t_csqrt(CMPLXL(a, b)) == CMPLXL(x, y)); ATF_CHECK(t_csqrt(CMPLXL(a, b)) == CMPLXL(x, y));
} }
} }
@ -190,11 +189,11 @@ static void
test_nans(void) test_nans(void)
{ {
assert(creall(t_csqrt(CMPLXL(INFINITY, NAN))) == INFINITY); ATF_CHECK(creall(t_csqrt(CMPLXL(INFINITY, NAN))) == INFINITY);
assert(isnan(cimagl(t_csqrt(CMPLXL(INFINITY, NAN))))); ATF_CHECK(isnan(cimagl(t_csqrt(CMPLXL(INFINITY, NAN)))));
assert(isnan(creall(t_csqrt(CMPLXL(-INFINITY, NAN))))); ATF_CHECK(isnan(creall(t_csqrt(CMPLXL(-INFINITY, NAN)))));
assert(isinf(cimagl(t_csqrt(CMPLXL(-INFINITY, NAN))))); ATF_CHECK(isinf(cimagl(t_csqrt(CMPLXL(-INFINITY, NAN)))));
assert_equal(t_csqrt(CMPLXL(NAN, INFINITY)), assert_equal(t_csqrt(CMPLXL(NAN, INFINITY)),
CMPLXL(INFINITY, INFINITY)); CMPLXL(INFINITY, INFINITY));
@ -224,7 +223,7 @@ test_overflow(int maxexp)
long double complex result; long double complex result;
int exp, i; int exp, i;
assert(maxexp > 0 && maxexp % 2 == 0); ATF_CHECK(maxexp > 0 && maxexp % 2 == 0);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
exp = maxexp - 2 * i; exp = maxexp - 2 * i;
@ -233,22 +232,22 @@ test_overflow(int maxexp)
a = ldexpl(115 * 0x1p-8, exp); a = ldexpl(115 * 0x1p-8, exp);
b = ldexpl(252 * 0x1p-8, exp); b = ldexpl(252 * 0x1p-8, exp);
result = t_csqrt(CMPLXL(a, b)); result = t_csqrt(CMPLXL(a, b));
assert(creall(result) == ldexpl(14 * 0x1p-4, exp / 2)); ATF_CHECK_EQ(creall(result), ldexpl(14 * 0x1p-4, exp / 2));
assert(cimagl(result) == ldexpl(9 * 0x1p-4, exp / 2)); ATF_CHECK_EQ(cimagl(result), ldexpl(9 * 0x1p-4, exp / 2));
/* csqrt(-11 + 60*I) = 5 + 6*I */ /* csqrt(-11 + 60*I) = 5 + 6*I */
a = ldexpl(-11 * 0x1p-6, exp); a = ldexpl(-11 * 0x1p-6, exp);
b = ldexpl(60 * 0x1p-6, exp); b = ldexpl(60 * 0x1p-6, exp);
result = t_csqrt(CMPLXL(a, b)); result = t_csqrt(CMPLXL(a, b));
assert(creall(result) == ldexpl(5 * 0x1p-3, exp / 2)); ATF_CHECK_EQ(creall(result), ldexpl(5 * 0x1p-3, exp / 2));
assert(cimagl(result) == ldexpl(6 * 0x1p-3, exp / 2)); ATF_CHECK_EQ(cimagl(result), ldexpl(6 * 0x1p-3, exp / 2));
/* csqrt(225 + 0*I) == 15 + 0*I */ /* csqrt(225 + 0*I) == 15 + 0*I */
a = ldexpl(225 * 0x1p-8, exp); a = ldexpl(225 * 0x1p-8, exp);
b = 0; b = 0;
result = t_csqrt(CMPLXL(a, b)); result = t_csqrt(CMPLXL(a, b));
assert(creall(result) == ldexpl(15 * 0x1p-4, exp / 2)); ATF_CHECK_EQ(creall(result), ldexpl(15 * 0x1p-4, exp / 2));
assert(cimagl(result) == 0); ATF_CHECK_EQ(cimagl(result), 0);
} }
} }
@ -266,8 +265,8 @@ test_precision(int maxexp, int mantdig)
uint64_t mantbits, sq_mantbits; uint64_t mantbits, sq_mantbits;
int exp, i; int exp, i;
assert(maxexp > 0 && maxexp % 2 == 0); ATF_CHECK(maxexp > 0 && maxexp % 2 == 0);
assert(mantdig <= 64); ATF_CHECK(mantdig <= 64);
mantdig = rounddown(mantdig, 2); mantdig = rounddown(mantdig, 2);
for (exp = 0; exp <= maxexp; exp += 2) { for (exp = 0; exp <= maxexp; exp += 2) {
@ -289,79 +288,67 @@ test_precision(int maxexp, int mantdig)
b = ldexpl((long double)sq_mantbits, b = ldexpl((long double)sq_mantbits,
exp - 1 - mantdig); exp - 1 - mantdig);
x = ldexpl(mantbits, (exp - 2 - mantdig) / 2); x = ldexpl(mantbits, (exp - 2 - mantdig) / 2);
assert(b == x * x * 2); ATF_CHECK_EQ(b, x * x * 2);
result = t_csqrt(CMPLXL(0, b)); result = t_csqrt(CMPLXL(0, b));
assert(creall(result) == x); ATF_CHECK_EQ(x, creall(result));
assert(cimagl(result) == x); ATF_CHECK_EQ(x, cimagl(result));
} }
} }
} }
int ATF_TC_WITHOUT_HEAD(csqrt);
main(void) ATF_TC_BODY(csqrt, tc)
{ {
printf("1..18\n");
/* Test csqrt() */ /* Test csqrt() */
t_csqrt = _csqrt; t_csqrt = _csqrt;
test_finite(); test_finite();
printf("ok 1 - csqrt\n");
test_zeros(); test_zeros();
printf("ok 2 - csqrt\n");
test_infinities(); test_infinities();
printf("ok 3 - csqrt\n");
test_nans(); test_nans();
printf("ok 4 - csqrt\n");
test_overflow(DBL_MAX_EXP); test_overflow(DBL_MAX_EXP);
printf("ok 5 - csqrt\n");
test_precision(DBL_MAX_EXP, DBL_MANT_DIG); test_precision(DBL_MAX_EXP, DBL_MANT_DIG);
printf("ok 6 - csqrt\n"); }
ATF_TC_WITHOUT_HEAD(csqrtf);
ATF_TC_BODY(csqrtf, tc)
{
/* Now test csqrtf() */ /* Now test csqrtf() */
t_csqrt = _csqrtf; t_csqrt = _csqrtf;
test_finite(); test_finite();
printf("ok 7 - csqrt\n");
test_zeros(); test_zeros();
printf("ok 8 - csqrt\n");
test_infinities(); test_infinities();
printf("ok 9 - csqrt\n");
test_nans(); test_nans();
printf("ok 10 - csqrt\n");
test_overflow(FLT_MAX_EXP); test_overflow(FLT_MAX_EXP);
printf("ok 11 - csqrt\n");
test_precision(FLT_MAX_EXP, FLT_MANT_DIG); test_precision(FLT_MAX_EXP, FLT_MANT_DIG);
printf("ok 12 - csqrt\n"); }
ATF_TC_WITHOUT_HEAD(csqrtl);
ATF_TC_BODY(csqrtl, tc)
{
/* Now test csqrtl() */ /* Now test csqrtl() */
t_csqrt = csqrtl; t_csqrt = csqrtl;
test_finite(); test_finite();
printf("ok 13 - csqrt\n");
test_zeros(); test_zeros();
printf("ok 14 - csqrt\n");
test_infinities(); test_infinities();
printf("ok 15 - csqrt\n");
test_nans(); test_nans();
printf("ok 16 - csqrt\n");
test_overflow(LDBL_MAX_EXP); test_overflow(LDBL_MAX_EXP);
printf("ok 17 - csqrt\n");
test_precision(LDBL_MAX_EXP, test_precision(LDBL_MAX_EXP,
#ifndef __i386__ #ifndef __i386__
@ -370,7 +357,13 @@ main(void)
DBL_MANT_DIG DBL_MANT_DIG
#endif #endif
); );
printf("ok 18 - csqrt\n"); }
return (0); ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, csqrt);
ATF_TP_ADD_TC(tp, csqrtf);
ATF_TP_ADD_TC(tp, csqrtl);
return (atf_no_error());
} }

View File

@ -38,8 +38,6 @@ __FBSDID("$FreeBSD$");
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include <atf-c.h>
#include "test-utils.h" #include "test-utils.h"
#pragma STDC FENV_ACCESS ON #pragma STDC FENV_ACCESS ON

View File

@ -31,7 +31,6 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <assert.h>
#include <fenv.h> #include <fenv.h>
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
@ -60,9 +59,10 @@ __FBSDID("$FreeBSD$");
*/ */
#define test(func, x, result, exceptmask, excepts) do { \ #define test(func, x, result, exceptmask, excepts) do { \
volatile long double _d = x; \ volatile long double _d = x; \
assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT)); \
assert(fpequal((func)(_d), (result))); \ ATF_CHECK(fpequal((func)(_d), (result))); \
assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ CHECK_FP_EXCEPTIONS_MSG(excepts, exceptmask, "for %s(%s)", \
#func, #x); \
} while (0) } while (0)
/* Test all the functions that compute b^x. */ /* Test all the functions that compute b^x. */
@ -122,48 +122,66 @@ run_generic_tests(void)
testall1(-50000.0, -1.0, ALL_STD_EXCEPT, FE_INEXACT); testall1(-50000.0, -1.0, ALL_STD_EXCEPT, FE_INEXACT);
} }
static void
run_exp2_tests(void)
{
unsigned i;
/* /*
* We should insist that exp2() return exactly the correct * We should insist that exp2() return exactly the correct
* result and not raise an inexact exception for integer * result and not raise an inexact exception for integer
* arguments. * arguments.
*/ */
feclearexcept(FE_ALL_EXCEPT); ATF_TC_WITHOUT_HEAD(exp2f);
for (i = FLT_MIN_EXP - FLT_MANT_DIG; i < FLT_MAX_EXP; i++) { ATF_TC_BODY(exp2f, tc)
assert(exp2f(i) == ldexpf(1.0, i)); {
assert(fetestexcept(ALL_STD_EXCEPT) == 0); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
} for (int i = FLT_MIN_EXP - FLT_MANT_DIG; i < FLT_MAX_EXP; i++) {
for (i = DBL_MIN_EXP - DBL_MANT_DIG; i < DBL_MAX_EXP; i++) { ATF_CHECK_EQ(exp2f(i), ldexpf(1.0, i));
assert(exp2(i) == ldexp(1.0, i)); CHECK_FP_EXCEPTIONS(0, ALL_STD_EXCEPT);
assert(fetestexcept(ALL_STD_EXCEPT) == 0);
}
for (i = LDBL_MIN_EXP - LDBL_MANT_DIG; i < LDBL_MAX_EXP; i++) {
assert(exp2l(i) == ldexpl(1.0, i));
assert(fetestexcept(ALL_STD_EXCEPT) == 0);
} }
} }
int ATF_TC_WITHOUT_HEAD(exp2);
main(void) ATF_TC_BODY(exp2, tc)
{ {
ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
for (int i = DBL_MIN_EXP - DBL_MANT_DIG; i < DBL_MAX_EXP; i++) {
ATF_CHECK_EQ(exp2(i), ldexp(1.0, i));
CHECK_FP_EXCEPTIONS(0, ALL_STD_EXCEPT);
}
}
printf("1..3\n"); ATF_TC_WITHOUT_HEAD(exp2l);
ATF_TC_BODY(exp2l, tc)
{
ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
for (int i = LDBL_MIN_EXP - LDBL_MANT_DIG; i < LDBL_MAX_EXP; i++) {
ATF_CHECK_EQ(exp2l(i), ldexpl(1.0, i));
CHECK_FP_EXCEPTIONS(0, ALL_STD_EXCEPT);
}
}
ATF_TC_WITHOUT_HEAD(generic);
ATF_TC_BODY(generic, tc)
{
run_generic_tests(); run_generic_tests();
printf("ok 1 - exponential\n"); }
#ifdef __i386__ #ifdef __i386__
ATF_TC_WITHOUT_HEAD(generic_fp_pe);
ATF_TC_BODY(generic_fp_pe, tc)
{
fpsetprec(FP_PE); fpsetprec(FP_PE);
run_generic_tests(); run_generic_tests();
#endif }
printf("ok 2 - exponential\n"); #endif
run_exp2_tests(); ATF_TP_ADD_TCS(tp)
printf("ok 3 - exponential\n"); {
ATF_TP_ADD_TC(tp, generic);
return (0); #ifdef __i386__
ATF_TP_ADD_TC(tp, generic_fp_pe);
#endif
ATF_TP_ADD_TC(tp, exp2);
ATF_TP_ADD_TC(tp, exp2f);
ATF_TP_ADD_TC(tp, exp2l);
return (atf_no_error());
} }

View File

@ -63,11 +63,14 @@ static int std_except_sets[1 << NEXCEPTS];
/* /*
* Initialize std_except_sets[] to the power set of std_excepts[] * Initialize std_except_sets[] to the power set of std_excepts[]
*/ */
static void static __attribute__((constructor)) void
init_exceptsets(void) do_setup(void)
{ {
unsigned i, j, sr; unsigned i, j, sr;
/* Avoid double output after fork() */
setvbuf(stdout, NULL, _IONBF, 0);
for (i = 0; i < 1 << NEXCEPTS; i++) { for (i = 0; i < 1 << NEXCEPTS; i++) {
for (sr = i, j = 0; sr != 0; sr >>= 1, j++) for (sr = i, j = 0; sr != 0; sr >>= 1, j++)
std_except_sets[i] |= std_excepts[j] & ((~sr & 1) - 1); std_except_sets[i] |= std_excepts[j] & ((~sr & 1) - 1);
@ -154,7 +157,7 @@ static void
trap_handler(int sig) trap_handler(int sig)
{ {
assert(sig == SIGFPE); ATF_CHECK_EQ(SIGFPE, sig);
_exit(0); _exit(0);
} }
@ -163,8 +166,8 @@ trap_handler(int sig)
* The memcmp() test below may be too much to ask for, since there * The memcmp() test below may be too much to ask for, since there
* could be multiple machine-specific default environments. * could be multiple machine-specific default environments.
*/ */
static void ATF_TC_WITHOUT_HEAD(dfl_env);
test_dfl_env(void) ATF_TC_BODY(dfl_env, tc)
{ {
#ifndef NO_STRICT_DFL_ENV #ifndef NO_STRICT_DFL_ENV
fenv_t env; fenv_t env;
@ -186,52 +189,51 @@ test_dfl_env(void)
* 1. http://support.amd.com/TechDocs/26569_APM_v5.pdf * 1. http://support.amd.com/TechDocs/26569_APM_v5.pdf
* 2. http://www.intel.com/Assets/en_US/PDF/manual/253666.pdf * 2. http://www.intel.com/Assets/en_US/PDF/manual/253666.pdf
*/ */
assert(memcmp(&env.__mxcsr, &FE_DFL_ENV->__mxcsr, ATF_CHECK(memcmp(&env.__mxcsr, &FE_DFL_ENV->__mxcsr,
sizeof(env.__mxcsr)) == 0); sizeof(env.__mxcsr)) == 0);
assert(memcmp(&env.__x87.__control, &FE_DFL_ENV->__x87.__control, ATF_CHECK(memcmp(&env.__x87.__control, &FE_DFL_ENV->__x87.__control,
sizeof(env.__x87.__control)) == 0); sizeof(env.__x87.__control)) == 0);
assert(memcmp(&env.__x87.__status, &FE_DFL_ENV->__x87.__status, ATF_CHECK(memcmp(&env.__x87.__status, &FE_DFL_ENV->__x87.__status,
sizeof(env.__x87.__status)) == 0); sizeof(env.__x87.__status)) == 0);
assert(memcmp(&env.__x87.__tag, &FE_DFL_ENV->__x87.__tag, ATF_CHECK(memcmp(&env.__x87.__tag, &FE_DFL_ENV->__x87.__tag,
sizeof(env.__x87.__tag)) == 0); sizeof(env.__x87.__tag)) == 0);
#else #else
assert(memcmp(&env, FE_DFL_ENV, sizeof(env)) == 0); ATF_CHECK_EQ(0, memcmp(&env, FE_DFL_ENV, sizeof(env)));
#endif #endif
#endif #endif
assert(fetestexcept(FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
} }
/* /*
* Test fetestexcept() and feclearexcept(). * Test fetestexcept() and feclearexcept().
*/ */
static void ATF_TC_WITHOUT_HEAD(fetestclearexcept);
test_fetestclearexcept(void) ATF_TC_BODY(fetestclearexcept, tc)
{ {
int excepts, i; int excepts, i;
for (i = 0; i < 1 << NEXCEPTS; i++) for (i = 0; i < 1 << NEXCEPTS; i++)
assert(fetestexcept(std_except_sets[i]) == 0); ATF_CHECK_EQ(0, fetestexcept(std_except_sets[i]));
for (i = 0; i < 1 << NEXCEPTS; i++) { for (i = 0; i < 1 << NEXCEPTS; i++) {
excepts = std_except_sets[i]; excepts = std_except_sets[i];
/* FE_ALL_EXCEPT might be special-cased, as on i386. */ /* FE_ALL_EXCEPT might be special-cased, as on i386. */
raiseexcept(excepts); raiseexcept(excepts);
assert(fetestexcept(excepts) == excepts); ATF_CHECK_EQ(excepts, fetestexcept(excepts));
assert(feclearexcept(FE_ALL_EXCEPT) == 0); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
assert(fetestexcept(FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
raiseexcept(excepts); raiseexcept(excepts);
assert(fetestexcept(excepts) == excepts); ATF_CHECK_EQ(excepts, fetestexcept(excepts));
if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0) { if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0) {
excepts |= FE_INEXACT; excepts |= FE_INEXACT;
assert((fetestexcept(ALL_STD_EXCEPT) | FE_INEXACT) == ATF_CHECK_EQ(excepts, (fetestexcept(ALL_STD_EXCEPT) | FE_INEXACT));
excepts);
} else { } else {
assert(fetestexcept(ALL_STD_EXCEPT) == excepts); ATF_CHECK_EQ(excepts, fetestexcept(ALL_STD_EXCEPT));
} }
assert(feclearexcept(excepts) == 0); ATF_CHECK_EQ(0, feclearexcept(excepts));
assert(fetestexcept(ALL_STD_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(ALL_STD_EXCEPT));
} }
} }
@ -240,31 +242,29 @@ test_fetestclearexcept(void)
* *
* Prerequisites: fetestexcept(), feclearexcept() * Prerequisites: fetestexcept(), feclearexcept()
*/ */
static void ATF_TC_WITHOUT_HEAD(fegsetexceptflag);
test_fegsetexceptflag(void) ATF_TC_BODY(fegsetexceptflag, tc)
{ {
fexcept_t flag; fexcept_t flag;
int excepts, i; int excepts, i;
assert(fetestexcept(FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
for (i = 0; i < 1 << NEXCEPTS; i++) { for (i = 0; i < 1 << NEXCEPTS; i++) {
excepts = std_except_sets[i]; excepts = std_except_sets[i];
assert(fegetexceptflag(&flag, excepts) == 0); ATF_CHECK_EQ(0, fegetexceptflag(&flag, excepts));
raiseexcept(ALL_STD_EXCEPT); raiseexcept(ALL_STD_EXCEPT);
assert(fesetexceptflag(&flag, excepts) == 0); ATF_CHECK_EQ(0, fesetexceptflag(&flag, excepts));
assert(fetestexcept(ALL_STD_EXCEPT) == ATF_CHECK_EQ((ALL_STD_EXCEPT ^ excepts), fetestexcept(ALL_STD_EXCEPT));
(ALL_STD_EXCEPT ^ excepts));
assert(fegetexceptflag(&flag, FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fegetexceptflag(&flag, FE_ALL_EXCEPT));
assert(feclearexcept(FE_ALL_EXCEPT) == 0); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
assert(fesetexceptflag(&flag, excepts) == 0); ATF_CHECK_EQ(0, fesetexceptflag(&flag, excepts));
assert(fetestexcept(ALL_STD_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(ALL_STD_EXCEPT));
assert(fesetexceptflag(&flag, ALL_STD_EXCEPT ^ excepts) == 0); ATF_CHECK_EQ(0, fesetexceptflag(&flag, ALL_STD_EXCEPT ^ excepts));
assert(fetestexcept(ALL_STD_EXCEPT) == ATF_CHECK_EQ((ALL_STD_EXCEPT ^ excepts), fetestexcept(ALL_STD_EXCEPT));
(ALL_STD_EXCEPT ^ excepts));
assert(feclearexcept(FE_ALL_EXCEPT) == 0); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
} }
} }
@ -273,63 +273,62 @@ test_fegsetexceptflag(void)
* *
* Prerequisites: fetestexcept(), feclearexcept() * Prerequisites: fetestexcept(), feclearexcept()
*/ */
static void ATF_TC_WITHOUT_HEAD(feraiseexcept);
test_feraiseexcept(void) ATF_TC_BODY(feraiseexcept, tc)
{ {
int excepts, i; int excepts, i;
for (i = 0; i < 1 << NEXCEPTS; i++) { for (i = 0; i < 1 << NEXCEPTS; i++) {
excepts = std_except_sets[i]; excepts = std_except_sets[i];
assert(fetestexcept(FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
assert(feraiseexcept(excepts) == 0); ATF_CHECK_EQ(0, feraiseexcept(excepts));
if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0) { if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0) {
excepts |= FE_INEXACT; excepts |= FE_INEXACT;
assert((fetestexcept(ALL_STD_EXCEPT) | FE_INEXACT) == ATF_CHECK_EQ(excepts, (fetestexcept(ALL_STD_EXCEPT) | FE_INEXACT));
excepts);
} else { } else {
assert(fetestexcept(ALL_STD_EXCEPT) == excepts); ATF_CHECK_EQ(excepts, fetestexcept(ALL_STD_EXCEPT));
} }
assert(feclearexcept(FE_ALL_EXCEPT) == 0); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
} }
assert(feraiseexcept(FE_INVALID | FE_DIVBYZERO) == 0); ATF_CHECK_EQ(0, feraiseexcept(FE_INVALID | FE_DIVBYZERO));
assert(fetestexcept(ALL_STD_EXCEPT) == (FE_INVALID | FE_DIVBYZERO)); ATF_CHECK_EQ((FE_INVALID | FE_DIVBYZERO), fetestexcept(ALL_STD_EXCEPT));
assert(feraiseexcept(FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) == 0); ATF_CHECK_EQ(0, feraiseexcept(FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT));
assert(fetestexcept(ALL_STD_EXCEPT) == ALL_STD_EXCEPT); ATF_CHECK_EQ(ALL_STD_EXCEPT, fetestexcept(ALL_STD_EXCEPT));
assert(feclearexcept(FE_ALL_EXCEPT) == 0); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
} }
/* /*
* Test fegetround() and fesetround(). * Test fegetround() and fesetround().
*/ */
static void ATF_TC_WITHOUT_HEAD(fegsetround);
test_fegsetround(void) ATF_TC_BODY(fegsetround, tc)
{ {
assert(fegetround() == FE_TONEAREST); ATF_CHECK_EQ(FE_TONEAREST, fegetround());
assert(getround() == FE_TONEAREST); ATF_CHECK_EQ(FE_TONEAREST, getround());
assert(FLT_ROUNDS == 1); ATF_CHECK_EQ(1, FLT_ROUNDS);
assert(fesetround(FE_DOWNWARD) == 0); ATF_CHECK_EQ(0, fesetround(FE_DOWNWARD));
assert(fegetround() == FE_DOWNWARD); ATF_CHECK_EQ(FE_DOWNWARD, fegetround());
assert(getround() == FE_DOWNWARD); ATF_CHECK_EQ(FE_DOWNWARD, getround());
assert(FLT_ROUNDS == 3); ATF_CHECK_EQ(3, FLT_ROUNDS);
assert(fesetround(FE_UPWARD) == 0); ATF_CHECK_EQ(0, fesetround(FE_UPWARD));
assert(getround() == FE_UPWARD); ATF_CHECK_EQ(FE_UPWARD, getround());
assert(fegetround() == FE_UPWARD); ATF_CHECK_EQ(FE_UPWARD, fegetround());
assert(FLT_ROUNDS == 2); ATF_CHECK_EQ(2, FLT_ROUNDS);
assert(fesetround(FE_TOWARDZERO) == 0); ATF_CHECK_EQ(0, fesetround(FE_TOWARDZERO));
assert(getround() == FE_TOWARDZERO); ATF_CHECK_EQ(FE_TOWARDZERO, getround());
assert(fegetround() == FE_TOWARDZERO); ATF_CHECK_EQ(FE_TOWARDZERO, fegetround());
assert(FLT_ROUNDS == 0); ATF_CHECK_EQ(0, FLT_ROUNDS);
assert(fesetround(FE_TONEAREST) == 0); ATF_CHECK_EQ(0, fesetround(FE_TONEAREST));
assert(getround() == FE_TONEAREST); ATF_CHECK_EQ(FE_TONEAREST, getround());
assert(FLT_ROUNDS == 1); ATF_CHECK_EQ(1, FLT_ROUNDS);
assert(feclearexcept(FE_ALL_EXCEPT) == 0); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
} }
/* /*
@ -337,8 +336,8 @@ test_fegsetround(void)
* *
* Prerequisites: fetestexcept(), feclearexcept(), fegetround(), fesetround() * Prerequisites: fetestexcept(), feclearexcept(), fegetround(), fesetround()
*/ */
static void ATF_TC_WITHOUT_HEAD(fegsetenv);
test_fegsetenv(void) ATF_TC_BODY(fegsetenv, tc)
{ {
fenv_t env1, env2; fenv_t env1, env2;
int excepts, i; int excepts, i;
@ -346,9 +345,9 @@ test_fegsetenv(void)
for (i = 0; i < 1 << NEXCEPTS; i++) { for (i = 0; i < 1 << NEXCEPTS; i++) {
excepts = std_except_sets[i]; excepts = std_except_sets[i];
assert(fetestexcept(FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
assert(fegetround() == FE_TONEAREST); ATF_CHECK_EQ(FE_TONEAREST, fegetround());
assert(fegetenv(&env1) == 0); ATF_CHECK_EQ(0, fegetenv(&env1));
/* /*
* fe[gs]etenv() should be able to save and restore * fe[gs]etenv() should be able to save and restore
@ -358,26 +357,26 @@ test_fegsetenv(void)
raiseexcept(excepts); raiseexcept(excepts);
if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0 && if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0 &&
(excepts & FE_INEXACT) == 0) (excepts & FE_INEXACT) == 0)
assert(feclearexcept(FE_INEXACT) == 0); ATF_CHECK_EQ(0, feclearexcept(FE_INEXACT));
fesetround(FE_DOWNWARD); fesetround(FE_DOWNWARD);
assert(fegetenv(&env2) == 0); ATF_CHECK_EQ(0, fegetenv(&env2));
assert(fesetenv(&env1) == 0); ATF_CHECK_EQ(0, fesetenv(&env1));
assert(fetestexcept(FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
assert(fegetround() == FE_TONEAREST); ATF_CHECK_EQ(FE_TONEAREST, fegetround());
assert(fesetenv(&env2) == 0); ATF_CHECK_EQ(0, fesetenv(&env2));
/* /*
* Some platforms like powerpc may set extra exception bits. Since * Some platforms like powerpc may set extra exception bits. Since
* only standard exceptions are tested, mask against ALL_STD_EXCEPT * only standard exceptions are tested, mask against ALL_STD_EXCEPT
*/ */
assert((fetestexcept(FE_ALL_EXCEPT) & ALL_STD_EXCEPT) == excepts); ATF_CHECK_EQ(excepts, (fetestexcept(FE_ALL_EXCEPT) & ALL_STD_EXCEPT));
assert(fegetround() == FE_DOWNWARD); ATF_CHECK_EQ(FE_DOWNWARD, fegetround());
assert(fesetenv(&env1) == 0); ATF_CHECK_EQ(0, fesetenv(&env1));
assert(fetestexcept(FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
assert(fegetround() == FE_TONEAREST); ATF_CHECK_EQ(FE_TONEAREST, fegetround());
} }
} }
@ -386,23 +385,20 @@ test_fegsetenv(void)
* *
* Prerequisites: fetestexcept(), feraiseexcept() * Prerequisites: fetestexcept(), feraiseexcept()
*/ */
static void ATF_TC_WITHOUT_HEAD(masking);
test_masking(void) ATF_TC_BODY(masking, tc)
{ {
struct sigaction act; struct sigaction act;
int except, pass, raise, status; int except, pass, raise, status;
unsigned i; unsigned i;
assert((fegetexcept() & ALL_STD_EXCEPT) == 0); ATF_CHECK_EQ(0, (fegetexcept() & ALL_STD_EXCEPT));
assert((feenableexcept(FE_INVALID|FE_OVERFLOW) & ALL_STD_EXCEPT) == 0); ATF_CHECK_EQ(0, (feenableexcept(FE_INVALID|FE_OVERFLOW) & ALL_STD_EXCEPT));
assert((feenableexcept(FE_UNDERFLOW) & ALL_STD_EXCEPT) == ATF_CHECK_EQ((FE_INVALID | FE_OVERFLOW), (feenableexcept(FE_UNDERFLOW) & ALL_STD_EXCEPT));
(FE_INVALID | FE_OVERFLOW)); ATF_CHECK_EQ((FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW), (fedisableexcept(FE_OVERFLOW) & ALL_STD_EXCEPT));
assert((fedisableexcept(FE_OVERFLOW) & ALL_STD_EXCEPT) == ATF_CHECK_EQ((FE_INVALID | FE_UNDERFLOW), (fegetexcept() & ALL_STD_EXCEPT));
(FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)); ATF_CHECK_EQ((FE_INVALID | FE_UNDERFLOW), (fedisableexcept(FE_ALL_EXCEPT) & ALL_STD_EXCEPT));
assert((fegetexcept() & ALL_STD_EXCEPT) == (FE_INVALID | FE_UNDERFLOW)); ATF_CHECK_EQ(0, (fegetexcept() & ALL_STD_EXCEPT));
assert((fedisableexcept(FE_ALL_EXCEPT) & ALL_STD_EXCEPT) ==
(FE_INVALID | FE_UNDERFLOW));
assert((fegetexcept() & ALL_STD_EXCEPT) == 0);
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
act.sa_flags = 0; act.sa_flags = 0;
@ -423,40 +419,39 @@ test_masking(void)
*/ */
switch(fork()) { switch(fork()) {
case 0: /* child */ case 0: /* child */
assert((fegetexcept() & ALL_STD_EXCEPT) == 0); ATF_CHECK_EQ(0, (fegetexcept() & ALL_STD_EXCEPT));
assert((feenableexcept(except) ATF_REQUIRE_EQ(0, (feenableexcept(except) & ALL_STD_EXCEPT));
& ALL_STD_EXCEPT) == 0); ATF_CHECK_EQ(except, fegetexcept());
assert(fegetexcept() == except);
raiseexcept(raise); raiseexcept(raise);
assert(feraiseexcept(raise) == 0); ATF_CHECK_EQ(0, feraiseexcept(raise));
assert(fetestexcept(ALL_STD_EXCEPT) == raise); ATF_CHECK_EQ(raise, fetestexcept(ALL_STD_EXCEPT));
assert(sigaction(SIGFPE, &act, NULL) == 0); ATF_CHECK_EQ(0, sigaction(SIGFPE, &act, NULL));
switch (pass) { switch (pass) {
case 0: case 0:
raiseexcept(except); raiseexcept(except);
case 1: case 1:
feraiseexcept(except); feraiseexcept(except);
default: default:
assert(0); ATF_REQUIRE(0);
} }
assert(0); ATF_REQUIRE(0);
default: /* parent */ default: /* parent */
assert(wait(&status) > 0); ATF_REQUIRE(wait(&status) > 0);
/* /*
* Avoid assert() here so that it's possible * Avoid assert() here so that it's possible
* to examine a failed child's core dump. * to examine a failed child's core dump.
*/ */
if (!WIFEXITED(status)) if (!WIFEXITED(status))
errx(1, "child aborted\n"); errx(1, "child aborted\n");
assert(WEXITSTATUS(status) == 0); ATF_CHECK_EQ(0, WEXITSTATUS(status));
break; break;
case -1: /* error */ case -1: /* error */
assert(0); ATF_REQUIRE(0);
} }
} }
} }
assert(fetestexcept(FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
} }
/* /*
@ -465,8 +460,8 @@ test_masking(void)
* Prerequisites: fetestexcept(), fegetround(), fesetround(), * Prerequisites: fetestexcept(), fegetround(), fesetround(),
* fedisableexcept(), feenableexcept() * fedisableexcept(), feenableexcept()
*/ */
static void ATF_TC_WITHOUT_HEAD(feholdupdate);
test_feholdupdate(void) ATF_TC_BODY(feholdupdate, tc)
{ {
fenv_t env; fenv_t env;
@ -499,67 +494,50 @@ test_feholdupdate(void)
* check other properties of feupdateenv(). * check other properties of feupdateenv().
*/ */
if (pass == 1) if (pass == 1)
assert((feenableexcept(except) & ATF_REQUIRE_EQ(0, feenableexcept(except) & ALL_STD_EXCEPT);
ALL_STD_EXCEPT) == 0);
raiseexcept(raise); raiseexcept(raise);
assert(fesetround(FE_DOWNWARD) == 0); ATF_CHECK_EQ(0, fesetround(FE_DOWNWARD));
assert(feholdexcept(&env) == 0); ATF_CHECK_EQ(0, feholdexcept(&env));
assert(fetestexcept(FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
raiseexcept(except); raiseexcept(except);
assert(fesetround(FE_UPWARD) == 0); ATF_CHECK_EQ(0, fesetround(FE_UPWARD));
if (pass == 1) if (pass == 1)
assert(sigaction(SIGFPE, &act, NULL) == ATF_CHECK_EQ(0, sigaction(SIGFPE, &act, NULL));
0); ATF_CHECK_EQ(0, feupdateenv(&env));
assert(feupdateenv(&env) == 0); ATF_CHECK_EQ(FE_DOWNWARD, fegetround());
assert(fegetround() == FE_DOWNWARD); ATF_CHECK_EQ((except | raise), fetestexcept(ALL_STD_EXCEPT));
assert(fetestexcept(ALL_STD_EXCEPT) ==
(except | raise));
assert(pass == 0); ATF_CHECK_EQ(0, pass);
_exit(0); _exit(0);
default: /* parent */ default: /* parent */
assert(wait(&status) > 0); ATF_REQUIRE(wait(&status) > 0);
/* /*
* Avoid assert() here so that it's possible * Avoid assert() here so that it's possible
* to examine a failed child's core dump. * to examine a failed child's core dump.
*/ */
if (!WIFEXITED(status)) if (!WIFEXITED(status))
errx(1, "child aborted\n"); errx(1, "child aborted\n");
assert(WEXITSTATUS(status) == 0); ATF_CHECK_EQ(0, WEXITSTATUS(status));
break; break;
case -1: /* error */ case -1: /* error */
assert(0); ATF_REQUIRE(0);
} }
} }
} }
assert(fetestexcept(FE_ALL_EXCEPT) == 0); ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
} }
int ATF_TP_ADD_TCS(tp)
main(void)
{ {
/* Avoid double output after fork() */ ATF_TP_ADD_TC(tp, dfl_env);
setvbuf(stdout, NULL, _IONBF, 0); ATF_TP_ADD_TC(tp, fetestclearexcept);
ATF_TP_ADD_TC(tp, fegsetexceptflag);
ATF_TP_ADD_TC(tp, feraiseexcept);
ATF_TP_ADD_TC(tp, fegsetround);
ATF_TP_ADD_TC(tp, fegsetenv);
ATF_TP_ADD_TC(tp, masking);
ATF_TP_ADD_TC(tp, feholdupdate);
printf("1..8\n"); return (atf_no_error());
init_exceptsets();
test_dfl_env();
printf("ok 1 - fenv\n");
test_fetestclearexcept();
printf("ok 2 - fenv\n");
test_fegsetexceptflag();
printf("ok 3 - fenv\n");
test_feraiseexcept();
printf("ok 4 - fenv\n");
test_fegsetround();
printf("ok 5 - fenv\n");
test_fegsetenv();
printf("ok 6 - fenv\n");
test_masking();
printf("ok 7 - fenv\n");
test_feholdupdate();
printf("ok 8 - fenv\n");
return (0);
} }

View File

@ -32,7 +32,6 @@
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <assert.h>
#include <fenv.h> #include <fenv.h>
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
@ -55,9 +54,10 @@ __FBSDID("$FreeBSD$");
*/ */
#define test(func, x, y, z, result, exceptmask, excepts) do { \ #define test(func, x, y, z, result, exceptmask, excepts) do { \
volatile long double _vx = (x), _vy = (y), _vz = (z); \ volatile long double _vx = (x), _vy = (y), _vz = (z); \
assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_CHECK(feclearexcept(FE_ALL_EXCEPT) == 0); \
assert(fpequal((func)(_vx, _vy, _vz), (result))); \ ATF_CHECK(fpequal((func)(_vx, _vy, _vz), (result))); \
assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ CHECK_FP_EXCEPTIONS_MSG(excepts, exceptmask, "for %s(%s)", \
#func, #x); \
} while (0) } while (0)
#define testall(x, y, z, result, exceptmask, excepts) do { \ #define testall(x, y, z, result, exceptmask, excepts) do { \
@ -124,7 +124,6 @@ test_zeroes(void)
static void static void
test_infinities(void) test_infinities(void)
{ {
testall(INFINITY, 1.0, -1.0, INFINITY, ALL_STD_EXCEPT, 0); testall(INFINITY, 1.0, -1.0, INFINITY, ALL_STD_EXCEPT, 0);
testall(-1.0, INFINITY, 0.0, -INFINITY, ALL_STD_EXCEPT, 0); testall(-1.0, INFINITY, 0.0, -INFINITY, ALL_STD_EXCEPT, 0);
testall(0.0, 0.0, INFINITY, INFINITY, ALL_STD_EXCEPT, 0); testall(0.0, 0.0, INFINITY, INFINITY, ALL_STD_EXCEPT, 0);
@ -161,7 +160,6 @@ test_infinities(void)
static void static void
test_nans(void) test_nans(void)
{ {
testall(NAN, 0.0, 0.0, NAN, ALL_STD_EXCEPT, 0); testall(NAN, 0.0, 0.0, NAN, ALL_STD_EXCEPT, 0);
testall(1.0, NAN, 1.0, NAN, ALL_STD_EXCEPT, 0); testall(1.0, NAN, 1.0, NAN, ALL_STD_EXCEPT, 0);
testall(1.0, -1.0, NAN, NAN, ALL_STD_EXCEPT, 0); testall(1.0, -1.0, NAN, NAN, ALL_STD_EXCEPT, 0);
@ -184,7 +182,6 @@ test_nans(void)
static void static void
test_small_z(void) test_small_z(void)
{ {
/* x*y positive, z positive */ /* x*y positive, z positive */
if (fegetround() == FE_UPWARD) { if (fegetround() == FE_UPWARD) {
test(fmaf, one, one, 0x1.0p-100, 1.0 + FLT_EPSILON, test(fmaf, one, one, 0x1.0p-100, 1.0 + FLT_EPSILON,
@ -244,7 +241,6 @@ test_small_z(void)
static void static void
test_big_z(void) test_big_z(void)
{ {
/* z positive, x*y positive */ /* z positive, x*y positive */
if (fegetround() == FE_UPWARD) { if (fegetround() == FE_UPWARD) {
test(fmaf, 0x1.0p-50, 0x1.0p-50, 1.0, 1.0 + FLT_EPSILON, test(fmaf, 0x1.0p-50, 0x1.0p-50, 1.0, 1.0 + FLT_EPSILON,
@ -471,74 +467,88 @@ test_double_rounding(void)
} }
int static const int rmodes[] = {
main(void) FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO
};
ATF_TC_WITHOUT_HEAD(zeroes);
ATF_TC_BODY(zeroes, tc)
{ {
int rmodes[] = { FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO }; for (size_t i = 0; i < nitems(rmodes); i++) {
unsigned i, j;
#if defined(__i386__)
printf("1..0 # SKIP all testcases fail on i386\n");
exit(0);
#endif
j = 1;
printf("1..19\n");
for (i = 0; i < nitems(rmodes); i++, j++) {
printf("rmode = %d\n", rmodes[i]); printf("rmode = %d\n", rmodes[i]);
fesetround(rmodes[i]); fesetround(rmodes[i]);
test_zeroes(); test_zeroes();
printf("ok %d - fma zeroes\n", j);
} }
}
for (i = 0; i < nitems(rmodes); i++, j++) { ATF_TC_WITHOUT_HEAD(infinities);
ATF_TC_BODY(infinities, tc)
{
#if defined(__amd64__) #if defined(__amd64__)
printf("ok %d # SKIP testcase fails assertion on " if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
"amd64\n", j); atf_tc_expect_fail("https://bugs.freebsd.org/205448");
continue; #endif
#else for (size_t i = 0; i < nitems(rmodes); i++) {
printf("rmode = %d\n", rmodes[i]); printf("rmode = %d\n", rmodes[i]);
fesetround(rmodes[i]); fesetround(rmodes[i]);
test_infinities(); test_infinities();
printf("ok %d - fma infinities\n", j);
#endif
} }
}
ATF_TC_WITHOUT_HEAD(nans);
ATF_TC_BODY(nans, tc)
{
fesetround(FE_TONEAREST); fesetround(FE_TONEAREST);
test_nans(); test_nans();
printf("ok %d - fma NaNs\n", j); }
j++;
for (i = 0; i < nitems(rmodes); i++, j++) {
ATF_TC_WITHOUT_HEAD(small_z);
ATF_TC_BODY(small_z, tc)
{
for (size_t i = 0; i < nitems(rmodes); i++) {
printf("rmode = %d\n", rmodes[i]); printf("rmode = %d\n", rmodes[i]);
fesetround(rmodes[i]); fesetround(rmodes[i]);
test_small_z(); test_small_z();
printf("ok %d - fma small z\n", j);
} }
}
for (i = 0; i < nitems(rmodes); i++, j++) {
ATF_TC_WITHOUT_HEAD(big_z);
ATF_TC_BODY(big_z, tc)
{
for (size_t i = 0; i < nitems(rmodes); i++) {
printf("rmode = %d\n", rmodes[i]); printf("rmode = %d\n", rmodes[i]);
fesetround(rmodes[i]); fesetround(rmodes[i]);
test_big_z(); test_big_z();
printf("ok %d - fma big z\n", j);
} }
}
ATF_TC_WITHOUT_HEAD(accuracy);
ATF_TC_BODY(accuracy, tc)
{
fesetround(FE_TONEAREST); fesetround(FE_TONEAREST);
test_accuracy(); test_accuracy();
printf("ok %d - fma accuracy\n", j); }
j++;
ATF_TC_WITHOUT_HEAD(double_rounding);
ATF_TC_BODY(double_rounding, tc) {
test_double_rounding(); test_double_rounding();
printf("ok %d - fma double rounding\n", j); }
j++;
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, zeroes);
ATF_TP_ADD_TC(tp, infinities);
ATF_TP_ADD_TC(tp, nans);
ATF_TP_ADD_TC(tp, small_z);
ATF_TP_ADD_TC(tp, big_z);
ATF_TP_ADD_TC(tp, accuracy);
ATF_TP_ADD_TC(tp, double_rounding);
/* /*
* TODO: * TODO:
* - Tests for subnormals * - Tests for subnormals
* - Cancellation tests (e.g., z = (double)x*y, but x*y is inexact) * - Cancellation tests (e.g., z = (double)x*y, but x*y is inexact)
*/ */
return (atf_no_error());
return (0);
} }

View File

@ -44,57 +44,44 @@ __FBSDID("$FreeBSD$");
* Test whether func(x, y) has the expected result, and make sure no * Test whether func(x, y) has the expected result, and make sure no
* exceptions are raised. * exceptions are raised.
*/ */
#define TEST(func, type, x, y, expected) do { \ #define TEST(func, type, x, y, expected, rmode) do { \
type __x = (x); /* convert before we clear exceptions */ \ type __x = (x); /* convert before we clear exceptions */ \
type __y = (y); \ type __y = (y); \
feclearexcept(ALL_STD_EXCEPT); \ ATF_REQUIRE_EQ(0, feclearexcept(ALL_STD_EXCEPT)); \
long double __result = func((__x), (__y)); \ long double __result = func((__x), (__y)); \
if (fetestexcept(ALL_STD_EXCEPT)) { \ CHECK_FP_EXCEPTIONS_MSG(0, ALL_STD_EXCEPT, \
fprintf(stderr, #func "(%.20Lg, %.20Lg) raised 0x%x\n", \ #func "(%.20Lg, %.20Lg) rmode%d", (x), (y), rmode); \
(x), (y), fetestexcept(FE_ALL_EXCEPT)); \ ATF_CHECK_MSG(fpequal(__result, (expected)), \
ok = 0; \ #func "(%.20Lg, %.20Lg) rmode%d = %.20Lg, expected %.20Lg\n", \
} \ (x), (y), rmode, __result, (expected)); \
if (!fpequal(__result, (expected))) { \
fprintf(stderr, #func "(%.20Lg, %.20Lg) = %.20Lg, " \
"expected %.20Lg\n", (x), (y), __result, (expected)); \
ok = 0; \
} \
} while (0) } while (0)
static int static void
testall_r(long double big, long double small) testall_r(long double big, long double small, int rmode)
{ {
int ok;
long double expected_max = isnan(big) ? small : big; long double expected_max = isnan(big) ? small : big;
long double expected_min = isnan(small) ? big : small; long double expected_min = isnan(small) ? big : small;
ok = 1; TEST(fmaxf, float, big, small, expected_max, rmode);
TEST(fmaxf, float, small, big, expected_max, rmode);
TEST(fmaxf, float, big, small, expected_max); TEST(fmax, double, big, small, expected_max, rmode);
TEST(fmaxf, float, small, big, expected_max); TEST(fmax, double, small, big, expected_max, rmode);
TEST(fmax, double, big, small, expected_max); TEST(fmaxl, long double, big, small, expected_max, rmode);
TEST(fmax, double, small, big, expected_max); TEST(fmaxl, long double, small, big, expected_max, rmode);
TEST(fmaxl, long double, big, small, expected_max); TEST(fminf, float, big, small, expected_min, rmode);
TEST(fmaxl, long double, small, big, expected_max); TEST(fminf, float, small, big, expected_min, rmode);
TEST(fminf, float, big, small, expected_min); TEST(fmin, double, big, small, expected_min, rmode);
TEST(fminf, float, small, big, expected_min); TEST(fmin, double, small, big, expected_min, rmode);
TEST(fmin, double, big, small, expected_min); TEST(fminl, long double, big, small, expected_min, rmode);
TEST(fmin, double, small, big, expected_min); TEST(fminl, long double, small, big, expected_min, rmode);
TEST(fminl, long double, big, small, expected_min);
TEST(fminl, long double, small, big, expected_min);
return (ok);
} }
static const char *comment = NULL;
/* /*
* Test all the functions: fmaxf, fmax, fmaxl, fminf, fmin, and fminl, * Test all the functions: fmaxf, fmax, fmaxl, fminf, fmin, and fminl,
* in all rounding modes and with the arguments in different orders. * in all rounding modes and with the arguments in different orders.
* The input 'big' must be >= 'small'. * The input 'big' must be >= 'small'.
*/ */
static void static void
testall(int testnum, long double big, long double small) testall(long double big, long double small)
{ {
static const int rmodes[] = { static const int rmodes[] = {
FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO
@ -103,15 +90,8 @@ testall(int testnum, long double big, long double small)
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
fesetround(rmodes[i]); fesetround(rmodes[i]);
if (!testall_r(big, small)) { testall_r(big, small, rmodes[i]);
fprintf(stderr, "FAILURE in rounding mode %d\n",
rmodes[i]);
break;
}
} }
printf("%sok %d - big = %.20Lg, small = %.20Lg%s\n",
(i == 4) ? "" : "not ", testnum, big, small,
comment == NULL ? "" : comment);
} }
/* Clang 3.8.0+ fails the invariants for testcase 6, 7, 10, and 11. */ /* Clang 3.8.0+ fails the invariants for testcase 6, 7, 10, and 11. */
@ -121,34 +101,104 @@ testall(int testnum, long double big, long double small)
#define affected_by_bug_208703 #define affected_by_bug_208703
#endif #endif
int ATF_TC_WITHOUT_HEAD(test1);
main(void) ATF_TC_BODY(test1, tc)
{ {
testall(1.0, 0.0);
printf("1..12\n"); }
testall(1, 1.0, 0.0); ATF_TC_WITHOUT_HEAD(test2);
testall(2, 42.0, nextafterf(42.0, -INFINITY)); ATF_TC_BODY(test2, tc)
testall(3, nextafterf(42.0, INFINITY), 42.0); {
testall(4, -5.0, -5.0); testall(42.0, nextafterf(42.0, -INFINITY));
testall(5, -3.0, -4.0); }
#ifdef affected_by_bug_208703 ATF_TC_WITHOUT_HEAD(test3);
comment = "# TODO: testcase 6-7 fails invariant with clang 3.8+ (bug 208703)"; ATF_TC_BODY(test3, tc)
#endif {
testall(6, 1.0, NAN); testall(nextafterf(42.0, INFINITY), 42.0);
testall(7, INFINITY, NAN); }
comment = NULL;
testall(8, INFINITY, 1.0); ATF_TC_WITHOUT_HEAD(test4);
testall(9, -3.0, -INFINITY); ATF_TC_BODY(test4, tc)
testall(10, 3.0, -INFINITY); {
#ifdef affected_by_bug_208703 testall(-5.0, -5.0);
comment = "# TODO: testcase 11-12 fails invariant with clang 3.8+ (bug 208703)"; }
#endif
testall(11, NAN, NAN); ATF_TC_WITHOUT_HEAD(test5);
ATF_TC_BODY(test5, tc)
/* This test isn't strictly required to work by C99. */ {
testall(12, 0.0, -0.0); testall(-3.0, -4.0);
comment = NULL; }
return (0); ATF_TC_WITHOUT_HEAD(test6);
ATF_TC_BODY(test6, tc)
{
#ifdef affected_by_bug_208703
atf_tc_expect_fail("fails invariant with clang 3.8+ (bug 208703)");
#endif
testall(1.0, NAN);
}
ATF_TC_WITHOUT_HEAD(test7);
ATF_TC_BODY(test7, tc)
{
#ifdef affected_by_bug_208703
atf_tc_expect_fail("fails invariant with clang 3.8+ (bug 208703)");
#endif
testall(INFINITY, NAN);
}
ATF_TC_WITHOUT_HEAD(test8);
ATF_TC_BODY(test8, tc)
{
testall(INFINITY, 1.0);
}
ATF_TC_WITHOUT_HEAD(test9);
ATF_TC_BODY(test9, tc)
{
testall(-3.0, -INFINITY);
}
ATF_TC_WITHOUT_HEAD(test10);
ATF_TC_BODY(test10, tc)
{
#ifdef affected_by_bug_208703
atf_tc_expect_fail("fails invariant with clang 3.8+ (bug 208703)");
#endif
testall(3.0, -INFINITY);
}
ATF_TC_WITHOUT_HEAD(test11);
ATF_TC_BODY(test11, tc)
{
#ifdef affected_by_bug_208703
atf_tc_expect_fail("fails invariant with clang 3.8+ (bug 208703)");
#endif
testall(NAN, NAN);
}
ATF_TC_WITHOUT_HEAD(test12);
ATF_TC_BODY(test12, tc)
{
/* This test isn't strictly required to work by C99. */
testall(0.0, -0.0);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, test1);
ATF_TP_ADD_TC(tp, test2);
ATF_TP_ADD_TC(tp, test3);
ATF_TP_ADD_TC(tp, test4);
ATF_TP_ADD_TC(tp, test5);
ATF_TP_ADD_TC(tp, test6);
ATF_TP_ADD_TC(tp, test7);
ATF_TP_ADD_TC(tp, test8);
ATF_TP_ADD_TC(tp, test9);
ATF_TP_ADD_TC(tp, test10);
ATF_TP_ADD_TC(tp, test11);
ATF_TP_ADD_TC(tp, test12);
return (atf_no_error());
} }

View File

@ -26,58 +26,78 @@
* $FreeBSD$ * $FreeBSD$
*/ */
#include <assert.h>
#include <float.h> #include <float.h>
#include <limits.h> #include <limits.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int #include "test-utils.h"
main(void)
ATF_TC_WITHOUT_HEAD(ilogb);
ATF_TC_BODY(ilogb, tc)
{ {
char buf[128], *end; char buf[128], *end;
double d; double d;
float f;
long double ld;
int e, i; int e, i;
printf("1..3\n"); ATF_CHECK_EQ(FP_ILOGB0, ilogb(0));
assert(ilogb(0) == FP_ILOGB0); ATF_CHECK_EQ(FP_ILOGBNAN, ilogb(NAN));
assert(ilogb(NAN) == FP_ILOGBNAN); ATF_CHECK_EQ(INT_MAX, ilogb(INFINITY));
assert(ilogb(INFINITY) == INT_MAX);
for (e = DBL_MIN_EXP - DBL_MANT_DIG; e < DBL_MAX_EXP; e++) { for (e = DBL_MIN_EXP - DBL_MANT_DIG; e < DBL_MAX_EXP; e++) {
snprintf(buf, sizeof(buf), "0x1.p%d", e); snprintf(buf, sizeof(buf), "0x1.p%d", e);
d = strtod(buf, &end); d = strtod(buf, &end);
assert(*end == '\0'); ATF_CHECK_EQ('\0', *end);
i = ilogb(d); i = ilogb(d);
assert(i == e); ATF_CHECK_EQ_MSG(e, i, "ilogb(%g) returned %d not %d", d, i, e);
} }
printf("ok 1 - ilogb\n"); }
assert(ilogbf(0) == FP_ILOGB0); ATF_TC_WITHOUT_HEAD(ilogbf);
assert(ilogbf(NAN) == FP_ILOGBNAN); ATF_TC_BODY(ilogbf, tc)
assert(ilogbf(INFINITY) == INT_MAX); {
char buf[128], *end;
float f;
int e, i;
ATF_CHECK_EQ(FP_ILOGB0, ilogbf(0));
ATF_CHECK_EQ(FP_ILOGBNAN, ilogbf(NAN));
ATF_CHECK_EQ(INT_MAX, ilogbf(INFINITY));
for (e = FLT_MIN_EXP - FLT_MANT_DIG; e < FLT_MAX_EXP; e++) { for (e = FLT_MIN_EXP - FLT_MANT_DIG; e < FLT_MAX_EXP; e++) {
snprintf(buf, sizeof(buf), "0x1.p%d", e); snprintf(buf, sizeof(buf), "0x1.p%d", e);
f = strtof(buf, &end); f = strtof(buf, &end);
assert(*end == '\0'); ATF_CHECK_EQ('\0', *end);
i = ilogbf(f); i = ilogbf(f);
assert(i == e); ATF_CHECK_EQ_MSG(e, i, "ilogbf(%g) returned %d not %d", f, i,
e);
} }
printf("ok 2 - ilogbf\n"); }
assert(ilogbl(0) == FP_ILOGB0); ATF_TC_WITHOUT_HEAD(ilogbl);
assert(ilogbl(NAN) == FP_ILOGBNAN); ATF_TC_BODY(ilogbl, tc)
assert(ilogbl(INFINITY) == INT_MAX); {
char buf[128], *end;
long double ld;
int e, i;
ATF_CHECK_EQ(FP_ILOGB0, ilogbl(0));
ATF_CHECK_EQ(FP_ILOGBNAN, ilogbl(NAN));
ATF_CHECK_EQ(INT_MAX, ilogbl(INFINITY));
for (e = LDBL_MIN_EXP - LDBL_MANT_DIG; e < LDBL_MAX_EXP; e++) { for (e = LDBL_MIN_EXP - LDBL_MANT_DIG; e < LDBL_MAX_EXP; e++) {
snprintf(buf, sizeof(buf), "0x1.p%d", e); snprintf(buf, sizeof(buf), "0x1.p%d", e);
ld = strtold(buf, &end); ld = strtold(buf, &end);
assert(*end == '\0'); ATF_CHECK_EQ('\0', *end);
i = ilogbl(ld); i = ilogbl(ld);
assert(i == e); ATF_CHECK_EQ_MSG(e, i, "ilogbl(%Lg) returned %d not %d", ld, i,
e);
} }
printf("ok 3 - ilogbl\n"); }
return (0); ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, ilogb);
ATF_TP_ADD_TC(tp, ilogbf);
ATF_TP_ADD_TC(tp, ilogbl);
return (atf_no_error());
} }

View File

@ -32,7 +32,6 @@
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <assert.h>
#include <complex.h> #include <complex.h>
#include <fenv.h> #include <fenv.h>
#include <float.h> #include <float.h>
@ -61,9 +60,10 @@ __FBSDID("$FreeBSD$");
volatile long double complex _d = z; \ volatile long double complex _d = z; \
debug(" testing %s(%Lg + %Lg I) == %Lg + %Lg I\n", #func, \ debug(" testing %s(%Lg + %Lg I) == %Lg + %Lg I\n", #func, \
creall(_d), cimagl(_d), creall(result), cimagl(result)); \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \
assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT)); \
assert(cfpequal_cs((func)(_d), (result), (checksign))); \ ATF_CHECK(cfpequal_cs((func)(_d), (result), (checksign))); \
assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ CHECK_FP_EXCEPTIONS_MSG(excepts, exceptmask, "for %s(%s)", \
#func, #z); \
} while (0) } while (0)
/* /*
@ -74,7 +74,7 @@ __FBSDID("$FreeBSD$");
volatile long double complex _d = z; \ volatile long double complex _d = z; \
debug(" testing %s(%Lg + %Lg I) ~= %Lg + %Lg I\n", #func, \ debug(" testing %s(%Lg + %Lg I) ~= %Lg + %Lg I\n", #func, \
creall(_d), cimagl(_d), creall(result), cimagl(result)); \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \
assert(cfpequal_tol((func)(_d), (result), (tol), CS_BOTH)); \ ATF_CHECK(cfpequal_tol((func)(_d), (result), (tol), CS_BOTH)); \
} while (0) } while (0)
/* These wrappers apply the identities f(conj(z)) = conj(f(z)). */ /* These wrappers apply the identities f(conj(z)) = conj(f(z)). */
@ -124,8 +124,8 @@ c3pi = 9.42477796076937971538793014983850839L;
/* Tests for 0 */ /* Tests for 0 */
static void ATF_TC_WITHOUT_HEAD(zero);
test_zero(void) ATF_TC_BODY(zero, tc)
{ {
long double complex zero = CMPLXL(0.0, 0.0); long double complex zero = CMPLXL(0.0, 0.0);
@ -144,8 +144,8 @@ test_zero(void)
/* /*
* Tests for NaN inputs. * Tests for NaN inputs.
*/ */
static void ATF_TC_WITHOUT_HEAD(nan);
test_nan(void) ATF_TC_BODY(nan, tc)
{ {
long double complex nan_nan = CMPLXL(NAN, NAN); long double complex nan_nan = CMPLXL(NAN, NAN);
long double complex z; long double complex z;
@ -223,8 +223,8 @@ test_nan(void)
testall(catan, z, CMPLXL(NAN, 0.0), ALL_STD_EXCEPT, 0, 0); testall(catan, z, CMPLXL(NAN, 0.0), ALL_STD_EXCEPT, 0, 0);
} }
static void ATF_TC_WITHOUT_HEAD(inf);
test_inf(void) ATF_TC_BODY(inf, tc)
{ {
long double complex z; long double complex z;
@ -270,8 +270,8 @@ test_inf(void)
} }
/* Tests along the real and imaginary axes. */ /* Tests along the real and imaginary axes. */
static void ATF_TC_WITHOUT_HEAD(axes);
test_axes(void) ATF_TC_BODY(axes, tc)
{ {
static const long double nums[] = { static const long double nums[] = {
-2, -1, -0.5, 0.5, 1, 2 -2, -1, -0.5, 0.5, 1, 2
@ -307,8 +307,8 @@ test_axes(void)
} }
} }
static void ATF_TC_WITHOUT_HEAD(small);
test_small(void) ATF_TC_BODY(small, tc)
{ {
/* /*
* z = 0.75 + i 0.25 * z = 0.75 + i 0.25
@ -333,36 +333,20 @@ test_small(void)
} }
/* Test inputs that might cause overflow in a sloppy implementation. */ /* Test inputs that might cause overflow in a sloppy implementation. */
static void ATF_TC_WITHOUT_HEAD(large);
test_large(void) ATF_TC_BODY(large, tc)
{ {
/* TODO: Write these tests */ /* TODO: Write these tests */
} }
int ATF_TP_ADD_TCS(tp)
main(void)
{ {
ATF_TP_ADD_TC(tp, zero);
ATF_TP_ADD_TC(tp, nan);
ATF_TP_ADD_TC(tp, inf);
ATF_TP_ADD_TC(tp, axes);
ATF_TP_ADD_TC(tp, small);
ATF_TP_ADD_TC(tp, large);
printf("1..6\n"); return (atf_no_error());
test_zero();
printf("ok 1 - invctrig zero\n");
test_nan();
printf("ok 2 - invctrig nan\n");
test_inf();
printf("ok 3 - invctrig inf\n");
test_axes();
printf("ok 4 - invctrig axes\n");
test_small();
printf("ok 5 - invctrig small\n");
test_large();
printf("ok 6 - invctrig large\n");
return (0);
} }

View File

@ -33,7 +33,6 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <assert.h>
#include <fenv.h> #include <fenv.h>
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
@ -54,9 +53,10 @@ __FBSDID("$FreeBSD$");
*/ */
#define test_tol(func, x, result, tol, excepts) do { \ #define test_tol(func, x, result, tol, excepts) do { \
volatile long double _in = (x), _out = (result); \ volatile long double _in = (x), _out = (result); \
assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT)); \
assert(fpequal_tol(func(_in), _out, (tol), CS_BOTH)); \ ATF_CHECK(fpequal_tol(func(_in), _out, (tol), CS_BOTH)); \
assert(((void)func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ CHECK_FP_EXCEPTIONS_MSG(excepts, ALL_STD_EXCEPT, "for %s(%s)", \
#func, #x); \
} while (0) } while (0)
#define test(func, x, result, excepts) \ #define test(func, x, result, excepts) \
test_tol(func, (x), (result), 0, (excepts)) test_tol(func, (x), (result), 0, (excepts))
@ -83,9 +83,10 @@ __FBSDID("$FreeBSD$");
#define test2_tol(func, y, x, result, tol, excepts) do { \ #define test2_tol(func, y, x, result, tol, excepts) do { \
volatile long double _iny = (y), _inx = (x), _out = (result); \ volatile long double _iny = (y), _inx = (x), _out = (result); \
assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT)); \
assert(fpequal_tol(func(_iny, _inx), _out, (tol), CS_BOTH)); \ ATF_CHECK(fpequal_tol(func(_iny, _inx), _out, (tol), CS_BOTH)); \
assert(((void)func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ CHECK_FP_EXCEPTIONS_MSG(excepts, ALL_STD_EXCEPT, "for %s(%s)", \
#func, #x); \
} while (0) } while (0)
#define test2(func, y, x, result, excepts) \ #define test2(func, y, x, result, excepts) \
test2_tol(func, (y), (x), (result), 0, (excepts)) test2_tol(func, (y), (x), (result), 0, (excepts))
@ -123,8 +124,8 @@ sqrt2m1 = 4.14213562373095048801688724209698081e-01L;
* Test special case inputs in asin(), acos() and atan(): signed * Test special case inputs in asin(), acos() and atan(): signed
* zeroes, infinities, and NaNs. * zeroes, infinities, and NaNs.
*/ */
static void ATF_TC_WITHOUT_HEAD(special);
test_special(void) ATF_TC_BODY(special, tc)
{ {
testall(asin, 0.0, 0.0, 0); testall(asin, 0.0, 0.0, 0);
@ -150,8 +151,8 @@ test_special(void)
* Test special case inputs in atan2(), where the exact value of y/x is * Test special case inputs in atan2(), where the exact value of y/x is
* zero or non-finite. * zero or non-finite.
*/ */
static void ATF_TC_WITHOUT_HEAD(special_atan2);
test_special_atan2(void) ATF_TC_BODY(special_atan2, tc)
{ {
long double z; long double z;
int e; int e;
@ -236,8 +237,8 @@ test_special_atan2(void)
* Test various inputs to asin(), acos() and atan() and verify that the * Test various inputs to asin(), acos() and atan() and verify that the
* results are accurate to within 1 ulp. * results are accurate to within 1 ulp.
*/ */
static void ATF_TC_WITHOUT_HEAD(accuracy);
test_accuracy(void) ATF_TC_BODY(accuracy, tc)
{ {
/* We expect correctly rounded results for these basic cases. */ /* We expect correctly rounded results for these basic cases. */
@ -274,8 +275,8 @@ test_accuracy(void)
* Test inputs to atan2() where x is a power of 2. These are easy cases * Test inputs to atan2() where x is a power of 2. These are easy cases
* because y/x is exact. * because y/x is exact.
*/ */
static void ATF_TC_WITHOUT_HEAD(p2x_atan2);
test_p2x_atan2(void) ATF_TC_BODY(p2x_atan2, tc)
{ {
testall2(atan2, 1.0, 1.0, pi / 4, FE_INEXACT); testall2(atan2, 1.0, 1.0, pi / 4, FE_INEXACT);
@ -297,8 +298,8 @@ test_p2x_atan2(void)
/* /*
* Test inputs very close to 0. * Test inputs very close to 0.
*/ */
static void ATF_TC_WITHOUT_HEAD(tiny);
test_tiny(void) ATF_TC_BODY(tiny, tc)
{ {
float tiny = 0x1.23456p-120f; float tiny = 0x1.23456p-120f;
@ -332,8 +333,8 @@ test_tiny(void)
/* /*
* Test very large inputs to atan(). * Test very large inputs to atan().
*/ */
static void ATF_TC_WITHOUT_HEAD(atan_huge);
test_atan_huge(void) ATF_TC_BODY(atan_huge, tc)
{ {
float huge = 0x1.23456p120; float huge = 0x1.23456p120;
@ -428,8 +429,8 @@ tanatanl(long double x)
return (tanl(atanl(x))); return (tanl(atanl(x)));
} }
static void ATF_TC_WITHOUT_HEAD(inverse);
test_inverse(void) ATF_TC_BODY(inverse, tc)
{ {
float i; float i;
@ -442,37 +443,15 @@ test_inverse(void)
} }
} }
int ATF_TP_ADD_TCS(tp)
main(void)
{ {
ATF_TP_ADD_TC(tp, special);
ATF_TP_ADD_TC(tp, special_atan2);
ATF_TP_ADD_TC(tp, accuracy);
ATF_TP_ADD_TC(tp, p2x_atan2);
ATF_TP_ADD_TC(tp, tiny);
ATF_TP_ADD_TC(tp, atan_huge);
ATF_TP_ADD_TC(tp, inverse);
#if defined(__i386__) return (atf_no_error());
printf("1..0 # SKIP fails all assertions on i386\n");
return (0);
#endif
printf("1..7\n");
test_special();
printf("ok 1 - special\n");
test_special_atan2();
printf("ok 2 - atan2 special\n");
test_accuracy();
printf("ok 3 - accuracy\n");
test_p2x_atan2();
printf("ok 4 - atan2 p2x\n");
test_tiny();
printf("ok 5 - tiny inputs\n");
test_atan_huge();
printf("ok 6 - atan huge inputs\n");
test_inverse();
printf("ok 7 - inverse\n");
return (0);
} }

View File

@ -32,7 +32,6 @@
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <assert.h>
#include <fenv.h> #include <fenv.h>
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
@ -59,24 +58,18 @@ __FBSDID("$FreeBSD$");
* XXX The volatile here is to avoid gcc's bogus constant folding and work * XXX The volatile here is to avoid gcc's bogus constant folding and work
* around the lack of support for the FENV_ACCESS pragma. * around the lack of support for the FENV_ACCESS pragma.
*/ */
#define test(func, x, result, exceptmask, excepts) do { \ #define test(func, x, result, exceptmask, excepts) do { \
volatile long double _d = x; \ volatile long double _d = x; \
assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_CHECK_EQ(0, feclearexcept(FE_ALL_EXCEPT)); \
assert(fpequal((func)(_d), (result))); \ ATF_CHECK(fpequal((func)(_d), (result))); \
assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ CHECK_FP_EXCEPTIONS_MSG(excepts, exceptmask, "for %s(%s)", \
} while (0) #func, #x); \
#define test(func, x, result, exceptmask, excepts) do { \
volatile long double _d = x; \
assert(feclearexcept(FE_ALL_EXCEPT) == 0); \
assert(fpequal((func)(_d), (result))); \
assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \
} while (0) } while (0)
#define test_tol(func, z, result, tol) do { \ #define test_tol(func, z, result, tol) do { \
volatile long double _d = z; \ volatile long double _d = z; \
debug(" testing %6s(%15La) ~= % .36Le\n", #func, _d, result); \ debug(" testing %6s(%15La) ~= % .36Le\n", #func, _d, result); \
assert(fpequal_tol((func)(_d), (result), (tol), CS_BOTH)); \ ATF_CHECK(fpequal_tol((func)(_d), (result), (tol), CS_BOTH)); \
} while (0) } while (0)
/* Test all the functions that compute log(x). */ /* Test all the functions that compute log(x). */
@ -99,8 +92,8 @@ __FBSDID("$FreeBSD$");
test(log1pl, x, result, exceptmask, excepts); \ test(log1pl, x, result, exceptmask, excepts); \
} while (0) } while (0)
static void ATF_TC_WITHOUT_HEAD(generic_tests);
run_generic_tests(void) ATF_TC_BODY(generic_tests, tc)
{ {
/* log(1) == 0, no exceptions raised */ /* log(1) == 0, no exceptions raised */
@ -128,8 +121,8 @@ run_generic_tests(void)
testall1(-1.0, -INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_DIVBYZERO); testall1(-1.0, -INFINITY, ALL_STD_EXCEPT & ~FE_INEXACT, FE_DIVBYZERO);
} }
static void ATF_TC_WITHOUT_HEAD(log2_tests);
run_log2_tests(void) ATF_TC_BODY(log2_tests, tc)
{ {
unsigned i; unsigned i;
@ -137,26 +130,23 @@ run_log2_tests(void)
* We should insist that log2() return exactly the correct * We should insist that log2() return exactly the correct
* result and not raise an inexact exception for powers of 2. * result and not raise an inexact exception for powers of 2.
*/ */
assert(feclearexcept(FE_ALL_EXCEPT) == 0); ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
for (i = FLT_MIN_EXP - FLT_MANT_DIG; i < FLT_MAX_EXP; i++) { for (i = FLT_MIN_EXP - FLT_MANT_DIG; i < FLT_MAX_EXP; i++) {
assert(log2f(ldexpf(1.0, i)) == i); ATF_CHECK_EQ(i, log2f(ldexpf(1.0, i)));
assert(fetestexcept(ALL_STD_EXCEPT) == 0); CHECK_FP_EXCEPTIONS(0, ALL_STD_EXCEPT);
} }
for (i = DBL_MIN_EXP - DBL_MANT_DIG; i < DBL_MAX_EXP; i++) { for (i = DBL_MIN_EXP - DBL_MANT_DIG; i < DBL_MAX_EXP; i++) {
assert(log2(ldexp(1.0, i)) == i); ATF_CHECK_EQ(i, log2(ldexp(1.0, i)));
assert(fetestexcept(ALL_STD_EXCEPT) == 0); CHECK_FP_EXCEPTIONS(0, ALL_STD_EXCEPT);
} }
for (i = LDBL_MIN_EXP - LDBL_MANT_DIG; i < LDBL_MAX_EXP; i++) { for (i = LDBL_MIN_EXP - LDBL_MANT_DIG; i < LDBL_MAX_EXP; i++) {
assert(log2l(ldexpl(1.0, i)) == i); ATF_CHECK_EQ(i, log2l(ldexpl(1.0, i)));
#if 0 CHECK_FP_EXCEPTIONS(0, ALL_STD_EXCEPT);
/* XXX This test does not pass yet. */
assert(fetestexcept(ALL_STD_EXCEPT) == 0);
#endif
} }
} }
static void ATF_TC_WITHOUT_HEAD(roundingmode_tests);
run_roundingmode_tests(void) ATF_TC_BODY(roundingmode_tests, tc)
{ {
/* /*
@ -189,8 +179,8 @@ run_roundingmode_tests(void)
fesetround(FE_TONEAREST); fesetround(FE_TONEAREST);
} }
static void ATF_TC_WITHOUT_HEAD(accuracy_tests);
run_accuracy_tests(void) ATF_TC_BODY(accuracy_tests, tc)
{ {
static const struct { static const struct {
float x; float x;
@ -243,10 +233,9 @@ run_accuracy_tests(void)
} }
} }
static void ATF_TC_WITHOUT_HEAD(log1p_accuracy_tests);
run_log1p_accuracy_tests(void) ATF_TC_BODY(log1p_accuracy_tests, tc)
{ {
test_tol(log1pf, 0x0.333333p0F, test_tol(log1pf, 0x0.333333p0F,
1.82321546859847114303367992804596800640e-1L, FLT_ULP()); 1.82321546859847114303367992804596800640e-1L, FLT_ULP());
test_tol(log1p, 0x0.3333333333333p0, test_tol(log1p, 0x0.3333333333333p0,
@ -262,26 +251,14 @@ run_log1p_accuracy_tests(void)
-2.23143551314209755752742563153765697950e-1L, LDBL_ULP()); -2.23143551314209755752742563153765697950e-1L, LDBL_ULP());
} }
int ATF_TP_ADD_TCS(tp)
main(void)
{ {
printf("1..5\n"); ATF_TP_ADD_TC(tp, generic_tests);
ATF_TP_ADD_TC(tp, log2_tests);
ATF_TP_ADD_TC(tp, roundingmode_tests);
ATF_TP_ADD_TC(tp, accuracy_tests);
ATF_TP_ADD_TC(tp, log1p_accuracy_tests);
run_generic_tests(); return (atf_no_error());
printf("ok 1 - logarithm\n");
run_log2_tests();
printf("ok 2 - logarithm\n");
run_roundingmode_tests();
printf("ok 3 - logarithm\n");
run_accuracy_tests();
printf("ok 4 - logarithm\n");
run_log1p_accuracy_tests();
printf("ok 5 - logarithm\n");
return (0);
} }

View File

@ -31,7 +31,6 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <assert.h>
#include <fenv.h> #include <fenv.h>
#include <limits.h> #include <limits.h>
#include <math.h> #include <math.h>
@ -49,10 +48,10 @@ __FBSDID("$FreeBSD$");
*/ */
#define test(func, x, result, excepts) do { \ #define test(func, x, result, excepts) do { \
volatile double _d = x; \ volatile double _d = x; \
assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_CHECK(feclearexcept(FE_ALL_EXCEPT) == 0); \
assert((func)(_d) == (result) || fetestexcept(FE_INVALID)); \ ATF_CHECK((func)(_d) == (result) || fetestexcept(FE_INVALID)); \
assert((fetestexcept(FE_ALL_EXCEPT) & ALL_STD_EXCEPT) \ CHECK_FP_EXCEPTIONS_MSG(excepts, FE_ALL_EXCEPT & ALL_STD_EXCEPT,\
== (excepts)); \ "for %s(%s)", #func, #x); \
} while (0) } while (0)
#define testall(x, result, excepts) do { \ #define testall(x, result, excepts) do { \
@ -71,12 +70,11 @@ __FBSDID("$FreeBSD$");
static void static void
run_tests(void) run_tests(void)
{ {
ATF_REQUIRE_EQ(0, fesetround(FE_DOWNWARD));
assert(fesetround(FE_DOWNWARD) == 0);
testall(0.75, 0, FE_INEXACT); testall(0.75, 0, FE_INEXACT);
testall(-0.5, -1, FE_INEXACT); testall(-0.5, -1, FE_INEXACT);
assert(fesetround(FE_TONEAREST) == 0); ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST));
testall(0.0, 0, 0); testall(0.0, 0, 0);
testall(0.25, 0, FE_INEXACT); testall(0.25, 0, FE_INEXACT);
testall(0.5, 0, FE_INEXACT); testall(0.5, 0, FE_INEXACT);
@ -88,65 +86,64 @@ run_tests(void)
testall(NAN, IGNORE, FE_INVALID); testall(NAN, IGNORE, FE_INVALID);
#if (LONG_MAX == 0x7fffffffl) #if (LONG_MAX == 0x7fffffffl)
assert(fesetround(FE_UPWARD) == 0); ATF_REQUIRE_EQ(0, fesetround(FE_UPWARD));
test(lrint, 0x7fffffff.8p0, IGNORE, FE_INVALID); test(lrint, 0x7fffffff.8p0, IGNORE, FE_INVALID);
test(lrint, -0x80000000.4p0, -0x80000000l, FE_INEXACT); test(lrint, -0x80000000.4p0, (long)-0x80000000l, FE_INEXACT);
assert(fesetround(FE_DOWNWARD) == 0); ATF_REQUIRE_EQ(0, fesetround(FE_DOWNWARD));
test(lrint, -0x80000000.8p0, IGNORE, FE_INVALID); test(lrint, -0x80000000.8p0, IGNORE, FE_INVALID);
test(lrint, 0x80000000.0p0, IGNORE, FE_INVALID); test(lrint, 0x80000000.0p0, IGNORE, FE_INVALID);
test(lrint, 0x7fffffff.4p0, 0x7fffffffl, FE_INEXACT); test(lrint, 0x7fffffff.4p0, 0x7fffffffl, FE_INEXACT);
test(lrintf, 0x80000000.0p0f, IGNORE, FE_INVALID); test(lrintf, 0x80000000.0p0f, IGNORE, FE_INVALID);
test(lrintf, 0x7fffff80.0p0f, 0x7fffff80l, 0); test(lrintf, 0x7fffff80.0p0f, 0x7fffff80l, 0);
assert(fesetround(FE_TOWARDZERO) == 0); ATF_REQUIRE_EQ(0, fesetround(FE_TOWARDZERO));
test(lrint, 0x7fffffff.8p0, 0x7fffffffl, FE_INEXACT); test(lrint, 0x7fffffff.8p0, 0x7fffffffl, FE_INEXACT);
test(lrint, -0x80000000.8p0, -0x80000000l, FE_INEXACT); test(lrint, -0x80000000.8p0, -0x80000000l, FE_INEXACT);
test(lrint, 0x80000000.0p0, IGNORE, FE_INVALID); test(lrint, 0x80000000.0p0, IGNORE, FE_INVALID);
test(lrintf, 0x80000000.0p0f, IGNORE, FE_INVALID); test(lrintf, 0x80000000.0p0f, IGNORE, FE_INVALID);
test(lrintf, 0x7fffff80.0p0f, 0x7fffff80l, 0); test(lrintf, 0x7fffff80.0p0f, 0x7fffff80l, 0);
#elif (LONG_MAX == 0x7fffffffffffffffll) #elif (LONG_MAX == 0x7fffffffffffffffll)
assert(fesetround(FE_TONEAREST) == 0); ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST));
test(lrint, 0x8000000000000000.0p0, IGNORE, FE_INVALID); test(lrint, 0x8000000000000000.0p0, IGNORE, FE_INVALID);
test(lrintf, 0x8000000000000000.0p0f, IGNORE, FE_INVALID); test(lrintf, 0x8000000000000000.0p0f, IGNORE, FE_INVALID);
test(lrint, 0x7ffffffffffffc00.0p0, 0x7ffffffffffffc00l, 0); test(lrint, 0x7ffffffffffffc00.0p0, 0x7ffffffffffffc00l, 0);
test(lrintf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000l, 0); test(lrintf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000l, 0);
test(lrint, -0x8000000000000800.0p0, IGNORE, FE_INVALID); test(lrint, -0x8000000000000800.0p0, IGNORE, FE_INVALID);
test(lrintf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID); test(lrintf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID);
test(lrint, -0x8000000000000000.0p0, -0x8000000000000000l, 0); test(lrint, -0x8000000000000000.0p0, (long long)-0x8000000000000000ul, 0);
test(lrintf, -0x8000000000000000.0p0f, -0x8000000000000000l, 0); test(lrintf, -0x8000000000000000.0p0f, (long long)-0x8000000000000000ul, 0);
#else #else
#error "Unsupported long size" #error "Unsupported long size"
#endif #endif
#if (LLONG_MAX == 0x7fffffffffffffffLL) #if (LLONG_MAX == 0x7fffffffffffffffLL)
assert(fesetround(FE_TONEAREST) == 0); ATF_REQUIRE_EQ(0, fesetround(FE_TONEAREST));
test(llrint, 0x8000000000000000.0p0, IGNORE, FE_INVALID); test(llrint, 0x8000000000000000.0p0, IGNORE, FE_INVALID);
test(llrintf, 0x8000000000000000.0p0f, IGNORE, FE_INVALID); test(llrintf, 0x8000000000000000.0p0f, IGNORE, FE_INVALID);
test(llrint, 0x7ffffffffffffc00.0p0, 0x7ffffffffffffc00ll, 0); test(llrint, 0x7ffffffffffffc00.0p0, 0x7ffffffffffffc00ll, 0);
test(llrintf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000ll, 0); test(llrintf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000ll, 0);
test(llrint, -0x8000000000000800.0p0, IGNORE, FE_INVALID); test(llrint, -0x8000000000000800.0p0, IGNORE, FE_INVALID);
test(llrintf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID); test(llrintf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID);
test(llrint, -0x8000000000000000.0p0, -0x8000000000000000ll, 0); test(llrint, -0x8000000000000000.0p0, (long long)-0x8000000000000000ull, 0);
test(llrintf, -0x8000000000000000.0p0f, -0x8000000000000000ll, 0); test(llrintf, -0x8000000000000000.0p0f, (long long)-0x8000000000000000ull, 0);
#else #else
#error "Unsupported long long size" #error "Unsupported long long size"
#endif #endif
} }
int ATF_TC_WITHOUT_HEAD(lrint);
main(void) ATF_TC_BODY(lrint, tc)
{ {
printf("1..1\n");
run_tests(); run_tests();
#ifdef __i386__ #ifdef __i386__
fpsetprec(FP_PE); fpsetprec(FP_PE);
run_tests(); run_tests();
#endif #endif
}
printf("ok 1 - lrint\n");
ATF_TP_ADD_TCS(tp)
return (0); {
ATF_TP_ADD_TC(tp, lrint);
return (atf_no_error());
} }

View File

@ -31,21 +31,33 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <assert.h>
#include <fenv.h> #include <fenv.h>
#include <limits.h> #include <limits.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include "test-utils.h"
#define IGNORE 0x12345
/* /*
* XXX The volatile here is to avoid gcc's bogus constant folding and work * XXX The volatile here is to avoid gcc's bogus constant folding and work
* around the lack of support for the FENV_ACCESS pragma. * around the lack of support for the FENV_ACCESS pragma.
*/ */
#define test(func, x, result, excepts) do { \ #define test(func, x, result, excepts) do { \
volatile double _d = x; \ volatile double _d = x; \
assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT)); \
assert((func)(_d) == (result) || fetestexcept(FE_INVALID)); \ volatile double _r = (func)(_d); \
assert(fetestexcept(FE_ALL_EXCEPT) == (excepts)); \ CHECK_FP_EXCEPTIONS_MSG(excepts, FE_ALL_EXCEPT, "for %s(%s)", \
#func, #x); \
if ((excepts & FE_INVALID) != 0) { \
ATF_REQUIRE_EQ(result, IGNORE); \
ATF_CHECK_EQ_MSG(FE_INVALID, fetestexcept(FE_INVALID), \
"FE_INVALID not set correctly for %s(%s)", #func, #x); \
} else { \
ATF_REQUIRE_MSG(result != IGNORE, "Expected can't be IGNORE!"); \
ATF_REQUIRE_EQ(result, (__STRING(func(_d)), _r)); \
} \
} while (0) } while (0)
#define testall(x, result, excepts) do { \ #define testall(x, result, excepts) do { \
@ -55,16 +67,12 @@ __FBSDID("$FreeBSD$");
test(llroundf, x, result, excepts); \ test(llroundf, x, result, excepts); \
} while (0) } while (0)
#define IGNORE 0
#pragma STDC FENV_ACCESS ON #pragma STDC FENV_ACCESS ON
int ATF_TC_WITHOUT_HEAD(main);
main(int argc, char *argv[]) ATF_TC_BODY(main, tc)
{ {
atf_tc_expect_fail("https://bugs.freebsd.org/205451");
printf("1..1\n");
testall(0.0, 0, 0); testall(0.0, 0, 0);
testall(0.25, 0, FE_INEXACT); testall(0.25, 0, FE_INEXACT);
testall(0.5, 1, FE_INEXACT); testall(0.5, 1, FE_INEXACT);
@ -90,8 +98,8 @@ main(int argc, char *argv[])
test(lroundf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000l, 0); test(lroundf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000l, 0);
test(lround, -0x8000000000000800.0p0, IGNORE, FE_INVALID); test(lround, -0x8000000000000800.0p0, IGNORE, FE_INVALID);
test(lroundf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID); test(lroundf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID);
test(lround, -0x8000000000000000.0p0, -0x8000000000000000l, 0); test(lround, -0x8000000000000000.0p0, (long)-0x8000000000000000l, 0);
test(lroundf, -0x8000000000000000.0p0f, -0x8000000000000000l, 0); test(lroundf, -0x8000000000000000.0p0f, (long)-0x8000000000000000l, 0);
#else #else
#error "Unsupported long size" #error "Unsupported long size"
#endif #endif
@ -103,13 +111,16 @@ main(int argc, char *argv[])
test(llroundf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000ll, 0); test(llroundf, 0x7fffff8000000000.0p0f, 0x7fffff8000000000ll, 0);
test(llround, -0x8000000000000800.0p0, IGNORE, FE_INVALID); test(llround, -0x8000000000000800.0p0, IGNORE, FE_INVALID);
test(llroundf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID); test(llroundf, -0x8000010000000000.0p0f, IGNORE, FE_INVALID);
test(llround, -0x8000000000000000.0p0, -0x8000000000000000ll, 0); test(llround, -0x8000000000000000.0p0, (long long)-0x8000000000000000ll, 0);
test(llroundf, -0x8000000000000000.0p0f, -0x8000000000000000ll, 0); test(llroundf, -0x8000000000000000.0p0f, (long long)-0x8000000000000000ll, 0);
#else #else
#error "Unsupported long long size" #error "Unsupported long long size"
#endif #endif
}
printf("ok 1 - lround\n");
ATF_TP_ADD_TCS(tp)
return (0); {
ATF_TP_ADD_TC(tp, main);
return (atf_no_error());
} }

View File

@ -1,10 +0,0 @@
#!/bin/sh
# $FreeBSD$
cd `dirname $0`
executable=`basename $0 .t`
make $executable 2>&1 > /dev/null
exec ./$executable

View File

@ -33,7 +33,6 @@
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <assert.h>
#include <fenv.h> #include <fenv.h>
#include <float.h> #include <float.h>
#include <locale.h> #include <locale.h>
@ -42,6 +41,8 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "test-utils.h"
static void static void
testnan(const char *nan_format) testnan(const char *nan_format)
{ {
@ -65,58 +66,58 @@ testnan(const char *nan_format)
} }
af[0] = nanf(nan_format); af[0] = nanf(nan_format);
assert(isnan(af[0])); ATF_REQUIRE(isnan(af[0]));
af[1] = strtof(nan_str, &end); af[1] = strtof(nan_str, &end);
assert(end == nan_str + strlen(nan_str)); ATF_REQUIRE(end == nan_str + strlen(nan_str));
assert(sscanf(nan_str, "%e", &af[2]) == 1); ATF_REQUIRE(sscanf(nan_str, "%e", &af[2]) == 1);
assert(memcmp(&af[0], &af[1], sizeof(float)) == 0); ATF_REQUIRE(memcmp(&af[0], &af[1], sizeof(float)) == 0);
assert(memcmp(&af[1], &af[2], sizeof(float)) == 0); ATF_REQUIRE(memcmp(&af[1], &af[2], sizeof(float)) == 0);
if (*nan_format == '\0') { if (*nan_format == '\0') {
/* nanf("") == strtof("nan") */ /* nanf("") == strtof("nan") */
af[3] = strtof("nan", NULL); af[3] = strtof("nan", NULL);
assert(memcmp(&af[2], &af[3], sizeof(float)) == 0); ATF_REQUIRE(memcmp(&af[2], &af[3], sizeof(float)) == 0);
} }
ad[0] = nan(nan_format); ad[0] = nan(nan_format);
assert(isnan(ad[0])); ATF_REQUIRE(isnan(ad[0]));
ad[1] = strtod(nan_str, &end); ad[1] = strtod(nan_str, &end);
assert(end == nan_str + strlen(nan_str)); ATF_REQUIRE(end == nan_str + strlen(nan_str));
assert(sscanf(nan_str, "%le", &ad[2]) == 1); ATF_REQUIRE(sscanf(nan_str, "%le", &ad[2]) == 1);
assert(memcmp(&ad[0], &ad[1], sizeof(double)) == 0); ATF_REQUIRE(memcmp(&ad[0], &ad[1], sizeof(double)) == 0);
assert(memcmp(&ad[1], &ad[2], sizeof(double)) == 0); ATF_REQUIRE(memcmp(&ad[1], &ad[2], sizeof(double)) == 0);
if (*nan_format == '\0') { if (*nan_format == '\0') {
/* nan("") == strtod("nan") */ /* nan("") == strtod("nan") */
ad[3] = strtod("nan", NULL); ad[3] = strtod("nan", NULL);
assert(memcmp(&ad[2], &ad[3], sizeof(double)) == 0); ATF_REQUIRE(memcmp(&ad[2], &ad[3], sizeof(double)) == 0);
} }
ald[0] = nanl(nan_format); ald[0] = nanl(nan_format);
assert(isnan(ald[0])); ATF_REQUIRE(isnan(ald[0]));
ald[1] = strtold(nan_str, &end); ald[1] = strtold(nan_str, &end);
assert(end == nan_str + strlen(nan_str)); ATF_REQUIRE(end == nan_str + strlen(nan_str));
assert(sscanf(nan_str, "%Le", &ald[2]) == 1); ATF_REQUIRE(sscanf(nan_str, "%Le", &ald[2]) == 1);
assert(memcmp(&ald[0], &ald[1], sizeof(long double)) == 0); ATF_REQUIRE(memcmp(&ald[0], &ald[1], sizeof(long double)) == 0);
assert(memcmp(&ald[1], &ald[2], sizeof(long double)) == 0); ATF_REQUIRE(memcmp(&ald[1], &ald[2], sizeof(long double)) == 0);
if (*nan_format == '\0') { if (*nan_format == '\0') {
/* nanl("") == strtold("nan") */ /* nanl("") == strtold("nan") */
ald[3] = strtold("nan", NULL); ald[3] = strtold("nan", NULL);
assert(memcmp(&ald[2], &ald[3], sizeof(long double)) == 0); ATF_REQUIRE(memcmp(&ald[2], &ald[3], sizeof(long double)) == 0);
} }
} }
int ATF_TC_WITHOUT_HEAD(nan);
main(void) ATF_TC_BODY(nan, tc)
{ {
printf("1..1\n");
/* Die if a signalling NaN is returned */ /* Die if a signalling NaN is returned */
feenableexcept(FE_INVALID); feenableexcept(FE_INVALID);
testnan("0x1234"); testnan("0x1234");
testnan(""); testnan("");
}
printf("ok 1 - nan\n");
ATF_TP_ADD_TCS(tp)
return (0); {
ATF_TP_ADD_TC(tp, nan);
return (atf_no_error());
} }

View File

@ -36,15 +36,12 @@
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <assert.h>
#include <fenv.h> #include <fenv.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include "test-utils.h" #include "test-utils.h"
static int testnum;
static const int rmodes[] = { static const int rmodes[] = {
FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO, FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO,
}; };
@ -95,25 +92,23 @@ test_nearby(int testindex)
unsigned i; unsigned i;
for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) {
fesetround(rmodes[i]); ATF_REQUIRE_EQ(0, fesetround(rmodes[i]));
feclearexcept(ALL_STD_EXCEPT); ATF_REQUIRE_EQ(0, feclearexcept(ALL_STD_EXCEPT));
in = tests[testindex].in; in = tests[testindex].in;
out = get_output(testindex, i, 0); out = get_output(testindex, i, 0);
assert(fpequal(out, libnearbyintf(in))); ATF_CHECK(fpequal(out, libnearbyintf(in)));
assert(fpequal(out, nearbyint(in))); ATF_CHECK(fpequal(out, nearbyint(in)));
assert(fpequal(out, nearbyintl(in))); ATF_CHECK(fpequal(out, nearbyintl(in)));
assert(fetestexcept(ALL_STD_EXCEPT) == 0); CHECK_FP_EXCEPTIONS(0, ALL_STD_EXCEPT);
in = -tests[testindex].in; in = -tests[testindex].in;
out = get_output(testindex, i, 1); out = get_output(testindex, i, 1);
assert(fpequal(out, nearbyintf(in))); ATF_CHECK(fpequal(out, nearbyintf(in)));
assert(fpequal(out, nearbyint(in))); ATF_CHECK(fpequal(out, nearbyint(in)));
assert(fpequal(out, nearbyintl(in))); ATF_CHECK(fpequal(out, nearbyintl(in)));
assert(fetestexcept(ALL_STD_EXCEPT) == 0); CHECK_FP_EXCEPTIONS(0, ALL_STD_EXCEPT);
} }
printf("ok %d\t\t# nearbyint(+%g)\n", testnum++, in);
} }
static void static void
@ -126,8 +121,8 @@ test_modf(int testindex)
unsigned i; unsigned i;
for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) {
fesetround(rmodes[i]); ATF_REQUIRE_EQ(0, fesetround(rmodes[i]));
feclearexcept(ALL_STD_EXCEPT); ATF_REQUIRE_EQ(0, feclearexcept(ALL_STD_EXCEPT));
in = tests[testindex].in; in = tests[testindex].in;
ipart_expected = tests[testindex].out[1]; ipart_expected = tests[testindex].out[1];
@ -135,41 +130,42 @@ test_modf(int testindex)
isinf(ipart_expected) ? 0.0 : in - ipart_expected, in); isinf(ipart_expected) ? 0.0 : in - ipart_expected, in);
ipartl = ipart = ipartf = 42.0; ipartl = ipart = ipartf = 42.0;
assert(fpequal(out, modff(in, &ipartf))); ATF_CHECK(fpequal(out, modff(in, &ipartf)));
assert(fpequal(ipart_expected, ipartf)); ATF_CHECK(fpequal(ipart_expected, ipartf));
assert(fpequal(out, modf(in, &ipart))); ATF_CHECK(fpequal(out, modf(in, &ipart)));
assert(fpequal(ipart_expected, ipart)); ATF_CHECK(fpequal(ipart_expected, ipart));
assert(fpequal(out, modfl(in, &ipartl))); ATF_CHECK(fpequal(out, modfl(in, &ipartl)));
assert(fpequal(ipart_expected, ipartl)); ATF_CHECK(fpequal(ipart_expected, ipartl));
assert(fetestexcept(ALL_STD_EXCEPT) == 0); CHECK_FP_EXCEPTIONS(0, ALL_STD_EXCEPT);
in = -in; in = -in;
ipart_expected = -ipart_expected; ipart_expected = -ipart_expected;
out = -out; out = -out;
ipartl = ipart = ipartf = 42.0; ipartl = ipart = ipartf = 42.0;
assert(fpequal(out, modff(in, &ipartf))); ATF_CHECK(fpequal(out, modff(in, &ipartf)));
assert(fpequal(ipart_expected, ipartf)); ATF_CHECK(fpequal(ipart_expected, ipartf));
assert(fpequal(out, modf(in, &ipart))); ATF_CHECK(fpequal(out, modf(in, &ipart)));
assert(fpequal(ipart_expected, ipart)); ATF_CHECK(fpequal(ipart_expected, ipart));
assert(fpequal(out, modfl(in, &ipartl))); ATF_CHECK(fpequal(out, modfl(in, &ipartl)));
assert(fpequal(ipart_expected, ipartl)); ATF_CHECK(fpequal(ipart_expected, ipartl));
assert(fetestexcept(ALL_STD_EXCEPT) == 0); CHECK_FP_EXCEPTIONS(0, ALL_STD_EXCEPT);
} }
printf("ok %d\t\t# modf(+%g)\n", testnum++, in);
} }
int ATF_TC_WITHOUT_HEAD(nearbyint);
main(void) ATF_TC_BODY(nearbyint, tc)
{ {
unsigned i; unsigned i;
printf("1..%zu\n", (size_t)(nitems(tests) * 2));
testnum = 1;
for (i = 0; i < nitems(tests); i++) { for (i = 0; i < nitems(tests); i++) {
test_nearby(i); test_nearby(i);
test_modf(i); test_modf(i);
} }
}
return (0);
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, nearbyint);
return (atf_no_error());
} }

View File

@ -72,14 +72,16 @@ static void _testl(const char *, int, long double, long double, int);
static double idd(double); static double idd(double);
static float idf(float); static float idf(float);
int static const int ex_under = FE_UNDERFLOW | FE_INEXACT; /* shorthand */
main(void) static const int ex_over = FE_OVERFLOW | FE_INEXACT;
{ static const long double ldbl_eps = LDBL_EPSILON;
static const int ex_under = FE_UNDERFLOW | FE_INEXACT; /* shorthand */
static const int ex_over = FE_OVERFLOW | FE_INEXACT;
long double ldbl_small, ldbl_eps, ldbl_max;
printf("1..5\n");
ATF_TC_WITHOUT_HEAD(zeros);
ATF_TC_BODY(zeros, tc)
{
long double ldbl_small;
#ifdef __i386__ #ifdef __i386__
fpsetprec(FP_PE); fpsetprec(FP_PE);
@ -90,8 +92,6 @@ main(void)
* double format. * double format.
*/ */
ldbl_small = ldexpl(1.0, LDBL_MIN_EXP - LDBL_MANT_DIG); ldbl_small = ldexpl(1.0, LDBL_MIN_EXP - LDBL_MANT_DIG);
ldbl_eps = LDBL_EPSILON;
ldbl_max = ldexpl(1.0 - ldbl_eps / 2, LDBL_MAX_EXP);
/* /*
* Special cases involving zeroes. * Special cases involving zeroes.
@ -120,9 +120,11 @@ main(void)
stest(nexttowardf, 0x1p-149f, f); stest(nexttowardf, 0x1p-149f, f);
stest(nexttowardl, ldbl_small, l); stest(nexttowardl, ldbl_small, l);
#undef stest #undef stest
}
printf("ok 1 - next\n"); ATF_TC_WITHOUT_HEAD(eq_and_nan);
ATF_TC_BODY(eq_and_nan, tc)
{
/* /*
* `x == y' and NaN tests * `x == y' and NaN tests
*/ */
@ -133,33 +135,37 @@ main(void)
testall(NAN, 42.0, NAN, 0); testall(NAN, 42.0, NAN, 0);
testall(42.0, NAN, NAN, 0); testall(42.0, NAN, NAN, 0);
testall(NAN, NAN, NAN, 0); testall(NAN, NAN, NAN, 0);
}
printf("ok 2 - next\n"); ATF_TC_WITHOUT_HEAD(ordinary);
ATF_TC_BODY(ordinary, tc)
{
/* /*
* Tests where x is an ordinary normalized number * Tests where x is an ordinary normalized number
*/ */
testboth(1.0, 2.0, 1.0 + DBL_EPSILON, 0, ); testboth(1.0, 2.0, 1.0 + DBL_EPSILON, 0, );
testboth(1.0, -INFINITY, 1.0 - DBL_EPSILON/2, 0, ); testboth(1.0, -INFINITY, 1.0 - DBL_EPSILON / 2, 0, );
testboth(1.0, 2.0, 1.0 + FLT_EPSILON, 0, f); testboth(1.0, 2.0, 1.0 + FLT_EPSILON, 0, f);
testboth(1.0, -INFINITY, 1.0 - FLT_EPSILON/2, 0, f); testboth(1.0, -INFINITY, 1.0 - FLT_EPSILON / 2, 0, f);
testboth(1.0, 2.0, 1.0 + ldbl_eps, 0, l); testboth(1.0, 2.0, 1.0 + ldbl_eps, 0, l);
testboth(1.0, -INFINITY, 1.0 - ldbl_eps/2, 0, l); testboth(1.0, -INFINITY, 1.0 - ldbl_eps / 2, 0, l);
testboth(-1.0, 2.0, -1.0 + DBL_EPSILON/2, 0, ); testboth(-1.0, 2.0, -1.0 + DBL_EPSILON / 2, 0, );
testboth(-1.0, -INFINITY, -1.0 - DBL_EPSILON, 0, ); testboth(-1.0, -INFINITY, -1.0 - DBL_EPSILON, 0, );
testboth(-1.0, 2.0, -1.0 + FLT_EPSILON/2, 0, f); testboth(-1.0, 2.0, -1.0 + FLT_EPSILON / 2, 0, f);
testboth(-1.0, -INFINITY, -1.0 - FLT_EPSILON, 0, f); testboth(-1.0, -INFINITY, -1.0 - FLT_EPSILON, 0, f);
testboth(-1.0, 2.0, -1.0 + ldbl_eps/2, 0, l); testboth(-1.0, 2.0, -1.0 + ldbl_eps / 2, 0, l);
testboth(-1.0, -INFINITY, -1.0 - ldbl_eps, 0, l); testboth(-1.0, -INFINITY, -1.0 - ldbl_eps, 0, l);
/* Cases where nextafter(...) != nexttoward(...) */ /* Cases where nextafter(...) != nexttoward(...) */
test(nexttoward(1.0, 1.0 + ldbl_eps), 1.0 + DBL_EPSILON, 0); test(nexttoward(1.0, 1.0 + ldbl_eps), 1.0 + DBL_EPSILON, 0);
testf(nexttowardf(1.0, 1.0 + ldbl_eps), 1.0 + FLT_EPSILON, 0); testf(nexttowardf(1.0, 1.0 + ldbl_eps), 1.0 + FLT_EPSILON, 0);
testl(nexttowardl(1.0, 1.0 + ldbl_eps), 1.0 + ldbl_eps, 0); testl(nexttowardl(1.0, 1.0 + ldbl_eps), 1.0 + ldbl_eps, 0);
}
printf("ok 3 - next\n"); ATF_TC_WITHOUT_HEAD(boundaries);
ATF_TC_BODY(boundaries, tc)
{
/* /*
* Tests at word boundaries, normalization boundaries, etc. * Tests at word boundaries, normalization boundaries, etc.
*/ */
@ -202,8 +208,18 @@ main(void)
testboth(0x1p-16382L, -INFINITY, testboth(0x1p-16382L, -INFINITY,
0x0.ffffffffffffffffffffffffffffp-16382L, ex_under, l); 0x0.ffffffffffffffffffffffffffffp-16382L, ex_under, l);
#endif #endif
}
printf("ok 4 - next\n"); ATF_TC_WITHOUT_HEAD(overflow);
ATF_TC_BODY(overflow, tc)
{
long double ldbl_max;
/*
* We can't use a compile-time constant here because gcc on
* FreeBSD/i386 assumes long doubles are truncated to the
* double format.
*/
ldbl_max = ldexpl(1.0 - ldbl_eps / 2, LDBL_MAX_EXP);
/* /*
* Overflow tests * Overflow tests
@ -222,10 +238,6 @@ main(void)
testboth(ldbl_max, INFINITY, INFINITY, ex_over, l); testboth(ldbl_max, INFINITY, INFINITY, ex_over, l);
testboth(INFINITY, 0.0, ldbl_max, 0, l); testboth(INFINITY, 0.0, ldbl_max, 0, l);
printf("ok 5 - next\n");
return (0);
} }
static void static void
@ -236,14 +248,13 @@ _testl(const char *exp, int line, long double actual, long double expected,
actual_except = fetestexcept(ALL_STD_EXCEPT); actual_except = fetestexcept(ALL_STD_EXCEPT);
if (!fpequal(actual, expected)) { if (!fpequal(actual, expected)) {
fprintf(stderr, "%d: %s returned %La, expecting %La\n", atf_tc_fail_check(__FILE__, line,
line, exp, actual, expected); "%s returned %La, expecting %La\n", exp, actual, expected);
abort();
} }
if (actual_except != except) { if (actual_except != except) {
fprintf(stderr, "%d: %s raised 0x%x, expecting 0x%x\n", atf_tc_fail_check(__FILE__, line,
line, exp, actual_except, except); "%s raised 0x%x, expecting 0x%x\n", exp, actual_except,
abort(); except);
} }
} }
@ -263,3 +274,14 @@ idf(float x)
{ {
return (x); return (x);
} }
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, zeros);
ATF_TP_ADD_TC(tp, ordinary);
ATF_TP_ADD_TC(tp, eq_and_nan);
ATF_TP_ADD_TC(tp, boundaries);
ATF_TP_ADD_TC(tp, overflow);
return (atf_no_error());
}

View File

@ -33,13 +33,14 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <assert.h>
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <strings.h> #include <strings.h>
#include "test-utils.h"
static void test_invalid(long double, long double); static void test_invalid(long double, long double);
static void testl(long double, long double, long double, int); static void testl(long double, long double, long double, int);
static void testd(double, double, double, int); static void testd(double, double, double, int);
@ -51,12 +52,9 @@ static void testf(float, float, float, int);
testf(x, y, e_r, e_q); \ testf(x, y, e_r, e_q); \
} while (0) } while (0)
int ATF_TC_WITHOUT_HEAD(rem1);
main(void) ATF_TC_BODY(rem1, tc)
{ {
printf("1..3\n");
test_invalid(0.0, 0.0); test_invalid(0.0, 0.0);
test_invalid(1.0, 0.0); test_invalid(1.0, 0.0);
test_invalid(INFINITY, 0.0); test_invalid(INFINITY, 0.0);
@ -72,15 +70,17 @@ main(void)
test(3.0, 4, -1, 1); test(3.0, 4, -1, 1);
test(3.0, -4, -1, -1); test(3.0, -4, -1, -1);
testd(275 * 1193040, 275, 0, 1193040); testd(275 * 1193040, 275, 0, 1193040);
test(4.5 * 7.5, 4.5, -2.25, 8); /* we should get the even one */ test(4.5 * 7.5, 4.5, -2.25, 8); /* we should get the even one */
testf(0x1.9044f6p-1, 0x1.ce662ep-1, -0x1.f109cp-4, 1); testf(0x1.9044f6p-1, 0x1.ce662ep-1, -0x1.f109cp-4, 1);
#if LDBL_MANT_DIG > 53 #if LDBL_MANT_DIG > 53
testl(-0x1.23456789abcdefp-2000L, 0x1.fedcba987654321p-2000L, testl(-0x1.23456789abcdefp-2000L, 0x1.fedcba987654321p-2000L,
0x1.b72ea61d950c862p-2001L, -1); 0x1.b72ea61d950c862p-2001L, -1);
#endif #endif
}
printf("ok 1 - rem\n"); ATF_TC_WITHOUT_HEAD(rem2);
ATF_TC_BODY(rem2, tc)
{
/* /*
* The actual quotient here is 864062210.50000003..., but * The actual quotient here is 864062210.50000003..., but
* double-precision division gets -8.64062210.5, which rounds * double-precision division gets -8.64062210.5, which rounds
@ -91,20 +91,18 @@ main(void)
0x1.fb3165b82de72p-333, -864062211); 0x1.fb3165b82de72p-333, -864062211);
/* Even harder cases with greater exponent separation */ /* Even harder cases with greater exponent separation */
test(0x1.fp100, 0x1.ep-40, -0x1.cp-41, 143165577); test(0x1.fp100, 0x1.ep-40, -0x1.cp-41, 143165577);
testd(-0x1.abcdefp120, 0x1.87654321p-120, testd(-0x1.abcdefp120, 0x1.87654321p-120, -0x1.69c78ec4p-121,
-0x1.69c78ec4p-121, -63816414); -63816414);
}
printf("ok 2 - rem\n");
ATF_TC_WITHOUT_HEAD(rem3);
ATF_TC_BODY(rem3, tc)
{
test(0x1.66666cp+120, 0x1p+71, 0.0, 1476395008); test(0x1.66666cp+120, 0x1p+71, 0.0, 1476395008);
testd(-0x1.0000000000003p+0, 0x1.0000000000003p+0, -0.0, -1); testd(-0x1.0000000000003p+0, 0x1.0000000000003p+0, -0.0, -1);
testl(-0x1.0000000000003p+0, 0x1.0000000000003p+0, -0.0, -1); testl(-0x1.0000000000003p+0, 0x1.0000000000003p+0, -0.0, -1);
testd(-0x1.0000000000001p-749, 0x1.4p-1072, 0x1p-1074, -1288490189); testd(-0x1.0000000000001p-749, 0x1.4p-1072, 0x1p-1074, -1288490189);
testl(-0x1.0000000000001p-749, 0x1.4p-1072, 0x1p-1074, -1288490189); testl(-0x1.0000000000001p-749, 0x1.4p-1072, 0x1p-1074, -1288490189);
printf("ok 3 - rem\n");
return (0);
} }
static void static void
@ -114,22 +112,22 @@ test_invalid(long double x, long double y)
q = 0xdeadbeef; q = 0xdeadbeef;
assert(isnan(remainder(x, y))); ATF_CHECK(isnan(remainder(x, y)));
assert(isnan(remquo(x, y, &q))); ATF_CHECK(isnan(remquo(x, y, &q)));
#ifdef STRICT #ifdef STRICT
assert(q == 0xdeadbeef); ATF_CHECK(q == 0xdeadbeef);
#endif #endif
assert(isnan(remainderf(x, y))); ATF_CHECK(isnan(remainderf(x, y)));
assert(isnan(remquof(x, y, &q))); ATF_CHECK(isnan(remquof(x, y, &q)));
#ifdef STRICT #ifdef STRICT
assert(q == 0xdeadbeef); ATF_CHECK(q == 0xdeadbeef);
#endif #endif
assert(isnan(remainderl(x, y))); ATF_CHECK(isnan(remainderl(x, y)));
assert(isnan(remquol(x, y, &q))); ATF_CHECK(isnan(remquol(x, y, &q)));
#ifdef STRICT #ifdef STRICT
assert(q == 0xdeadbeef); ATF_CHECK(q == 0xdeadbeef);
#endif #endif
} }
@ -148,17 +146,17 @@ testl(long double x, long double y, long double expected_rem, int expected_quo)
q = random(); q = random();
rem = remainderl(x, y); rem = remainderl(x, y);
assert(rem == expected_rem); ATF_CHECK(rem == expected_rem);
assert(!signbit(rem) == !signbit(expected_rem)); ATF_CHECK(!signbit(rem) == !signbit(expected_rem));
rem = remquol(x, y, &q); rem = remquol(x, y, &q);
assert(rem == expected_rem); ATF_CHECK(rem == expected_rem);
assert(!signbit(rem) == !signbit(expected_rem)); ATF_CHECK(!signbit(rem) == !signbit(expected_rem));
assert((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */ ATF_CHECK((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */
assert((q & 0x7) == (expected_quo & 0x7)); ATF_CHECK((q & 0x7) == (expected_quo & 0x7));
if (q != 0) { if (q != 0) {
assert((q > 0) ^ !(expected_quo > 0)); ATF_CHECK((q > 0) ^ !(expected_quo > 0));
q = abs(q); q = abs(q);
assert(q == (abs(expected_quo) & mask(q))); ATF_CHECK(q == (abs(expected_quo) & mask(q)));
} }
} }
@ -170,17 +168,17 @@ testd(double x, double y, double expected_rem, int expected_quo)
q = random(); q = random();
rem = remainder(x, y); rem = remainder(x, y);
assert(rem == expected_rem); ATF_CHECK(rem == expected_rem);
assert(!signbit(rem) == !signbit(expected_rem)); ATF_CHECK(!signbit(rem) == !signbit(expected_rem));
rem = remquo(x, y, &q); rem = remquo(x, y, &q);
assert(rem == expected_rem); ATF_CHECK(rem == expected_rem);
assert(!signbit(rem) == !signbit(expected_rem)); ATF_CHECK(!signbit(rem) == !signbit(expected_rem));
assert((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */ ATF_CHECK((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */
assert((q & 0x7) == (expected_quo & 0x7)); ATF_CHECK((q & 0x7) == (expected_quo & 0x7));
if (q != 0) { if (q != 0) {
assert((q > 0) ^ !(expected_quo > 0)); ATF_CHECK((q > 0) ^ !(expected_quo > 0));
q = abs(q); q = abs(q);
assert(q == (abs(expected_quo) & mask(q))); ATF_CHECK(q == (abs(expected_quo) & mask(q)));
} }
} }
@ -192,16 +190,25 @@ testf(float x, float y, float expected_rem, int expected_quo)
q = random(); q = random();
rem = remainderf(x, y); rem = remainderf(x, y);
assert(rem == expected_rem); ATF_CHECK(rem == expected_rem);
assert(!signbit(rem) == !signbit(expected_rem)); ATF_CHECK(!signbit(rem) == !signbit(expected_rem));
rem = remquof(x, y, &q); rem = remquof(x, y, &q);
assert(rem == expected_rem); ATF_CHECK(rem == expected_rem);
assert(!signbit(rem) == !signbit(expected_rem)); ATF_CHECK(!signbit(rem) == !signbit(expected_rem));
assert((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */ ATF_CHECK((q ^ expected_quo) >= 0); /* sign(q) == sign(expected_quo) */
assert((q & 0x7) == (expected_quo & 0x7)); ATF_CHECK((q & 0x7) == (expected_quo & 0x7));
if (q != 0) { if (q != 0) {
assert((q > 0) ^ !(expected_quo > 0)); ATF_CHECK((q > 0) ^ !(expected_quo > 0));
q = abs(q); q = abs(q);
assert((q & mask(q)) == (abs(expected_quo) & mask(q))); ATF_CHECK((q & mask(q)) == (abs(expected_quo) & mask(q)));
} }
} }
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, rem1);
ATF_TP_ADD_TC(tp, rem2);
ATF_TP_ADD_TC(tp, rem3);
return (atf_no_error());
}

View File

@ -32,6 +32,8 @@
#include <complex.h> #include <complex.h>
#include <fenv.h> #include <fenv.h>
#include <atf-c.h>
/* /*
* Implementations are permitted to define additional exception flags * Implementations are permitted to define additional exception flags
* not specified in the standard, so it is not necessarily true that * not specified in the standard, so it is not necessarily true that
@ -179,4 +181,13 @@ cfpequal_tol(long double complex x, long double complex y, long double tol,
&& fpequal_tol(cimag(x), cimag(y), tol, flags)); && fpequal_tol(cimag(x), cimag(y), tol, flags));
} }
#define CHECK_FP_EXCEPTIONS(excepts, exceptmask) \
ATF_CHECK_EQ_MSG((excepts), fetestexcept(exceptmask), \
"unexpected exception flags: %#x not %#x", \
fetestexcept(exceptmask), (excepts))
#define CHECK_FP_EXCEPTIONS_MSG(excepts, exceptmask, fmt, ...) \
ATF_CHECK_EQ_MSG((excepts), fetestexcept(exceptmask), \
"unexpected exception flags: got %#x not %#x " fmt, \
fetestexcept(exceptmask), (excepts), __VA_ARGS__)
#endif /* _TEST_UTILS_H_ */ #endif /* _TEST_UTILS_H_ */

View File

@ -38,14 +38,11 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h> #include <sys/param.h>
#include <assert.h>
#include <fenv.h> #include <fenv.h>
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include <atf-c.h>
#include "test-utils.h" #include "test-utils.h"
#pragma STDC FENV_ACCESS ON #pragma STDC FENV_ACCESS ON
@ -66,8 +63,9 @@ __FBSDID("$FreeBSD$");
#define test(func, x, result, exceptmask, excepts) do { \ #define test(func, x, result, exceptmask, excepts) do { \
volatile long double _d = x; \ volatile long double _d = x; \
ATF_CHECK(feclearexcept(FE_ALL_EXCEPT) == 0); \ ATF_CHECK(feclearexcept(FE_ALL_EXCEPT) == 0); \
ATF_CHECK(fpequal((func)(_d), (result))); \ ATF_CHECK(fpequal((func)(_d), (result))); \
ATF_CHECK(((void)(func), fetestexcept(exceptmask) == (excepts))); \ CHECK_FP_EXCEPTIONS_MSG(excepts, exceptmask, "for %s(%s)", \
#func, #x); \
} while (0) } while (0)
#define testall(prefix, x, result, exceptmask, excepts) do { \ #define testall(prefix, x, result, exceptmask, excepts) do { \