[Top][All Lists]
[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