bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

float, math: Fix 'int' to 'long double' conversion on Linux/SPARC64


From: Bruno Haible
Subject: float, math: Fix 'int' to 'long double' conversion on Linux/SPARC64
Date: Fri, 30 Sep 2011 21:08:24 +0200
User-agent: KMail/1.13.6 (Linux/2.6.37.6-0.5-desktop; KDE/4.6.0; x86_64; ; )

It started as a test failure on Linux/SPARC64:

  test-logl.c:42: assertion failed
  FAIL: test-logl

I tried to fix it by activating the gnulib replacement code for logl(). But
the bug persisted.

Debugging it in detail, it turned out to be a bug in the 'int' to 'long double'
conversion. The glibc provided function, that is invoked by the GCC generated
code, actually performs an 'unsigned int' to 'long double' conversion.

I've reported it at <http://sources.redhat.com/bugzilla/show_bug.cgi?id=13240>.
Here's the workaround for gnulib.


2011-09-30  Bruno Haible  <address@hidden>

        float, math: Fix 'int' to 'long double' conversion on Linux/SPARC64.
        * m4/float_h.m4 (gl_FLOAT_H): Test conversion from 'int' to
        'long double'. Set REPLACE_ITOLD.
        * lib/float.in.h (_Qp_itoq, _gl_float_fix_itold): New declarations.
        * lib/math.in.h (_Qp_itoq, _gl_math_fix_itold): New declarations.
        * lib/itold.c: New file.
        * modules/float (Files): Add lib/itold.c.
        (configure.ac): When REPLACE_ITOLD is 1, arrange to compile itold.c.
        (Makefile.am): Substitute REPLACE_ITOLD.
        * modules/math (Depends-on): Add float.
        (Makefile.am): Substitute REPLACE_ITOLD.
        * doc/posix-headers/float.texi: Mention problem on Linux/SPARC64.
        * doc/posix-headers/math.texi: Likewise.
        * doc/posix-functions/logl.texi: Likewise.

================================= lib/itold.c =================================
/* Replacement for 'int' to 'long double' conversion routine.
   Copyright (C) 2011 Free Software Foundation, Inc.
   Written by Bruno Haible <address@hidden>, 2011.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include <config.h>

/* Specification.  */
#include <float.h>

void
_Qp_itoq (long double *result, int a)
{
  /* Convert from 'int' to 'double', then from 'double' to 'long double'.  */
  *result = (double) a;
}
===============================================================================
--- doc/posix-functions/logl.texi.orig  Fri Sep 30 20:59:36 2011
+++ doc/posix-functions/logl.texi       Fri Sep 30 20:19:22 2011
@@ -17,6 +17,9 @@
 @item
 This function is not declared on some platforms:
 MacOS X 10.3.
address@hidden
+This function returns wrong results on some platforms:
+glibc 2.7 on Linux/SPARC64.
 @end itemize
 
 Portability problems not fixed by Gnulib:
--- doc/posix-headers/float.texi.orig   Fri Sep 30 20:59:36 2011
+++ doc/posix-headers/float.texi        Fri Sep 30 20:47:24 2011
@@ -8,6 +8,10 @@
 Portability problems fixed by Gnulib:
 @itemize
 @item
+The conversion from @code{int} to @code{long double} in incorrect on some
+platforms:
+glibc 2.7 on Linux/SPARC64.
address@hidden
 The values of @code{LDBL_*} macros are incorrect on some platforms:
 On OpenBSD 4.0, MirBSD 10, and BeOS, they are the same as the values of the
 @code{DBL_*} macros, although @samp{long double} is a larger type than
--- doc/posix-headers/math.texi.orig    Fri Sep 30 20:59:36 2011
+++ doc/posix-headers/math.texi Fri Sep 30 20:46:58 2011
@@ -8,6 +8,11 @@
 Portability problems fixed by Gnulib:
 @itemize
 @item
+The conversion from @code{int} to @code{long double} in incorrect on some
+platforms:
+glibc 2.7 on Linux/SPARC64.
+
address@hidden
 The macro @code{NAN} is not defined on some platforms:
 OpenBSD 4.0, AIX 5.1, IRIX 6.5, OSF/1 5.1.
 
--- lib/float.in.h.orig Fri Sep 30 20:59:36 2011
+++ lib/float.in.h      Fri Sep 30 20:51:41 2011
@@ -173,5 +173,16 @@
 # endif
 #endif
 
+#if @REPLACE_ITOLD@
+/* Pull in a function that fixes the 'int' to 'long double' conversion
+   of glibc 2.7.  */
+extern
+# ifdef __cplusplus
+"C"
+# endif
+void _Qp_itoq (long double *, int);
+static void (*_gl_float_fix_itold) (long double *, int) = _Qp_itoq;
+#endif
+
 #endif /* address@hidden@_FLOAT_H */
 #endif /* address@hidden@_FLOAT_H */
