bug-gnulib
[Top][All Lists]
Advanced

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

new module 'isfinite'


From: Ben Pfaff
Subject: new module 'isfinite'
Date: Tue, 23 Oct 2007 22:00:45 -0700
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux)

PSPP would like to use the isfinite macro in ISO C99 <math.h>.
The following patch (not yet committed) adds a module that
implements a substitute when the system does not provide
isfinite.  It tests out OK with glibc on GNU/Linux, both
configured normally and when I manually force use of the
substitute.  I wanted to test it on a machine that actually lacks
isfinite, but none of the testdrive machines run one of those
OSes (based on doc/functions/isfinite.texi).

Two possible issues I see here are:

        * Is it acceptable for isfinite to raise an exception on
          a signaling NaN?  By my analysis (see the patch to
          isfinite.texi), this is acceptable, standards-wise, but
          it is different from what glibc does.

        * Is it acceptable to #include <float.h> in and put
          inline functions in math.in.h?  Nothing else does
          either of those, right now.

If anyone thinks that either of those is a real problem, I will
reformulate the module.

diff --git a/MODULES.html.sh b/MODULES.html.sh
index 11c4e3e..3f353a7 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -1970,6 +1970,7 @@ func_all_modules ()
   func_module frexp
   func_module frexpl
   func_module frexpl-nolibm
+  func_module isfinite
   func_module isnan-nolibm
   func_module isnanf-nolibm
   func_module isnanl
diff --git a/doc/functions/isfinite.texi b/doc/functions/isfinite.texi
index 2b777a6..1d1a667 100644
--- a/doc/functions/isfinite.texi
+++ b/doc/functions/isfinite.texi
@@ -4,15 +4,23 @@
 
 POSIX specification: @url{http://www.opengroup.org/susv3xsh/isfinite.html}
 
-Gnulib module: ---
+Gnulib module: isfinite
 
 Portability problems fixed by Gnulib:
 @itemize
address@hidden
+This macro is missing on some platforms:
+MacOS X 10.3, OpenBSD 3.8, AIX 5.1, IRIX 6.5, OSF/1 5.1, Solaris 10, Interix 
3.5.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
 @item
-This function is missing on some platforms:
-MacOS X 10.3, OpenBSD 3.8, AIX 5.1, IRIX 6.5, OSF/1 5.1, Solaris 10, Interix 
3.5.
+POSIX defers to ISO C99 on the definition of this macro, ISO C99
+section F.3 in turn defers to the definition of the @code{finite}
+function from IEC 60559, and the Appendix to IEC 60559 that defines
address@hidden states that it is up to the implementation whether
address@hidden is considered an arithmetic operation that raises an
+exception for a signaling NaN operand.  The Gnulib implementation will
+raise an exception in this case, but glibc does not.
 @end itemize
diff --git a/lib/math.in.h b/lib/math.in.h
index c5d98f0..34491ab 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -334,6 +334,30 @@ extern long double truncl (long double x);
      truncl (x))
 #endif
 
+#if @GNULIB_ISFINITE@
+# if address@hidden@
+#  include <float.h>
+static inline int gl_isfinitef (float x) 
+{
+  return x >= -FLT_MAX && x <= FLT_MAX;
+}
+static inline int gl_isfinited (double x) 
+{
+  return x >= -DBL_MAX && x <= DBL_MAX;
+}
+static inline int gl_isfinitel (long double x) 
+{
+  return x >= -LDBL_MAX && x <= LDBL_MAX;
+}
+#  undef isfinite
+#  define isfinite(x) \
+   (sizeof (x) == sizeof (long double) ? gl_isfinitel (x) : \
+    sizeof (x) == sizeof (double) ? gl_isfinited (x) : \
+    gl_isfinitef (x))
+# endif
+#elif defined GNULIB_POSIXCHECK
+  /* How to override a macro?  */
+#endif
 
 #if @GNULIB_SIGNBIT@
 # if @REPLACE_SIGNBIT@
