bug-gnulib
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]