More dtoa.c cleanup; remove the need for bc.dplen, bc.dp0 and bc.dp1.
This commit is contained in:
parent
02139d74ba
commit
d2a9940acb
104
Python/dtoa.c
104
Python/dtoa.c
|
@ -270,7 +270,7 @@ typedef union { double d; ULong L[2]; } U;
|
|||
typedef struct BCinfo BCinfo;
|
||||
struct
|
||||
BCinfo {
|
||||
int dp0, dp1, dplen, dsign, e0, nd, nd0, scale;
|
||||
int dsign, e0, nd, nd0, scale;
|
||||
};
|
||||
|
||||
#define FFFFFFFF 0xffffffffUL
|
||||
|
@ -437,7 +437,7 @@ multadd(Bigint *b, int m, int a) /* multiply by m and add a */
|
|||
NULL on failure. */
|
||||
|
||||
static Bigint *
|
||||
s2b(const char *s, int nd0, int nd, ULong y9, int dplen)
|
||||
s2b(const char *s, int nd0, int nd, ULong y9)
|
||||
{
|
||||
Bigint *b;
|
||||
int i, k;
|
||||
|
@ -451,18 +451,16 @@ s2b(const char *s, int nd0, int nd, ULong y9, int dplen)
|
|||
b->x[0] = y9;
|
||||
b->wds = 1;
|
||||
|
||||
i = 9;
|
||||
if (9 < nd0) {
|
||||
if (nd <= 9)
|
||||
return b;
|
||||
|
||||
s += 9;
|
||||
do {
|
||||
for (i = 9; i < nd0; i++) {
|
||||
b = multadd(b, 10, *s++ - '0');
|
||||
if (b == NULL)
|
||||
return NULL;
|
||||
} while(++i < nd0);
|
||||
s += dplen;
|
||||
}
|
||||
else
|
||||
s += dplen + 9;
|
||||
s++;
|
||||
for(; i < nd; i++) {
|
||||
b = multadd(b, 10, *s++ - '0');
|
||||
if (b == NULL)
|
||||
|
@ -1180,26 +1178,14 @@ sulp(U *x, BCinfo *bc)
|
|||
bc is a struct containing information gathered during the parsing and
|
||||
estimation steps of _Py_dg_strtod. Description of fields follows:
|
||||
|
||||
bc->dp0 gives the position of the decimal point in the input string
|
||||
(if any), relative to the start of s0. If there's no decimal
|
||||
point, it points to one past the last significant digit.
|
||||
|
||||
bc->dp1 gives the position immediately following the decimal point in
|
||||
the input string, relative to the start of s0. If there's no
|
||||
decimal point, it points to one past the last significant digit.
|
||||
|
||||
bc->dplen gives the length of the decimal separator. In the current
|
||||
implementation, which only allows '.' as a decimal separator, it's
|
||||
1 if a separator is present in the significant digits of s0, and 0
|
||||
otherwise.
|
||||
|
||||
bc->dsign is 1 if rv < decimal value, 0 if rv >= decimal value. In
|
||||
normal use, it should almost always be 1 when bigcomp is entered.
|
||||
|
||||
bc->e0 gives the exponent of the input value, such that dv = (integer
|
||||
given by the bd->nd digits of s0) * 10**e0
|
||||
|
||||
bc->nd gives the total number of significant digits of s0.
|
||||
bc->nd gives the total number of significant digits of s0. It will
|
||||
be at least 1.
|
||||
|
||||
bc->nd0 gives the number of significant digits of s0 before the
|
||||
decimal separator. If there's no decimal separator, bc->nd0 ==
|
||||
|
@ -1218,13 +1204,14 @@ static int
|
|||
bigcomp(U *rv, const char *s0, BCinfo *bc)
|
||||
{
|
||||
Bigint *b, *d;
|
||||
int b2, bbits, d2, dd, dig, i, j, nd, nd0, p2, p5;
|
||||
int b2, bbits, d2, dd, i, nd, nd0, p2, p5;
|
||||
|
||||
dd = 0; /* silence compiler warning about possibly unused variable */
|
||||
nd = bc->nd;
|
||||
nd0 = bc->nd0;
|
||||
p5 = nd + bc->e0;
|
||||
if (rv->d == 0.) { /* special case: value near underflow-to-zero */
|
||||
/* threshold was rounded to zero */
|
||||
if (rv->d == 0.) {
|
||||
/* special case because d2b doesn't handle 0.0 */
|
||||
b = i2b(0);
|
||||
if (b == NULL)
|
||||
return -1;
|
||||
|
@ -1243,9 +1230,8 @@ bigcomp(U *rv, const char *s0, BCinfo *bc)
|
|||
that b << i has at most P significant bits and p2 - i >= Emin - P +
|
||||
1. */
|
||||
i = P - bbits;
|
||||
j = p2 - (Emin - P + 1);
|
||||
if (i > j)
|
||||
i = j;
|
||||
if (i > p2 - (Emin - P + 1))
|
||||
i = p2 - (Emin - P + 1);
|
||||
/* increment i so that we shift b by an extra bit; then or-ing a 1 into
|
||||
the lsb of b gives us rv/2^(bc->scale) + 0.5ulp. */
|
||||
b = lshift(b, ++i);
|
||||
|
@ -1300,55 +1286,43 @@ bigcomp(U *rv, const char *s0, BCinfo *bc)
|
|||
}
|
||||
}
|
||||
|
||||
/* Now 10*b/d = exactly half-way between the two floating-point values
|
||||
on either side of the input string. If b >= d, round down. */
|
||||
/* if b >= d, round down */
|
||||
if (cmp(b, d) >= 0) {
|
||||
dd = -1;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
/* Compute first digit of 10*b/d. */
|
||||
b = multadd(b, 10, 0);
|
||||
if (b == NULL) {
|
||||
Bfree(d);
|
||||
return -1;
|
||||
}
|
||||
dig = quorem(b, d);
|
||||
assert(dig < 10);
|
||||
|
||||
/* Compare b/d with s0 */
|
||||
|
||||
assert(nd > 0);
|
||||
dd = 9999; /* silence gcc compiler warning */
|
||||
for(i = 0; i < nd0; ) {
|
||||
if ((dd = s0[i++] - '0' - dig))
|
||||
for(i = 0; i < nd0; i++) {
|
||||
b = multadd(b, 10, 0);
|
||||
if (b == NULL) {
|
||||
Bfree(d);
|
||||
return -1;
|
||||
}
|
||||
dd = *s0++ - '0' - quorem(b, d);
|
||||
if (dd)
|
||||
goto ret;
|
||||
if (!b->x[0] && b->wds == 1) {
|
||||
if (i < nd)
|
||||
dd = 1;
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
s0++;
|
||||
for(; i < nd; i++) {
|
||||
b = multadd(b, 10, 0);
|
||||
if (b == NULL) {
|
||||
Bfree(d);
|
||||
return -1;
|
||||
}
|
||||
dig = quorem(b,d);
|
||||
}
|
||||
for(j = bc->dp1; i++ < nd;) {
|
||||
if ((dd = s0[j++] - '0' - dig))
|
||||
dd = *s0++ - '0' - quorem(b, d);
|
||||
if (dd)
|
||||
goto ret;
|
||||
if (!b->x[0] && b->wds == 1) {
|
||||
if (i < nd)
|
||||
dd = 1;
|
||||
goto ret;
|
||||
}
|
||||
b = multadd(b, 10, 0);
|
||||
if (b == NULL) {
|
||||
Bfree(d);
|
||||
return -1;
|
||||
}
|
||||
dig = quorem(b,d);
|
||||
}
|
||||
if (b->x[0] || b->wds > 1)
|
||||
dd = -1;
|
||||
|
@ -1369,7 +1343,7 @@ bigcomp(U *rv, const char *s0, BCinfo *bc)
|
|||
double
|
||||
_Py_dg_strtod(const char *s00, char **se)
|
||||
{
|
||||
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1, error;
|
||||
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dp0, dp1, dplen, e, e1, error;
|
||||
int esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
|
||||
const char *s, *s0, *s1;
|
||||
double aadj, aadj1;
|
||||
|
@ -1378,7 +1352,7 @@ _Py_dg_strtod(const char *s00, char **se)
|
|||
BCinfo bc;
|
||||
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
|
||||
|
||||
sign = nz0 = nz = bc.dplen = 0;
|
||||
sign = nz0 = nz = dplen = 0;
|
||||
dval(&rv) = 0.;
|
||||
for(s = s00;;s++) switch(*s) {
|
||||
case '-':
|
||||
|
@ -1417,11 +1391,11 @@ _Py_dg_strtod(const char *s00, char **se)
|
|||
else if (nd < 16)
|
||||
z = 10*z + c - '0';
|
||||
nd0 = nd;
|
||||
bc.dp0 = bc.dp1 = s - s0;
|
||||
dp0 = dp1 = s - s0;
|
||||
if (c == '.') {
|
||||
c = *++s;
|
||||
bc.dp1 = s - s0;
|
||||
bc.dplen = bc.dp1 - bc.dp0;
|
||||
dp1 = s - s0;
|
||||
dplen = 1;
|
||||
if (!nd) {
|
||||
for(; c == '0'; c = *++s)
|
||||
nz++;
|
||||
|
@ -1624,10 +1598,10 @@ _Py_dg_strtod(const char *s00, char **se)
|
|||
/* in IEEE arithmetic. */
|
||||
i = j = 18;
|
||||
if (i > nd0)
|
||||
j += bc.dplen;
|
||||
j += dplen;
|
||||
for(;;) {
|
||||
if (--j <= bc.dp1 && j >= bc.dp0)
|
||||
j = bc.dp0 - 1;
|
||||
if (--j <= dp1 && j >= dp0)
|
||||
j = dp0 - 1;
|
||||
if (s0[j] != '0')
|
||||
break;
|
||||
--i;
|
||||
|
@ -1640,11 +1614,11 @@ _Py_dg_strtod(const char *s00, char **se)
|
|||
y = 0;
|
||||
for(i = 0; i < nd0; ++i)
|
||||
y = 10*y + s0[i] - '0';
|
||||
for(j = bc.dp1; i < nd; ++i)
|
||||
for(j = dp1; i < nd; ++i)
|
||||
y = 10*y + s0[j++] - '0';
|
||||
}
|
||||
}
|
||||
bd0 = s2b(s0, nd0, nd, y, bc.dplen);
|
||||
bd0 = s2b(s0, nd0, nd, y);
|
||||
if (bd0 == NULL)
|
||||
goto failed_malloc;
|
||||
|
||||
|
|
Loading…
Reference in New Issue