]> 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, 19 Apr 2024 11:57:14 +0000 (13:57 +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.
* tests/test-totalorder.c (TOTALORDER_MINUS): New macro.
* tests/test-totalorderf.c (TOTALORDER_MINUS): New macro.
* tests/test-totalorderl.c (TOTALORDER_MINUS): New macro.
* tests/test-totalorder.h (negative_NaN_with_payload): Use it.
* tests/test-totalordermag.c (TOTALORDER_MINUS): New macro.
* tests/test-totalordermagf.c (TOTALORDER_MINUS): New macro.
* tests/test-totalordermagl.c (TOTALORDER_MINUS): New macro.
* tests/test-totalordermag.h (negative_NaN_with_payload): Use it.

ChangeLog
lib/signed-nan.h
tests/test-totalorder.c
tests/test-totalorder.h
tests/test-totalorderf.c
tests/test-totalorderl.c
tests/test-totalordermag.c
tests/test-totalordermag.h
tests/test-totalordermagf.c
tests/test-totalordermagl.c

index 25caba51c530aaa3169b453a7d1f254f90bd0faa..fc32137e74952c9da4524e9b3df91c82f721495b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+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.
+       * tests/test-totalorder.c (TOTALORDER_MINUS): New macro.
+       * tests/test-totalorderf.c (TOTALORDER_MINUS): New macro.
+       * tests/test-totalorderl.c (TOTALORDER_MINUS): New macro.
+       * tests/test-totalorder.h (negative_NaN_with_payload): Use it.
+       * tests/test-totalordermag.c (TOTALORDER_MINUS): New macro.
+       * tests/test-totalordermagf.c (TOTALORDER_MINUS): New macro.
+       * tests/test-totalordermagl.c (TOTALORDER_MINUS): New macro.
+       * tests/test-totalordermag.h (negative_NaN_with_payload): Use it.
+
 2024-04-19  Collin Funk  <collin.funk1@gmail.com>
 
        gnulib-tool.py: Add a comment about coding style.
index 14d2c525f5c80806d22b7fe6c6c64a3958100ae7..c2c2def71964871ca2a7e0f31fb2f75f0347c256 100644 (file)
@@ -26,6 +26,23 @@ extern "C" {
 #endif
 
 
+/* 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 ()
@@ -33,7 +50,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.  */
@@ -43,10 +60,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 ()
@@ -54,7 +88,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.  */
@@ -64,10 +98,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 ()
@@ -75,7 +117,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.  */
@@ -85,7 +127,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));
 }
 
 
index 412c3d301e1f1fa9257e2ae7dd53163e5478dc7d..2112b49af90af72cf5b94c6c5f410d82fa3acd5c 100644 (file)
@@ -26,6 +26,7 @@ SIGNATURE_CHECK (totalorder, int, (const double *, const double *));
 #define TOTALORDER_TYPE memory_double
 #define TOTALORDER_INF Infinityd
 #define TOTALORDER_MINUS_ZERO minus_zerod
+#define TOTALORDER_MINUS minus_NaNd
 #define TOTALORDER_SETPAYLOAD setpayload
 #define TOTALORDER_HAVE_SNAN HAVE_SNAND
 #define TOTALORDER_POSITIVE_SNAN memory_positive_SNaNd
index b02cec310b610ba5d256d5ab4ebcc3ba1091d53f..e675bd334f556a66a39c7ded53b23ed5c49e2abc 100644 (file)
@@ -36,7 +36,7 @@ negative_NaN_with_payload (int payload)
 {
   TOTALORDER_TYPE x;
   ASSERT (TOTALORDER_SETPAYLOAD (&x.value, payload) == 0);
-  x.value = - x.value;
+  x.value = TOTALORDER_MINUS (x.value);
   return x;
 }
 
