Patchwork Kill gdtoa from libquadmath

login
register
mail settings
Submitter Jakub Jelinek
Date Feb. 17, 2011, 8:06 p.m.
Message ID <20110217200629.GH30899@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/83482/
State New
Headers show

Comments

Jakub Jelinek - Feb. 17, 2011, 8:06 p.m.
Hi!

This patch together with svn rm libquadmath/gdtoa
replaces the buggy gdtoa implementation even for strtoflt128
with code from glibc.  libquadmath.so.0 size shrinks, because
mpn routines are shared with the printf hooks/quadmath_snprintf
implementation.
size(1) output before the changes:
 223980    1752    2728  228460   37c6c obj480/x86_64-unknown-linux-gnu/libquadmath/.libs/libquadmath.so.0
 472386    1136    2692  476214   74436 obj481/i686-pc-linux-gnu/libquadmath/.libs/libquadmath.so.0
and after it:
 214291    1696      24  216011   34bcb obj482/x86_64-unknown-linux-gnu/libquadmath/.libs/libquadmath.so.0 
 463021    1124      16  464161   71521 obj483/i686-pc-linux-gnu/libquadmath/.libs/libquadmath.so.0

Bootstrapped/regtested on x86_64-linux and i686-linux, tested with
http://gcc.gnu.org/bugzilla/attachment.cgi?id=23382
testcase and Kai kindly tested this on mingw.
Committed to trunk.

2011-02-17  Jakub Jelinek  <jakub@redhat.com>

	* libquadmath.texi (FLT128_DIG, FLT128_MIN_10_EXP,
	FLT128_MAX_10_EXP): Document.
	(strtoflt128): Remove obsolete comment.
	* configure.ac (HAVE_STRTOULL): New check.
	* printf/gmp-impl.h (mpn_construct_float128): New prototype,
	define.
	* printf/mul_n.c: Include <config.h>.
	* printf/add_n.c: Likewise.
	* printf/cmp.c: Likewise.
	* printf/fpioconst.c: Likewise.
	* printf/mul_1.c: Likewise.
	* printf/rshift.c: Likewise.
	* printf/lshift.c: Likewise.
	* printf/submul_1.c: Likewise.
	* printf/sub_n.c: Likewise.
	* printf/divrem.c: Likewise.
	* printf/addmul_1.c: Likewise.
	* printf/mul.c: Likewise.
	* printf/quadmath-printf.h (isupper, isdigit, tolower): Change
	to avoid evaluating argument multiple times.
	(isxdigit): Redefine.
	* strtod/strtoflt128.c: New file.
	* strtod/strtod_l.c: New file.
	* strtod/mpn2flt128.c: New file.
	* strtod/grouping.h: New file.
	* strtod/tens_in_limb.c: New file.
	* gdtoa/arith.h: Removed.
	* gdtoa/gd_qnan.h: Removed.
	* gdtoa/gdtoa_fltrnds.h: Removed.
	* gdtoa/gdtoa.h: Removed.
	* gdtoa/gdtoaimp.h: Removed.
	* gdtoa/gethex.c: Removed.
	* gdtoa/gmisc.c: Removed.
	* gdtoa/hd_init.c: Removed.
	* gdtoa/hexnan.c: Removed.
	* gdtoa/makefile: Removed.
	* gdtoa/misc.c: Removed.
	* gdtoa/README.gdtoa: Removed.
	* gdtoa/smisc.c: Removed.
	* gdtoa/strtodg.c: Removed.
	* gdtoa/strtopQ.c: Removed.
	* gdtoa/sum.c: Removed.
	* quadmath.h (FLT128_DIG, FLT128_MIN_10_EXP, FLT128_MAX_10_EXP):
	Define.
	* Makefile.am (libquadmath_la_SOURCES): Remove gdtoa/*, add
	strtod/strtoflt128.c, strtod/mpn2flt128.c and strtod/tens_in_limb.c.
	* config.h.in: Regenerated.
	* configure: Regenerated.
	* Makefile.in: Regenerated.


	Jakub

Patch

--- libquadmath/libquadmath.texi.jj	2011-02-15 15:27:13.000000000 +0100
+++ libquadmath/libquadmath.texi	2011-02-17 13:56:48.000000000 +0100
@@ -109,6 +109,9 @@  The following macros are defined, which 
 @item @code{FLT128_MANT_DIG}: number of digits in the mantissa (bit precision)
 @item @code{FLT128_MIN_EXP}: maximal negative exponent
 @item @code{FLT128_MAX_EXP}: maximal positive exponent
+@item @code{FLT128_DIG}: number of decimal digits in the mantissa
+@item @code{FLT128_MIN_10_EXP}: maximal negative decimal exponent
+@item @code{FLT128_MAX_10_EXP}: maximal positive decimal exponent
 @end table
 
 The following mathematical constants of type @code{__float128} are defined.
@@ -260,10 +263,6 @@  The function @code{dmath_strtopQ} conver
 @item Syntax
 @code{__float128 strtoflt128 (const char *s, char **sp)}
 
-@c The return values are defined in gdtoa/gdtoa.h STRTOG_*
-@c However, the values are currently not exported - thus we
-@c do not define them here, either.
-
 @item @emph{Arguments}:
 @multitable @columnfractions .15 .70
 @item @var{s}  @tab input string
--- libquadmath/configure.ac.jj	2011-02-17 10:10:01.000000000 +0100
+++ libquadmath/configure.ac	2011-02-17 13:55:37.000000000 +0100
@@ -124,6 +124,7 @@  if test x$gcc_no_link != xyes; then
   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])])
+  AC_CHECK_FUNCS(strtoull)
 else
   if test "x$ac_cv_lib_m_sqrtl" = x""yes; then
     AC_DEFINE([HAVE_SQRTL],[1],[libm includes sqrtl])  
--- libquadmath/printf/gmp-impl.h.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/gmp-impl.h	2011-02-17 11:30:21.000000000 +0100
@@ -140,6 +140,10 @@  mp_limb_t mpn_submul_1 (mp_ptr, mp_srcpt
 mp_size_t mpn_extract_flt128 (mp_ptr res_ptr, mp_size_t size, int *expt,
 			      int *is_neg, __float128 value) attribute_hidden;
 
+#define mpn_construct_float128 __MPN(construct_float128)
+__float128 mpn_construct_float128 (mp_srcptr frac_ptr, int expt, int sign)
+     attribute_hidden;
+
 #define mpn_divmod(qp,np,nsize,dp,dsize) mpn_divrem (qp,0,np,nsize,dp,dsize)
 
 static inline mp_limb_t
--- libquadmath/printf/mul_n.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/mul_n.c	2011-02-17 12:48:26.000000000 +0100
@@ -19,6 +19,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 /* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP),
--- libquadmath/printf/add_n.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/add_n.c	2011-02-17 12:47:50.000000000 +0100
@@ -19,6 +19,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 mp_limb_t
--- libquadmath/printf/cmp.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/cmp.c	2011-02-17 12:48:00.000000000 +0100
@@ -19,6 +19,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 /* Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE.
--- libquadmath/printf/fpioconst.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/fpioconst.c	2011-02-17 12:48:08.000000000 +0100
@@ -18,6 +18,7 @@ 
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <config.h>
 #include "gmp-impl.h"		/* This defines BITS_PER_MP_LIMB.  */
 #include "fpioconst.h"
 
--- libquadmath/printf/mul_1.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/mul_1.c	2011-02-17 12:48:20.000000000 +0100
@@ -20,6 +20,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 mp_limb_t
--- libquadmath/printf/rshift.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/rshift.c	2011-02-17 12:48:31.000000000 +0100
@@ -19,6 +19,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 /* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right
--- libquadmath/printf/lshift.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/lshift.c	2011-02-17 12:48:12.000000000 +0100
@@ -19,6 +19,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 /* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left
--- libquadmath/printf/submul_1.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/submul_1.c	2011-02-17 12:48:39.000000000 +0100
@@ -22,6 +22,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 mp_limb_t
--- libquadmath/printf/sub_n.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/sub_n.c	2011-02-17 12:48:35.000000000 +0100
@@ -19,6 +19,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 mp_limb_t
--- libquadmath/printf/divrem.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/divrem.c	2011-02-17 12:48:04.000000000 +0100
@@ -20,6 +20,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 /* Divide num (NP/NSIZE) by den (DP/DSIZE) and write
--- libquadmath/printf/addmul_1.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/addmul_1.c	2011-02-17 12:47:55.000000000 +0100
@@ -22,6 +22,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 mp_limb_t
--- libquadmath/printf/mul.c.jj	2011-02-15 15:27:08.000000000 +0100
+++ libquadmath/printf/mul.c	2011-02-17 12:48:16.000000000 +0100
@@ -19,6 +19,7 @@  along with the GNU MP Library; see the f
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA. */
 
+#include <config.h>
 #include "gmp-impl.h"
 
 /* Multiply the natural numbers u (pointed to by UP, with USIZE limbs)
--- libquadmath/printf/quadmath-printf.h.jj	2011-02-17 10:10:01.000000000 +0100
+++ libquadmath/printf/quadmath-printf.h	2011-02-17 13:29:23.000000000 +0100
@@ -62,10 +62,20 @@  Boston, MA 02110-1301, USA.  */
 /* Won't work for EBCDIC.  */
 #undef isupper
 #undef isdigit
+#undef isxdigit
 #undef tolower
-#define isupper(x) ((x) >= 'A' && (x) <= 'Z')
-#define isdigit(x) ((x) >= '0' && (x) <= '9')
-#define tolower(x) (isupper (x) ? (x) - 'A' + 'a' : (x))
+#define isupper(x) \
+  ({__typeof(x) __is_x = (x); __is_x >= 'A' && __is_x <= 'Z'; })
+#define isdigit(x) \
+  ({__typeof(x) __is_x = (x); __is_x >= '0' && __is_x <= '9'; })
+#define isxdigit(x) \
+  ({__typeof(x) __is_x = (x); \
+    (__is_x >= '0' && __is_x <= '9') \
+    || ((x) >= 'A' && (x) <= 'F') \
+    || ((x) >= 'a' && (x) <= 'f'); })
+#define tolower(x) \
+  ({__typeof(x) __is_x = (x); \
+    (__is_x >= 'A' && __is_x <= 'Z') ? __is_x - 'A' + 'a' : __is_x; })
 #endif
 
 #ifndef CHAR_MAX
