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  <adhemerval.zanella@linaro.org>
Co-authored-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
This commit is contained in:
Wilco Dijkstra
2026-02-02 14:34:18 -03:00
committed by Adhemerval Zanella
co-authored by Adhemerval Zanella
parent 1dd9951d85
commit 570fc094c3
8 changed files with 45 additions and 55 deletions
+36 -28
View File
@@ -62,32 +62,21 @@ libm_hidden_proto (__expm1f128)
#include <stdint.h>
#include <nan-high-order-bit.h>
/* 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
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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))
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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;
}
+2 -2
View File
@@ -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;
-9
View File
@@ -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
-9
View File
@@ -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