]> Savannah Git Hosting - gnulib.git/commitdiff
signed-nan: Don't assume that '-' works as expected on NaN values.
authorBruno Haible <bruno@clisp.org>
Fri, 19 Apr 2024 11:57:14 +0000 (13:57 +0200)
committerBruno Haible <bruno@clisp.org>
Fri, 26 Apr 2024 03:50:22 +0000 (05:50 +0200)
* lib/signed-nan.h (minus_NaNf): New function.
(positive_NaNf, negative_NaNf): Use it.
(minus_NaNd): New function.
(positive_NaNd, negative_NaNd): Use it.
(minus_NaNl): New function.
(positive_NaNl, negative_NaNl): Use it.

ChangeLog
lib/signed-nan.h

index 86f04d2fe69023a638a3de0e881019ba089bdabd..831a14211d3b5be8fb1048f03b7ce34bb48ea4aa 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2024-04-19  Bruno Haible  <bruno@clisp.org>
+
+       signed-nan: Don't assume that '-' works as expected on NaN values.
+       * lib/signed-nan.h (minus_NaNf): New function.
+       (positive_NaNf, negative_NaNf): Use it.
+       (minus_NaNd): New function.
+       (positive_NaNd, negative_NaNd): Use it.
+       (minus_NaNl): New function.
+       (positive_NaNl, negative_NaNl): Use it.
+
 2024-04-18  Bruno Haible  <bruno@clisp.org>
 
        totalorder*: Support newer MIPS CPUs.
index 18a550a7515e0b26e1ecda2772fe99d910a13cff..92b42510a9fc893449765c0790f3932c28ae0213 100644 (file)
 #include "nan.h"
 
 
+/* Returns - x, implemented by inverting the sign bit,
+   so that it works also on 'float' NaN values.  */
+_GL_UNUSED static float
+minus_NaNf (float x)
+{
+#if defined __mips__
+  /* The mips instruction neg.s may have no effect on NaNs.
+     Therefore, invert the sign bit using integer operations.  */
+  union { unsigned int i; float value; } u;
+  u.value = x;
+  u.i ^= 1U << 31;
+  return u.value;
+#else
+  return - x;
+#endif
+}
+
 /* Returns a quiet 'float' NaN with sign bit == 0.  */
 _GL_UNUSED static float
 positive_NaNf ()
@@ -29,7 +46,7 @@ positive_NaNf ()
   /* 'volatile' works around a GCC bug:
      <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655>  */
   float volatile nan = NaNf ();
-  return (signbit (nan) ? - nan : nan);
+  return (signbit (nan) ? minus_NaNf (nan) : nan);
 }
 
 /* Returns a quiet 'float' NaN with sign bit == 1.  */
@@ -39,10 +56,27 @@ negative_NaNf ()
   /* 'volatile' works around a GCC bug:
      <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655>  */
   float volatile nan = NaNf ();
-  return (signbit (nan) ? nan : - nan);
+  return (signbit (nan) ? nan : minus_NaNf (nan));
 }
 
 
+/* Returns - x, implemented by inverting the sign bit,
+   so that it works also on 'double' NaN values.  */
+_GL_UNUSED static double
+minus_NaNd (double x)
+{
+#if defined __mips__
+  /* The mips instruction neg.d may have no effect on NaNs.
+     Therefore, invert the sign bit using integer operations.  */
+  union { unsigned long long i; double value; } u;
+  u.value = x;
+  u.i ^= 1ULL << 63;
+  return u.value;
+#else
+  return - x;
+#endif
+}
+
 /* Returns a quiet 'double' NaN with sign bit == 0.  */
 _GL_UNUSED static double
 positive_NaNd ()
@@ -50,7 +84,7 @@ positive_NaNd ()
   /* 'volatile' works around a GCC bug:
      <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655>  */
   double volatile nan = NaNd ();
-  return (signbit (nan) ? - nan : nan);
+  return (signbit (nan) ? minus_NaNd (nan) : nan);
 }
 
 /* Returns a quiet 'double' NaN with sign bit == 1.  */
@@ -60,10 +94,18 @@ negative_NaNd ()
   /* 'volatile' works around a GCC bug:
      <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655>  */
   double volatile nan = NaNd ();
-  return (signbit (nan) ? nan : - nan);
+  return (signbit (nan) ? nan : minus_NaNd (nan));
 }
 
 
+/* Returns - x, implemented by inverting the sign bit,
+   so that it works also on 'long double' NaN values.  */
+_GL_UNUSED static long double
+minus_NaNl (long double x)
+{
+  return - x;
+}
+
 /* Returns a quiet 'long double' NaN with sign bit == 0.  */
 _GL_UNUSED static long double
 positive_NaNl ()
@@ -71,7 +113,7 @@ positive_NaNl ()
   /* 'volatile' works around a GCC bug:
      <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655>  */
   long double volatile nan = NaNl ();
-  return (signbit (nan) ? - nan : nan);
+  return (signbit (nan) ? minus_NaNl (nan) : nan);
 }
 
 /* Returns a quiet 'long double' NaN with sign bit == 1.  */
@@ -81,7 +123,7 @@ negative_NaNl ()
   /* 'volatile' works around a GCC bug:
      <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111655>  */
   long double volatile nan = NaNl ();
-  return (signbit (nan) ? nan : - nan);
+  return (signbit (nan) ? nan : minus_NaNl (nan));
 }