# HG changeset patch # User Ben Pfaff # Date 1215884763 25200 # Node ID c0565d2cba3284b9639088f4e8f12efe13797d2b # Parent ecc1f86df80915f39288a264cf6b3e4d0d6b981d Add isnanf module. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2008-07-10 Ben Pfaff + + Add isnanf module. + * lib/isnanf.m4: New file. + * m4/isnanf.m4 (gl_FUNC_ISNANF): New macro. + (gl_HAVE_ISNANF_IN_LIBM): New macro. + (gl_BUILD_ISNANF): New macro used by gl_FUNC_ISNANF, + gl_FUNC_ISNANF_NO_LIBM, and gl_FUNC_ISNAN. + * modules/isnanf: New file. + * modules/isnanf-tests: New file. + * modules/isnanf-nolibm-tests: Add tests/test-isnanf.h to list of + files. + * tests/test-isnanf-nolibm.c: factored most of its contents into + new file tests/test-isnanf.h. + * tests/test-isnanf.h: New file. + * tests/test-isnanf.c: New file. + * MODULES.html.sh: Mention new module. + * doc/glibc-functions/isnanf.texi: Mention new module. + 2008-07-10 Ben Pfaff Add isnand module. diff --git a/MODULES.html.sh b/MODULES.html.sh --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -1999,6 +1999,7 @@ func_module frexpl func_module frexpl-nolibm func_module isfinite + func_module isnanf func_module isnanf-nolibm func_module isnand func_module isnand-nolibm diff --git a/doc/glibc-functions/isnanf.texi b/doc/glibc-functions/isnanf.texi --- a/doc/glibc-functions/isnanf.texi +++ b/doc/glibc-functions/isnanf.texi @@ -2,15 +2,15 @@ @subsection @code{isnanf} @findex isnanf -Gnulib module: --- +Gnulib module: isnanf Portability problems fixed by Gnulib: @itemize -@end itemize - -Portability problems not fixed by Gnulib: -@itemize @item This function is missing on some platforms: MacOS X 10.3, AIX 5.1, HP-UX 11. @end itemize + +Portability problems not fixed by Gnulib: +@itemize +@end itemize diff --git a/lib/isnanf.h b/lib/isnanf.h new file mode 100644 --- /dev/null +++ b/lib/isnanf.h @@ -0,0 +1,33 @@ +/* Test for NaN. + Copyright (C) 2007-2008 Free Software Foundation, Inc. + + 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 . */ + +#if HAVE_ISNANF +/* Get declaration of isnan macro or (older) isnanf function. */ +# include +# if __GNUC__ >= 4 + /* GCC 4.0 and newer provides three built-ins for isnan. */ +# undef isnanf +# define isnanf(x) __builtin_isnanf ((float)(x)) +# elif defined isnan +# undef isnanf +# define isnanf(x) isnan ((float)(x)) +# endif +#else +/* Test whether X is a NaN. */ +# undef isnanf +# define isnanf rpl_isnanf +extern int isnanf (float x); +#endif diff --git a/m4/isnanf.m4 b/m4/isnanf.m4 --- a/m4/isnanf.m4 +++ b/m4/isnanf.m4 @@ -1,9 +1,43 @@ -# isnanf.m4 serial 6 +# isnanf.m4 serial 7 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. +dnl Check how to get or define isnanf(). + +AC_DEFUN([gl_FUNC_ISNANF], +[ + ISNANF_LIBM= + gl_HAVE_ISNANF_NO_LIBM + if test $gl_cv_func_isnanf_no_libm = no; then + gl_HAVE_ISNANF_IN_LIBM + if test $gl_cv_func_isnanf_in_libm = yes; then + ISNANF_LIBM=-lm + fi + fi + if test $gl_cv_func_isnanf_no_libm = yes \ + || test $gl_cv_func_isnanf_in_libm = yes; then + save_LIBS="$LIBS" + LIBS="$LIBS $ISNANF_LIBM" + gl_ISNANF_WORKS + LIBS="$save_LIBS" + case "$gl_cv_func_isnanf_works" in + *yes) gl_func_isnanf=yes ;; + *) gl_func_isnanf=no; ISNANF_LIBM= ;; + esac + else + gl_func_isnanf=no + fi + if test $gl_func_isnanf = yes; then + AC_DEFINE([HAVE_ISNANF], 1, + [Define if the isnan(float) function is available.]) + else + gl_BUILD_ISNANF + fi + AC_SUBST([ISNANF_LIBM]) +]) + dnl Check how to get or define isnanf() without linking with libm. AC_DEFUN([gl_FUNC_ISNANF_NO_LIBM], @@ -21,11 +55,17 @@ AC_DEFINE([HAVE_ISNANF_IN_LIBC], 1, [Define if the isnan(float) function is available in libc.]) else - AC_LIBOBJ([isnanf]) - gl_FLOAT_EXPONENT_LOCATION + gl_BUILD_ISNANF fi ]) +dnl Pull in replacement isnanf definition. +AC_DEFUN([gl_BUILD_ISNANF], +[ + AC_LIBOBJ([isnanf]) + gl_FLOAT_EXPONENT_LOCATION +]) + dnl Test whether isnanf() can be used without libm. AC_DEFUN([gl_HAVE_ISNANF_NO_LIBM], [ @@ -47,6 +87,30 @@ ]) ]) +dnl Test whether isnanf() can be used with libm. +AC_DEFUN([gl_HAVE_ISNANF_IN_LIBM], +[ + AC_CACHE_CHECK([whether isnan(float) can be used with libm], + [gl_cv_func_isnanf_in_libm], + [ + save_LIBS="$LIBS" + LIBS="$LIBS -lm" + AC_TRY_LINK([#include + #if __GNUC__ >= 4 + # undef isnanf + # define isnanf(x) __builtin_isnanf ((float)(x)) + #elif defined isnan + # undef isnanf + # define isnanf(x) isnan ((float)(x)) + #endif + float x;], + [return isnanf (x);], + [gl_cv_func_isnanf_in_libm=yes], + [gl_cv_func_isnanf_in_libm=no]) + LIBS="$save_LIBS" + ]) +]) + dnl Test whether isnanf() rejects Infinity (this fails on Solaris 2.5.1), dnl recognizes a NaN (this fails on IRIX 6.5 with cc), and recognizes a NaN dnl with in-memory representation 0x7fbfffff (this fails on IRIX 6.5). diff --git a/modules/isnanf b/modules/isnanf new file mode 100644 --- /dev/null +++ b/modules/isnanf @@ -0,0 +1,30 @@ +Description: +isnanf() function: test for NaN. + +Files: +lib/isnanf.h +lib/isnanf.c +lib/isnan.c +lib/float+.h +m4/isnanf.m4 + +Depends-on: +fpieee + +configure.ac: +gl_FUNC_ISNANF + +Makefile.am: + +Include: +#include "isnanf.h" + +Link: +$(ISNANF_LIBM) + +License: +LGPL + +Maintainer: +Bruno Haible + diff --git a/modules/isnanf-nolibm-tests b/modules/isnanf-nolibm-tests --- a/modules/isnanf-nolibm-tests +++ b/modules/isnanf-nolibm-tests @@ -1,5 +1,6 @@ Files: tests/test-isnanf-nolibm.c +tests/test-isnanf.h tests/nan.h Depends-on: diff --git a/modules/isnanf-tests b/modules/isnanf-tests new file mode 100644 --- /dev/null +++ b/modules/isnanf-tests @@ -0,0 +1,15 @@ +Files: +tests/test-isnanf.c +tests/test-isnanf.h +tests/nan.h + +Depends-on: + +configure.ac: +gl_FLOAT_EXPONENT_LOCATION + +Makefile.am: +TESTS += test-isnanf +check_PROGRAMS += test-isnanf +test_isnanf_LDADD = $(LDADD) @ISNANF_LIBM@ + diff --git a/tests/test-isnanf-nolibm.c b/tests/test-isnanf-nolibm.c --- a/tests/test-isnanf-nolibm.c +++ b/tests/test-isnanf-nolibm.c @@ -14,67 +14,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/* Written by Bruno Haible , 2007. */ - #include #include "isnanf-nolibm.h" -#include -#include -#include - -#include "nan.h" - -#define ASSERT(expr) \ - do \ - { \ - if (!(expr)) \ - { \ - fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ - fflush (stderr); \ - abort (); \ - } \ - } \ - while (0) - -int -main () -{ - /* Finite values. */ - ASSERT (!isnanf (3.141f)); - ASSERT (!isnanf (3.141e30f)); - ASSERT (!isnanf (3.141e-30f)); - ASSERT (!isnanf (-2.718f)); - ASSERT (!isnanf (-2.718e30f)); - ASSERT (!isnanf (-2.718e-30f)); - ASSERT (!isnanf (0.0f)); - ASSERT (!isnanf (-0.0f)); - /* Infinite values. */ - ASSERT (!isnanf (1.0f / 0.0f)); - ASSERT (!isnanf (-1.0f / 0.0f)); - /* Quiet NaN. */ - ASSERT (isnanf (NaNf ())); -#if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT - /* Signalling NaN. */ - { - #define NWORDS \ - ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) - typedef union { float value; unsigned int word[NWORDS]; } memory_float; - memory_float m; - m.value = NaNf (); -# if FLT_EXPBIT0_BIT > 0 - m.word[FLT_EXPBIT0_WORD] ^= (unsigned int) 1 << (FLT_EXPBIT0_BIT - 1); -# else - m.word[FLT_EXPBIT0_WORD + (FLT_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] - ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1); -# endif - if (FLT_EXPBIT0_WORD < NWORDS / 2) - m.word[FLT_EXPBIT0_WORD + 1] |= (unsigned int) 1 << FLT_EXPBIT0_BIT; - else - m.word[0] |= (unsigned int) 1; - ASSERT (isnanf (m.value)); - } -#endif - return 0; -} +#include "test-isnanf.h" diff --git a/tests/test-isnanf.c b/tests/test-isnanf.c new file mode 100644 --- /dev/null +++ b/tests/test-isnanf.c @@ -0,0 +1,21 @@ +/* Test of isnanf() substitute. + Copyright (C) 2007-2008 Free Software Foundation, Inc. + + 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 . */ + +#include + +#include "isnanf.h" + +#include "test-isnanf.h" diff --git a/tests/test-isnanf.h b/tests/test-isnanf.h new file mode 100644 --- /dev/null +++ b/tests/test-isnanf.h @@ -0,0 +1,76 @@ +/* Test of isnanf() substitute. + Copyright (C) 2007-2008 Free Software Foundation, Inc. + + 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 . */ + +/* Written by Bruno Haible , 2007. */ + +#include +#include +#include + +#include "nan.h" + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + +int +main () +{ + /* Finite values. */ + ASSERT (!isnanf (3.141f)); + ASSERT (!isnanf (3.141e30f)); + ASSERT (!isnanf (3.141e-30f)); + ASSERT (!isnanf (-2.718f)); + ASSERT (!isnanf (-2.718e30f)); + ASSERT (!isnanf (-2.718e-30f)); + ASSERT (!isnanf (0.0f)); + ASSERT (!isnanf (-0.0f)); + /* Infinite values. */ + ASSERT (!isnanf (1.0f / 0.0f)); + ASSERT (!isnanf (-1.0f / 0.0f)); + /* Quiet NaN. */ + ASSERT (isnanf (NaNf ())); +#if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT + /* Signalling NaN. */ + { + #define NWORDS \ + ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + typedef union { float value; unsigned int word[NWORDS]; } memory_float; + memory_float m; + m.value = NaNf (); +# if FLT_EXPBIT0_BIT > 0 + m.word[FLT_EXPBIT0_WORD] ^= (unsigned int) 1 << (FLT_EXPBIT0_BIT - 1); +# else + m.word[FLT_EXPBIT0_WORD + (FLT_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)] + ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1); +# endif + if (FLT_EXPBIT0_WORD < NWORDS / 2) + m.word[FLT_EXPBIT0_WORD + 1] |= (unsigned int) 1 << FLT_EXPBIT0_BIT; + else + m.word[0] |= (unsigned int) 1; + ASSERT (isnanf (m.value)); + } +#endif + return 0; +}