diff --git a/ChangeLog b/ChangeLog index 9bf5fcc23e..20a400dfbc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +Fri Mar 17 13:28:04 1995 Ulrich Drepper + + * 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 * locale/C-ctype.c: New correct data generated by drepper. diff --git a/stdio/fpioconst.c b/stdio/fpioconst.c index 231cae34ed..8d0a8233b0 100644 --- a/stdio/fpioconst.c +++ b/stdio/fpioconst.c @@ -196,7 +196,8 @@ static const mp_limb _ten_p12[] = 0xae7be4a2, 0x271133ee, 0xbb0fd922, 0x25254932, 0xa60a9fc0, 0x104bcd64, 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 @@ -369,7 +370,8 @@ static const mp_limb _ten_p12[] = 0x271133eeae7be4a2, 0x25254932bb0fd922, 0x104bcd64a60a9fc0, 0x0000006230290145 }; -#define LAST_POW10 12 +/* This value is the index of the last array element. */ +#define _LAST_POW10 12 #else # 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. 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_p1, sizeof (_ten_p1) / sizeof (_ten_p0[1]), 7, 4 }, - { _ten_p2, sizeof (_ten_p2) / sizeof (_ten_p0[2]), 14, 10 }, - { _ten_p3, sizeof (_ten_p3) / sizeof (_ten_p0[3]), 27, 24 }, - { _ten_p4, sizeof (_ten_p4) / sizeof (_ten_p0[4]), 54, 50 }, - { _ten_p5, sizeof (_ten_p5) / sizeof (_ten_p0[5]), 107, 103 }, - { _ten_p6, sizeof (_ten_p6) / sizeof (_ten_p0[6]), 213, 210 }, - { _ten_p7, sizeof (_ten_p7) / sizeof (_ten_p0[7]), 426, 422 }, - { _ten_p8, sizeof (_ten_p8) / sizeof (_ten_p0[8]), 851, 848 }, - { _ten_p9, sizeof (_ten_p9) / sizeof (_ten_p0[9]), 1701, 1698 }, - { _ten_p10, sizeof (_ten_p10) / sizeof (_ten_p0[10]), 3402, 3399 }, - { _ten_p11, sizeof (_ten_p11) / sizeof (_ten_p0[11]), 6804, 6800 }, - { _ten_p12, sizeof (_ten_p12) / sizeof (_ten_p0[12]), 13607, 13604 } + { _ten_p1, sizeof (_ten_p1) / sizeof (_ten_p1[0]), 7, 4 }, + { _ten_p2, sizeof (_ten_p2) / sizeof (_ten_p2[0]), 14, 10 }, + { _ten_p3, sizeof (_ten_p3) / sizeof (_ten_p3[0]), 27, 24 }, + { _ten_p4, sizeof (_ten_p4) / sizeof (_ten_p4[0]), 54, 50 }, + { _ten_p5, sizeof (_ten_p5) / sizeof (_ten_p5[0]), 107, 103 }, + { _ten_p6, sizeof (_ten_p6) / sizeof (_ten_p6[0]), 213, 210 }, + { _ten_p7, sizeof (_ten_p7) / sizeof (_ten_p7[0]), 426, 422 }, + { _ten_p8, sizeof (_ten_p8) / sizeof (_ten_p8[0]), 851, 848 }, + { _ten_p9, sizeof (_ten_p9) / sizeof (_ten_p9[0]), 1701, 1698 }, + { _ten_p10, sizeof (_ten_p10) / sizeof (_ten_p10[0]), 3402, 3399 }, + { _ten_p11, sizeof (_ten_p11) / sizeof (_ten_p11[0]), 6804, 6800 }, + { _ten_p12, sizeof (_ten_p12) / sizeof (_ten_p12[0]), 13607, 13604 } }; -#if LDBL_MAX_10_EXP_LOG > LAST_POW10 -#error "Need to expand 10^(2^i) table for i up to" LDBL_MAX_10_EXP_LOG +#if LAST_POW10 > _LAST_POW10 +#error "Need to expand 10^(2^i) table for i up to" LAST_POW10 #endif diff --git a/stdlib/atof.c b/stdlib/atof.c index 79585464d1..a4b7eb92bd 100644 --- a/stdlib/atof.c +++ b/stdlib/atof.c @@ -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. 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, Cambridge, MA 02139, USA. */ -#include #include #undef atof @@ -24,7 +23,8 @@ Cambridge, MA 02139, USA. */ /* Convert a string to a 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); } diff --git a/stdlib/atoi.c b/stdlib/atoi.c index 9fe280cc3e..df053710f3 100644 --- a/stdlib/atoi.c +++ b/stdlib/atoi.c @@ -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. 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, Cambridge, MA 02139, USA. */ -#include #include #undef atoi @@ -24,7 +23,8 @@ Cambridge, MA 02139, USA. */ /* Convert a string to an 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); } diff --git a/stdlib/atol.c b/stdlib/atol.c index 75f599c107..dd68ce0b74 100644 --- a/stdlib/atol.c +++ b/stdlib/atol.c @@ -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. 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, Cambridge, MA 02139, USA. */ -#include #include #undef atol @@ -24,7 +23,8 @@ Cambridge, MA 02139, USA. */ /* Convert a string to a 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); } 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) diff --git a/stdlib/strtof.c b/stdlib/strtof.c index fbf92e671a..1d1c41f46a 100644 --- a/stdlib/strtof.c +++ b/stdlib/strtof.c @@ -6,6 +6,5 @@ #define STRTOF strtof #define MPN2FLOAT __mpn_construct_float #define FLOAT_HUGE_VAL HUGE_VALf -#define IMPLICIT_ONE 1 #include "strtod.c" diff --git a/stdlib/strtold.c b/stdlib/strtold.c index 6388cb904d..ec2b49b279 100644 --- a/stdlib/strtold.c +++ b/stdlib/strtold.c @@ -6,6 +6,5 @@ #define STRTOF strtold #define MPN2FLOAT __mpn_construct_long_double #define FLOAT_HUGE_VAL HUGE_VALl -#define IMPLICIT_ONE 0 /* XXX for i387 extended format */ #include "strtod.c"