t_fe_round.c revision 1.7 1 1.1 maya /*
2 1.1 maya * Written by Maya Rashish <maya (at) NetBSD.org>
3 1.1 maya * Public domain.
4 1.1 maya *
5 1.1 maya * Testing IEEE-754 rounding modes (and lrint)
6 1.1 maya */
7 1.1 maya
8 1.1 maya #include <atf-c.h>
9 1.1 maya #include <fenv.h>
10 1.1 maya #ifdef __HAVE_FENV
11 1.1 maya #include <math.h>
12 1.1 maya #include <stdio.h>
13 1.1 maya #include <stdlib.h>
14 1.1 maya
15 1.1 maya /*#pragma STDC FENV_ACCESS ON gcc?? */
16 1.1 maya
17 1.1 maya #define INT 9223L
18 1.1 maya
19 1.1 maya #define EPSILON 0.001
20 1.1 maya
21 1.1 maya static const struct {
22 1.1 maya int round_mode;
23 1.1 maya double input;
24 1.1 maya long int expected;
25 1.1 maya } values[] = {
26 1.1 maya { FE_DOWNWARD, 3.7, 3},
27 1.1 maya { FE_DOWNWARD, -3.7, -4},
28 1.1 maya { FE_DOWNWARD, +0, 0},
29 1.1 maya { FE_DOWNWARD, -INT-0.01, -INT-1},
30 1.1 maya { FE_DOWNWARD, +INT-0.01, INT-1},
31 1.1 maya { FE_DOWNWARD, -INT+0.01, -INT},
32 1.1 maya { FE_DOWNWARD, +INT+0.01, INT},
33 1.1 maya #if 0 /* cpu bugs? */
34 1.1 maya { FE_DOWNWARD, -0, -1},
35 1.1 maya
36 1.1 maya { FE_UPWARD, +0, 1},
37 1.1 maya #endif
38 1.1 maya { FE_UPWARD, -0, 0},
39 1.1 maya { FE_UPWARD, -123.7, -123},
40 1.1 maya { FE_UPWARD, 123.999, 124},
41 1.1 maya { FE_UPWARD, -INT-0.01, -INT},
42 1.1 maya { FE_UPWARD, +INT-0.01, INT},
43 1.1 maya { FE_UPWARD, -INT+0.01, -INT+1},
44 1.1 maya { FE_UPWARD, +INT+0.01, INT+1},
45 1.1 maya
46 1.1 maya { FE_TOWARDZERO, 1.99, 1},
47 1.1 maya { FE_TOWARDZERO, -1.99, -1},
48 1.1 maya { FE_TOWARDZERO, 0.2, 0},
49 1.1 maya { FE_TOWARDZERO, INT+0.01, INT},
50 1.1 maya { FE_TOWARDZERO, INT-0.01, INT - 1},
51 1.1 maya { FE_TOWARDZERO, -INT+0.01, -INT + 1},
52 1.1 maya { FE_TOWARDZERO, +0, 0},
53 1.1 maya { FE_TOWARDZERO, -0, 0},
54 1.1 maya
55 1.1 maya { FE_TONEAREST, -INT-0.01, -INT},
56 1.1 maya { FE_TONEAREST, +INT-0.01, INT},
57 1.1 maya { FE_TONEAREST, -INT+0.01, -INT},
58 1.1 maya { FE_TONEAREST, +INT+0.01, INT},
59 1.1 maya { FE_TONEAREST, -INT-0.501, -INT-1},
60 1.1 maya { FE_TONEAREST, +INT-0.501, INT-1},
61 1.1 maya { FE_TONEAREST, -INT+0.501, -INT+1},
62 1.1 maya { FE_TONEAREST, +INT+0.501, INT+1},
63 1.1 maya { FE_TONEAREST, +0, 0},
64 1.1 maya { FE_TONEAREST, -0, 0},
65 1.1 maya };
66 1.1 maya
67 1.1 maya ATF_TC(fe_round);
68 1.1 maya ATF_TC_HEAD(fe_round, tc)
69 1.1 maya {
70 1.1 maya atf_tc_set_md_var(tc, "descr","Checking IEEE 754 rounding modes using lrint");
71 1.1 maya }
72 1.1 maya
73 1.1 maya ATF_TC_BODY(fe_round, tc)
74 1.1 maya {
75 1.1 maya long int received;
76 1.1 maya
77 1.1 maya for (unsigned int i = 0; i < __arraycount(values); i++) {
78 1.1 maya fesetround(values[i].round_mode);
79 1.1 maya
80 1.1 maya received = lrint(values[i].input);
81 1.1 maya ATF_CHECK_MSG(
82 1.2 maya (labs(received - values[i].expected) < EPSILON),
83 1.1 maya "lrint rounding wrong, difference too large\n"
84 1.1 maya "input: %f (index %d): got %ld, expected %ld\n",
85 1.1 maya values[i].input, i, received, values[i].expected);
86 1.1 maya
87 1.1 maya /* Do we get the same rounding mode out? */
88 1.1 maya ATF_CHECK_MSG(
89 1.1 maya (fegetround() == values[i].round_mode),
90 1.1 maya "Didn't get the same rounding mode out!\n"
91 1.1 maya "(index %d) fed in %d rounding mode, got %d out\n",
92 1.3 he i, values[i].round_mode, fegetround());
93 1.1 maya }
94 1.1 maya }
95 1.1 maya
96 1.6 he ATF_TC(fe_nearbyint);
97 1.6 he ATF_TC_HEAD(fe_nearbyint, tc)
98 1.6 he {
99 1.6 he atf_tc_set_md_var(tc, "descr","Checking IEEE 754 rounding modes using nearbyint");
100 1.6 he }
101 1.6 he
102 1.6 he ATF_TC_BODY(fe_nearbyint, tc)
103 1.6 he {
104 1.6 he double received;
105 1.6 he
106 1.6 he for (unsigned int i = 0; i < __arraycount(values); i++) {
107 1.6 he fesetround(values[i].round_mode);
108 1.6 he
109 1.6 he received = nearbyint(values[i].input);
110 1.6 he ATF_CHECK_MSG(
111 1.6 he (fabs(received - values[i].expected) < EPSILON),
112 1.6 he "nearbyint rounding wrong, difference too large\n"
113 1.6 he "input: %f (index %d): got %f, expected %ld\n",
114 1.6 he values[i].input, i, received, values[i].expected);
115 1.6 he
116 1.6 he /* Do we get the same rounding mode out? */
117 1.6 he ATF_CHECK_MSG(
118 1.6 he (fegetround() == values[i].round_mode),
119 1.6 he "Didn't get the same rounding mode out!\n"
120 1.6 he "(index %d) fed in %d rounding mode, got %d out\n",
121 1.6 he i, values[i].round_mode, fegetround());
122 1.6 he }
123 1.6 he }
124 1.6 he
125 1.7 he static const struct {
126 1.7 he double input;
127 1.7 he double toward;
128 1.7 he double expected;
129 1.7 he } values2[] = {
130 1.7 he { 10.0, 11.0, 10.0 },
131 1.7 he { -5.0, -6.0, -5.0 },
132 1.7 he };
133 1.7 he
134 1.7 he ATF_TC(fe_nextafter);
135 1.7 he ATF_TC_HEAD(fe_nextafter, tc)
136 1.7 he {
137 1.7 he atf_tc_set_md_var(tc, "descr", "Checking IEEE 754 rounding using nextafter()");
138 1.7 he }
139 1.7 he
140 1.7 he ATF_TC_BODY(fe_nextafter, tc)
141 1.7 he {
142 1.7 he double received;
143 1.7 he int res;
144 1.7 he
145 1.7 he for (unsigned int i = 0; i < __arraycount(values2); i++) {
146 1.7 he received = nextafter(values2[i].input, values2[i].toward);
147 1.7 he if (values2[i].input < values2[i].toward) {
148 1.7 he res = (received > values2[i].input);
149 1.7 he } else {
150 1.7 he res = (received < values2[i].input);
151 1.7 he }
152 1.7 he ATF_CHECK_MSG(
153 1.7 he res && (fabs(received - values2[i].expected) < EPSILON),
154 1.7 he "nextafter() rounding wrong, difference too large\n"
155 1.7 he "input: %f (index %d): got %f, expected %f, res %d\n",
156 1.7 he values2[i].input, i, received, values2[i].expected, res);
157 1.7 he }
158 1.7 he }
159 1.7 he
160 1.7 he ATF_TC(fe_nexttoward);
161 1.7 he ATF_TC_HEAD(fe_nexttoward, tc)
162 1.7 he {
163 1.7 he atf_tc_set_md_var(tc, "descr", "Checking IEEE 754 rounding using nexttoward()");
164 1.7 he }
165 1.7 he
166 1.7 he ATF_TC_BODY(fe_nexttoward, tc)
167 1.7 he {
168 1.7 he double received;
169 1.7 he int res;
170 1.7 he
171 1.7 he for (unsigned int i = 0; i < __arraycount(values2); i++) {
172 1.7 he received = nexttoward(values2[i].input, values2[i].toward);
173 1.7 he if (values2[i].input < values2[i].toward) {
174 1.7 he res = (received > values2[i].input);
175 1.7 he } else {
176 1.7 he res = (received < values2[i].input);
177 1.7 he }
178 1.7 he ATF_CHECK_MSG(
179 1.7 he res && (fabs(received - values2[i].expected) < EPSILON),
180 1.7 he "nexttoward() rounding wrong, difference too large\n"
181 1.7 he "input: %f (index %d): got %f, expected %f, res %d\n",
182 1.7 he values2[i].input, i, received, values2[i].expected, res);
183 1.7 he }
184 1.7 he }
185 1.7 he
186 1.1 maya ATF_TP_ADD_TCS(tp)
187 1.1 maya {
188 1.1 maya
189 1.1 maya ATF_TP_ADD_TC(tp, fe_round);
190 1.6 he ATF_TP_ADD_TC(tp, fe_nearbyint);
191 1.7 he ATF_TP_ADD_TC(tp, fe_nextafter);
192 1.7 he ATF_TP_ADD_TC(tp, fe_nexttoward);
193 1.1 maya
194 1.1 maya return atf_no_error();
195 1.1 maya }
196 1.1 maya #else
197 1.1 maya ATF_TC(t_nofe_round);
198 1.1 maya
199 1.1 maya ATF_TC_HEAD(t_nofe_round, tc)
200 1.1 maya {
201 1.1 maya atf_tc_set_md_var(tc, "descr",
202 1.1 maya "dummy test case - no fenv.h support");
203 1.1 maya }
204 1.1 maya
205 1.4 he ATF_TC_BODY(t_nofe_round, tc)
206 1.4 he {
207 1.4 he atf_tc_skip("no fenv.h support on this architecture");
208 1.4 he }
209 1.1 maya
210 1.6 he ATF_TC(t_nofe_nearbyint);
211 1.6 he
212 1.6 he ATF_TC_HEAD(t_nofe_nearbyint, tc)
213 1.6 he {
214 1.6 he atf_tc_set_md_var(tc, "descr",
215 1.6 he "dummy test case - no fenv.h support");
216 1.6 he }
217 1.6 he
218 1.6 he ATF_TC_BODY(t_nofe_nearbyint, tc)
219 1.6 he {
220 1.6 he atf_tc_skip("no fenv.h support on this architecture");
221 1.6 he }
222 1.6 he
223 1.7 he ATF_TC(t_nofe_nextafter);
224 1.7 he
225 1.7 he ATF_TC_HEAD(t_nofe_nextafter, tc)
226 1.7 he {
227 1.7 he atf_tc_set_md_var(tc, "descr",
228 1.7 he "dummy test case - no fenv.h support");
229 1.7 he }
230 1.7 he
231 1.7 he ATF_TC_BODY(t_nofe_nextafter, tc)
232 1.7 he {
233 1.7 he atf_tc_skip("no fenv.h support on this architecture");
234 1.7 he }
235 1.7 he
236 1.7 he ATF_TC(t_nofe_nexttoward);
237 1.7 he
238 1.7 he ATF_TC_HEAD(t_nofe_nexttoward, tc)
239 1.7 he {
240 1.7 he atf_tc_set_md_var(tc, "descr",
241 1.7 he "dummy test case - no fenv.h support");
242 1.7 he }
243 1.7 he
244 1.7 he ATF_TC_BODY(t_nofe_nexttoward, tc)
245 1.7 he {
246 1.7 he atf_tc_skip("no fenv.h support on this architecture");
247 1.7 he }
248 1.6 he
249 1.1 maya ATF_TP_ADD_TCS(tp)
250 1.1 maya {
251 1.1 maya ATF_TP_ADD_TC(tp, t_nofe_round);
252 1.6 he ATF_TP_ADD_TC(tp, t_nofe_nearbyint);
253 1.7 he ATF_TP_ADD_TC(tp, t_nofe_nextafter);
254 1.7 he ATF_TP_ADD_TC(tp, t_nofe_nexttoward);
255 1.1 maya return atf_no_error();
256 1.1 maya }
257 1.1 maya
258 1.1 maya #endif
259