summaryrefslogtreecommitdiff
path: root/tests/signed-nan.h
diff options
context:
space:
mode:
Diffstat (limited to 'tests/signed-nan.h')
-rw-r--r--tests/signed-nan.h76
1 files changed, 63 insertions, 13 deletions
diff --git a/tests/signed-nan.h b/tests/signed-nan.h
index 18a550a7..cae6c5d5 100644
--- a/tests/signed-nan.h
+++ b/tests/signed-nan.h
@@ -1,17 +1,17 @@
/* Macros for quiet not-a-number.
Copyright (C) 2023-2024 Free Software Foundation, Inc.
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _SIGNED_NAN_H
@@ -21,6 +21,27 @@
#include "nan.h"
+#ifdef __cplusplus
+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
@@ -29,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. */
@@ -39,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 ()
@@ -50,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. */
@@ -60,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 ()
@@ -71,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. */
@@ -81,8 +127,12 @@ 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));
}
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _SIGNED_NAN_H */