about summary refs log tree commit diff
path: root/stdlib/strtod.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1995-03-17 17:15:40 +0000
committerUlrich Drepper <drepper@redhat.com>1995-03-17 17:15:40 +0000
commitb3fe1350509737887ab1f2ac8c4efb547af80b58 (patch)
tree958f30f27ae0126822842fc9480a3dfbcf5f96af /stdlib/strtod.c
parent61cd9516c24492da32637bb73ec26c06bb09e857 (diff)
downloadglibc-b3fe1350509737887ab1f2ac8c4efb547af80b58.tar.gz
glibc-b3fe1350509737887ab1f2ac8c4efb547af80b58.tar.xz
glibc-b3fe1350509737887ab1f2ac8c4efb547af80b58.zip
Fri Mar 17 13:28:04 1995 Ulrich Drepper <drepper@ipd.info.uni-karlsruhe.de>
	* sysdeps/ieee754/ldbl2mpn.c (__mpn_extract_long_double):
	Handle 80-bit denormalized numbers correct.

	* stdlib/strtod.c,stdlib/strtof.c,stdlib/strtold.c:
	[IMPLICIT_ONE,*_MAX_10_EXP_LOG]: not needed anymore.
	* stdlib/strtod.c (RETURN): parenthesis around return value.
	(round_and_return): correct handling of denormalized numbers.
	(__strtod_internal): don't check for grouping when not requested
	while returning 0.0.

	* stdio/fpioconst.[ch]: [LDBL_MAX_10_EXP_LOG]: don't use it.
	LAST_POW10 defines the maximal available exponent.

	* stdlib/{atof,atoi,atol}.c: use __strtoX_internal.
Diffstat (limited to 'stdlib/strtod.c')
-rw-r--r--stdlib/strtod.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/stdlib/strtod.c b/stdlib/strtod.c
index 8f71d136de..dcec00c5d7 100644
--- a/stdlib/strtod.c
+++ b/stdlib/strtod.c
@@ -27,7 +27,6 @@ Cambridge, MA 02139, USA.  */
 #define	STRTOF		strtod
 #define	MPN2FLOAT	__mpn_construct_double
 #define	FLOAT_HUGE_VAL	HUGE_VAL
-#define	IMPLICIT_ONE	1
 #endif
 /* End of configuration part.  */
 
@@ -54,7 +53,6 @@ Cambridge, MA 02139, USA.  */
 #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)
-#define	MAX_10_EXP_LOG	PASTE(FLT,_MAX_10_EXP_LOG)
 
 /* Extra macros required to get FLT expanded before the pasting.  */
 #define PASTE(a,b)	PASTE1(a,b)
@@ -102,7 +100,7 @@ static const mp_limb _tens_in_limb[MAX_DIG_PER_LIMB + 1] =
 #define	RETURN_LIMB_SIZE		howmany (MANT_DIG, BITS_PER_MP_LIMB)
 
 #define RETURN(val,end) \
-  do { if (endptr != 0) *endptr = (char *) (end); return (val); } while (0)
+    do { if (endptr != 0) *endptr = (char *) (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) \
@@ -120,21 +118,38 @@ static inline FLOAT
 round_and_return (mp_limb *retval, int exponent, int negative,
 		  mp_limb round_limb, mp_size_t round_bit, int more_bits)
 {
-  if (exponent < MIN_EXP - 2 + IMPLICIT_ONE)
+  if (exponent < MIN_EXP - 1)
     {
-      mp_size_t shift = MIN_EXP - 2 + IMPLICIT_ONE - exponent;
+      mp_size_t shift = MIN_EXP - 1 - exponent;
 
-      if (shift >= MANT_DIG)
+      if (shift > MANT_DIG)
 	{
 	  errno = EDOM;
 	  return 0.0;
 	}
 
       more_bits |= (round_limb & ((1 << round_bit) - 1)) != 0;
-      if (shift >= BITS_PER_MP_LIMB)
+      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 = BITS_PER_MP_LIMB - 1;
+	  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 & ((1 << round_bit) - 1)) != 0;
 
 	  (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB],
                                RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
@@ -167,7 +182,7 @@ round_and_return (mp_limb *retval, int exponent, int negative,
 	  retval[RETURN_LIMB_SIZE - 1] |= 1 << ((MANT_DIG - 1)
 						% BITS_PER_MP_LIMB);
 	}
-      else if (IMPLICIT_ONE && exponent == MIN_EXP - 2
+      else if (exponent == MIN_EXP - 2
 	       && (retval[RETURN_LIMB_SIZE - 1]
 		   & (1 << ((MANT_DIG - 1) % BITS_PER_MP_LIMB))) != 0)
 	  /* The number was denormalized but now normalized.  */
@@ -390,9 +405,13 @@ INTERNAL (STRTOF) (nptr, endptr, group)
      Return current read pointer.  */
   if (!isdigit (c) && c != decimal)
     {
-      tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping);
-      /* If TP is at the start of the digits, there was no correctly
-	 grouped prefix of the string; so no number found.  */
+      if (grouping)
+	/* Check the grouping of the digits.  */
+        tp = correctly_grouped_prefix (start_of_digits, cp, thousands,
+				       grouping);
+      else
+	tp = cp;
+
       RETURN (0.0, tp == start_of_digits ? nptr : tp);
     }
 
@@ -418,7 +437,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
       /* Check the grouping of the digits.  */
       tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping);
       if (cp != tp)
-       {
+        {
 	  /* Less than the entire string was correctly grouped.  */
 
 	  if (tp == start_of_digits)
@@ -539,7 +558,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
       assert (dig_no >= int_no);
     }
 
- number_parsed:
+  number_parsed:
 
   /* The whole string is parsed.  Store the address of the next character.  */
   if (endptr)
@@ -584,7 +603,6 @@ INTERNAL (STRTOF) (nptr, endptr, group)
 	  int expbit = 1;
 	  const struct mp_power *ttab = &_fpioconst_pow10[0];
 
-	  assert (exponent < (1 << (MAX_10_EXP_LOG + 1)));
 	  do
 	    {
 	      if ((exponent & expbit) != 0)