new test system
[libc-test] / src / math / fenv.c
1 #include <stdint.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include "mtest.h"
5
6 static int test_status;
7
8 #define error(...) print(__FILE__, __LINE__, __VA_ARGS__)
9 static void print(char *f, int l, char *fmt, ...)
10 {
11         test_status = 1;
12         va_list ap;
13         printf("%s:%d: ", f, l);
14         va_start(ap, fmt);
15         vprintf(fmt, ap);
16         va_end(ap);
17 }
18
19 #define F(n) {#n, n}
20
21 static struct {
22         char *name;
23         int i;
24 } te[] = {
25 #ifdef FE_DIVBYZERO
26         F(FE_DIVBYZERO),
27 #endif
28 #ifdef FE_INEXACT
29         F(FE_INEXACT),
30 #endif
31 #ifdef FE_INVALID
32         F(FE_INVALID),
33 #endif
34 #ifdef FE_OVERFLOW
35         F(FE_OVERFLOW),
36 #endif
37 #ifdef FE_UNDERFLOW
38         F(FE_UNDERFLOW),
39 #endif
40 };
41
42 static void test_except()
43 {
44         #pragma STDC FENV_ACCESS ON
45         int i,r;
46
47         for (i=0; i < sizeof te/sizeof*te; i++) {
48                 feclearexcept(FE_ALL_EXCEPT);
49
50                 r = feraiseexcept(te[i].i);
51                 if (r)
52                         error("feraiseexcept(%s) returned %d\n", te[i].name, r);
53                 r = fetestexcept(FE_ALL_EXCEPT);
54                 if (r != te[i].i)
55                         error("feraiseexcept(%s) want %d got %d\n",
56                                 te[i].name, te[i].i, r);
57         }
58 }
59
60 static struct {
61         char *name;
62         int i;
63 } tr[] = {
64         F(FE_TONEAREST),
65 #ifdef FE_UPWARD
66         F(FE_UPWARD),
67 #endif
68 #ifdef FE_DOWNWARD
69         F(FE_DOWNWARD),
70 #endif
71 #ifdef FE_TOWARDZERO
72         F(FE_TOWARDZERO),
73 #endif
74 };
75
76 static void test_round()
77 {
78         #pragma STDC FENV_ACCESS ON
79         int i,r;
80
81         for (i=0; i < sizeof tr/sizeof*tr; i++) {
82                 if (tr[i].i < 0)
83                         error("%s (%d) < 0\n", tr[i].name, tr[i].i);
84                 for (r=0; r < i; r++)
85                         if (tr[r].i == tr[i].i)
86                                 error("%s (%d) == %s (%d)\n",
87                                         tr[r].name, tr[r].i, tr[i].name, tr[i].i);
88         }
89
90         for (i=0; i < sizeof tr/sizeof*tr; i++) {
91                 r = fesetround(tr[i].i);
92                 if (r != 0)
93                         error("fesetround %d\n", r);
94                 r = fegetround();
95                 if (r != tr[i].i)
96                         error("fegetround %x wanted %x\n", r, tr[i].i);
97         }
98 }
99
100 /* ieee double precision add operation */
101 static struct dd_d t[] = {
102 T(RN,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
103 T(RN,                  0x1p+0,                 0x1p-53,                  0x1p+0,         -0x1p-1, INEXACT)
104 T(RN,                  0x1p+0,              0x1.01p-53,    0x1.0000000000001p+0,       0x1.fep-2, INEXACT)
105 T(RN,                  0x1p+0,                -0x1p-54,                  0x1p+0,          0x1p-2, INEXACT)
106 T(RN,                  0x1p+0,             -0x1.01p-54,    0x1.fffffffffffffp-1,      -0x1.fep-2, INEXACT)
107 T(RN,                 -0x1p+0,                -0x1p-53,                 -0x1p+0,          0x1p-1, INEXACT)
108 T(RN,                 -0x1p+0,             -0x1.01p-53,   -0x1.0000000000001p+0,      -0x1.fep-2, INEXACT)
109 T(RN,                 -0x1p+0,                 0x1p-54,                 -0x1p+0,         -0x1p-2, INEXACT)
110 T(RN,                 -0x1p+0,              0x1.01p-54,   -0x1.fffffffffffffp-1,       0x1.fep-2, INEXACT)
111
112 T(RU,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
113 T(RU,                  0x1p+0,                 0x1p-53,    0x1.0000000000001p+0,          0x1p-1, INEXACT)
114 T(RU,                  0x1p+0,              0x1.01p-53,    0x1.0000000000001p+0,       0x1.fep-2, INEXACT)
115 T(RU,                  0x1p+0,                -0x1p-54,                  0x1p+0,          0x1p-2, INEXACT)
116 T(RU,                  0x1p+0,             -0x1.01p-54,                  0x1p+0,       0x1.01p-2, INEXACT)
117 T(RU,                 -0x1p+0,                -0x1p-53,                 -0x1p+0,          0x1p-1, INEXACT)
118 T(RU,                 -0x1p+0,             -0x1.01p-53,                 -0x1p+0,       0x1.01p-1, INEXACT)
119 T(RU,                 -0x1p+0,                 0x1p-54,   -0x1.fffffffffffffp-1,          0x1p-1, INEXACT)
120 T(RU,                 -0x1p+0,              0x1.01p-54,   -0x1.fffffffffffffp-1,       0x1.fep-2, INEXACT)
121
122 T(RD,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
123 T(RD,                  0x1p+0,                 0x1p-53,                  0x1p+0,         -0x1p-1, INEXACT)
124 T(RD,                  0x1p+0,              0x1.01p-53,                  0x1p+0,      -0x1.01p-1, INEXACT)
125 T(RD,                  0x1p+0,                -0x1p-54,    0x1.fffffffffffffp-1,         -0x1p-1, INEXACT)
126 T(RD,                  0x1p+0,             -0x1.01p-54,    0x1.fffffffffffffp-1,      -0x1.fep-2, INEXACT)
127 T(RD,                 -0x1p+0,                -0x1p-53,   -0x1.0000000000001p+0,         -0x1p-1, INEXACT)
128 T(RD,                 -0x1p+0,             -0x1.01p-53,   -0x1.0000000000001p+0,      -0x1.fep-2, INEXACT)
129 T(RD,                 -0x1p+0,                 0x1p-54,                 -0x1p+0,         -0x1p-2, INEXACT)
130 T(RD,                 -0x1p+0,              0x1.01p-54,                 -0x1p+0,      -0x1.01p-2, INEXACT)
131
132 T(RZ,                  0x1p+0,                 0x1p-52,    0x1.0000000000001p+0,          0x0p+0, 0)
133 T(RZ,                  0x1p+0,                 0x1p-53,                  0x1p+0,         -0x1p-1, INEXACT)
134 T(RZ,                  0x1p+0,              0x1.01p-53,                  0x1p+0,      -0x1.01p-1, INEXACT)
135 T(RZ,                  0x1p+0,                -0x1p-54,    0x1.fffffffffffffp-1,         -0x1p-1, INEXACT)
136 T(RZ,                  0x1p+0,             -0x1.01p-54,    0x1.fffffffffffffp-1,      -0x1.fep-2, INEXACT)
137 T(RZ,                 -0x1p+0,                -0x1p-53,                 -0x1p+0,          0x1p-1, INEXACT)
138 T(RZ,                 -0x1p+0,             -0x1.01p-53,                 -0x1p+0,       0x1.01p-1, INEXACT)
139 T(RZ,                 -0x1p+0,                 0x1p-54,   -0x1.fffffffffffffp-1,          0x1p-1, INEXACT)
140 T(RZ,                 -0x1p+0,              0x1.01p-54,   -0x1.fffffffffffffp-1,       0x1.fep-2, INEXACT)
141 };
142
143 static void test_round_add(void)
144 {
145         #pragma STDC FENV_ACCESS ON
146         double y;
147         float d;
148         int i;
149         struct dd_d *p;
150
151         for (i = 0; i < sizeof t/sizeof *t; i++) {
152                 p = t + i;
153
154                 if (p->r < 0)
155                         continue;
156                 fesetround(p->r);
157                 y = p->x + p->x2;
158                 d = ulperr(y, p->y, p->dy);
159                 if (!checkcr(y, p->y, p->r)) {
160                         printf("%s:%d: %s %a+%a want %a got %a ulperr %.3f = %a + %a\n",
161                                 p->file, p->line, rstr(p->r), p->x, p->x2, p->y, y, d, d-p->dy, p->dy);
162                         test_status = 1;
163                 }
164         }
165 }
166
167 int main(void)
168 {
169         test_except();
170         test_round();
171         test_round_add();
172         return test_status;
173 }