| /* PR libstdc++/85466 */ |
| /* { dg-do run } */ |
| /* { dg-options "-O2 -fno-math-errno -fno-trapping-math -fdump-tree-optimized" } */ |
| /* { dg-add-options ieee } */ |
| /* { dg-skip-if "not IEEE float" { "pdp11-*-*" } } */ |
| /* { dg-final { scan-tree-dump-not "nextafter" "optimized" } } */ |
| /* { dg-final { scan-tree-dump-not "nexttoward" "optimized" } } */ |
| |
| #ifndef _NEXT_AFTER_2 |
| float nextafterf (float, float); |
| double nextafter (double, double); |
| long double nextafterl (long double, long double); |
| float nexttowardf (float, long double); |
| double nexttoward (double, long double); |
| long double nexttowardl (long double, long double); |
| #endif |
| |
| #define CHECK(x) if (!(x)) __builtin_abort () |
| |
| #ifndef NEED_ERRNO |
| #define NEED_ERRNO 0 |
| #endif |
| #ifndef NEED_EXC |
| #define NEED_EXC 0 |
| #endif |
| #ifndef NO_LONG_DOUBLE |
| #define NO_LONG_DOUBLE (__LDBL_MANT_DIG__ == 106) |
| #endif |
| |
| #define TEST(name, fn, type, L1, L2, l1, l2, MIN1, \ |
| MAX1, DENORM_MIN1, EPSILON1, MIN2, MAX2, DENORM_MIN2) \ |
| void \ |
| name (void) \ |
| { \ |
| const type a = fn (0.0##L1, 0.0##L2); \ |
| CHECK (a == 0.0##L1 && !__builtin_signbit (a)); \ |
| const type b = fn (0.0##L1, -0.0##L2); \ |
| CHECK (b == 0.0##L1 && __builtin_signbit (b)); \ |
| const type c = fn (__builtin_nan##l1 (""), 0.0##L2); \ |
| CHECK (__builtin_isnan##l1 (c)); \ |
| const type d = fn (2.0##L1, __builtin_nan##l2 ("")); \ |
| CHECK (__builtin_isnan##l1 (d)); \ |
| const type e = NEED_EXC ? DENORM_MIN1 : fn (0.0##L1, 8.0##L2); \ |
| CHECK (e == DENORM_MIN1); \ |
| const type f = fn (1.0##L1, 8.0##L2); \ |
| CHECK (f == 1.0##L1 + EPSILON1); \ |
| const type g = fn (1.0##L1, -8.0##L2); \ |
| CHECK (g == 1.0##L1 - EPSILON1 / 2.0##L1); \ |
| const type h = fn (__builtin_inf (), 0.0##L2); \ |
| CHECK (h == MAX1); \ |
| const type i = fn (-1.0##L1, -__builtin_inf ()); \ |
| CHECK (i == -1.0##L1 - EPSILON1); \ |
| const type j = fn (1.5##L1, __builtin_inf ()); \ |
| CHECK (j == 1.5##L1 + EPSILON1); \ |
| const type k = fn (1.5##L1 - EPSILON1, 100.0##L2); \ |
| CHECK (k == 1.5##L1); \ |
| const type l \ |
| = (NEED_EXC || NEED_ERRNO) ? 0.0##L1 : fn (DENORM_MIN1, 0.0##L2); \ |
| CHECK (l == 0.0##L1 && !__builtin_signbit (l)); \ |
| const type m \ |
| = (NEED_EXC || NEED_ERRNO) ? __builtin_inf##l1 () \ |
| : fn (MAX1, __builtin_inf ()); \ |
| CHECK (__builtin_isinf##l1 (m) && !__builtin_signbit (m)); \ |
| const type n \ |
| = (NEED_EXC || NEED_ERRNO) ? 2.0##L1 * DENORM_MIN1 \ |
| : fn (DENORM_MIN1, 12.0##L2); \ |
| CHECK (n == 2.0##L1 * DENORM_MIN1); \ |
| const type o \ |
| = (NEED_EXC || NEED_ERRNO) ? 3.0##L1 * DENORM_MIN1 \ |
| : fn (n, 24.0##L2); \ |
| CHECK (o == 3.0##L1 * DENORM_MIN1); \ |
| const type p \ |
| = (NEED_EXC || NEED_ERRNO) ? 4.0##L1 * DENORM_MIN1 \ |
| : fn (o, 132.0##L2); \ |
| CHECK (p == 4.0##L1 * DENORM_MIN1); \ |
| const type q \ |
| = (NEED_EXC || NEED_ERRNO) ? DENORM_MIN1 \ |
| : fn (2.0##L1 * DENORM_MIN1, -__builtin_inf ()); \ |
| CHECK (q == DENORM_MIN1); \ |
| const type r \ |
| = (NEED_EXC || NEED_ERRNO) ? 2.0##L1 * DENORM_MIN1 \ |
| : fn (3.0##L1 * DENORM_MIN1, DENORM_MIN2); \ |
| CHECK (r == 2.0##L1 * DENORM_MIN1); \ |
| const type s \ |
| = (NEED_EXC || NEED_ERRNO) ? 3.0##L1 * DENORM_MIN1 \ |
| : fn (4.0##L1 * DENORM_MIN1, 2.0##L2 * DENORM_MIN2); \ |
| CHECK (s == 3.0##L1 * DENORM_MIN1); \ |
| const type t \ |
| = (NEED_EXC || NEED_ERRNO) ? MIN1 - DENORM_MIN1 \ |
| : fn (MIN1, 0.0##L2); \ |
| CHECK (t == MIN1 - DENORM_MIN1); \ |
| const type u \ |
| = (NEED_EXC || NEED_ERRNO) ? MIN1 - 2.0##L1 * DENORM_MIN1 \ |
| : fn (MIN1 - DENORM_MIN1, -MIN2); \ |
| CHECK (u == MIN1 - 2.0##L1 * DENORM_MIN1); \ |
| const type v \ |
| = (NEED_EXC || NEED_ERRNO) ? MIN1 - DENORM_MIN1 \ |
| : fn (MIN1 - 2.0##L1 * DENORM_MIN1, 100.0##L2); \ |
| CHECK (v == MIN1 - DENORM_MIN1); \ |
| const type w = fn (MIN1 - DENORM_MIN1, MAX2); \ |
| CHECK (w == MIN1); \ |
| const type x = fn (MIN1, 17.0##L2); \ |
| CHECK (x == MIN1 + DENORM_MIN1); \ |
| const type y = fn (MIN1 + DENORM_MIN1, __builtin_inf##l2 ()); \ |
| CHECK (y == MIN1 + 2.0##L1 * DENORM_MIN1); \ |
| const type z \ |
| = (NEED_EXC || NEED_ERRNO) ? MIN1 / 2.0##L1 - DENORM_MIN1 \ |
| : fn (MIN1 / 2.0##L1, -MIN2); \ |
| CHECK (z == MIN1 / 2.0##L1 - DENORM_MIN1); \ |
| const type aa \ |
| = (NEED_EXC || NEED_ERRNO) ? -MIN1 / 4.0##L1 + DENORM_MIN1 \ |
| : fn (-MIN1 / 4.0##L1, MIN2); \ |
| CHECK (aa == -MIN1 / 4.0##L1 + DENORM_MIN1); \ |
| const type ab = fn (MIN1 * 2.0##L1, -MIN2); \ |
| CHECK (ab == MIN1 * 2.0##L1 - DENORM_MIN1); \ |
| const type ac = fn (MIN1 * 4.0##L1, MIN2); \ |
| CHECK (ac == MIN1 * 4.0##L1 - DENORM_MIN1 * 2.0##L1); \ |
| const type ad = fn (MIN1 * 64.0##L1, MIN2); \ |
| CHECK (ad == MIN1 * 64.0##L1 - DENORM_MIN1 * 32.0##L1); \ |
| const type ae \ |
| = (NEED_EXC || NEED_ERRNO) ? MIN1 / 2.0##L1 \ |
| : fn (MIN1 / 2.0##L1 - DENORM_MIN1, 100.0##L2); \ |
| CHECK (ae == MIN1 / 2.0##L1); \ |
| const type af \ |
| = (NEED_EXC || NEED_ERRNO) ? -MIN1 / 4.0##L1 \ |
| : fn (-MIN1 / 4 + DENORM_MIN1, -100.0##L2); \ |
| CHECK (af == -MIN1 / 4.0##L1); \ |
| const type ag = fn (MIN1 * 2.0##L1 - DENORM_MIN1, 100.0##L2); \ |
| CHECK (ag == MIN1 * 2.0##L1); \ |
| const type ah = fn (MIN1 * 4.0##L1 - 2.0##L1 * DENORM_MIN1, 100.0##L2); \ |
| CHECK (ah == MIN1 * 4.0##L1); \ |
| const type ai = fn (MIN1 * 64.0##L1 - 32.0##L1 * DENORM_MIN1, 100.0##L2); \ |
| CHECK (ai == MIN1 * 64.0##L1); \ |
| const type aj = fn (MIN1 * 64.0##L1, 100.0##L2); \ |
| CHECK (aj == MIN1 * 64.0##L1 + 64.0##L1 * DENORM_MIN1); \ |
| const type ak = fn (MIN1 * 64.0##L1 + DENORM_MIN1 * 64.0##L1, 1024.0##L2); \ |
| CHECK (ak == MIN1 * 64.0##L1 + 128.0##L1 * DENORM_MIN1); \ |
| const type al = fn (128.0##L1, 128.0##L2); \ |
| CHECK (al == 128.0##L1); \ |
| const type am = fn (128.0##L1, 129.0##L2); \ |
| CHECK (am == 128.0##L1 + 128.0##L1 * EPSILON1); \ |
| const type an = fn (-128.0##L1 + -128.0##L1 * EPSILON1, -130.0##L2); \ |
| CHECK (an == -128.0##L1 - 256.0##L1 * EPSILON1); \ |
| const type ao = fn (128.0##L1 + 256.0##L1 * EPSILON1, 256.0##L2); \ |
| CHECK (ao == 128.0##L1 + 384.0##L1 * EPSILON1); \ |
| const type ap = fn (128.0##L1 + 384.0##L1 * EPSILON1, -0.0##L2); \ |
| CHECK (ap == 128.0##L1 + 256.0##L1 * EPSILON1); \ |
| const type aq = fn (128.0##L1 + 256.0##L1 * EPSILON1, 1.0##L2); \ |
| CHECK (aq == 128.0##L1 + 128.0##L1 * EPSILON1); \ |
| const type ar = fn (128.0##L1 + 128.0##L1 * EPSILON1, 0.0##L2); \ |
| CHECK (ar == 128.0##L1); \ |
| const type as = fn (128.0##L1, 0.0##L2); \ |
| CHECK (as == 128.0##L1 - 64.0##L1 * EPSILON1); \ |
| const type at = fn (128.0##L1 - 64.0##L1 * EPSILON1, 5.0##L2); \ |
| CHECK (at == 128.0##L1 - 128.0##L1 * EPSILON1); \ |
| } |
| |
| TEST (test1, nextafterf, float, F, F, f, f, __FLT_MIN__, __FLT_MAX__, |
| __FLT_DENORM_MIN__, __FLT_EPSILON__, __FLT_MIN__, __FLT_MAX__, |
| __FLT_DENORM_MIN__) |
| TEST (test2, nextafter, double, , , , , __DBL_MIN__, __DBL_MAX__, |
| __DBL_DENORM_MIN__, __DBL_EPSILON__, __DBL_MIN__, __DBL_MAX__, |
| __DBL_DENORM_MIN__) |
| #if !NO_LONG_DOUBLE |
| TEST (test3, nextafterl, long double, L, L, l, l, __LDBL_MIN__, __LDBL_MAX__, |
| __LDBL_DENORM_MIN__, __LDBL_EPSILON__, __LDBL_MIN__, __LDBL_MAX__, |
| __LDBL_DENORM_MIN__) |
| TEST (test4, nexttowardf, float, F, L, f, l, __FLT_MIN__, __FLT_MAX__, |
| __FLT_DENORM_MIN__, __FLT_EPSILON__, __LDBL_MIN__, __LDBL_MAX__, |
| __LDBL_DENORM_MIN__) |
| TEST (test5, nexttoward, double, , L, , l, __DBL_MIN__, __DBL_MAX__, |
| __DBL_DENORM_MIN__, __DBL_EPSILON__, __LDBL_MIN__, __LDBL_MAX__, |
| __LDBL_DENORM_MIN__) |
| TEST (test6, nexttowardl, long double, L, L, l, l, __LDBL_MIN__, __LDBL_MAX__, |
| __LDBL_DENORM_MIN__, __LDBL_EPSILON__, __LDBL_MIN__, __LDBL_MAX__, |
| __LDBL_DENORM_MIN__) |
| #endif |
| |
| int |
| main () |
| { |
| test1 (); |
| test2 (); |
| #if !NO_LONG_DOUBLE |
| test3 (); |
| test4 (); |
| test5 (); |
| test6 (); |
| #endif |
| return 0; |
| } |