From a9fc1cd7a76bd6289a011c4f0b3206a1e34fa773 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Tue, 10 Apr 2007 21:38:36 +0000 Subject: [PATCH] Use copysign when implementing signbit, if the libc has it already. --- ChangeLog | 10 ++++++++ lib/signbitd.c | 8 +++++++ lib/signbitf.c | 8 +++++++ lib/signbitl.c | 8 +++++++ m4/signbit.m4 | 62 +++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 95 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index fd64f06adb..ab182fa4f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-04-10 Paul Eggert + Bruno Haible + + * 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 * lib/stdio_.h [REPLACE_FFLUSH]: Declare rpl_fflush. diff --git a/lib/signbitd.c b/lib/signbitd.c index f8a9613db5..3c06ebde9d 100644 --- a/lib/signbitd.c +++ b/lib/signbitd.c @@ -30,11 +30,19 @@ int 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. */ diff --git a/lib/signbitf.c b/lib/signbitf.c index c172b5fbef..d7e0663c7b 100644 --- a/lib/signbitf.c +++ b/lib/signbitf.c @@ -30,11 +30,19 @@ int 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. */ diff --git a/lib/signbitl.c b/lib/signbitl.c index 04814dcda8..c6675fc19b 100644 --- a/lib/signbitl.c +++ b/lib/signbitl.c @@ -30,11 +30,19 @@ int 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. */ diff --git a/m4/signbit.m4 b/m4/signbit.m4 index 267ef6718b..689b929be1 100644 --- 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 @@ int main () 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 ]) + 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 + 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 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 ]) + 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 + 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 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 ]) + 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 + 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 and available in libc.]) + fi + fi + fi fi ]) -- 2.30.2