diff options
-rw-r--r-- | libquadmath/ChangeLog | 19 | ||||
-rw-r--r-- | libquadmath/Makefile.am | 2 | ||||
-rw-r--r-- | libquadmath/Makefile.in | 19 | ||||
-rw-r--r-- | libquadmath/config.h.in | 18 | ||||
-rwxr-xr-x | libquadmath/configure | 354 | ||||
-rw-r--r-- | libquadmath/configure.ac | 22 | ||||
-rw-r--r-- | libquadmath/libquadmath.texi | 1 | ||||
-rw-r--r-- | libquadmath/math/expq.c | 30 | ||||
-rw-r--r-- | libquadmath/math/fmaq.c | 241 | ||||
-rw-r--r-- | libquadmath/quadmath-imp.h | 1 | ||||
-rw-r--r-- | libquadmath/quadmath.h | 1 | ||||
-rw-r--r-- | libquadmath/quadmath.map | 1 | ||||
-rw-r--r-- | libquadmath/quadmath_weak.h | 1 |
13 files changed, 699 insertions, 11 deletions
diff --git a/libquadmath/ChangeLog b/libquadmath/ChangeLog index 5158dba51d4..1cb4aa0a383 100644 --- a/libquadmath/ChangeLog +++ b/libquadmath/ChangeLog @@ -1,3 +1,22 @@ +2011-01-16 Jakub Jelinek <jakub@redhat.com> + + PR fortran/46402 + * quadmath.map (QUADMATH_1.0): Add fmaq. + * configure.ac: Check for fenv.h, feholdexcept, fesetround, + feupdateenv, fesetenv and fetestexcept. + * configure: Regenerated. + * config.h.in: Regenerated. + * quadmath.h (fmaq): New prototype. + * quadmath_weak.h (fmaq): Add. + * Makefile.am (libquadmath_la_SOURCES): Add math/fmaq.c. + * Makefile.in: Regenerated. + * quadmath-imp.h: Include config.h. + * math/expq.c: Include fenv.h. + (USE_FENV_H): Define if libm support for fe* is there. + (expq): Add fesetround etc. support if USE_FENV_H is defined. + * math/fmaq.c: New file. + * libquadmath.texi (fmaq): Add. + 2011-01-14 Tobias Burnus <burnus@net-b.de> PR fortran/47182 diff --git a/libquadmath/Makefile.am b/libquadmath/Makefile.am index 87ebf20f294..c4bd0e43bae 100644 --- a/libquadmath/Makefile.am +++ b/libquadmath/Makefile.am @@ -61,7 +61,7 @@ libquadmath_la_SOURCES = \ math/erfq.c math/logq.c math/sqrtq.c math/expm1q.c math/lroundq.c \ math/tanhq.c math/expq.c math/modfq.c math/tanq.c math/fabsq.c \ math/nanq.c math/tgammaq.c math/finiteq.c math/nextafterq.c \ - math/truncq.c math/floorq.c math/powq.c + math/truncq.c math/floorq.c math/powq.c math/fmaq.c # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and diff --git a/libquadmath/Makefile.in b/libquadmath/Makefile.in index 49e64987232..a241b131da3 100644 --- a/libquadmath/Makefile.in +++ b/libquadmath/Makefile.in @@ -43,17 +43,16 @@ DIST_COMMON = ChangeLog $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/config.h.in $(srcdir)/../mkinstalldirs \ $(srcdir)/../depcomp $(libquadmath_TEXINFOS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/../ltoptions.m4 \ + $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \ + $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/lead-dot.m4 \ $(top_srcdir)/../config/lthostflags.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ - $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \ - $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \ - $(top_srcdir)/acinclude.m4 $(top_srcdir)/../libtool.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/../config/override.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ @@ -123,7 +122,7 @@ am__dirstamp = $(am__leading_dot)dirstamp @BUILD_LIBQUADMATH_TRUE@ math/nanq.lo math/tgammaq.lo \ @BUILD_LIBQUADMATH_TRUE@ math/finiteq.lo math/nextafterq.lo \ @BUILD_LIBQUADMATH_TRUE@ math/truncq.lo math/floorq.lo \ -@BUILD_LIBQUADMATH_TRUE@ math/powq.lo +@BUILD_LIBQUADMATH_TRUE@ math/powq.lo math/fmaq.lo libquadmath_la_OBJECTS = $(am_libquadmath_la_OBJECTS) libquadmath_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -325,7 +324,7 @@ AUTOMAKE_OPTIONS = 1.8 foreign @BUILD_LIBQUADMATH_TRUE@ math/erfq.c math/logq.c math/sqrtq.c math/expm1q.c math/lroundq.c \ @BUILD_LIBQUADMATH_TRUE@ math/tanhq.c math/expq.c math/modfq.c math/tanq.c math/fabsq.c \ @BUILD_LIBQUADMATH_TRUE@ math/nanq.c math/tgammaq.c math/finiteq.c math/nextafterq.c \ -@BUILD_LIBQUADMATH_TRUE@ math/truncq.c math/floorq.c math/powq.c +@BUILD_LIBQUADMATH_TRUE@ math/truncq.c math/floorq.c math/powq.c math/fmaq.c # Work around what appears to be a GNU make bug handling MAKEFLAGS @@ -570,6 +569,7 @@ math/nextafterq.lo: math/$(am__dirstamp) \ math/truncq.lo: math/$(am__dirstamp) math/$(DEPDIR)/$(am__dirstamp) math/floorq.lo: math/$(am__dirstamp) math/$(DEPDIR)/$(am__dirstamp) math/powq.lo: math/$(am__dirstamp) math/$(DEPDIR)/$(am__dirstamp) +math/fmaq.lo: math/$(am__dirstamp) math/$(DEPDIR)/$(am__dirstamp) libquadmath.la: $(libquadmath_la_OBJECTS) $(libquadmath_la_DEPENDENCIES) $(libquadmath_la_LINK) $(am_libquadmath_la_rpath) $(libquadmath_la_OBJECTS) $(libquadmath_la_LIBADD) $(LIBS) @@ -643,6 +643,8 @@ mostlyclean-compile: -rm -f math/finiteq.lo -rm -f math/floorq.$(OBJEXT) -rm -f math/floorq.lo + -rm -f math/fmaq.$(OBJEXT) + -rm -f math/fmaq.lo -rm -f math/fmodq.$(OBJEXT) -rm -f math/fmodq.lo -rm -f math/frexpq.$(OBJEXT) @@ -756,6 +758,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@math/$(DEPDIR)/fabsq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@math/$(DEPDIR)/finiteq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@math/$(DEPDIR)/floorq.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@math/$(DEPDIR)/fmaq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@math/$(DEPDIR)/fmodq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@math/$(DEPDIR)/frexpq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@math/$(DEPDIR)/hypotq.Plo@am__quote@ diff --git a/libquadmath/config.h.in b/libquadmath/config.h.in index 648942b281c..5dd10184f0d 100644 --- a/libquadmath/config.h.in +++ b/libquadmath/config.h.in @@ -6,6 +6,24 @@ /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H +/* libm includes feholdexcept */ +#undef HAVE_FEHOLDEXCEPT + +/* Define to 1 if you have the <fenv.h> header file. */ +#undef HAVE_FENV_H + +/* libm includes fesetenv */ +#undef HAVE_FESETENV + +/* libm includes fesetround */ +#undef HAVE_FESETROUND + +/* libm includes fetestexcept */ +#undef HAVE_FETESTEXCEPT + +/* libm includes feupdateenv */ +#undef HAVE_FEUPDATEENV + /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H diff --git a/libquadmath/configure b/libquadmath/configure index baed9215061..9844d9a3f9e 100755 --- a/libquadmath/configure +++ b/libquadmath/configure @@ -1757,6 +1757,93 @@ $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. @@ -10370,7 +10457,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10373 "configure" +#line 10460 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10476,7 +10563,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10479 "configure" +#line 10566 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11781,6 +11868,19 @@ esac +for ac_header in fenv.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "fenv.h" "ac_cv_header_fenv_h" "$ac_includes_default" +if test "x$ac_cv_header_fenv_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FENV_H 1 +_ACEOF + +fi + +done + + # If available, sqrtl and cbrtl speed up the calculation - # but they are not required if test x$gcc_no_link != xyes; then @@ -11874,6 +11974,231 @@ $as_echo "#define HAVE_CBRTL 1" >>confdefs.h fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for feholdexcept in -lm" >&5 +$as_echo_n "checking for feholdexcept in -lm... " >&6; } +if test "${ac_cv_lib_m_feholdexcept+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char feholdexcept (); +int +main () +{ +return feholdexcept (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_feholdexcept=yes +else + ac_cv_lib_m_feholdexcept=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_feholdexcept" >&5 +$as_echo "$ac_cv_lib_m_feholdexcept" >&6; } +if test "x$ac_cv_lib_m_feholdexcept" = x""yes; then : + +$as_echo "#define HAVE_FEHOLDEXCEPT 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fesetround in -lm" >&5 +$as_echo_n "checking for fesetround in -lm... " >&6; } +if test "${ac_cv_lib_m_fesetround+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char fesetround (); +int +main () +{ +return fesetround (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_fesetround=yes +else + ac_cv_lib_m_fesetround=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_fesetround" >&5 +$as_echo "$ac_cv_lib_m_fesetround" >&6; } +if test "x$ac_cv_lib_m_fesetround" = x""yes; then : + +$as_echo "#define HAVE_FESETROUND 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for feupdateenv in -lm" >&5 +$as_echo_n "checking for feupdateenv in -lm... " >&6; } +if test "${ac_cv_lib_m_feupdateenv+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char feupdateenv (); +int +main () +{ +return feupdateenv (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_feupdateenv=yes +else + ac_cv_lib_m_feupdateenv=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_feupdateenv" >&5 +$as_echo "$ac_cv_lib_m_feupdateenv" >&6; } +if test "x$ac_cv_lib_m_feupdateenv" = x""yes; then : + +$as_echo "#define HAVE_FEUPDATEENV 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fesetenv in -lm" >&5 +$as_echo_n "checking for fesetenv in -lm... " >&6; } +if test "${ac_cv_lib_m_fesetenv+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char fesetenv (); +int +main () +{ +return fesetenv (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_fesetenv=yes +else + ac_cv_lib_m_fesetenv=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_fesetenv" >&5 +$as_echo "$ac_cv_lib_m_fesetenv" >&6; } +if test "x$ac_cv_lib_m_fesetenv" = x""yes; then : + +$as_echo "#define HAVE_FESETENV 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fetestexcept in -lm" >&5 +$as_echo_n "checking for fetestexcept in -lm... " >&6; } +if test "${ac_cv_lib_m_fetestexcept+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char fetestexcept (); +int +main () +{ +return fetestexcept (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_fetestexcept=yes +else + ac_cv_lib_m_fetestexcept=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_fetestexcept" >&5 +$as_echo "$ac_cv_lib_m_fetestexcept" >&6; } +if test "x$ac_cv_lib_m_fetestexcept" = x""yes; then : + +$as_echo "#define HAVE_FETESTEXCEPT 1" >>confdefs.h + +fi + else if test "x$ac_cv_lib_m_sqrtl" = x""yes; then @@ -11885,6 +12210,31 @@ $as_echo "#define HAVE_SQRTL 1" >>confdefs.h $as_echo "#define HAVE_CBRTL 1" >>confdefs.h fi + if test "x$ac_cv_lib_m_feholdexcept" = x""yes; then + +$as_echo "#define HAVE_FEHOLDEXCEPT 1" >>confdefs.h + + fi + if test "x$ac_cv_lib_m_fesetround" = x""yes; then + +$as_echo "#define HAVE_FESETROUND 1" >>confdefs.h + + fi + if test "x$ac_cv_lib_m_feupdateenv" = x""yes; then + +$as_echo "#define HAVE_FEUPDATEENV 1" >>confdefs.h + + fi + if test "x$ac_cv_lib_m_fesetenv" = x""yes; then + +$as_echo "#define HAVE_FESETENV 1" >>confdefs.h + + fi + if test "x$ac_cv_lib_m_fetestexcept" = x""yes; then + +$as_echo "#define HAVE_FETESTEXCEPT 1" >>confdefs.h + + fi fi # Check for symbol versioning (copied from libssp). diff --git a/libquadmath/configure.ac b/libquadmath/configure.ac index cae6abb57b1..0bc2315a6b2 100644 --- a/libquadmath/configure.ac +++ b/libquadmath/configure.ac @@ -110,11 +110,18 @@ esac AC_SUBST(toolexecdir) AC_SUBST(toolexeclibdir) +AC_CHECK_HEADERS(fenv.h) + # If available, sqrtl and cbrtl speed up the calculation - # but they are not required if test x$gcc_no_link != xyes; then AC_CHECK_LIB([m],[sqrtl],[AC_DEFINE([HAVE_SQRTL],[1],[libm includes sqrtl])]) AC_CHECK_LIB([m],[cbrtl],[AC_DEFINE([HAVE_CBRTL],[1],[libm includes cbrtl])]) + AC_CHECK_LIB([m],[feholdexcept],[AC_DEFINE([HAVE_FEHOLDEXCEPT],[1],[libm includes feholdexcept])]) + AC_CHECK_LIB([m],[fesetround],[AC_DEFINE([HAVE_FESETROUND],[1],[libm includes fesetround])]) + AC_CHECK_LIB([m],[feupdateenv],[AC_DEFINE([HAVE_FEUPDATEENV],[1],[libm includes feupdateenv])]) + AC_CHECK_LIB([m],[fesetenv],[AC_DEFINE([HAVE_FESETENV],[1],[libm includes fesetenv])]) + AC_CHECK_LIB([m],[fetestexcept],[AC_DEFINE([HAVE_FETESTEXCEPT],[1],[libm includes fetestexcept])]) else if test "x$ac_cv_lib_m_sqrtl" = x""yes; then AC_DEFINE([HAVE_SQRTL],[1],[libm includes sqrtl]) @@ -122,6 +129,21 @@ else if test "x$ac_cv_lib_m_cbrtl" = x""yes; then AC_DEFINE([HAVE_CBRTL],[1],[libm includes cbrtl]) fi + if test "x$ac_cv_lib_m_feholdexcept" = x""yes; then + AC_DEFINE([HAVE_FEHOLDEXCEPT],[1],[libm includes feholdexcept]) + fi + if test "x$ac_cv_lib_m_fesetround" = x""yes; then + AC_DEFINE([HAVE_FESETROUND],[1],[libm includes fesetround]) + fi + if test "x$ac_cv_lib_m_feupdateenv" = x""yes; then + AC_DEFINE([HAVE_FEUPDATEENV],[1],[libm includes feupdateenv]) + fi + if test "x$ac_cv_lib_m_fesetenv" = x""yes; then + AC_DEFINE([HAVE_FESETENV],[1],[libm includes fesetenv]) + fi + if test "x$ac_cv_lib_m_fetestexcept" = x""yes; then + AC_DEFINE([HAVE_FETESTEXCEPT],[1],[libm includes fetestexcept]) + fi fi # Check for symbol versioning (copied from libssp). diff --git a/libquadmath/libquadmath.texi b/libquadmath/libquadmath.texi index 8818a37c911..aba777b4fcd 100644 --- a/libquadmath/libquadmath.texi +++ b/libquadmath/libquadmath.texi @@ -113,6 +113,7 @@ The following mathematical functions are available: @item @code{fabsq}: absolute value function @item @code{finiteq}: check finiteness of value @item @code{floorq}: floor value function +@item @code{fmaq}: fused multiply and add @item @code{fmodq}: remainder value function @item @code{frexpq}: extract mantissa and exponent @item @code{hypotq}: Eucledian distance function diff --git a/libquadmath/math/expq.c b/libquadmath/math/expq.c index a5fbc810269..2740b4e2cc9 100644 --- a/libquadmath/math/expq.c +++ b/libquadmath/math/expq.c @@ -21,6 +21,13 @@ 02111-1307 USA. */ #include "quadmath-imp.h" +#ifdef HAVE_FENV_H +# include <fenv.h> +# if defined HAVE_FEHOLDEXCEPT && defined HAVE_FESETROUND \ + && defined HAVE_FESETENV && defined FE_TONEAREST +# define USE_FENV_H +# endif +#endif /* __expl_table basically consists of four tables, T_EXPL_ARG{1,2} and @@ -1093,6 +1100,14 @@ expq (__float128 x) int tval1, tval2, unsafe, n_i; __float128 x22, n, t, result, xl; ieee854_float128 ex2_u, scale_u; +#ifdef USE_FENV_H + fenv_t oldenv; + + feholdexcept (&oldenv); +# ifdef FE_TONEAREST + fesetround (FE_TONEAREST); +# endif +#endif /* Calculate n. */ n = x * M_1_LN2 + THREEp111; @@ -1140,6 +1155,9 @@ expq (__float128 x) x22 = x + x*x*(P1+x*(P2+x*(P3+x*(P4+x*(P5+x*P6))))); /* Return result. */ +#ifdef USE_FENV_H + fesetenv (&oldenv); +#endif result = x22 * ex2_u.value + ex2_u.value; /* Now we can test whether the result is ultimate or if we are unsure. @@ -1153,12 +1171,24 @@ expq (__float128 x) union ieee854_long_double ex3_u; +#ifdef USE_FENV_H + #ifdef FE_TONEAREST + fesetround (FE_TONEAREST); + #endif +#endif ex3_u.d = (result - ex2_u.d) - x22 * ex2_u.d; ex2_u.d = result; ex3_u.ieee.exponent += LDBL_MANT_DIG + 15 + IEEE854_LONG_DOUBLE_BIAS - ex2_u.ieee.exponent; n_i = abs (ex3_u.d); n_i = (n_i + 1) / 2; +#ifdef USE_FENV_H + fesetenv (&oldenv); + #ifdef FE_TONEAREST + if (fegetround () == FE_TONEAREST) + n_i -= 0x4000; + #endif +#endif if (!n_i) { return __ieee754_expl_proc2 (origx); } diff --git a/libquadmath/math/fmaq.c b/libquadmath/math/fmaq.c new file mode 100644 index 00000000000..126b0a2d26b --- /dev/null +++ b/libquadmath/math/fmaq.c @@ -0,0 +1,241 @@ +/* Compute x * y + z as ternary operation. + Copyright (C) 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2010. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "quadmath-imp.h" +#include <math.h> +#include <float.h> +#ifdef HAVE_FENV_H +# include <fenv.h> +# if defined HAVE_FEHOLDEXCEPT && defined HAVE_FESETROUND \ + && defined HAVE_FEUPDATEENV && defined HAVE_FETESTEXCEPT \ + && defined FE_TOWARDZERO && defined FE_INEXACT +# define USE_FENV_H +# endif +#endif + +/* This implementation uses rounding to odd to avoid problems with + double rounding. See a paper by Boldo and Melquiond: + http://www.lri.fr/~melquion/doc/08-tc.pdf */ + +__float128 +fmaq (__float128 x, __float128 y, __float128 z) +{ + ieee854_float128 u, v, w; + int adjust = 0; + u.value = x; + v.value = y; + w.value = z; + if (__builtin_expect (u.ieee.exponent + v.ieee.exponent + >= 0x7fff + IEEE854_FLOAT128_BIAS + - FLT128_MANT_DIG, 0) + || __builtin_expect (u.ieee.exponent >= 0x7fff - FLT128_MANT_DIG, 0) + || __builtin_expect (v.ieee.exponent >= 0x7fff - FLT128_MANT_DIG, 0) + || __builtin_expect (w.ieee.exponent >= 0x7fff - FLT128_MANT_DIG, 0) + || __builtin_expect (u.ieee.exponent + v.ieee.exponent + <= IEEE854_FLOAT128_BIAS + FLT128_MANT_DIG, 0)) + { + /* If z is Inf, but x and y are finite, the result should be + z rather than NaN. */ + if (w.ieee.exponent == 0x7fff + && u.ieee.exponent != 0x7fff + && v.ieee.exponent != 0x7fff) + return (z + x) + y; + /* If x or y or z is Inf/NaN, or if fma will certainly overflow, + or if x * y is less than half of FLT128_DENORM_MIN, + compute as x * y + z. */ + if (u.ieee.exponent == 0x7fff + || v.ieee.exponent == 0x7fff + || w.ieee.exponent == 0x7fff + || u.ieee.exponent + v.ieee.exponent + > 0x7fff + IEEE854_FLOAT128_BIAS + || u.ieee.exponent + v.ieee.exponent + < IEEE854_FLOAT128_BIAS - FLT128_MANT_DIG - 2) + return x * y + z; + if (u.ieee.exponent + v.ieee.exponent + >= 0x7fff + IEEE854_FLOAT128_BIAS - FLT128_MANT_DIG) + { + /* Compute 1p-113 times smaller result and multiply + at the end. */ + if (u.ieee.exponent > v.ieee.exponent) + u.ieee.exponent -= FLT128_MANT_DIG; + else + v.ieee.exponent -= FLT128_MANT_DIG; + /* If x + y exponent is very large and z exponent is very small, + it doesn't matter if we don't adjust it. */ + if (w.ieee.exponent > FLT128_MANT_DIG) + w.ieee.exponent -= FLT128_MANT_DIG; + adjust = 1; + } + else if (w.ieee.exponent >= 0x7fff - FLT128_MANT_DIG) + { + /* Similarly. + If z exponent is very large and x and y exponents are + very small, it doesn't matter if we don't adjust it. */ + if (u.ieee.exponent > v.ieee.exponent) + { + if (u.ieee.exponent > FLT128_MANT_DIG) + u.ieee.exponent -= FLT128_MANT_DIG; + } + else if (v.ieee.exponent > FLT128_MANT_DIG) + v.ieee.exponent -= FLT128_MANT_DIG; + w.ieee.exponent -= FLT128_MANT_DIG; + adjust = 1; + } + else if (u.ieee.exponent >= 0x7fff - FLT128_MANT_DIG) + { + u.ieee.exponent -= FLT128_MANT_DIG; + if (v.ieee.exponent) + v.ieee.exponent += FLT128_MANT_DIG; + else + v.value *= 0x1p113Q; + } + else if (v.ieee.exponent >= 0x7fff - FLT128_MANT_DIG) + { + v.ieee.exponent -= FLT128_MANT_DIG; + if (u.ieee.exponent) + u.ieee.exponent += FLT128_MANT_DIG; + else + u.value *= 0x1p113Q; + } + else /* if (u.ieee.exponent + v.ieee.exponent + <= IEEE854_FLOAT128_BIAS + FLT128_MANT_DIG) */ + { + if (u.ieee.exponent > v.ieee.exponent) + u.ieee.exponent += 2 * FLT128_MANT_DIG; + else + v.ieee.exponent += 2 * FLT128_MANT_DIG; + if (w.ieee.exponent <= 4 * FLT128_MANT_DIG + 4) + { + if (w.ieee.exponent) + w.ieee.exponent += 2 * FLT128_MANT_DIG; + else + w.value *= 0x1p226Q; + adjust = -1; + } + /* Otherwise x * y should just affect inexact + and nothing else. */ + } + x = u.value; + y = v.value; + z = w.value; + } + /* Multiplication m1 + m2 = x * y using Dekker's algorithm. */ +#define C ((1LL << (FLT128_MANT_DIG + 1) / 2) + 1) + __float128 x1 = x * C; + __float128 y1 = y * C; + __float128 m1 = x * y; + x1 = (x - x1) + x1; + y1 = (y - y1) + y1; + __float128 x2 = x - x1; + __float128 y2 = y - y1; + __float128 m2 = (((x1 * y1 - m1) + x1 * y2) + x2 * y1) + x2 * y2; + + /* Addition a1 + a2 = z + m1 using Knuth's algorithm. */ + __float128 a1 = z + m1; + __float128 t1 = a1 - z; + __float128 t2 = a1 - t1; + t1 = m1 - t1; + t2 = z - t2; + __float128 a2 = t1 + t2; + +#ifdef USE_FENV_H + fenv_t env; + feholdexcept (&env); + fesetround (FE_TOWARDZERO); +#endif + /* Perform m2 + a2 addition with round to odd. */ + u.value = a2 + m2; + + if (__builtin_expect (adjust == 0, 1)) + { +#ifdef USE_FENV_H + if ((u.ieee.mant_low & 1) == 0 && u.ieee.exponent != 0x7fff) + u.ieee.mant_low |= fetestexcept (FE_INEXACT) != 0; + feupdateenv (&env); +#endif + /* Result is a1 + u.value. */ + return a1 + u.value; + } + else if (__builtin_expect (adjust > 0, 1)) + { +#ifdef USE_FENV_H + if ((u.ieee.mant_low & 1) == 0 && u.ieee.exponent != 0x7fff) + u.ieee.mant_low |= fetestexcept (FE_INEXACT) != 0; + feupdateenv (&env); +#endif + /* Result is a1 + u.value, scaled up. */ + return (a1 + u.value) * 0x1p113Q; + } + else + { +#ifdef USE_FENV_H + if ((u.ieee.mant_low & 1) == 0) + u.ieee.mant_low |= fetestexcept (FE_INEXACT) != 0; +#endif + v.value = a1 + u.value; + /* Ensure the addition is not scheduled after fetestexcept call. */ + asm volatile ("" : : "m" (v)); +#ifdef USE_FENV_H + int j = fetestexcept (FE_INEXACT) != 0; + feupdateenv (&env); +#else + int j = 0; +#endif + /* Ensure the following computations are performed in default rounding + mode instead of just reusing the round to zero computation. */ + asm volatile ("" : "=m" (u) : "m" (u)); + /* If a1 + u.value is exact, the only rounding happens during + scaling down. */ + if (j == 0) + return v.value * 0x1p-226Q; + /* If result rounded to zero is not subnormal, no double + rounding will occur. */ + if (v.ieee.exponent > 226) + return (a1 + u.value) * 0x1p-226Q; + /* If v.value * 0x1p-226Q with round to zero is a subnormal above + or equal to FLT128_MIN / 2, then v.value * 0x1p-226Q shifts mantissa + down just by 1 bit, which means v.ieee.mant_low |= j would + change the round bit, not sticky or guard bit. + v.value * 0x1p-226Q never normalizes by shifting up, + so round bit plus sticky bit should be already enough + for proper rounding. */ + if (v.ieee.exponent == 226) + { + /* v.ieee.mant_low & 2 is LSB bit of the result before rounding, + v.ieee.mant_low & 1 is the round bit and j is our sticky + bit. In round-to-nearest 001 rounds down like 00, + 011 rounds up, even though 01 rounds down (thus we need + to adjust), 101 rounds down like 10 and 111 rounds up + like 11. */ + if ((v.ieee.mant_low & 3) == 1) + { + v.value *= 0x1p-226Q; + if (v.ieee.negative) + return v.value - 0x1p-16494Q /* __FLT128_DENORM_MIN__ */; + else + return v.value + 0x1p-16494Q /* __FLT128_DENORM_MIN__ */; + } + else + return v.value * 0x1p-226Q; + } + v.ieee.mant_low |= j; + return v.value * 0x1p-226Q; + } +} diff --git a/libquadmath/quadmath-imp.h b/libquadmath/quadmath-imp.h index e297529a1e6..ac9359b6626 100644 --- a/libquadmath/quadmath-imp.h +++ b/libquadmath/quadmath-imp.h @@ -24,6 +24,7 @@ Boston, MA 02110-1301, USA. */ #include <stdint.h> #include <stdlib.h> #include "quadmath.h" +#include "config.h" // Prototypes for internal functions diff --git a/libquadmath/quadmath.h b/libquadmath/quadmath.h index 22683603cab..5fe9549d376 100644 --- a/libquadmath/quadmath.h +++ b/libquadmath/quadmath.h @@ -48,6 +48,7 @@ extern __float128 expm1q (__float128); extern __float128 fabsq (__float128); extern int finiteq (const __float128); extern __float128 floorq (__float128); +extern __float128 fmaq (__float128, __float128, __float128); extern __float128 fmodq (__float128, __float128); extern __float128 frexpq (__float128, int *); extern __float128 hypotq (__float128, __float128); diff --git a/libquadmath/quadmath.map b/libquadmath/quadmath.map index 1d016fbd612..f70cda120af 100644 --- a/libquadmath/quadmath.map +++ b/libquadmath/quadmath.map @@ -19,6 +19,7 @@ QUADMATH_1.0 { fabsq; finiteq; floorq; + fmaq; fmodq; frexpq; hypotq; diff --git a/libquadmath/quadmath_weak.h b/libquadmath/quadmath_weak.h index a14014e1018..05b04389376 100644 --- a/libquadmath/quadmath_weak.h +++ b/libquadmath/quadmath_weak.h @@ -55,6 +55,7 @@ __qmath3 (expm1q) __qmath3 (fabsq) __qmath3 (finiteq) __qmath3 (floorq) +__qmath3 (fmaq) __qmath3 (fmodq) __qmath3 (frexpq) __qmath3 (hypotq) |