--- lib/math.in.h.orig  Fri Sep 30 20:59:36 2011
+++ lib/math.in.h       Fri Sep 30 20:51:32 2011
@@ -67,6 +67,14 @@
    : rpl_ ## func ## l (value))
 
 
+#if @REPLACE_ITOLD@
+/* Pull in a function that fixes the 'int' to 'long double' conversion
+   of glibc 2.7.  */
+_GL_EXTERN_C void _Qp_itoq (long double *, int);
+static void (*_gl_math_fix_itold) (long double *, int) = _Qp_itoq;
+#endif
+
+
 /* POSIX allows platforms that don't support NAN.  But all major
    machines in the past 15 years have supported something close to
    IEEE NaN, so we define this unconditionally.  We also must define
--- m4/float_h.m4.orig  Fri Sep 30 20:59:36 2011
+++ m4/float_h.m4       Fri Sep 30 20:59:16 2011
@@ -1,4 +1,4 @@
-# float_h.m4 serial 8
+# float_h.m4 serial 9
 dnl Copyright (C) 2007, 2009-2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -48,9 +48,51 @@
       fi
       ;;
   esac
+
+  dnl Test against glibc-2.7 Linux/SPARC64 bug.
+  REPLACE_ITOLD=0
+  AC_CACHE_CHECK([whether conversion from 'int' to 'long double' works],
+    [gl_cv_func_itold_works],
+    [
+      AC_RUN_IFELSE(
+        [AC_LANG_SOURCE([[
+int i = -1;
+volatile long double ld;
+int main ()
+{
+  ld += i * 1.0L;
+  if (ld > 0)
+    return 1;
+  return 0;
+}]])],
+        [gl_cv_func_itold_works=yes],
+        [gl_cv_func_itold_works=no],
+        [case "$host" in
+           sparc*-*-linux*)
+             AC_EGREP_CPP([yes],
+               [#if defined __LP64__ || defined __arch64__
+                yes
+                #endif],
+               [gl_cv_func_itold_works="guessing no"],
+               [gl_cv_func_itold_works="guessing yes"])
+             ;;
+           *) gl_cv_func_itold_works="guessing yes" ;;
+         esac
+        ])
+    ])
+  case "$gl_cv_func_itold_works" in
+    *no)
+      REPLACE_ITOLD=1
+      dnl We add the workaround to <float.h> but also to <math.h>,
+      dnl to increase the chances that the fix function gets pulled in.
+      FLOAT_H=float.h
+      ;;
+  esac
+
   if test -n "$FLOAT_H"; then
     gl_NEXT_HEADERS([float.h])
   fi
   AC_SUBST([FLOAT_H])
   AM_CONDITIONAL([GL_GENERATE_FLOAT_H], [test -n "$FLOAT_H"])
+  AC_SUBST([REPLACE_ITOLD])
 ])
--- modules/float.orig  Fri Sep 30 20:59:36 2011
+++ modules/float       Fri Sep 30 20:52:38 2011
@@ -4,6 +4,7 @@
 Files:
 lib/float.in.h
 lib/float.c
+lib/itold.c
 m4/float_h.m4
 
 Depends-on:
@@ -14,6 +15,9 @@
 if test $REPLACE_FLOAT_LDBL = 1; then
   AC_LIBOBJ([float])
 fi
+if test $REPLACE_ITOLD = 1; then
+  AC_LIBOBJ([itold])
+fi
 
 Makefile.am:
 BUILT_SOURCES += $(FLOAT_H)
@@ -29,6 +33,7 @@
              -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
              -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
              -e 's|@''NEXT_FLOAT_H''@|$(NEXT_FLOAT_H)|g' \
+             -e 's|@''REPLACE_ITOLD''@|$(REPLACE_ITOLD)|g' \
              < $(srcdir)/float.in.h; \
        } > address@hidden && \
        mv address@hidden $@
--- modules/math.orig   Fri Sep 30 20:59:36 2011
+++ modules/math        Fri Sep 30 20:52:41 2011
@@ -10,6 +10,7 @@
 snippet/arg-nonnull
 snippet/c++defs
 snippet/warn-on-use
+float
 
 configure.ac:
 gl_MATH_H
@@ -107,6 +108,7 @@
              -e 's|@''REPLACE_ISFINITE''@|$(REPLACE_ISFINITE)|g' \
              -e 's|@''REPLACE_ISINF''@|$(REPLACE_ISINF)|g' \
              -e 's|@''REPLACE_ISNAN''@|$(REPLACE_ISNAN)|g' \
+             -e 's|@''REPLACE_ITOLD''@|$(REPLACE_ITOLD)|g' \
              -e 's|@''REPLACE_LDEXPL''@|$(REPLACE_LDEXPL)|g' \
              -e 's|@''REPLACE_NAN''@|$(REPLACE_NAN)|g' \
              -e 's|@''REPLACE_ROUND''@|$(REPLACE_ROUND)|g' \

-- 
In memoriam Kelsang Namtso 
<http://en.wikipedia.org/wiki/Nangpa_La_shooting_incident>



reply via email to

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