mirror of
https://github.com/python/cpython.git
synced 2025-07-28 13:44:43 +00:00
Additional explanatory comments for _Py_dg_strtod.
This commit is contained in:
parent
1942806013
commit
ca6ea56718
1 changed files with 73 additions and 0 deletions
|
@ -1672,6 +1672,16 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (e1 < 0) {
|
else if (e1 < 0) {
|
||||||
|
/* The input decimal value lies in [10**e1, 10**(e1+16)).
|
||||||
|
|
||||||
|
If e1 <= -512, underflow immediately.
|
||||||
|
If e1 <= -256, set bc.scale to 2*P.
|
||||||
|
|
||||||
|
So for input value < 1e-256, bc.scale is always set;
|
||||||
|
for input value >= 1e-240, bc.scale is never set.
|
||||||
|
For input values in [1e-256, 1e-240), bc.scale may or may
|
||||||
|
not be set. */
|
||||||
|
|
||||||
e1 = -e1;
|
e1 = -e1;
|
||||||
if ((i = e1 & 15))
|
if ((i = e1 & 15))
|
||||||
dval(&rv) /= tens[i];
|
dval(&rv) /= tens[i];
|
||||||
|
@ -1742,7 +1752,34 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
if (bd0 == NULL)
|
if (bd0 == NULL)
|
||||||
goto failed_malloc;
|
goto failed_malloc;
|
||||||
|
|
||||||
|
/* Notation for the comments below. Write:
|
||||||
|
|
||||||
|
- dv for the absolute value of the number represented by the original
|
||||||
|
decimal input string.
|
||||||
|
|
||||||
|
- if we've truncated dv, write tdv for the truncated value.
|
||||||
|
Otherwise, set tdv == dv.
|
||||||
|
|
||||||
|
- srv for the quantity rv/2^bc.scale; so srv is the current binary
|
||||||
|
approximation to tdv (and dv). It should be exactly representable
|
||||||
|
in an IEEE 754 double.
|
||||||
|
*/
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
|
||||||
|
/* This is the main correction loop for _Py_dg_strtod.
|
||||||
|
|
||||||
|
We've got a decimal value tdv, and a floating-point approximation
|
||||||
|
srv=rv/2^bc.scale to tdv. The aim is to determine whether srv is
|
||||||
|
close enough (i.e., within 0.5 ulps) to tdv, and to compute a new
|
||||||
|
approximation if not.
|
||||||
|
|
||||||
|
To determine whether srv is close enough to tdv, compute integers
|
||||||
|
bd, bb and bs proportional to tdv, srv and 0.5 ulp(srv)
|
||||||
|
respectively, and then use integer arithmetic to determine whether
|
||||||
|
|tdv - srv| is less than, equal to, or greater than 0.5 ulp(srv).
|
||||||
|
*/
|
||||||
|
|
||||||
bd = Balloc(bd0->k);
|
bd = Balloc(bd0->k);
|
||||||
if (bd == NULL) {
|
if (bd == NULL) {
|
||||||
Bfree(bd0);
|
Bfree(bd0);
|
||||||
|
@ -1755,6 +1792,7 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
Bfree(bd0);
|
Bfree(bd0);
|
||||||
goto failed_malloc;
|
goto failed_malloc;
|
||||||
}
|
}
|
||||||
|
/* tdv = bd * 10^e; srv = bb * 2^(bbe - scale) */
|
||||||
bs = i2b(1);
|
bs = i2b(1);
|
||||||
if (bs == NULL) {
|
if (bs == NULL) {
|
||||||
Bfree(bb);
|
Bfree(bb);
|
||||||
|
@ -1775,6 +1813,17 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
bb2 += bbe;
|
bb2 += bbe;
|
||||||
else
|
else
|
||||||
bd2 -= bbe;
|
bd2 -= bbe;
|
||||||
|
|
||||||
|
/* At this stage e = bd2 - bb2 + bbe = bd5 - bb5, so:
|
||||||
|
|
||||||
|
tdv = bd * 2^(bbe + bd2 - bb2) * 5^(bd5 - bb5)
|
||||||
|
srv = bb * 2^(bbe - scale).
|
||||||
|
|
||||||
|
Compute j such that
|
||||||
|
|
||||||
|
0.5 ulp(srv) = 2^(bbe - scale - j)
|
||||||
|
*/
|
||||||
|
|
||||||
bs2 = bb2;
|
bs2 = bb2;
|
||||||
j = bbe - bc.scale;
|
j = bbe - bc.scale;
|
||||||
i = j + bbbits - 1; /* logb(rv) */
|
i = j + bbbits - 1; /* logb(rv) */
|
||||||
|
@ -1782,9 +1831,26 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
j += P - Emin;
|
j += P - Emin;
|
||||||
else
|
else
|
||||||
j = P + 1 - bbbits;
|
j = P + 1 - bbbits;
|
||||||
|
|
||||||
|
/* Now we have:
|
||||||
|
|
||||||
|
M * tdv = bd * 2^(bd2 + scale + j) * 5^bd5
|
||||||
|
M * srv = bb * 2^(bb2 + j) * 5^bb5
|
||||||
|
M * 0.5 ulp(srv) = 2^bs2 * 5^bb5
|
||||||
|
|
||||||
|
where M is the constant (currently) represented by 2^(j + scale +
|
||||||
|
bb2 - bbe) * 5^bb5.
|
||||||
|
*/
|
||||||
|
|
||||||
bb2 += j;
|
bb2 += j;
|
||||||
bd2 += j;
|
bd2 += j;
|
||||||
bd2 += bc.scale;
|
bd2 += bc.scale;
|
||||||
|
|
||||||
|
/* After the adjustments above, tdv, srv and 0.5 ulp(srv) are
|
||||||
|
proportional to: bd * 2^bd2 * 5^bd5, bb * 2^bb2 * 5^bb5, and
|
||||||
|
bs * 2^bs2 * 5^bb5, respectively. */
|
||||||
|
|
||||||
|
/* Remove excess powers of 2. i = min(bb2, bd2, bs2). */
|
||||||
i = bb2 < bd2 ? bb2 : bd2;
|
i = bb2 < bd2 ? bb2 : bd2;
|
||||||
if (i > bs2)
|
if (i > bs2)
|
||||||
i = bs2;
|
i = bs2;
|
||||||
|
@ -1793,6 +1859,8 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
bd2 -= i;
|
bd2 -= i;
|
||||||
bs2 -= i;
|
bs2 -= i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Scale bb, bd, bs by the appropriate powers of 2 and 5. */
|
||||||
if (bb5 > 0) {
|
if (bb5 > 0) {
|
||||||
bs = pow5mult(bs, bb5);
|
bs = pow5mult(bs, bb5);
|
||||||
if (bs == NULL) {
|
if (bs == NULL) {
|
||||||
|
@ -1847,6 +1915,11 @@ _Py_dg_strtod(const char *s00, char **se)
|
||||||
goto failed_malloc;
|
goto failed_malloc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now bd, bb and bs are scaled versions of tdv, srv and 0.5 ulp(srv),
|
||||||
|
respectively. Compute the difference |tdv - srv|, and compare
|
||||||
|
with 0.5 ulp(srv). */
|
||||||
|
|
||||||
delta = diff(bb, bd);
|
delta = diff(bb, bd);
|
||||||
if (delta == NULL) {
|
if (delta == NULL) {
|
||||||
Bfree(bb);
|
Bfree(bb);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue