From: Bruno Haible Date: Sat, 14 Oct 2023 18:38:49 +0000 (+0200) Subject: snan, signed-snan: Add API that works also on x86 and x86_64 CPUs. X-Git-Tag: v1.0~705 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=b2209aff82519af2275e353378fa1d7ffdca005e;p=gnulib.git snan, signed-snan: Add API that works also on x86 and x86_64 CPUs. * lib/snan.h (memory_float, memory_double, memory_long_double): New types. (construct_memory_SNaNf, memory_SNaNf, construct_memory_SNaNd, memory_SNaNd, construct_memory_SNaNl, memory_SNaNl): New functions. * lib/signed-snan.h (memory_positive_SNaNf, memory_negative_SNaNf, memory_positive_SNaNd, memory_negative_SNaNd, memory_positive_SNaNl, memory_negative_SNaNl): New functions. --- diff --git a/ChangeLog b/ChangeLog index 0fe658e2d3..78851b3b4a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2023-10-14 Bruno Haible + + snan, signed-snan: Add API that works also on x86 and x86_64 CPUs. + * lib/snan.h (memory_float, memory_double, memory_long_double): New + types. + (construct_memory_SNaNf, memory_SNaNf, construct_memory_SNaNd, + memory_SNaNd, construct_memory_SNaNl, memory_SNaNl): New functions. + * lib/signed-snan.h (memory_positive_SNaNf, memory_negative_SNaNf, + memory_positive_SNaNd, memory_negative_SNaNd, memory_positive_SNaNl, + memory_negative_SNaNl): New functions. + 2023-10-14 Bruno Haible snan tests: Fix "unused variable" warnings on i386. diff --git a/lib/signed-snan.h b/lib/signed-snan.h index f275467567..410ad71ce1 100644 --- a/lib/signed-snan.h +++ b/lib/signed-snan.h @@ -23,18 +23,38 @@ #if HAVE_SNANF +/* Returns a signalling 'float' NaN with sign bit == 0 in memory. */ +_GL_UNUSED static memory_float +memory_positive_SNaNf () +{ + return construct_memory_SNaNf (positive_NaNf ()); +} + +/* Returns a signalling 'float' NaN with sign bit == 1 in memory. */ +_GL_UNUSED static memory_float +memory_negative_SNaNf () +{ + return construct_memory_SNaNf (negative_NaNf ()); +} + +/* Note: On 32-bit x86 processors, as well as on x86_64 processors with + CC="gcc -mfpmath=387", the following functions may return a quiet NaN + instead. Use the functions with 'memory_' prefix if you need to avoid this. + See + for details. */ + /* Returns a signalling 'float' NaN with sign bit == 0. */ _GL_UNUSED static float positive_SNaNf () { - return construct_SNaNf (positive_NaNf ()); + return memory_positive_SNaNf ().value; } /* Returns a signalling 'float' NaN with sign bit == 1. */ _GL_UNUSED static float negative_SNaNf () { - return construct_SNaNf (negative_NaNf ()); + return memory_negative_SNaNf ().value; } #endif @@ -42,18 +62,38 @@ negative_SNaNf () #if HAVE_SNAND +/* Returns a signalling 'double' NaN with sign bit == 0 in memory. */ +_GL_UNUSED static memory_double +memory_positive_SNaNd () +{ + return construct_memory_SNaNd (positive_NaNd ()); +} + +/* Returns a signalling 'double' NaN with sign bit == 1 in memory. */ +_GL_UNUSED static memory_double +memory_negative_SNaNd () +{ + return construct_memory_SNaNd (negative_NaNd ()); +} + +/* Note: On 32-bit x86 processors, as well as on x86_64 processors with + CC="gcc -mfpmath=387", the following functions may return a quiet NaN + instead. Use the functions with 'memory_' prefix if you need to avoid this. + See + for details. */ + /* Returns a signalling 'double' NaN with sign bit == 0. */ _GL_UNUSED static double positive_SNaNd () { - return construct_SNaNd (positive_NaNd ()); + return memory_positive_SNaNd ().value; } /* Returns a signalling 'double' NaN with sign bit == 1. */ _GL_UNUSED static double negative_SNaNd () { - return construct_SNaNd (negative_NaNd ()); + return memory_negative_SNaNd ().value; } #endif @@ -61,18 +101,39 @@ negative_SNaNd () #if HAVE_SNANL +/* Returns a signalling 'long double' NaN with sign bit == 0 in memory. */ +_GL_UNUSED static memory_long_double +memory_positive_SNaNl () +{ + return construct_memory_SNaNl (positive_NaNl ()); +} + +/* Returns a signalling 'long double' NaN with sign bit == 1 in memory. */ +_GL_UNUSED static memory_long_double +memory_negative_SNaNl () +{ + return construct_memory_SNaNl (negative_NaNl ()); +} + +/* Note: On 32-bit x86 processors, as well as on x86_64 processors with + CC="gcc -mfpmath=387", if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE is 1, the + following functions may return a quiet NaN instead. Use the functions + with 'memory_' prefix if you need to avoid this. See + + for details. */ + /* Returns a signalling 'long double' NaN with sign bit == 0. */ _GL_UNUSED static long double positive_SNaNl () { - return construct_SNaNl (positive_NaNl ()); + return memory_positive_SNaNl ().value; } /* Returns a signalling 'long double' NaN with sign bit == 1. */ _GL_UNUSED static long double negative_SNaNl () { - return construct_SNaNl (negative_NaNl ()); + return memory_negative_SNaNl ().value; } #endif diff --git a/lib/snan.h b/lib/snan.h index a65b12e713..ebf88ab0c5 100644 --- a/lib/snan.h +++ b/lib/snan.h @@ -44,16 +44,17 @@ /* 'float' = IEEE 754 single-precision */ +#define NWORDS \ + ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) +typedef union { float value; unsigned int word[NWORDS]; } memory_float; + #if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT # define HAVE_SNANF 1 -_GL_UNUSED static float -construct_SNaNf (float quiet_value) +_GL_UNUSED static memory_float +construct_memory_SNaNf (float quiet_value) { - #define NWORDS \ - ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) - typedef union { float value; unsigned int word[NWORDS]; } memory_float; memory_float m; m.value = quiet_value; /* Turn the quiet NaN into a signalling NaN. */ @@ -68,33 +69,53 @@ construct_SNaNf (float quiet_value) m.word[FLT_EXPBIT0_WORD + 1] |= (unsigned int) 1 << FLT_EXPBIT0_BIT; else /* NWORDS == 1 or little endian */ m.word[0] |= (unsigned int) 1; - #undef NWORDS - return m.value; + return m; +} + +/* Returns a signalling 'float' NaN in memory. */ +_GL_UNUSED static memory_float +memory_SNaNf () +{ + return construct_memory_SNaNf (NaNf ()); +} + +_GL_UNUSED static float +construct_SNaNf (float quiet_value) +{ + return construct_memory_SNaNf (quiet_value).value; } -/* Returns a signalling 'float' NaN. */ +/* Returns a signalling 'float' NaN. + Note: On 32-bit x86 processors, as well as on x86_64 processors with + CC="gcc -mfpmath=387", this function may return a quiet NaN instead. + Use memory_SNaNf() if you need to avoid this. See + + for details. */ _GL_UNUSED static float SNaNf () { - return construct_SNaNf (NaNf ()); + return memory_SNaNf ().value; } #endif +#undef NWORDS + /* 'double' = IEEE 754 double-precision */ +#define NWORDS \ + ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) +typedef union { double value; unsigned int word[NWORDS]; } memory_double; + #if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT # define HAVE_SNAND 1 -_GL_UNUSED static double -construct_SNaNd (double quiet_value) +_GL_UNUSED static memory_double +construct_memory_SNaNd (double quiet_value) { - #define NWORDS \ - ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) - typedef union { double value; unsigned int word[NWORDS]; } memory_double; memory_double m; m.value = quiet_value; /* Turn the quiet NaN into a signalling NaN. */ @@ -107,19 +128,38 @@ construct_SNaNd (double quiet_value) /* Set some arbitrary mantissa bit. */ m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] |= (unsigned int) 1 << DBL_EXPBIT0_BIT; - #undef NWORDS - return m.value; + return m; +} + +/* Returns a signalling 'double' NaN in memory. */ +_GL_UNUSED static memory_double +memory_SNaNd () +{ + return construct_memory_SNaNd (NaNd ()); } -/* Returns a signalling 'double' NaN. */ +_GL_UNUSED static double +construct_SNaNd (double quiet_value) +{ + return construct_memory_SNaNd (quiet_value).value; +} + +/* Returns a signalling 'double' NaN. + Note: On 32-bit x86 processors, as well as on x86_64 processors with + CC="gcc -mfpmath=387", this function may return a quiet NaN instead. + Use memory_SNaNf() if you need to avoid this. See + + for details. */ _GL_UNUSED static double SNaNd () { - return construct_SNaNd (NaNd ()); + return memory_SNaNd ().value; } #endif +#undef NWORDS + /* 'long double' = * if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE: @@ -139,19 +179,18 @@ SNaNd () 80-bits extended-precision, padded to 96 bits, with non-IEEE exponent */ +#define NWORDS \ + ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) +typedef union { unsigned int word[NWORDS]; long double value; } + memory_long_double; + #if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT # define HAVE_SNANL 1 -_GL_UNUSED static long double -construct_SNaNl (long double quiet_value) +_GL_UNUSED static memory_long_double +construct_memory_SNaNl (long double quiet_value) { - /* A bit pattern that is different from a Quiet NaN. With a bit of luck, - it's a Signalling NaN. */ - #define NWORDS \ - ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) - typedef union { unsigned int word[NWORDS]; long double value; } - memory_long_double; memory_long_double m; m.value = quiet_value; #if defined __powerpc__ && LDBL_MANT_DIG == 106 @@ -186,18 +225,38 @@ construct_SNaNl (long double quiet_value) m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < HNWORDS / 2 ? 1 : - 1)] |= (unsigned int) 1 << LDBL_EXPBIT0_BIT; #undef HNWORDS - #undef NWORDS - return m.value; + return m; +} + +/* Returns a signalling 'long double' NaN in memory. */ +_GL_UNUSED static memory_long_double +memory_SNaNl () +{ + return construct_memory_SNaNl (NaNl ()); } -/* Returns a signalling 'long double' NaN. */ +_GL_UNUSED static long double +construct_SNaNl (long double quiet_value) +{ + return construct_memory_SNaNl (quiet_value).value; +} + +/* Returns a signalling 'long double' NaN. + Note: On 32-bit x86 processors, as well as on x86_64 processors with + CC="gcc -mfpmath=387", if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE is 1, this + function may return a quiet NaN instead. Use memory_SNaNf() if you + need to avoid this. See + + for details. */ _GL_UNUSED static long double SNaNl () { - return construct_SNaNl (NaNl ()); + return memory_SNaNl ().value; } #endif +#undef NWORDS + #endif /* _SNAN_H */