t_fe_round.c revision 1.18 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.12 kre #include <stdint.h>
13 1.1 maya #include <stdio.h>
14 1.1 maya #include <stdlib.h>
15 1.1 maya
16 1.1 maya /*#pragma STDC FENV_ACCESS ON gcc?? */
17 1.1 maya
18 1.1 maya #define INT 9223L
19 1.1 maya
20 1.1 maya #define EPSILON 0.001
21 1.1 maya
22 1.10 riastrad static const char *
23 1.10 riastrad rmname(int rm)
24 1.10 riastrad {
25 1.10 riastrad switch (rm) {
26 1.10 riastrad case FE_TOWARDZERO:
27 1.10 riastrad return "FE_TOWARDZERO";
28 1.10 riastrad case FE_DOWNWARD:
29 1.10 riastrad return "FE_DOWNWARD";
30 1.10 riastrad case FE_UPWARD:
31 1.10 riastrad return "FE_UPWARD";
32 1.10 riastrad case FE_TONEAREST:
33 1.10 riastrad return "FE_TONEAREST";
34 1.10 riastrad default:
35 1.10 riastrad return "unknown";
36 1.10 riastrad }
37 1.10 riastrad }
38 1.10 riastrad
39 1.1 maya static const struct {
40 1.1 maya int round_mode;
41 1.1 maya double input;
42 1.1 maya long int expected;
43 1.1 maya } values[] = {
44 1.16 riastrad { FE_DOWNWARD, 3.75, 3},
45 1.16 riastrad { FE_DOWNWARD, -3.75, -4},
46 1.16 riastrad { FE_DOWNWARD, +0., 0},
47 1.16 riastrad { FE_DOWNWARD, -INT-0.0625, -INT-1},
48 1.16 riastrad { FE_DOWNWARD, +INT-0.0625, INT-1},
49 1.16 riastrad { FE_DOWNWARD, -INT+0.0625, -INT},
50 1.16 riastrad { FE_DOWNWARD, +INT+0.0625, INT},
51 1.1 maya #if 0 /* cpu bugs? */
52 1.16 riastrad { FE_DOWNWARD, -0., -1},
53 1.1 maya
54 1.16 riastrad { FE_UPWARD, +0., 1},
55 1.1 maya #endif
56 1.16 riastrad { FE_UPWARD, -0., 0},
57 1.16 riastrad { FE_UPWARD, -123.75, -123},
58 1.16 riastrad { FE_UPWARD, 123.75, 124},
59 1.16 riastrad { FE_UPWARD, -INT-0.0625, -INT},
60 1.16 riastrad { FE_UPWARD, +INT-0.0625, INT},
61 1.16 riastrad { FE_UPWARD, -INT+0.0625, -INT+1},
62 1.16 riastrad { FE_UPWARD, +INT+0.0625, INT+1},
63 1.16 riastrad
64 1.16 riastrad { FE_TOWARDZERO, 1.9375, 1},
65 1.16 riastrad { FE_TOWARDZERO, -1.9375, -1},
66 1.16 riastrad { FE_TOWARDZERO, 0.25, 0},
67 1.16 riastrad { FE_TOWARDZERO, INT+0.0625, INT},
68 1.16 riastrad { FE_TOWARDZERO, INT-0.0625, INT - 1},
69 1.16 riastrad { FE_TOWARDZERO, -INT+0.0625, -INT + 1},
70 1.16 riastrad { FE_TOWARDZERO, +0., 0},
71 1.16 riastrad { FE_TOWARDZERO, -0., 0},
72 1.16 riastrad
73 1.16 riastrad { FE_TONEAREST, -INT-0.0625, -INT},
74 1.16 riastrad { FE_TONEAREST, +INT-0.0625, INT},
75 1.16 riastrad { FE_TONEAREST, -INT+0.0625, -INT},
76 1.16 riastrad { FE_TONEAREST, +INT+0.0625, INT},
77 1.16 riastrad { FE_TONEAREST, -INT-0.53125, -INT-1},
78 1.16 riastrad { FE_TONEAREST, +INT-0.53125, INT-1},
79 1.16 riastrad { FE_TONEAREST, -INT+0.53125, -INT+1},
80 1.16 riastrad { FE_TONEAREST, +INT+0.53125, INT+1},
81 1.16 riastrad { FE_TONEAREST, +0., 0},
82 1.16 riastrad { FE_TONEAREST, -0., 0},
83 1.1 maya };
84 1.1 maya
85 1.16 riastrad ATF_TC(fe_lrint);
86 1.16 riastrad ATF_TC_HEAD(fe_lrint, tc)
87 1.1 maya {
88 1.16 riastrad atf_tc_set_md_var(tc, "descr",
89 1.16 riastrad "Checking IEEE 754 rounding modes using lrint(3)");
90 1.1 maya }
91 1.1 maya
92 1.16 riastrad ATF_TC_BODY(fe_lrint, tc)
93 1.1 maya {
94 1.16 riastrad enum {
95 1.16 riastrad LLRINT,
96 1.16 riastrad LLRINTF,
97 1.16 riastrad LRINT,
98 1.16 riastrad LRINTF,
99 1.16 riastrad N_FN,
100 1.16 riastrad } fn;
101 1.16 riastrad static const char *const fnname[] = {
102 1.16 riastrad [LLRINT] = "llrint",
103 1.16 riastrad [LLRINTF] = "llrintf",
104 1.16 riastrad [LRINT] = "lrint",
105 1.16 riastrad [LRINTF] = "lrintf",
106 1.16 riastrad };
107 1.1 maya long int received;
108 1.16 riastrad unsigned i;
109 1.1 maya
110 1.16 riastrad for (i = 0; i < __arraycount(values); i++) {
111 1.16 riastrad for (fn = 0; fn < N_FN; fn++) {
112 1.16 riastrad /*
113 1.16 riastrad * Set the requested rounding mode.
114 1.16 riastrad */
115 1.16 riastrad fesetround(values[i].round_mode);
116 1.16 riastrad
117 1.16 riastrad /*
118 1.16 riastrad * Call the lrint(3)-family function.
119 1.16 riastrad */
120 1.16 riastrad switch (fn) {
121 1.16 riastrad case LLRINT:
122 1.16 riastrad received = llrint(values[i].input);
123 1.16 riastrad break;
124 1.16 riastrad case LLRINTF:
125 1.16 riastrad received = llrintf(values[i].input);
126 1.16 riastrad break;
127 1.16 riastrad case LRINT:
128 1.16 riastrad received = lrint(values[i].input);
129 1.16 riastrad break;
130 1.16 riastrad case LRINTF:
131 1.16 riastrad received = lrintf(values[i].input);
132 1.16 riastrad break;
133 1.16 riastrad default:
134 1.16 riastrad atf_tc_fail("impossible");
135 1.16 riastrad }
136 1.16 riastrad
137 1.16 riastrad /*
138 1.16 riastrad * Assuming the result we got has zero
139 1.16 riastrad * fractional part, casting to long int should
140 1.16 riastrad * have no rounding. Verify it matches the
141 1.16 riastrad * integer we expect.
142 1.16 riastrad */
143 1.16 riastrad ATF_CHECK_MSG((long int)received == values[i].expected,
144 1.16 riastrad "[%u] %s %s(%f): got %ld, expected %ld",
145 1.16 riastrad i, rmname(values[i].round_mode), fnname[fn],
146 1.16 riastrad values[i].input,
147 1.16 riastrad (long int)received, values[i].expected);
148 1.16 riastrad
149 1.16 riastrad /* Do we get the same rounding mode out? */
150 1.16 riastrad ATF_CHECK_MSG(fegetround() == values[i].round_mode,
151 1.16 riastrad "[%u] %s: set %d (%s), got %d (%s)",
152 1.16 riastrad i, fnname[fn],
153 1.16 riastrad values[i].round_mode, rmname(values[i].round_mode),
154 1.16 riastrad fegetround(), rmname(fegetround()));
155 1.16 riastrad }
156 1.1 maya }
157 1.1 maya }
158 1.1 maya
159 1.16 riastrad ATF_TC(fe_nearbyint_rint);
160 1.16 riastrad ATF_TC_HEAD(fe_nearbyint_rint, tc)
161 1.6 he {
162 1.10 riastrad atf_tc_set_md_var(tc, "descr",
163 1.16 riastrad "Checking IEEE 754 rounding modes using nearbyint/rint");
164 1.6 he }
165 1.6 he
166 1.16 riastrad ATF_TC_BODY(fe_nearbyint_rint, tc)
167 1.6 he {
168 1.16 riastrad enum {
169 1.16 riastrad NEARBYINT,
170 1.16 riastrad NEARBYINTF,
171 1.16 riastrad NEARBYINTL,
172 1.16 riastrad RINT,
173 1.16 riastrad RINTF,
174 1.16 riastrad RINTL,
175 1.16 riastrad N_FN,
176 1.16 riastrad } fn;
177 1.16 riastrad static const char *const fnname[] = {
178 1.16 riastrad [NEARBYINT] = "nearbyint",
179 1.16 riastrad [NEARBYINTF] = "nearbyintf",
180 1.16 riastrad [NEARBYINTL] = "nearbyintl",
181 1.16 riastrad [RINT] = "rint",
182 1.16 riastrad [RINTF] = "rintf",
183 1.16 riastrad [RINTL] = "rintl",
184 1.16 riastrad };
185 1.10 riastrad double received, ipart, fpart;
186 1.16 riastrad unsigned i;
187 1.6 he
188 1.16 riastrad for (i = 0; i < __arraycount(values); i++) {
189 1.16 riastrad for (fn = 0; fn < N_FN; fn++) {
190 1.16 riastrad bool expect_except =
191 1.16 riastrad values[i].input != (double)values[i].expected;
192 1.16 riastrad
193 1.16 riastrad /*
194 1.16 riastrad * Set the requested rounding mode.
195 1.16 riastrad */
196 1.16 riastrad fesetround(values[i].round_mode);
197 1.16 riastrad
198 1.17 riastrad #ifdef __ia64__
199 1.17 riastrad /*
200 1.17 riastrad * Without this barrier, we get:
201 1.17 riastrad *
202 1.17 riastrad * /tmp//ccJayu9g.s:2793: Warning: Use of 'mov.m' violates RAW dependency 'AR[FPSR].sf0.flags' (impliedf)
203 1.17 riastrad * /tmp//ccJayu9g.s:2793: Warning: Only the first path encountering the conflict is reported
204 1.17 riastrad * /tmp//ccJayu9g.s:2757: Warning: This is the location of the conflicting usage
205 1.17 riastrad *
206 1.17 riastrad * (If you fix this, remove the entry from doc/HACKS.)
207 1.17 riastrad */
208 1.17 riastrad __insn_barrier();
209 1.17 riastrad #endif
210 1.17 riastrad
211 1.16 riastrad /*
212 1.16 riastrad * Clear sticky floating-point exception bits
213 1.16 riastrad * so we can verify whether the FE_INEXACT
214 1.16 riastrad * exception is raised.
215 1.16 riastrad */
216 1.16 riastrad feclearexcept(FE_ALL_EXCEPT);
217 1.16 riastrad
218 1.16 riastrad /*
219 1.16 riastrad * Call the rint(3)-family function.
220 1.16 riastrad */
221 1.16 riastrad switch (fn) {
222 1.16 riastrad case NEARBYINT:
223 1.16 riastrad received = nearbyint(values[i].input);
224 1.16 riastrad expect_except = false;
225 1.16 riastrad break;
226 1.16 riastrad case NEARBYINTF:
227 1.16 riastrad received = nearbyintf(values[i].input);
228 1.16 riastrad expect_except = false;
229 1.16 riastrad break;
230 1.16 riastrad case NEARBYINTL:
231 1.16 riastrad received = nearbyintl(values[i].input);
232 1.16 riastrad expect_except = false;
233 1.16 riastrad break;
234 1.16 riastrad case RINT:
235 1.16 riastrad received = rint(values[i].input);
236 1.16 riastrad break;
237 1.16 riastrad case RINTF:
238 1.16 riastrad received = rintf(values[i].input);
239 1.16 riastrad break;
240 1.16 riastrad case RINTL:
241 1.16 riastrad received = rintl(values[i].input);
242 1.16 riastrad break;
243 1.16 riastrad default:
244 1.16 riastrad atf_tc_fail("impossible");
245 1.16 riastrad }
246 1.16 riastrad
247 1.16 riastrad /*
248 1.16 riastrad * Verify FE_INEXACT was raised or not,
249 1.16 riastrad * depending on whether there was rounding and
250 1.16 riastrad * whether the function is supposed to raise
251 1.16 riastrad * exceptions.
252 1.16 riastrad */
253 1.16 riastrad if (expect_except) {
254 1.16 riastrad ATF_CHECK_MSG(fetestexcept(FE_INEXACT) != 0,
255 1.16 riastrad "[%u] %s %s(%f)"
256 1.16 riastrad " failed to raise FE_INEXACT",
257 1.16 riastrad i, rmname(values[i].round_mode),
258 1.16 riastrad fnname[fn], values[i].input);
259 1.16 riastrad } else {
260 1.16 riastrad ATF_CHECK_MSG(fetestexcept(FE_INEXACT) == 0,
261 1.16 riastrad "[%u] %s %s(%f)"
262 1.16 riastrad " spuriously raised FE_INEXACT",
263 1.16 riastrad i, rmname(values[i].round_mode),
264 1.16 riastrad fnname[fn], values[i].input);
265 1.16 riastrad }
266 1.16 riastrad
267 1.16 riastrad /*
268 1.16 riastrad * Verify the fractional part of the result is
269 1.16 riastrad * zero -- the result of rounding to an integer
270 1.16 riastrad * is supposed to be an integer.
271 1.16 riastrad */
272 1.16 riastrad fpart = modf(received, &ipart);
273 1.16 riastrad ATF_CHECK_MSG(fpart == 0,
274 1.16 riastrad "[%u] %s %s(%f)=%f has fractional part %f"
275 1.16 riastrad " (integer part %f)",
276 1.16 riastrad i, rmname(values[i].round_mode), fnname[fn],
277 1.16 riastrad values[i].input, received, fpart, ipart);
278 1.16 riastrad
279 1.16 riastrad /*
280 1.16 riastrad * Assuming the result we got has zero
281 1.16 riastrad * fractional part, casting to long int should
282 1.16 riastrad * have no rounding. Verify it matches the
283 1.16 riastrad * integer we expect.
284 1.16 riastrad */
285 1.16 riastrad ATF_CHECK_MSG((long int)received == values[i].expected,
286 1.16 riastrad "[%u] %s %s(%f): got %f, expected %ld",
287 1.16 riastrad i, rmname(values[i].round_mode), fnname[fn],
288 1.16 riastrad values[i].input, received, values[i].expected);
289 1.16 riastrad
290 1.16 riastrad /* Do we get the same rounding mode out? */
291 1.16 riastrad ATF_CHECK_MSG(fegetround() == values[i].round_mode,
292 1.16 riastrad "[%u] %s: set %d (%s), got %d (%s)",
293 1.16 riastrad i, fnname[fn],
294 1.16 riastrad values[i].round_mode, rmname(values[i].round_mode),
295 1.16 riastrad fegetround(), rmname(fegetround()));
296 1.16 riastrad }
297 1.6 he }
298 1.6 he }
299 1.6 he
300 1.11 riastrad #ifdef __HAVE_LONG_DOUBLE
301 1.11 riastrad
302 1.11 riastrad /*
303 1.11 riastrad * Use one bit more than fits in IEEE 754 binary64.
304 1.11 riastrad */
305 1.11 riastrad static const struct {
306 1.11 riastrad int round_mode;
307 1.11 riastrad long double input;
308 1.16 riastrad int64_t expected;
309 1.11 riastrad } valuesl[] = {
310 1.13 riastrad { FE_TOWARDZERO, 0x2.00000000000008p+52L, 0x20000000000000 },
311 1.13 riastrad { FE_DOWNWARD, 0x2.00000000000008p+52L, 0x20000000000000 },
312 1.13 riastrad { FE_UPWARD, 0x2.00000000000008p+52L, 0x20000000000001 },
313 1.13 riastrad { FE_TONEAREST, 0x2.00000000000008p+52L, 0x20000000000000 },
314 1.13 riastrad { FE_TOWARDZERO, 0x2.00000000000018p+52L, 0x20000000000001 },
315 1.13 riastrad { FE_DOWNWARD, 0x2.00000000000018p+52L, 0x20000000000001 },
316 1.13 riastrad { FE_UPWARD, 0x2.00000000000018p+52L, 0x20000000000002 },
317 1.13 riastrad { FE_TONEAREST, 0x2.00000000000018p+52L, 0x20000000000002 },
318 1.11 riastrad };
319 1.11 riastrad
320 1.16 riastrad ATF_TC(fe_nearbyintl_rintl);
321 1.16 riastrad ATF_TC_HEAD(fe_nearbyintl_rintl, tc)
322 1.11 riastrad {
323 1.11 riastrad atf_tc_set_md_var(tc, "descr",
324 1.16 riastrad "Checking IEEE 754 rounding modes using nearbyintl/rintl");
325 1.11 riastrad }
326 1.11 riastrad
327 1.16 riastrad ATF_TC_BODY(fe_nearbyintl_rintl, tc)
328 1.11 riastrad {
329 1.16 riastrad enum {
330 1.16 riastrad RINTL,
331 1.16 riastrad NEARBYINTL,
332 1.16 riastrad N_FN,
333 1.16 riastrad } fn;
334 1.16 riastrad static const char *const fnname[] = {
335 1.16 riastrad [RINTL] = "rintl",
336 1.16 riastrad [NEARBYINTL] = "nearbyintl",
337 1.16 riastrad };
338 1.11 riastrad long double received, ipart, fpart;
339 1.16 riastrad unsigned i;
340 1.11 riastrad
341 1.16 riastrad for (i = 0; i < __arraycount(valuesl); i++) {
342 1.16 riastrad for (fn = 0; fn < N_FN; fn++) {
343 1.16 riastrad bool expect_except =
344 1.16 riastrad (valuesl[i].input !=
345 1.16 riastrad (long double)valuesl[i].expected);
346 1.16 riastrad
347 1.16 riastrad /*
348 1.16 riastrad * Set the requested rounding mode.
349 1.16 riastrad */
350 1.16 riastrad fesetround(valuesl[i].round_mode);
351 1.16 riastrad
352 1.16 riastrad /*
353 1.16 riastrad * Clear sticky floating-point exception bits
354 1.16 riastrad * so we can verify whether the FE_INEXACT
355 1.16 riastrad * exception is raised.
356 1.16 riastrad */
357 1.16 riastrad feclearexcept(FE_ALL_EXCEPT);
358 1.16 riastrad
359 1.16 riastrad /*
360 1.16 riastrad * Call the rint(3)-family function.
361 1.16 riastrad */
362 1.16 riastrad switch (fn) {
363 1.16 riastrad case NEARBYINTL:
364 1.16 riastrad received = nearbyintl(valuesl[i].input);
365 1.16 riastrad expect_except = false;
366 1.16 riastrad break;
367 1.16 riastrad case RINTL:
368 1.16 riastrad received = rintl(valuesl[i].input);
369 1.16 riastrad break;
370 1.16 riastrad default:
371 1.16 riastrad atf_tc_fail("impossible");
372 1.16 riastrad }
373 1.16 riastrad
374 1.16 riastrad /*
375 1.16 riastrad * Verify FE_INEXACT was raised or not,
376 1.16 riastrad * depending on whether there was rounding and
377 1.16 riastrad * whether the function is supposed to raise
378 1.16 riastrad * exceptions.
379 1.16 riastrad */
380 1.16 riastrad if (expect_except) {
381 1.16 riastrad ATF_CHECK_MSG(fetestexcept(FE_INEXACT) != 0,
382 1.16 riastrad "[%u] %s %s(%Lf)"
383 1.16 riastrad " failed to raise FE_INEXACT",
384 1.16 riastrad i, rmname(valuesl[i].round_mode),
385 1.16 riastrad fnname[fn], valuesl[i].input);
386 1.16 riastrad } else {
387 1.16 riastrad ATF_CHECK_MSG(fetestexcept(FE_INEXACT) == 0,
388 1.16 riastrad "[%u] %s %s(%Lf)"
389 1.16 riastrad " spuriously raised FE_INEXACT",
390 1.16 riastrad i, rmname(valuesl[i].round_mode),
391 1.16 riastrad fnname[fn], valuesl[i].input);
392 1.16 riastrad }
393 1.16 riastrad
394 1.18 riastrad #if __HAVE_LONG_DOUBLE + 0 == 128
395 1.18 riastrad atf_tc_expect_fail("PR lib/58237:"
396 1.18 riastrad " modfl returns wrong answers"
397 1.18 riastrad " on ld128 architectures");
398 1.18 riastrad #endif
399 1.18 riastrad
400 1.16 riastrad /*
401 1.16 riastrad * Verify the fractional part of the result is
402 1.16 riastrad * zero -- the result of rounding to an integer
403 1.16 riastrad * is supposed to be an integer.
404 1.16 riastrad */
405 1.16 riastrad fpart = modfl(received, &ipart);
406 1.16 riastrad ATF_CHECK_MSG(fpart == 0,
407 1.16 riastrad "[%u] %s %s(%Lf)=%Lf has fractional part %Lf"
408 1.16 riastrad " (integer part %Lf)",
409 1.16 riastrad i, rmname(valuesl[i].round_mode), fnname[fn],
410 1.16 riastrad valuesl[i].input, received, fpart, ipart);
411 1.16 riastrad
412 1.16 riastrad /*
413 1.16 riastrad * Assuming the result we got has zero
414 1.16 riastrad * fractional part, casting to int64_t should
415 1.16 riastrad * have no rounding. Verify it matches the
416 1.16 riastrad * integer we expect.
417 1.16 riastrad */
418 1.16 riastrad ATF_CHECK_MSG(((int64_t)received ==
419 1.16 riastrad valuesl[i].expected),
420 1.16 riastrad "[%u] %s %s(%Lf): got %Lf, expected %jd",
421 1.16 riastrad i, rmname(valuesl[i].round_mode), fnname[fn],
422 1.16 riastrad valuesl[i].input, received, valuesl[i].expected);
423 1.16 riastrad
424 1.16 riastrad /* Do we get the same rounding mode out? */
425 1.16 riastrad ATF_CHECK_MSG(fegetround() == valuesl[i].round_mode,
426 1.16 riastrad "[%u] %s: set %d (%s), got %d (%s)",
427 1.16 riastrad i, fnname[fn],
428 1.16 riastrad valuesl[i].round_mode,
429 1.16 riastrad rmname(valuesl[i].round_mode),
430 1.16 riastrad fegetround(), rmname(fegetround()));
431 1.16 riastrad }
432 1.11 riastrad }
433 1.11 riastrad }
434 1.11 riastrad
435 1.11 riastrad #endif
436 1.11 riastrad
437 1.7 he static const struct {
438 1.7 he double input;
439 1.7 he double toward;
440 1.7 he double expected;
441 1.7 he } values2[] = {
442 1.7 he { 10.0, 11.0, 10.0 },
443 1.7 he { -5.0, -6.0, -5.0 },
444 1.7 he };
445 1.7 he
446 1.7 he ATF_TC(fe_nextafter);
447 1.7 he ATF_TC_HEAD(fe_nextafter, tc)
448 1.7 he {
449 1.7 he atf_tc_set_md_var(tc, "descr", "Checking IEEE 754 rounding using nextafter()");
450 1.7 he }
451 1.7 he
452 1.7 he ATF_TC_BODY(fe_nextafter, tc)
453 1.7 he {
454 1.7 he double received;
455 1.7 he int res;
456 1.7 he
457 1.7 he for (unsigned int i = 0; i < __arraycount(values2); i++) {
458 1.7 he received = nextafter(values2[i].input, values2[i].toward);
459 1.7 he if (values2[i].input < values2[i].toward) {
460 1.7 he res = (received > values2[i].input);
461 1.7 he } else {
462 1.7 he res = (received < values2[i].input);
463 1.7 he }
464 1.7 he ATF_CHECK_MSG(
465 1.7 he res && (fabs(received - values2[i].expected) < EPSILON),
466 1.7 he "nextafter() rounding wrong, difference too large\n"
467 1.7 he "input: %f (index %d): got %f, expected %f, res %d\n",
468 1.7 he values2[i].input, i, received, values2[i].expected, res);
469 1.7 he }
470 1.7 he }
471 1.7 he
472 1.7 he ATF_TC(fe_nexttoward);
473 1.7 he ATF_TC_HEAD(fe_nexttoward, tc)
474 1.7 he {
475 1.7 he atf_tc_set_md_var(tc, "descr", "Checking IEEE 754 rounding using nexttoward()");
476 1.7 he }
477 1.7 he
478 1.7 he ATF_TC_BODY(fe_nexttoward, tc)
479 1.7 he {
480 1.7 he double received;
481 1.7 he int res;
482 1.7 he
483 1.7 he for (unsigned int i = 0; i < __arraycount(values2); i++) {
484 1.7 he received = nexttoward(values2[i].input, values2[i].toward);
485 1.7 he if (values2[i].input < values2[i].toward) {
486 1.7 he res = (received > values2[i].input);
487 1.7 he } else {
488 1.7 he res = (received < values2[i].input);
489 1.7 he }
490 1.7 he ATF_CHECK_MSG(
491 1.7 he res && (fabs(received - values2[i].expected) < EPSILON),
492 1.7 he "nexttoward() rounding wrong, difference too large\n"
493 1.7 he "input: %f (index %d): got %f, expected %f, res %d\n",
494 1.7 he values2[i].input, i, received, values2[i].expected, res);
495 1.7 he }
496 1.7 he }
497 1.7 he
498 1.1 maya ATF_TP_ADD_TCS(tp)
499 1.1 maya {
500 1.1 maya
501 1.16 riastrad ATF_TP_ADD_TC(tp, fe_lrint);
502 1.16 riastrad ATF_TP_ADD_TC(tp, fe_nearbyint_rint);
503 1.11 riastrad #ifdef __HAVE_LONG_DOUBLE
504 1.16 riastrad ATF_TP_ADD_TC(tp, fe_nearbyintl_rintl);
505 1.11 riastrad #endif
506 1.7 he ATF_TP_ADD_TC(tp, fe_nextafter);
507 1.7 he ATF_TP_ADD_TC(tp, fe_nexttoward);
508 1.1 maya
509 1.1 maya return atf_no_error();
510 1.1 maya }
511 1.1 maya #else
512 1.1 maya ATF_TC(t_nofe_round);
513 1.1 maya
514 1.1 maya ATF_TC_HEAD(t_nofe_round, tc)
515 1.1 maya {
516 1.1 maya atf_tc_set_md_var(tc, "descr",
517 1.1 maya "dummy test case - no fenv.h support");
518 1.1 maya }
519 1.1 maya
520 1.4 he ATF_TC_BODY(t_nofe_round, tc)
521 1.4 he {
522 1.4 he atf_tc_skip("no fenv.h support on this architecture");
523 1.4 he }
524 1.1 maya
525 1.6 he ATF_TC(t_nofe_nearbyint);
526 1.6 he
527 1.6 he ATF_TC_HEAD(t_nofe_nearbyint, tc)
528 1.6 he {
529 1.6 he atf_tc_set_md_var(tc, "descr",
530 1.6 he "dummy test case - no fenv.h support");
531 1.6 he }
532 1.6 he
533 1.6 he ATF_TC_BODY(t_nofe_nearbyint, tc)
534 1.6 he {
535 1.6 he atf_tc_skip("no fenv.h support on this architecture");
536 1.6 he }
537 1.6 he
538 1.7 he ATF_TC(t_nofe_nextafter);
539 1.7 he
540 1.7 he ATF_TC_HEAD(t_nofe_nextafter, tc)
541 1.7 he {
542 1.7 he atf_tc_set_md_var(tc, "descr",
543 1.7 he "dummy test case - no fenv.h support");
544 1.7 he }
545 1.7 he
546 1.7 he ATF_TC_BODY(t_nofe_nextafter, tc)
547 1.7 he {
548 1.7 he atf_tc_skip("no fenv.h support on this architecture");
549 1.7 he }
550 1.7 he
551 1.7 he ATF_TC(t_nofe_nexttoward);
552 1.7 he
553 1.7 he ATF_TC_HEAD(t_nofe_nexttoward, tc)
554 1.7 he {
555 1.7 he atf_tc_set_md_var(tc, "descr",
556 1.7 he "dummy test case - no fenv.h support");
557 1.7 he }
558 1.7 he
559 1.7 he ATF_TC_BODY(t_nofe_nexttoward, tc)
560 1.7 he {
561 1.7 he atf_tc_skip("no fenv.h support on this architecture");
562 1.7 he }
563 1.6 he
564 1.1 maya ATF_TP_ADD_TCS(tp)
565 1.1 maya {
566 1.1 maya ATF_TP_ADD_TC(tp, t_nofe_round);
567 1.6 he ATF_TP_ADD_TC(tp, t_nofe_nearbyint);
568 1.7 he ATF_TP_ADD_TC(tp, t_nofe_nextafter);
569 1.7 he ATF_TP_ADD_TC(tp, t_nofe_nexttoward);
570 1.1 maya return atf_no_error();
571 1.1 maya }
572 1.1 maya
573 1.1 maya #endif
574