bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

math: Fix INFINITY and NAN on FreeBSD and AIX


From: Bruno Haible
Subject: math: Fix INFINITY and NAN on FreeBSD and AIX
Date: Thu, 01 Aug 2024 16:45:07 +0200

On AIX and older FreeBSD, INFINITY and NAN are not constant expressions, as
required by ISO C 99 ยง 7.12. This patch adds workarounds for this and related
bugs.


2024-08-01  Bruno Haible  <bruno@clisp.org>

        math: Fix INFINITY and NAN on FreeBSD and AIX.
        * doc/posix-headers/math.texi: Mention some FreeBSD and AIX bugs.
        * lib/math.in.h (INFINITY): New macro.
        (NAN): Replace also on FreeBSD < 8 and AIX. Use __builtin_nanf where
        available.
        (HUGE_VALF): Replace also on FreeBSD < 6. Use __builtin_inff where
        available.
        (HUGE_VAL): Replace also on FreeBSD < 6. Use __builtin_inf where
        available.
        (HUGE_VALL): Replace also on FreeBSD < 6. Use __builtin_infl where
        available.
        * tests/test-math.c: Check that INFINITY, NAN, HUGE_VALF, HUGE_VAL,
        HUGE_VALL are constant expressions.
        (main): Check the type of INFINITY and NAN.

diff --git a/doc/posix-headers/math.texi b/doc/posix-headers/math.texi
index be7cad2759..92b4d1b172 100644
--- a/doc/posix-headers/math.texi
+++ b/doc/posix-headers/math.texi
@@ -42,6 +42,21 @@
 @c https://dev.haiku-os.org/ticket/18351
 Haiku 2022.
 
+@item
+@code{HUGE_VAL}, @code{HUGE_VALF}, @code{HUGE_VALL} are not compile time
+constants on some platforms:
+FreeBSD 5.2.
+
+@item
+@code{INFINITY} and @code{NAN} are not compile time constants
+on some platforms:
+FreeBSD 5.2, AIX 7.1.
+
+@item
+@code{INFINITY} and @code{NAN} are of type @code{double} instead of 
@code{float}
+on some platforms:
+FreeBSD 7.1.
+
 @item
 The macros @code{NAN}, @code{HUGE_VALL}, and @code{INFINITY} are not
 defined on some platforms:
diff --git a/lib/math.in.h b/lib/math.in.h
index d3ecb74e69..7730efb7f5 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -160,12 +160,23 @@ static void (*_gl_math_fix_itold) (long double *, int) = 
_Qp_itoq;
 #endif
 
 
+/* Ensure that INFINITY is a constant expression, of type 'float'.  */
+#if !defined INFINITY || (defined __FreeBSD__ && __FreeBSD__ < 8) || defined 
_AIX
+# undef INFINITY
+# if defined __GNUC__ || defined __clang__
+#  define INFINITY (__builtin_inff ())
+# else
+#  define INFINITY (1.0f / 0.0f)
+# endif
+#endif
+
 /* POSIX allows platforms that don't support NAN.  But all major
    machines in the past 15 years have supported something close to
    IEEE NaN, so we define this unconditionally.  We also must define
    it on platforms like Solaris 10, where NAN is present but defined
-   as a function pointer rather than a floating point constant.  */
-#if !defined NAN || @REPLACE_NAN@
+   as a function pointer rather than a floating point constant.
+   Also ensure that it is a constant expression, of type 'float'.  */
+#if !defined NAN || @REPLACE_NAN@ || (defined __FreeBSD__ && __FreeBSD__ < 8) 
|| defined _AIX
 # if !GNULIB_defined_NAN
 #  undef NAN
   /* The Compaq (ex-DEC) C 6.4 compiler and the Microsoft MSVC 9 compiler
@@ -178,6 +189,8 @@ _NaN ()
   return zero / zero;
 }
 #   define NAN (_NaN())
+#  elif defined __GNUC__ || defined __clang__
+#   define NAN (__builtin_nanf (""))
 #  else
 #   define NAN (0.0f / 0.0f)
 #  endif
@@ -197,30 +210,39 @@ _NaN ()
 #endif
 
 /* HUGE_VALF is a 'float' Infinity.  */
