Patchwork Add fmaq to libquadmath (PR fortran/46402)

login
register
mail settings
Submitter Jakub Jelinek
Date Jan. 6, 2011, 12:14 a.m.
Message ID <20110106001424.GP16156@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/77649/
State New
Headers show

Comments

Jakub Jelinek - Jan. 6, 2011, 12:14 a.m.
Hi!

This patch adds fmaq to libquadmath (slightly modified s_fmal.c
from glibc) and adds small hunks of rounding stuff to expq
conditionally on fenv.h presence and fe* existence (the configury checking
had to be added anyway for fmaq).  Bootstrapped/regtested on x86_64-linux
and i686-linux, ok for trunk?

2011-01-05  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.
	* 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.


	Jakub

Patch

--- libquadmath/quadmath.map.jj	2010-11-19 20:56:38.000000000 +0100
+++ libquadmath/quadmath.map	2011-01-05 15:27:46.000000000 +0100
@@ -19,6 +19,7 @@  QUADMATH_1.0 {
     fabsq;
     finiteq;
     floorq;
+    fmaq;
     fmodq;
     frexpq;
     hypotq;
--- libquadmath/configure.ac.jj	2010-12-21 12:23:15.000000000 +0100
+++ libquadmath/configure.ac	2011-01-05 16:20:22.000000000 +0100
@@ -109,11 +109,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])  
@@ -121,6 +128,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).
--- libquadmath/quadmath.h.jj	2010-12-07 17:32:50.000000000 +0100
+++ libquadmath/quadmath.h	2011-01-05 16:41:59.000000000 +0100
@@ -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);
--- libquadmath/Makefile.am.jj	2010-12-09 11:12:40.000000000 +0100
+++ libquadmath/Makefile.am	2011-01-05 15:26:00.000000000 +0100
@@ -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
--- libquadmath/quadmath-imp.h.jj	2010-12-14 08:11:24.000000000 +0100
+++ libquadmath/quadmath-imp.h	2011-01-05 16:23:44.000000000 +0100
@@ -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
--- libquadmath/math/expq.c.jj	2010-11-19 20:56:37.000000000 +0100
+++ libquadmath/math/expq.c	2011-01-05 16:13:16.000000000 +0100
@@ -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);
 	  }
--- libquadmath/math/fmaq.c.jj	2011-01-05 15:12:56.000000000 +0100
+++ libquadmath/math/fmaq.c	2011-01-05 16:17:09.000000000 +0100
@@ -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;
+    }
+}
--- libquadmath/libquadmath.texi.jj	2010-12-09 11:12:40.000000000 +0100
+++ libquadmath/libquadmath.texi	2011-01-05 19:33:17.000000000 +0100
@@ -113,6 +113,7 @@  The following mathematical functions are
 @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
--- libquadmath/configure.jj	2010-12-21 12:23:15.000000000 +0100
+++ libquadmath/configure	2011-01-05 16:20:34.000000000 +0100
@@ -1753,6 +1753,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.
@@ -10337,7 +10424,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10340 "configure"
+#line 10427 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10443,7 +10530,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 10446 "configure"
+#line 10533 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11748,6 +11835,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
@@ -11841,6 +11941,231 @@  $as_echo "#define HAVE_CBRTL 1" >>confde
 
 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
 
@@ -11852,6 +12177,31 @@  $as_echo "#define HAVE_SQRTL 1" >>confde
 $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).
--- libquadmath/Makefile.in.jj	2010-12-09 11:12:40.000000000 +0100
+++ libquadmath/Makefile.in	2011-01-05 16:08:55.000000000 +0100
@@ -43,17 +43,16 @@  DIST_COMMON = ChangeLog $(srcdir)/Makefi
 	$(srcdir)/config.h.in $(srcdir)/../mkinstalldirs \
 	$(srcdir)/../depcomp
 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)dirstam
 @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) \
@@ -323,7 +322,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
@@ -567,6 +566,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)
 
@@ -640,6 +640,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)
@@ -753,6 +755,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@
--- libquadmath/config.h.in.jj	2010-11-19 20:56:38.000000000 +0100
+++ libquadmath/config.h.in	2011-01-05 16:09:21.000000000 +0100
@@ -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