From: Wilco Dijkstra Date: Fri, 23 Jan 2026 13:02:14 +0000 (-0300) Subject: math: Add __issignaling inline X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=570fc094c3d159c31cafaf0f6275a6c1c063ceea;p=thirdparty%2Fglibc.git math: Add __issignaling inline Add __issignaling inline based on the issignaling_inline implementation. Improve the __issignalingf inline. Remove issignaling(f)_inline and its uses. Reviewed-by: Adhemerval Zanella Co-authored-by: Adhemerval Zanella --- diff --git a/include/math.h b/include/math.h index 2565a4723a..b197333e95 100644 --- a/include/math.h +++ b/include/math.h @@ -62,32 +62,21 @@ libm_hidden_proto (__expm1f128) #include #include -/* A union which permits us to convert between a float and a 32 bit - int. */ - -typedef union -{ - float value; - uint32_t word; -} ieee_float_shape_type; - /* Get a 32 bit int from a float. */ #ifndef GET_FLOAT_WORD -# define GET_FLOAT_WORD(i,d) \ +# define GET_FLOAT_WORD(__i, __d) \ do { \ - ieee_float_shape_type gf_u; \ - gf_u.value = (d); \ - (i) = gf_u.word; \ + union { float f; uint32_t i; } u = { .f = (__d) }; \ + (__i) = u.i; \ } while (0) #endif /* Set a float from a 32 bit int. */ #ifndef SET_FLOAT_WORD -# define SET_FLOAT_WORD(d,i) \ +# define SET_FLOAT_WORD(__d, __i) \ do { \ - ieee_float_shape_type sf_u; \ - sf_u.word = (i); \ - (d) = sf_u.value; \ + union { float f; uint32_t i; } u = { .i = (__i) }; \ + (__d) = u.f; \ } while (0) #endif @@ -96,20 +85,39 @@ __issignalingf (float x) { uint32_t xi; GET_FLOAT_WORD (xi, x); -#if HIGH_ORDER_BIT_IS_SET_FOR_SNAN + /* We only have to care about the high-order bit of x's significand, because having it set (sNaN) already makes the significand different from that used to designate infinity. */ - return (xi & 0x7fc00000) == 0x7fc00000; -#else - /* To keep the following comparison simple, toggle the quiet/signaling bit, - so that it is set for sNaNs. This is inverse to IEEE 754-2008 (as well as - common practice for IEEE 754-1985). */ - xi ^= 0x00400000; - /* We have to compare for greater (instead of greater or equal), because x's - significand being all-zero designates infinity not NaN. */ - return (xi & 0x7fffffff) > 0x7fc00000; -#endif + if (HIGH_ORDER_BIT_IS_SET_FOR_SNAN) + return (xi & 0x7fc00000) == 0x7fc00000; + + /* IEEE 754-2008 is_quiet flag is zero for signaling NaN. To simplify the + comparison logic, first toggle the flag, so that it is set for a sNaN. + We shift out the sign bit and compare for greater than because xi's + significand being all-zero means infinity, not sNaN. */ + return 2 * (xi ^ 0x00400000) > 2 * 0x7fc00000U; +} + +extern inline int +__issignaling (double x) +{ + union { double f; uint64_t i; } u = { .f = x }; + uint64_t xi = u.i; + + /* We only have to care about the high-order bit of x's significand, because + having it set (sNaN) already makes the significand different from that + used to designate infinity. */ + if (HIGH_ORDER_BIT_IS_SET_FOR_SNAN) + return (xi & UINT64_C (0x7ff8000000000000)) + == UINT64_C (0x7ff8000000000000); + + /* IEEE 754-2008 is_quiet flag is zero for signaling NaN. To simplify the + comparison logic, first toggle the flag, so that it is set for a sNaN. + We shift out the sign bit and compare for greater than because xi's + significand being all-zero means infinity, not sNaN. */ + return 2 * (xi ^ UINT64_C (0x0008000000000000)) + > UINT64_C (0xfff0000000000000); } # if __HAVE_DISTINCT_FLOAT128 diff --git a/sysdeps/aarch64/fpu/finite_pow.h b/sysdeps/aarch64/fpu/finite_pow.h index 8a6a229cb4..44aaa1c4ad 100644 --- a/sysdeps/aarch64/fpu/finite_pow.h +++ b/sysdeps/aarch64/fpu/finite_pow.h @@ -269,9 +269,9 @@ pow_scalar_special_case (double x, double y) if (__glibc_unlikely (zeroinfnan (iy))) { if (2 * iy == 0) - return issignaling_inline (x) ? x + y : 1.0; + return issignaling (x) ? x + y : 1.0; if (ix == asuint64 (1.0)) - return issignaling_inline (y) ? x + y : 1.0; + return issignaling (y) ? x + y : 1.0; if (2 * ix > 2 * asuint64 (INFINITY) || 2 * iy > 2 * asuint64 (INFINITY)) return x + y; diff --git a/sysdeps/aarch64/fpu/pow_sve.c b/sysdeps/aarch64/fpu/pow_sve.c index d1ceab5a1c..19062b5375 100644 --- a/sysdeps/aarch64/fpu/pow_sve.c +++ b/sysdeps/aarch64/fpu/pow_sve.c @@ -341,9 +341,9 @@ pow_specialcase (double x, double y) if (__glibc_unlikely (zeroinfnan (iy))) { if (2 * iy == 0) - return issignaling_inline (x) ? x + y : 1.0; + return issignaling (x) ? x + y : 1.0; if (ix == asuint64 (1.0)) - return issignaling_inline (y) ? x + y : 1.0; + return issignaling (y) ? x + y : 1.0; if (2 * ix > 2 * asuint64 (INFINITY) || 2 * iy > 2 * asuint64 (INFINITY)) return x + y; if (2 * ix == 2 * asuint64 (1.0)) diff --git a/sysdeps/aarch64/fpu/powf_sve.c b/sysdeps/aarch64/fpu/powf_sve.c index 25cd8cd15e..46b006c845 100644 --- a/sysdeps/aarch64/fpu/powf_sve.c +++ b/sysdeps/aarch64/fpu/powf_sve.c @@ -123,9 +123,9 @@ powf_specialcase (float x, float y) if (__glibc_unlikely (zeroinfnan (iy))) { if (2 * iy == 0) - return issignalingf_inline (x) ? x + y : 1.0f; + return issignaling (x) ? x + y : 1.0f; if (ix == 0x3f800000) - return issignalingf_inline (y) ? x + y : 1.0f; + return issignaling (y) ? x + y : 1.0f; if (2 * ix > 2u * 0x7f800000 || 2 * iy > 2u * 0x7f800000) return x + y; if (2 * ix == 2 * 0x3f800000) diff --git a/sysdeps/ieee754/dbl-64/e_hypot.c b/sysdeps/ieee754/dbl-64/e_hypot.c index b901ee1ef1..c99f40310b 100644 --- a/sysdeps/ieee754/dbl-64/e_hypot.c +++ b/sysdeps/ieee754/dbl-64/e_hypot.c @@ -98,7 +98,7 @@ __hypot (double x, double y) if (!isfinite(x) || !isfinite(y)) { if ((isinf (x) || isinf (y)) - && !issignaling_inline (x) && !issignaling_inline (y)) + && !issignaling (x) && !issignaling (y)) return INFINITY; return x + y; } diff --git a/sysdeps/ieee754/dbl-64/e_pow.c b/sysdeps/ieee754/dbl-64/e_pow.c index 3ff41922d8..56c393e917 100644 --- a/sysdeps/ieee754/dbl-64/e_pow.c +++ b/sysdeps/ieee754/dbl-64/e_pow.c @@ -303,9 +303,9 @@ __pow (double x, double y) if (__glibc_unlikely (zeroinfnan (iy))) { if (2 * iy == 0) - return issignaling_inline (x) ? x + y : 1.0; + return issignaling (x) ? x + y : 1.0; if (ix == asuint64 (1.0)) - return issignaling_inline (y) ? x + y : 1.0; + return issignaling (y) ? x + y : 1.0; if (2 * ix > 2 * asuint64 (INFINITY) || 2 * iy > 2 * asuint64 (INFINITY)) return x + y; diff --git a/sysdeps/ieee754/dbl-64/math_config.h b/sysdeps/ieee754/dbl-64/math_config.h index 5158d4cdb7..dd0a4494e3 100644 --- a/sysdeps/ieee754/dbl-64/math_config.h +++ b/sysdeps/ieee754/dbl-64/math_config.h @@ -125,15 +125,6 @@ asdouble (uint64_t i) return u.f; } -static inline int -issignaling_inline (double x) -{ - uint64_t ix = asuint64 (x); - if (HIGH_ORDER_BIT_IS_SET_FOR_SNAN) - return (ix & 0x7ff8000000000000) == 0x7ff8000000000000; - return 2 * (ix ^ 0x0008000000000000) > 2 * 0x7ff8000000000000ULL; -} - #define BIT_WIDTH 64 #define MANTISSA_WIDTH 52 #define EXPONENT_WIDTH 11 diff --git a/sysdeps/ieee754/flt-32/math_config.h b/sysdeps/ieee754/flt-32/math_config.h index 27eaf50191..1509c2ef62 100644 --- a/sysdeps/ieee754/flt-32/math_config.h +++ b/sysdeps/ieee754/flt-32/math_config.h @@ -154,15 +154,6 @@ asdouble (uint64_t i) return u.f; } -static inline int -issignalingf_inline (float x) -{ - uint32_t ix = asuint (x); - if (HIGH_ORDER_BIT_IS_SET_FOR_SNAN) - return (ix & 0x7fc00000) == 0x7fc00000; - return 2 * (ix ^ 0x00400000) > 2 * 0x7fc00000UL; -} - #define BIT_WIDTH 32 #define MANTISSA_WIDTH 23 #define EXPONENT_WIDTH 8