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.
This commit is contained in:
Ulrich Drepper 1995-03-17 17:15:40 +00:00
parent 61cd9516c2
commit b3fe135050
8 changed files with 80 additions and 45 deletions

View File

@ -1,3 +1,20 @@
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.
Thu Mar 16 00:04:41 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> Thu Mar 16 00:04:41 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* locale/C-ctype.c: New correct data generated by drepper. * locale/C-ctype.c: New correct data generated by drepper.

View File

@ -196,7 +196,8 @@ static const mp_limb _ten_p12[] =
0xae7be4a2, 0x271133ee, 0xbb0fd922, 0x25254932, 0xa60a9fc0, 0x104bcd64, 0xae7be4a2, 0x271133ee, 0xbb0fd922, 0x25254932, 0xa60a9fc0, 0x104bcd64,
0x30290145, 0x00000062 }; 0x30290145, 0x00000062 };
#define LAST_POW10 12 /* This value is the index of the last array element. */
#define _LAST_POW10 12
#elif BITS_PER_MP_LIMB == 64 #elif BITS_PER_MP_LIMB == 64
@ -369,7 +370,8 @@ static const mp_limb _ten_p12[] =
0x271133eeae7be4a2, 0x25254932bb0fd922, 0x104bcd64a60a9fc0, 0x271133eeae7be4a2, 0x25254932bb0fd922, 0x104bcd64a60a9fc0,
0x0000006230290145 }; 0x0000006230290145 };
#define LAST_POW10 12 /* This value is the index of the last array element. */
#define _LAST_POW10 12
#else #else
# error "mp_limb size " BITS_PER_MP_LIMB "not accounted for" # error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
@ -379,23 +381,23 @@ static const mp_limb _ten_p12[] =
/* Each of array variable above defines one mpn integer which is a power of 10. /* Each of array variable above defines one mpn integer which is a power of 10.
This table points to those variables, indexed by the exponent. */ This table points to those variables, indexed by the exponent. */
const struct mp_power _fpioconst_pow10[LDBL_MAX_10_EXP_LOG + 1] = const struct mp_power _fpioconst_pow10[_LAST_POW10 + 1] =
{ {
{ _ten_p0, sizeof (_ten_p0) / sizeof (_ten_p0[0]), 4, }, { _ten_p0, sizeof (_ten_p0) / sizeof (_ten_p0[0]), 4, },
{ _ten_p1, sizeof (_ten_p1) / sizeof (_ten_p0[1]), 7, 4 }, { _ten_p1, sizeof (_ten_p1) / sizeof (_ten_p1[0]), 7, 4 },
{ _ten_p2, sizeof (_ten_p2) / sizeof (_ten_p0[2]), 14, 10 }, { _ten_p2, sizeof (_ten_p2) / sizeof (_ten_p2[0]), 14, 10 },
{ _ten_p3, sizeof (_ten_p3) / sizeof (_ten_p0[3]), 27, 24 }, { _ten_p3, sizeof (_ten_p3) / sizeof (_ten_p3[0]), 27, 24 },
{ _ten_p4, sizeof (_ten_p4) / sizeof (_ten_p0[4]), 54, 50 }, { _ten_p4, sizeof (_ten_p4) / sizeof (_ten_p4[0]), 54, 50 },
{ _ten_p5, sizeof (_ten_p5) / sizeof (_ten_p0[5]), 107, 103 }, { _ten_p5, sizeof (_ten_p5) / sizeof (_ten_p5[0]), 107, 103 },
{ _ten_p6, sizeof (_ten_p6) / sizeof (_ten_p0[6]), 213, 210 }, { _ten_p6, sizeof (_ten_p6) / sizeof (_ten_p6[0]), 213, 210 },
{ _ten_p7, sizeof (_ten_p7) / sizeof (_ten_p0[7]), 426, 422 }, { _ten_p7, sizeof (_ten_p7) / sizeof (_ten_p7[0]), 426, 422 },
{ _ten_p8, sizeof (_ten_p8) / sizeof (_ten_p0[8]), 851, 848 }, { _ten_p8, sizeof (_ten_p8) / sizeof (_ten_p8[0]), 851, 848 },
{ _ten_p9, sizeof (_ten_p9) / sizeof (_ten_p0[9]), 1701, 1698 }, { _ten_p9, sizeof (_ten_p9) / sizeof (_ten_p9[0]), 1701, 1698 },
{ _ten_p10, sizeof (_ten_p10) / sizeof (_ten_p0[10]), 3402, 3399 }, { _ten_p10, sizeof (_ten_p10) / sizeof (_ten_p10[0]), 3402, 3399 },
{ _ten_p11, sizeof (_ten_p11) / sizeof (_ten_p0[11]), 6804, 6800 }, { _ten_p11, sizeof (_ten_p11) / sizeof (_ten_p11[0]), 6804, 6800 },
{ _ten_p12, sizeof (_ten_p12) / sizeof (_ten_p0[12]), 13607, 13604 } { _ten_p12, sizeof (_ten_p12) / sizeof (_ten_p12[0]), 13607, 13604 }
}; };
#if LDBL_MAX_10_EXP_LOG > LAST_POW10 #if LAST_POW10 > _LAST_POW10
#error "Need to expand 10^(2^i) table for i up to" LDBL_MAX_10_EXP_LOG #error "Need to expand 10^(2^i) table for i up to" LAST_POW10
#endif #endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991 Free Software Foundation, Inc. /* Copyright (C) 1991, 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -16,7 +16,6 @@ License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave, not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */ Cambridge, MA 02139, USA. */
#include <ansidecl.h>
#include <stdlib.h> #include <stdlib.h>
#undef atof #undef atof
@ -24,7 +23,8 @@ Cambridge, MA 02139, USA. */
/* Convert a string to a double. */ /* Convert a string to a double. */
double double
DEFUN(atof, (nptr), CONST char *nptr) atof (nptr)
const char *nptr;
{ {
return(strtod(nptr, (char **) NULL)); return __strtod_internal (nptr, (char **) NULL, 0);
} }

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991 Free Software Foundation, Inc. /* Copyright (C) 1991, 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -16,7 +16,6 @@ License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave, not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */ Cambridge, MA 02139, USA. */
#include <ansidecl.h>
#include <stdlib.h> #include <stdlib.h>
#undef atoi #undef atoi
@ -24,7 +23,8 @@ Cambridge, MA 02139, USA. */
/* Convert a string to an int. */ /* Convert a string to an int. */
int int
DEFUN(atoi, (nptr), CONST char *nptr) atoi (nptr)
const char *nptr;
{ {
return((int) strtol(nptr, (char **) NULL, 10)); return (int) __strtol_internal (nptr, (char **) NULL, 10, 0);
} }

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991 Free Software Foundation, Inc. /* Copyright (C) 1991, 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -16,7 +16,6 @@ License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave, not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */ Cambridge, MA 02139, USA. */
#include <ansidecl.h>
#include <stdlib.h> #include <stdlib.h>
#undef atol #undef atol
@ -24,7 +23,8 @@ Cambridge, MA 02139, USA. */
/* Convert a string to a long int. */ /* Convert a string to a long int. */
long int long int
DEFUN(atol, (nptr), CONST char *nptr) atol (nptr)
const char *nptr;
{ {
return(strtol(nptr, (char **) NULL, 10)); return __strtol_internal (nptr, (char **) NULL, 10, 0);
} }

