1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-28 00:21:52 +03:00

* stdlib/strtod.c: Fixes from drepper.

[IMPLICIT_ONE]: New macro, one for IEEE754 formats.
	* stdlib/strtold.c [IMPLICIT_ONE]: New macro, 0.
	* stdlib/strtof.c [IMPLICIT_ONE]: New macro, 1.

	* stdio/vfprintf.c: Correctly notice Z modifier.
This commit is contained in:
Roland McGrath
1995-03-02 10:00:12 +00:00
parent 30e7777245
commit 4933a099c2
5 changed files with 101 additions and 61 deletions

View File

@ -1,5 +1,12 @@
Wed Mar 1 00:57:47 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> Wed Mar 1 00:57:47 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* stdlib/strtod.c: Fixes from drepper.
[IMPLICIT_ONE]: New macro, one for IEEE754 formats.
* stdlib/strtold.c [IMPLICIT_ONE]: New macro, 0.
* stdlib/strtof.c [IMPLICIT_ONE]: New macro, 1.
* stdio/vfprintf.c: Correctly notice Z modifier.
* misc/search.h: New file. * misc/search.h: New file.
* misc/Makefile (headers): Add search.h. * misc/Makefile (headers): Add search.h.
* misc/insremque.c: Include search.h. * misc/insremque.c: Include search.h.

View File

