]> Savannah Git Hosting - gnulib.git/commitdiff
log2l: Work around musl libc bugs.
authorBruno Haible <bruno@clisp.org>
Sun, 31 Jan 2021 12:20:28 +0000 (13:20 +0100)
committerBruno Haible <bruno@clisp.org>
Sun, 31 Jan 2021 12:20:28 +0000 (13:20 +0100)
* doc/posix-functions/log2l.texi: Document musl libc bugs.
* m4/log2l.m4 (gl_FUNC_LOG2L_WORKS): Add more tests. Update cross
compilation guess.

ChangeLog
doc/posix-functions/log2l.texi
m4/log2l.m4

index acc8ca8fa07ae62641b8a32dfa78361d19db637d..1b8fd272f33e3a70111f30f22f7b452f7811f9a5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2021-01-31  Bruno Haible  <bruno@clisp.org>
+
+       log2l: Work around musl libc bugs.
+       * doc/posix-functions/log2l.texi: Document musl libc bugs.
+       * m4/log2l.m4 (gl_FUNC_LOG2L_WORKS): Add more tests. Update cross
+       compilation guess.
+
 2021-01-31  Bruno Haible  <bruno@clisp.org>
 
        log1pl: Work around musl libc bug.
index 24e367c10f0367a209b3511cce236f73893d3287..563a67ecc32377fb623d4856cfb36706f1558e9c 100644 (file)
@@ -14,6 +14,13 @@ FreeBSD 6.0, NetBSD 9.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, older IRIX
 @item
 This function is not declared on some platforms:
 IRIX 6.5.
+@item
+This function produces results which are accurate to only 16 digits on some
+platforms:
+musl libc 1.2.2/arm64, musl libc 1.2.2/s390x.
+@item
+This function returns Infinity for some large finite arguments on some platforms:
+musl libc 1.2.2/arm64, musl libc 1.2.2/s390x.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index 47765434fedf1c87e15e5c205efa3a8b51b5d288..cd8e9847418a882ab3d6d8852dee565789e5de8c 100644 (file)
@@ -1,4 +1,4 @@
-# log2l.m4 serial 2
+# log2l.m4 serial 3
 dnl Copyright (C) 2010-2021 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -69,6 +69,7 @@ AC_DEFUN([gl_FUNC_LOG2L],
 
 dnl Test whether log2l() works.
 dnl On OSF/1 5.1, log2l(-0.0) is NaN.
+dnl On musl 1.2.2/{arm64,s390x}, the result is accurate to only 16 digits.
 AC_DEFUN([gl_FUNC_LOG2L_WORKS],
 [
   AC_REQUIRE([AC_PROG_CC])
@@ -77,7 +78,40 @@ AC_DEFUN([gl_FUNC_LOG2L_WORKS],
     [
       AC_RUN_IFELSE(
         [AC_LANG_SOURCE([[
+#ifndef __NO_MATH_INLINES
+# define __NO_MATH_INLINES 1 /* for glibc */
+#endif
+#include <float.h>
 #include <math.h>
+/* Override the values of <float.h>, like done in float.in.h.  */
+#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG   64
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP    (-16381)
+# undef LDBL_MAX_EXP
+# define LDBL_MAX_EXP    16384
+#endif
+#if defined __i386__ && (defined __FreeBSD__ || defined __DragonFly__)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG   64
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP    (-16381)
+# undef LDBL_MAX_EXP
+# define LDBL_MAX_EXP    16384
+#endif
+#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__
+# undef LDBL_MIN_EXP
+# define LDBL_MIN_EXP DBL_MIN_EXP
+#endif
+#if defined __sgi && (LDBL_MANT_DIG >= 106)
+# undef LDBL_MANT_DIG
+# define LDBL_MANT_DIG 106
+# if defined __GNUC__
+#  undef LDBL_MIN_EXP
+#  define LDBL_MIN_EXP DBL_MIN_EXP
+# endif
+#endif
 #ifndef log2l /* for AIX */
 extern
 #ifdef __cplusplus
@@ -85,25 +119,59 @@ extern
 #endif
 long double log2l (long double);
 #endif
-volatile long double x;
-volatile long double y;
-int main ()
+static long double dummy (long double x) { return 0; }
+volatile long double gx;
+volatile long double gy;
+int main (int argc, char *argv[])
 {
+  long double (* volatile my_log2l) (long double) = argc ? log2l : dummy;
+  int result = 0;
   /* This test fails on OSF/1 5.1.  */
-  x = -0.0L;
-  y = log2l (x);
-  if (!(y + y == y))
-    return 1;
-  return 0;
+  {
+    gx = -0.0L;
+    gy = my_log2l (gx);
+    if (!(gy + gy == gy))
+      result |= 1;
+  }
+  /* This test fails on musl 1.2.2/arm64, musl 1.2.2/s390x.  */
+  {
+    const long double TWO_LDBL_MANT_DIG = /* 2^LDBL_MANT_DIG */
+      (long double) (1U << ((LDBL_MANT_DIG - 1) / 5))
+      * (long double) (1U << ((LDBL_MANT_DIG - 1 + 1) / 5))
+      * (long double) (1U << ((LDBL_MANT_DIG - 1 + 2) / 5))
+      * (long double) (1U << ((LDBL_MANT_DIG - 1 + 3) / 5))
+      * (long double) (1U << ((LDBL_MANT_DIG - 1 + 4) / 5));
+    long double x = 11.358L;
+    long double y = my_log2l (x);
+    long double z = my_log2l (1.0L / x);
+    long double err = (y + z) * TWO_LDBL_MANT_DIG;
+    if (!(err >= -10000.0L && err <= 10000.0L))
+      result |= 2;
+  }
+  /* This test fails on musl 1.2.2/arm64, musl 1.2.2/s390x.  */
+  if (DBL_MAX_EXP < LDBL_MAX_EXP)
+    {
+      long double x = ldexpl (1.0L, DBL_MAX_EXP); /* finite! */
+      long double y = my_log2l (x);
+      if (y > 0 && y + y == y) /* infinite? */
+        result |= 4;
+    }
+  return result;
 }
 ]])],
         [gl_cv_func_log2l_works=yes],
         [gl_cv_func_log2l_works=no],
         [case "$host_os" in
-           osf*)   gl_cv_func_log2l_works="guessing no" ;;
-                   # Guess yes on native Windows.
-           mingw*) gl_cv_func_log2l_works="guessing yes" ;;
-           *)      gl_cv_func_log2l_works="guessing yes" ;;
+                          # Guess yes on glibc systems.
+           *-gnu* | gnu*) gl_cv_func_log2l_works="guessing yes" ;;
+                          # Guess no on musl systems.
+           *-musl*)       gl_cv_func_log2l_works="guessing no" ;;
+                          # Guess no on OSF/1.
+           osf*)          gl_cv_func_log2l_works="guessing no" ;;
+                          # Guess yes on native Windows.
+           mingw*)        gl_cv_func_log2l_works="guessing yes" ;;
+                          # If we don't know, obey --enable-cross-guesses.
+           *)             gl_cv_func_log2l_works="$gl_cross_guess_normal" ;;
          esac
         ])
     ])