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])
