bug-gnulib
[Top][All Lists]
Advanced

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

modules 'round', 'roundf', 'roundl' for review


From: Ben Pfaff
Subject: modules 'round', 'roundf', 'roundl' for review
Date: Sat, 06 Oct 2007 20:36:04 -0700
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux)

The round, roundf, and roundl functions were added in C99 and
hence not supported everywhere.  I've written modules for them
that are heavily based on Bruno Haible's modules for trunc,
truncf, and truncl.  Here they are.  They work OK in my testing.
If I don't receive substantive objections in the next few days
I'll check them in.

I think that the numerical technique I used is sound, but I am
only a novice in the pitfalls of floating-point arithmetic.
Comments?

There is a huge amount of redundancy in the m4 code across all
six modules (trunc*, round*) and perhaps others.  Perhaps I
should write a common m4 macro that just takes a parameter or two
and avoids the redundancy.  Bruno, do you think that this is a
good idea?

diff --git a/doc/functions/round.texi b/doc/functions/round.texi
index 9910e23..28eb574 100644
--- a/doc/functions/round.texi
+++ b/doc/functions/round.texi
@@ -4,15 +4,15 @@
 
 POSIX specification: @url{http://www.opengroup.org/susv3xsh/round.html}
 
-Gnulib module: ---
+Gnulib module: round
 
 Portability problems fixed by Gnulib:
 @itemize
address@hidden
+This function is missing on some platforms:
+FreeBSD 5.2.1, OpenBSD 3.8, AIX 5.1, IRIX 6.5, OSF/1 4.0, Solaris 9, Interix 
3.5.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
address@hidden
-This function is missing on some platforms:
-FreeBSD 5.2.1, OpenBSD 3.8, AIX 5.1, IRIX 6.5, OSF/1 4.0, Solaris 9, Interix 
3.5.
 @end itemize
diff --git a/doc/functions/roundf.texi b/doc/functions/roundf.texi
index f389a64..41b3a7f 100644
--- a/doc/functions/roundf.texi
+++ b/doc/functions/roundf.texi
@@ -4,15 +4,15 @@
 
 POSIX specification: @url{http://www.opengroup.org/susv3xsh/roundf.html}
 
-Gnulib module: ---
+Gnulib module: roundf
 
 Portability problems fixed by Gnulib:
 @itemize
address@hidden
+This function is missing on some platforms:
+FreeBSD 5.2.1, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 4.0, Solaris 9, 
Interix 3.5.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
address@hidden
-This function is missing on some platforms:
-FreeBSD 5.2.1, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 4.0, Solaris 9, 
Interix 3.5.
 @end itemize
diff --git a/doc/functions/roundl.texi b/doc/functions/roundl.texi
index 439a0a8..a4eaa7d 100644
--- a/doc/functions/roundl.texi
+++ b/doc/functions/roundl.texi
@@ -4,15 +4,15 @@
 
 POSIX specification: @url{http://www.opengroup.org/susv3xsh/roundl.html}
 
-Gnulib module: ---
+Gnulib module: roundl
 
 Portability problems fixed by Gnulib:
 @itemize
address@hidden
+This function is missing on some platforms:
+FreeBSD 5.2.1, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 
4.0, Solaris 9, Cygwin, Interix 3.5, BeOS.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
address@hidden
-This function is missing on some platforms:
-FreeBSD 5.2.1, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 
4.0, Solaris 9, Cygwin, Interix 3.5, BeOS.
 @end itemize
diff --git a/lib/math.in.h b/lib/math.in.h
index b5dc1ea..6125b8a 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -218,6 +218,48 @@ extern long double logl (long double x);
 #endif
 
 
+#if @GNULIB_ROUNDF@
+# if address@hidden@
+#  define roundf rpl_roundf
+extern float roundf (float x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef roundf
+# define roundf(x) \
+    (GL_LINK_WARNING ("roundf is unportable - " \
+                      "use gnulib module roundf for portability"), \
+     roundf (x))
+#endif
+
+
+#if @GNULIB_ROUND@
+# if address@hidden@
+#  define round rpl_round
+extern double round (double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef round
+# define round(x) \
+    (GL_LINK_WARNING ("round is unportable - " \
+                      "use gnulib module round for portability"), \
+     round (x))
+#endif
+
+
+#if @GNULIB_ROUNDL@
+# if address@hidden@
+#  define roundl rpl_roundl
+extern long double roundl (long double x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef roundl
+# define roundl(x) \
+    (GL_LINK_WARNING ("roundl is unportable - " \
+                      "use gnulib module roundl for portability"), \
+     roundl (x))
+#endif
+
+
 #if @GNULIB_MATHL@ || address@hidden@
 extern long double sinl (long double x);
 #endif
diff --git a/lib/round.c b/lib/round.c
new file mode 100644
index 0000000..8baf119
--- /dev/null
+++ b/lib/round.c
@@ -0,0 +1,60 @@
+/* Round toward nearest, breaking ties away from zero.
+   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 Ben Pfaff <address@hidden>, 2007.
+   Based heavily on Bruno Haible's trunc.c. */
+
+#include <config.h>
+
+/* Specification.  */
+#include <math.h>
+
+#ifdef USE_LONG_DOUBLE
+# define ROUND roundl
+# define FLOOR floorl
+# define DOUBLE long double
+# define L_(literal) literal##L
+#elif ! defined USE_FLOAT
+# define ROUND round
+# define FLOOR floor
+# define DOUBLE double
+# define L_(literal) literal
+#else /* defined USE_FLOAT */
+# define ROUND roundf
+# define FLOOR floorf
+# define DOUBLE float
+# define L_(literal) literal##f
+#endif
+
+DOUBLE
+ROUND (DOUBLE x)
+{
+  if (x >= L_(0.0)) 
+    {
+      DOUBLE y = FLOOR (x);
+      if (x - y >= L_(0.5))
+        y += L_(1.0);
+      return y;
+    }
+  else
+    {
+      DOUBLE y = FLOOR (-x);
+      if (-x - y >= L_(0.5))
+        y += L_(1.0);
+      return -y;
+    }
+}
diff --git a/lib/roundf.c b/lib/roundf.c
new file mode 100644
index 0000000..8d7f94b
--- /dev/null
+++ b/lib/roundf.c
@@ -0,0 +1,19 @@
+/* Round toward nearest, breaking ties away from zero.
+   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.  */
+
+#define USE_FLOAT
+#include "round.c"
diff --git a/lib/roundl.c b/lib/roundl.c
new file mode 100644
index 0000000..e53ac0a
--- /dev/null
+++ b/lib/roundl.c
@@ -0,0 +1,19 @@
+/* Round toward nearest, breaking ties away from zero.
+   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.  */
+
+#define USE_LONG_DOUBLE
+#include "round.c"
diff --git a/m4/math_h.m4 b/m4/math_h.m4
index 5539d79..4806e08 100644
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -27,6 +27,9 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   GNULIB_FREXPL=0;  AC_SUBST([GNULIB_FREXPL])
   GNULIB_LDEXPL=0;  AC_SUBST([GNULIB_LDEXPL])
   GNULIB_MATHL=0;   AC_SUBST([GNULIB_MATHL])
+  GNULIB_ROUND=0;   AC_SUBST([GNULIB_ROUND])
+  GNULIB_ROUNDF=0;  AC_SUBST([GNULIB_ROUNDF])
+  GNULIB_ROUNDL=0;  AC_SUBST([GNULIB_ROUNDL])
   GNULIB_SIGNBIT=0; AC_SUBST([GNULIB_SIGNBIT])
   GNULIB_TRUNC=0;   AC_SUBST([GNULIB_TRUNC])
   GNULIB_TRUNCF=0;  AC_SUBST([GNULIB_TRUNCF])
@@ -44,6 +47,9 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   HAVE_DECL_FREXPL=1; AC_SUBST([HAVE_DECL_FREXPL])
   HAVE_DECL_LDEXPL=1; AC_SUBST([HAVE_DECL_LDEXPL])
   HAVE_DECL_LOGL=1;   AC_SUBST([HAVE_DECL_LOGL])
+  HAVE_DECL_ROUND=1;  AC_SUBST([HAVE_DECL_ROUND])
+  HAVE_DECL_ROUNDF=1; AC_SUBST([HAVE_DECL_ROUNDF])
+  HAVE_DECL_ROUNDL=1; AC_SUBST([HAVE_DECL_ROUNDL])
   HAVE_DECL_SINL=1;   AC_SUBST([HAVE_DECL_SINL])
   HAVE_DECL_SQRTL=1;  AC_SUBST([HAVE_DECL_SQRTL])
   HAVE_DECL_TANL=1;   AC_SUBST([HAVE_DECL_TANL])
diff --git a/m4/round.m4 b/m4/round.m4
new file mode 100644
index 0000000..76ab809
--- /dev/null
+++ b/m4/round.m4
@@ -0,0 +1,48 @@
+# round.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_FUNC_ROUND],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  dnl Persuade glibc <math.h> to declare round().
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  dnl Test whether round() is declared.
+  AC_CHECK_DECLS([round], , , [#include <math.h>])
+  if test "$ac_cv_have_decl_round" = yes; then
+    dnl Test whether round() can be used without libm.
+    ROUND_LIBM=?
+    AC_TRY_LINK([
+       #ifndef __NO_MATH_INLINES
+       # define __NO_MATH_INLINES 1 /* for glibc */
+       #endif
+       #include <math.h>
+       double x;],
+      [x = round(x);],
+      [ROUND_LIBM=])
+    if test "$ROUND_LIBM" = "?"; then
+      save_LIBS="$LIBS"
+      LIBS="$LIBS -lm"
+      AC_TRY_LINK([
+         #ifndef __NO_MATH_INLINES
+         # define __NO_MATH_INLINES 1 /* for glibc */
+         #endif
+         #include <math.h>
+         double x;],
+        [x = round(x);],
+        [ROUND_LIBM="-lm"])
+      LIBS="$save_LIBS"
+    fi
+    if test "$ROUND_LIBM" = "?"; then
+      ROUND_LIBM=
+    fi
+  else
+    HAVE_DECL_ROUND=0
+    AC_LIBOBJ([round])
+    ROUND_LIBM=
+  fi
+  AC_SUBST([HAVE_DECL_ROUND])
+  AC_SUBST([ROUND_LIBM])
+])
diff --git a/m4/roundf.m4 b/m4/roundf.m4
new file mode 100644
index 0000000..9d48107
--- /dev/null
+++ b/m4/roundf.m4
@@ -0,0 +1,48 @@
+# roundf.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_FUNC_ROUNDF],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  dnl Persuade glibc <math.h> to declare roundf().
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  dnl Test whether roundf() is declared.
+  AC_CHECK_DECLS([roundf], , , [#include <math.h>])
+  if test "$ac_cv_have_decl_roundf" = yes; then
+    dnl Test whether roundf() can be used without libm.
+    ROUNDF_LIBM=?
+    AC_TRY_LINK([
+       #ifndef __NO_MATH_INLINES
+       # define __NO_MATH_INLINES 1 /* for glibc */
+       #endif
+       #include <math.h>
+       float x;],
+      [x = roundf(x);],
+      [ROUNDF_LIBM=])
+    if test "$ROUNDF_LIBM" = "?"; then
+      save_LIBS="$LIBS"
+      LIBS="$LIBS -lm"
+      AC_TRY_LINK([
+         #ifndef __NO_MATH_INLINES
+         # define __NO_MATH_INLINES 1 /* for glibc */
+         #endif
+         #include <math.h>
+         float x;],
+        [x = roundf(x);],
+        [ROUNDF_LIBM="-lm"])
+      LIBS="$save_LIBS"
+    fi
+    if test "$ROUNDF_LIBM" = "?"; then
+      ROUNDF_LIBM=
+    fi
+  else
+    HAVE_DECL_ROUNDF=0
+    AC_LIBOBJ([roundf])
+    ROUNDF_LIBM=
+  fi
+  AC_SUBST([HAVE_DECL_ROUNDF])
+  AC_SUBST([ROUNDF_LIBM])
+])
diff --git a/m4/roundl.m4 b/m4/roundl.m4
new file mode 100644
index 0000000..94cfb99
--- /dev/null
+++ b/m4/roundl.m4
@@ -0,0 +1,48 @@
+# roundl.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_FUNC_ROUNDL],
+[
+  AC_REQUIRE([gl_MATH_H_DEFAULTS])
+  dnl Persuade glibc <math.h> to declare roundl().
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  dnl Test whether roundl() is declared.
+  AC_CHECK_DECLS([roundl], , , [#include <math.h>])
+  if test "$ac_cv_have_decl_roundl" = yes; then
+    dnl Test whether roundl() can be used without libm.
+    ROUNDL_LIBM=?
+    AC_TRY_LINK([
+       #ifndef __NO_MATH_INLINES
+       # define __NO_MATH_INLINES 1 /* for glibc */
+       #endif
+       #include <math.h>
+       long double x;],
+      [x = roundl(x);],
+      [ROUNDL_LIBM=])
+    if test "$ROUNDL_LIBM" = "?"; then
+      save_LIBS="$LIBS"
+      LIBS="$LIBS -lm"
+      AC_TRY_LINK([
+         #ifndef __NO_MATH_INLINES
+         # define __NO_MATH_INLINES 1 /* for glibc */
+         #endif
+         #include <math.h>
+         long double x;],
+        [x = roundl(x);],
+        [ROUNDL_LIBM="-lm"])
+      LIBS="$save_LIBS"
+    fi
+    if test "$ROUNDL_LIBM" = "?"; then
+      ROUNDL_LIBM=
+    fi
+  else
+    HAVE_DECL_ROUNDL=0
+    AC_LIBOBJ([roundl])
+    ROUNDL_LIBM=
+  fi
+  AC_SUBST([HAVE_DECL_ROUNDL])
+  AC_SUBST([ROUNDL_LIBM])
+])
diff --git a/modules/math b/modules/math
index 15e16e6..540f2fa 100644
--- a/modules/math
+++ b/modules/math
@@ -30,6 +30,9 @@ math.h: math.in.h
              -e 's|@''GNULIB_FREXPL''@|$(GNULIB_FREXPL)|g' \
              -e 's|@''GNULIB_LDEXPL''@|$(GNULIB_LDEXPL)|g' \
              -e 's|@''GNULIB_MATHL''@|$(GNULIB_MATHL)|g' \
+             -e 's|@''GNULIB_ROUND''@|$(GNULIB_ROUND)|g' \
+             -e 's|@''GNULIB_ROUNDF''@|$(GNULIB_ROUNDF)|g' \
+             -e 's|@''GNULIB_ROUNDL''@|$(GNULIB_ROUNDL)|g' \
              -e 's|@''GNULIB_SIGNBIT''@|$(GNULIB_SIGNBIT)|g' \
              -e 's|@''GNULIB_TRUNC''@|$(GNULIB_TRUNC)|g' \
              -e 's|@''GNULIB_TRUNCF''@|$(GNULIB_TRUNCF)|g' \
@@ -46,6 +49,9 @@ math.h: math.in.h
              -e 's|@''HAVE_DECL_FREXPL''@|$(HAVE_DECL_FREXPL)|g' \
              -e 's|@''HAVE_DECL_LDEXPL''@|$(HAVE_DECL_LDEXPL)|g' \
              -e 's|@''HAVE_DECL_LOGL''@|$(HAVE_DECL_LOGL)|g' \
+             -e 's|@''HAVE_DECL_ROUND''@|$(HAVE_DECL_ROUND)|g' \
+             -e 's|@''HAVE_DECL_ROUNDF''@|$(HAVE_DECL_ROUNDF)|g' \
+             -e 's|@''HAVE_DECL_ROUNDL''@|$(HAVE_DECL_ROUNDL)|g' \
              -e 's|@''HAVE_DECL_SINL''@|$(HAVE_DECL_SINL)|g' \
              -e 's|@''HAVE_DECL_SQRTL''@|$(HAVE_DECL_SQRTL)|g' \
              -e 's|@''HAVE_DECL_TANL''@|$(HAVE_DECL_TANL)|g' \
diff --git a/modules/round b/modules/round
new file mode 100644
index 0000000..e3a62fb
--- /dev/null
+++ b/modules/round
@@ -0,0 +1,29 @@
+Description:
+round() function: round toward nearest, breaking ties away from zero.
+
+Files:
+lib/round.c
+m4/round.m4
+
+Depends-on:
+math
+extensions
+
+configure.ac:
+gl_FUNC_ROUND
+gl_MATH_MODULE_INDICATOR([round])
+
+Makefile.am:
+
+Include:
+<math.h>
+
+Link:
+$(ROUND_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+Ben Pfaff
+
diff --git a/modules/round-tests b/modules/round-tests
new file mode 100644
index 0000000..1c492e2
--- /dev/null
+++ b/modules/round-tests
@@ -0,0 +1,14 @@
+Files:
+tests/test-round.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-round
+check_PROGRAMS += test-round
+test_round_LDADD = $(LDADD) @ROUND_LIBM@
+
+License:
+LGPL
diff --git a/modules/roundf b/modules/roundf
new file mode 100644
index 0000000..972f8a2
--- /dev/null
+++ b/modules/roundf
@@ -0,0 +1,30 @@
+Description:
+roundf() function: round toward nearest, breaking ties away from zero.
+
+Files:
+lib/roundf.c
+m4/roundf.m4
+
+Depends-on:
+math
+extensions
+floorf
+
+configure.ac:
+gl_FUNC_ROUNDF
+gl_MATH_MODULE_INDICATOR([roundf])
+
+Makefile.am:
+
+Include:
+<math.h>
+
+Link:
+$(ROUNDF_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+Ben Pfaff
+
diff --git a/modules/roundf-tests b/modules/roundf-tests
new file mode 100644
index 0000000..16a7d70
--- /dev/null
+++ b/modules/roundf-tests
@@ -0,0 +1,14 @@
+Files:
+tests/test-roundf.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-roundf
+check_PROGRAMS += test-roundf
+test_roundf_LDADD = $(LDADD) @ROUNDF_LIBM@
+
+License:
+LGPL
diff --git a/modules/roundl b/modules/roundl
new file mode 100644
index 0000000..6d86250
--- /dev/null
+++ b/modules/roundl
@@ -0,0 +1,30 @@
+Description:
+roundl() function: round toward nearest, breaking ties away from zero.
+
+Files:
+lib/roundl.c
+m4/roundl.m4
+
+Depends-on:
+math
+extensions
+floorl
+
+configure.ac:
+gl_FUNC_ROUNDL
+gl_MATH_MODULE_INDICATOR([roundl])
+
+Makefile.am:
+
+Include:
+<math.h>
+
+Link:
+$(ROUNDL_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+Ben Pfaff
+
diff --git a/modules/roundl-tests b/modules/roundl-tests
new file mode 100644
index 0000000..9bed031
--- /dev/null
+++ b/modules/roundl-tests
@@ -0,0 +1,14 @@
+Files:
+tests/test-roundl.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-roundl
+check_PROGRAMS += test-roundl
+test_roundl_LDADD = $(LDADD) @ROUNDL_LIBM@
+
+License:
+LGPL
diff --git a/tests/test-round.c b/tests/test-round.c
new file mode 100644
index 0000000..396fcc4
--- /dev/null
+++ b/tests/test-round.c
@@ -0,0 +1,90 @@
+/* Test of rounding to nearest, breaking ties away from zero.
+   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 Ben Pfaff <address@hidden>, 2007.
+   Based heavily on Bruno Haible's test-trunc.c. */
+
+#include <config.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)
+
+/* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0.  */
+#ifdef __DECC
+static double
+NaN ()
+{
+  static double zero = 0.0;
+  return zero / zero;
+}
+#else
+# define NaN() (0.0 / 0.0)
+#endif
+
+int
+main ()
+{
+  /* Zero.  */
+  ASSERT (round (0.0) == 0.0);
+  ASSERT (round (-0.0) == 0.0);
+  /* Positive numbers.  */
+  ASSERT (round (0.3) == 0.0);
+  ASSERT (round (0.5) == 1.0);
+  ASSERT (round (0.7) == 1.0);
+  ASSERT (round (1.0) == 1.0);
+  ASSERT (round (1.5) == 2.0);
+  ASSERT (round (2.5) == 3.0);
+  ASSERT (round (1.999) == 2.0);
+  ASSERT (round (2.0) == 2.0);
+  ASSERT (round (65535.999) == 65536.0);
+  ASSERT (round (65536.0) == 65536.0);
+  ASSERT (round (65536.001) == 65536.0);
+  ASSERT (round (2.341e31) == 2.341e31);
+  /* Negative numbers.  */
+  ASSERT (round (-0.3) == 0.0);
+  ASSERT (round (-0.5) == -1.0);
+  ASSERT (round (-0.7) == -1.0);
+  ASSERT (round (-1.0) == -1.0);
+  ASSERT (round (-1.5) == -2.0);
+  ASSERT (round (-2.5) == -3.0);
+  ASSERT (round (-1.999) == -2.0);
+  ASSERT (round (-2.0) == -2.0);
+  ASSERT (round (-65535.999) == -65536.0);
+  ASSERT (round (-65536.0) == -65536.0);
+  ASSERT (round (-65536.001) == -65536.0);
+  ASSERT (round (-2.341e31) == -2.341e31);
+  /* Infinite numbers.  */
+  ASSERT (round (1.0 / 0.0) == 1.0 / 0.0);
+  ASSERT (round (-1.0 / 0.0) == -1.0 / 0.0);
+  /* NaNs.  */
+  ASSERT (isnan (round (NaN ())));
+
+  return 0;
+}
diff --git a/tests/test-roundf.c b/tests/test-roundf.c
new file mode 100644
index 0000000..56fc1db
--- /dev/null
+++ b/tests/test-roundf.c
@@ -0,0 +1,90 @@
+/* Test of rounding to nearest, breaking ties away from zero.
+   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 Ben Pfaff <address@hidden>, 2007.
+   Based heavily on Bruno Haible's test-truncf.c. */
+
+#include <config.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)
+
+/* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0.  */
+#ifdef __DECC
+static float
+NaN ()
+{
+  static float zero = 0.0f;
+  return zero / zero;
+}
+#else
+# define NaN() (0.0f / 0.0f)
+#endif
+
+int
+main ()
+{
+  /* Zero.  */
+  ASSERT (roundf (0.0f) == 0.0f);
+  ASSERT (roundf (-0.0f) == 0.0f);
+  /* Positive numbers.  */
+  ASSERT (roundf (0.3f) == 0.0f);
+  ASSERT (roundf (0.5f) == 1.0f);
+  ASSERT (roundf (0.7f) == 1.0f);
+  ASSERT (roundf (1.0f) == 1.0f);
+  ASSERT (roundf (1.5f) == 2.0f);
+  ASSERT (roundf (2.5f) == 3.0f);
+  ASSERT (roundf (1.999f) == 2.0f);
+  ASSERT (roundf (2.0f) == 2.0f);
+  ASSERT (roundf (65535.999f) == 65536.0f);
+  ASSERT (roundf (65536.0f) == 65536.0f);
+  ASSERT (roundf (65536.001f) == 65536.0f);
+  ASSERT (roundf (2.341e31f) == 2.341e31f);
+  /* Negative numbers.  */
+  ASSERT (roundf (-0.3f) == 0.0f);
+  ASSERT (roundf (-0.5f) == -1.0f);
+  ASSERT (roundf (-0.7f) == -1.0f);
+  ASSERT (roundf (-1.0f) == -1.0f);
+  ASSERT (roundf (-1.5f) == -2.0f);
+  ASSERT (roundf (-2.5f) == -3.0f);
+  ASSERT (roundf (-1.999f) == -2.0f);
+  ASSERT (roundf (-2.0f) == -2.0f);
+  ASSERT (roundf (-65535.999f) == -65536.0f);
+  ASSERT (roundf (-65536.0f) == -65536.0f);
+  ASSERT (roundf (-65536.001f) == -65536.0f);
+  ASSERT (roundf (-2.341e31f) == -2.341e31f);
+  /* Infinite numbers.  */
+  ASSERT (roundf (1.0 / 0.0f) == 1.0 / 0.0f);
+  ASSERT (roundf (-1.0 / 0.0f) == -1.0 / 0.0f);
+  /* NaNs.  */
+  ASSERT (isnan (roundf (NaN ())));
+
+  return 0;
+}
diff --git a/tests/test-roundl.c b/tests/test-roundl.c
new file mode 100644
index 0000000..4e0ef4e
--- /dev/null
+++ b/tests/test-roundl.c
@@ -0,0 +1,90 @@
+/* Test of rounding to nearest, breaking ties away from zero.
+   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 Ben Pfaff <address@hidden>, 2007.
+   Based heavily on Bruno Haible's test-truncl.c. */
+
+#include <config.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)
+
+/* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0.  */
+#ifdef __DECC
+static long double
+NaN ()
+{
+  static long double zero = 0.0L;
+  return zero / zero;
+}
+#else
+# define NaN() (0.0L / 0.0L)
+#endif
+
+int
+main ()
+{
+  /* Zero.  */
+  ASSERT (roundl (0.0L) == 0.0L);
+  ASSERT (roundl (-0.0L) == 0.0L);
+  /* Positive numbers.  */
+  ASSERT (roundl (0.3L) == 0.0L);
+  ASSERT (roundl (0.5L) == 1.0L);
+  ASSERT (roundl (0.7L) == 1.0L);
+  ASSERT (roundl (1.0L) == 1.0L);
+  ASSERT (roundl (1.5L) == 2.0L);
+  ASSERT (roundl (2.5L) == 3.0L);
+  ASSERT (roundl (1.999L) == 2.0L);
+  ASSERT (roundl (2.0L) == 2.0L);
+  ASSERT (roundl (65535.999L) == 65536.0L);
+  ASSERT (roundl (65536.0L) == 65536.0L);
+  ASSERT (roundl (65536.001L) == 65536.0L);
+  ASSERT (roundl (2.341e31L) == 2.341e31L);
+  /* Negative numbers.  */
+  ASSERT (roundl (-0.3L) == 0.0L);
+  ASSERT (roundl (-0.5L) == -1.0L);
+  ASSERT (roundl (-0.7L) == -1.0L);
+  ASSERT (roundl (-1.0L) == -1.0L);
+  ASSERT (roundl (-1.5L) == -2.0L);
+  ASSERT (roundl (-2.5L) == -3.0L);
+  ASSERT (roundl (-1.999L) == -2.0L);
+  ASSERT (roundl (-2.0L) == -2.0L);
+  ASSERT (roundl (-65535.999L) == -65536.0L);
+  ASSERT (roundl (-65536.0L) == -65536.0L);
+  ASSERT (roundl (-65536.001L) == -65536.0L);
+  ASSERT (roundl (-2.341e31L) == -2.341e31L);
+  /* Infinite numbers.  */
+  ASSERT (roundl (1.0 / 0.0L) == 1.0 / 0.0L);
+  ASSERT (roundl (-1.0 / 0.0L) == -1.0 / 0.0L);
+  /* NaNs.  */
+  ASSERT (isnan (roundl (NaN ())));
+
+  return 0;
+}

-- 
Ben Pfaff 
http://benpfaff.org





reply via email to

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