X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fmath%2Ffenv.c;h=c221d7fb227a1a728fbe25a4108b1bee805e39a8;hb=c58b8e7cb29f954791ffd5bc2d97ddb4d4202d0c;hp=ae1f897869ea11369530d24ab13560debe76cec5;hpb=0c7d465f8b04e9db61c2c9a32510799c19ec0503;p=libc-test diff --git a/src/math/fenv.c b/src/math/fenv.c index ae1f897..c221d7f 100644 --- a/src/math/fenv.c +++ b/src/math/fenv.c @@ -1,60 +1,173 @@ -#include "test.h" -#include #include -#include #include -#include +#include +#include "util.h" +static int test_status; -void test_fenv() +#define error(...) print(__FILE__, __LINE__, __VA_ARGS__) +static void print(char *f, int l, char *fmt, ...) { - int r; - - r = fesetround(FE_UPWARD); - if (r != 0) - error("fesetround %d\n", r); - r = fegetround(); - if (r != FE_UPWARD) - error("fegetround %x wanted %x\n", r, FE_UPWARD); - r = fesetround(FE_TONEAREST); - if (r != 0) - error("fesetround %d\n", r); - r = fegetround(); - if (r != FE_TONEAREST) - error("fegetround %x wanted %x\n", r, FE_TONEAREST); + test_status = 1; + va_list ap; + printf("%s:%d: ", f, l); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); } -void test_fenv_except() +#define F(n) {#n, n} + +static struct { + char *name; + int i; +} te[] = { +#ifdef FE_DIVBYZERO + F(FE_DIVBYZERO), +#endif +#ifdef FE_INEXACT + F(FE_INEXACT), +#endif +#ifdef FE_INVALID + F(FE_INVALID), +#endif +#ifdef FE_OVERFLOW + F(FE_OVERFLOW), +#endif +#ifdef FE_UNDERFLOW + F(FE_UNDERFLOW), +#endif +}; + +static void test_except() { + #pragma STDC FENV_ACCESS ON int i,r; - for (i = 0; i < 64; i++) { + for (i=0; i < sizeof te/sizeof*te; i++) { feclearexcept(FE_ALL_EXCEPT); - r = feraiseexcept(i); + r = feraiseexcept(te[i].i); if (r) - error("feraise %d returned %d\n", i, r); + error("feraiseexcept(%s) returned %d\n", te[i].name, r); r = fetestexcept(FE_ALL_EXCEPT); - if (r != i) - error("feraise want %d got %d\n", i, r); + if (r != te[i].i) + error("feraiseexcept(%s) want %d got %d\n", + te[i].name, te[i].i, r); } } -void bench_feraiseexcept(int N) -{ +static struct { + char *name; int i; - for (i = 0; i < N; i++) { - feraiseexcept(i&63); +} tr[] = { + F(FE_TONEAREST), +#ifdef FE_UPWARD + F(FE_UPWARD), +#endif +#ifdef FE_DOWNWARD + F(FE_DOWNWARD), +#endif +#ifdef FE_TOWARDZERO + F(FE_TOWARDZERO), +#endif +}; + +static void test_round() +{ + #pragma STDC FENV_ACCESS ON + int i,r; + + for (i=0; i < sizeof tr/sizeof*tr; i++) { + if (tr[i].i < 0) + error("%s (%d) < 0\n", tr[i].name, tr[i].i); + for (r=0; r < i; r++) + if (tr[r].i == tr[i].i) + error("%s (%d) == %s (%d)\n", + tr[r].name, tr[r].i, tr[i].name, tr[i].i); + } + + for (i=0; i < sizeof tr/sizeof*tr; i++) { + r = fesetround(tr[i].i); + if (r != 0) + error("fesetround %d\n", r); + r = fegetround(); + if (r != tr[i].i) + error("fegetround %x wanted %x\n", r, tr[i].i); } } -void bench_fesetround(int N) +/* ieee double precision add operation */ +static struct dd_d t[] = { +T(RN, 0x1p+0, 0x1p-52, 0x1.0000000000001p+0, 0x0p+0, 0) +T(RN, 0x1p+0, 0x1p-53, 0x1p+0, -0x1p-1, INEXACT) +T(RN, 0x1p+0, 0x1.01p-53, 0x1.0000000000001p+0, 0x1.fep-2, INEXACT) +T(RN, 0x1p+0, -0x1p-54, 0x1p+0, 0x1p-2, INEXACT) +T(RN, 0x1p+0, -0x1.01p-54, 0x1.fffffffffffffp-1, -0x1.fep-2, INEXACT) +T(RN, -0x1p+0, -0x1p-53, -0x1p+0, 0x1p-1, INEXACT) +T(RN, -0x1p+0, -0x1.01p-53, -0x1.0000000000001p+0, -0x1.fep-2, INEXACT) +T(RN, -0x1p+0, 0x1p-54, -0x1p+0, -0x1p-2, INEXACT) +T(RN, -0x1p+0, 0x1.01p-54, -0x1.fffffffffffffp-1, 0x1.fep-2, INEXACT) + +T(RU, 0x1p+0, 0x1p-52, 0x1.0000000000001p+0, 0x0p+0, 0) +T(RU, 0x1p+0, 0x1p-53, 0x1.0000000000001p+0, 0x1p-1, INEXACT) +T(RU, 0x1p+0, 0x1.01p-53, 0x1.0000000000001p+0, 0x1.fep-2, INEXACT) +T(RU, 0x1p+0, -0x1p-54, 0x1p+0, 0x1p-2, INEXACT) +T(RU, 0x1p+0, -0x1.01p-54, 0x1p+0, 0x1.01p-2, INEXACT) +T(RU, -0x1p+0, -0x1p-53, -0x1p+0, 0x1p-1, INEXACT) +T(RU, -0x1p+0, -0x1.01p-53, -0x1p+0, 0x1.01p-1, INEXACT) +T(RU, -0x1p+0, 0x1p-54, -0x1.fffffffffffffp-1, 0x1p-1, INEXACT) +T(RU, -0x1p+0, 0x1.01p-54, -0x1.fffffffffffffp-1, 0x1.fep-2, INEXACT) + +T(RD, 0x1p+0, 0x1p-52, 0x1.0000000000001p+0, 0x0p+0, 0) +T(RD, 0x1p+0, 0x1p-53, 0x1p+0, -0x1p-1, INEXACT) +T(RD, 0x1p+0, 0x1.01p-53, 0x1p+0, -0x1.01p-1, INEXACT) +T(RD, 0x1p+0, -0x1p-54, 0x1.fffffffffffffp-1, -0x1p-1, INEXACT) +T(RD, 0x1p+0, -0x1.01p-54, 0x1.fffffffffffffp-1, -0x1.fep-2, INEXACT) +T(RD, -0x1p+0, -0x1p-53, -0x1.0000000000001p+0, -0x1p-1, INEXACT) +T(RD, -0x1p+0, -0x1.01p-53, -0x1.0000000000001p+0, -0x1.fep-2, INEXACT) +T(RD, -0x1p+0, 0x1p-54, -0x1p+0, -0x1p-2, INEXACT) +T(RD, -0x1p+0, 0x1.01p-54, -0x1p+0, -0x1.01p-2, INEXACT) + +T(RZ, 0x1p+0, 0x1p-52, 0x1.0000000000001p+0, 0x0p+0, 0) +T(RZ, 0x1p+0, 0x1p-53, 0x1p+0, -0x1p-1, INEXACT) +T(RZ, 0x1p+0, 0x1.01p-53, 0x1p+0, -0x1.01p-1, INEXACT) +T(RZ, 0x1p+0, -0x1p-54, 0x1.fffffffffffffp-1, -0x1p-1, INEXACT) +T(RZ, 0x1p+0, -0x1.01p-54, 0x1.fffffffffffffp-1, -0x1.fep-2, INEXACT) +T(RZ, -0x1p+0, -0x1p-53, -0x1p+0, 0x1p-1, INEXACT) +T(RZ, -0x1p+0, -0x1.01p-53, -0x1p+0, 0x1.01p-1, INEXACT) +T(RZ, -0x1p+0, 0x1p-54, -0x1.fffffffffffffp-1, 0x1p-1, INEXACT) +T(RZ, -0x1p+0, 0x1.01p-54, -0x1.fffffffffffffp-1, 0x1.fep-2, INEXACT) +}; + +static void test_round_add(void) { + #pragma STDC FENV_ACCESS ON + double y; + float d; int i; - int r = 0; + struct dd_d *p; - for (i = 0; i < N; i++) { - r ^= 0x400; - fesetround(r); + for (i = 0; i < sizeof t/sizeof *t; i++) { + p = t + i; + + if (p->r < 0) + continue; + fesetround(p->r); + y = p->x + p->x2; + d = ulperr(y, p->y, p->dy); + if (!checkcr(y, p->y, p->r)) { + printf("%s:%d: %s %a+%a want %a got %a ulperr %.3f = %a + %a\n", + p->file, p->line, rstr(p->r), p->x, p->x2, p->y, y, d, d-p->dy, p->dy); + test_status = 1; + } } } + +int main(void) +{ + test_except(); + test_round(); + test_round_add(); + return test_status; +}