changeset 8659:d6d05661430a

Use copysign when implementing signbit, if the libc has it already.
author Bruno Haible <bruno@clisp.org>
date Tue, 10 Apr 2007 21:38:36 +0000
parents d961c268d661
children f682656899d3
files ChangeLog lib/signbitd.c lib/signbitf.c lib/signbitl.c m4/signbit.m4
diffstat 5 files changed, 95 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2007-04-10  Paul Eggert  <eggert@cs.ucla.edu>
+            Bruno Haible  <bruno@clisp.org>
+
+	* m4/signbit.m4 (gl_SIGNBIT): When the sign bit position could not
+	be determined, test for availability of the copysignf, copysign,
+	copysignl functions.
+	* lib/signbitf.c (gl_signbitf): Use copysignf if available in libc.
+	* lib/signbitd.c (gl_signbitd): Use copysign if available in libc.
+	* lib/signbitl.c (gl_signbitl): Use copysignl if available in libc.
+
 2007-04-09  Eric Blake  <ebb9@byu.net>
 
 	* lib/stdio_.h [REPLACE_FFLUSH]: Declare rpl_fflush.
--- a/lib/signbitd.c
+++ b/lib/signbitd.c
@@ -30,11 +30,19 @@
 gl_signbitd (double arg)
 {
 #if defined DBL_SIGNBIT_WORD && defined DBL_SIGNBIT_BIT
+  /* The use of a union to extract the bits of the representation of a
+     'long double' is safe in practice, despite of the "aliasing rules" of
+     C99, because the GCC docs say
+       "Even with '-fstrict-aliasing', type-punning is allowed, provided the
+        memory is accessed through the union type."
+     and similarly for other compilers.  */
 # define NWORDS \
     ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
   union { double value; unsigned int word[NWORDS]; } m;
   m.value = arg;
   return (m.word[DBL_SIGNBIT_WORD] >> DBL_SIGNBIT_BIT) & 1;
+#elif HAVE_COPYSIGN_IN_LIBC
+  return copysign (1.0, arg) < 0;
 #else
   /* This does not do the right thing for NaN, but this is irrelevant for
      most use cases.  */
--- a/lib/signbitf.c
+++ b/lib/signbitf.c
@@ -30,11 +30,19 @@
 gl_signbitf (float arg)
 {
 #if defined FLT_SIGNBIT_WORD && defined FLT_SIGNBIT_BIT
+  /* The use of a union to extract the bits of the representation of a
+     'long double' is safe in practice, despite of the "aliasing rules" of
+     C99, because the GCC docs say
+       "Even with '-fstrict-aliasing', type-punning is allowed, provided the
+        memory is accessed through the union type."
+     and similarly for other compilers.  */
 # define NWORDS \
     ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
   union { float value; unsigned int word[NWORDS]; } m;
   m.value = arg;
   return (m.word[FLT_SIGNBIT_WORD] >> FLT_SIGNBIT_BIT) & 1;
+#elif HAVE_COPYSIGNF_IN_LIBC
+  return copysignf (1.0f, arg) < 0;
 #else
   /* This does not do the right thing for NaN, but this is irrelevant for
      most use cases.  */
--- a/lib/signbitl.c
+++ b/lib/signbitl.c
@@ -30,11 +30,19 @@
 gl_signbitl (long double arg)
 {
 #if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT
+  /* The use of a union to extract the bits of the representation of a
+     'long double' is safe in practice, despite of the "aliasing rules" of
+     C99, because the GCC docs say
+       "Even with '-fstrict-aliasing', type-punning is allowed, provided the
+        memory is accessed through the union type."
+     and similarly for other compilers.  */
 # define NWORDS \
     ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
   union { long double value; unsigned int word[NWORDS]; } m;
   m.value = arg;
   return (m.word[LDBL_SIGNBIT_WORD] >> LDBL_SIGNBIT_BIT) & 1;
+#elif HAVE_COPYSIGNL_IN_LIBC
+  return copysignl (1.0L, arg) < 0;
 #else
   /* This does not do the right thing for NaN, but this is irrelevant for
      most use cases.  */
--- a/m4/signbit.m4
+++ b/m4/signbit.m4
@@ -1,4 +1,4 @@
-# signbit.m4 serial 1
+# signbit.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,
@@ -65,6 +65,66 @@
     gl_FLOAT_SIGN_LOCATION
     gl_DOUBLE_SIGN_LOCATION
     gl_LONG_DOUBLE_SIGN_LOCATION
+    if test "$gl_cv_cc_float_signbit" = unknown; then
+      dnl Test whether copysignf() is declared.
+      AC_CHECK_DECLS([copysignf], , , [#include <math.h>])
+      if test "$ac_cv_have_decl_copysignf" = yes; then
+        dnl Test whether copysignf() can be used without libm.
+        AC_CACHE_CHECK([whether copysignf can be used without linking with libm],
+          [gl_cv_func_copysignf_no_libm],
+          [
+            AC_TRY_LINK([#include <math.h>
+                         float x, y;],
+                        [return copysignf (x, y) < 0;],
+              [gl_cv_func_copysignf_no_libm=yes],
+              [gl_cv_func_copysignf_no_libm=no])
+          ])
+        if test $gl_cv_func_copysignf_no_libm = yes; then
+          AC_DEFINE([HAVE_COPYSIGNF_IN_LIBC], 1,
+            [Define if the copysignf function is declared in <math.h> and available in libc.])
+        fi
+      fi
+    fi
+    if test "$gl_cv_cc_double_signbit" = unknown; then
+      dnl Test whether copysign() is declared.
+      AC_CHECK_DECLS([copysign], , , [#include <math.h>])
+      if test "$ac_cv_have_decl_copysign" = yes; then
+        dnl Test whether copysign() can be used without libm.
+        AC_CACHE_CHECK([whether copysign can be used without linking with libm],
+          [gl_cv_func_copysign_no_libm],
+          [
+            AC_TRY_LINK([#include <math.h>
+                         double x, y;],
+                        [return copysign (x, y) < 0;],
+              [gl_cv_func_copysign_no_libm=yes],
+              [gl_cv_func_copysign_no_libm=no])
+          ])
+        if test $gl_cv_func_copysign_no_libm = yes; then
+          AC_DEFINE([HAVE_COPYSIGN_IN_LIBC], 1,
+            [Define if the copysign function is declared in <math.h> and available in libc.])
+        fi
+      fi
+    fi
+    if test "$gl_cv_cc_long_double_signbit" = unknown; then
+      dnl Test whether copysignl() is declared.
+      AC_CHECK_DECLS([copysignl], , , [#include <math.h>])
+      if test "$ac_cv_have_decl_copysignl" = yes; then
+        dnl Test whether copysignl() can be used without libm.
+        AC_CACHE_CHECK([whether copysignl can be used without linking with libm],
+          [gl_cv_func_copysignl_no_libm],
+          [
+            AC_TRY_LINK([#include <math.h>
+                         long double x, y;],
+                        [return copysignl (x, y) < 0;],
+              [gl_cv_func_copysignl_no_libm=yes],
+              [gl_cv_func_copysignl_no_libm=no])
+          ])
+        if test $gl_cv_func_copysignl_no_libm = yes; then
+          AC_DEFINE([HAVE_COPYSIGNL_IN_LIBC], 1,
+            [Define if the copysignl function is declared in <math.h> and available in libc.])
+        fi
+      fi
+    fi
   fi
 ])