mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-08 23:58:31 +08:00
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:
committed by
Adhemerval Zanella
co-authored by
Adhemerval Zanella
parent
1dd9951d85
commit
570fc094c3
+36
-28
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user