+2007-10-04 Bruno Haible <bruno@clisp.org>
+
+ * modules/truncf: New file.
+ * lib/trunc.c: Make paramerizable through USE_* macros.
+ * lib/truncf.c: New file.
+ * m4/truncf.m4: New file.
+ * lib/math.in.h (truncf): New declaration.
+ * m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize GNULIB_TRUNCF and
+ HAVE_DECL_TRUNCF.
+ * modules/math (Makefile.am): Substitute also GNULIB_TRUNCF and
+ HAVE_DECL_TRUNCF.
+ * doc/functions/truncf.texi: Mention the 'truncf' module.
+
2007-10-03 Bruno Haible <bruno@clisp.org>
* gnulib-tool (func_get_automake_snippet): Synthesize an EXTRA_DIST
POSIX specification: @url{http://www.opengroup.org/susv3xsh/truncf.html}
-Gnulib module: ---
+Gnulib module: truncf
Portability problems fixed by Gnulib:
@itemize
+@item
+This function is missing on some platforms:
+FreeBSD 5.2.1, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, Solaris 9, Interix 3.5.
@end itemize
Portability problems not fixed by Gnulib:
@itemize
-@item
-This function is missing on some platforms:
-FreeBSD 5.2.1, NetBSD 3.0, OpenBSD 3.8, AIX 5.1, HP-UX 11, Solaris 9, Interix 3.5.
@end itemize
acosl (x))
#endif
+
#if @GNULIB_MATHL@ || !@HAVE_DECL_ASINL@
extern long double asinl (long double x);
#endif
asinl (x))
#endif
+
#if @GNULIB_MATHL@ || !@HAVE_DECL_ATANL@
extern long double atanl (long double x);
#endif
atanl (x))
#endif
+
#if @GNULIB_MATHL@ || !@HAVE_DECL_CEILL@
extern long double ceill (long double x);
#endif
ceill (x))
#endif
+
#if @GNULIB_MATHL@ || !@HAVE_DECL_COSL@
extern long double cosl (long double x);
#endif
cosl (x))
#endif
+
#if @GNULIB_MATHL@ || !@HAVE_DECL_EXPL@
extern long double expl (long double x);
#endif
expl (x))
#endif
+
#if @GNULIB_MATHL@ || !@HAVE_DECL_FLOORL@
extern long double floorl (long double x);
#endif
floorl (x))
#endif
+
/* Write x as
x = mantissa * 2^exp
where
frexpl (x, e))
#endif
+
/* Return x * 2^exp. */
#if @GNULIB_LDEXPL@ && @REPLACE_LDEXPL@
# define ldexpl rpl_ldexpl
ldexpl (x, e))
#endif
+
#if @GNULIB_MATHL@ || !@HAVE_DECL_LOGL@
extern long double logl (long double x);
#endif
logl (x))
#endif
+
#if @GNULIB_MATHL@ || !@HAVE_DECL_SINL@
extern long double sinl (long double x);
#endif
sinl (x))
#endif
+
#if @GNULIB_MATHL@ || !@HAVE_DECL_SQRTL@
extern long double sqrtl (long double x);
#endif
sqrtl (x))
#endif
+
#if @GNULIB_MATHL@ || !@HAVE_DECL_TANL@
extern long double tanl (long double x);
#endif
tanl (x))
#endif
+
+#if @GNULIB_TRUNCF@
+# if !@HAVE_DECL_TRUNCF@
+# define truncf rpl_truncf
+extern float truncf (float x);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef truncf
+# define truncf(x) \
+ (GL_LINK_WARNING ("truncf is unportable - " \
+ "use gnulib module truncf for portability"), \
+ truncf (x))
+#endif
+
#if @GNULIB_TRUNC@
# if !@HAVE_DECL_TRUNC@
# define trunc rpl_trunc
#include <float.h>
-/* 2^(DBL_MANT_DIG-1). */
+#ifdef USE_LONG_DOUBLE
+# define FUNC truncl
+# define DOUBLE long double
+# define MANT_DIG LDBL_MANT_DIG
+# define L_(literal) literal##L
+#elif ! defined USE_FLOAT
+# define FUNC trunc
+# define DOUBLE double
+# define MANT_DIG DBL_MANT_DIG
+# define L_(literal) literal
+#else /* defined USE_FLOAT */
+# define FUNC truncf
+# define DOUBLE float
+# define MANT_DIG FLT_MANT_DIG
+# define L_(literal) literal##f
+#endif
+
+/* 2^(MANT_DIG-1). */
static const double TWO_MANT_DIG =
- /* Assume DBL_MANT_DIG <= 4 * 31.
+ /* Assume MANT_DIG <= 5 * 31.
Use the identity
- n = floor(n/4) + floor((n+1)/4) + floor((n+2)/4) + floor((n+3)/4). */
- (double) (1U << ((DBL_MANT_DIG - 1) / 4))
- * (double) (1U << ((DBL_MANT_DIG - 1 + 1) / 4))
- * (double) (1U << ((DBL_MANT_DIG - 1 + 2) / 4))
- * (double) (1U << ((DBL_MANT_DIG - 1 + 3) / 4));
+ n = floor(n/5) + floor((n+1)/5) + ... + floor((n+4)/5). */
+ (DOUBLE) (1U << ((MANT_DIG - 1) / 5))
+ * (DOUBLE) (1U << ((MANT_DIG - 1 + 1) / 5))
+ * (DOUBLE) (1U << ((MANT_DIG - 1 + 2) / 5))
+ * (DOUBLE) (1U << ((MANT_DIG - 1 + 3) / 5))
+ * (DOUBLE) (1U << ((MANT_DIG - 1 + 4) / 5));
-double
-trunc (double x)
+DOUBLE
+FUNC (DOUBLE x)
{
/* The use of 'volatile' guarantees that excess precision bits are dropped
at each addition step and before the following comparison at the caller's
compliant by default, to avoid that the results become platform and compiler
option dependent. 'volatile' is a portable alternative to gcc's
-ffloat-store option. */
- volatile double y = x;
- volatile double z = y;
+ volatile DOUBLE y = x;
+ volatile DOUBLE z = y;
- if (z > 0)
+ if (z > L_(0.0))
{
/* Round to the next integer (nearest or up or down, doesn't matter). */
z += TWO_MANT_DIG;
z -= TWO_MANT_DIG;
/* Enforce rounding down. */
if (z > y)
- z -= 1.0;
+ z -= L_(1.0);
}
- else if (z < 0)
+ else if (z < L_(0.0))
{
/* Round to the next integer (nearest or up or down, doesn't matter). */
z -= TWO_MANT_DIG;
z += TWO_MANT_DIG;
/* Enforce rounding up. */
if (z < y)
- z += 1.0;
+ z += L_(1.0);
}
return z;
}
--- /dev/null
+/* Round towards 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 Bruno Haible <bruno@clisp.org>, 2007. */
+
+#define USE_FLOAT
+#include "trunc.c"
GNULIB_MATHL=0; AC_SUBST([GNULIB_MATHL])
GNULIB_SIGNBIT=0; AC_SUBST([GNULIB_SIGNBIT])
GNULIB_TRUNC=0; AC_SUBST([GNULIB_TRUNC])
+ GNULIB_TRUNCF=0; AC_SUBST([GNULIB_TRUNCF])
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])
HAVE_DECL_SQRTL=1; AC_SUBST([HAVE_DECL_SQRTL])
HAVE_DECL_TANL=1; AC_SUBST([HAVE_DECL_TANL])
HAVE_DECL_TRUNC=1; AC_SUBST([HAVE_DECL_TRUNC])
+ HAVE_DECL_TRUNCF=1; AC_SUBST([HAVE_DECL_TRUNCF])
REPLACE_FREXP=0; AC_SUBST([REPLACE_FREXP])
REPLACE_FREXPL=0; AC_SUBST([REPLACE_FREXPL])
REPLACE_LDEXPL=0; AC_SUBST([REPLACE_LDEXPL])
--- /dev/null
+# truncf.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_TRUNCF],
+[
+ AC_REQUIRE([gl_MATH_H_DEFAULTS])
+ dnl Persuade glibc <math.h> to declare truncf().
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+ dnl Test whether truncf() is declared.
+ AC_CHECK_DECLS([truncf], , , [#include <math.h>])
+ if test "$ac_cv_have_decl_truncf" = yes; then
+ dnl Test whether truncf() can be used without libm.
+ TRUNCF_LIBM=?
+ AC_TRY_LINK([
+ #ifndef __NO_MATH_INLINES
+ # define __NO_MATH_INLINES 1 /* for glibc */
+ #endif
+ #include <math.h>
+ float x;],
+ [x = truncf(x);],
+ [TRUNCF_LIBM=])
+ if test "$TRUNCF_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 = truncf(x);],
+ [TRUNCF_LIBM="-lm"])
+ LIBS="$save_LIBS"
+ fi
+ if test "$TRUNCF_LIBM" = "?"; then
+ TRUNCF_LIBM=
+ fi
+ else
+ HAVE_DECL_TRUNCF=0
+ AC_LIBOBJ([truncf])
+ TRUNCF_LIBM=
+ fi
+ AC_SUBST([HAVE_DECL_TRUNCF])
+ AC_SUBST([TRUNCF_LIBM])
+])
-e 's|@''GNULIB_MATHL''@|$(GNULIB_MATHL)|g' \
-e 's|@''GNULIB_SIGNBIT''@|$(GNULIB_SIGNBIT)|g' \
-e 's|@''GNULIB_TRUNC''@|$(GNULIB_TRUNC)|g' \
+ -e 's|@''GNULIB_TRUNCF''@|$(GNULIB_TRUNCF)|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' \
-e 's|@''HAVE_DECL_SQRTL''@|$(HAVE_DECL_SQRTL)|g' \
-e 's|@''HAVE_DECL_TANL''@|$(HAVE_DECL_TANL)|g' \
-e 's|@''HAVE_DECL_TRUNC''@|$(HAVE_DECL_TRUNC)|g' \
+ -e 's|@''HAVE_DECL_TRUNCF''@|$(HAVE_DECL_TRUNCF)|g' \
-e 's|@''REPLACE_FREXP''@|$(REPLACE_FREXP)|g' \
-e 's|@''REPLACE_FREXPL''@|$(REPLACE_FREXPL)|g' \
-e 's|@''REPLACE_LDEXPL''@|$(REPLACE_LDEXPL)|g' \
--- /dev/null
+Description:
+truncf() function: round towards zero.
+
+Files:
+lib/truncf.c
+lib/trunc.c
+m4/truncf.m4
+
+Depends-on:
+math
+extensions
+float
+
+configure.ac:
+gl_FUNC_TRUNCF
+gl_MATH_MODULE_INDICATOR([truncf])
+
+Makefile.am:
+
+Include:
+<math.h>
+
+Link:
+$(TRUNCF_LIBM)
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible
+