On Linux/ia64 (RHEL 5.11, a glibc 2.5 system), I see this test failure: ../../gltests/test-isfinite.c:174: assertion '!isfinite (m.value)' failed FAIL test-isfinite (exit status: 134)
It's a bug in the isfinite() macro from glibc. From 2008-04-27 to 2015-02-21, this bug was worked around, due to the configure test checking whether isfinite(long double) works... no But since 2015-02-21, this configure test produces checking whether isfinite(long double) works... yes The patch below fixes it, by strengthening the configure test, so that it again produces checking whether isfinite(long double) works... no For this purpose, it uses a value that gdb prints as {word = {0, 1073741825, 327679, 536870912}, value = -nan(0x4000000100000000)} 2023-10-08 Bruno Haible <br...@clisp.org> isfinite: Work around a bug with 'long double' in glibc 2.5/ia64. * m4/isfinite.m4 (gl_ISFINITEL_WORKS): Require gl_LONG_DOUBLE_EXPONENT_LOCATION. Test also another NaN value. * modules/isfinite (Files): Add m4/exponentl.m4. * doc/posix-functions/isfinite.texi: Mention also a 'long double' problem on ia64. diff --git a/doc/posix-functions/isfinite.texi b/doc/posix-functions/isfinite.texi index d6ea43f818..8278c9449a 100644 --- a/doc/posix-functions/isfinite.texi +++ b/doc/posix-functions/isfinite.texi @@ -12,9 +12,9 @@ This macro is missing on some platforms: macOS 11.1, OpenBSD 6.7, AIX 5.1, IRIX 6.5, Solaris 11.4. @item -This macro incorrectly yields true for some @samp{double} arguments, on some -platforms: -Linux/ia64 (signalling NaNs). +This macro incorrectly yields true for some @samp{double} and for some +@samp{long double} arguments, on some platforms: +Linux/ia64 (NaNs). @end itemize Portability problems not fixed by Gnulib: diff --git a/m4/isfinite.m4 b/m4/isfinite.m4 index 6170890d25..47e945a0ce 100644 --- a/m4/isfinite.m4 +++ b/m4/isfinite.m4 @@ -1,4 +1,4 @@ -# isfinite.m4 serial 18 +# isfinite.m4 serial 19 dnl Copyright (C) 2007-2023 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -46,6 +46,7 @@ AC_DEFUN([gl_ISFINITEL_WORKS] [ AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([gl_BIGENDIAN]) + AC_REQUIRE([gl_LONG_DOUBLE_EXPONENT_LOCATION]) AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE]) AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles AC_CACHE_CHECK([whether isfinite(long double) works], [gl_cv_func_isfinitel_works], @@ -87,6 +88,31 @@ AC_DEFUN([gl_ISFINITEL_WORKS] m.word[i] |= 1; if (isfinite (m.value)) result |= 1; + +#if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT + /* Another NaN, more precisely crafted. */ + m.value = NaNl (); + #if defined __powerpc__ && LDBL_MANT_DIG == 106 + /* This is PowerPC "double double", a pair of two doubles. Inf and NaN are + represented as the corresponding 64-bit IEEE values in the first double; + the second is ignored. Manipulate only the first double. */ + #define HNWORDS \ + ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + #else + #define HNWORDS NWORDS + #endif + #if LDBL_EXPBIT0_BIT > 0 + m.word[LDBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (LDBL_EXPBIT0_BIT - 1); + #else + m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < HNWORDS / 2 ? 1 : - 1)] + ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1); + #endif + m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < HNWORDS / 2 ? 1 : - 1)] + |= (unsigned int) 1 << LDBL_EXPBIT0_BIT; + #undef HNWORDS + if (isfinite (m.value)) + result |= 1; +#endif } #if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) && !HAVE_SAME_LONG_DOUBLE_AS_DOUBLE diff --git a/modules/isfinite b/modules/isfinite index 9933109cb0..0e801457bd 100644 --- a/modules/isfinite +++ b/modules/isfinite @@ -5,6 +5,7 @@ Files: lib/isfinite.c m4/isfinite.m4 m4/check-math-lib.m4 +m4/exponentl.m4 Depends-on: math