bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
* work around inaccurate 'long double' math functions on NetBSD
@ 2019-01-20 23:39 Bruno Haible
  0 siblings, 0 replies; only message in thread
From: Bruno Haible @ 2019-01-20 23:39 UTC (permalink / raw)
  To: bug-gnulib

[-- Attachment #1: Type: text/plain, Size: 478 bytes --]

On NetBSD 8.0 (x86_64, x86, and sparc64) I'm seeing test failures:

FAIL: test-exp2l
FAIL: test-expl
FAIL: test-expm1l
FAIL: test-log10l
FAIL: test-log1pl
FAIL: test-log2l
FAIL: test-logl

The results have apparently only 54 bits of precision, even though
'long double' has 64 or 113 bits of mantissa, respectively.

Also this failure, due to wrong results for negative arguments.

FAIL: test-rintl

This series of patches adds workarounds, so that all these tests pass.

Bruno

[-- Attachment #2: 0001-exp2l-Work-around-inaccurate-implementation-on-NetBS.patch --]
[-- Type: text/x-patch, Size: 5370 bytes --]

From e86cbc4644f41ea3a7b5c898790264e93191a49e Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sun, 20 Jan 2019 21:45:29 +0100
Subject: [PATCH 1/6] exp2l: Work around inaccurate implementation on NetBSD.

* m4/exp2l.m4 (gl_FUNC_EXP2L): Add test for a certain accuracy.
* doc/posix-functions/exp2l.texi: Mention the NetBSD bug.
---
 ChangeLog                      |  6 +++
 doc/posix-functions/exp2l.texi |  4 ++
 m4/exp2l.m4                    | 90 +++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index 6e02f8a..a8c6797 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2019-01-20  Bruno Haible  <bruno@clisp.org>
 
+	exp2l: Work around inaccurate implementation on NetBSD.
+	* m4/exp2l.m4 (gl_FUNC_EXP2L): Add test for a certain accuracy.
+	* doc/posix-functions/exp2l.texi: Mention the NetBSD bug.
+
+2019-01-20  Bruno Haible  <bruno@clisp.org>
+
 	floor, floorl: Avoid autoconf warnings.
 	* modules/floor (configure.ac): Use AC_REQUIRE.
 	* modules/floorl (configure.ac): Likewise.
diff --git a/doc/posix-functions/exp2l.texi b/doc/posix-functions/exp2l.texi
index a0f7841..672b4de 100644
--- a/doc/posix-functions/exp2l.texi
+++ b/doc/posix-functions/exp2l.texi
@@ -14,6 +14,10 @@ FreeBSD 6.0, NetBSD 5.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:
+NetBSD 8.0.
 @end itemize
 
 Portability problems fixed by Gnulib module @code{exp2l-ieee}:
diff --git a/m4/exp2l.m4 b/m4/exp2l.m4
index 20630cc..8a065d9 100644
--- a/m4/exp2l.m4
+++ b/m4/exp2l.m4
@@ -1,4 +1,4 @@
-# exp2l.m4 serial 6
+# exp2l.m4 serial 7
 dnl Copyright (C) 2010-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -26,6 +26,94 @@ AC_DEFUN([gl_FUNC_EXP2L],
     dnl Also check whether it's declared.
     dnl IRIX 6.5 has exp2l() in libm but doesn't declare it in <math.h>.
     AC_CHECK_DECL([exp2l], , [HAVE_DECL_EXP2L=0], [[#include <math.h>]])
+    if test $REPLACE_EXP2L = 0; then
+      AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+      AC_CACHE_CHECK([whether exp2l works],
+        [gl_cv_func_exp2l_works],
+        [
+          save_LIBS="$LIBS"
+          LIBS="$LIBS $EXP2L_LIBM"
+          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
+#undef exp2l
+extern
+#ifdef __cplusplus
+"C"
+#endif
+long double exp2l (long double);
+static long double dummy (long double x) { return 0; }
+int main (int argc, char *argv[])
+{
+  long double (* volatile my_exp2l) (long double) = argc ? exp2l : dummy;
+  int result = 0;
+  /* This test fails on NetBSD 8.0.  */
+  {
+    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 err = (my_exp2l (x) * my_exp2l (- x) - 1.0L) * TWO_LDBL_MANT_DIG;
+    if (!(err >= -100.0L && err <= 100.0L))
+      result |= 1;
+  }
+  return result;
+}
+            ]])],
+            [gl_cv_func_exp2l_works=yes],
+            [gl_cv_func_exp2l_works=no],
+            [case "$host_os" in
+                              # Guess yes on glibc systems.
+               *-gnu* | gnu*) gl_cv_func_exp2l_works="guessing yes" ;;
+                              # Guess yes on native Windows.
+               mingw*)        gl_cv_func_exp2l_works="guessing yes" ;;
+                              # If we don't know, assume the worst.
+               *)             gl_cv_func_exp2l_works="guessing no" ;;
+             esac
+            ])
+          LIBS="$save_LIBS"
+        ])
+      case "$gl_cv_func_exp2l_works" in
+        *yes) ;;
+        *) REPLACE_EXP2L=1 ;;
+      esac
+    fi
     m4_ifdef([gl_FUNC_EXP2L_IEEE], [
       if test $gl_exp2l_required = ieee && test $REPLACE_EXP2L = 0; then
         AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
-- 
2.7.4


[-- Attachment #3: 0002-expl-Work-around-inaccurate-implementation-on-NetBSD.patch --]
[-- Type: text/x-patch, Size: 9567 bytes --]

From 0ac7b4317dbe2247c520d0f786926e9e520ba81c Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sun, 20 Jan 2019 22:04:01 +0100
Subject: [PATCH 2/6] expl: Work around inaccurate implementation on NetBSD.

* lib/math.in.h (expl): Test also REPLACE_EXPL.
* m4/expl.m4 (gl_FUNC_EXPL): Add test for a certain accuracy. Set
REPLACE_EXPL.
* m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize REPLACE_EXPL.
* modules/math (Makefile.in): Substitute REPLACE_EXPL.
* modules/expl (Depends-on, configure.ac): Test REPLACE_EXPL.
* doc/posix-functions/expl.texi: Mention the NetBSD bug.
---
 ChangeLog                     | 11 ++++++
 doc/posix-functions/expl.texi |  4 ++
 lib/math.in.h                 | 15 +++++--
 m4/expl.m4                    | 92 ++++++++++++++++++++++++++++++++++++++++++-
 m4/math_h.m4                  |  3 +-
 modules/expl                  | 12 +++---
 modules/math                  |  1 +
 7 files changed, 127 insertions(+), 11 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a8c6797..80f00e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2019-01-20  Bruno Haible  <bruno@clisp.org>
 
+	expl: Work around inaccurate implementation on NetBSD.
+	* lib/math.in.h (expl): Test also REPLACE_EXPL.
+	* m4/expl.m4 (gl_FUNC_EXPL): Add test for a certain accuracy. Set
+	REPLACE_EXPL.
+	* m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize REPLACE_EXPL.
+	* modules/math (Makefile.in): Substitute REPLACE_EXPL.
+	* modules/expl (Depends-on, configure.ac): Test REPLACE_EXPL.
+	* doc/posix-functions/expl.texi: Mention the NetBSD bug.
+
+2019-01-20  Bruno Haible  <bruno@clisp.org>
+
 	exp2l: Work around inaccurate implementation on NetBSD.
 	* m4/exp2l.m4 (gl_FUNC_EXP2L): Add test for a certain accuracy.
 	* doc/posix-functions/exp2l.texi: Mention the NetBSD bug.
diff --git a/doc/posix-functions/expl.texi b/doc/posix-functions/expl.texi
index 2e5d086..4a3ffdd 100644
--- a/doc/posix-functions/expl.texi
+++ b/doc/posix-functions/expl.texi
@@ -23,6 +23,10 @@ MSVC 14.
 @item
 This function is not declared on some platforms:
 Mac OS X 10.3.
+@item
+This function produces results which are accurate to only 16 digits on some
+platforms:
+NetBSD 8.0.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/lib/math.in.h b/lib/math.in.h
index d395552..c5f9b46 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -627,11 +627,20 @@ _GL_WARN_ON_USE (expf, "expf is unportable - "
 #endif
 
 #if @GNULIB_EXPL@
-# if !@HAVE_EXPL@ || !@HAVE_DECL_EXPL@
-#  undef expl
+# if @REPLACE_EXPL@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef expl
+#   define expl rpl_expl
+#  endif
+_GL_FUNCDECL_RPL (expl, long double, (long double x));
+_GL_CXXALIAS_RPL (expl, long double, (long double x));
+# else
+#  if !@HAVE_EXPL@ || !@HAVE_DECL_EXPL@
+#   undef expl
 _GL_FUNCDECL_SYS (expl, long double, (long double x));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (expl, long double, (long double x));
+# endif
 _GL_CXXALIASWARN (expl);
 #elif defined GNULIB_POSIXCHECK
 # undef expl
diff --git a/m4/expl.m4 b/m4/expl.m4
index 93851a2..c04c1cb 100644
--- a/m4/expl.m4
+++ b/m4/expl.m4
@@ -1,4 +1,4 @@
-# expl.m4 serial 11
+# expl.m4 serial 12
 dnl Copyright (C) 2010-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -96,9 +96,99 @@ AC_DEFUN([gl_FUNC_EXPL],
     dnl Also check whether it's declared.
     dnl Mac OS X 10.3 has expl() in libc but doesn't declare it in <math.h>.
     AC_CHECK_DECL([expl], , [HAVE_DECL_EXPL=0], [[#include <math.h>]])
+    if test $REPLACE_EXPL = 0; then
+      AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+      AC_CACHE_CHECK([whether expl works],
+        [gl_cv_func_expl_works],
+        [
+          save_LIBS="$LIBS"
+          LIBS="$LIBS $EXPL_LIBM"
+          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
+#undef expl
+extern
+#ifdef __cplusplus
+"C"
+#endif
+long double expl (long double);
+static long double dummy (long double x) { return 0; }
+int main (int argc, char *argv[])
+{
+  long double (* volatile my_expl) (long double) = argc ? expl : dummy;
+  int result = 0;
+  /* This test fails on NetBSD 8.0.  */
+  {
+    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 err = (my_expl (x) * my_expl (- x) - 1.0L) * TWO_LDBL_MANT_DIG;
+    if (!(err >= -100.0L && err <= 100.0L))
+      result |= 1;
+  }
+  return result;
+}
+            ]])],
+            [gl_cv_func_expl_works=yes],
+            [gl_cv_func_expl_works=no],
+            [case "$host_os" in
+                              # Guess yes on glibc systems.
+               *-gnu* | gnu*) gl_cv_func_expl_works="guessing yes" ;;
+                              # Guess yes on native Windows.
+               mingw*)        gl_cv_func_expl_works="guessing yes" ;;
+                              # If we don't know, assume the worst.
+               *)             gl_cv_func_expl_works="guessing no" ;;
+             esac
+            ])
+          LIBS="$save_LIBS"
+        ])
+      case "$gl_cv_func_expl_works" in
+        *yes) ;;
+        *) REPLACE_EXPL=1 ;;
+      esac
+    fi
   else
     HAVE_DECL_EXPL=0
     HAVE_EXPL=0
