ISO C99 wants also some functions that operate on 'float', not only on 'double' or 'long double'. I'm not sure whether a conversion of a signalling NaN(f) to a 'double' value will crash the program or not, so better be careful: I'm adding a module 'isnanf' that test a 'float' for NaN.
2007-04-06 Bruno Haible <[EMAIL PROTECTED]> * modules/isnanf-nolibm: New file. * lib/isnanf.h: New file. * lib/isnanf.c: New file. * lib/isnan.c: Consider the USE_FLOAT macro. * m4/isnanf.m4: New file. ============================== modules/isnanf-nolibm ========================== Description: isnanf() function: test for NaN, without requiring libm. Files: lib/isnanf.h lib/isnanf.c lib/isnan.c lib/float+.h m4/isnanf.m4 Depends-on: fpieee configure.ac: gl_FUNC_ISNANF_NO_LIBM Makefile.am: Include: #include "isnanf.h" License: LGPL Maintainer: Bruno Haible ================================ lib/isnanf.h ================================= /* Test for NaN that does not need libm. Copyright (C) 2007 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 2, 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #if HAVE_ISNANF_IN_LIBC /* Get declaration of isnan macro or (older) isnanf function. */ # include <math.h> # ifdef 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 ================================ lib/isnanf.c ================================= /* Test for NaN that does not need libm. Copyright (C) 2007 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 2, 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Bruno Haible <[EMAIL PROTECTED]>, 2007. */ #define USE_FLOAT #include "isnan.c" ================================ m4/isnanf.m4 ================================= # isnanf.m4 serial 1 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. dnl Check how to get or define isnanf() without linking with libm. AC_DEFUN([gl_FUNC_ISNANF_NO_LIBM], [ gl_HAVE_ISNANF_NO_LIBM if test $gl_cv_func_isnanf_no_libm = yes; then 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 fi ]) dnl Test whether isnanf() can be used without libm. AC_DEFUN([gl_HAVE_ISNANF_NO_LIBM], [ AC_CACHE_CHECK([whether isnan(float) can be used without linking with libm], [gl_cv_func_isnanf_no_libm], [ AC_TRY_LINK([#include <math.h> #ifdef isnan # undef isnanf # define isnanf(x) isnan ((float)(x)) #endif float x;], [return isnanf (x);], [gl_cv_func_isnanf_no_libm=yes], [gl_cv_func_isnanf_no_libm=no]) ]) ]) AC_DEFUN([gl_FLOAT_EXPONENT_LOCATION], [ AC_CACHE_CHECK([where to find the exponent in a 'float'], [gl_cv_cc_float_expbit0], [ AC_TRY_RUN([ #include <float.h> #include <stddef.h> #include <stdio.h> #include <string.h> #define NWORDS \ ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) typedef union { float value; unsigned int word[NWORDS]; } memory_float; static unsigned int ored_words[NWORDS]; static unsigned int anded_words[NWORDS]; static void add_to_ored_words (float x) { memory_float m; size_t i; /* Clear it first, in case sizeof (float) < sizeof (memory_float). */ memset (&m, 0, sizeof (memory_float)); m.value = x; for (i = 0; i < NWORDS; i++) { ored_words[i] |= m.word[i]; anded_words[i] &= m.word[i]; } } int main () { size_t j; FILE *fp = fopen ("conftest.out", "w"); if (fp == NULL) return 1; for (j = 0; j < NWORDS; j++) anded_words[j] = ~ (unsigned int) 0; add_to_ored_words (0.25f); add_to_ored_words (0.5f); add_to_ored_words (1.0f); add_to_ored_words (2.0f); add_to_ored_words (4.0f); /* Remove bits that are common (e.g. if representation of the first mantissa bit is explicit). */ for (j = 0; j < NWORDS; j++) ored_words[j] &= ~anded_words[j]; /* Now find the nonzero word. */ for (j = 0; j < NWORDS; j++) if (ored_words[j] != 0) break; if (j < NWORDS) { size_t i; for (i = j + 1; i < NWORDS; i++) if (ored_words[i] != 0) { fprintf (fp, "unknown"); return (fclose (fp) != 0); } for (i = 0; ; i++) if ((ored_words[j] >> i) & 1) { fprintf (fp, "word %d bit %d", (int) j, (int) i); return (fclose (fp) != 0); } } fprintf (fp, "unknown"); return (fclose (fp) != 0); } ], [gl_cv_cc_float_expbit0=`cat conftest.out`], [gl_cv_cc_float_expbit0="unknown"], [gl_cv_cc_double_expbit0="word 0 bit 23"]) rm -f conftest.out ]) case "$gl_cv_cc_float_expbit0" in word*bit*) word=`echo "$gl_cv_cc_float_expbit0" | sed -e 's/word //' -e 's/ bit.*//'` bit=`echo "$gl_cv_cc_float_expbit0" | sed -e 's/word.*bit //'` AC_DEFINE_UNQUOTED([FLT_EXPBIT0_WORD], [$word], [Define as the word index where to find the exponent of 'float'.]) AC_DEFINE_UNQUOTED([FLT_EXPBIT0_BIT], [$bit], [Define as the bit index in the word where to find bit 0 of the exponent of 'float'.]) ;; esac ]) =============================================================================== *** lib/isnan.c 25 Mar 2007 19:45:26 -0000 1.5 --- lib/isnan.c 6 Apr 2007 20:17:50 -0000 *************** *** 36,42 **** # endif # define SIZE SIZEOF_LDBL # define L_(literal) literal##L ! #else # define FUNC rpl_isnan # define DOUBLE double # define MAX_EXP DBL_MAX_EXP --- 36,42 ---- # endif # define SIZE SIZEOF_LDBL # define L_(literal) literal##L ! #elif ! defined USE_FLOAT # define FUNC rpl_isnan # define DOUBLE double # define MAX_EXP DBL_MAX_EXP *************** *** 48,53 **** --- 48,65 ---- # endif # define SIZE SIZEOF_DBL # define L_(literal) literal + #else /* defined USE_FLOAT */ + # define FUNC rpl_isnanf + # define DOUBLE float + # define MAX_EXP FLT_MAX_EXP + # define MIN_EXP FLT_MIN_EXP + # if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT + # define KNOWN_EXPBIT0_LOCATION + # define EXPBIT0_WORD FLT_EXPBIT0_WORD + # define EXPBIT0_BIT FLT_EXPBIT0_BIT + # endif + # define SIZE SIZEOF_FLT + # define L_(literal) literal##f #endif #define EXP_MASK ((MAX_EXP - MIN_EXP) | 7)