View File

@ -27,7 +27,6 @@ Cambridge, MA 02139, USA. */
#define STRTOF strtod #define STRTOF strtod
#define MPN2FLOAT __mpn_construct_double #define MPN2FLOAT __mpn_construct_double
#define FLOAT_HUGE_VAL HUGE_VAL #define FLOAT_HUGE_VAL HUGE_VAL
#define IMPLICIT_ONE 1
#endif #endif
/* End of configuration part. */ /* End of configuration part. */
@ -54,7 +53,6 @@ Cambridge, MA 02139, USA. */
#define MIN_EXP PASTE(FLT,_MIN_EXP) #define MIN_EXP PASTE(FLT,_MIN_EXP)
#define MAX_10_EXP PASTE(FLT,_MAX_10_EXP) #define MAX_10_EXP PASTE(FLT,_MAX_10_EXP)
#define MIN_10_EXP PASTE(FLT,_MIN_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. */ /* Extra macros required to get FLT expanded before the pasting. */
#define PASTE(a,b) PASTE1(a,b) #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_LIMB_SIZE howmany (MANT_DIG, BITS_PER_MP_LIMB)
#define RETURN(val,end) \ #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. */ /* Maximum size necessary for mpn integers to hold floating point numbers. */
#define MPNSIZE (howmany (MAX_EXP + 2 * MANT_DIG, BITS_PER_MP_LIMB) \ #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, round_and_return (mp_limb *retval, int exponent, int negative,
mp_limb round_limb, mp_size_t round_bit, int more_bits) 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; errno = EDOM;
return 0.0; return 0.0;
} }
more_bits |= (round_limb & ((1 << round_bit) - 1)) != 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_limb = retval[(shift - 1) / BITS_PER_MP_LIMB];
round_bit = (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], (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB],
RETURN_LIMB_SIZE - (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) retval[RETURN_LIMB_SIZE - 1] |= 1 << ((MANT_DIG - 1)
% BITS_PER_MP_LIMB); % BITS_PER_MP_LIMB);
} }
else if (IMPLICIT_ONE && exponent == MIN_EXP - 2 else if (exponent == MIN_EXP - 2
&& (retval[RETURN_LIMB_SIZE - 1] && (retval[RETURN_LIMB_SIZE - 1]
& (1 << ((MANT_DIG - 1) % BITS_PER_MP_LIMB))) != 0) & (1 << ((MANT_DIG - 1) % BITS_PER_MP_LIMB))) != 0)
/* The number was denormalized but now normalized. */ /* The number was denormalized but now normalized. */
@ -390,9 +405,13 @@ INTERNAL (STRTOF) (nptr, endptr, group)
Return current read pointer. */ Return current read pointer. */
if (!isdigit (c) && c != decimal) if (!isdigit (c) && c != decimal)
{ {
tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping); if (grouping)
/* If TP is at the start of the digits, there was no correctly /* Check the grouping of the digits. */
grouped prefix of the string; so no number found. */ tp = correctly_grouped_prefix (start_of_digits, cp, thousands,
grouping);
else
tp = cp;
RETURN (0.0, tp == start_of_digits ? nptr : tp); RETURN (0.0, tp == start_of_digits ? nptr : tp);
} }
@ -418,7 +437,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
/* Check the grouping of the digits. */ /* Check the grouping of the digits. */
tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping); tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping);
if (cp != tp) if (cp != tp)
{ {
/* Less than the entire string was correctly grouped. */ /* Less than the entire string was correctly grouped. */
if (tp == start_of_digits) if (tp == start_of_digits)
@ -539,7 +558,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
assert (dig_no >= int_no); assert (dig_no >= int_no);
} }
number_parsed: number_parsed:
/* The whole string is parsed. Store the address of the next character. */ /* The whole string is parsed. Store the address of the next character. */
if (endptr) if (endptr)
@ -584,7 +603,6 @@ INTERNAL (STRTOF) (nptr, endptr, group)
int expbit = 1; int expbit = 1;
const struct mp_power *ttab = &_fpioconst_pow10[0]; const struct mp_power *ttab = &_fpioconst_pow10[0];
assert (exponent < (1 << (MAX_10_EXP_LOG + 1)));
do do
{ {
if ((exponent & expbit) != 0) if ((exponent & expbit) != 0)

View File

@ -6,6 +6,5 @@
#define STRTOF strtof #define STRTOF strtof
#define MPN2FLOAT __mpn_construct_float #define MPN2FLOAT __mpn_construct_float
#define FLOAT_HUGE_VAL HUGE_VALf #define FLOAT_HUGE_VAL HUGE_VALf
#define IMPLICIT_ONE 1
#include "strtod.c" #include "strtod.c"

View File

@ -6,6 +6,5 @@
#define STRTOF strtold #define STRTOF strtold
#define MPN2FLOAT __mpn_construct_long_double #define MPN2FLOAT __mpn_construct_long_double
#define FLOAT_HUGE_VAL HUGE_VALl #define FLOAT_HUGE_VAL HUGE_VALl
#define IMPLICIT_ONE 0 /* XXX for i387 extended format */
#include "strtod.c" #include "strtod.c"