Mercurial > hg > octave-kai > gnulib-hg
changeset 16530:3cae6aa4577f
hypot-ieee: Work around test failure on OSF/1 and native Windows.
* lib/math.in.h (hypot): New declaration.
* lib/hypot.c: New file.
* m4/hypot-ieee.m4: New file.
* m4/hypot.m4 (gl_FUNC_HYPOT): If gl_FUNC_HYPOT_IEEE is present, test
whether hypot works with mixed NaN and Infinity arguments. Replace it
if not.
* m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize GNULIB_HYPOT,
REPLACE_HYPOT.
* modules/math (Makefile.am): Substitute GNULIB_HYPOT, REPLACE_HYPOT.
* modules/hypot (Files): Add lib/hypot.c.
(Depends-on): Add dependencies.
(configure.ac): Arrange to compile replacement if REPLACE_HYPOT is 1.
* modules/hypot-ieee (Files): Add m4/hypot-ieee.m4.
(configure.ac): Invoke gl_FUNC_HYPOT_IEEE.
* tests/test-math-c++.cc: Check the declaration of hypot.
* doc/posix-functions/hypot.texi: Mention the hypot-ieee module.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Wed, 29 Feb 2012 20:00:38 +0100 |
parents | 4e6611458e9e |
children | 89e5e3b8457d |
files | ChangeLog doc/posix-functions/hypot.texi lib/hypot.c lib/math.in.h m4/hypot-ieee.m4 m4/hypot.m4 m4/math_h.m4 modules/hypot modules/hypot-ieee modules/math tests/test-math-c++.cc |
diffstat | 11 files changed, 245 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,23 @@ 2012-02-29 Bruno Haible <bruno@clisp.org> + hypot-ieee: Work around test failure on OSF/1 and native Windows. + * lib/math.in.h (hypot): New declaration. + * lib/hypot.c: New file. + * m4/hypot-ieee.m4: New file. + * m4/hypot.m4 (gl_FUNC_HYPOT): If gl_FUNC_HYPOT_IEEE is present, test + whether hypot works with mixed NaN and Infinity arguments. Replace it + if not. + * m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize GNULIB_HYPOT, + REPLACE_HYPOT. + * modules/math (Makefile.am): Substitute GNULIB_HYPOT, REPLACE_HYPOT. + * modules/hypot (Files): Add lib/hypot.c. + (Depends-on): Add dependencies. + (configure.ac): Arrange to compile replacement if REPLACE_HYPOT is 1. + * modules/hypot-ieee (Files): Add m4/hypot-ieee.m4. + (configure.ac): Invoke gl_FUNC_HYPOT_IEEE. + * tests/test-math-c++.cc: Check the declaration of hypot. + * doc/posix-functions/hypot.texi: Mention the hypot-ieee module. + Tests for module 'hypotl-ieee'. * modules/hypotl-ieee-tests: New file. * tests/test-hypotl-ieee.c: New file.
--- a/doc/posix-functions/hypot.texi +++ b/doc/posix-functions/hypot.texi @@ -4,10 +4,18 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/hypot.html} -Gnulib module: hypot +Gnulib module: hypot or hypot-ieee + +Portability problems fixed by either Gnulib module @code{hypot} or @code{hypot-ieee}: +@itemize +@end itemize -Portability problems fixed by Gnulib: +Portability problems fixed by Gnulib module @code{hypot-ieee}: @itemize +@item +When the arguments are mixed NaN and Infinity, this function returns a wrong +value on some platforms: +OSF/1 5.1, mingw, MSVC 9. @end itemize Portability problems not fixed by Gnulib:
new file mode 100644 --- /dev/null +++ b/lib/hypot.c @@ -0,0 +1,79 @@ +/* Hypotenuse of a right-angled triangle. + 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/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2012. */ + +#include <config.h> + +/* Specification. */ +#include <math.h> + +double +hypot (double x, double y) +{ + if (isfinite (x) && isfinite (y)) + { + /* Determine absolute values. */ + x = fabs (x); + y = fabs (y); + + { + /* Find the bigger and the smaller one. */ + double a; + double b; + + if (x >= y) + { + a = x; + b = y; + } + else + { + a = y; + b = x; + } + /* Now 0 <= b <= a. */ + + { + int e; + double an; + double bn; + + /* Write a = an * 2^e, b = bn * 2^e with 0 <= bn <= an < 1. */ + an = frexp (a, &e); + bn = ldexp (b, - e); + + { + double cn; + + /* Through the normalization, no unneeded overflow or underflow + will occur here. */ + cn = sqrt (an * an + bn * bn); + return ldexp (cn, e); + } + } + } + } + else + { + if (isinf (x) || isinf (y)) + /* x or y is infinite. Return +Infinity. */ + return HUGE_VAL; + else + /* x or y is NaN. Return NaN. */ + return x + y; + } +}
--- a/lib/math.in.h +++ b/lib/math.in.h @@ -833,6 +833,27 @@ #endif /* Return sqrt(x^2+y^2). */ +#if @GNULIB_HYPOT@ +# if @REPLACE_HYPOT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef hypot +# define hypot rpl_hypot +# endif +_GL_FUNCDECL_RPL (hypot, double, (double x, double y)); +_GL_CXXALIAS_RPL (hypot, double, (double x, double y)); +# else +_GL_CXXALIAS_SYS (hypot, double, (double x, double y)); +# endif +_GL_CXXALIASWARN (hypot); +#elif defined GNULIB_POSIXCHECK +# undef hypot +# if HAVE_RAW_DECL_HYPOT +_GL_WARN_ON_USE (hypotf, "hypot has portability problems - " + "use gnulib module hypot for portability"); +# endif +#endif + +/* Return sqrt(x^2+y^2). */ #if @GNULIB_HYPOTL@ # if !@HAVE_HYPOTL@ _GL_FUNCDECL_SYS (hypotl, long double, (long double x, long double y));
new file mode 100644 --- /dev/null +++ b/m4/hypot-ieee.m4 @@ -0,0 +1,15 @@ +# hypot-ieee.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. + +dnl This macro is in a separate file (not in hypot.m4 and not inlined in the +dnl module description), so that gl_FUNC_HYPOT can test whether 'aclocal' has +dnl found uses of this macro. + +AC_DEFUN([gl_FUNC_HYPOT_IEEE], +[ + m4_divert_text([INIT_PREPARE], [gl_hypot_required=ieee]) + AC_REQUIRE([gl_FUNC_HYPOT]) +])
--- a/m4/hypot.m4 +++ b/m4/hypot.m4 @@ -1,4 +1,4 @@ -# hypot.m4 serial 1 +# hypot.m4 serial 2 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, @@ -6,6 +6,85 @@ AC_DEFUN([gl_FUNC_HYPOT], [ + m4_divert_text([DEFAULTS], [gl_hypot_required=plain]) + AC_REQUIRE([gl_MATH_H_DEFAULTS]) + dnl Determine HYPOT_LIBM. gl_COMMON_DOUBLE_MATHFUNC([hypot]) + + m4_ifdef([gl_FUNC_HYPOT_IEEE], [ + if test $gl_hypot_required = ieee && test $REPLACE_HYPOT = 0; then + AC_CACHE_CHECK([whether hypot works according to ISO C 99 with IEC 60559], + [gl_cv_func_hypot_ieee], + [ + save_LIBS="$LIBS" + LIBS="$LIBS $HYPOT_LIBM" + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#ifndef __NO_MATH_INLINES +# define __NO_MATH_INLINES 1 /* for glibc */ +#endif +#include <math.h> +/* Compare two numbers with ==. + This is a separate function because IRIX 6.5 "cc -O" miscompiles an + 'x == x' test. */ +static int +numeric_equal (double x, double y) +{ + return x == y; +} +static double dummy (double x, double y) { return 0; } +double zero; +double one = 1.0; +int main (int argc, char *argv[]) +{ + double (*my_hypot) (double, double) = argc ? hypot : dummy; + double f; + /* Test hypot(NaN,Infinity). + This test fails on OSF/1 5.1 and native Windows. */ + f = my_hypot (zero / zero, one / zero); + if (!numeric_equal (f, f)) + return 1; + return 0; +} + ]])], + [gl_cv_func_hypot_ieee=yes], + [gl_cv_func_hypot_ieee=no], + [gl_cv_func_hypot_ieee="guessing no"]) + LIBS="$save_LIBS" + ]) + case "$gl_cv_func_hypot_ieee" in + *yes) ;; + *) REPLACE_HYPOT=1 ;; + esac + fi + ]) + if test $REPLACE_HYPOT = 1; then + dnl Find libraries needed to link lib/hypot.c. + AC_REQUIRE([gl_FUNC_FABS]) + AC_REQUIRE([gl_FUNC_FREXP]) + AC_REQUIRE([gl_FUNC_LDEXP]) + AC_REQUIRE([gl_FUNC_SQRT]) + HYPOT_LIBM= + dnl Append $FABS_LIBM to HYPOT_LIBM, avoiding gratuitous duplicates. + case " $HYPOT_LIBM " in + *" $FABS_LIBM "*) ;; + *) HYPOT_LIBM="$HYPOT_LIBM $FABS_LIBM" ;; + esac + dnl Append $FREXP_LIBM to HYPOT_LIBM, avoiding gratuitous duplicates. + case " $HYPOT_LIBM " in + *" $FREXP_LIBM "*) ;; + *) HYPOT_LIBM="$HYPOT_LIBM $FREXP_LIBM" ;; + esac + dnl Append $LDEXP_LIBM to HYPOT_LIBM, avoiding gratuitous duplicates. + case " $HYPOT_LIBM " in + *" $LDEXP_LIBM "*) ;; + *) HYPOT_LIBM="$HYPOT_LIBM $LDEXP_LIBM" ;; + esac + dnl Append $SQRT_LIBM to HYPOT_LIBM, avoiding gratuitous duplicates. + case " $HYPOT_LIBM " in + *" $SQRT_LIBM "*) ;; + *) HYPOT_LIBM="$HYPOT_LIBM $SQRT_LIBM" ;; + esac + fi ])
--- a/m4/math_h.m4 +++ b/m4/math_h.m4 @@ -1,4 +1,4 @@ -# math_h.m4 serial 73 +# math_h.m4 serial 74 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, @@ -92,6 +92,7 @@ GNULIB_FREXPF=0; AC_SUBST([GNULIB_FREXPF]) GNULIB_FREXP=0; AC_SUBST([GNULIB_FREXP]) GNULIB_FREXPL=0; AC_SUBST([GNULIB_FREXPL]) + GNULIB_HYPOT=0; AC_SUBST([GNULIB_HYPOT]) GNULIB_HYPOTF=0; AC_SUBST([GNULIB_HYPOTF]) GNULIB_HYPOTL=0; AC_SUBST([GNULIB_HYPOTL]) GNULIB_ISFINITE=0; AC_SUBST([GNULIB_ISFINITE]) @@ -224,6 +225,7 @@ REPLACE_FREXP=0; AC_SUBST([REPLACE_FREXP]) REPLACE_FREXPL=0; AC_SUBST([REPLACE_FREXPL]) REPLACE_HUGE_VAL=0; AC_SUBST([REPLACE_HUGE_VAL]) + REPLACE_HYPOT=0; AC_SUBST([REPLACE_HYPOT]) REPLACE_HYPOTF=0; AC_SUBST([REPLACE_HYPOTF]) REPLACE_ISFINITE=0; AC_SUBST([REPLACE_ISFINITE]) REPLACE_ISINF=0; AC_SUBST([REPLACE_ISINF])
--- a/modules/hypot +++ b/modules/hypot @@ -2,13 +2,25 @@ hypot() function: length of a vector in the plane. Files: +lib/hypot.c m4/hypot.m4 m4/mathfunc.m4 Depends-on: +math +isfinite [test $REPLACE_HYPOT = 1] +fabs [test $REPLACE_HYPOT = 1] +frexp [test $REPLACE_HYPOT = 1] +ldexp [test $REPLACE_HYPOT = 1] +sqrt [test $REPLACE_HYPOT = 1] +isinf [test $REPLACE_HYPOT = 1] configure.ac: gl_FUNC_HYPOT +if test $REPLACE_HYPOT = 1; then + AC_LIBOBJ([hypot]) +fi +gl_MATH_MODULE_INDICATOR([hypot]) Makefile.am:
--- a/modules/hypot-ieee +++ b/modules/hypot-ieee @@ -2,12 +2,14 @@ hypot() function according to ISO C 99 with IEC 60559. Files: +m4/hypot-ieee.m4 Depends-on: hypot fpieee configure.ac: +gl_FUNC_HYPOT_IEEE Makefile.am:
--- a/modules/math +++ b/modules/math @@ -60,6 +60,7 @@ -e 's/@''GNULIB_FREXPF''@/$(GNULIB_FREXPF)/g' \ -e 's/@''GNULIB_FREXP''@/$(GNULIB_FREXP)/g' \ -e 's/@''GNULIB_FREXPL''@/$(GNULIB_FREXPL)/g' \ + -e 's/@''GNULIB_HYPOT''@/$(GNULIB_HYPOT)/g' \ -e 's/@''GNULIB_HYPOTF''@/$(GNULIB_HYPOTF)/g' \ -e 's/@''GNULIB_HYPOTL''@/$(GNULIB_HYPOTL)/g' \ -e 's/@''GNULIB_ISFINITE''@/$(GNULIB_ISFINITE)/g' \ @@ -193,6 +194,7 @@ -e 's|@''REPLACE_FREXP''@|$(REPLACE_FREXP)|g' \ -e 's|@''REPLACE_FREXPL''@|$(REPLACE_FREXPL)|g' \ -e 's|@''REPLACE_HUGE_VAL''@|$(REPLACE_HUGE_VAL)|g' \ + -e 's|@''REPLACE_HYPOT''@|$(REPLACE_HYPOT)|g' \ -e 's|@''REPLACE_HYPOTF''@|$(REPLACE_HYPOTF)|g' \ -e 's|@''REPLACE_ISFINITE''@|$(REPLACE_ISFINITE)|g' \ -e 's|@''REPLACE_ISINF''@|$(REPLACE_ISINF)|g' \
--- a/tests/test-math-c++.cc +++ b/tests/test-math-c++.cc @@ -158,7 +158,9 @@ #if GNULIB_TEST_HYPOTF SIGNATURE_CHECK (GNULIB_NAMESPACE::hypotf, float, (float, float)); #endif -//SIGNATURE_CHECK (GNULIB_NAMESPACE::hypot, double, (double, double)); +#if GNULIB_TEST_HYPOT +SIGNATURE_CHECK (GNULIB_NAMESPACE::hypot, double, (double, double)); +#endif #if GNULIB_TEST_HYPOTL SIGNATURE_CHECK (GNULIB_NAMESPACE::hypotl, long double, (long double, long double));