+  fi
+  if test $HAVE_EXPL = 0 || test $REPLACE_EXPL = 1; then
     dnl Find libraries needed to link lib/expl.c.
     if test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1; then
       AC_REQUIRE([gl_FUNC_EXP])
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index 7e79831..2eec8c4 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,4 +1,4 @@
-# math_h.m4 serial 116
+# math_h.m4 serial 117
 dnl Copyright (C) 2007-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -268,6 +268,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   REPLACE_COSF=0;              AC_SUBST([REPLACE_COSF])
   REPLACE_COSHF=0;             AC_SUBST([REPLACE_COSHF])
   REPLACE_EXPF=0;              AC_SUBST([REPLACE_EXPF])
+  REPLACE_EXPL=0;              AC_SUBST([REPLACE_EXPL])
   REPLACE_EXPM1=0;             AC_SUBST([REPLACE_EXPM1])
   REPLACE_EXPM1F=0;            AC_SUBST([REPLACE_EXPM1F])
   REPLACE_EXP2=0;              AC_SUBST([REPLACE_EXP2])
diff --git a/modules/expl b/modules/expl
index 32ee6c0..90a7e65 100644
--- a/modules/expl
+++ b/modules/expl
@@ -9,15 +9,15 @@ m4/expl.m4
 Depends-on:
 math
 extensions
