More dtoa.c cleanup; remove the need for bc.dplen, bc.dp0 and bc.dp1.
This commit is contained in:
parent
02139d74ba
commit
d2a9940acb
120
Python/dtoa.c
120
Python/dtoa.c
|
@ -270,7 +270,7 @@ typedef union { double d; ULong L[2]; } U;
|
||||||
typedef struct BCinfo BCinfo;
|
typedef struct BCinfo BCinfo;
|
||||||
struct
|
struct
|
||||||
BCinfo {
|
BCinfo {
|
||||||
int dp0, dp1, dplen, dsign, e0, nd, nd0, scale;
|
int dsign, e0, nd, nd0, scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FFFFFFFF 0xffffffffUL
|
#define FFFFFFFF 0xffffffffUL
|
||||||
|
@ -437,7 +437,7 @@ multadd(Bigint *b, int m, int a) /* multiply by m and add a */
|
||||||
NULL on failure. */
|
NULL on failure. */
|
||||||
|
|
||||||
static Bigint *
|
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;
|
Bigint *b;
|
||||||
int i, k;
|
int i, k;
|
||||||
|
@ -451,18 +451,16 @@ s2b(const char *s, int nd0, int nd, ULong y9, int dplen)
|
||||||
b->x[0] = y9;
|
b->x[0] = y9;
|
||||||
b->wds = 1;
|
b->wds = 1;
|
||||||
|
|
||||||
i = 9;
|
if (nd <= 9)
|
||||||
if (9 < nd0) {
|
return b;
|
||||||
s += 9;
|
|
||||||
do {
|
s += 9;
|
||||||
b = multadd(b, 10, *s++ - '0');
|
for (i = 9; i < nd0; i++) {
|
||||||
if (b == NULL)
|
b = multadd(b, 10, *s++ - '0');
|
||||||
return NULL;
|
if (b == NULL)
|
||||||
} while(++i < nd0);
|
return NULL;
|
||||||
s += dplen;
|
|
||||||
}
|
}
|
||||||
else
|
s++;
|
||||||
s += dplen + 9;
|
|
||||||
for(; i < nd; i++) {
|
for(; i < nd; i++) {
|
||||||
b = multadd(b, 10, *s++ - '0');
|
b = multadd(b, 10, *s++ - '0');
|
||||||
if (b == NULL)
|
if (b == NULL)
|
||||||
|
@ -1180,26 +1178,14 @@ sulp(U *x, BCinfo *bc)
|
||||||
bc is a struct containing information gathered during the parsing and
|
bc is a struct containing information gathered during the parsing and
|
||||||
estimation steps of _Py_dg_strtod. Description of fields follows:
|
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
|
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.
|
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
|
bc->e0 gives the exponent of the input value, such that dv = (integer
|
||||||
given by the bd->nd digits of s0) * 10**e0
|
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
|
bc->nd0 gives the number of significant digits of s0 before the
|
||||||
decimal separator. If there's no decimal separator, bc->nd0 ==
|
decimal separator. If there's no decimal separator, bc->nd0 ==
|
||||||
|
@ -1218,13 +1204,14 @@ static int
|
||||||
bigcomp(U *rv, const char *s0, BCinfo *bc)
|
bigcomp(U *rv, const char *s0, BCinfo *bc)
|
||||||
{
|
{
|
||||||
Bigint *b, *d;
|
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;
|
nd = bc->nd;
|
||||||
nd0 = bc->nd0;
|
nd0 = bc->nd0;
|
||||||
p5 = nd + bc->e0;
|
p5 = nd + bc->e0;
|
||||||
if (rv->d == 0.) { /* special case: value near underflow-to-zero */
|
if (rv->d == 0.) {
|
||||||
/* threshold was rounded to zero */
|
/* special case because d2b doesn't handle 0.0 */
|
||||||
b = i2b(0);
|
b = i2b(0);
|
||||||
if (b == NULL)
|
if (b == NULL)
|
||||||
return -1;
|
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 +
|
that b << i has at most P significant bits and p2 - i >= Emin - P +
|
||||||
1. */
|
1. */
|
||||||
i = P - bbits;
|
i = P - bbits;
|
||||||
j = p2 - (Emin - P + 1);
|
if (i > p2 - (Emin - P + 1))
|
||||||
if (i > j)
|
i = p2 - (Emin - P + 1);
|
||||||
i = j;
|
|
||||||
/* increment i so that we shift b by an extra bit; then or-ing a 1 into
|
/* 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. */
|
the lsb of b gives us rv/2^(bc->scale) + 0.5ulp. */
|
||||||
b = lshift(b, ++i);
|
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
|
/* if b >= d, round down */
|
||||||
on either side of the input string. If b >= d, round down. */
|
|
||||||
if (cmp(b, d) >= 0) {
|
if (cmp(b, d) >= 0) {
|
||||||
dd = -1;
|
dd = -1;
|
||||||
goto ret;
|
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 */
|
/* Compare b/d with s0 */
|
||||||
|
for(i = 0; i < nd0; i++) {
|
||||||
assert(nd > 0);
|
b = multadd(b, 10, 0);
|
||||||
dd = 9999; /* silence gcc compiler warning */
|
if (b == NULL) {
|
||||||
for(i = 0; i < nd0; ) {
|
Bfree(d);
|
||||||
if ((dd = s0[i++] - '0' - dig))
|
return -1;
|
||||||
|
}
|
||||||
|
dd = *s0++ - '0' - quorem(b, d);
|
||||||
|
if (dd)
|
||||||
goto ret;
|
goto ret;
|
||||||
if (!b->x[0] && b->wds == 1) {
|
if (!b->x[0] && b->wds == 1) {
|
||||||
if (i < nd)
|
if (i < nd)
|
||||||
dd = 1;
|
dd = 1;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
b = multadd(b, 10, 0);
|
|
||||||
if (b == NULL) {
|
|
||||||
Bfree(d);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
dig = quorem(b,d);
|
|
||||||
}
|
}
|
||||||
for(j = bc->dp1; i++ < nd;) {
|
s0++;
|
||||||
if ((dd = s0[j++] - '0' - dig))
|
for(; i < nd; i++) {
|
||||||
|
b = multadd(b, 10, 0);
|
||||||
|
if (b == NULL) {
|
||||||
|
Bfree(d);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dd = *s0++ - '0' - quorem(b, d);
|
||||||
|
if (dd)
|
||||||
goto ret;
|
goto ret;
|
||||||
if (!b->x[0] && b->wds == 1) {
|
if (!b->x[0] && b->wds == 1) {
|
||||||
if (i < nd)
|
if (i < nd)
|
||||||
dd = 1;
|
dd = 1;
|
||||||
goto ret;
|
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)
|
if (b->x[0] || b->wds > 1)
|
||||||
dd = -1;
|
dd = -1;
|
||||||
|
@ -1369,7 +1343,7 @@ bigcomp(U *rv, const char *s0, BCinfo *bc)
|
||||||
double
|
double
|
||||||
_Py_dg_strtod(const char *s00, char **se)
|
_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;
|
int esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
|
||||||
const char *s, *s0, *s1;
|
const char *s, *s0, *s1;
|
||||||
double aadj, aadj1;
|
double aadj, aadj1;
|
||||||
|
@ -1378,7 +1352,7 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
BCinfo bc;
|
BCinfo bc;
|
||||||
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
|
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
|
||||||
|
|
||||||
sign = nz0 = nz = bc.dplen = 0;
|
sign = nz0 = nz = dplen = 0;
|
||||||
dval(&rv) = 0.;
|
dval(&rv) = 0.;
|
||||||
for(s = s00;;s++) switch(*s) {
|
for(s = s00;;s++) switch(*s) {
|
||||||
case '-':
|
case '-':
|
||||||
|
@ -1417,11 +1391,11 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
else if (nd < 16)
|
else if (nd < 16)
|
||||||
z = 10*z + c - '0';
|
z = 10*z + c - '0';
|
||||||
nd0 = nd;
|
nd0 = nd;
|
||||||
bc.dp0 = bc.dp1 = s - s0;
|
dp0 = dp1 = s - s0;
|
||||||
if (c == '.') {
|
if (c == '.') {
|
||||||
c = *++s;
|
c = *++s;
|
||||||
bc.dp1 = s - s0;
|
dp1 = s - s0;
|
||||||
bc.dplen = bc.dp1 - bc.dp0;
|
dplen = 1;
|
||||||
if (!nd) {
|
if (!nd) {
|
||||||
for(; c == '0'; c = *++s)
|
for(; c == '0'; c = *++s)
|
||||||
nz++;
|
nz++;
|
||||||
|
@ -1624,10 +1598,10 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
/* in IEEE arithmetic. */
|
/* in IEEE arithmetic. */
|
||||||
i = j = 18;
|
i = j = 18;
|
||||||
if (i > nd0)
|
if (i > nd0)
|
||||||
j += bc.dplen;
|
j += dplen;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (--j <= bc.dp1 && j >= bc.dp0)
|
if (--j <= dp1 && j >= dp0)
|
||||||
j = bc.dp0 - 1;
|
j = dp0 - 1;
|
||||||
if (s0[j] != '0')
|
if (s0[j] != '0')
|
||||||
break;
|
break;
|
||||||
--i;
|
--i;
|
||||||
|
@ -1640,11 +1614,11 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
y = 0;
|
y = 0;
|
||||||
for(i = 0; i < nd0; ++i)
|
for(i = 0; i < nd0; ++i)
|
||||||
y = 10*y + s0[i] - '0';
|
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';
|
y = 10*y + s0[j++] - '0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bd0 = s2b(s0, nd0, nd, y, bc.dplen);
|
bd0 = s2b(s0, nd0, nd, y);
|
||||||
if (bd0 == NULL)
|
if (bd0 == NULL)
|
||||||
goto failed_malloc;
|
goto failed_malloc;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue