]> Savannah Git Hosting - gnulib.git/commitdiff
snan, signed-snan: Add API that works also on x86 and x86_64 CPUs.
authorBruno Haible <bruno@clisp.org>
Sat, 14 Oct 2023 18:38:49 +0000 (20:38 +0200)
committerBruno Haible <bruno@clisp.org>
Sat, 14 Oct 2023 18:38:49 +0000 (20:38 +0200)
* 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.

ChangeLog
lib/signed-snan.h
lib/snan.h

index 0fe658e2d3bbf03184389edcc8ca750fc0136ecc..78851b3b4aa0e0f00c62ea64de263b99cc0891dd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2023-10-14  Bruno Haible  <bruno@clisp.org>
+
+       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  <bruno@clisp.org>
 
        snan tests: Fix "unused variable" warnings on i386.
index f2754675679743edb5308ccdeb400ba21ce93b99..410ad71ce12310064faca9b4c81eced3ae97c6bc 100644 (file)
 
 #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 <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
+   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 <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
+   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
+   <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
+   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
index a65b12e713bd1d22a6c267c26d49de9c449d8185..ebf88ab0c533c50c144c3cd4e063b230b71e07d8 100644 (file)
 /* 'float' = IEEE 754 single-precision
    <https://en.wikipedia.org/wiki/Single-precision_floating-point_format>  */
 
+#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
+   <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
+   for details.  */
 _GL_UNUSED static float
 SNaNf ()
 {
-  return construct_SNaNf (NaNf ());
+  return memory_SNaNf ().value;
 }
 
 #endif
 
+#undef NWORDS
+
 
 /* 'double' = IEEE 754 double-precision
    <https://en.wikipedia.org/wiki/Double-precision_floating-point_format>  */
 
+#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
+   <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
+   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
+   <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
+   for details.  */
 _GL_UNUSED static long double
 SNaNl ()
 {
-  return construct_SNaNl (NaNl ());
+  return memory_SNaNl ().value;
 }
 
 #endif
 
+#undef NWORDS
+
 
 #endif /* _SNAN_H */