--- libquadmath/strtod/strtoflt128.c.jj	2011-02-17 10:58:22.000000000 +0100
+++ libquadmath/strtod/strtoflt128.c	2011-02-17 12:44:19.000000000 +0100
@@ -0,0 +1,50 @@ 
+/* Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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.  */
+
+/* The actual implementation for all floating point sizes is in strtod.c.
+   These macros tell it to produce the `__float128' version, `strtold'.  */
+
+#define FLOAT		__float128
+#define FLT		FLT128
+#ifdef USE_WIDE_CHAR
+# define STRTOF		wcstoflt128
+# define __STRTOF	__wcstoflt128
+#else
+# define STRTOF		strtoflt128
+# define __STRTOF	__strtoflt128
+#endif
+#define MPN2FLOAT	mpn_construct_float128
+#define FLOAT_HUGE_VAL	HUGE_VALQ
+#define SET_MANTISSA(flt, mant) \
+  do { ieee854_float128 u;						      \
+       u.value = (flt);							      \
+       u.ieee.mant_high = 0x800000000000ULL;				      \
+       u.ieee.mant_low = mant;						      \
+       (flt) = u.value;							      \
+  } while (0)
+
+static inline __attribute__((__always_inline__))
+__float128 ____strtoflt128_internal (const char *, char **, int);
+
+#include "strtod_l.c"
+
+__float128
+strtoflt128 (const char *nptr, char **endptr)
+{
+  return ____STRTOF_INTERNAL (nptr, endptr, 0);
+}
--- libquadmath/strtod/strtod_l.c.jj	2011-02-17 10:56:35.000000000 +0100
+++ libquadmath/strtod/strtod_l.c	2011-02-17 14:25:51.000000000 +0100
@@ -0,0 +1,1571 @@ 
+/* Convert string representing a number to float value, using given locale.
+   Copyright (C) 1997,1998,2002,2004,2005,2006,2007,2008,2009,2010
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   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 <config.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+#define NDEBUG 1
+#include <assert.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include "../printf/quadmath-printf.h"
+#include "../printf/fpioconst.h"
+
+
+#undef L_
+#ifdef USE_WIDE_CHAR
+# define STRING_TYPE wchar_t
+# define CHAR_TYPE wint_t
+# define L_(Ch) L##Ch
+# define ISSPACE(Ch) __iswspace_l ((Ch), loc)
+# define ISDIGIT(Ch) __iswdigit_l ((Ch), loc)
+# define ISXDIGIT(Ch) __iswxdigit_l ((Ch), loc)
+# define TOLOWER(Ch) __towlower_l ((Ch), loc)
+# define TOLOWER_C(Ch) __towlower_l ((Ch), _nl_C_locobj_ptr)
+# define STRNCASECMP(S1, S2, N) \
+  __wcsncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr)
+# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc)
+#else
+# define STRING_TYPE char
+# define CHAR_TYPE char
+# define L_(Ch) Ch
+# define ISSPACE(Ch) isspace (Ch)
+# define ISDIGIT(Ch) isdigit (Ch)
+# define ISXDIGIT(Ch) isxdigit (Ch)
+# define TOLOWER(Ch) tolower (Ch)
+# define TOLOWER_C(Ch) \
+  ({__typeof(Ch) __tlc = (Ch); \
+    (__tlc >= 'A' && __tlc <= 'Z') ? __tlc - 'A' + 'a' : __tlc; })
+# define STRNCASECMP(S1, S2, N) \
+  __quadmath_strncasecmp_c (S1, S2, N)
+# ifdef HAVE_STRTOULL
+#  define STRTOULL(S, E, B) strtoull (S, E, B)
+# else
+#  define STRTOULL(S, E, B) strtoul (S, E, B)
+# endif
+
+static inline int
+__quadmath_strncasecmp_c (const char *s1, const char *s2, size_t n)
+{
+  const unsigned char *p1 = (const unsigned char *) s1;
+  const unsigned char *p2 = (const unsigned char *) s2;
+  int result;
+  if (p1 == p2 || n == 0)
+    return 0;
+  while ((result = TOLOWER_C (*p1) - TOLOWER_C (*p2++)) == 0)
+    if (*p1++ == '\0' || --n == 0)
+      break;
+
+  return result;
+}
+#endif
+
+
+/* Constants we need from float.h; select the set for the FLOAT precision.  */
+#define MANT_DIG	PASTE(FLT,_MANT_DIG)
+#define	DIG		PASTE(FLT,_DIG)
+#define	MAX_EXP		PASTE(FLT,_MAX_EXP)
+#define	MIN_EXP		PASTE(FLT,_MIN_EXP)
+#define MAX_10_EXP	PASTE(FLT,_MAX_10_EXP)
+#define MIN_10_EXP	PASTE(FLT,_MIN_10_EXP)
+
+/* Extra macros required to get FLT expanded before the pasting.  */
+#define PASTE(a,b)	PASTE1(a,b)
+#define PASTE1(a,b)	a##b
+
+/* Function to construct a floating point number from an MP integer
+   containing the fraction bits, a base 2 exponent, and a sign flag.  */
+extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative);
+
+/* Definitions according to limb size used.  */
+#if	BITS_PER_MP_LIMB == 32
+# define MAX_DIG_PER_LIMB	9
+# define MAX_FAC_PER_LIMB	1000000000UL
+#elif	BITS_PER_MP_LIMB == 64
+# define MAX_DIG_PER_LIMB	19
+# define MAX_FAC_PER_LIMB	10000000000000000000ULL
+#else
+# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for"
+#endif
+
+#define _tens_in_limb __quadmath_tens_in_limb
+extern const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1] attribute_hidden;
+
+#ifndef	howmany
+#define	howmany(x,y)		(((x)+((y)-1))/(y))
+#endif
+#define SWAP(x, y)		({ typeof(x) _tmp = x; x = y; y = _tmp; })
+
+#define NDIG			(MAX_10_EXP - MIN_10_EXP + 2 * MANT_DIG)
+#define HEXNDIG			((MAX_EXP - MIN_EXP + 7) / 8 + 2 * MANT_DIG)
+#define	RETURN_LIMB_SIZE		howmany (MANT_DIG, BITS_PER_MP_LIMB)
+
+#define RETURN(val,end)							      \
+    do { if (endptr != NULL) *endptr = (STRING_TYPE *) (end);		      \
+	 return val; } while (0)
+
+/* Maximum size necessary for mpn integers to hold floating point numbers.  */
+#define	MPNSIZE		(howmany (MAX_EXP + 2 * MANT_DIG, BITS_PER_MP_LIMB) \
+			 + 2)
+/* Declare an mpn integer variable that big.  */
+#define	MPN_VAR(name)	mp_limb_t name[MPNSIZE]; mp_size_t name##size
+/* Copy an mpn integer value.  */
+#define MPN_ASSIGN(dst, src) \
+	memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb_t))
+
+
+/* Return a floating point number of the needed type according to the given
+   multi-precision number after possible rounding.  */
+static FLOAT
+round_and_return (mp_limb_t *retval, int exponent, int negative,
+		  mp_limb_t round_limb, mp_size_t round_bit, int more_bits)
+{
+  if (exponent < MIN_EXP - 1)
+    {
+      mp_size_t shift = MIN_EXP - 1 - exponent;
+
+      if (shift > MANT_DIG)
+	{
+#if defined HAVE_ERRNO_H && defined EDOM
+	  errno = EDOM;
+#endif
+	  return 0.0;
+	}
+
+      more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0;
+      if (shift == MANT_DIG)
+	/* This is a special case to handle the very seldom case where
+	   the mantissa will be empty after the shift.  */
+	{
+	  int i;
+
+	  round_limb = retval[RETURN_LIMB_SIZE - 1];
+	  round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
+	  for (i = 0; i < RETURN_LIMB_SIZE; ++i)
+	    more_bits |= retval[i] != 0;
+	  MPN_ZERO (retval, RETURN_LIMB_SIZE);
+	}
+      else if (shift >= BITS_PER_MP_LIMB)
+	{
+	  int i;
+
+	  round_limb = retval[(shift - 1) / BITS_PER_MP_LIMB];
+	  round_bit = (shift - 1) % BITS_PER_MP_LIMB;
+	  for (i = 0; i < (shift - 1) / BITS_PER_MP_LIMB; ++i)
+	    more_bits |= retval[i] != 0;
+	  more_bits |= ((round_limb & ((((mp_limb_t) 1) << round_bit) - 1))
+			!= 0);
+
+	  (void) mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB],
+			     RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
+			     shift % BITS_PER_MP_LIMB);
+	  MPN_ZERO (&retval[RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)],
+		    shift / BITS_PER_MP_LIMB);
+	}
+      else if (shift > 0)
+	{
+	  round_limb = retval[0];
+	  round_bit = shift - 1;
+	  (void) mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift);
+	}
+      /* This is a hook for the m68k long double format, where the
+	 exponent bias is the same for normalized and denormalized
+	 numbers.  */
+#ifndef DENORM_EXP
+# define DENORM_EXP (MIN_EXP - 2)
+#endif
+      exponent = DENORM_EXP;
+#if defined HAVE_ERRNO_H && defined ERANGE
+      errno = ERANGE;
+#endif
+    }
+
+  if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0
+      && (more_bits || (retval[0] & 1) != 0
+	  || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0))
+    {
+      mp_limb_t cy = mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1);
+
+      if (((MANT_DIG % BITS_PER_MP_LIMB) == 0 && cy) ||
+	  ((MANT_DIG % BITS_PER_MP_LIMB) != 0 &&
+	   (retval[RETURN_LIMB_SIZE - 1]
+	    & (((mp_limb_t) 1) << (MANT_DIG % BITS_PER_MP_LIMB))) != 0))
+	{
+	  ++exponent;
+	  (void) mpn_rshift (retval, retval, RETURN_LIMB_SIZE, 1);
+	  retval[RETURN_LIMB_SIZE - 1]
+	    |= ((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB);
+	}
+      else if (exponent == DENORM_EXP
+	       && (retval[RETURN_LIMB_SIZE - 1]
+		   & (((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB)))
+	       != 0)
+	  /* The number was denormalized but now normalized.  */
+	exponent = MIN_EXP - 1;
+    }
+
+  if (exponent > MAX_EXP)
+    return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+
+  return MPN2FLOAT (retval, exponent, negative);
+}
+
+
+/* Read a multi-precision integer starting at STR with exactly DIGCNT digits
+   into N.  Return the size of the number limbs in NSIZE at the first
+   character od the string that is not part of the integer as the function
+   value.  If the EXPONENT is small enough to be taken as an additional
+   factor for the resulting number (see code) multiply by it.  */
+static const STRING_TYPE *
+str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
+	    int *exponent
+#ifndef USE_WIDE_CHAR
+	    , const char *decimal, size_t decimal_len, const char *thousands
+#endif
+
+	    )
+{
+  /* Number of digits for actual limb.  */
+  int cnt = 0;
+  mp_limb_t low = 0;
+  mp_limb_t start;
+
+  *nsize = 0;
+  assert (digcnt > 0);
+  do
+    {
+      if (cnt == MAX_DIG_PER_LIMB)
+	{
+	  if (*nsize == 0)
+	    {
+	      n[0] = low;
+	      *nsize = 1;
+	    }
+	  else
+	    {
+	      mp_limb_t cy;
+	      cy = mpn_mul_1 (n, n, *nsize, MAX_FAC_PER_LIMB);
+	      cy += mpn_add_1 (n, n, *nsize, low);
+	      if (cy != 0)
+		{
+		  n[*nsize] = cy;
+		  ++(*nsize);
+		}
+	    }
+	  cnt = 0;
+	  low = 0;
+	}
+
+      /* There might be thousands separators or radix characters in
+	 the string.  But these all can be ignored because we know the
+	 format of the number is correct and we have an exact number
+	 of characters to read.  */
+#ifdef USE_WIDE_CHAR
+      if (*str < L'0' || *str > L'9')
+	++str;
+#else
+      if (*str < '0' || *str > '9')
+	{
+	  int inner = 0;
+	  if (thousands != NULL && *str == *thousands
+	      && ({ for (inner = 1; thousands[inner] != '\0'; ++inner)
+		      if (thousands[inner] != str[inner])
+			break;
+		    thousands[inner] == '\0'; }))
+	    str += inner;
+	  else
+	    str += decimal_len;
+	}
+#endif
+      low = low * 10 + *str++ - L_('0');
+      ++cnt;
+    }
+  while (--digcnt > 0);
+
+  if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB)
+    {
+      low *= _tens_in_limb[*exponent];
+      start = _tens_in_limb[cnt + *exponent];
+      *exponent = 0;
+    }
+  else
+    start = _tens_in_limb[cnt];
+
+  if (*nsize == 0)
+    {
+      n[0] = low;
+      *nsize = 1;
+    }
+  else
+    {
+      mp_limb_t cy;
+      cy = mpn_mul_1 (n, n, *nsize, start);
+      cy += mpn_add_1 (n, n, *nsize, low);
+      if (cy != 0)
+	n[(*nsize)++] = cy;
+    }
+
+  return str;
+}
+
+
+/* Shift {PTR, SIZE} COUNT bits to the left, and fill the vacated bits
+   with the COUNT most significant bits of LIMB.
+
+   Tege doesn't like this function so I have to write it here myself. :)
+   --drepper */
+static inline void
+__attribute ((always_inline))
+mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count,
+	      mp_limb_t limb)
+{
+  if (__builtin_constant_p (count) && count == BITS_PER_MP_LIMB)
+    {
+      /* Optimize the case of shifting by exactly a word:
+	 just copy words, with no actual bit-shifting.  */
+      mp_size_t i;
+      for (i = size - 1; i > 0; --i)
+	ptr[i] = ptr[i - 1];
+      ptr[0] = limb;
+    }
+  else
+    {
+      (void) mpn_lshift (ptr, ptr, size, count);
+      ptr[0] |= limb >> (BITS_PER_MP_LIMB - count);
+    }
+}
+
+
+#define INTERNAL(x) INTERNAL1(x)
+#define INTERNAL1(x) __##x##_internal
+#ifndef ____STRTOF_INTERNAL
+# define ____STRTOF_INTERNAL INTERNAL (__STRTOF)
+#endif
+
+/* This file defines a function to check for correct grouping.  */
+#include "grouping.h"
+
+
+/* Return a floating point number with the value of the given string NPTR.
+   Set *ENDPTR to the character after the last used one.  If the number is
+   smaller than the smallest representable number, set `errno' to ERANGE and
+   return 0.0.  If the number is too big to be represented, set `errno' to
+   ERANGE and return HUGE_VAL with the appropriate sign.  */
+FLOAT
+____STRTOF_INTERNAL (nptr, endptr, group)
+     const STRING_TYPE *nptr;
+     STRING_TYPE **endptr;
+     int group;
+{
+  int negative;			/* The sign of the number.  */
+  MPN_VAR (num);		/* MP representation of the number.  */
+  int exponent;			/* Exponent of the number.  */
+
+  /* Numbers starting `0X' or `0x' have to be processed with base 16.  */
+  int base = 10;
+
+  /* When we have to compute fractional digits we form a fraction with a
+     second multi-precision number (and we sometimes need a second for
+     temporary results).  */
+  MPN_VAR (den);
+
+  /* Representation for the return value.  */
+  mp_limb_t retval[RETURN_LIMB_SIZE];
+  /* Number of bits currently in result value.  */
+  int bits;
+
+  /* Running pointer after the last character processed in the string.  */
+  const STRING_TYPE *cp, *tp;
+  /* Start of significant part of the number.  */
+  const STRING_TYPE *startp, *start_of_digits;
+  /* Points at the character following the integer and fractional digits.  */
+  const STRING_TYPE *expp;
+  /* Total number of digit and number of digits in integer part.  */
+  int dig_no, int_no, lead_zero;
+  /* Contains the last character read.  */
+  CHAR_TYPE c;
+
+  /* The radix character of the current locale.  */
+#ifdef USE_WIDE_CHAR
+  wchar_t decimal;
+#else
+  const char *decimal;
+  size_t decimal_len;
+#endif
+  /* The thousands character of the current locale.  */
+#ifdef USE_WIDE_CHAR
+  wchar_t thousands = L'\0';
+#else
+  const char *thousands = NULL;
+#endif
+  /* The numeric grouping specification of the current locale,
+     in the format described in <locale.h>.  */
+  const char *grouping;
+  /* Used in several places.  */
+  int cnt;
+
+#if defined USE_LOCALECONV && !defined USE_NL_LANGINFO
+  const struct lconv *lc = localeconv ();
+#endif
+
+  if (__builtin_expect (group, 0))
+    {
+#ifdef USE_NL_LANGINFO
+      grouping = nl_langinfo (GROUPING);
+      if (*grouping <= 0 || *grouping == CHAR_MAX)
+	grouping = NULL;
+      else
+	{
+	  /* Figure out the thousands separator character.  */
+#ifdef USE_WIDE_CHAR
+	  thousands = nl_langinfo_wc (_NL_NUMERIC_THOUSANDS_SEP_WC);
+	  if (thousands == L'\0')
+	    grouping = NULL;
+#else
+	  thousands = nl_langinfo (THOUSANDS_SEP);
+	  if (*thousands == '\0')
+	    {
+	      thousands = NULL;
+	      grouping = NULL;
+	    }
+#endif
+	}
+#elif defined USE_LOCALECONV
+      grouping = lc->grouping;
+      if (grouping == NULL || *grouping <= 0 || *grouping == CHAR_MAX)
+	grouping = NULL;
+      else
+	{
+	  /* Figure out the thousands separator character.  */
+	  thousands = lc->thousands_sep;
+	  if (thousands == NULL || *thousands == '\0')
+	    {
+	      thousands = NULL;
+	      grouping = NULL;
+	    }
+	}
+#else
+      grouping = NULL;
+#endif
+    }
+  else
+    grouping = NULL;
+
+  /* Find the locale's decimal point character.  */
+#ifdef USE_WIDE_CHAR
+  decimal = nl_langinfo_wc (_NL_NUMERIC_DECIMAL_POINT_WC);
+  assert (decimal != L'\0');
+# define decimal_len 1
+#else
+#ifdef USE_NL_LANGINFO
+  decimal = nl_langinfo (DECIMAL_POINT);
+  decimal_len = strlen (decimal);
+  assert (decimal_len > 0);
+#elif defined USE_LOCALECONV
+  decimal = lc->decimal_point;
+  if (decimal == NULL || *decimal == '\0')
+    decimal = ".";
+  decimal_len = strlen (decimal);
+#else
+  decimal = ".";
+  decimal_len = 1;
+#endif
+#endif
+
+  /* Prepare number representation.  */
+  exponent = 0;
+  negative = 0;
+  bits = 0;
+
+  /* Parse string to get maximal legal prefix.  We need the number of
+     characters of the integer part, the fractional part and the exponent.  */
+  cp = nptr - 1;
+  /* Ignore leading white space.  */
+  do
+    c = *++cp;
+  while (ISSPACE (c));
+
+  /* Get sign of the result.  */
+  if (c == L_('-'))
+    {
+      negative = 1;
+      c = *++cp;
+    }
+  else if (c == L_('+'))
+    c = *++cp;
+
+  /* Return 0.0 if no legal string is found.
+     No character is used even if a sign was found.  */
+#ifdef USE_WIDE_CHAR
+  if (c == (wint_t) decimal
+      && (wint_t) cp[1] >= L'0' && (wint_t) cp[1] <= L'9')
+    {
+      /* We accept it.  This funny construct is here only to indent
+	 the code correctly.  */
+    }
+#else
+  for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+    if (cp[cnt] != decimal[cnt])
+      break;
+  if (decimal[cnt] == '\0' && cp[cnt] >= '0' && cp[cnt] <= '9')
+    {
+      /* We accept it.  This funny construct is here only to indent
+	 the code correctly.  */
+    }
+#endif
+  else if (c < L_('0') || c > L_('9'))
+    {
+      /* Check for `INF' or `INFINITY'.  */
+      CHAR_TYPE lowc = TOLOWER_C (c);
+
+      if (lowc == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0)
+	{
+	  /* Return +/- infinity.  */
+	  if (endptr != NULL)
+	    *endptr = (STRING_TYPE *)
+		      (cp + (STRNCASECMP (cp + 3, L_("inity"), 5) == 0
+			     ? 8 : 3));
+
+	  return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+	}
+
+      if (lowc == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0)
+	{
+	  /* Return NaN.  */
+	  FLOAT retval = NAN;
+
+	  cp += 3;
+
+	  /* Match `(n-char-sequence-digit)'.  */
+	  if (*cp == L_('('))
+	    {
+	      const STRING_TYPE *startp = cp;
+	      do
+		++cp;
+	      while ((*cp >= L_('0') && *cp <= L_('9'))
+		     || ({ CHAR_TYPE lo = TOLOWER (*cp);
+			   lo >= L_('a') && lo <= L_('z'); })
+		     || *cp == L_('_'));
+
+	      if (*cp != L_(')'))
+		/* The closing brace is missing.  Only match the NAN
+		   part.  */
+		cp = startp;
+	      else
+		{
+		  /* This is a system-dependent way to specify the
+		     bitmask used for the NaN.  We expect it to be
+		     a number which is put in the mantissa of the
+		     number.  */
+		  STRING_TYPE *endp;
+		  unsigned long long int mant;
+
+		  mant = STRTOULL (startp + 1, &endp, 0);
+		  if (endp == cp)
+		    SET_MANTISSA (retval, mant);
+
+		  /* Consume the closing brace.  */
+		  ++cp;
+		}
+	    }
+
+	  if (endptr != NULL)
+	    *endptr = (STRING_TYPE *) cp;
+
+	  return retval;
+	}
+
+      /* It is really a text we do not recognize.  */
+      RETURN (0.0, nptr);
+    }
+
+  /* First look whether we are faced with a hexadecimal number.  */
+  if (c == L_('0') && TOLOWER (cp[1]) == L_('x'))
+    {
+      /* Okay, it is a hexa-decimal number.  Remember this and skip
+	 the characters.  BTW: hexadecimal numbers must not be
+	 grouped.  */
+      base = 16;
+      cp += 2;
+      c = *cp;
+      grouping = NULL;
+    }
+
+  /* Record the start of the digits, in case we will check their grouping.  */
+  start_of_digits = startp = cp;
+
+  /* Ignore leading zeroes.  This helps us to avoid useless computations.  */
+#ifdef USE_WIDE_CHAR
+  while (c == L'0' || ((wint_t) thousands != L'\0' && c == (wint_t) thousands))
+    c = *++cp;
+#else
+  if (__builtin_expect (thousands == NULL, 1))
+    while (c == '0')
+      c = *++cp;
+  else
+    {
+      /* We also have the multibyte thousands string.  */
+      while (1)
+	{
+	  if (c != '0')
+	    {
+	      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
+		if (thousands[cnt] != cp[cnt])
+		  break;
+	      if (thousands[cnt] != '\0')
+		break;
+	      cp += cnt - 1;
+	    }
+	  c = *++cp;
+	}
+    }
+#endif
+
+  /* If no other digit but a '0' is found the result is 0.0.
+     Return current read pointer.  */
+  CHAR_TYPE lowc = TOLOWER (c);
+  if (!((c >= L_('0') && c <= L_('9'))
+	|| (base == 16 && lowc >= L_('a') && lowc <= L_('f'))
+	|| (
+#ifdef USE_WIDE_CHAR
+	    c == (wint_t) decimal
+#else
+	    ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+		 if (decimal[cnt] != cp[cnt])
+		   break;
+	       decimal[cnt] == '\0'; })
+#endif
+	    /* '0x.' alone is not a valid hexadecimal number.
+	       '.' alone is not valid either, but that has been checked
+	       already earlier.  */
+	    && (base != 16
+		|| cp != start_of_digits
+		|| (cp[decimal_len] >= L_('0') && cp[decimal_len] <= L_('9'))
+		|| ({ CHAR_TYPE lo = TOLOWER (cp[decimal_len]);
+		      lo >= L_('a') && lo <= L_('f'); })))
+	|| (base == 16 && (cp != start_of_digits
+			   && lowc == L_('p')))
+	|| (base != 16 && lowc == L_('e'))))
+    {
+#ifdef USE_WIDE_CHAR
+      tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
+					 grouping);
+#else
+      tp = __correctly_grouped_prefixmb (start_of_digits, cp, thousands,
+					 grouping);
+#endif
+      /* If TP is at the start of the digits, there was no correctly
+	 grouped prefix of the string; so no number found.  */
+      RETURN (negative ? -0.0 : 0.0,
+	      tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp);
+    }
+
+  /* Remember first significant digit and read following characters until the
+     decimal point, exponent character or any non-FP number character.  */
+  startp = cp;
+  dig_no = 0;
+  while (1)
+    {
+      if ((c >= L_('0') && c <= L_('9'))
+	  || (base == 16
+	      && ({ CHAR_TYPE lo = TOLOWER (c);
+		    lo >= L_('a') && lo <= L_('f'); })))
+	++dig_no;
+      else
+	{
+#ifdef USE_WIDE_CHAR
+	  if (__builtin_expect ((wint_t) thousands == L'\0', 1)
+	      || c != (wint_t) thousands)
+	    /* Not a digit or separator: end of the integer part.  */
+	    break;
+#else
+	  if (__builtin_expect (thousands == NULL, 1))
+	    break;
+	  else
+	    {
+	      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
+		if (thousands[cnt] != cp[cnt])
+		  break;
+	      if (thousands[cnt] != '\0')
+		break;
+	      cp += cnt - 1;
+	    }
+#endif
+	}
+      c = *++cp;
+    }
+
+  if (__builtin_expect (grouping != NULL, 0) && cp > start_of_digits)
+    {
+      /* Check the grouping of the digits.  */
+#ifdef USE_WIDE_CHAR
+      tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
+					 grouping);
+#else
+      tp = __correctly_grouped_prefixmb (start_of_digits, cp, thousands,
+					 grouping);
+#endif
+      if (cp != tp)
+	{
+	  /* Less than the entire string was correctly grouped.  */
+
+	  if (tp == start_of_digits)
+	    /* No valid group of numbers at all: no valid number.  */
+	    RETURN (0.0, nptr);
+
+	  if (tp < startp)
+	    /* The number is validly grouped, but consists
+	       only of zeroes.  The whole value is zero.  */
+	    RETURN (negative ? -0.0 : 0.0, tp);
+
+	  /* Recompute DIG_NO so we won't read more digits than
+	     are properly grouped.  */
+	  cp = tp;
+	  dig_no = 0;
+	  for (tp = startp; tp < cp; ++tp)
+	    if (*tp >= L_('0') && *tp <= L_('9'))
+	      ++dig_no;
+
+	  int_no = dig_no;
+	  lead_zero = 0;
+
+	  goto number_parsed;
+	}
+    }
+
+  /* We have the number of digits in the integer part.  Whether these
+     are all or any is really a fractional digit will be decided
+     later.  */
+  int_no = dig_no;
+  lead_zero = int_no == 0 ? -1 : 0;
+
+  /* Read the fractional digits.  A special case are the 'american
+     style' numbers like `16.' i.e. with decimal point but without
+     trailing digits.  */
+  if (
+#ifdef USE_WIDE_CHAR
+      c == (wint_t) decimal
+#else
+      ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
+	   if (decimal[cnt] != cp[cnt])
+	     break;
+	 decimal[cnt] == '\0'; })
+#endif
+      )
+    {
+      cp += decimal_len;
+      c = *cp;
+      while ((c >= L_('0') && c <= L_('9')) ||
+	     (base == 16 && ({ CHAR_TYPE lo = TOLOWER (c);
+			       lo >= L_('a') && lo <= L_('f'); })))
+	{
+	  if (c != L_('0') && lead_zero == -1)
+	    lead_zero = dig_no - int_no;
+	  ++dig_no;
+	  c = *++cp;
+	}
+    }
+
+  /* Remember start of exponent (if any).  */
+  expp = cp;
+
+  /* Read exponent.  */
+  lowc = TOLOWER (c);
+  if ((base == 16 && lowc == L_('p'))
+      || (base != 16 && lowc == L_('e')))
+    {
+      int exp_negative = 0;
+
+      c = *++cp;
+      if (c == L_('-'))
+	{
+	  exp_negative = 1;
+	  c = *++cp;
+	}
+      else if (c == L_('+'))
+	c = *++cp;
+
+      if (c >= L_('0') && c <= L_('9'))
+	{
+	  int exp_limit;
+
+	  /* Get the exponent limit. */
+	  if (base == 16)
+	    exp_limit = (exp_negative ?
+			 -MIN_EXP + MANT_DIG + 4 * int_no :
+			 MAX_EXP - 4 * int_no + 4 * lead_zero + 3);
+	  else
+	    exp_limit = (exp_negative ?
+			 -MIN_10_EXP + MANT_DIG + int_no :
+			 MAX_10_EXP - int_no + lead_zero + 1);
+
+	  do
+	    {
+	      exponent *= 10;
+	      exponent += c - L_('0');
+
+	      if (__builtin_expect (exponent > exp_limit, 0))
+		/* The exponent is too large/small to represent a valid
+		   number.  */
+		{
+	 	  FLOAT result;
+
+		  /* We have to take care for special situation: a joker
+		     might have written "0.0e100000" which is in fact
+		     zero.  */
+		  if (lead_zero == -1)
+		    result = negative ? -0.0 : 0.0;
+		  else
+		    {
+		      /* Overflow or underflow.  */
+#if defined HAVE_ERRNO_H && defined ERANGE
+		      errno = ERANGE;
+#endif
+		      result = (exp_negative ? (negative ? -0.0 : 0.0) :
+				negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL);
+		    }
+
+		  /* Accept all following digits as part of the exponent.  */
+		  do
+		    ++cp;
+		  while (*cp >= L_('0') && *cp <= L_('9'));
+
+		  RETURN (result, cp);
+		  /* NOTREACHED */
+		}
+
+	      c = *++cp;
+	    }
+	  while (c >= L_('0') && c <= L_('9'));
+
+	  if (exp_negative)
+	    exponent = -exponent;
+	}
+      else
+	cp = expp;
+    }
+
+  /* We don't want to have to work with trailing zeroes after the radix.  */
+  if (dig_no > int_no)
+    {
+      while (expp[-1] == L_('0'))
+	{
+	  --expp;
+	  --dig_no;
+	}
+      assert (dig_no >= int_no);
+    }
+
+  if (dig_no == int_no && dig_no > 0 && exponent < 0)
+    do
+      {
+	while (! (base == 16 ? ISXDIGIT (expp[-1]) : ISDIGIT (expp[-1])))
+	  --expp;
+
+	if (expp[-1] != L_('0'))
+	  break;
+
+	--expp;
+	--dig_no;
+	--int_no;
+	exponent += base == 16 ? 4 : 1;
+      }
+    while (dig_no > 0 && exponent < 0);
+
+ number_parsed:
+
+  /* The whole string is parsed.  Store the address of the next character.  */
+  if (endptr)
+    *endptr = (STRING_TYPE *) cp;
+
+  if (dig_no == 0)
+    return negative ? -0.0 : 0.0;
+
+  if (lead_zero)
+    {
+      /* Find the decimal point */
+#ifdef USE_WIDE_CHAR
+      while (*startp != decimal)
+	++startp;
+#else
+      while (1)
+	{
+	  if (*startp == decimal[0])
+	    {
+	      for (cnt = 1; decimal[cnt] != '\0'; ++cnt)
+		if (decimal[cnt] != startp[cnt])
+		  break;
+	      if (decimal[cnt] == '\0')
+		break;
+	    }
+	  ++startp;
+	}
+#endif
+      startp += lead_zero + decimal_len;
+      exponent -= base == 16 ? 4 * lead_zero : lead_zero;
+      dig_no -= lead_zero;
+    }
+
+  /* If the BASE is 16 we can use a simpler algorithm.  */
+  if (base == 16)
+    {
+      static const int nbits[16] = { 0, 1, 2, 2, 3, 3, 3, 3,
+				     4, 4, 4, 4, 4, 4, 4, 4 };
+      int idx = (MANT_DIG - 1) / BITS_PER_MP_LIMB;
+      int pos = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
+      mp_limb_t val;
+
+      while (!ISXDIGIT (*startp))
+	++startp;
+      while (*startp == L_('0'))
+	++startp;
+      if (ISDIGIT (*startp))
+	val = *startp++ - L_('0');
+      else
+	val = 10 + TOLOWER (*startp++) - L_('a');
+      bits = nbits[val];
+      /* We cannot have a leading zero.  */
+      assert (bits != 0);
+
+      if (pos + 1 >= 4 || pos + 1 >= bits)
+	{
+	  /* We don't have to care for wrapping.  This is the normal
+	     case so we add the first clause in the `if' expression as
+	     an optimization.  It is a compile-time constant and so does
+	     not cost anything.  */
+	  retval[idx] = val << (pos - bits + 1);
+	  pos -= bits;
+	}
+      else
+	{
+	  retval[idx--] = val >> (bits - pos - 1);
+	  retval[idx] = val << (BITS_PER_MP_LIMB - (bits - pos - 1));
+	  pos = BITS_PER_MP_LIMB - 1 - (bits - pos - 1);
+	}
+
+      /* Adjust the exponent for the bits we are shifting in.  */
+      exponent += bits - 1 + (int_no - 1) * 4;
+
+      while (--dig_no > 0 && idx >= 0)
+	{
+	  if (!ISXDIGIT (*startp))
+	    startp += decimal_len;
+	  if (ISDIGIT (*startp))
+	    val = *startp++ - L_('0');
+	  else
+	    val = 10 + TOLOWER (*startp++) - L_('a');
+
+	  if (pos + 1 >= 4)
+	    {
+	      retval[idx] |= val << (pos - 4 + 1);
+	      pos -= 4;
+	    }
+	  else
+	    {
+	      retval[idx--] |= val >> (4 - pos - 1);
+	      val <<= BITS_PER_MP_LIMB - (4 - pos - 1);
+	      if (idx < 0)
+		return round_and_return (retval, exponent, negative, val,
+					 BITS_PER_MP_LIMB - 1, dig_no > 0);
+
+	      retval[idx] = val;
+	      pos = BITS_PER_MP_LIMB - 1 - (4 - pos - 1);
+	    }
+	}
+
+      /* We ran out of digits.  */
+      MPN_ZERO (retval, idx);
+
+      return round_and_return (retval, exponent, negative, 0, 0, 0);
+    }
+
+  /* Now we have the number of digits in total and the integer digits as well
+     as the exponent and its sign.  We can decide whether the read digits are
+     really integer digits or belong to the fractional part; i.e. we normalize
+     123e-2 to 1.23.  */
+  {
+    register int incr = (exponent < 0 ? MAX (-int_no, exponent)
+			 : MIN (dig_no - int_no, exponent));
+    int_no += incr;
+    exponent -= incr;
+  }
+
+  if (__builtin_expect (int_no + exponent > MAX_10_EXP + 1, 0))
+    {
+#if defined HAVE_ERRNO_H && defined ERANGE
+      errno = ERANGE;
+#endif
+      return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+    }
+
+  if (__builtin_expect (exponent < MIN_10_EXP - (DIG + 1), 0))
+    {
+#if defined HAVE_ERRNO_H && defined ERANGE
+      errno = ERANGE;
+#endif
+      return negative ? -0.0 : 0.0;
+    }
+
+  if (int_no > 0)
+    {
+      /* Read the integer part as a multi-precision number to NUM.  */
+      startp = str_to_mpn (startp, int_no, num, &numsize, &exponent
+#ifndef USE_WIDE_CHAR
+			   , decimal, decimal_len, thousands
+#endif
+			   );
+
+      if (exponent > 0)
+	{
+	  /* We now multiply the gained number by the given power of ten.  */
+	  mp_limb_t *psrc = num;
+	  mp_limb_t *pdest = den;
+	  int expbit = 1;
+	  const struct mp_power *ttab = &_fpioconst_pow10[0];
+
+	  do
+	    {
+	      if ((exponent & expbit) != 0)
+		{
+		  size_t size = ttab->arraysize - _FPIO_CONST_OFFSET;
+		  mp_limb_t cy;
+		  exponent ^= expbit;
+
+		  /* FIXME: not the whole multiplication has to be
+		     done.  If we have the needed number of bits we
+		     only need the information whether more non-zero
+		     bits follow.  */
+		  if (numsize >= ttab->arraysize - _FPIO_CONST_OFFSET)
+		    cy = mpn_mul (pdest, psrc, numsize,
+				  &__tens[ttab->arrayoff
+					  + _FPIO_CONST_OFFSET],
+				  size);
+		  else
+		    cy = mpn_mul (pdest, &__tens[ttab->arrayoff
+						 + _FPIO_CONST_OFFSET],
+				  size, psrc, numsize);
+		  numsize += size;
+		  if (cy == 0)
+		    --numsize;
+		  (void) SWAP (psrc, pdest);
+		}
+	      expbit <<= 1;
+	      ++ttab;
+	    }
+	  while (exponent != 0);
+
+	  if (psrc == den)
+	    memcpy (num, den, numsize * sizeof (mp_limb_t));
+	}
+
+      /* Determine how many bits of the result we already have.  */
+      count_leading_zeros (bits, num[numsize - 1]);
+      bits = numsize * BITS_PER_MP_LIMB - bits;
+
+      /* Now we know the exponent of the number in base two.
+	 Check it against the maximum possible exponent.  */
+      if (__builtin_expect (bits > MAX_EXP, 0))
+	{
+#if defined HAVE_ERRNO_H && defined ERANGE
+	  errno = ERANGE;
+#endif
+	  return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+	}
+
+      /* We have already the first BITS bits of the result.  Together with
+	 the information whether more non-zero bits follow this is enough
+	 to determine the result.  */
+      if (bits > MANT_DIG)
+	{
+	  int i;
+	  const mp_size_t least_idx = (bits - MANT_DIG) / BITS_PER_MP_LIMB;
+	  const mp_size_t least_bit = (bits - MANT_DIG) % BITS_PER_MP_LIMB;
+	  const mp_size_t round_idx = least_bit == 0 ? least_idx - 1
+						     : least_idx;
+	  const mp_size_t round_bit = least_bit == 0 ? BITS_PER_MP_LIMB - 1
+						     : least_bit - 1;
+
+	  if (least_bit == 0)
+	    memcpy (retval, &num[least_idx],
+		    RETURN_LIMB_SIZE * sizeof (mp_limb_t));
+	  else
+	    {
+	      for (i = least_idx; i < numsize - 1; ++i)
+		retval[i - least_idx] = (num[i] >> least_bit)
+					| (num[i + 1]
+					   << (BITS_PER_MP_LIMB - least_bit));
+	      if (i - least_idx < RETURN_LIMB_SIZE)
+		retval[RETURN_LIMB_SIZE - 1] = num[i] >> least_bit;
+	    }
+
+	  /* Check whether any limb beside the ones in RETVAL are non-zero.  */
+	  for (i = 0; num[i] == 0; ++i)
+	    ;
+
+	  return round_and_return (retval, bits - 1, negative,
+				   num[round_idx], round_bit,
+				   int_no < dig_no || i < round_idx);
+	  /* NOTREACHED */
+	}
+      else if (dig_no == int_no)
+	{
+	  const mp_size_t target_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
+	  const mp_size_t is_bit = (bits - 1) % BITS_PER_MP_LIMB;
+
+	  if (target_bit == is_bit)
+	    {
+	      memcpy (&retval[RETURN_LIMB_SIZE - numsize], num,
+		      numsize * sizeof (mp_limb_t));
+	      /* FIXME: the following loop can be avoided if we assume a
+		 maximal MANT_DIG value.  */
+	      MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize);
+	    }
+	  else if (target_bit > is_bit)
+	    {
+	      (void) mpn_lshift (&retval[RETURN_LIMB_SIZE - numsize],
+				 num, numsize, target_bit - is_bit);
+	      /* FIXME: the following loop can be avoided if we assume a
+		 maximal MANT_DIG value.  */
+	      MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize);
+	    }
+	  else
+	    {
+	      mp_limb_t cy;
+	      assert (numsize < RETURN_LIMB_SIZE);
+
+	      cy = mpn_rshift (&retval[RETURN_LIMB_SIZE - numsize],
+			       num, numsize, is_bit - target_bit);
+	      retval[RETURN_LIMB_SIZE - numsize - 1] = cy;
+	      /* FIXME: the following loop can be avoided if we assume a
+		 maximal MANT_DIG value.  */
+	      MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize - 1);
+	    }
+
+	  return round_and_return (retval, bits - 1, negative, 0, 0, 0);
+	  /* NOTREACHED */
+	}
+
+      /* Store the bits we already have.  */
+      memcpy (retval, num, numsize * sizeof (mp_limb_t));
+#if RETURN_LIMB_SIZE > 1
+      if (numsize < RETURN_LIMB_SIZE)
+# if RETURN_LIMB_SIZE == 2
+	retval[numsize] = 0;
+# else
+	MPN_ZERO (retval + numsize, RETURN_LIMB_SIZE - numsize);
+# endif
+#endif
+    }
+
+  /* We have to compute at least some of the fractional digits.  */
+  {
+    /* We construct a fraction and the result of the division gives us
+       the needed digits.  The denominator is 1.0 multiplied by the
+       exponent of the lowest digit; i.e. 0.123 gives 123 / 1000 and
+       123e-6 gives 123 / 1000000.  */
+
+    int expbit;
+    int neg_exp;
+    int more_bits;
+    mp_limb_t cy;
+    mp_limb_t *psrc = den;
+    mp_limb_t *pdest = num;
+    const struct mp_power *ttab = &_fpioconst_pow10[0];
+
+    assert (dig_no > int_no && exponent <= 0);
+
+
+    /* For the fractional part we need not process too many digits.  One
+       decimal digits gives us log_2(10) ~ 3.32 bits.  If we now compute
+			ceil(BITS / 3) =: N
+       digits we should have enough bits for the result.  The remaining
+       decimal digits give us the information that more bits are following.
+       This can be used while rounding.  (Two added as a safety margin.)  */
+    if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 2)
+      {
+	dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 2;
+	more_bits = 1;
+      }
+    else
+      more_bits = 0;
+
+    neg_exp = dig_no - int_no - exponent;
+
+    /* Construct the denominator.  */
+    densize = 0;
+    expbit = 1;
+    do
+      {
+	if ((neg_exp & expbit) != 0)
+	  {
+	    mp_limb_t cy;
+	    neg_exp ^= expbit;
+
+	    if (densize == 0)
+	      {
+		densize = ttab->arraysize - _FPIO_CONST_OFFSET;
+		memcpy (psrc, &__tens[ttab->arrayoff + _FPIO_CONST_OFFSET],
+			densize * sizeof (mp_limb_t));
+	      }
+	    else
+	      {
+		cy = mpn_mul (pdest, &__tens[ttab->arrayoff
+					     + _FPIO_CONST_OFFSET],
+			      ttab->arraysize - _FPIO_CONST_OFFSET,
+			      psrc, densize);
+		densize += ttab->arraysize - _FPIO_CONST_OFFSET;
+		if (cy == 0)
+		  --densize;
+		(void) SWAP (psrc, pdest);
+	      }
+	  }
+	expbit <<= 1;
+	++ttab;
+      }
+    while (neg_exp != 0);
+
+    if (psrc == num)
+      memcpy (den, num, densize * sizeof (mp_limb_t));
+
+    /* Read the fractional digits from the string.  */
+    (void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent
+#ifndef USE_WIDE_CHAR
+		       , decimal, decimal_len, thousands
+#endif
+		       );
+
+    /* We now have to shift both numbers so that the highest bit in the
+       denominator is set.  In the same process we copy the numerator to
+       a high place in the array so that the division constructs the wanted
+       digits.  This is done by a "quasi fix point" number representation.
+
+       num:   ddddddddddd . 0000000000000000000000
+	      |--- m ---|
+       den:                            ddddddddddd      n >= m
+				       |--- n ---|
+     */
+
+    count_leading_zeros (cnt, den[densize - 1]);
+
+    if (cnt > 0)
+      {
+	/* Don't call `mpn_shift' with a count of zero since the specification
+	   does not allow this.  */
+	(void) mpn_lshift (den, den, densize, cnt);
+	cy = mpn_lshift (num, num, numsize, cnt);
+	if (cy != 0)
+	  num[numsize++] = cy;
+      }
+
+    /* Now we are ready for the division.  But it is not necessary to
+       do a full multi-precision division because we only need a small
+       number of bits for the result.  So we do not use mpn_divmod
+       here but instead do the division here by hand and stop whenever
+       the needed number of bits is reached.  The code itself comes
+       from the GNU MP Library by Torbj\"orn Granlund.  */
+
+    exponent = bits;
+
+    switch (densize)
+      {
+      case 1:
+	{
+	  mp_limb_t d, n, quot;
+	  int used = 0;
+
+	  n = num[0];
+	  d = den[0];
+	  assert (numsize == 1 && n < d);
+
+	  do
+	    {
+	      udiv_qrnnd (quot, n, n, 0, d);
+
+#define got_limb							      \
+	      if (bits == 0)						      \
+		{							      \
+		  register int cnt;					      \
+		  if (quot == 0)					      \
+		    cnt = BITS_PER_MP_LIMB;				      \
+		  else							      \
+		    count_leading_zeros (cnt, quot);			      \
+		  exponent -= cnt;					      \
+		  if (BITS_PER_MP_LIMB - cnt > MANT_DIG)		      \
+		    {							      \
+		      used = MANT_DIG + cnt;				      \
+		      retval[0] = quot >> (BITS_PER_MP_LIMB - used);	      \
+		      bits = MANT_DIG + 1;				      \
+		    }							      \
+		  else							      \
+		    {							      \
+		      /* Note that we only clear the second element.  */      \
+		      /* The conditional is determined at compile time.  */   \
+		      if (RETURN_LIMB_SIZE > 1)				      \
+			retval[1] = 0;					      \
+		      retval[0] = quot;					      \
+		      bits = -cnt;					      \
+		    }							      \
+		}							      \
+	      else if (bits + BITS_PER_MP_LIMB <= MANT_DIG)		      \
+		mpn_lshift_1 (retval, RETURN_LIMB_SIZE, BITS_PER_MP_LIMB,     \
+			      quot);					      \
+	      else							      \
+		{							      \
+		  used = MANT_DIG - bits;				      \
+		  if (used > 0)						      \
+		    mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, quot);      \
+		}							      \
+	      bits += BITS_PER_MP_LIMB
+
+	      got_limb;
+	    }
+	  while (bits <= MANT_DIG);
+
+	  return round_and_return (retval, exponent - 1, negative,
+				   quot, BITS_PER_MP_LIMB - 1 - used,
+				   more_bits || n != 0);
+	}
+      case 2:
+	{
+	  mp_limb_t d0, d1, n0, n1;
+	  mp_limb_t quot = 0;
+	  int used = 0;
+
+	  d0 = den[0];
+	  d1 = den[1];
+
+	  if (numsize < densize)
+	    {
+	      if (num[0] >= d1)
+		{
+		  /* The numerator of the number occupies fewer bits than
+		     the denominator but the one limb is bigger than the
+		     high limb of the numerator.  */
+		  n1 = 0;
+		  n0 = num[0];
+		}
+	      else
+		{
+		  if (bits <= 0)
+		    exponent -= BITS_PER_MP_LIMB;
+		  else
+		    {
+		      if (bits + BITS_PER_MP_LIMB <= MANT_DIG)
+			mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
+				      BITS_PER_MP_LIMB, 0);
+		      else
+			{
+			  used = MANT_DIG - bits;
+			  if (used > 0)
+			    mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
+			}
+		      bits += BITS_PER_MP_LIMB;
+		    }
+		  n1 = num[0];
+		  n0 = 0;
+		}
+	    }
+	  else
+	    {
+	      n1 = num[1];
+	      n0 = num[0];
+	    }
+
+	  while (bits <= MANT_DIG)
+	    {
+	      mp_limb_t r;
+
+	      if (n1 == d1)
+		{
+		  /* QUOT should be either 111..111 or 111..110.  We need
+		     special treatment of this rare case as normal division
+		     would give overflow.  */
+		  quot = ~(mp_limb_t) 0;
+
+		  r = n0 + d1;
+		  if (r < d1)	/* Carry in the addition?  */
+		    {
+		      add_ssaaaa (n1, n0, r - d0, 0, 0, d0);
+		      goto have_quot;
+		    }
+		  n1 = d0 - (d0 != 0);
+		  n0 = -d0;
+		}
+	      else
+		{
+		  udiv_qrnnd (quot, r, n1, n0, d1);
+		  umul_ppmm (n1, n0, d0, quot);
+		}
+
+	    q_test:
+	      if (n1 > r || (n1 == r && n0 > 0))
+		{
+		  /* The estimated QUOT was too large.  */
+		  --quot;
+
+		  sub_ddmmss (n1, n0, n1, n0, 0, d0);
+		  r += d1;
+		  if (r >= d1)	/* If not carry, test QUOT again.  */
+		    goto q_test;
+		}
+	      sub_ddmmss (n1, n0, r, 0, n1, n0);
+
+	    have_quot:
+	      got_limb;
+	    }
+
+	  return round_and_return (retval, exponent - 1, negative,
+				   quot, BITS_PER_MP_LIMB - 1 - used,
+				   more_bits || n1 != 0 || n0 != 0);
+	}
+      default:
+	{
+	  int i;
+	  mp_limb_t cy, dX, d1, n0, n1;
+	  mp_limb_t quot = 0;
+	  int used = 0;
+
+	  dX = den[densize - 1];
+	  d1 = den[densize - 2];
+
+	  /* The division does not work if the upper limb of the two-limb
+	     numerator is greater than the denominator.  */
+	  if (mpn_cmp (num, &den[densize - numsize], numsize) > 0)
+	    num[numsize++] = 0;
+
+	  if (numsize < densize)
+	    {
+	      mp_size_t empty = densize - numsize;
+	      register int i;
+
+	      if (bits <= 0)
+		exponent -= empty * BITS_PER_MP_LIMB;
+	      else
+		{
+		  if (bits + empty * BITS_PER_MP_LIMB <= MANT_DIG)
+		    {
+		      /* We make a difference here because the compiler
+			 cannot optimize the `else' case that good and
+			 this reflects all currently used FLOAT types
+			 and GMP implementations.  */
+#if RETURN_LIMB_SIZE <= 2
+		      assert (empty == 1);
+		      mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
+				    BITS_PER_MP_LIMB, 0);
+#else
+		      for (i = RETURN_LIMB_SIZE - 1; i >= empty; --i)
+			retval[i] = retval[i - empty];
+		      while (i >= 0)
+			retval[i--] = 0;
+#endif
+		    }
+		  else
+		    {
+		      used = MANT_DIG - bits;
+		      if (used >= BITS_PER_MP_LIMB)
+			{
+			  register int i;
+			  (void) mpn_lshift (&retval[used
+						     / BITS_PER_MP_LIMB],
+					     retval,
+					     (RETURN_LIMB_SIZE
+					      - used / BITS_PER_MP_LIMB),
+					     used % BITS_PER_MP_LIMB);
+			  for (i = used / BITS_PER_MP_LIMB - 1; i >= 0; --i)
+			    retval[i] = 0;
+			}
+		      else if (used > 0)
+			mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
+		    }
+		  bits += empty * BITS_PER_MP_LIMB;
+		}
+	      for (i = numsize; i > 0; --i)
+		num[i + empty] = num[i - 1];
+	      MPN_ZERO (num, empty + 1);
+	    }
+	  else
+	    {
+	      int i;
+	      assert (numsize == densize);
+	      for (i = numsize; i > 0; --i)
+		num[i] = num[i - 1];
+	    }
+
+	  den[densize] = 0;
+	  n0 = num[densize];
+
+	  while (bits <= MANT_DIG)
+	    {
+	      if (n0 == dX)
+		/* This might over-estimate QUOT, but it's probably not
+		   worth the extra code here to find out.  */
+		quot = ~(mp_limb_t) 0;
+	      else
+		{
+		  mp_limb_t r;
+
+		  udiv_qrnnd (quot, r, n0, num[densize - 1], dX);
+		  umul_ppmm (n1, n0, d1, quot);
+
+		  while (n1 > r || (n1 == r && n0 > num[densize - 2]))
+		    {
+		      --quot;
+		      r += dX;
+		      if (r < dX) /* I.e. "carry in previous addition?" */
+			break;
+		      n1 -= n0 < d1;
+		      n0 -= d1;
+		    }
+		}
+
+	      /* Possible optimization: We already have (q * n0) and (1 * n1)
+		 after the calculation of QUOT.  Taking advantage of this, we
+		 could make this loop make two iterations less.  */
+
+	      cy = mpn_submul_1 (num, den, densize + 1, quot);
+
+	      if (num[densize] != cy)
+		{
+		  cy = mpn_add_n (num, num, den, densize);
+		  assert (cy != 0);
+		  --quot;
+		}
+	      n0 = num[densize] = num[densize - 1];
+	      for (i = densize - 1; i > 0; --i)
+		num[i] = num[i - 1];
+
+	      got_limb;
+	    }
+
+	  for (i = densize; num[i] == 0 && i >= 0; --i)
+	    ;
+	  return round_and_return (retval, exponent - 1, negative,
+				   quot, BITS_PER_MP_LIMB - 1 - used,
+				   more_bits || i >= 0);
+	}
+      }
+  }
+
+  /* NOTREACHED */
+}
--- libquadmath/strtod/mpn2flt128.c.jj	2011-02-17 11:00:16.000000000 +0100
+++ libquadmath/strtod/mpn2flt128.c	2011-02-17 12:25:28.000000000 +0100
@@ -0,0 +1,51 @@ 
+/* Copyright (C) 1995,1996,1997,1998,1999,2002,2003
+	Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 <config.h>
+#include <float.h>
+#include <math.h>
+#include "../printf/gmp-impl.h"
+
+/* Convert a multi-precision integer of the needed number of bits (113 for
+   long double) and an integral power of two to a `long double' in IEEE854
+   quad-precision format.  */
+
+__float128
+mpn_construct_float128 (mp_srcptr frac_ptr, int expt, int sign)
+{
+  ieee854_float128 u;
+
+  u.ieee.negative = sign;
+  u.ieee.exponent = expt + IEEE854_FLOAT128_BIAS;
+#if BITS_PER_MP_LIMB == 32
+  u.ieee.mant_low = (((uint64_t) frac_ptr[1]) << 32)
+		    | (frac_ptr[0] & 0xffffffff);
+  u.ieee.mant_high = (((uint64_t) frac_ptr[3]
+		       & (((mp_limb_t) 1 << (FLT128_MANT_DIG - 96)) - 1))
+		      << 32) | (frac_ptr[2] & 0xffffffff);
+#elif BITS_PER_MP_LIMB == 64
+  u.ieee.mant_low = frac_ptr[0];
+  u.ieee.mant_high = frac_ptr[1]
+		     & (((mp_limb_t) 1 << (FLT128_MANT_DIG - 64)) - 1);
+#else
+  #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
+#endif
+
+  return u.value;
+}
--- libquadmath/strtod/grouping.h.jj	2011-02-17 11:53:19.000000000 +0100
+++ libquadmath/strtod/grouping.h	2011-02-17 12:25:59.000000000 +0100
@@ -0,0 +1,37 @@ 
+/* Internal header for proving correct grouping in strings of numbers.
+   Copyright (C) 1995,1996,1997,1998,2000,2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+
+   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.  */
+
+/* Find the maximum prefix of the string between BEGIN and END which
+   satisfies the grouping rules.  It is assumed that at least one digit
+   follows BEGIN directly.  */
+extern const wchar_t *__correctly_grouped_prefixwc (const wchar_t *begin,
+						    const wchar_t *end,
+						    wchar_t thousands,
+						    const char *grouping)
+     attribute_hidden;
+
+extern const char *__correctly_grouped_prefixmb (const char *begin,
+						 const char *end,
+						 const char *thousands,
+						 const char *grouping)
+     attribute_hidden;
+
+/* Disable grouping support for now.  */
+#define __correctly_grouped_prefixmb(b,e,t,g) e
--- libquadmath/strtod/tens_in_limb.c.jj	2011-02-17 12:45:43.000000000 +0100
+++ libquadmath/strtod/tens_in_limb.c	2011-02-17 12:49:43.000000000 +0100
@@ -0,0 +1,33 @@ 
+#include <config.h>
+#include "../printf/gmp-impl.h"
+
+
+/* Definitions according to limb size used.  */
+#if	BITS_PER_MP_LIMB == 32
+# define MAX_DIG_PER_LIMB	9
+# define MAX_FAC_PER_LIMB	1000000000UL
+#elif	BITS_PER_MP_LIMB == 64
+# define MAX_DIG_PER_LIMB	19
+# define MAX_FAC_PER_LIMB	10000000000000000000ULL
+#else
+# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for"
+#endif
+
+
+/* Local data structure.  */
+const mp_limb_t __quadmath_tens_in_limb[MAX_DIG_PER_LIMB + 1] attribute_hidden
+=
+{    0,                   10,                   100,
+     1000,                10000,                100000L,
+     1000000L,            10000000L,            100000000L,
+     1000000000L
+#if BITS_PER_MP_LIMB > 32
+	        ,	  10000000000ULL,       100000000000ULL,
+     1000000000000ULL,    10000000000000ULL,    100000000000000ULL,
+     1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL,
+     1000000000000000000ULL, 10000000000000000000ULL
+#endif
+#if BITS_PER_MP_LIMB > 64
+  #error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB
+#endif
+};
--- libquadmath/quadmath.h.jj	2011-02-15 15:27:13.000000000 +0100
+++ libquadmath/quadmath.h	2011-02-17 12:15:12.000000000 +0100
@@ -144,8 +144,9 @@  extern int quadmath_snprintf (char *str,
 #define FLT128_MANT_DIG 113
 #define FLT128_MIN_EXP (-16381)
 #define FLT128_MAX_EXP 16384
-/* TODO -- One day, we need to add the following macros:
-   FLT128_DIG, FLT128_MIN_10_EXP, FLT128_MAX_10_EXP */
+#define FLT128_DIG 33
+#define FLT128_MIN_10_EXP (-4931)
+#define FLT128_MAX_10_EXP 4932
 
 
 #define HUGE_VALQ __builtin_huge_valq()
--- libquadmath/Makefile.am.jj	2011-02-15 15:27:13.000000000 +0100
+++ libquadmath/Makefile.am	2011-02-17 13:49:44.000000000 +0100
@@ -43,11 +43,6 @@  nodist_libsubinclude_HEADERS = quadmath.
 libsubincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
 
 libquadmath_la_SOURCES = \
-  gdtoa/arith.h gdtoa/gdtoa_fltrnds.h gdtoa/gd_qnan.h gdtoa/gdtoaimp.h \
-  gdtoa/gdtoa.h quadmath-imp.h \
-  gdtoa/hd_init.c gdtoa/smisc.c gdtoa/sum.c \
-  gdtoa/gethex.c gdtoa/hexnan.c gdtoa/strtodg.c \
-  gdtoa/gmisc.c gdtoa/misc.c gdtoa/strtopQ.c \
   math/acoshq.c math/fmodq.c math/acosq.c math/frexpq.c \
   math/rem_pio2q.c math/asinhq.c math/hypotq.c math/remainderq.c \
   math/asinq.c math/rintq.c math/atan2q.c math/isinfq.c \
@@ -68,7 +63,8 @@  libquadmath_la_SOURCES = \
   printf/addmul_1.c printf/add_n.c printf/cmp.c printf/divrem.c \
   printf/flt1282mpn.c printf/fpioconst.c printf/lshift.c printf/mul_1.c \
   printf/mul_n.c printf/mul.c printf/printf_fphex.c printf/printf_fp.c \
-  printf/quadmath-printf.c printf/rshift.c printf/submul_1.c printf/sub_n.c
+  printf/quadmath-printf.c printf/rshift.c printf/submul_1.c printf/sub_n.c \
+  strtod/strtoflt128.c strtod/mpn2flt128.c strtod/tens_in_limb.c
 
 
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
--- libquadmath/config.h.in.jj	2011-02-17 10:10:01.000000000 +0100
+++ libquadmath/config.h.in	2011-02-17 13:55:58.000000000 +0100
@@ -69,6 +69,9 @@ 
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
+/* Define to 1 if you have the `strtoull' function. */
+#undef HAVE_STRTOULL
+
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
 
--- libquadmath/configure.jj	2011-02-17 10:10:01.000000000 +0100
+++ libquadmath/configure	2011-02-17 13:55:56.000000000 +0100
@@ -12255,6 +12255,17 @@  $as_echo "#define HAVE_FETESTEXCEPT 1" >
 
 fi
 
+  for ac_func in strtoull
+do :
+  ac_fn_c_check_func "$LINENO" "strtoull" "ac_cv_func_strtoull"
+if test "x$ac_cv_func_strtoull" = x""yes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRTOULL 1
+_ACEOF
+
+fi
+done
+
 else
   if test "x$ac_cv_lib_m_sqrtl" = x""yes; then
 
--- libquadmath/Makefile.in.jj	2011-02-15 15:27:13.000000000 +0100
+++ libquadmath/Makefile.in	2011-02-17 13:49:50.000000000 +0100
@@ -87,59 +87,57 @@  am__installdirs = "$(DESTDIR)$(toolexecl
 	"$(DESTDIR)$(libsubincludedir)"
 LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
 am__dirstamp = $(am__leading_dot)dirstamp
-@BUILD_LIBQUADMATH_TRUE@am_libquadmath_la_OBJECTS = gdtoa/hd_init.lo \
-@BUILD_LIBQUADMATH_TRUE@	gdtoa/smisc.lo gdtoa/sum.lo \
-@BUILD_LIBQUADMATH_TRUE@	gdtoa/gethex.lo gdtoa/hexnan.lo \
-@BUILD_LIBQUADMATH_TRUE@	gdtoa/strtodg.lo gdtoa/gmisc.lo \
-@BUILD_LIBQUADMATH_TRUE@	gdtoa/misc.lo gdtoa/strtopQ.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/acoshq.lo math/fmodq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/acosq.lo math/frexpq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/rem_pio2q.lo math/asinhq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/hypotq.lo math/remainderq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/asinq.lo math/rintq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/atan2q.lo math/isinfq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/roundq.lo math/atanhq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/isnanq.lo math/scalblnq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/atanq.lo math/j0q.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/scalbnq.lo math/cbrtq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/j1q.lo math/signbitq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/ceilq.lo math/jnq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/sincos_table.lo math/complex.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/ldexpq.lo math/sincosq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/copysignq.lo math/lgammaq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/sincosq_kernel.lo math/coshq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/llroundq.lo math/sinhq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/cosq.lo math/log10q.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/sinq.lo math/cosq_kernel.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/log1pq.lo math/sinq_kernel.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/erfq.lo math/logq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/sqrtq.lo math/expm1q.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/lroundq.lo math/tanhq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/expq.lo math/modfq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/tanq.lo math/fabsq.lo \
-@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 math/fmaq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/cacoshq.lo math/cacosq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/casinhq.lo math/casinq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/catanhq.lo math/catanq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/cimagq.lo math/conjq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/cprojq.lo math/crealq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/fdimq.lo math/fmaxq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/fminq.lo math/ilogbq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/llrintq.lo math/log2q.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/lrintq.lo math/nearbyintq.lo \
-@BUILD_LIBQUADMATH_TRUE@	math/remquoq.lo printf/addmul_1.lo \
-@BUILD_LIBQUADMATH_TRUE@	printf/add_n.lo printf/cmp.lo \
-@BUILD_LIBQUADMATH_TRUE@	printf/divrem.lo printf/flt1282mpn.lo \
+@BUILD_LIBQUADMATH_TRUE@am_libquadmath_la_OBJECTS = math/acoshq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/fmodq.lo math/acosq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/frexpq.lo math/rem_pio2q.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/asinhq.lo math/hypotq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/remainderq.lo math/asinq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/rintq.lo math/atan2q.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/isinfq.lo math/roundq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/atanhq.lo math/isnanq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/scalblnq.lo math/atanq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/j0q.lo math/scalbnq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/cbrtq.lo math/j1q.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/signbitq.lo math/ceilq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/jnq.lo math/sincos_table.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/complex.lo math/ldexpq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/sincosq.lo math/copysignq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/lgammaq.lo math/sincosq_kernel.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/coshq.lo math/llroundq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/sinhq.lo math/cosq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/log10q.lo math/sinq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/cosq_kernel.lo math/log1pq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/sinq_kernel.lo math/erfq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/logq.lo math/sqrtq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/expm1q.lo math/lroundq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/tanhq.lo math/expq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/modfq.lo math/tanq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/fabsq.lo math/nanq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/tgammaq.lo math/finiteq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/nextafterq.lo math/truncq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/floorq.lo math/powq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/fmaq.lo math/cacoshq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/cacosq.lo math/casinhq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/casinq.lo math/catanhq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/catanq.lo math/cimagq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/conjq.lo math/cprojq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/crealq.lo math/fdimq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/fmaxq.lo math/fminq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/ilogbq.lo math/llrintq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/log2q.lo math/lrintq.lo \
+@BUILD_LIBQUADMATH_TRUE@	math/nearbyintq.lo math/remquoq.lo \
+@BUILD_LIBQUADMATH_TRUE@	printf/addmul_1.lo printf/add_n.lo \
+@BUILD_LIBQUADMATH_TRUE@	printf/cmp.lo printf/divrem.lo \
+@BUILD_LIBQUADMATH_TRUE@	printf/flt1282mpn.lo \
 @BUILD_LIBQUADMATH_TRUE@	printf/fpioconst.lo printf/lshift.lo \
 @BUILD_LIBQUADMATH_TRUE@	printf/mul_1.lo printf/mul_n.lo \
 @BUILD_LIBQUADMATH_TRUE@	printf/mul.lo printf/printf_fphex.lo \
 @BUILD_LIBQUADMATH_TRUE@	printf/printf_fp.lo \
 @BUILD_LIBQUADMATH_TRUE@	printf/quadmath-printf.lo \
 @BUILD_LIBQUADMATH_TRUE@	printf/rshift.lo printf/submul_1.lo \
-@BUILD_LIBQUADMATH_TRUE@	printf/sub_n.lo
+@BUILD_LIBQUADMATH_TRUE@	printf/sub_n.lo strtod/strtoflt128.lo \
+@BUILD_LIBQUADMATH_TRUE@	strtod/mpn2flt128.lo \
+@BUILD_LIBQUADMATH_TRUE@	strtod/tens_in_limb.lo
 libquadmath_la_OBJECTS = $(am_libquadmath_la_OBJECTS)
 libquadmath_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -323,11 +321,6 @@  AUTOMAKE_OPTIONS = 1.8 foreign
 @BUILD_LIBQUADMATH_TRUE@nodist_libsubinclude_HEADERS = quadmath.h quadmath_weak.h
 @BUILD_LIBQUADMATH_TRUE@libsubincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
 @BUILD_LIBQUADMATH_TRUE@libquadmath_la_SOURCES = \
-@BUILD_LIBQUADMATH_TRUE@  gdtoa/arith.h gdtoa/gdtoa_fltrnds.h gdtoa/gd_qnan.h gdtoa/gdtoaimp.h \
-@BUILD_LIBQUADMATH_TRUE@  gdtoa/gdtoa.h quadmath-imp.h \
-@BUILD_LIBQUADMATH_TRUE@  gdtoa/hd_init.c gdtoa/smisc.c gdtoa/sum.c \
-@BUILD_LIBQUADMATH_TRUE@  gdtoa/gethex.c gdtoa/hexnan.c gdtoa/strtodg.c \
-@BUILD_LIBQUADMATH_TRUE@  gdtoa/gmisc.c gdtoa/misc.c gdtoa/strtopQ.c \
 @BUILD_LIBQUADMATH_TRUE@  math/acoshq.c math/fmodq.c math/acosq.c math/frexpq.c \
 @BUILD_LIBQUADMATH_TRUE@  math/rem_pio2q.c math/asinhq.c math/hypotq.c math/remainderq.c \
 @BUILD_LIBQUADMATH_TRUE@  math/asinq.c math/rintq.c math/atan2q.c math/isinfq.c \
@@ -348,7 +341,8 @@  AUTOMAKE_OPTIONS = 1.8 foreign
 @BUILD_LIBQUADMATH_TRUE@  printf/addmul_1.c printf/add_n.c printf/cmp.c printf/divrem.c \
 @BUILD_LIBQUADMATH_TRUE@  printf/flt1282mpn.c printf/fpioconst.c printf/lshift.c printf/mul_1.c \
 @BUILD_LIBQUADMATH_TRUE@  printf/mul_n.c printf/mul.c printf/printf_fphex.c printf/printf_fp.c \
-@BUILD_LIBQUADMATH_TRUE@  printf/quadmath-printf.c printf/rshift.c printf/submul_1.c printf/sub_n.c
+@BUILD_LIBQUADMATH_TRUE@  printf/quadmath-printf.c printf/rshift.c printf/submul_1.c printf/sub_n.c \
+@BUILD_LIBQUADMATH_TRUE@  strtod/strtoflt128.c strtod/mpn2flt128.c strtod/tens_in_limb.c
 
 
 # Work around what appears to be a GNU make bug handling MAKEFLAGS
@@ -501,24 +495,6 @@  clean-toolexeclibLTLIBRARIES:
 	  echo "rm -f \"$${dir}/so_locations\""; \
 	  rm -f "$${dir}/so_locations"; \
 	done
-gdtoa/$(am__dirstamp):
-	@$(MKDIR_P) gdtoa
-	@: > gdtoa/$(am__dirstamp)
-gdtoa/$(DEPDIR)/$(am__dirstamp):
-	@$(MKDIR_P) gdtoa/$(DEPDIR)
-	@: > gdtoa/$(DEPDIR)/$(am__dirstamp)
-gdtoa/hd_init.lo: gdtoa/$(am__dirstamp) \
-	gdtoa/$(DEPDIR)/$(am__dirstamp)
-gdtoa/smisc.lo: gdtoa/$(am__dirstamp) gdtoa/$(DEPDIR)/$(am__dirstamp)
-gdtoa/sum.lo: gdtoa/$(am__dirstamp) gdtoa/$(DEPDIR)/$(am__dirstamp)
-gdtoa/gethex.lo: gdtoa/$(am__dirstamp) gdtoa/$(DEPDIR)/$(am__dirstamp)
-gdtoa/hexnan.lo: gdtoa/$(am__dirstamp) gdtoa/$(DEPDIR)/$(am__dirstamp)
-gdtoa/strtodg.lo: gdtoa/$(am__dirstamp) \
-	gdtoa/$(DEPDIR)/$(am__dirstamp)
-gdtoa/gmisc.lo: gdtoa/$(am__dirstamp) gdtoa/$(DEPDIR)/$(am__dirstamp)
-gdtoa/misc.lo: gdtoa/$(am__dirstamp) gdtoa/$(DEPDIR)/$(am__dirstamp)
-gdtoa/strtopQ.lo: gdtoa/$(am__dirstamp) \
-	gdtoa/$(DEPDIR)/$(am__dirstamp)
 math/$(am__dirstamp):
 	@$(MKDIR_P) math
 	@: > math/$(am__dirstamp)
@@ -645,29 +621,23 @@  printf/submul_1.lo: printf/$(am__dirstam
 	printf/$(DEPDIR)/$(am__dirstamp)
 printf/sub_n.lo: printf/$(am__dirstamp) \
 	printf/$(DEPDIR)/$(am__dirstamp)
+strtod/$(am__dirstamp):
+	@$(MKDIR_P) strtod
+	@: > strtod/$(am__dirstamp)
+strtod/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) strtod/$(DEPDIR)
+	@: > strtod/$(DEPDIR)/$(am__dirstamp)
+strtod/strtoflt128.lo: strtod/$(am__dirstamp) \
+	strtod/$(DEPDIR)/$(am__dirstamp)
+strtod/mpn2flt128.lo: strtod/$(am__dirstamp) \
+	strtod/$(DEPDIR)/$(am__dirstamp)
+strtod/tens_in_limb.lo: strtod/$(am__dirstamp) \
+	strtod/$(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)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
-	-rm -f gdtoa/gethex.$(OBJEXT)
-	-rm -f gdtoa/gethex.lo
-	-rm -f gdtoa/gmisc.$(OBJEXT)
-	-rm -f gdtoa/gmisc.lo
-	-rm -f gdtoa/hd_init.$(OBJEXT)
-	-rm -f gdtoa/hd_init.lo
-	-rm -f gdtoa/hexnan.$(OBJEXT)
-	-rm -f gdtoa/hexnan.lo
-	-rm -f gdtoa/misc.$(OBJEXT)
-	-rm -f gdtoa/misc.lo
-	-rm -f gdtoa/smisc.$(OBJEXT)
-	-rm -f gdtoa/smisc.lo
-	-rm -f gdtoa/strtodg.$(OBJEXT)
-	-rm -f gdtoa/strtodg.lo
-	-rm -f gdtoa/strtopQ.$(OBJEXT)
-	-rm -f gdtoa/strtopQ.lo
-	-rm -f gdtoa/sum.$(OBJEXT)
-	-rm -f gdtoa/sum.lo
 	-rm -f math/acoshq.$(OBJEXT)
 	-rm -f math/acoshq.lo
 	-rm -f math/acosq.$(OBJEXT)
@@ -854,19 +824,16 @@  mostlyclean-compile:
 	-rm -f printf/sub_n.lo
 	-rm -f printf/submul_1.$(OBJEXT)
 	-rm -f printf/submul_1.lo
+	-rm -f strtod/mpn2flt128.$(OBJEXT)
+	-rm -f strtod/mpn2flt128.lo
+	-rm -f strtod/strtoflt128.$(OBJEXT)
+	-rm -f strtod/strtoflt128.lo
+	-rm -f strtod/tens_in_limb.$(OBJEXT)
+	-rm -f strtod/tens_in_limb.lo
 
 distclean-compile:
 	-rm -f *.tab.c
 
-@AMDEP_TRUE@@am__include@ @am__quote@gdtoa/$(DEPDIR)/gethex.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@gdtoa/$(DEPDIR)/gmisc.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@gdtoa/$(DEPDIR)/hd_init.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@gdtoa/$(DEPDIR)/hexnan.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@gdtoa/$(DEPDIR)/misc.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@gdtoa/$(DEPDIR)/smisc.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@gdtoa/$(DEPDIR)/strtodg.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@gdtoa/$(DEPDIR)/strtopQ.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@gdtoa/$(DEPDIR)/sum.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@math/$(DEPDIR)/acoshq.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@math/$(DEPDIR)/acosq.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@math/$(DEPDIR)/asinhq.Plo@am__quote@
@@ -960,6 +927,9 @@  distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@printf/$(DEPDIR)/rshift.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@printf/$(DEPDIR)/sub_n.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@printf/$(DEPDIR)/submul_1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@strtod/$(DEPDIR)/mpn2flt128.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@strtod/$(DEPDIR)/strtoflt128.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@strtod/$(DEPDIR)/tens_in_limb.Plo@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@@ -990,9 +960,9 @@  mostlyclean-libtool:
 
 clean-libtool:
 	-rm -rf .libs _libs
-	-rm -rf gdtoa/.libs gdtoa/_libs
 	-rm -rf math/.libs math/_libs
 	-rm -rf printf/.libs printf/_libs
+	-rm -rf strtod/.libs strtod/_libs
 
 distclean-libtool:
 	-rm -f libtool config.lt
@@ -1239,12 +1209,12 @@  clean-generic:
 distclean-generic:
 	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
 	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-	-rm -f gdtoa/$(DEPDIR)/$(am__dirstamp)
-	-rm -f gdtoa/$(am__dirstamp)
 	-rm -f math/$(DEPDIR)/$(am__dirstamp)
 	-rm -f math/$(am__dirstamp)
 	-rm -f printf/$(DEPDIR)/$(am__dirstamp)
 	-rm -f printf/$(am__dirstamp)
+	-rm -f strtod/$(DEPDIR)/$(am__dirstamp)
+	-rm -f strtod/$(am__dirstamp)
 
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
@@ -1257,7 +1227,7 @@  clean-am: clean-aminfo clean-generic cle
 
 distclean: distclean-am distclean-multi
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-	-rm -rf gdtoa/$(DEPDIR) math/$(DEPDIR) printf/$(DEPDIR)
+	-rm -rf math/$(DEPDIR) printf/$(DEPDIR) strtod/$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-hdr distclean-libtool distclean-tags
@@ -1381,7 +1351,7 @@  installcheck-am:
 maintainer-clean: maintainer-clean-am maintainer-clean-multi
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
 	-rm -rf $(top_srcdir)/autom4te.cache
-	-rm -rf gdtoa/$(DEPDIR) math/$(DEPDIR) printf/$(DEPDIR)
+	-rm -rf math/$(DEPDIR) printf/$(DEPDIR) strtod/$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-aminfo \
 	maintainer-clean-generic