On NetBSD 10.0, the recently enhanced sinl() test fails:

../../gltests/test-sinl.c:52: assertion 'y >= -0.000000000000000004000000000L 
&& y <= -0.000000000000000003999999999L' failed

In the debugger, I see that the value is
y = -4.00000000000000028617e-18

In other words, the inequality |sin(x)| <= |x| is not fulfilled.

This patch works around the bug.


2025-12-04  Bruno Haible  <[email protected]>

        sinl: Work around NetBSD 10.0 bug.
        * lib/math.in.h (sinl): Consider REPLACE_SINL.
        * m4/sinl.m4 (gl_FUNC_SINL): Test whether sinl works. Set REPLACE_SINL
        to 1 if not.
        * m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize REPLACE_SINL.
        * modules/math-h (Makefile.am): Substitute REPLACE_SINL.
        * modules/sinl (configure.ac): Consider REPLACE_SINL.
        * doc/posix-functions/sinl.texi: Mention the NetBSD bug.

diff --git a/doc/posix-functions/sinl.texi b/doc/posix-functions/sinl.texi
index b6545296ce..82b0158985 100644
--- a/doc/posix-functions/sinl.texi
+++ b/doc/posix-functions/sinl.texi
@@ -15,6 +15,11 @@
 @item
 This function is only defined as a macro with arguments on some platforms:
 MSVC 14.
+@item
+This function returns a value that is larger that the argument,
+for some positive arguments,
+on some platforms:
+NetBSD 10.0.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/lib/math.in.h b/lib/math.in.h
index e456f02333..53450d4c60 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -2175,11 +2175,20 @@ _GL_WARN_ON_USE (sinf, "sinf is unportable - "
 #endif
 
 #if @GNULIB_SINL@
-# if !@HAVE_SINL@ || !@HAVE_DECL_SINL@
-#  undef sinl
+# if @REPLACE_SINL@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef sinl
+#   define sinl rpl_sinl
+#  endif
+_GL_FUNCDECL_RPL (sinl, long double, (long double x), );
+_GL_CXXALIAS_RPL (sinl, long double, (long double x));
+# else
+#  if !@HAVE_SINL@ || !@HAVE_DECL_SINL@
+#   undef sinl
 _GL_FUNCDECL_SYS (sinl, long double, (long double x), );
-# endif
+#  endif
 _GL_CXXALIAS_SYS (sinl, long double, (long double x));
+# endif
 # if __GLIBC__ >= 2
 _GL_CXXALIASWARN (sinl);
 # endif
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index fa2ace3fe4..805cca471d 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,5 +1,5 @@
 # math_h.m4
-# serial 141
+# serial 142
 dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -396,6 +396,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS]
   REPLACE_SIGNBIT_USING_BUILTINS=0; AC_SUBST([REPLACE_SIGNBIT_USING_BUILTINS])
   REPLACE_SINF=0;                   AC_SUBST([REPLACE_SINF])
   REPLACE_SINHF=0;                  AC_SUBST([REPLACE_SINHF])
+  REPLACE_SINL=0;                   AC_SUBST([REPLACE_SINL])
   REPLACE_SQRTF=0;                  AC_SUBST([REPLACE_SQRTF])
   REPLACE_SQRTL=0;                  AC_SUBST([REPLACE_SQRTL])
   REPLACE_TANF=0;                   AC_SUBST([REPLACE_TANF])
diff --git a/m4/sinl.m4 b/m4/sinl.m4
index 802528a355..9d9fcfb451 100644
--- a/m4/sinl.m4
+++ b/m4/sinl.m4
@@ -1,5 +1,5 @@
 # sinl.m4
