Here's the module for the floorl() function. Very much like the truncl() function.
Paolo, this replaces the floorl part of the 'mathl' module. I think the following changes are all improvements: - Don't assume that LDBL_EPSILON is a power of two. If LDBL_EPSILON is not a power of two, I think the rounding will be incorrect for some numbers between 0.5/LDBL_EPSILON and 1.0/LDBL_EPSILON. - Forbid compiler optimizations: Compilers are allowed to rearrange y = 1.0L / LDBL_EPSILON + x - 1.0 / LDBL_EPSILON; into y = x, which would obviously break the function. - In math.h, do a "#define floorl rpl_floorl", in order to avoid possible undesired compiler optimizations. 2007-10-04 Bruno Haible <[EMAIL PROTECTED]> * modules/floorl: New file. * lib/floorl.c: Replace entire file. * m4/floorl.m4: New file. * lib/math.in.h (floorl): Replace declaration. * m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize GNULIB_FLOORL. * modules/math (Makefile.am): Substitute also GNULIB_FLOORL. * doc/functions/floorl.texi: Mention the 'floorl' module. * modules/mathl (Files): Remove lib/floorl.c. (Depends-on): Add floorl. *** doc/functions/floorl.texi.orig 2007-10-05 03:26:02.000000000 +0200 --- doc/functions/floorl.texi 2007-10-05 03:07:12.000000000 +0200 *************** *** 4,18 **** POSIX specification: @url{http://www.opengroup.org/susv3xsh/floorl.html} ! Gnulib module: --- Portability problems fixed by Gnulib: @itemize @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, HP-UX 11, IRIX 6.5, Solaris 9, Cygwin, Interix 3.5, BeOS. @end itemize --- 4,18 ---- POSIX specification: @url{http://www.opengroup.org/susv3xsh/floorl.html} ! Gnulib module: floorl Portability problems fixed by Gnulib: @itemize + @item + This function is missing on some platforms: + FreeBSD 5.2.1, NetBSD 3.0, OpenBSD 3.8, HP-UX 11, IRIX 6.5, Solaris 9, Cygwin, Interix 3.5, BeOS. @end itemize Portability problems not fixed by Gnulib: @itemize @end itemize *** lib/floorl.c.orig 2007-10-05 03:26:02.000000000 +0200 --- lib/floorl.c 2007-10-05 03:08:38.000000000 +0200 *************** *** 1,9 **** ! /* Emulation for floorl. ! Contributed by Paolo Bonzini ! ! Copyright 2002, 2003, 2007 Free Software Foundation, Inc. ! ! This file is part of gnulib. 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 --- 1,5 ---- ! /* Round towards negative infinity. ! 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 *************** *** 19,46 **** with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ ! #include <config.h> ! ! /* Specification. */ ! #include <math.h> ! ! #include <float.h> ! ! /* To compute the integer part of X, sum a big enough ! integer so that the precision of the floating point ! number is exactly 1. */ ! ! long double ! floorl(long double x) ! { ! long double y; ! if (x < 0.0L) ! y = -(1.0L / LDBL_EPSILON - x - 1.0 / LDBL_EPSILON); ! else ! y = 1.0L / LDBL_EPSILON + x - 1.0 / LDBL_EPSILON; ! if (y > x) ! return y - 1.0L; ! else ! return y; ! } --- 15,21 ---- 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_LONG_DOUBLE ! #include "floor.c" *** lib/math.in.h.orig 2007-10-05 03:26:02.000000000 +0200 --- lib/math.in.h 2007-10-05 03:19:54.000000000 +0200 *************** *** 139,152 **** floorf (x)) #endif ! #if @GNULIB_MATHL@ || [EMAIL PROTECTED]@ extern long double floorl (long double x); ! #endif ! #if [EMAIL PROTECTED]@ && defined GNULIB_POSIXCHECK # undef floorl # define floorl(x) \ (GL_LINK_WARNING ("floorl is unportable - " \ ! "use gnulib module mathl for portability"), \ floorl (x)) #endif --- 139,154 ---- floorf (x)) #endif ! #if @GNULIB_FLOORL@ ! # if [EMAIL PROTECTED]@ ! # define floorl rpl_floorl extern long double floorl (long double x); ! # endif ! #elif defined GNULIB_POSIXCHECK # undef floorl # define floorl(x) \ (GL_LINK_WARNING ("floorl is unportable - " \ ! "use gnulib module floorl for portability"), \ floorl (x)) #endif Changing permissions from . to 100644 *** m4/floorl.m4.orig 2003-09-23 19:59:22.000000000 +0200 --- m4/floorl.m4 2007-10-05 03:22:37.000000000 +0200 *************** *** 0 **** --- 1,48 ---- + # floorl.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_FLOORL], + [ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + dnl Persuade glibc <math.h> to declare floorl(). + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + dnl Test whether floorl() is declared. + AC_CHECK_DECLS([floorl], , , [#include <math.h>]) + if test "$ac_cv_have_decl_floorl" = yes; then + dnl Test whether floorl() can be used without libm. + FLOORL_LIBM=? + AC_TRY_LINK([ + #ifndef __NO_MATH_INLINES + # define __NO_MATH_INLINES 1 /* for glibc */ + #endif + #include <math.h> + long double x;], + [x = floorl(x);], + [FLOORL_LIBM=]) + if test "$FLOORL_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 = floorl(x);], + [FLOORL_LIBM="-lm"]) + LIBS="$save_LIBS" + fi + if test "$FLOORL_LIBM" = "?"; then + FLOORL_LIBM= + fi + else + HAVE_DECL_FLOORL=0 + AC_LIBOBJ([floorl]) + FLOORL_LIBM= + fi + AC_SUBST([HAVE_DECL_FLOORL]) + AC_SUBST([FLOORL_LIBM]) + ]) *** m4/math_h.m4.orig 2007-10-05 03:26:02.000000000 +0200 --- m4/math_h.m4 2007-10-05 03:18:35.000000000 +0200 *************** *** 20,25 **** --- 20,26 ---- AC_DEFUN([gl_MATH_H_DEFAULTS], [ GNULIB_FLOORF=0; AC_SUBST([GNULIB_FLOORF]) + GNULIB_FLOORL=0; AC_SUBST([GNULIB_FLOORL]) GNULIB_FREXP=0; AC_SUBST([GNULIB_FREXP]) GNULIB_FREXPL=0; AC_SUBST([GNULIB_FREXPL]) GNULIB_LDEXPL=0; AC_SUBST([GNULIB_LDEXPL]) Changing permissions from . to 100644 *** modules/floorl.orig 2003-09-23 19:59:22.000000000 +0200 --- modules/floorl 2007-10-05 03:11:34.000000000 +0200 *************** *** 0 **** --- 1,31 ---- + Description: + floorl() function: round towards negative infinity. + + Files: + lib/floorl.c + lib/floor.c + m4/floorl.m4 + + Depends-on: + math + extensions + float + + configure.ac: + gl_FUNC_FLOORL + gl_MATH_MODULE_INDICATOR([floorl]) + + Makefile.am: + + Include: + <math.h> + + Link: + $(FLOORL_LIBM) + + License: + LGPL + + Maintainer: + Bruno Haible + *** modules/math.orig 2007-10-05 03:26:02.000000000 +0200 --- modules/math 2007-10-05 03:18:23.000000000 +0200 *************** *** 23,28 **** --- 23,29 ---- sed -e 's/@''INCLUDE_NEXT''@/$(INCLUDE_NEXT)/g' \ -e 's|@''NEXT_MATH_H''@|$(NEXT_MATH_H)|g' \ -e 's|@''GNULIB_FLOORF''@|$(GNULIB_FLOORF)|g' \ + -e 's|@''GNULIB_FLOORL''@|$(GNULIB_FLOORL)|g' \ -e 's|@''GNULIB_FREXP''@|$(GNULIB_FREXP)|g' \ -e 's|@''GNULIB_FREXPL''@|$(GNULIB_FREXPL)|g' \ -e 's|@''GNULIB_LDEXPL''@|$(GNULIB_LDEXPL)|g' \ *** modules/mathl.orig 2007-10-05 03:26:02.000000000 +0200 --- modules/mathl 2007-10-05 03:17:20.000000000 +0200 *************** *** 8,14 **** lib/ceill.c lib/cosl.c lib/expl.c - lib/floorl.c lib/logl.c lib/sincosl.c lib/sinl.c --- 8,13 ---- *************** *** 24,29 **** --- 23,29 ---- frexpl isnanl ldexpl + floorl configure.ac: gl_FUNC_LONG_DOUBLE_MATH