index a3dd23a2969c72a68b417a7c3f49ffafecf312db..a7223feaf635b502f60b94f921d919e0bdb0e578 100644 (file)
@@ -26,6 +26,7 @@ SIGNATURE_CHECK (totalorderf, int, (const float *, const float *));
 #define TOTALORDER_TYPE memory_float
 #define TOTALORDER_INF Infinityf
 #define TOTALORDER_MINUS_ZERO minus_zerof
+#define TOTALORDER_MINUS minus_NaNf
 #define TOTALORDER_SETPAYLOAD setpayloadf
 #define TOTALORDER_HAVE_SNAN HAVE_SNANF
 #define TOTALORDER_POSITIVE_SNAN memory_positive_SNaNf
index f3db8194f72d6384357263a7759d700e30a6506b..79bb7d9ab854bb0d9bb46c2d14ebd0066e6c59a4 100644 (file)
@@ -26,6 +26,7 @@ SIGNATURE_CHECK (totalorderl, int, (const long double *, const long double *));
 #define TOTALORDER_TYPE memory_long_double
 #define TOTALORDER_INF Infinityl
 #define TOTALORDER_MINUS_ZERO minus_zerol
+#define TOTALORDER_MINUS minus_NaNl
 #define TOTALORDER_SETPAYLOAD setpayloadl
 #define TOTALORDER_HAVE_SNAN HAVE_SNANL
 #define TOTALORDER_POSITIVE_SNAN memory_positive_SNaNl
index 5b2c4c70d938f3790c5f6304fd53ca08748afe7d..7ac2498a506d4972f7fe6980f13891770d032cd6 100644 (file)
@@ -26,6 +26,7 @@ SIGNATURE_CHECK (totalordermag, int, (const double *, const double *));
 #define TOTALORDER_TYPE memory_double
 #define TOTALORDER_INF Infinityd
 #define TOTALORDER_MINUS_ZERO minus_zerod
+#define TOTALORDER_MINUS minus_NaNd
 #define TOTALORDER_SETPAYLOAD setpayload
 #define TOTALORDER_HAVE_SNAN HAVE_SNAND
 #define TOTALORDER_POSITIVE_SNAN memory_positive_SNaNd
index 4d4746fae146715ea06f22664d190f15d28d2ae1..ec86d55c27478c7982cf366685ab6462923ee41b 100644 (file)
@@ -36,7 +36,7 @@ negative_NaN_with_payload (int payload)
 {
   TOTALORDER_TYPE x;
   ASSERT (TOTALORDER_SETPAYLOAD (&x.value, payload) == 0);
-  x.value = - x.value;
+  x.value = TOTALORDER_MINUS (x.value);
   return x;
 }
 
index b6ada9d59f45f637f256ee9ac30b31753affad07..01d1ab0b125c2fb40a897c1c9b96012e6b4be72e 100644 (file)
@@ -26,6 +26,7 @@ SIGNATURE_CHECK (totalordermagf, int, (const float *, const float *));
 #define TOTALORDER_TYPE memory_float
 #define TOTALORDER_INF Infinityf
 #define TOTALORDER_MINUS_ZERO minus_zerof
+#define TOTALORDER_MINUS minus_NaNf
 #define TOTALORDER_SETPAYLOAD setpayloadf
 #define TOTALORDER_HAVE_SNAN HAVE_SNANF
 #define TOTALORDER_POSITIVE_SNAN memory_positive_SNaNf
index 1d33404405fcb98db99f05969e978a27be51a16f..34e8a102b5de6ee44b5d9a4acb09f9bd6ed9b923 100644 (file)
@@ -26,6 +26,7 @@ SIGNATURE_CHECK (totalordermagl, int, (const long double *, const long double *)
 #define TOTALORDER_TYPE memory_long_double
 #define TOTALORDER_INF Infinityl
 #define TOTALORDER_MINUS_ZERO minus_zerol
+#define TOTALORDER_MINUS minus_NaNl
 #define TOTALORDER_SETPAYLOAD setpayloadl
 #define TOTALORDER_HAVE_SNAN HAVE_SNANL
 #define TOTALORDER_POSITIVE_SNAN memory_positive_SNaNl