-# serial 10
+# serial 11
 dnl Copyright (C) 2010-2025 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,9 +60,65 @@ AC_DEFUN([gl_FUNC_SINL]
     dnl Also check whether it's declared.
     dnl Mac OS X 10.3 has sinl() in libc but doesn't declare it in <math.h>.
     AC_CHECK_DECL([sinl], , [HAVE_DECL_SINL=0], [[#include <math.h>]])
+    if test $REPLACE_SINL = 0; then
+      AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+      AC_CACHE_CHECK([whether sinl works],
+        [gl_cv_func_sinl_works],
+        [
+          saved_LIBS="$LIBS"
+          LIBS="$LIBS $SINL_LIBM"
+          AC_RUN_IFELSE(
+            [AC_LANG_SOURCE([[
+#ifndef __NO_MATH_INLINES
+# define __NO_MATH_INLINES 1 /* for glibc */
+#endif
+#include <math.h>
+#undef sinl
+extern
+#ifdef __cplusplus
+"C"
+#endif
+long double sinl (long double);
+static long double dummy (long double x) { return 0; }
+int main (int argc, char *argv[])
+{
+  long double (* volatile my_sinl) (long double) = argc ? sinl : dummy;
+  int result = 0;
+  /* On NetBSD 10.0 the system's native sinl() is buggy:
+     it does not obey the inequality |sin(x)| <= |x|.  */
+  {
+    volatile long double x = 0.000000000000000004L;
+    if (my_sinl (x) > x)
+      result |= 1;
+  }
+  return result;
+}
+            ]])],
+            [gl_cv_func_sinl_works=yes],
+            [gl_cv_func_sinl_works=no],
+            [case "$host_os" in
+                                   # Guess yes on glibc systems.
+               *-gnu* | gnu*)      gl_cv_func_sinl_works="guessing yes" ;;
+                                   # Guess yes on musl systems.
+               *-musl* | midipix*) gl_cv_func_sinl_works="guessing yes" ;;
+                                   # Guess yes on native Windows.
+               mingw* | windows*)  gl_cv_func_sinl_works="guessing yes" ;;
+                                   # If we don't know, obey 
--enable-cross-guesses.
+               *)                  
gl_cv_func_sinl_works="$gl_cross_guess_normal" ;;
+             esac
+            ])
+          LIBS="$saved_LIBS"
+        ])
+      case "$gl_cv_func_sinl_works" in
+        *yes) ;;
+        *) REPLACE_SINL=1 ;;
+      esac
+    fi
   else
     HAVE_DECL_SINL=0
     HAVE_SINL=0
+  fi
+  if test $HAVE_SINL = 0 || test $REPLACE_SINL = 1; then
     dnl Find libraries needed to link lib/sinl.c, lib/sincosl.c, lib/trigl.c.
     if test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1; then
       AC_REQUIRE([gl_FUNC_SIN])
diff --git a/modules/math-h b/modules/math-h
index 5d0697f4b1..da3214ad4e 100644
--- a/modules/math-h
+++ b/modules/math-h
@@ -352,6 +352,7 @@ math.h: math.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H) $(
              -e 
's|@''REPLACE_SIGNBIT_USING_BUILTINS''@|$(REPLACE_SIGNBIT_USING_BUILTINS)|g' \
              -e 's|@''REPLACE_SINF''@|$(REPLACE_SINF)|g' \
              -e 's|@''REPLACE_SINHF''@|$(REPLACE_SINHF)|g' \
+             -e 's|@''REPLACE_SINL''@|$(REPLACE_SINL)|g' \
              -e 's|@''REPLACE_SQRTF''@|$(REPLACE_SQRTF)|g' \
              -e 's|@''REPLACE_SQRTL''@|$(REPLACE_SQRTL)|g' \
              -e 's|@''REPLACE_TANF''@|$(REPLACE_TANF)|g' \
diff --git a/modules/sinl b/modules/sinl
index f6a255067f..bc63bf8d94 100644
--- a/modules/sinl
+++ b/modules/sinl
@@ -11,15 +11,16 @@ m4/sinl.m4
 Depends-on:
 math-h
 extensions
-sin             [test $HAVE_SINL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE 
= 1]
-float-h         [test $HAVE_SINL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE 
= 0]
-isnanl          [test $HAVE_SINL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE 
= 0]
-floor           [test $HAVE_SINL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE 
= 0]
-floorl          [test $HAVE_SINL = 0 && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE 
= 0]
+sin             [{ test $HAVE_SINL = 0 || test $REPLACE_SINL = 1; } && test 
$HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
+float-h         [{ test $HAVE_SINL = 0 || test $REPLACE_SINL = 1; } && test 
$HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+isnanl          [{ test $HAVE_SINL = 0 || test $REPLACE_SINL = 1; } && test 
$HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+floor           [{ test $HAVE_SINL = 0 || test $REPLACE_SINL = 1; } && test 
$HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
+floorl          [{ test $HAVE_SINL = 0 || test $REPLACE_SINL = 1; } && test 
$HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0]
 
 configure.ac:
 gl_FUNC_SINL
-gl_CONDITIONAL([GL_COND_OBJ_SINL], [test $HAVE_SINL = 0])
+gl_CONDITIONAL([GL_COND_OBJ_SINL],
+               [test $HAVE_SINL = 0 || test $REPLACE_SINL = 1])
 AM_COND_IF([GL_COND_OBJ_SINL], [
   if test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0; then
     AC_LIBOBJ([sincosl])




Reply via email to