[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
isfinite: fix bugs
From: |
Bruno Haible |
Subject: |
isfinite: fix bugs |
Date: |
Sun, 27 Apr 2008 14:11:56 +0200 |
User-agent: |
KMail/1.5.4 |
On mingw, the test-isfinite test failed:
test-isfinite.c:169: assertion failed
FAIL: test-isfinite.exe
And after adding the same tests as for isnan(long double) - namely, that
signalling NaNs, pseudo-denormals and the like be considered as NaNs, not as
finite numbers - the test failed also Linux/x86, MacOS X/x86_64. Linux/ia64,
etc.
I changed the autoconf macros to activate the replacements in these cases;
this fixes the test failures.
2008-04-27 Bruno Haible <address@hidden>
Fix 'isfinite' on x86, x86_64, ia64 platforms.
* tests/test-isfinite.c (test_isfinitel): Also test the behavior on
argument that lie outside the IEEE 854 domain.
* m4/isfinite.m4 (gl_ISFINITEL_WORKS): New macro.
(gl_ISFINITE): Use it.
* doc/posix-functions/isfinite.texi: Document the fixed bugs.
*** doc/posix-functions/isfinite.texi.orig 2008-04-27 14:03:17.000000000
+0200
--- doc/posix-functions/isfinite.texi 2008-04-27 14:02:50.000000000 +0200
***************
*** 11,16 ****
--- 11,26 ----
@item
This macro is missing on some platforms:
MacOS X 10.3, OpenBSD 3.8, AIX 5.1, IRIX 6.5, OSF/1 5.1, Solaris 10, Interix
3.5.
+ @item
+ This macro incorrectly yields true for some @samp{double} arguments, on some
+ platforms:
+ Linux/ia64 (signalling NaNs).
+ @item
+ This macro incorrectly yields true for some @samp{long double} arguments, on
+ some platforms:
+ x86 (pseudo-zeroes, unnormalized numbers, pseudo-denormals),
+ x86_64 (pseudo-denormals),
+ ia64 (pseudo-NaN, pseudo-Infinity, pseudo-zeroes, unnormalized numbers,
pseudo-denormals).
@end itemize
Portability problems not fixed by Gnulib:
*** m4/isfinite.m4.orig 2008-04-27 14:03:17.000000000 +0200
--- m4/isfinite.m4 2008-04-27 13:48:41.000000000 +0200
***************
*** 1,5 ****
! # isfinite.m4 serial 2
! dnl Copyright (C) 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
--- 1,5 ----
! # isfinite.m4 serial 3
! dnl Copyright (C) 2007-2008 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
***************
*** 12,17 ****
--- 12,28 ----
AC_CHECK_DECLS([isfinite], , , [#include <math.h>])
if test "$ac_cv_have_decl_isfinite" = yes; then
gl_CHECK_MATH_LIB([ISFINITE_LIBM], [x = isfinite (x);])
+ if test "$ISFINITE_LIBM" != missing; then
+ dnl Test whether isfinite() on 'long double' works.
+ gl_ISFINITEL_WORKS
+ case "$gl_cv_func_isfinitel_works" in
+ *yes) ;;
+ *) ISFINITE_LIBM=missing;;
+ esac
+ dnl Also, isfinite() on 'double' does not work on Linux/ia64 (because of
+ dnl signalling NaNs). But this does not have to be tested, since
+ dnl isfinite(long double) also does not work in this situation.
+ fi
fi
if test "$ac_cv_have_decl_isfinite" != yes ||
test "$ISFINITE_LIBM" = missing; then
***************
*** 22,24 ****
--- 33,149 ----
AC_SUBST([REPLACE_ISFINITE])
AC_SUBST([ISFINITE_LIBM])
])
+
+ dnl Test whether isfinite() on 'long double' recognizes all numbers which are
+ dnl neither finite nor infinite. This test fails e.g. on i686, x86_64, ia64,
+ dnl because of
+ dnl - pseudo-denormals on x86_64,
+ dnl - pseudo-zeroes, unnormalized numbers, and pseudo-denormals on i686,
+ dnl - pseudo-NaN, pseudo-Infinity, pseudo-zeroes, unnormalized numbers, and
+ dnl pseudo-denormals on ia64.
+ AC_DEFUN([gl_ISFINITEL_WORKS],
+ [
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_C_BIGENDIAN])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_CACHE_CHECK([whether isfinite(long double) works],
[gl_cv_func_isfinitel_works],
+ [
+ AC_TRY_RUN([
+ #include <float.h>
+ #include <limits.h>
+ #include <math.h>
+ #define NWORDS \
+ ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+ typedef union { unsigned int word[NWORDS]; long double value; }
+ memory_long_double;
+ int main ()
+ {
+ memory_long_double m;
+ unsigned int i;
+
+ /* The isfinite macro should be immune against changes in the sign bit and
+ in the mantissa bits. The xor operation twiddles a bit that can only be
+ a sign bit or a mantissa bit (since the exponent never extends to
+ bit 31). */
+ m.value = 0.0L / 0.0L;
+ m.word[NWORDS / 2] ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT
- 1);
+ for (i = 0; i < NWORDS; i++)
+ m.word[i] |= 1;
+ if (isfinite (m.value))
+ return 1;
+
+ #if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ ||
defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 ||
defined _M_IX86 || defined _X86_))
+ /* Representation of an 80-bit 'long double' as an initializer for a sequence
+ of 'unsigned int' words. */
+ # ifdef WORDS_BIGENDIAN
+ # define LDBL80_WORDS(exponent,manthi,mantlo) \
+ { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \
+ ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16), \
+ (unsigned int) (mantlo) << 16 \
+ }
+ # else
+ # define LDBL80_WORDS(exponent,manthi,mantlo) \
+ { mantlo, manthi, exponent }
+ # endif
+ { /* Quiet NaN. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+ if (isfinite (x.value))
+ return 1;
+ }
+ {
+ /* Signalling NaN. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+ if (isfinite (x.value))
+ return 1;
+ }
+ /* The isfinite macro should recognize Pseudo-NaNs, Pseudo-Infinities,
+ Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+ Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+ Application Architecture.
+ Table 5-2 "Floating-Point Register Encodings"
+ Figure 5-6 "Memory to Floating-Point Register Data Translation"
+ */
+ { /* Pseudo-NaN. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+ if (isfinite (x.value))
+ return 1;
+ }
+ { /* Pseudo-Infinity. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+ if (isfinite (x.value))
+ return 1;
+ }
+ { /* Pseudo-Zero. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+ if (isfinite (x.value))
+ return 1;
+ }
+ { /* Unnormalized number. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+ if (isfinite (x.value))
+ return 1;
+ }
+ { /* Pseudo-Denormal. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+ if (isfinite (x.value))
+ return 1;
+ }
+ #endif
+
+ return 0;
+ }], [gl_cv_func_isfinitel_works=yes], [gl_cv_func_isfinitel_works=no],
+ [case "$host_cpu" in
+ # Guess no on ia64, x86_64, i386.
+ ia64 | x86_64 | i*86) gl_cv_func_isnanl_works="guessing no";;
+ *) gl_cv_func_isnanl_works="guessing yes";;
+ esac
+ ])
+ ])
+ ])
*** tests/test-isfinite.c.orig 2008-04-27 14:03:17.000000000 +0200
--- tests/test-isfinite.c 2008-04-27 13:18:38.000000000 +0200
***************
*** 131,136 ****
--- 131,141 ----
static void
test_isfinitel ()
{
+ #define NWORDS \
+ ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned
int))
+ typedef union { unsigned int word[NWORDS]; long double value; }
+ memory_long_double;
+
/* Zero. */
ASSERT (isfinite (0.0L));
/* Subnormal values. */
***************
*** 148,161 ****
ASSERT (!isfinite (-1.0L / 0.0L));
/* Quiet NaN. */
ASSERT (!isfinite (zerol / zerol));
#if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
/* A bit pattern that is different from a Quiet NaN. With a bit of luck,
it's a Signalling NaN. */
{
- #define NWORDS \
- ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned
int))
- typedef union { unsigned int word[NWORDS]; long double value; }
- memory_long_double;
memory_long_double m;
m.value = zerol / zerol;
# if LDBL_EXPBIT0_BIT > 0
--- 153,163 ----
ASSERT (!isfinite (-1.0L / 0.0L));
/* Quiet NaN. */
ASSERT (!isfinite (zerol / zerol));
+
#if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
/* A bit pattern that is different from a Quiet NaN. With a bit of luck,
it's a Signalling NaN. */
{
memory_long_double m;
m.value = zerol / zerol;
# if LDBL_EXPBIT0_BIT > 0
***************
*** 167,175 ****
m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
|= (unsigned int) 1 << LDBL_EXPBIT0_BIT;
ASSERT (!isfinite (m.value));
- #undef NWORDS
}
#endif
}
int
--- 169,236 ----
m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
|= (unsigned int) 1 << LDBL_EXPBIT0_BIT;
ASSERT (!isfinite (m.value));
}
#endif
+
+ #if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ ||
defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 ||
defined _M_IX86 || defined _X86_))
+ /* Representation of an 80-bit 'long double' as an initializer for a sequence
+ of 'unsigned int' words. */
+ # ifdef WORDS_BIGENDIAN
+ # define LDBL80_WORDS(exponent,manthi,mantlo) \
+ { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \
+ ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16), \
+ (unsigned int) (mantlo) << 16 \
+ }
+ # else
+ # define LDBL80_WORDS(exponent,manthi,mantlo) \
+ { mantlo, manthi, exponent }
+ # endif
+ { /* Quiet NaN. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+ ASSERT (!isfinite (x.value));
+ }
+ {
+ /* Signalling NaN. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+ ASSERT (!isfinite (x.value));
+ }
+ /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+ Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+ Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+ Application Architecture.
+ Table 5-2 "Floating-Point Register Encodings"
+ Figure 5-6 "Memory to Floating-Point Register Data Translation"
+ */
+ { /* Pseudo-NaN. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+ ASSERT (!isfinite (x.value));
+ }
+ { /* Pseudo-Infinity. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+ ASSERT (!isfinite (x.value));
+ }
+ { /* Pseudo-Zero. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+ ASSERT (!isfinite (x.value));
+ }
+ { /* Unnormalized number. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+ ASSERT (!isfinite (x.value));
+ }
+ { /* Pseudo-Denormal. */
+ static memory_long_double x =
+ { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+ ASSERT (!isfinite (x.value));
+ }
+ #endif
+
+ #undef NWORDS
}
int
- isfinite: fix bugs,
Bruno Haible <=