#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
-#include "util.h"
+#include "mtest.h"
static int test_status;
#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 {
{
#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)
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 */
}
}
+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;
}