mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-27 03:41:23 +08: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:
parent
30e7777245
commit
4933a099c2
@ -1,5 +1,12 @@
|
||||
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/Makefile (headers): Add search.h.
|
||||
* misc/insremque.c: Include search.h.
|
||||
|
@ -338,7 +338,7 @@ DEFUN(vfprintf, (s, format, args),
|
||||
|
||||
/* Check for type modifiers. */
|
||||
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++)
|
||||
{
|
||||
case 'h':
|
||||
|
151
stdlib/strtod.c
151
stdlib/strtod.c
@ -27,6 +27,7 @@ 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. */
|
||||
|
||||
@ -36,18 +37,19 @@ Cambridge, MA 02139, USA. */
|
||||
#include <localeinfo.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "../stdio/gmp.h"
|
||||
#include "../stdio/gmp-impl.h"
|
||||
#include "gmp.h"
|
||||
#include "gmp-impl.h"
|
||||
#include <gmp-mparam.h>
|
||||
#include "../stdio/longlong.h"
|
||||
#include "../stdio/fpioconst.h"
|
||||
#include "longlong.h"
|
||||
#include "fpioconst.h"
|
||||
|
||||
/* #define NDEBUG 1 */
|
||||
#define NDEBUG 1
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
/* 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)
|
||||
@ -75,15 +77,16 @@ extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative);
|
||||
|
||||
|
||||
/* Local data structure. */
|
||||
static const mp_limb _tens_in_limb[MAX_DIG_PER_LIMB] =
|
||||
{ 0, 10, 100,
|
||||
1000, 10000, 100000,
|
||||
1000000, 10000000, 100000000
|
||||
static const mp_limb _tens_in_limb[MAX_DIG_PER_LIMB + 1] =
|
||||
{ 0, 10, 100,
|
||||
1000, 10000, 100000,
|
||||
1000000, 10000000, 100000000,
|
||||
1000000000
|
||||
#if BITS_PER_MP_LIMB > 32
|
||||
, 1000000000, 10000000000, 100000000000,
|
||||
1000000000000, 10000000000000, 100000000000000,
|
||||
1000000000000000, 10000000000000000, 100000000000000000,
|
||||
1000000000000000000
|
||||
, 10000000000, 100000000000,
|
||||
1000000000000, 10000000000000, 100000000000000,
|
||||
1000000000000000, 10000000000000000, 100000000000000000,
|
||||
1000000000000000000, 10000000000000000000
|
||||
#endif
|
||||
#if BITS_PER_MP_LIMB > 64
|
||||
#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)
|
||||
|
||||
/* 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. */
|
||||
#define MPN_VAR(name) mp_limb name[MPNSIZE]; mp_size_t name##size
|
||||
/* Copy an mpn integer value. */
|
||||
@ -116,9 +119,9 @@ 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)
|
||||
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)
|
||||
{
|
||||
@ -131,44 +134,43 @@ round_and_return (mp_limb *retval, int exponent, int negative,
|
||||
{
|
||||
round_limb = retval[(shift - 1) / BITS_PER_MP_LIMB];
|
||||
round_bit = (shift - 1) % BITS_PER_MP_LIMB;
|
||||
#if RETURN_LIMB_SIZE <= 2
|
||||
assert (RETURN_LIMB_SIZE == 2);
|
||||
more_bits |= retval[0] != 0;
|
||||
retval[0] = retval[1];
|
||||
retval[1] = 0;
|
||||
#else
|
||||
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;
|
||||
|
||||
(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
|
||||
else if (shift > 0)
|
||||
{
|
||||
round_limb = retval[0];
|
||||
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;
|
||||
}
|
||||
|
||||
if ((round_limb & (1 << round_bit)) != 0 &&
|
||||
(more_bits || (retval[0] & 1) != 0 ||
|
||||
(round_limb & ((1 << round_bit) - 1)) != 0))
|
||||
if ((round_limb & (1 << round_bit)) != 0
|
||||
&& (more_bits || (retval[0] & 1) != 0
|
||||
|| (round_limb & ((1 << round_bit) - 1)) != 0))
|
||||
{
|
||||
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;
|
||||
(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)
|
||||
@ -305,7 +307,7 @@ STRTOF (nptr, endptr)
|
||||
/* Points at the character following the integer and fractional digits. */
|
||||
const char *expp;
|
||||
/* 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. */
|
||||
char c;
|
||||
|
||||
@ -440,15 +442,18 @@ STRTOF (nptr, endptr)
|
||||
/* We have the number 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. */
|
||||
if (c == decimal)
|
||||
{
|
||||
if (isdigit (cp[1]))
|
||||
{
|
||||
++cp;
|
||||
c = *++cp;
|
||||
do
|
||||
{
|
||||
if (c != '0' && lead_zero == -1)
|
||||
lead_zero = dig_no - int_no;
|
||||
++dig_no;
|
||||
c = *++cp;
|
||||
}
|
||||
@ -547,7 +552,7 @@ STRTOF (nptr, endptr)
|
||||
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;
|
||||
return 0.0;
|
||||
@ -607,20 +612,26 @@ STRTOF (nptr, endptr)
|
||||
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_idx - 1;
|
||||
int i;
|
||||
: least_bit - 1;
|
||||
|
||||
if (least_bit == 0)
|
||||
memcpy (retval, &num[least_idx],
|
||||
RETURN_LIMB_SIZE * sizeof (mp_limb));
|
||||
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. */
|
||||
for (i = 0; num[i] == 0; ++i)
|
||||
@ -686,14 +697,32 @@ STRTOF (nptr, endptr)
|
||||
|
||||
int expbit;
|
||||
int cnt;
|
||||
int neg_exp;
|
||||
int more_bits;
|
||||
mp_limb cy;
|
||||
mp_limb *psrc = den;
|
||||
mp_limb *pdest = num;
|
||||
int neg_exp = dig_no - int_no - exponent;
|
||||
const struct mp_power *ttab = &_fpioconst_pow10[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. */
|
||||
densize = 0;
|
||||
expbit = 1;
|
||||
@ -782,36 +811,38 @@ STRTOF (nptr, endptr)
|
||||
exponent -= cnt; \
|
||||
if (BITS_PER_MP_LIMB - cnt > MANT_DIG) \
|
||||
{ \
|
||||
used = cnt + MANT_DIG; \
|
||||
used = MANT_DIG + cnt; \
|
||||
retval[0] = quot >> (BITS_PER_MP_LIMB - used); \
|
||||
bits -= BITS_PER_MP_LIMB - used; \
|
||||
bits = MANT_DIG + 1; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* 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; \
|
||||
bits -= cnt; \
|
||||
bits = -cnt; \
|
||||
} \
|
||||
} \
|
||||
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); \
|
||||
else \
|
||||
{ \
|
||||
used = MANT_DIG - bits; \
|
||||
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
|
||||
|
||||
got_limb;
|
||||
got_limb;
|
||||
}
|
||||
while (bits <= MANT_DIG);
|
||||
|
||||
return round_and_return (retval, exponent - 1, negative,
|
||||
quot, BITS_PER_MP_LIMB - 1 - used,
|
||||
n != 0);
|
||||
more_bits || n != 0);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
@ -893,7 +924,7 @@ STRTOF (nptr, endptr)
|
||||
|
||||
return round_and_return (retval, exponent - 1, negative,
|
||||
quot, BITS_PER_MP_LIMB - 1 - used,
|
||||
n1 != 0 || n0 != 0);
|
||||
more_bits || n1 != 0 || n0 != 0);
|
||||
}
|
||||
default:
|
||||
{
|
||||
@ -907,7 +938,7 @@ STRTOF (nptr, endptr)
|
||||
|
||||
/* The division does not work if the upper limb of the two-limb
|
||||
numerator is greater than the denominator. */
|
||||
if (num[numsize - 1] > dX)
|
||||
if (__mpn_cmp (num, &den[densize - numsize], numsize) > 0)
|
||||
num[numsize++] = 0;
|
||||
|
||||
if (numsize < densize)
|
||||
@ -1017,11 +1048,11 @@ STRTOF (nptr, endptr)
|
||||
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,
|
||||
quot, BITS_PER_MP_LIMB - 1 - used,
|
||||
i >= 0);
|
||||
more_bits || i >= 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define STRTOF __strtof
|
||||
#define MPN2FLOAT __mpn_construct_float
|
||||
#define FLOAT_HUGE_VAL HUGE_VALf
|
||||
#define IMPLICIT_ONE 1
|
||||
|
||||
#include "strtod.c"
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#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"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user