X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fmath%2Ffenv.c;h=def30b7cdc65d9e11b06e5b3c3ed5b57aded146d;hb=2064be16d307b6409cd518303897cd0763cfdb97;hp=ef358f0b71346cb307775dd33011468a76636159;hpb=cfa23cc1bd01f5c44d7746b8b1839f84d5e1b6eb;p=libc-test diff --git a/src/math/fenv.c b/src/math/fenv.c index ef358f0..def30b7 100644 --- a/src/math/fenv.c +++ b/src/math/fenv.c @@ -37,24 +37,57 @@ static struct { #ifdef FE_UNDERFLOW F(FE_UNDERFLOW), #endif + {0, 0} }; static void test_except() { #pragma STDC FENV_ACCESS ON int i,r; + fenv_t env; - for (i=0; i < sizeof te/sizeof*te; i++) { + for (i=0; te[i].i; i++) { feclearexcept(FE_ALL_EXCEPT); r = feraiseexcept(te[i].i); if (r) error("feraiseexcept(%s) returned %d\n", te[i].name, r); r = fetestexcept(FE_ALL_EXCEPT); - if (r != te[i].i) + if (r != te[i].i) { +#if defined FE_OVERFLOW && defined FE_INEXACT + if (te[i].i == FE_OVERFLOW && r == (FE_OVERFLOW|FE_INEXACT)) + continue; +#endif +#if defined FE_UNDERFLOW && defined FE_INEXACT + if (te[i].i == FE_UNDERFLOW && r == (FE_UNDERFLOW|FE_INEXACT)) + continue; +#endif error("feraiseexcept(%s) want %d got %d\n", te[i].name, te[i].i, r); + } } + + r = feraiseexcept(FE_ALL_EXCEPT); + if (r != 0) + error("feraisexcept(FE_ALL_EXCEPT) failed\n"); + r = fegetenv(&env); + if (r != 0) + error("fegetenv(&env) = %d\n", r); + r = fetestexcept(FE_ALL_EXCEPT); + if (r != FE_ALL_EXCEPT) + error("fetestexcept failed: got 0x%x, want 0x%x (FE_ALL_ECXEPT)\n", r, FE_ALL_EXCEPT); + r = fesetenv(FE_DFL_ENV); + if (r != 0) + error("fesetenv(FE_DFL_ENV) = %d\n", r); + r = fetestexcept(FE_ALL_EXCEPT); + if (r != 0) + error("fesetenv(FE_DFL_ENV) did not clear exceptions: 0x%x\n", r); + r = fesetenv(&env); + if (r != 0) + error("fesetenv(&env) = %d\n", r); + r = fetestexcept(FE_ALL_EXCEPT); + if (r != FE_ALL_EXCEPT) + error("fesetenv(&env) did not restore exceptions: 0x%x\n", r); } static struct { @@ -77,6 +110,9 @@ static void test_round() { #pragma STDC FENV_ACCESS ON int i,r; + fenv_t env; + volatile float two100 = 0x1p100; + volatile float x; for (i=0; i < sizeof tr/sizeof*tr; i++) { if (tr[i].i < 0) @@ -90,11 +126,45 @@ static void test_round() for (i=0; i < sizeof tr/sizeof*tr; i++) { r = fesetround(tr[i].i); if (r != 0) - error("fesetround %d\n", r); + error("fesetround(%s) = %d\n", tr[i].name, r); r = fegetround(); if (r != tr[i].i) - error("fegetround %x wanted %x\n", r, tr[i].i); + error("fegetround() = 0x%x, wanted 0x%x (%s)\n", r, tr[i].i, tr[i].name); } + +#ifdef FE_UPWARD + r = fesetround(FE_UPWARD); + if (r != 0) + error("fesetround(FE_UPWARD) failed\n"); +#endif + r = fegetenv(&env); + if (r != 0) + error("fegetenv(&env) = %d\n", r); + i = fegetround(); + r = fesetenv(FE_DFL_ENV); + if (r != 0) + error("fesetenv(FE_DFL_ENV) = %d\n", r); + r = fegetround(); + if (r != FE_TONEAREST) + error("fesetenv(FE_DFL_ENV) did not set FE_TONEAREST (0x%x), got 0x%x\n", FE_TONEAREST, r); + x = two100 + 1; + if (x != two100) + error("fesetenv(FE_DFL_ENV) did not set FE_TONEAREST, arithmetics rounds upward\n"); + x = two100 - 1; + if (x != two100) + error("fesetenv(FE_DFL_ENV) did not set FE_TONEAREST, arithmetics rounds downward or tozero\n"); + r = fesetenv(&env); + if (r != 0) + error("fesetenv(&env) = %d\n", r); + r = fegetround(); + if (r != i) + error("fesetenv(&env) did not restore 0x%x, got 0x%x\n", i, r); +#ifdef FE_UPWARD + x = two100 + 1; + if (x == two100) + error("fesetenv did not restore upward rounding\n"); +#endif + } /* ieee double precision add operation */ @@ -164,10 +234,42 @@ static void test_round_add(void) } } +static void test_bad(void) +{ + fexcept_t f; + int r; + + r = feclearexcept(FE_ALL_EXCEPT); + if (r != 0) + error("feclearexcept(FE_ALL_EXCEPT) failed\n"); + r = fetestexcept(-1); + if (r != 0) + error("fetestexcept(-1) should return 0 when all exceptions are cleared, got %d\n", r); + r = feraiseexcept(1234567|FE_ALL_EXCEPT); + if (r != 0) + error("feraiseexcept returned non-zero for non-supported exceptions: %d\n", r); + r = feclearexcept(1234567|FE_ALL_EXCEPT); + if (r != 0) + error("feclearexcept returned non-zero for non-supported exceptions: %d\n", r); + r = fesetround(1234567); + if (r == 0) + error("fesetround should fail on invalid rounding mode\n"); + r = fegetexceptflag(&f, 1234567); + if (r != 0) + error("fegetexceptflag returned non-zero for non-supported exceptions: %d\n", r); + r = fegetexceptflag(&f, 0); + if (r != 0) + error("fegetexceptflag(0) failed\n"); + r = fesetexceptflag(&f, 1234567); + if (r != 0) + error("fesetexceptflag returned non-zero fir non-supported exceptions: %d\n", r); +} + int main(void) { test_except(); test_round(); test_round_add(); + test_bad(); return test_status; }