-#ifndef HUGE_VALF
+#if !defined HUGE_VALF || (defined __FreeBSD__ && __FreeBSD__ < 6)
+# undef HUGE_VALF
 # if defined _MSC_VER
 /* The Microsoft MSVC 9 compiler chokes on the expression 1.0f / 0.0f.  */
 #  define HUGE_VALF (1e25f * 1e25f)
+# elif defined __GNUC__ || defined __clang__
+#  define HUGE_VALF (__builtin_inff ())
 # else
 #  define HUGE_VALF (1.0f / 0.0f)
 # endif
 #endif
 
 /* HUGE_VAL is a 'double' Infinity.  */
-#ifndef HUGE_VAL
+#if !defined HUGE_VAL || (defined __FreeBSD__ && __FreeBSD__ < 6)
+# undef HUGE_VAL
 # if defined _MSC_VER
 /* The Microsoft MSVC 9 compiler chokes on the expression 1.0 / 0.0.  */
 #  define HUGE_VAL (1e250 * 1e250)
+# elif defined __GNUC__ || defined __clang__
+#  define HUGE_VAL (__builtin_inf ())
 # else
 #  define HUGE_VAL (1.0 / 0.0)
 # endif
 #endif
 
 /* HUGE_VALL is a 'long double' Infinity.  */
-#ifndef HUGE_VALL
+#if !defined HUGE_VALL || (defined __FreeBSD__ && __FreeBSD__ < 6)
+# undef HUGE_VALL
 # if defined _MSC_VER
 /* The Microsoft MSVC 9 compiler chokes on the expression 1.0L / 0.0L.  */
 #  define HUGE_VALL (1e250L * 1e250L)
+# elif defined __GNUC__ || defined __clang__
+#  define HUGE_VALL (__builtin_infl ())
 # else
 #  define HUGE_VALL (1.0L / 0.0L)
 # endif
diff --git a/tests/test-math.c b/tests/test-math.c
index d33ec7e5e2..cfb510b933 100644
--- a/tests/test-math.c
+++ b/tests/test-math.c
@@ -20,8 +20,13 @@
 
 #include <math.h>
 
+#ifndef INFINITY
+# error INFINITY should be defined, added in ISO C 99
+choke me
+#endif
+
 #ifndef NAN
-# error NAN should be defined
+# error NAN should be defined, added in ISO C 99
 choke me
 #endif
 
@@ -50,10 +55,20 @@ choke me
 choke me
 #endif
 
-#if 0
+/* Check that INFINITY expands into a constant expression.  */
+float in = INFINITY;
+
 /* Check that NAN expands into a constant expression.  */
-static float n = NAN;
-#endif
+float na = NAN;
+
+/* Check that HUGE_VALF expands into a constant expression.  */
+float hf = HUGE_VALF;
+
+/* Check that HUGE_VAL expands into a constant expression.  */
+double hd = HUGE_VAL;
+
+/* Check that HUGE_VALL expands into a constant expression.  */
+long double hl = HUGE_VALL;
 
 #include <limits.h>
 
@@ -81,17 +96,28 @@ numeric_equall (long double x, long double y)
 int
 main (void)
 {
-  double d = NAN;
+  double d;
   double zero = 0.0;
-  ASSERT (!numeric_equald (d, d));
 
-  d = HUGE_VAL;
-  ASSERT (numeric_equald (d, 1.0 / zero));
+  /* Check that INFINITY is a float.  */
+  ASSERT (sizeof (INFINITY) == sizeof (float));
+
+  /* Check that NAN is a float.  */
+  ASSERT (sizeof (NAN) == sizeof (float));
 
+  /* Check the value of NAN.  */
+  d = NAN;
+  ASSERT (!numeric_equald (d, d));
+
+  /* Check the value of HUGE_VALF.  */
   ASSERT (numeric_equalf (HUGE_VALF, HUGE_VALF + HUGE_VALF));
 
+  /* Check the value of HUGE_VAL.  */
+  d = HUGE_VAL;
+  ASSERT (numeric_equald (d, 1.0 / zero));
   ASSERT (numeric_equald (HUGE_VAL, HUGE_VAL + HUGE_VAL));
 
+  /* Check the value of HUGE_VALL.  */
   ASSERT (numeric_equall (HUGE_VALL, HUGE_VALL + HUGE_VALL));
 
   /* Check the value of FP_ILOGB0.  */






reply via email to

[Prev in Thread] Current Thread [Next in Thread]