Mercurial > hg > octave-lyh > gnulib-hg
changeset 16676:e9598f93f892
New module 'log2'.
* lib/math.in.h (log2): New declaration.
* lib/log2.c: New file.
* m4/log2.m4: New file.
* m4/math_h.m4 (gl_MATH_H): Test whether log2 is declared.
(gl_MATH_H_DEFAULTS): Initialize GNULIB_LOG2, HAVE_DECL_LOG2,
REPLACE_LOG2.
* modules/math (Makefile.am): Substitute GNULIB_LOG2, HAVE_DECL_LOG2,
REPLACE_LOG2.
* modules/log2: New file.
* tests/test-math-c++.cc: Check the declaration of log2.
* doc/posix-functions/log2.texi: Mention the new module and the IRIX
and OSF/1 and Cygwin problems.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sun, 11 Mar 2012 14:42:17 +0100 |
parents | 801fab1c35f6 |
children | 05117c6c2f05 |
files | ChangeLog doc/posix-functions/log2.texi lib/log2.c lib/math.in.h m4/log2.m4 m4/math_h.m4 modules/log2 modules/math tests/test-math-c++.cc |
diffstat | 9 files changed, 287 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2012-03-11 Bruno Haible <bruno@clisp.org> + + New module 'log2'. + * lib/math.in.h (log2): New declaration. + * lib/log2.c: New file. + * m4/log2.m4: New file. + * m4/math_h.m4 (gl_MATH_H): Test whether log2 is declared. + (gl_MATH_H_DEFAULTS): Initialize GNULIB_LOG2, HAVE_DECL_LOG2, + REPLACE_LOG2. + * modules/math (Makefile.am): Substitute GNULIB_LOG2, HAVE_DECL_LOG2, + REPLACE_LOG2. + * modules/log2: New file. + * tests/test-math-c++.cc: Check the declaration of log2. + * doc/posix-functions/log2.texi: Mention the new module and the IRIX + and OSF/1 and Cygwin problems. + 2012-03-11 Bruno Haible <bruno@clisp.org> exp2* tests: More tests.
--- a/doc/posix-functions/log2.texi +++ b/doc/posix-functions/log2.texi @@ -4,19 +4,28 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/log2.html} -Gnulib module: --- +Gnulib module: log2 Portability problems fixed by Gnulib: @itemize +@item +This function is missing on some platforms: +FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, older IRIX 6.5, +Solaris 9, MSVC 9, Interix 3.5. +@item +This function is not declared on some platforms: +IRIX 6.5. +@item +This function is only provided as a macro on some platforms: +Cygwin 1.5.x. +@item +This function returns a wrong value for a minus zero argument on some platforms: +OSF/1 5.1. +@item +This function returns slightly wrong values for exact powers of 2 on some platforms: +Cygwin 1.7.9. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function is missing on some platforms: -FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, IRIX 6.5, -Solaris 9, MSVC 9, Interix 3.5. -@item -This function is only provided as a macro on some platforms: -Cygwin 1.5.x. @end itemize
new file mode 100644 --- /dev/null +++ b/lib/log2.c @@ -0,0 +1,73 @@ +/* Base 2 logarithm. + 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 <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <math.h> + +/* Best possible approximation of log(2) as a 'double'. */ +#define LOG2 0.693147180559945309417232121458176568075 + +/* Best possible approximation of 1/log(2) as a 'double'. */ +#define LOG2_INVERSE 1.44269504088896340735992468100189213743 + +/* sqrt(0.5). */ +#define SQRT_HALF 0.707106781186547524400844362104849039284 + +double +log2 (double x) +{ + if (isnand (x)) + return x; + + if (x <= 0.0) + { + if (x == 0.0) + /* Return -Infinity. */ + return - HUGE_VAL; + else + { + /* Return NaN. */ +#if defined _MSC_VER || (defined __sgi && !defined __GNUC__) + static double zero; + return zero / zero; +#else + return 0.0 / 0.0; +#endif + } + } + + /* Decompose x into + x = 2^e * y + where + e is an integer, + 1/2 < y < 2. + Then log2(x) = e + log2(y) = e + log(y)/log(2). */ + { + int e; + double y; + + y = frexp (x, &e); + if (y < SQRT_HALF) + { + y = 2.0 * y; + e = e - 1; + } + + return (double) e + log (y) * LOG2_INVERSE; + } +}
--- a/lib/math.in.h +++ b/lib/math.in.h @@ -1291,6 +1291,31 @@ #endif +#if @GNULIB_LOG2@ +# if @REPLACE_LOG2@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef log2 +# define log2 rpl_log2 +# endif +_GL_FUNCDECL_RPL (log2, double, (double x)); +_GL_CXXALIAS_RPL (log2, double, (double x)); +# else +# if !@HAVE_DECL_LOG2@ +# undef log2 +_GL_FUNCDECL_SYS (log2, double, (double x)); +# endif +_GL_CXXALIAS_SYS (log2, double, (double x)); +# endif +_GL_CXXALIASWARN (log2); +#elif defined GNULIB_POSIXCHECK +# undef log2 +# if HAVE_RAW_DECL_LOG2 +_GL_WARN_ON_USE (log2, "log2 is unportable - " + "use gnulib module log2 for portability"); +# endif +#endif + + #if @GNULIB_MODFF@ # if @REPLACE_MODFF@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE)
new file mode 100644 --- /dev/null +++ b/m4/log2.m4 @@ -0,0 +1,109 @@ +# log2.m4 serial 1 +dnl Copyright (C) 2010-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_LOG2], +[ + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + + dnl Persuade glibc <math.h> to declare log2(). + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + + dnl Determine LOG2_LIBM. + gl_COMMON_DOUBLE_MATHFUNC([log2]) + + dnl Test whether log2() exists. + save_LIBS="$LIBS" + LIBS="$LIBS $LOG2_LIBM" + AC_CHECK_FUNCS([log2]) + LIBS="$save_LIBS" + if test $ac_cv_func_log2 = yes; then + HAVE_LOG2=1 + dnl Also check whether it's declared. + dnl IRIX 6.5 has log2() in libm but doesn't declare it in <math.h>. + AC_CHECK_DECL([log2], , [HAVE_DECL_LOG2=0], [[#include <math.h>]]) + + save_LIBS="$LIBS" + LIBS="$LIBS $LOG2_LIBM" + gl_FUNC_LOG2_WORKS + LIBS="$save_LIBS" + case "$gl_cv_func_log2_works" in + *yes) ;; + *) REPLACE_LOG2=1 ;; + esac + else + HAVE_LOG2=0 + HAVE_DECL_LOG2=0 + fi + if test $HAVE_LOG2 = 0 || test $REPLACE_LOG2 = 1; then + dnl Find libraries needed to link lib/log2.c. + AC_REQUIRE([gl_FUNC_ISNAND]) + AC_REQUIRE([gl_FUNC_FREXP]) + AC_REQUIRE([gl_FUNC_LOG]) + LOG2_LIBM= + dnl Append $ISNAND_LIBM to LOG2_LIBM, avoiding gratuitous duplicates. + case " $LOG2_LIBM " in + *" $ISNAND_LIBM "*) ;; + *) LOG2_LIBM="$LOG2_LIBM $ISNAND_LIBM" ;; + esac + dnl Append $FREXP_LIBM to LOG2_LIBM, avoiding gratuitous duplicates. + case " $LOG2_LIBM " in + *" $FREXP_LIBM "*) ;; + *) LOG2_LIBM="$LOG2_LIBM $FREXP_LIBM" ;; + esac + dnl Append $LOG_LIBM to LOG2_LIBM, avoiding gratuitous duplicates. + case " $LOG2_LIBM " in + *" $LOG_LIBM "*) ;; + *) LOG2_LIBM="$LOG2_LIBM $LOG_LIBM" ;; + esac + fi +]) + +dnl Test whether log2() works. +dnl On OSF/1 5.1, log2(-0.0) is NaN. +dnl On Cygwin 1.7.9, log2(2^29) is not exactly 29. +AC_DEFUN([gl_FUNC_LOG2_WORKS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether log2 works], [gl_cv_func_log2_works], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include <math.h> +#ifndef log2 /* for Cygwin 1.7.x */ +extern +#ifdef __cplusplus +"C" +#endif +double log2 (double); +#endif +volatile double x; +volatile double y; +int main () +{ + int result = 0; + /* This test fails on OSF/1 5.1. */ + x = -0.0; + y = log2 (x); + if (!(y + y == y)) + result |= 1; + /* This test fails on Cygwin 1.7.9. */ + x = 536870912.0; + y = log2 (x); + if (!(y == 29.0)) + result |= 2; + return result; +} +]])], + [gl_cv_func_log2_works=yes], + [gl_cv_func_log2_works=no], + [case "$host_os" in + cygwin* | osf*) gl_cv_func_log2_works="guessing no";; + *) gl_cv_func_log2_works="guessing yes";; + esac + ]) + ]) +])
--- a/m4/math_h.m4 +++ b/m4/math_h.m4 @@ -1,4 +1,4 @@ -# math_h.m4 serial 100 +# math_h.m4 serial 101 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, @@ -44,7 +44,7 @@ expf expl exp2 exp2f exp2l expm1 expm1f expm1l fabsf fabsl floorf floorl fma fmaf fmal fmod fmodf fmodl frexpf frexpl hypotf hypotl - ldexpf ldexpl logb log logf logl log10f log10l log1p log1pf log1pl + ldexpf ldexpl logb log logf logl log10f log10l log1p log1pf log1pl log2 modf modff modfl powf remainder remainderf remainderl rint rintf rintl round roundf roundl sinf sinl sinhf sqrtf sqrtl @@ -123,6 +123,7 @@ GNULIB_LOG1P=0; AC_SUBST([GNULIB_LOG1P]) GNULIB_LOG1PF=0; AC_SUBST([GNULIB_LOG1PF]) GNULIB_LOG1PL=0; AC_SUBST([GNULIB_LOG1PL]) + GNULIB_LOG2=0; AC_SUBST([GNULIB_LOG2]) GNULIB_MODF=0; AC_SUBST([GNULIB_MODF]) GNULIB_MODFF=0; AC_SUBST([GNULIB_MODFF]) GNULIB_MODFL=0; AC_SUBST([GNULIB_MODFL]) @@ -225,6 +226,7 @@ HAVE_DECL_LOGB=1; AC_SUBST([HAVE_DECL_LOGB]) HAVE_DECL_LOGL=1; AC_SUBST([HAVE_DECL_LOGL]) HAVE_DECL_LOG10L=1; AC_SUBST([HAVE_DECL_LOG10L]) + HAVE_DECL_LOG2=1; AC_SUBST([HAVE_DECL_LOG2]) HAVE_DECL_REMAINDER=1; AC_SUBST([HAVE_DECL_REMAINDER]) HAVE_DECL_REMAINDERL=1; AC_SUBST([HAVE_DECL_REMAINDERL]) HAVE_DECL_RINTF=1; AC_SUBST([HAVE_DECL_RINTF]) @@ -273,6 +275,7 @@ REPLACE_LOG1P=0; AC_SUBST([REPLACE_LOG1P]) REPLACE_LOG1PF=0; AC_SUBST([REPLACE_LOG1PF]) REPLACE_LOG1PL=0; AC_SUBST([REPLACE_LOG1PL]) + REPLACE_LOG2=0; AC_SUBST([REPLACE_LOG2]) REPLACE_MODF=0; AC_SUBST([REPLACE_MODF]) REPLACE_MODFF=0; AC_SUBST([REPLACE_MODFF]) REPLACE_MODFL=0; AC_SUBST([REPLACE_MODFL])
new file mode 100644 --- /dev/null +++ b/modules/log2 @@ -0,0 +1,35 @@ +Description: +log2() function: base 2 logarithm. + +Files: +lib/log2.c +m4/log2.m4 +m4/mathfunc.m4 + +Depends-on: +math +extensions +isnand [test $HAVE_LOG2 = 0 || test $REPLACE_LOG2 = 1] +frexp [test $HAVE_LOG2 = 0 || test $REPLACE_LOG2 = 1] +log [test $HAVE_LOG2 = 0 || test $REPLACE_LOG2 = 1] + +configure.ac: +gl_FUNC_LOG2 +if test $HAVE_LOG2 = 0 || test $REPLACE_LOG2 = 1; then + AC_LIBOBJ([log2]) +fi +gl_MATH_MODULE_INDICATOR([log2]) + +Makefile.am: + +Include: +<math.h> + +Link: +$(LOG2_LIBM) + +License: +LGPL + +Maintainer: +Bruno Haible
--- a/modules/math +++ b/modules/math @@ -89,6 +89,7 @@ -e 's/@''GNULIB_LOG1P''@/$(GNULIB_LOG1P)/g' \ -e 's/@''GNULIB_LOG1PF''@/$(GNULIB_LOG1PF)/g' \ -e 's/@''GNULIB_LOG1PL''@/$(GNULIB_LOG1PL)/g' \ + -e 's/@''GNULIB_LOG2''@/$(GNULIB_LOG2)/g' \ -e 's/@''GNULIB_MODF''@/$(GNULIB_MODF)/g' \ -e 's/@''GNULIB_MODFF''@/$(GNULIB_MODFF)/g' \ -e 's/@''GNULIB_MODFL''@/$(GNULIB_MODFL)/g' \ @@ -191,6 +192,7 @@ -e 's|@''HAVE_DECL_LOGB''@|$(HAVE_DECL_LOGB)|g' \ -e 's|@''HAVE_DECL_LOGL''@|$(HAVE_DECL_LOGL)|g' \ -e 's|@''HAVE_DECL_LOG10L''@|$(HAVE_DECL_LOG10L)|g' \ + -e 's|@''HAVE_DECL_LOG2''@|$(HAVE_DECL_LOG2)|g' \ -e 's|@''HAVE_DECL_REMAINDER''@|$(HAVE_DECL_REMAINDER)|g' \ -e 's|@''HAVE_DECL_REMAINDERL''@|$(HAVE_DECL_REMAINDERL)|g' \ -e 's|@''HAVE_DECL_RINTF''@|$(HAVE_DECL_RINTF)|g' \ @@ -241,6 +243,7 @@ -e 's|@''REPLACE_LOG1P''@|$(REPLACE_LOG1P)|g' \ -e 's|@''REPLACE_LOG1PF''@|$(REPLACE_LOG1PF)|g' \ -e 's|@''REPLACE_LOG1PL''@|$(REPLACE_LOG1PL)|g' \ + -e 's|@''REPLACE_LOG2''@|$(REPLACE_LOG2)|g' \ -e 's|@''REPLACE_MODF''@|$(REPLACE_MODF)|g' \ -e 's|@''REPLACE_MODFF''@|$(REPLACE_MODFF)|g' \ -e 's|@''REPLACE_MODFL''@|$(REPLACE_MODFL)|g' \
--- a/tests/test-math-c++.cc +++ b/tests/test-math-c++.cc @@ -241,6 +241,10 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::log10f, float, (float)); #endif +#if GNULIB_TEST_LOG2 +SIGNATURE_CHECK (GNULIB_NAMESPACE::log2, double, (double)); +#endif + #if GNULIB_TEST_MODFF SIGNATURE_CHECK (GNULIB_NAMESPACE::modff, float, (float, float *)); #endif