From: Bruno Haible Date: Tue, 3 Apr 2012 10:53:31 +0000 (+0200) Subject: New module 'logbl'. X-Git-Tag: v0.1~771 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=032debd69f3b84239767c727598fb3237a3eeaca;p=gnulib.git New module 'logbl'. * lib/math.in.h (logbl): New declaration. * lib/logbl.c: New file. * m4/logbl.m4: New file. * m4/math_h.m4 (gl_MATH_H): Test whether logbl is declared. (gl_MATH_H_DEFAULTS): Initialize GNULIB_LOGBL, HAVE_LOGBL, REPLACE_LOGBL. * modules/math (Makefile.am): Substitute GNULIB_LOGBL, HAVE_LOGBL, REPLACE_LOGBL. * modules/logbl: New file. * tests/test-math-c++.cc: Check the declaration of logbl. * doc/posix-functions/logbl.texi: Mention the new module. --- diff --git a/ChangeLog b/ChangeLog index 967e53a78..10d0412a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2012-04-03 Bruno Haible + + New module 'logbl'. + * lib/math.in.h (logbl): New declaration. + * lib/logbl.c: New file. + * m4/logbl.m4: New file. + * m4/math_h.m4 (gl_MATH_H): Test whether logbl is declared. + (gl_MATH_H_DEFAULTS): Initialize GNULIB_LOGBL, HAVE_LOGBL, + REPLACE_LOGBL. + * modules/math (Makefile.am): Substitute GNULIB_LOGBL, HAVE_LOGBL, + REPLACE_LOGBL. + * modules/logbl: New file. + * tests/test-math-c++.cc: Check the declaration of logbl. + * doc/posix-functions/logbl.texi: Mention the new module. + 2012-04-02 Bruno Haible Tests for module 'logbf'. diff --git a/doc/posix-functions/logbl.texi b/doc/posix-functions/logbl.texi index 8ad3e9628..fd9c384d9 100644 --- a/doc/posix-functions/logbl.texi +++ b/doc/posix-functions/logbl.texi @@ -4,15 +4,18 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/logbl.html} -Gnulib module: --- +Gnulib module: logbl Portability problems fixed by Gnulib: @itemize +@item +This function is missing on some platforms: +FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, older IRIX 6.5, Solaris 9, Cygwin, MSVC 9, Interix 3.5, BeOS. +@item +This function produces wrong results for subnormal numbers on some platforms: +glibc 2.11/ppc, glibc 2.7/sparc, glibc 2.7/hppa, Solaris 11 2011-11. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on some platforms: -FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 9, Cygwin, MSVC 9, Interix 3.5, BeOS. @end itemize diff --git a/lib/logbl.c b/lib/logbl.c new file mode 100644 index 000000000..04b204726 --- /dev/null +++ b/lib/logbl.c @@ -0,0 +1,35 @@ +/* Floating-point exponent. + Copyright (C) 2012 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 . */ + +#include + +/* Specification. */ +#include + +#if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE + +long double +logbl (long double x) +{ + return logb (x); +} + +#else + +# define USE_LONG_DOUBLE +# include "logb.c" + +#endif diff --git a/lib/math.in.h b/lib/math.in.h index 247c64417..10cabe0ac 100644 --- a/lib/math.in.h +++ b/lib/math.in.h @@ -1434,6 +1434,29 @@ _GL_WARN_ON_USE (logb, "logb is unportable - " # endif #endif +#if @GNULIB_LOGBL@ +# if @REPLACE_LOGBL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef logbl +# define logbl rpl_logbl +# endif +_GL_FUNCDECL_RPL (logbl, long double, (long double x)); +_GL_CXXALIAS_RPL (logbl, long double, (long double x)); +# else +# if !@HAVE_LOGBL@ +_GL_FUNCDECL_SYS (logbl, long double, (long double x)); +# endif +_GL_CXXALIAS_SYS (logbl, long double, (long double x)); +# endif +_GL_CXXALIASWARN (logbl); +#elif defined GNULIB_POSIXCHECK +# undef logbl +# if HAVE_RAW_DECL_LOGBL +_GL_WARN_ON_USE (logbl, "logbl is unportable - " + "use gnulib module logbl for portability"); +# endif +#endif + #if @GNULIB_MODFF@ # if @REPLACE_MODFF@ diff --git a/m4/logbl.m4 b/m4/logbl.m4 new file mode 100644 index 000000000..44458760e --- /dev/null +++ b/m4/logbl.m4 @@ -0,0 +1,108 @@ +# logbl.m4 serial 1 +dnl Copyright (C) 2012 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_LOGBL], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE]) + AC_REQUIRE([gl_FUNC_LOGB]) + + dnl Persuade glibc to declare logbl(). + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + + dnl Test whether logbl() exists and determine LOGBL_LIBM. We cannot assume + dnl that logbl(), if it exists, is defined in the same library as logb(). + dnl This is not the case on AIX >= 5.2, Solaris >= 10. + gl_MATHFUNC([logbl], [long double], [(long double)]) + if test $gl_cv_func_logbl_no_libm = yes \ + || test $gl_cv_func_logbl_in_libm = yes; then + save_LIBS="$LIBS" + LIBS="$LIBS $LOGBL_LIBM" + gl_FUNC_LOGBL_WORKS + LIBS="$save_LIBS" + case "$gl_cv_func_logbl_works" in + *yes) ;; + *) REPLACE_LOGBL=1 ;; + esac + else + HAVE_LOGBL=0 + fi + if test $HAVE_LOGBL = 0 || test $REPLACE_LOGBL = 1; then + dnl Find libraries needed to link lib/logbl.c. + if test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1; then + LOGBL_LIBM="$LOGB_LIBM" + else + AC_REQUIRE([gl_FUNC_FREXPL]) + AC_REQUIRE([gl_FUNC_ISNANL]) + LOGBL_LIBM= + dnl Append $FREXPL_LIBM to LOGBL_LIBM, avoiding gratuitous duplicates. + case " $LOGBL_LIBM " in + *" $FREXPL_LIBM "*) ;; + *) LOGBL_LIBM="$LOGBL_LIBM $FREXPL_LIBM" ;; + esac + dnl Append $ISNANL_LIBM to LOGBL_LIBM, avoiding gratuitous duplicates. + case " $LOGBL_LIBM " in + *" $ISNANL_LIBM "*) ;; + *) LOGBL_LIBM="$LOGBL_LIBM $ISNANL_LIBM" ;; + esac + fi + fi + AC_SUBST([LOGBL_LIBM]) +]) + +dnl Test whether logbl() works. +dnl On glibc 2.11/ppc, glibc 2.7/sparc, glibc 2.7/hppa, Solaris 10/SPARC, the +dnl return value for subnormal (denormalized) arguments is too large. +AC_DEFUN([gl_FUNC_LOGBL_WORKS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether logbl works], [gl_cv_func_logbl_works], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +/* Override the values of , like done in float.in.h. */ +#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__) +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP (-16381) +#endif +#if defined __i386__ && defined __FreeBSD__ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP (-16381) +#endif +#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP DBL_MIN_EXP +#endif +#if defined __sgi && (LDBL_MANT_DIG >= 106) +# if defined __GNUC__ +# undef LDBL_MIN_EXP +# define LDBL_MIN_EXP DBL_MIN_EXP +# endif +#endif +volatile long double x; +int main () +{ + int i; + for (i = 1, x = 1.0L; i >= LDBL_MIN_EXP - 54; i--, x *= 0.5L) + /* Either x = 2^(i-1) or x = 0.0. */ + if ((i == LDBL_MIN_EXP - 1 || i == LDBL_MIN_EXP - 54) + && (x > 0.0L && !(logbl (x) == (long double)(i - 1)))) + return 1; + return 0; +} +]])], + [gl_cv_func_logbl_works=yes], + [gl_cv_func_logbl_works=no], + [case "$host_os" in + *gnu* | solaris*) gl_cv_func_logbl_works="guessing no";; + *) gl_cv_func_logbl_works="guessing yes";; + esac + ]) + ]) +]) diff --git a/m4/math_h.m4 b/m4/math_h.m4 index 6f606651f..ef97a600d 100644 --- a/m4/math_h.m4 +++ b/m4/math_h.m4 @@ -1,4 +1,4 @@ -# math_h.m4 serial 109 +# math_h.m4 serial 110 dnl Copyright (C) 2007-2012 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -46,7 +46,7 @@ AC_DEFUN([gl_MATH_H], fmod fmodf fmodl frexpf frexpl hypotf hypotl ldexpf ldexpl log logf logl log10 log10f log10l log1p log1pf log1pl log2 log2f log2l - logb logbf + logb logbf logbl modf modff modfl powf remainder remainderf remainderl rint rintf rintl round roundf roundl sinf sinl sinhf sqrtf sqrtl @@ -130,6 +130,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS], GNULIB_LOG2L=0; AC_SUBST([GNULIB_LOG2L]) GNULIB_LOGB=0; AC_SUBST([GNULIB_LOGB]) GNULIB_LOGBF=0; AC_SUBST([GNULIB_LOGBF]) + GNULIB_LOGBL=0; AC_SUBST([GNULIB_LOGBL]) GNULIB_MODF=0; AC_SUBST([GNULIB_MODF]) GNULIB_MODFF=0; AC_SUBST([GNULIB_MODFF]) GNULIB_MODFL=0; AC_SUBST([GNULIB_MODFL]) @@ -197,6 +198,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS], HAVE_LOG1PF=1; AC_SUBST([HAVE_LOG1PF]) HAVE_LOG1PL=1; AC_SUBST([HAVE_LOG1PL]) HAVE_LOGBF=1; AC_SUBST([HAVE_LOGBF]) + HAVE_LOGBL=1; AC_SUBST([HAVE_LOGBL]) HAVE_MODFF=1; AC_SUBST([HAVE_MODFF]) HAVE_MODFL=1; AC_SUBST([HAVE_MODFL]) HAVE_POWF=1; AC_SUBST([HAVE_POWF]) @@ -292,6 +294,7 @@ AC_DEFUN([gl_MATH_H_DEFAULTS], REPLACE_LOG2L=0; AC_SUBST([REPLACE_LOG2L]) REPLACE_LOGB=0; AC_SUBST([REPLACE_LOGB]) REPLACE_LOGBF=0; AC_SUBST([REPLACE_LOGBF]) + REPLACE_LOGBL=0; AC_SUBST([REPLACE_LOGBL]) REPLACE_MODF=0; AC_SUBST([REPLACE_MODF]) REPLACE_MODFF=0; AC_SUBST([REPLACE_MODFF]) REPLACE_MODFL=0; AC_SUBST([REPLACE_MODFL]) diff --git a/modules/logbl b/modules/logbl new file mode 100644 index 000000000..b58e9456d --- /dev/null +++ b/modules/logbl @@ -0,0 +1,37 @@ +Description: +logbl() function: get exponent. + +Files: +lib/logbl.c +lib/logb.c +m4/logbl.m4 +m4/mathfunc.m4 + +Depends-on: +math +extensions +logb [{ test $HAVE_LOGBL = 0 || test $REPLACE_LOGBL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1] +isfinite [{ test $HAVE_LOGBL = 0 || test $REPLACE_LOGBL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0] +frexpl [{ test $HAVE_LOGBL = 0 || test $REPLACE_LOGBL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0] +isnanl [{ test $HAVE_LOGBL = 0 || test $REPLACE_LOGBL = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 0] + +configure.ac: +gl_FUNC_LOGBL +if test $HAVE_LOGBL = 0 || test $REPLACE_LOGBL = 1; then + AC_LIBOBJ([logbl]) +fi +gl_MATH_MODULE_INDICATOR([logbl]) + +Makefile.am: + +Include: + + +Link: +$(LOGBL_LIBM) + +License: +LGPL + +Maintainer: +Bruno Haible diff --git a/modules/math b/modules/math index 440aa7856..b83edfd22 100644 --- a/modules/math +++ b/modules/math @@ -94,6 +94,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $( -e 's/@''GNULIB_LOG2L''@/$(GNULIB_LOG2L)/g' \ -e 's/@''GNULIB_LOGB''@/$(GNULIB_LOGB)/g' \ -e 's/@''GNULIB_LOGBF''@/$(GNULIB_LOGBF)/g' \ + -e 's/@''GNULIB_LOGBL''@/$(GNULIB_LOGBL)/g' \ -e 's/@''GNULIB_MODF''@/$(GNULIB_MODF)/g' \ -e 's/@''GNULIB_MODFF''@/$(GNULIB_MODFF)/g' \ -e 's/@''GNULIB_MODFL''@/$(GNULIB_MODFL)/g' \ @@ -161,6 +162,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $( -e 's|@''HAVE_LOG1PF''@|$(HAVE_LOG1PF)|g' \ -e 's|@''HAVE_LOG1PL''@|$(HAVE_LOG1PL)|g' \ -e 's|@''HAVE_LOGBF''@|$(HAVE_LOGBF)|g' \ + -e 's|@''HAVE_LOGBL''@|$(HAVE_LOGBL)|g' \ -e 's|@''HAVE_MODFF''@|$(HAVE_MODFF)|g' \ -e 's|@''HAVE_MODFL''@|$(HAVE_MODFL)|g' \ -e 's|@''HAVE_POWF''@|$(HAVE_POWF)|g' \ @@ -258,6 +260,7 @@ math.h: math.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $( -e 's|@''REPLACE_LOG2L''@|$(REPLACE_LOG2L)|g' \ -e 's|@''REPLACE_LOGB''@|$(REPLACE_LOGB)|g' \ -e 's|@''REPLACE_LOGBF''@|$(REPLACE_LOGBF)|g' \ + -e 's|@''REPLACE_LOGBL''@|$(REPLACE_LOGBL)|g' \ -e 's|@''REPLACE_MODF''@|$(REPLACE_MODF)|g' \ -e 's|@''REPLACE_MODFF''@|$(REPLACE_MODFF)|g' \ -e 's|@''REPLACE_MODFL''@|$(REPLACE_MODFL)|g' \ diff --git a/tests/test-math-c++.cc b/tests/test-math-c++.cc index 1821dd29d..2c616b36f 100644 --- a/tests/test-math-c++.cc +++ b/tests/test-math-c++.cc @@ -257,6 +257,9 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::logbf, float, (float)); #if GNULIB_TEST_LOGB SIGNATURE_CHECK (GNULIB_NAMESPACE::logb, double, (double)); #endif +#if GNULIB_TEST_LOGBL +SIGNATURE_CHECK (GNULIB_NAMESPACE::logbl, long double, (long double)); +#endif #if GNULIB_TEST_MODFF SIGNATURE_CHECK (GNULIB_NAMESPACE::modff, float, (float, float *));