@ -338,7 +338,7 @@ DEFUN(vfprintf, (s, format, args),
/* Check for type modifiers. */ /* Check for type modifiers. */
is_short = is_long = is_long_double = 0; is_short = is_long = is_long_double = 0;
while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'q') while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'q' || *f == 'Z')
switch (*f++) switch (*f++)
{ {
case 'h': case 'h':

View File

@ -27,6 +27,7 @@ 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. */
@ -36,18 +37,19 @@ Cambridge, MA 02139, USA. */
#include <localeinfo.h> #include <localeinfo.h>
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include "../stdio/gmp.h" #include "gmp.h"
#include "../stdio/gmp-impl.h" #include "gmp-impl.h"
#include <gmp-mparam.h> #include <gmp-mparam.h>
#include "../stdio/longlong.h" #include "longlong.h"
#include "../stdio/fpioconst.h" #include "fpioconst.h"
/* #define NDEBUG 1 */ #define NDEBUG 1
#include <assert.h> #include <assert.h>
/* Constants we need from float.h; select the set for the FLOAT precision. */ /* Constants we need from float.h; select the set for the FLOAT precision. */
#define MANT_DIG PASTE(FLT,_MANT_DIG) #define MANT_DIG PASTE(FLT,_MANT_DIG)
#define DIG PASTE(FLT,_DIG)
#define MAX_EXP PASTE(FLT,_MAX_EXP) #define MAX_EXP PASTE(FLT,_MAX_EXP)
#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)
@ -75,15 +77,16 @@ extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative);
/* Local data structure. */ /* Local data structure. */
static const mp_limb _tens_in_limb[MAX_DIG_PER_LIMB] = static const mp_limb _tens_in_limb[MAX_DIG_PER_LIMB + 1] =
{ 0, 10, 100, { 0, 10, 100,
1000, 10000, 100000, 1000, 10000, 100000,
1000000, 10000000, 100000000 1000000, 10000000, 100000000,
1000000000
#if BITS_PER_MP_LIMB > 32 #if BITS_PER_MP_LIMB > 32
, 1000000000, 10000000000, 100000000000, , 10000000000, 100000000000,
1000000000000, 10000000000000, 100000000000000, 1000000000000, 10000000000000, 100000000000000,
1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000, 10000000000000000, 100000000000000000,
1000000000000000000 1000000000000000000, 10000000000000000000
#endif #endif
#if BITS_PER_MP_LIMB > 64 #if BITS_PER_MP_LIMB > 64
#error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB #error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB
@ -102,7 +105,7 @@ static const mp_limb _tens_in_limb[MAX_DIG_PER_LIMB] =
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 + MANT_DIG, BITS_PER_MP_LIMB) + 1) #define MPNSIZE (howmany (MAX_EXP + 2 * MANT_DIG, BITS_PER_MP_LIMB) + 2)
/* Declare an mpn integer variable that big. */ /* Declare an mpn integer variable that big. */
#define MPN_VAR(name) mp_limb name[MPNSIZE]; mp_size_t name##size #define MPN_VAR(name) mp_limb name[MPNSIZE]; mp_size_t name##size
/* Copy an mpn integer value. */ /* Copy an mpn integer value. */
@ -116,9 +119,9 @@ 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) if (exponent < MIN_EXP - 2 + IMPLICIT_ONE)
{ {
mp_size_t shift = MIN_EXP - 1 - exponent; mp_size_t shift = MIN_EXP - 2 + IMPLICIT_ONE - exponent;
if (shift >= MANT_DIG) if (shift >= MANT_DIG)
{ {
@ -131,44 +134,43 @@ round_and_return (mp_limb *retval, int exponent, int negative,
{ {
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;
#if RETURN_LIMB_SIZE <= 2
assert (RETURN_LIMB_SIZE == 2); (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB],
more_bits |= retval[0] != 0; RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
retval[0] = retval[1]; shift % BITS_PER_MP_LIMB);
retval[1] = 0; MPN_ZERO (&retval[RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)],
#else shift / BITS_PER_MP_LIMB);
int disp = shift / BITS_PER_MP_LIMB;
int i = 0;
while (retval[i] == 0 && i < disp)
++i;
more_bits |= i < disp;
for (i = disp; i < RETURN_LIMB_SIZE; ++i)
retval[i - disp] = retval[i];
MPN_ZERO (&retval[RETURN_LIMB_SIZE - disp], disp);
#endif
shift %= BITS_PER_MP_LIMB;
} }
else else if (shift > 0)
{ {
round_limb = retval[0]; round_limb = retval[0];
round_bit = shift - 1; round_bit = shift - 1;
(void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift);
} }
(void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift);
exponent = MIN_EXP - 2; exponent = MIN_EXP - 2;
} }
if ((round_limb & (1 << round_bit)) != 0 && if ((round_limb & (1 << round_bit)) != 0
(more_bits || (retval[0] & 1) != 0 || && (more_bits || (retval[0] & 1) != 0
(round_limb & ((1 << round_bit) - 1)) != 0)) || (round_limb & ((1 << round_bit) - 1)) != 0))
{ {
mp_limb cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1); mp_limb cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1);
if (cy || (retval[RETURN_LIMB_SIZE - 1]
& (1 << (MANT_DIG % BITS_PER_MP_LIMB))) != 0) if (((MANT_DIG % BITS_PER_MP_LIMB) == 0 && cy) ||
((MANT_DIG % BITS_PER_MP_LIMB) != 0 &&
(retval[RETURN_LIMB_SIZE - 1]
& (1 << (MANT_DIG % BITS_PER_MP_LIMB))) != 0))
{ {
++exponent; ++exponent;
(void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, 1); (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, 1);
retval[RETURN_LIMB_SIZE - 1] |= 1 << (MANT_DIG % BITS_PER_MP_LIMB); retval[RETURN_LIMB_SIZE - 1] |= 1 << ((MANT_DIG - 1)
% BITS_PER_MP_LIMB);
} }
else if (IMPLICIT_ONE && 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. */
exponent = MIN_EXP - 1;
} }
if (exponent > MAX_EXP) if (exponent > MAX_EXP)
@ -305,7 +307,7 @@ STRTOF (nptr, endptr)
/* Points at the character following the integer and fractional digits. */ /* Points at the character following the integer and fractional digits. */
const char *expp; const char *expp;
/* Total number of digit and number of digits in integer part. */ /* Total number of digit and number of digits in integer part. */
int dig_no, int_no; int dig_no, int_no, lead_zero;
/* Contains the last character read. */ /* Contains the last character read. */
char c; char c;
@ -440,15 +442,18 @@ STRTOF (nptr, endptr)
/* We have the number digits in the integer part. Whether these are all or /* We have the number digits in the integer part. Whether these are all or
any is really a fractional digit will be decided later. */ any is really a fractional digit will be decided later. */
int_no = dig_no; int_no = dig_no;
lead_zero = int_no == 0 ? -1 : 0;
/* Read the fractional digits. */ /* Read the fractional digits. */
if (c == decimal) if (c == decimal)
{ {
if (isdigit (cp[1])) if (isdigit (cp[1]))
{ {
++cp; c = *++cp;
do do
{ {
if (c != '0' && lead_zero == -1)
lead_zero = dig_no - int_no;
++dig_no; ++dig_no;
c = *++cp; c = *++cp;
} }
@ -547,7 +552,7 @@ STRTOF (nptr, endptr)
return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
} }
if (int_no - dig_no + exponent < MIN_10_EXP - MANT_DIG) if (exponent - MAX(0, lead_zero) < MIN_10_EXP - (DIG + 1))
{ {
errno = ERANGE; errno = ERANGE;
return 0.0; return 0.0;
@ -607,20 +612,26 @@ STRTOF (nptr, endptr)
to determine the result. */ to determine the result. */
if (bits > MANT_DIG) if (bits > MANT_DIG)
{ {
int i;
const mp_size_t least_idx = (bits - MANT_DIG) / BITS_PER_MP_LIMB; 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 least_bit = (bits - MANT_DIG) % BITS_PER_MP_LIMB;
const mp_size_t round_idx = least_bit == 0 ? least_idx - 1 const mp_size_t round_idx = least_bit == 0 ? least_idx - 1
: least_idx; : least_idx;
const mp_size_t round_bit = least_bit == 0 ? BITS_PER_MP_LIMB - 1 const mp_size_t round_bit = least_bit == 0 ? BITS_PER_MP_LIMB - 1
: least_idx - 1; : least_bit - 1;
int i;
if (least_bit == 0) if (least_bit == 0)
memcpy (retval, &num[least_idx], memcpy (retval, &num[least_idx],
RETURN_LIMB_SIZE * sizeof (mp_limb)); RETURN_LIMB_SIZE * sizeof (mp_limb));
else else
(void) __mpn_rshift (retval, &num[least_idx], {
numsize - least_idx + 1, least_bit); 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. */ /* Check whether any limb beside the ones in RETVAL are non-zero. */
for (i = 0; num[i] == 0; ++i) for (i = 0; num[i] == 0; ++i)
@ -686,14 +697,32 @@ STRTOF (nptr, endptr)
int expbit; int expbit;
int cnt; int cnt;
int neg_exp;
int more_bits;
mp_limb cy; mp_limb cy;
mp_limb *psrc = den; mp_limb *psrc = den;
mp_limb *pdest = num; mp_limb *pdest = num;
int neg_exp = dig_no - int_no - exponent;
const struct mp_power *ttab = &_fpioconst_pow10[0]; const struct mp_power *ttab = &_fpioconst_pow10[0];
assert (dig_no > int_no && exponent <= 0); assert (dig_no > int_no && exponent <= 0);
/* For the fractional part we need not process too much 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. (One added as a safety margin.) */
if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 1)
{
dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 1;
more_bits = 1;
}
else
more_bits = 0;
neg_exp = dig_no - int_no - exponent;
/* Construct the denominator. */ /* Construct the denominator. */
densize = 0; densize = 0;
expbit = 1; expbit = 1;
@ -782,36 +811,38 @@ STRTOF (nptr, endptr)
exponent -= cnt; \ exponent -= cnt; \
if (BITS_PER_MP_LIMB - cnt > MANT_DIG) \ if (BITS_PER_MP_LIMB - cnt > MANT_DIG) \
{ \ { \
used = cnt + MANT_DIG; \ used = MANT_DIG + cnt; \
retval[0] = quot >> (BITS_PER_MP_LIMB - used); \ retval[0] = quot >> (BITS_PER_MP_LIMB - used); \
bits -= BITS_PER_MP_LIMB - used; \ bits = MANT_DIG + 1; \
} \ } \
else \ else \
{ \ { \
/* Note that we only clear the second element. */ \ /* Note that we only clear the second element. */ \
retval[1] = 0; \ /* The conditional is determined at compile time. */ \
if (RETURN_LIMB_SIZE > 1) \
retval[1] = 0; \
retval[0] = quot; \ retval[0] = quot; \
bits -= cnt; \ bits = -cnt; \
} \ } \
} \ } \
else if (bits + BITS_PER_MP_LIMB <= MANT_DIG) \ else if (bits + BITS_PER_MP_LIMB <= MANT_DIG) \
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, BITS_PER_MP_LIMB, \ __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, BITS_PER_MP_LIMB, \
quot); \ quot); \
else \ else \
{ \ { \
used = MANT_DIG - bits; \ used = MANT_DIG - bits; \
if (used > 0) \ if (used > 0) \
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, quot); \ __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, quot); \
} \ } \
bits += BITS_PER_MP_LIMB bits += BITS_PER_MP_LIMB
got_limb; got_limb;
} }
while (bits <= MANT_DIG); while (bits <= MANT_DIG);
return round_and_return (retval, exponent - 1, negative, return round_and_return (retval, exponent - 1, negative,
quot, BITS_PER_MP_LIMB - 1 - used, quot, BITS_PER_MP_LIMB - 1 - used,
n != 0); more_bits || n != 0);
} }
case 2: case 2:
{ {
@ -893,7 +924,7 @@ STRTOF (nptr, endptr)
return round_and_return (retval, exponent - 1, negative, return round_and_return (retval, exponent - 1, negative,
quot, BITS_PER_MP_LIMB - 1 - used, quot, BITS_PER_MP_LIMB - 1 - used,
n1 != 0 || n0 != 0); more_bits || n1 != 0 || n0 != 0);
} }
default: default:
{ {
@ -907,7 +938,7 @@ STRTOF (nptr, endptr)
/* The division does not work if the upper limb of the two-limb /* The division does not work if the upper limb of the two-limb
numerator is greater than the denominator. */ numerator is greater than the denominator. */
if (num[numsize - 1] > dX) if (__mpn_cmp (num, &den[densize - numsize], numsize) > 0)
num[numsize++] = 0; num[numsize++] = 0;
if (numsize < densize) if (numsize < densize)
@ -1017,11 +1048,11 @@ STRTOF (nptr, endptr)
got_limb; got_limb;
} }
for (i = densize - 1; num[i] != 0 && i >= 0; --i) for (i = densize; num[i] == 0 && i >= 0; --i)
; ;
return round_and_return (retval, exponent - 1, negative, return round_and_return (retval, exponent - 1, negative,
quot, BITS_PER_MP_LIMB - 1 - used, quot, BITS_PER_MP_LIMB - 1 - used,
i >= 0); more_bits || i >= 0);
} }
} }
} }

View File

@ -6,6 +6,7 @@
#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,7 @@
#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"