diff --git a/m4/isfinite.m4 b/m4/isfinite.m4
new file mode 100644
index 0000000..5058f95
--- /dev/null
+++ b/m4/isfinite.m4
@@ -0,0 +1,21 @@
+# isfinite.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.
+
+AC_DEFUN([gl_ISFINITE],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  dnl Persuade glibc <math.h> to declare isfinite.
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  AC_CHECK_DECLS([isfinite], , , [#include <math.h>])
+  if test "$ac_cv_have_decl_isfinite" = yes; then
+    gl_CHECK_MATH_LIB([ISFINITE_LIBM], [x = isfinite (x);])
+  else
+    ISFINITE_LIBM=
+    HAVE_DECL_ISFINITE=0
+  fi
+  AC_SUBST([HAVE_DECL_ISFINITE])
+  AC_SUBST([ISFINITE_LIBM])
+])
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index 4806e08..890888c 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -34,6 +34,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   GNULIB_TRUNC=0;   AC_SUBST([GNULIB_TRUNC])
   GNULIB_TRUNCF=0;  AC_SUBST([GNULIB_TRUNCF])
   GNULIB_TRUNCL=0;  AC_SUBST([GNULIB_TRUNCL])
+  GNULIB_ISFINITE=0; AC_SUBST([GNULIB_ISFINITE])
   dnl Assume proper GNU behavior unless another module says otherwise.
   HAVE_DECL_ACOSL=1;  AC_SUBST([HAVE_DECL_ACOSL])
   HAVE_DECL_ASINL=1;  AC_SUBST([HAVE_DECL_ASINL])
@@ -56,6 +57,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   HAVE_DECL_TRUNC=1;  AC_SUBST([HAVE_DECL_TRUNC])
   HAVE_DECL_TRUNCF=1; AC_SUBST([HAVE_DECL_TRUNCF])
   HAVE_DECL_TRUNCL=1; AC_SUBST([HAVE_DECL_TRUNCL])
+  HAVE_DECL_ISFINITE=1; AC_SUBST([HAVE_DECL_ISFINITE])
   REPLACE_FREXP=0;    AC_SUBST([REPLACE_FREXP])
   REPLACE_FREXPL=0;   AC_SUBST([REPLACE_FREXPL])
   REPLACE_LDEXPL=0;   AC_SUBST([REPLACE_LDEXPL])
diff --git a/modules/isfinite b/modules/isfinite
new file mode 100644
index 0000000..5ceafb4
--- /dev/null
+++ b/modules/isfinite
@@ -0,0 +1,27 @@
+Description:
+isfinite macro: test for finite value (zero, subnormal, or normal, and not 
infinite or NaN).
+
+Files:
+m4/isfinite.m4
+m4/check-math-lib.m4
+
+Depends-on:
+inline
+math
+extensions
+float
+
+configure.ac:
+gl_ISFINITE
+gl_MATH_MODULE_INDICATOR([isfinite])
+
+Makefile.am:
+
+Include:
+<math.h>
+
+License:
+GPL
+
+Maintainer:
+Ben Pfaff
diff --git a/modules/isfinite-tests b/modules/isfinite-tests
new file mode 100644
index 0000000..bca2e85
--- /dev/null
+++ b/modules/isfinite-tests
@@ -0,0 +1,14 @@
+Files:
+tests/test-isfinite.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-isfinite
+check_PROGRAMS += test-isfinite
+test_isfinite_LDADD = $(LDADD) @ISFINITE_LIBM@
+
+License:
+GPL
diff --git a/modules/math b/modules/math
index 540f2fa..935bebb 100644
--- a/modules/math
+++ b/modules/math
@@ -37,6 +37,7 @@ math.h: math.in.h
              -e 's|@''GNULIB_TRUNC''@|$(GNULIB_TRUNC)|g' \
              -e 's|@''GNULIB_TRUNCF''@|$(GNULIB_TRUNCF)|g' \
              -e 's|@''GNULIB_TRUNCL''@|$(GNULIB_TRUNCL)|g' \
+             -e 's|@''GNULIB_ISFINITE''@|$(GNULIB_ISFINITE)|g' \
              -e 's|@''HAVE_DECL_ACOSL''@|$(HAVE_DECL_ACOSL)|g' \
              -e 's|@''HAVE_DECL_ASINL''@|$(HAVE_DECL_ASINL)|g' \
              -e 's|@''HAVE_DECL_ATANL''@|$(HAVE_DECL_ATANL)|g' \
@@ -58,6 +59,7 @@ math.h: math.in.h
              -e 's|@''HAVE_DECL_TRUNC''@|$(HAVE_DECL_TRUNC)|g' \
              -e 's|@''HAVE_DECL_TRUNCF''@|$(HAVE_DECL_TRUNCF)|g' \
              -e 's|@''HAVE_DECL_TRUNCL''@|$(HAVE_DECL_TRUNCL)|g' \
+             -e 's|@''HAVE_DECL_ISFINITE''@|$(HAVE_DECL_ISFINITE)|g' \
              -e 's|@''REPLACE_FREXP''@|$(REPLACE_FREXP)|g' \
              -e 's|@''REPLACE_FREXPL''@|$(REPLACE_FREXPL)|g' \
              -e 's|@''REPLACE_LDEXPL''@|$(REPLACE_LDEXPL)|g' \
diff --git a/tests/test-isfinite.c b/tests/test-isfinite.c
new file mode 100644
index 0000000..43d0ee1
--- /dev/null
+++ b/tests/test-isfinite.c
@@ -0,0 +1,116 @@
+/* Test of isfinite() substitute.
+   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 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/>.  */
+
+/* Written by Ben Pfaff, 2007, using Bruno Haible's code as a
+   template. */
+
+#include <config.h>
+
+#include <float.h>
+#include <math.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ASSERT(expr) \
+  do                                                                        \
+    {                                                                       \
+      if (!(expr))                                                          \
+        {                                                                   \
+          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+          abort ();                                                         \
+        }                                                                   \
+    }                                                                       \
+  while (0)
+
+float zerof = 0.0f;
+double zerod = 0.0;
+long double zerol = 0.0L;
+
+static void
+test_isfinitef ()
+{
+  /* Zero. */
+  ASSERT (isfinite (0.0f));
+  /* Subnormal values. */
+  ASSERT (isfinite (FLT_MIN / 2));
+  ASSERT (isfinite (-FLT_MIN / 2));
+  /* Finite values.  */
+  ASSERT (isfinite (3.141f));
+  ASSERT (isfinite (3.141e30f));
+  ASSERT (isfinite (3.141e-30f));
+  ASSERT (isfinite (-2.718f));
+  ASSERT (isfinite (-2.718e30f));
+  ASSERT (isfinite (-2.718e-30f));
+  /* Infinite values.  */
+  ASSERT (!isfinite (1.0f / 0.0f));
+  ASSERT (!isfinite (-1.0f / 0.0f));
+  /* Quiet NaN.  */
+  ASSERT (!isfinite (zerof / zerof));
+}
+
+static void
+test_isfinited ()
+{
+  /* Zero. */
+  ASSERT (isfinite (0.0));
+  /* Subnormal values. */
+  ASSERT (isfinite (DBL_MIN / 2));
+  ASSERT (isfinite (-DBL_MIN / 2));
+  /* Finite values. */
+  ASSERT (isfinite (3.141));
+  ASSERT (isfinite (3.141e30));
+  ASSERT (isfinite (3.141e-30));
+  ASSERT (isfinite (-2.718));
+  ASSERT (isfinite (-2.718e30));
+  ASSERT (isfinite (-2.718e-30));
+  /* Infinite values.  */
+  ASSERT (!isfinite (1.0 / 0.0));
+  ASSERT (!isfinite (-1.0 / 0.0));
+  /* Quiet NaN.  */
+  ASSERT (!isfinite (zerod / zerod));
+}
+
+static void
+test_isfinitel ()
+{
+  /* Zero. */
+  ASSERT (isfinite (0.0L));
+  /* Subnormal values. */
+  ASSERT (isfinite (LDBL_MIN / 2));
+  ASSERT (isfinite (-LDBL_MIN / 2));
+  /* Finite values. */
+  ASSERT (isfinite (3.141L));
+  ASSERT (isfinite (3.141e30L));
+  ASSERT (isfinite (3.141e-30L));
+  ASSERT (isfinite (-2.718L));
+  ASSERT (isfinite (-2.718e30L));
+  ASSERT (isfinite (-2.718e-30L));
+  /* Infinite values.  */
+  ASSERT (!isfinite (1.0L / 0.0L));
+  ASSERT (!isfinite (-1.0L / 0.0L));
+  /* Quiet NaN.  */
+  ASSERT (!isfinite (zerol / zerol));
+}
+
+int
+main ()
+{
+  test_isfinitef ();
+  test_isfinited ();
+  test_isfinitel ();
+  return 0;
+}

-- 
"A computer is a state machine.
 Threads are for people who cant [sic] program state machines."
--Alan Cox





reply via email to

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