-exp             [test $HAVE_EXPL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
-float           [test $HAVE_EXPL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
-isnanl          [test $HAVE_EXPL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
-roundl          [test $HAVE_EXPL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
-ldexpl          [test $HAVE_EXPL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+exp             [{ test $HAVE_EXPL = 0 || test $REPLACE_EXPL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
+float           [{ test $HAVE_EXPL = 0 || test $REPLACE_EXPL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+isnanl          [{ test $HAVE_EXPL = 0 || test $REPLACE_EXPL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+roundl          [{ test $HAVE_EXPL = 0 || test $REPLACE_EXPL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+ldexpl          [{ test $HAVE_EXPL = 0 || test $REPLACE_EXPL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
 
 configure.ac:
 gl_FUNC_EXPL
-if test $HAVE_EXPL = 0; then
+if test $HAVE_EXPL = 0 || test $REPLACE_EXPL = 1; then
   AC_LIBOBJ([expl])
   AC_LIBOBJ([expl-table])
 fi
diff --git a/modules/math b/modules/math
index d539518..77197e5 100644
--- a/modules/math
+++ b/modules/math
@@ -237,6 +237,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's|@''REPLACE_COSF''@|$(REPLACE_COSF)|g' \
 	      -e 's|@''REPLACE_COSHF''@|$(REPLACE_COSHF)|g' \
 	      -e 's|@''REPLACE_EXPF''@|$(REPLACE_EXPF)|g' \
+	      -e 's|@''REPLACE_EXPL''@|$(REPLACE_EXPL)|g' \
 	      -e 's|@''REPLACE_EXPM1''@|$(REPLACE_EXPM1)|g' \
 	      -e 's|@''REPLACE_EXPM1F''@|$(REPLACE_EXPM1F)|g' \
 	      -e 's|@''REPLACE_EXP2''@|$(REPLACE_EXP2)|g' \
-- 
2.7.4


[-- Attachment #4: 0003-expm1l-Work-around-inaccurate-implementation-on-NetB.patch --]
[-- Type: text/x-patch, Size: 10075 bytes --]

From 67df3cffac300d320307e8d7e494029098edc334 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sun, 20 Jan 2019 22:28:37 +0100
Subject: [PATCH 3/6] expm1l: Work around inaccurate implementation on NetBSD.

* lib/math.in.h (expm1l): Test also REPLACE_EXPM1L.
* m4/expm1l.m4 (gl_FUNC_EXPM1L): Add test for a certain accuracy. Set
REPLACE_EXPM1L.
* m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize REPLACE_EXPM1L.
* modules/math (Makefile.in): Substitute REPLACE_EXPM1L.
* modules/expm1l (Depends-on, configure.ac): Test REPLACE_EXPM1L.
* doc/posix-functions/expm1l.texi: Mention the NetBSD bug.
---
 ChangeLog                       | 11 +++++
 doc/posix-functions/expm1l.texi |  4 ++
 lib/math.in.h                   | 15 +++++--
 m4/expm1l.m4                    | 94 ++++++++++++++++++++++++++++++++++++++++-
 m4/math_h.m4                    |  3 +-
 modules/expm1l                  | 14 +++---
 modules/math                    |  1 +
 7 files changed, 130 insertions(+), 12 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 80f00e2..07f3cc4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2019-01-20  Bruno Haible  <bruno@clisp.org>
 
+	expm1l: Work around inaccurate implementation on NetBSD.
+	* lib/math.in.h (expm1l): Test also REPLACE_EXPM1L.
+	* m4/expm1l.m4 (gl_FUNC_EXPM1L): Add test for a certain accuracy. Set
+	REPLACE_EXPM1L.
+	* m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize REPLACE_EXPM1L.
+	* modules/math (Makefile.in): Substitute REPLACE_EXPM1L.
+	* modules/expm1l (Depends-on, configure.ac): Test REPLACE_EXPM1L.
+	* doc/posix-functions/expm1l.texi: Mention the NetBSD bug.
+
+2019-01-20  Bruno Haible  <bruno@clisp.org>
+
 	expl: Work around inaccurate implementation on NetBSD.
 	* lib/math.in.h (expl): Test also REPLACE_EXPL.
 	* m4/expl.m4 (gl_FUNC_EXPL): Add test for a certain accuracy. Set
diff --git a/doc/posix-functions/expm1l.texi b/doc/posix-functions/expm1l.texi
index 3ccf9b1..75534f2 100644
--- a/doc/posix-functions/expm1l.texi
+++ b/doc/posix-functions/expm1l.texi
@@ -14,6 +14,10 @@ FreeBSD 6.0, NetBSD 5.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:
+NetBSD 8.0.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/lib/math.in.h b/lib/math.in.h
index c5f9b46..270caaf 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -760,11 +760,20 @@ _GL_WARN_ON_USE (expm1, "expm1 is unportable - "
 #endif
 
 #if @GNULIB_EXPM1L@
-# if !@HAVE_DECL_EXPM1L@
-#  undef expm1l
+# if @REPLACE_EXPM1L@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef expm1l
+#   define expm1l rpl_expm1l
+#  endif
+_GL_FUNCDECL_RPL (expm1l, long double, (long double x));
+_GL_CXXALIAS_RPL (expm1l, long double, (long double x));
+# else
+#  if !@HAVE_DECL_EXPM1L@
+#   undef expm1l
 _GL_FUNCDECL_SYS (expm1l, long double, (long double x));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (expm1l, long double, (long double x));
+# endif
 _GL_CXXALIASWARN (expm1l);
 #elif defined GNULIB_POSIXCHECK
 # undef expm1l
diff --git a/m4/expm1l.m4 b/m4/expm1l.m4
index d074550..d2307f2 100644
--- a/m4/expm1l.m4
+++ b/m4/expm1l.m4
@@ -1,4 +1,4 @@
-# expm1l.m4 serial 2
+# expm1l.m4 serial 3
 dnl Copyright (C) 2010-2019 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,9 +69,101 @@ AC_DEFUN([gl_FUNC_EXPM1L],
     dnl Also check whether it's declared.
     dnl IRIX 6.5 has expm1l() in libm but doesn't declare it in <math.h>.
     AC_CHECK_DECL([expm1l], , [HAVE_DECL_EXPM1L=0], [[#include <math.h>]])
+    if test $REPLACE_EXPM1L = 0; then
+      AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+      AC_CACHE_CHECK([whether expm1l works],
+        [gl_cv_func_expm1l_works],
+        [
+          save_LIBS="$LIBS"
+          LIBS="$LIBS $EXPM1L_LIBM"
+          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
+#undef expm1l
+extern
+#ifdef __cplusplus
+"C"
+#endif
+long double expm1l (long double);
+static long double dummy (long double x) { return 0; }
+int main (int argc, char *argv[])
+{
+  long double (* volatile my_expm1l) (long double) = argc ? expm1l : dummy;
+  int result = 0;
+  /* This test fails on NetBSD 8.0.  */
+  {
+    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_expm1l (x);
+    long double z = my_expm1l (- x);
+    long double err = (y + (1.0L + y) * z) * TWO_LDBL_MANT_DIG;
+    if (!(err >= -100.0L && err <= 100.0L))
+      result |= 1;
+  }
+  return result;
+}
+            ]])],
+            [gl_cv_func_expm1l_works=yes],
+            [gl_cv_func_expm1l_works=no],
+            [case "$host_os" in
+                              # Guess yes on glibc systems.
+               *-gnu* | gnu*) gl_cv_func_expm1l_works="guessing yes" ;;
+                              # Guess yes on native Windows.
+               mingw*)        gl_cv_func_expm1l_works="guessing yes" ;;
+                              # If we don't know, assume the worst.
+               *)             gl_cv_func_expm1l_works="guessing no" ;;
+             esac
+            ])
+          LIBS="$save_LIBS"
+        ])
+      case "$gl_cv_func_expm1l_works" in
+        *yes) ;;
+        *) REPLACE_EXPM1L=1 ;;
+      esac
+    fi
   else
     HAVE_EXPM1L=0
     HAVE_DECL_EXPM1L=0
+  fi
+  if test $HAVE_EXPM1L = 0 || test $REPLACE_EXPM1L = 1; then
     dnl Find libraries needed to link lib/expm1l.c.
     if test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1; then
       AC_REQUIRE([gl_FUNC_EXPM1])
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index 2eec8c4..bbbe5d4 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,4 +1,4 @@
-# math_h.m4 serial 117
+# math_h.m4 serial 118
 dnl Copyright (C) 2007-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -271,6 +271,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   REPLACE_EXPL=0;              AC_SUBST([REPLACE_EXPL])
   REPLACE_EXPM1=0;             AC_SUBST([REPLACE_EXPM1])
   REPLACE_EXPM1F=0;            AC_SUBST([REPLACE_EXPM1F])
+  REPLACE_EXPM1L=0;            AC_SUBST([REPLACE_EXPM1L])
   REPLACE_EXP2=0;              AC_SUBST([REPLACE_EXP2])
   REPLACE_EXP2L=0;             AC_SUBST([REPLACE_EXP2L])
   REPLACE_FABSL=0;             AC_SUBST([REPLACE_FABSL])
diff --git a/modules/expm1l b/modules/expm1l
index 1f23a0d..f7137e2 100644
--- a/modules/expm1l
+++ b/modules/expm1l
@@ -8,16 +8,16 @@ m4/expm1l.m4
 Depends-on:
 math
 extensions
-expm1           [test $HAVE_EXPM1L = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
-float           [test $HAVE_EXPM1L = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
-isnanl          [test $HAVE_EXPM1L = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
-expl            [test $HAVE_EXPM1L = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
-roundl          [test $HAVE_EXPM1L = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
-ldexpl          [test $HAVE_EXPM1L = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+expm1           [{ test $HAVE_EXPM1L = 0 || test $REPLACE_EXPM1L = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
+float           [{ test $HAVE_EXPM1L = 0 || test $REPLACE_EXPM1L = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+isnanl          [{ test $HAVE_EXPM1L = 0 || test $REPLACE_EXPM1L = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+expl            [{ test $HAVE_EXPM1L = 0 || test $REPLACE_EXPM1L = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+roundl          [{ test $HAVE_EXPM1L = 0 || test $REPLACE_EXPM1L = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+ldexpl          [{ test $HAVE_EXPM1L = 0 || test $REPLACE_EXPM1L = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
 
 configure.ac:
 gl_FUNC_EXPM1L
-if test $HAVE_EXPM1L = 0; then
+if test $HAVE_EXPM1L = 0 || test $REPLACE_EXPM1L = 1; then
   AC_LIBOBJ([expm1l])
 fi
 gl_MATH_MODULE_INDICATOR([expm1l])
diff --git a/modules/math b/modules/math
index 77197e5..1f23a17 100644
--- a/modules/math
+++ b/modules/math
@@ -240,6 +240,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's|@''REPLACE_EXPL''@|$(REPLACE_EXPL)|g' \
 	      -e 's|@''REPLACE_EXPM1''@|$(REPLACE_EXPM1)|g' \
 	      -e 's|@''REPLACE_EXPM1F''@|$(REPLACE_EXPM1F)|g' \
+	      -e 's|@''REPLACE_EXPM1L''@|$(REPLACE_EXPM1L)|g' \
 	      -e 's|@''REPLACE_EXP2''@|$(REPLACE_EXP2)|g' \
 	      -e 's|@''REPLACE_EXP2L''@|$(REPLACE_EXP2L)|g' \
 	      -e 's|@''REPLACE_FABSL''@|$(REPLACE_FABSL)|g' \
-- 
2.7.4


[-- Attachment #5: 0004-logl-Work-around-inaccurate-implementation-on-NetBSD.patch --]
[-- Type: text/x-patch, Size: 5713 bytes --]

From 27f3a1709d027b85bcf5ff91e604818978377af4 Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sun, 20 Jan 2019 22:57:41 +0100
Subject: [PATCH 4/6] logl: Work around inaccurate implementation on NetBSD.

* m4/logl.m4 (gl_FUNC_LOGL_WORKS): Add test for a certain accuracy.
* lib/logl.c: Comment out unused code.
* doc/posix-functions/logl.texi: Mention the NetBSD bug.
---
 ChangeLog                     |  7 ++++
 doc/posix-functions/logl.texi |  4 ++
 lib/logl.c                    |  2 +-
 m4/logl.m4                    | 88 ++++++++++++++++++++++++++++++++++++-------
 4 files changed, 87 insertions(+), 14 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 07f3cc4..98702e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2019-01-20  Bruno Haible  <bruno@clisp.org>
 
+	logl: Work around inaccurate implementation on NetBSD.
+	* m4/logl.m4 (gl_FUNC_LOGL_WORKS): Add test for a certain accuracy.
+	* lib/logl.c: Comment out unused code.
+	* doc/posix-functions/logl.texi: Mention the NetBSD bug.
+
+2019-01-20  Bruno Haible  <bruno@clisp.org>
+
 	expm1l: Work around inaccurate implementation on NetBSD.
 	* lib/math.in.h (expm1l): Test also REPLACE_EXPM1L.
 	* m4/expm1l.m4 (gl_FUNC_EXPM1L): Add test for a certain accuracy. Set
diff --git a/doc/posix-functions/logl.texi b/doc/posix-functions/logl.texi
index 51e2081..a82c3af 100644
--- a/doc/posix-functions/logl.texi
+++ b/doc/posix-functions/logl.texi
@@ -23,6 +23,10 @@ glibc 2.7 on Linux/SPARC64.
 @item
 This function returns a wrong value for a minus zero argument on some platforms:
 OSF/1 5.1.
+@item
+This function produces results which are accurate to only 16 digits on some
+platforms:
+NetBSD 8.0.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/lib/logl.c b/lib/logl.c
index 07cc7aa..0e8162f 100644
--- a/lib/logl.c
+++ b/lib/logl.c
@@ -26,7 +26,7 @@ logl (long double x)
   return log (x);
 }
 
-#elif HAVE_LOGL
+#elif 0 /* was: HAVE_LOGL */
 
 long double
 logl (long double x)
diff --git a/m4/logl.m4 b/m4/logl.m4
index 12b7081..a3576cb 100644
--- a/m4/logl.m4
+++ b/m4/logl.m4
@@ -1,4 +1,4 @@
-# logl.m4 serial 10
+# logl.m4 serial 11
 dnl Copyright (C) 2010-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -103,6 +103,7 @@ AC_DEFUN([gl_FUNC_LOGL],
 
 dnl Test whether logl() works.
 dnl On OSF/1 5.1, logl(-0.0L) is NaN.
+dnl On NetBSD 8.0, the result is accurate to only 16 digits.
 AC_DEFUN([gl_FUNC_LOGL_WORKS],
 [
   AC_REQUIRE([AC_PROG_CC])
@@ -111,25 +112,86 @@ AC_DEFUN([gl_FUNC_LOGL_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>
-volatile long double x;
-long double y;
-int main ()
+/* 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
+#undef logl
+extern
+#ifdef __cplusplus
+"C"
+#endif
+long double logl (long double);
+static long double dummy (long double x) { return 0; }
+volatile long double gx;
+long double gy;
+int main (int argc, char *argv[])
 {
-  x = -0.0L;
-  y = logl (x);
-  if (!(y + y == y))
-    return 1;
-  return 0;
+  long double (* volatile my_logl) (long double) = argc ? logl : dummy;
+  int result = 0;
+  /* This test fails on OSF/1 5.1.  */
+  {
+    gx = -0.0L;
+    gy = logl (gx);
+    if (!(gy + gy == gy))
+      result |= 1;
+  }
+  /* This test fails on NetBSD 8.0.  */
+  {
+    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 = 16.981137113807045L;
+    long double err = (my_logl (x) + my_logl (1.0L / x)) * TWO_LDBL_MANT_DIG;
+    if (!(err >= -100.0L && err <= 100.0L))
+      result |= 2;
+  }
+
+  return result;
 }
 ]])],
         [gl_cv_func_logl_works=yes],
         [gl_cv_func_logl_works=no],
         [case "$host_os" in
-           osf*)   gl_cv_func_logl_works="guessing no" ;;
-                   # Guess yes on native Windows.
-           mingw*) gl_cv_func_logl_works="guessing yes" ;;
-           *)      gl_cv_func_logl_works="guessing yes" ;;
+                          # Guess yes on glibc systems.
+           *-gnu* | gnu*) gl_cv_func_logl_works="guessing yes" ;;
+                          # Guess yes on native Windows.
+           mingw*)        gl_cv_func_logl_works="guessing yes" ;;
+                          # If we don't know, assume the worst.
+           *)             gl_cv_func_logl_works="guessing no" ;;
          esac
         ])
     ])
-- 
2.7.4


[-- Attachment #6: 0005-log10l-Work-around-inaccurate-implementation-on-NetB.patch --]
[-- Type: text/x-patch, Size: 6136 bytes --]

From e5462c3304ef7f373bfb7c6a976dc25730412a7a Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Sun, 20 Jan 2019 23:48:18 +0100
Subject: [PATCH 5/6] log10l: Work around inaccurate implementation on NetBSD.

* m4/log10l.m4 (gl_FUNC_LOG10L_WORKS): Add test for a certain accuracy.
* lib/log10l.c: Comment out too simplistic override.
* doc/posix-functions/log10l.texi: Mention the NetBSD bug.
---
 ChangeLog                       |  7 ++++
 doc/posix-functions/log10l.texi |  4 ++
 lib/log10l.c                    |  2 +-
 m4/log10l.m4                    | 87 +++++++++++++++++++++++++++++++++--------
 4 files changed, 82 insertions(+), 18 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 98702e2..00516b2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2019-01-20  Bruno Haible  <bruno@clisp.org>
 
+	log10l: Work around inaccurate implementation on NetBSD.
+	* m4/log10l.m4 (gl_FUNC_LOG10L_WORKS): Add test for a certain accuracy.
+	* lib/log10l.c: Comment out too simplistic override.
+	* doc/posix-functions/log10l.texi: Mention the NetBSD bug.
+
+2019-01-20  Bruno Haible  <bruno@clisp.org>
+
 	logl: Work around inaccurate implementation on NetBSD.
 	* m4/logl.m4 (gl_FUNC_LOGL_WORKS): Add test for a certain accuracy.
 	* lib/logl.c: Comment out unused code.
diff --git a/doc/posix-functions/log10l.texi b/doc/posix-functions/log10l.texi
index b26a249..ac42644 100644
--- a/doc/posix-functions/log10l.texi
+++ b/doc/posix-functions/log10l.texi
@@ -26,6 +26,10 @@ IRIX 6.5.
 @item
 This function returns an unnormalized positive infinity for a positive infinite argument on some platforms:
 IRIX 6.5.
+@item
+This function produces results which are accurate to only 16 digits on some
+platforms:
+NetBSD 8.0.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/lib/log10l.c b/lib/log10l.c
index 765d485..4ac6085 100644
--- a/lib/log10l.c
+++ b/lib/log10l.c
@@ -27,7 +27,7 @@ log10l (long double x)
   return log10 (x);
 }
 
-#elif HAVE_LOG10L
+#elif 0 /* was: HAVE_LOG10L */
 
 # include <float.h>
 
diff --git a/m4/log10l.m4 b/m4/log10l.m4
index af0afaf..80835f6 100644
--- a/m4/log10l.m4
+++ b/m4/log10l.m4
@@ -1,4 +1,4 @@
-# log10l.m4 serial 5
+# log10l.m4 serial 6
 dnl Copyright (C) 2011-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -60,6 +60,7 @@ dnl 0xFFF00000000000007FF0000000000000, should be
 dnl 0xFFF00000000000000000000000000000.
 dnl On AIX 5.1, log10l(-0.0L) is finite if it's not the first log10l call
 dnl in the program.
+dnl On NetBSD 8.0, the result is accurate to only 16 digits.
 AC_DEFUN([gl_FUNC_LOG10L_WORKS],
 [
   AC_REQUIRE([AC_PROG_CC])
@@ -68,36 +69,88 @@ AC_DEFUN([gl_FUNC_LOG10L_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>
-#ifndef log10l /* for AIX */
+/* 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
+#undef log10l /* for AIX */
 extern
 #ifdef __cplusplus
 "C"
 #endif
 long double log10l (long double);
-#endif
-volatile long double x;
-long double y;
-int main ()
+static long double dummy (long double x) { return 0; }
+volatile long double gx;
+long double gy;
+int main (int argc, char *argv[])
 {
+  long double (* volatile my_log10l) (long double) = argc ? log10l : dummy;
+  int result = 0;
   /* Dummy call, to trigger the AIX 5.1 bug.  */
-  x = 0.6L;
-  y = log10l (x);
+  gx = 0.6L;
+  gy = log10l (gx);
   /* This test fails on AIX 5.1, IRIX 6.5, OSF/1 5.1.  */
-  x = -0.0L;
-  y = log10l (x);
-  if (!(y + y == y))
-    return 1;
-  return 0;
+  {
+    gx = -0.0L;
+    gy = log10l (gx);
+    if (!(gy + gy == gy))
+      result |= 1;
+  }
+  /* This test fails on NetBSD 8.0.  */
+  {
+    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 = 7.90097792256024576L;
+    long double err = (my_log10l (x) + my_log10l (1.0L / x)) * TWO_LDBL_MANT_DIG;
+    if (!(err >= -100.0L && err <= 100.0L))
+      result |= 2;
+  }
+  return result;
 }
 ]])],
         [gl_cv_func_log10l_works=yes],
         [gl_cv_func_log10l_works=no],
         [case "$host_os" in
-           aix* | irix* | osf*) gl_cv_func_log10l_works="guessing no" ;;
-                                # Guess yes on native Windows.
-           mingw*)              gl_cv_func_log10l_works="guessing yes" ;;
-           *)                   gl_cv_func_log10l_works="guessing yes" ;;
+                          # Guess yes on glibc systems.
+           *-gnu* | gnu*) gl_cv_func_log10l_works="guessing yes" ;;
+                          # Guess yes on native Windows.
+           mingw*)        gl_cv_func_log10l_works="guessing yes" ;;
+                          # If we don't know, assume the worst.
+           *)             gl_cv_func_log10l_works="guessing no" ;;
          esac
         ])
     ])
-- 
2.7.4


[-- Attachment #7: 0006-rintl-Override-broken-implementation-on-NetBSD.patch --]
[-- Type: text/x-patch, Size: 7611 bytes --]

From 5b490ef07f257a5dd41fc0b351c1a387b8a8f89c Mon Sep 17 00:00:00 2001
From: Bruno Haible <bruno@clisp.org>
Date: Mon, 21 Jan 2019 00:33:28 +0100
Subject: [PATCH 6/6] rintl: Override broken implementation on NetBSD.

* lib/math.in.h (rintl): Test also REPLACE_RINTL.
* m4/rintl.m4 (gl_FUNC_RINTL): Add test for negative arguments. Set
REPLACE_RINTL.
* m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize REPLACE_RINTL.
* modules/math (Makefile.in): Substitute REPLACE_RINTL.
* modules/rintl (Depends-on, configure.ac): Test REPLACE_RINTL.
* doc/posix-functions/rintl.texi: Mention the NetBSD bug.
---
 ChangeLog                      | 11 ++++++++
 doc/posix-functions/rintl.texi |  3 +++
 lib/math.in.h                  | 13 ++++++++--
 m4/math_h.m4                   |  3 ++-
 m4/rintl.m4                    | 58 +++++++++++++++++++++++++++++++++++++++---
 modules/math                   |  1 +
 modules/rintl                  |  4 +--
 7 files changed, 85 insertions(+), 8 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 00516b2..3f40cc4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2019-01-20  Bruno Haible  <bruno@clisp.org>
 
+	rintl: Override broken implementation on NetBSD.
+	* lib/math.in.h (rintl): Test also REPLACE_RINTL.
+	* m4/rintl.m4 (gl_FUNC_RINTL): Add test for negative arguments. Set
+	REPLACE_RINTL.
+	* m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize REPLACE_RINTL.
+	* modules/math (Makefile.in): Substitute REPLACE_RINTL.
+	* modules/rintl (Depends-on, configure.ac): Test REPLACE_RINTL.
+	* doc/posix-functions/rintl.texi: Mention the NetBSD bug.
+
+2019-01-20  Bruno Haible  <bruno@clisp.org>
+
 	log10l: Work around inaccurate implementation on NetBSD.
 	* m4/log10l.m4 (gl_FUNC_LOG10L_WORKS): Add test for a certain accuracy.
 	* lib/log10l.c: Comment out too simplistic override.
diff --git a/doc/posix-functions/rintl.texi b/doc/posix-functions/rintl.texi
index d843544..26f50f5 100644
--- a/doc/posix-functions/rintl.texi
+++ b/doc/posix-functions/rintl.texi
@@ -11,6 +11,9 @@ Portability problems fixed by Gnulib:
 @item
 This function is missing on some platforms:
 FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 9, Cygwin 1.5.x, MSVC 9, Interix 3.5, BeOS, Android 4.4.
+@item
+This function produces wrong results for negative numbers on some platforms:
+NetBSD 8.0.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/lib/math.in.h b/lib/math.in.h
index 270caaf..aa03ea3 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -1845,10 +1845,19 @@ _GL_WARN_ON_USE (rint, "rint is unportable - "
 #endif
 
 #if @GNULIB_RINTL@
-# if !@HAVE_RINTL@
+# if @REPLACE_RINTL@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef rintl
+#   define rintl rpl_rintl
+#  endif
+_GL_FUNCDECL_RPL (rintl, long double, (long double x));
+_GL_CXXALIAS_RPL (rintl, long double, (long double x));
+# else
+#  if !@HAVE_RINTL@
 _GL_FUNCDECL_SYS (rintl, long double, (long double x));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (rintl, long double, (long double x));
+# endif
 _GL_CXXALIASWARN (rintl);
 #elif defined GNULIB_POSIXCHECK
 # undef rintl
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index bbbe5d4..3d5af84 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,4 +1,4 @@
-# math_h.m4 serial 118
+# math_h.m4 serial 119
 dnl Copyright (C) 2007-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -320,6 +320,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   REPLACE_REMAINDER=0;         AC_SUBST([REPLACE_REMAINDER])
   REPLACE_REMAINDERF=0;        AC_SUBST([REPLACE_REMAINDERF])
   REPLACE_REMAINDERL=0;        AC_SUBST([REPLACE_REMAINDERL])
+  REPLACE_RINTL=0;             AC_SUBST([REPLACE_RINTL])
   REPLACE_ROUND=0;             AC_SUBST([REPLACE_ROUND])
   REPLACE_ROUNDF=0;            AC_SUBST([REPLACE_ROUNDF])
   REPLACE_ROUNDL=0;            AC_SUBST([REPLACE_ROUNDL])
diff --git a/m4/rintl.m4 b/m4/rintl.m4
index fc40a5b..6683119 100644
--- a/m4/rintl.m4
+++ b/m4/rintl.m4
@@ -1,4 +1,4 @@
-# rintl.m4 serial 4
+# rintl.m4 serial 5
 dnl Copyright (C) 2011-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -14,9 +14,61 @@ AC_DEFUN([gl_FUNC_RINTL],
 
   dnl Determine RINTL_LIBM.
   gl_MATHFUNC([rintl], [long double], [(long double)])
-  if test $gl_cv_func_rintl_no_libm = no \
-     && test $gl_cv_func_rintl_in_libm = no; then
+  if test $gl_cv_func_rintl_no_libm = yes \
+     || test $gl_cv_func_rintl_in_libm = yes; then
+    if test $REPLACE_RINTL = 0; then
+      AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+      AC_CACHE_CHECK([whether rintl works],
+        [gl_cv_func_rintl_works],
+        [
+          save_LIBS="$LIBS"
+          LIBS="$LIBS $RINTL_LIBM"
+          AC_RUN_IFELSE(
+            [AC_LANG_SOURCE([[
+#include <math.h>
+#undef rintl
+extern
+#ifdef __cplusplus
+"C"
+#endif
+long double rintl (long double);
+static long double dummy (long double x) { return 0; }
+int main (int argc, char *argv[])
+{
+  long double (* volatile my_rintl) (long double) = argc ? rintl : dummy;
+  int result = 0;
+  /* This test fails on NetBSD 8.0.  */
+  {
+    volatile long double x = -0.3L;
+    long double y = my_rintl (x);
+    if (!(y == 0.0L))
+      result |= 1;
+  }
+  return result;
+}
+            ]])],
+            [gl_cv_func_rintl_works=yes],
+            [gl_cv_func_rintl_works=no],
+            [case "$host_os" in
+                              # Guess yes on glibc systems.
+               *-gnu* | gnu*) gl_cv_func_rintl_works="guessing yes" ;;
+                              # Guess yes on native Windows.
+               mingw*)        gl_cv_func_rintl_works="guessing yes" ;;
+                              # If we don't know, assume the worst.
+               *)             gl_cv_func_rintl_works="guessing no" ;;
+             esac
+            ])
+          LIBS="$save_LIBS"
+        ])
+      case "$gl_cv_func_rintl_works" in
+        *yes) ;;
+        *) REPLACE_RINTL=1 ;;
+      esac
+    fi
+  else
     HAVE_RINTL=0
+  fi
+  if test $HAVE_RINTL = 0 || test $REPLACE_RINTL = 1; then
     dnl Find libraries needed to link lib/rintl.c.
     if test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1; then
       AC_REQUIRE([gl_FUNC_RINT])
diff --git a/modules/math b/modules/math
index 1f23a17..0cdf885 100644
--- a/modules/math
+++ b/modules/math
@@ -290,6 +290,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
 	      -e 's|@''REPLACE_REMAINDER''@|$(REPLACE_REMAINDER)|g' \
 	      -e 's|@''REPLACE_REMAINDERF''@|$(REPLACE_REMAINDERF)|g' \
 	      -e 's|@''REPLACE_REMAINDERL''@|$(REPLACE_REMAINDERL)|g' \
+	      -e 's|@''REPLACE_RINTL''@|$(REPLACE_RINTL)|g' \
 	      -e 's|@''REPLACE_ROUND''@|$(REPLACE_ROUND)|g' \
 	      -e 's|@''REPLACE_ROUNDF''@|$(REPLACE_ROUNDF)|g' \
 	      -e 's|@''REPLACE_ROUNDL''@|$(REPLACE_ROUNDL)|g' \
diff --git a/modules/rintl b/modules/rintl
index 0ca3f44..cedabfd 100644
--- a/modules/rintl
+++ b/modules/rintl
@@ -10,11 +10,11 @@ m4/mathfunc.m4
 Depends-on:
 math
 extensions
-rint            [test $HAVE_RINTL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
+rint            [{ test $HAVE_RINTL = 0 || test $REPLACE_RINTL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
 
 configure.ac:
 gl_FUNC_RINTL
-if test $HAVE_RINTL = 0; then
+if test $HAVE_RINTL = 0 || test $REPLACE_RINTL = 1; then
   AC_LIBOBJ([rintl])
 fi
 gl_MATH_MODULE_INDICATOR([rintl])
-- 
2.7.4


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2019-01-20 23:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-20 23:39 work around inaccurate 'long double' math functions on NetBSD Bruno Haible

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).