t_next.c revision 1.7.6.2 1 /* $NetBSD: t_next.c,v 1.7.6.2 2024/10/13 15:09:57 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2024 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: t_next.c,v 1.7.6.2 2024/10/13 15:09:57 martin Exp $");
31
32 #include <atf-c.h>
33 #include <float.h>
34 #include <math.h>
35
36 #ifdef __vax__ /* XXX PR 57881: vax libm is missing various symbols */
37
38 ATF_TC(vaxafter);
39 ATF_TC_HEAD(vaxafter, tc)
40 {
41
42 atf_tc_set_md_var(tc, "descr", "vax nextafter/nexttoward reminder");
43 }
44 ATF_TC_BODY(vaxafter, tc)
45 {
46
47 atf_tc_expect_fail("PR 57881: vax libm is missing various symbols");
48 atf_tc_fail("missing nextafter{,f,l} and nexttoward{,f,l} on vax");
49 }
50
51 #else /* !__vax__ */
52
53 #define CHECK(i, next, x, d, y) do \
54 { \
55 volatile __typeof__(x) check_x = (x); \
56 volatile __typeof__(d) check_d = (d); \
57 volatile __typeof__(y) check_y = (y); \
58 const volatile __typeof__(y) check_tmp = (next)(check_x, check_d); \
59 ATF_CHECK_MSG(check_tmp == check_y, \
60 "[%u] %s(%s=%La=%Lg, %s=%La=%Lg)=%La=%Lg != %s=%La=%Lg", \
61 (i), #next, \
62 #x, (long double)check_x, (long double)check_x, \
63 #d, (long double)check_d, (long double)check_d, \
64 (long double)check_tmp, (long double)check_tmp, \
65 #y, (long double)check_y, (long double)check_y); \
66 } while (0)
67
68 /*
69 * check(x, n)
70 *
71 * x[0], x[1], ..., x[n - 1] are consecutive double floating-point
72 * numbers. Verify nextafter and nexttoward follow exactly this
73 * sequence, forward and back, and in negative.
74 */
75 static void
76 check(const double *x, unsigned n)
77 {
78 unsigned i;
79
80 for (i = 0; i < n; i++) {
81 CHECK(i, nextafter, x[i], x[i], x[i]);
82 CHECK(i, nexttoward, x[i], x[i], x[i]);
83 CHECK(i, nextafter, -x[i], -x[i], -x[i]);
84 CHECK(i, nexttoward, -x[i], -x[i], -x[i]);
85 }
86
87 for (i = 0; i < n - 1; i++) {
88 ATF_REQUIRE_MSG(x[i] < x[i + 1], "i=%u", i);
89
90 if (isnormal(x[i])) {
91 CHECK(i, nexttoward, x[i], x[i]*(1 + LDBL_EPSILON),
92 x[i + 1]);
93 }
94
95 CHECK(i, nextafter, x[i], x[i + 1], x[i + 1]);
96 CHECK(i, nexttoward, x[i], x[i + 1], x[i + 1]);
97 CHECK(i, nextafter, x[i], x[n - 1], x[i + 1]);
98 CHECK(i, nexttoward, x[i], x[n - 1], x[i + 1]);
99 CHECK(i, nextafter, x[i], INFINITY, x[i + 1]);
100 CHECK(i, nexttoward, x[i], INFINITY, x[i + 1]);
101
102 CHECK(i, nextafter, -x[i], -x[i + 1], -x[i + 1]);
103 CHECK(i, nexttoward, -x[i], -x[i + 1], -x[i + 1]);
104 CHECK(i, nextafter, -x[i], -x[n - 1], -x[i + 1]);
105 CHECK(i, nexttoward, -x[i], -x[n - 1], -x[i + 1]);
106 CHECK(i, nextafter, -x[i], -INFINITY, -x[i + 1]);
107 CHECK(i, nexttoward, -x[i], -INFINITY, -x[i + 1]);
108 }
109
110 for (i = n; i --> 1;) {
111 ATF_REQUIRE_MSG(x[i - 1] < x[i], "i=%u", i);
112
113 if (isnormal(x[i])) {
114 CHECK(i, nexttoward, x[i], x[i]*(1 - LDBL_EPSILON/2),
115 x[i - 1]);
116 }
117
118 CHECK(i, nextafter, x[i], x[i - 1], x[i - 1]);
119 CHECK(i, nexttoward, x[i], x[i - 1], x[i - 1]);
120 CHECK(i, nextafter, x[i], x[0], x[i - 1]);
121 CHECK(i, nexttoward, x[i], x[0], x[i - 1]);
122 CHECK(i, nextafter, x[i], +0., x[i - 1]);
123 CHECK(i, nexttoward, x[i], +0., x[i - 1]);
124 CHECK(i, nextafter, x[i], -0., x[i - 1]);
125 CHECK(i, nexttoward, x[i], -0., x[i - 1]);
126 CHECK(i, nextafter, x[i], -x[0], x[i - 1]);
127 CHECK(i, nexttoward, x[i], -x[0], x[i - 1]);
128 CHECK(i, nextafter, x[i], -x[i], x[i - 1]);
129 CHECK(i, nexttoward, x[i], -x[i], x[i - 1]);
130 CHECK(i, nextafter, x[i], -INFINITY, x[i - 1]);
131 CHECK(i, nexttoward, x[i], -INFINITY, x[i - 1]);
132
133 CHECK(i, nextafter, -x[i], -x[i - 1], -x[i - 1]);
134 CHECK(i, nexttoward, -x[i], -x[i - 1], -x[i - 1]);
135 CHECK(i, nextafter, -x[i], -x[0], -x[i - 1]);
136 CHECK(i, nexttoward, -x[i], -x[0], -x[i - 1]);
137 CHECK(i, nextafter, -x[i], -0., -x[i - 1]);
138 CHECK(i, nexttoward, -x[i], -0., -x[i - 1]);
139 CHECK(i, nextafter, -x[i], +0., -x[i - 1]);
140 CHECK(i, nexttoward, -x[i], +0., -x[i - 1]);
141 CHECK(i, nextafter, -x[i], x[0], -x[i - 1]);
142 CHECK(i, nexttoward, -x[i], x[0], -x[i - 1]);
143 CHECK(i, nextafter, -x[i], INFINITY, -x[i - 1]);
144 CHECK(i, nexttoward, -x[i], INFINITY, -x[i - 1]);
145 }
146 }
147
148 /*
149 * checkf(x, n)
150 *
151 * x[0], x[1], ..., x[n - 1] are consecutive single floating-point
152 * numbers. Verify nextafterf and nexttowardf follow exactly this
153 * sequence, forward and back, and in negative.
154 */
155 static void
156 checkf(const float *x, unsigned n)
157 {
158 unsigned i;
159
160 for (i = 0; i < n; i++) {
161 CHECK(i, nextafterf, x[i], x[i], x[i]);
162 CHECK(i, nexttowardf, x[i], x[i], x[i]);
163 CHECK(i, nextafterf, -x[i], -x[i], -x[i]);
164 CHECK(i, nexttowardf, -x[i], -x[i], -x[i]);
165 }
166
167 for (i = 0; i < n - 1; i++) {
168 ATF_REQUIRE_MSG(x[i] < x[i + 1], "i=%u", i);
169
170 if (isnormal(x[i])) {
171 CHECK(i, nexttowardf, x[i], x[i]*(1 + LDBL_EPSILON),
172 x[i + 1]);
173 }
174
175 CHECK(i, nextafterf, x[i], x[i + 1], x[i + 1]);
176 CHECK(i, nexttowardf, x[i], x[i + 1], x[i + 1]);
177 CHECK(i, nextafterf, x[i], x[n - 1], x[i + 1]);
178 CHECK(i, nexttowardf, x[i], x[n - 1], x[i + 1]);
179 CHECK(i, nextafterf, x[i], INFINITY, x[i + 1]);
180 CHECK(i, nexttowardf, x[i], INFINITY, x[i + 1]);
181
182 CHECK(i, nextafterf, -x[i], -x[i + 1], -x[i + 1]);
183 CHECK(i, nexttowardf, -x[i], -x[i + 1], -x[i + 1]);
184 CHECK(i, nextafterf, -x[i], -x[n - 1], -x[i + 1]);
185 CHECK(i, nexttowardf, -x[i], -x[n - 1], -x[i + 1]);
186 CHECK(i, nextafterf, -x[i], -INFINITY, -x[i + 1]);
187 CHECK(i, nexttowardf, -x[i], -INFINITY, -x[i + 1]);
188 }
189
190 for (i = n; i --> 1;) {
191 ATF_REQUIRE_MSG(x[i - 1] < x[i], "i=%u", i);
192
193 if (isnormal(x[i])) {
194 CHECK(i, nexttowardf, x[i], x[i]*(1 - LDBL_EPSILON/2),
195 x[i - 1]);
196 }
197
198 CHECK(i, nextafterf, x[i], x[i - 1], x[i - 1]);
199 CHECK(i, nexttowardf, x[i], x[i - 1], x[i - 1]);
200 CHECK(i, nextafterf, x[i], x[0], x[i - 1]);
201 CHECK(i, nexttowardf, x[i], x[0], x[i - 1]);
202 CHECK(i, nextafterf, x[i], +0., x[i - 1]);
203 CHECK(i, nexttowardf, x[i], +0., x[i - 1]);
204 CHECK(i, nextafterf, x[i], -0., x[i - 1]);
205 CHECK(i, nexttowardf, x[i], -0., x[i - 1]);
206 CHECK(i, nextafterf, x[i], -x[0], x[i - 1]);
207 CHECK(i, nexttowardf, x[i], -x[0], x[i - 1]);
208 CHECK(i, nextafterf, x[i], -x[i], x[i - 1]);
209 CHECK(i, nexttowardf, x[i], -x[i], x[i - 1]);
210 CHECK(i, nextafterf, x[i], -INFINITY, x[i - 1]);
211 CHECK(i, nexttowardf, x[i], -INFINITY, x[i - 1]);
212
213 CHECK(i, nextafterf, -x[i], -x[i - 1], -x[i - 1]);
214 CHECK(i, nexttowardf, -x[i], -x[i - 1], -x[i - 1]);
215 CHECK(i, nextafterf, -x[i], -x[0], -x[i - 1]);
216 CHECK(i, nexttowardf, -x[i], -x[0], -x[i - 1]);
217 CHECK(i, nextafterf, -x[i], -0., -x[i - 1]);
218 CHECK(i, nexttowardf, -x[i], -0., -x[i - 1]);
219 CHECK(i, nextafterf, -x[i], +0., -x[i - 1]);
220 CHECK(i, nexttowardf, -x[i], +0., -x[i - 1]);
221 CHECK(i, nextafterf, -x[i], x[0], -x[i - 1]);
222 CHECK(i, nexttowardf, -x[i], x[0], -x[i - 1]);
223 CHECK(i, nextafterf, -x[i], INFINITY, -x[i - 1]);
224 CHECK(i, nexttowardf, -x[i], INFINITY, -x[i - 1]);
225 }
226 }
227
228 /*
229 * checkl(x, n)
230 *
231 * x[0], x[1], ..., x[n - 1] are consecutive long double
232 * floating-point numbers. Verify nextafterl and nexttowardl
233 * follow exactly this sequence, forward and back, and in
234 * negative.
235 */
236 static void
237 checkl(const long double *x, unsigned n)
238 {
239 unsigned i;
240
241 for (i = 0; i < n; i++) {
242 CHECK(i, nextafterl, x[i], x[i], x[i]);
243 CHECK(i, nexttowardl, x[i], x[i], x[i]);
244 CHECK(i, nextafterl, -x[i], -x[i], -x[i]);
245 CHECK(i, nexttowardl, -x[i], -x[i], -x[i]);
246 }
247
248 for (i = 0; i < n - 1; i++) {
249 ATF_REQUIRE_MSG(x[i] < x[i + 1], "i=%u", i);
250
251 CHECK(i, nextafterl, x[i], x[i + 1], x[i + 1]);
252 CHECK(i, nexttowardl, x[i], x[i + 1], x[i + 1]);
253 CHECK(i, nextafterl, x[i], x[n - 1], x[i + 1]);
254 CHECK(i, nexttowardl, x[i], x[n - 1], x[i + 1]);
255 CHECK(i, nextafterl, x[i], INFINITY, x[i + 1]);
256 CHECK(i, nexttowardl, x[i], INFINITY, x[i + 1]);
257
258 CHECK(i, nextafterl, -x[i], -x[i + 1], -x[i + 1]);
259 CHECK(i, nexttowardl, -x[i], -x[i + 1], -x[i + 1]);
260 CHECK(i, nextafterl, -x[i], -x[n - 1], -x[i + 1]);
261 CHECK(i, nexttowardl, -x[i], -x[n - 1], -x[i + 1]);
262 CHECK(i, nextafterl, -x[i], -INFINITY, -x[i + 1]);
263 CHECK(i, nexttowardl, -x[i], -INFINITY, -x[i + 1]);
264 }
265
266 for (i = n; i --> 1;) {
267 ATF_REQUIRE_MSG(x[i - 1] < x[i], "i=%u", i);
268
269 CHECK(i, nextafterl, x[i], x[i - 1], x[i - 1]);
270 CHECK(i, nexttowardl, x[i], x[i - 1], x[i - 1]);
271 CHECK(i, nextafterl, x[i], x[0], x[i - 1]);
272 CHECK(i, nexttowardl, x[i], x[0], x[i - 1]);
273 CHECK(i, nextafterl, x[i], +0., x[i - 1]);
274 CHECK(i, nexttowardl, x[i], +0., x[i - 1]);
275 CHECK(i, nextafterl, x[i], -0., x[i - 1]);
276 CHECK(i, nexttowardl, x[i], -0., x[i - 1]);
277 CHECK(i, nextafterl, x[i], -x[0], x[i - 1]);
278 CHECK(i, nexttowardl, x[i], -x[0], x[i - 1]);
279 CHECK(i, nextafterl, x[i], -x[i], x[i - 1]);
280 CHECK(i, nexttowardl, x[i], -x[i], x[i - 1]);
281 CHECK(i, nextafterl, x[i], -INFINITY, x[i - 1]);
282 CHECK(i, nexttowardl, x[i], -INFINITY, x[i - 1]);
283
284 CHECK(i, nextafterl, -x[i], -x[i - 1], -x[i - 1]);
285 CHECK(i, nexttowardl, -x[i], -x[i - 1], -x[i - 1]);
286 CHECK(i, nextafterl, -x[i], -x[0], -x[i - 1]);
287 CHECK(i, nexttowardl, -x[i], -x[0], -x[i - 1]);
288 CHECK(i, nextafterl, -x[i], -0., -x[i - 1]);
289 CHECK(i, nexttowardl, -x[i], -0., -x[i - 1]);
290 CHECK(i, nextafterl, -x[i], +0., -x[i - 1]);
291 CHECK(i, nexttowardl, -x[i], +0., -x[i - 1]);
292 CHECK(i, nextafterl, -x[i], x[0], -x[i - 1]);
293 CHECK(i, nexttowardl, -x[i], x[0], -x[i - 1]);
294 CHECK(i, nextafterl, -x[i], INFINITY, -x[i - 1]);
295 CHECK(i, nexttowardl, -x[i], INFINITY, -x[i - 1]);
296 }
297 }
298
299 ATF_TC(next_nan);
300 ATF_TC_HEAD(next_nan, tc)
301 {
302 atf_tc_set_md_var(tc, "descr", "nextafter/nexttoward on NaN");
303 }
304 ATF_TC_BODY(next_nan, tc)
305 {
306 #ifdef NAN
307 /* XXX verify the NaN is quiet */
308 ATF_CHECK(isnan(nextafter(NAN, 0)));
309 ATF_CHECK(isnan(nexttoward(NAN, 0)));
310 ATF_CHECK(isnan(nextafter(0, NAN)));
311 ATF_CHECK(isnan(nexttoward(0, NAN)));
312 #else
313 atf_tc_skip("no NaNs on this architecture");
314 #endif
315 }
316
317 ATF_TC(next_signed_0);
318 ATF_TC_HEAD(next_signed_0, tc)
319 {
320 atf_tc_set_md_var(tc, "descr", "nextafter/nexttoward on signed 0");
321 }
322 ATF_TC_BODY(next_signed_0, tc)
323 {
324 volatile double z_pos = +0.;
325 volatile double z_neg = -0.;
326 #ifdef __DBL_HAS_DENORM__
327 volatile double m = __DBL_DENORM_MIN__;
328 #else
329 volatile double m = DBL_MIN;
330 #endif
331
332 if (signbit(z_pos) == signbit(z_neg))
333 atf_tc_skip("no signed zeroes on this architecture");
334
335 /*
336 * `nextUp(x) is the least floating-point number in the format
337 * of x that compares greater than x. [...] nextDown(x) is
338 * -nextUp(-x).'
339 * --IEEE 754-2019, 5.3.1 General operations, p. 19
340 *
341 * Verify that nextafter and nexttoward, which implement the
342 * nextUp and nextDown operations, obey this rule and don't
343 * send -0 to +0 or +0 to -0, respectively.
344 */
345
346 CHECK(0, nextafter, z_neg, +INFINITY, m);
347 CHECK(1, nexttoward, z_neg, +INFINITY, m);
348 CHECK(2, nextafter, z_pos, +INFINITY, m);
349 CHECK(3, nexttoward, z_pos, +INFINITY, m);
350
351 CHECK(4, nextafter, z_pos, -INFINITY, -m);
352 CHECK(5, nexttoward, z_pos, -INFINITY, -m);
353 CHECK(6, nextafter, z_neg, -INFINITY, -m);
354 CHECK(7, nexttoward, z_neg, -INFINITY, -m);
355
356 /*
357 * `If x is the negative number of least magnitude in x's
358 * format, nextUp(x) is -0.'
359 * --IEEE 754-2019, 5.3.1 General operations, p. 19
360 *
361 * Verify that nextafter and nexttoward return the correctly
362 * signed zero.
363 */
364 CHECK(8, nextafter, -m, +INFINITY, 0);
365 CHECK(9, nexttoward, -m, +INFINITY, 0);
366 ATF_CHECK(signbit(nextafter(-m, +INFINITY)) != 0);
367 CHECK(10, nextafter, m, -INFINITY, 0);
368 CHECK(11, nexttoward, m, -INFINITY, 0);
369 ATF_CHECK(signbit(nextafter(m, -INFINITY)) == 0);
370 }
371
372 ATF_TC(next_near_0);
373 ATF_TC_HEAD(next_near_0, tc)
374 {
375 atf_tc_set_md_var(tc, "descr", "nextafter/nexttoward near 0");
376 }
377 ATF_TC_BODY(next_near_0, tc)
378 {
379 static const double x[] = {
380 [0] = 0,
381 #ifdef __DBL_HAS_DENORM__
382 [1] = __DBL_DENORM_MIN__,
383 [2] = 2*__DBL_DENORM_MIN__,
384 [3] = 3*__DBL_DENORM_MIN__,
385 [4] = 4*__DBL_DENORM_MIN__,
386 #else
387 [1] = DBL_MIN,
388 [2] = DBL_MIN*(1 + DBL_EPSILON),
389 [3] = DBL_MIN*(1 + 2*DBL_EPSILON),
390 [4] = DBL_MIN*(1 + 3*DBL_EPSILON),
391 #endif
392 };
393
394 check(x, __arraycount(x));
395 }
396
397 ATF_TC(next_near_sub_normal);
398 ATF_TC_HEAD(next_near_sub_normal, tc)
399 {
400 atf_tc_set_md_var(tc, "descr",
401 "nextafter/nexttoward near the subnormal/normal boundary");
402 }
403 ATF_TC_BODY(next_near_sub_normal, tc)
404 {
405 #ifdef __DBL_HAS_DENORM__
406 static const double x[] = {
407 [0] = DBL_MIN - 3*__DBL_DENORM_MIN__,
408 [1] = DBL_MIN - 2*__DBL_DENORM_MIN__,
409 [2] = DBL_MIN - __DBL_DENORM_MIN__,
410 [3] = DBL_MIN,
411 [4] = DBL_MIN + __DBL_DENORM_MIN__,
412 [5] = DBL_MIN + 2*__DBL_DENORM_MIN__,
413 [6] = DBL_MIN + 3*__DBL_DENORM_MIN__,
414 };
415
416 check(x, __arraycount(x));
417 #else /* !__DBL_HAS_DENORM__ */
418 atf_tc_skip("no subnormals on this architecture");
419 #endif /* !__DBL_HAS_DENORM__ */
420 }
421
422 ATF_TC(next_near_1);
423 ATF_TC_HEAD(next_near_1, tc)
424 {
425 atf_tc_set_md_var(tc, "descr", "nextafter/nexttoward near 1");
426 }
427 ATF_TC_BODY(next_near_1, tc)
428 {
429 static const double x[] = {
430 [0] = 1 - 3*DBL_EPSILON/2,
431 [1] = 1 - 2*DBL_EPSILON/2,
432 [2] = 1 - DBL_EPSILON/2,
433 [3] = 1,
434 [4] = 1 + DBL_EPSILON,
435 [5] = 1 + 2*DBL_EPSILON,
436 [6] = 1 + 3*DBL_EPSILON,
437 };
438
439 check(x, __arraycount(x));
440 }
441
442 ATF_TC(next_near_1_5);
443 ATF_TC_HEAD(next_near_1_5, tc)
444 {
445 atf_tc_set_md_var(tc, "descr", "nextafter/nexttoward near 1.5");
446 }
447 ATF_TC_BODY(next_near_1_5, tc)
448 {
449 static const double x[] = {
450 [0] = 1.5 - 3*DBL_EPSILON,
451 [1] = 1.5 - 2*DBL_EPSILON,
452 [2] = 1.5 - DBL_EPSILON,
453 [3] = 1.5,
454 [4] = 1.5 + DBL_EPSILON,
455 [5] = 1.5 + 2*DBL_EPSILON,
456 [6] = 1.5 + 3*DBL_EPSILON,
457 };
458
459 check(x, __arraycount(x));
460 }
461
462 ATF_TC(next_near_infinity);
463 ATF_TC_HEAD(next_near_infinity, tc)
464 {
465 atf_tc_set_md_var(tc, "descr", "nextafter/nexttoward near infinity");
466 }
467 ATF_TC_BODY(next_near_infinity, tc)
468 {
469 static const double x[] = {
470 [0] = DBL_MAX,
471 [1] = INFINITY,
472 };
473 volatile double t;
474
475 if (!isinf(INFINITY))
476 atf_tc_skip("no infinities on this architecture");
477
478 check(x, __arraycount(x));
479
480 ATF_CHECK_EQ_MSG((t = nextafter(INFINITY, INFINITY)), INFINITY,
481 "t=%a=%g", t, t);
482 ATF_CHECK_EQ_MSG((t = nextafter(-INFINITY, -INFINITY)), -INFINITY,
483 "t=%a=%g", t, t);
484 }
485
486 ATF_TC(nextf_nan);
487 ATF_TC_HEAD(nextf_nan, tc)
488 {
489 atf_tc_set_md_var(tc, "descr", "nextafterf/nexttowardf on NaN");
490 }
491 ATF_TC_BODY(nextf_nan, tc)
492 {
493 #ifdef NAN
494 /* XXX verify the NaN is quiet */
495 ATF_CHECK(isnan(nextafterf(NAN, 0)));
496 ATF_CHECK(isnan(nexttowardf(NAN, 0)));
497 ATF_CHECK(isnan(nextafterf(0, NAN)));
498 ATF_CHECK(isnan(nexttowardf(0, NAN)));
499 #else
500 atf_tc_skip("no NaNs on this architecture");
501 #endif
502 }
503
504 ATF_TC(nextf_signed_0);
505 ATF_TC_HEAD(nextf_signed_0, tc)
506 {
507 atf_tc_set_md_var(tc, "descr", "nextafterf/nexttowardf on signed 0");
508 }
509 ATF_TC_BODY(nextf_signed_0, tc)
510 {
511 volatile float z_pos = +0.;
512 volatile float z_neg = -0.;
513 #ifdef __FLT_HAS_DENORM__
514 volatile float m = __FLT_DENORM_MIN__;
515 #else
516 volatile float m = FLT_MIN;
517 #endif
518
519 if (signbit(z_pos) == signbit(z_neg))
520 atf_tc_skip("no signed zeroes on this architecture");
521
522 /*
523 * `nextUp(x) is the least floating-point number in the format
524 * of x that compares greater than x. [...] nextDown(x) is
525 * -nextUp(-x).'
526 * --IEEE 754-2019, 5.3.1 General operations, p. 19
527 *
528 * Verify that nextafterf and nexttowardf, which implement the
529 * nextUp and nextDown operations, obey this rule and don't
530 * send -0 to +0 or +0 to -0, respectively.
531 */
532
533 CHECK(0, nextafterf, z_neg, +INFINITY, m);
534 CHECK(1, nexttowardf, z_neg, +INFINITY, m);
535 CHECK(2, nextafterf, z_pos, +INFINITY, m);
536 CHECK(3, nexttowardf, z_pos, +INFINITY, m);
537
538 CHECK(4, nextafterf, z_pos, -INFINITY, -m);
539 CHECK(5, nexttowardf, z_pos, -INFINITY, -m);
540 CHECK(6, nextafterf, z_neg, -INFINITY, -m);
541 CHECK(7, nexttowardf, z_neg, -INFINITY, -m);
542
543 /*
544 * `If x is the negative number of least magnitude in x's
545 * format, nextUp(x) is -0.'
546 * --IEEE 754-2019, 5.3.1 General operations, p. 19
547 */
548 CHECK(8, nextafterf, -m, +INFINITY, 0);
549 CHECK(9, nexttowardf, -m, +INFINITY, 0);
550 ATF_CHECK(signbit(nextafterf(-m, +INFINITY)) != 0);
551 CHECK(10, nextafterf, m, -INFINITY, 0);
552 CHECK(11, nexttowardf, m, -INFINITY, 0);
553 ATF_CHECK(signbit(nextafterf(m, -INFINITY)) == 0);
554 }
555
556 ATF_TC(nextf_near_0);
557 ATF_TC_HEAD(nextf_near_0, tc)
558 {
559 atf_tc_set_md_var(tc, "descr", "nextafterf/nexttowardf near 0");
560 }
561 ATF_TC_BODY(nextf_near_0, tc)
562 {
563 static const float x[] = {
564 [0] = 0,
565 #ifdef __FLT_HAS_DENORM__
566 [1] = __FLT_DENORM_MIN__,
567 [2] = 2*__FLT_DENORM_MIN__,
568 [3] = 3*__FLT_DENORM_MIN__,
569 [4] = 4*__FLT_DENORM_MIN__,
570 #else
571 [1] = FLT_MIN,
572 [2] = FLT_MIN*(1 + FLT_EPSILON),
573 [3] = FLT_MIN*(1 + 2*FLT_EPSILON),
574 [4] = FLT_MIN*(1 + 3*FLT_EPSILON),
575 #endif
576 };
577
578 checkf(x, __arraycount(x));
579 }
580
581 ATF_TC(nextf_near_sub_normal);
582 ATF_TC_HEAD(nextf_near_sub_normal, tc)
583 {
584 atf_tc_set_md_var(tc, "descr",
585 "nextafterf/nexttowardf near the subnormal/normal boundary");
586 }
587 ATF_TC_BODY(nextf_near_sub_normal, tc)
588 {
589 #ifdef __FLT_HAS_DENORM__
590 static const float x[] = {
591 [0] = FLT_MIN - 3*__FLT_DENORM_MIN__,
592 [1] = FLT_MIN - 2*__FLT_DENORM_MIN__,
593 [2] = FLT_MIN - __FLT_DENORM_MIN__,
594 [3] = FLT_MIN,
595 [4] = FLT_MIN + __FLT_DENORM_MIN__,
596 [5] = FLT_MIN + 2*__FLT_DENORM_MIN__,
597 [6] = FLT_MIN + 3*__FLT_DENORM_MIN__,
598 };
599
600 checkf(x, __arraycount(x));
601 #else /* !__FLT_HAS_DENORM__ */
602 atf_tc_skip("no subnormals on this architecture");
603 #endif /* !__FLT_HAS_DENORM__ */
604 }
605
606 ATF_TC(nextf_near_1);
607 ATF_TC_HEAD(nextf_near_1, tc)
608 {
609 atf_tc_set_md_var(tc, "descr", "nextafterf/nexttowardf near 1");
610 }
611 ATF_TC_BODY(nextf_near_1, tc)
612 {
613 static const float x[] = {
614 [0] = 1 - 3*FLT_EPSILON/2,
615 [1] = 1 - 2*FLT_EPSILON/2,
616 [2] = 1 - FLT_EPSILON/2,
617 [3] = 1,
618 [4] = 1 + FLT_EPSILON,
619 [5] = 1 + 2*FLT_EPSILON,
620 [6] = 1 + 3*FLT_EPSILON,
621 };
622
623 checkf(x, __arraycount(x));
624 }
625
626 ATF_TC(nextf_near_1_5);
627 ATF_TC_HEAD(nextf_near_1_5, tc)
628 {
629 atf_tc_set_md_var(tc, "descr", "nextafterf/nexttowardf near 1.5");
630 }
631 ATF_TC_BODY(nextf_near_1_5, tc)
632 {
633 static const float x[] = {
634 [0] = 1.5 - 3*FLT_EPSILON,
635 [1] = 1.5 - 2*FLT_EPSILON,
636 [2] = 1.5 - FLT_EPSILON,
637 [3] = 1.5,
638 [4] = 1.5 + FLT_EPSILON,
639 [5] = 1.5 + 2*FLT_EPSILON,
640 [6] = 1.5 + 3*FLT_EPSILON,
641 };
642
643 checkf(x, __arraycount(x));
644 }
645
646 ATF_TC(nextf_near_infinity);
647 ATF_TC_HEAD(nextf_near_infinity, tc)
648 {
649 atf_tc_set_md_var(tc, "descr", "nextafterf/nexttowardf near infinity");
650 }
651 ATF_TC_BODY(nextf_near_infinity, tc)
652 {
653 static const float x[] = {
654 [0] = FLT_MAX,
655 [1] = INFINITY,
656 };
657 volatile float t;
658
659 if (!isinf(INFINITY))
660 atf_tc_skip("no infinities on this architecture");
661
662 checkf(x, __arraycount(x));
663
664 ATF_CHECK_EQ_MSG((t = nextafterf(INFINITY, INFINITY)), INFINITY,
665 "t=%a=%g", t, t);
666 ATF_CHECK_EQ_MSG((t = nextafterf(-INFINITY, -INFINITY)), -INFINITY,
667 "t=%a=%g", t, t);
668 }
669
670 ATF_TC(nextl_nan);
671 ATF_TC_HEAD(nextl_nan, tc)
672 {
673 atf_tc_set_md_var(tc, "descr", "nextafterl/nexttowardl on NaN");
674 }
675 ATF_TC_BODY(nextl_nan, tc)
676 {
677 #ifdef NAN
678 /* XXX verify the NaN is quiet */
679 ATF_CHECK(isnan(nextafterl(NAN, 0)));
680 ATF_CHECK(isnan(nexttowardl(NAN, 0)));
681 ATF_CHECK(isnan(nextafterl(0, NAN)));
682 ATF_CHECK(isnan(nexttowardl(0, NAN)));
683 #else
684 atf_tc_skip("no NaNs on this architecture");
685 #endif
686 }
687
688 ATF_TC(nextl_signed_0);
689 ATF_TC_HEAD(nextl_signed_0, tc)
690 {
691 atf_tc_set_md_var(tc, "descr", "nextafterl/nexttowardl on signed 0");
692 }
693 ATF_TC_BODY(nextl_signed_0, tc)
694 {
695 volatile long double z_pos = +0.;
696 volatile long double z_neg = -0.;
697 #ifdef __LDBL_HAS_DENORM__
698 volatile long double m = __LDBL_DENORM_MIN__;
699 #else
700 volatile long double m = LDBL_MIN;
701 #endif
702
703 if (signbit(z_pos) == signbit(z_neg))
704 atf_tc_skip("no signed zeroes on this architecture");
705
706 /*
707 * `nextUp(x) is the least floating-point number in the format
708 * of x that compares greater than x. [...] nextDown(x) is
709 * -nextUp(-x).'
710 * --IEEE 754-2019, 5.3.1 General operations, p. 19
711 *
712 * Verify that nextafterl and nexttowardl, which implement the
713 * nextUp and nextDown operations, obey this rule and don't
714 * send -0 to +0 or +0 to -0, respectively.
715 */
716
717 CHECK(0, nextafterl, z_neg, +INFINITY, m);
718 CHECK(1, nexttowardl, z_neg, +INFINITY, m);
719 CHECK(2, nextafterl, z_pos, +INFINITY, m);
720 CHECK(3, nexttowardl, z_pos, +INFINITY, m);
721
722 CHECK(4, nextafterl, z_pos, -INFINITY, -m);
723 CHECK(5, nexttowardl, z_pos, -INFINITY, -m);
724 CHECK(6, nextafterl, z_neg, -INFINITY, -m);
725 CHECK(7, nexttowardl, z_neg, -INFINITY, -m);
726
727 /*
728 * `If x is the negative number of least magnitude in x's
729 * format, nextUp(x) is -0.'
730 * --IEEE 754-2019, 5.3.1 General operations, p. 19
731 */
732 CHECK(8, nextafterl, -m, +INFINITY, 0);
733 CHECK(9, nexttowardl, -m, +INFINITY, 0);
734 ATF_CHECK(signbit(nextafterl(-m, +INFINITY)) != 0);
735 CHECK(10, nextafterl, m, -INFINITY, 0);
736 CHECK(11, nexttowardl, m, -INFINITY, 0);
737 ATF_CHECK(signbit(nextafterl(m, -INFINITY)) == 0);
738 }
739
740 ATF_TC(nextl_near_0);
741 ATF_TC_HEAD(nextl_near_0, tc)
742 {
743 atf_tc_set_md_var(tc, "descr", "nextafterl/nexttowardl near 0");
744 }
745 ATF_TC_BODY(nextl_near_0, tc)
746 {
747 static const long double x[] = {
748 [0] = 0,
749 #ifdef __LDBL_HAS_DENORM__
750 [1] = __LDBL_DENORM_MIN__,
751 [2] = 2*__LDBL_DENORM_MIN__,
752 [3] = 3*__LDBL_DENORM_MIN__,
753 [4] = 4*__LDBL_DENORM_MIN__,
754 #else
755 [1] = LDBL_MIN,
756 [2] = LDBL_MIN*(1 + LDBL_EPSILON),
757 [3] = LDBL_MIN*(1 + 2*LDBL_EPSILON),
758 [4] = LDBL_MIN*(1 + 3*LDBL_EPSILON),
759 #endif
760 };
761
762 checkl(x, __arraycount(x));
763 }
764
765 ATF_TC(nextl_near_sub_normal);
766 ATF_TC_HEAD(nextl_near_sub_normal, tc)
767 {
768 atf_tc_set_md_var(tc, "descr",
769 "nextafterl/nexttowardl near the subnormal/normal boundary");
770 }
771 ATF_TC_BODY(nextl_near_sub_normal, tc)
772 {
773 #ifdef __LDBL_HAS_DENORM__
774 static const long double x[] = {
775 [0] = LDBL_MIN - 3*__LDBL_DENORM_MIN__,
776 [1] = LDBL_MIN - 2*__LDBL_DENORM_MIN__,
777 [2] = LDBL_MIN - __LDBL_DENORM_MIN__,
778 [3] = LDBL_MIN,
779 [4] = LDBL_MIN + __LDBL_DENORM_MIN__,
780 [5] = LDBL_MIN + 2*__LDBL_DENORM_MIN__,
781 [6] = LDBL_MIN + 3*__LDBL_DENORM_MIN__,
782 };
783
784 checkl(x, __arraycount(x));
785 #else /* !__LDBL_HAS_DENORM__ */
786 atf_tc_skip("no subnormals on this architecture");
787 #endif /* !__LDBL_HAS_DENORM__ */
788 }
789
790 ATF_TC(nextl_near_1);
791 ATF_TC_HEAD(nextl_near_1, tc)
792 {
793 atf_tc_set_md_var(tc, "descr", "nextafterl/nexttowardl near 1");
794 }
795 ATF_TC_BODY(nextl_near_1, tc)
796 {
797 static const long double x[] = {
798 [0] = 1 - 3*LDBL_EPSILON/2,
799 [1] = 1 - 2*LDBL_EPSILON/2,
800 [2] = 1 - LDBL_EPSILON/2,
801 [3] = 1,
802 [4] = 1 + LDBL_EPSILON,
803 [5] = 1 + 2*LDBL_EPSILON,
804 [6] = 1 + 3*LDBL_EPSILON,
805 };
806
807 checkl(x, __arraycount(x));
808 }
809
810 ATF_TC(nextl_near_1_5);
811 ATF_TC_HEAD(nextl_near_1_5, tc)
812 {
813 atf_tc_set_md_var(tc, "descr", "nextafterl/nexttowardl near 1.5");
814 }
815 ATF_TC_BODY(nextl_near_1_5, tc)
816 {
817 static const long double x[] = {
818 [0] = 1.5 - 3*LDBL_EPSILON,
819 [1] = 1.5 - 2*LDBL_EPSILON,
820 [2] = 1.5 - LDBL_EPSILON,
821 [3] = 1.5,
822 [4] = 1.5 + LDBL_EPSILON,
823 [5] = 1.5 + 2*LDBL_EPSILON,
824 [6] = 1.5 + 3*LDBL_EPSILON,
825 };
826
827 checkl(x, __arraycount(x));
828 }
829
830 ATF_TC(nextl_near_infinity);
831 ATF_TC_HEAD(nextl_near_infinity, tc)
832 {
833 atf_tc_set_md_var(tc, "descr", "nextafterl/nexttowardl near infinity");
834 }
835 ATF_TC_BODY(nextl_near_infinity, tc)
836 {
837 static const long double x[] = {
838 [0] = LDBL_MAX,
839 [1] = INFINITY,
840 };
841 volatile long double t;
842
843 if (!isinf(INFINITY))
844 atf_tc_skip("no infinities on this architecture");
845
846 checkl(x, __arraycount(x));
847
848 ATF_CHECK_EQ_MSG((t = nextafterl(INFINITY, INFINITY)), INFINITY,
849 "t=%La=%Lg", t, t);
850 ATF_CHECK_EQ_MSG((t = nextafterl(-INFINITY, -INFINITY)), -INFINITY,
851 "t=%La=%Lg", t, t);
852 }
853
854 #endif /* __vax__ */
855
856 ATF_TP_ADD_TCS(tp)
857 {
858
859 #ifdef __vax__
860 ATF_TP_ADD_TC(tp, vaxafter);
861 #else
862 ATF_TP_ADD_TC(tp, next_nan);
863 ATF_TP_ADD_TC(tp, next_near_0);
864 ATF_TP_ADD_TC(tp, next_near_1);
865 ATF_TP_ADD_TC(tp, next_near_1_5);
866 ATF_TP_ADD_TC(tp, next_near_infinity);
867 ATF_TP_ADD_TC(tp, next_near_sub_normal);
868 ATF_TP_ADD_TC(tp, next_signed_0);
869 ATF_TP_ADD_TC(tp, nextf_nan);
870 ATF_TP_ADD_TC(tp, nextf_near_0);
871 ATF_TP_ADD_TC(tp, nextf_near_1);
872 ATF_TP_ADD_TC(tp, nextf_near_1_5);
873 ATF_TP_ADD_TC(tp, nextf_near_infinity);
874 ATF_TP_ADD_TC(tp, nextf_near_sub_normal);
875 ATF_TP_ADD_TC(tp, nextf_signed_0);
876 ATF_TP_ADD_TC(tp, nextl_nan);
877 ATF_TP_ADD_TC(tp, nextl_near_0);
878 ATF_TP_ADD_TC(tp, nextl_near_1);
879 ATF_TP_ADD_TC(tp, nextl_near_1_5);
880 ATF_TP_ADD_TC(tp, nextl_near_infinity);
881 ATF_TP_ADD_TC(tp, nextl_near_sub_normal);
882 ATF_TP_ADD_TC(tp, nextl_signed_0);
883 #endif
884 return atf_no_error();
885 }
886