* 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 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.
#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 ()
/* '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. */
/* '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 ()
/* '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. */
/* '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 ()
/* '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. */
/* '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));
}
#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
{
TOTALORDER_TYPE x;
ASSERT (TOTALORDER_SETPAYLOAD (&x.value, payload) == 0);
- x.value = - x.value;
+ x.value = TOTALORDER_MINUS (x.value);
return x;
}
#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
#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
#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
{
TOTALORDER_TYPE x;
ASSERT (TOTALORDER_SETPAYLOAD (&x.value, payload) == 0);
- x.value = - x.value;
+ x.value = TOTALORDER_MINUS (x.value);
return x;
}
#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
#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