Merged revisions 77691,77698,77713-77714 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r77691 | mark.dickinson | 2010-01-22 16:18:09 +0000 (Fri, 22 Jan 2010) | 1 line

  Correct typo in comment.
........
  r77698 | mark.dickinson | 2010-01-22 17:04:07 +0000 (Fri, 22 Jan 2010) | 3 lines

  Issue #7743:  Fix a potential incorrect rounding bug in dtoa.c (2nd bug
  in issue 7743).
........
  r77713 | mark.dickinson | 2010-01-23 20:48:56 +0000 (Sat, 23 Jan 2010) | 3 lines

  Issue #7743:  Add checks for zero inputs to the lshift and mult functions;
  this fixes the first bug described in issue #7743.
........
  r77714 | mark.dickinson | 2010-01-23 21:25:53 +0000 (Sat, 23 Jan 2010) | 1 line

  dtoa.c fix from upstream that fixes incorrectly rounded results for certain subnormals that are also halfway cases.
........
This commit is contained in:
Mark Dickinson 2010-01-24 10:16:29 +00:00
parent 53ab5cbcc7
commit f41d29a8eb
2 changed files with 124 additions and 71 deletions

View File

@ -235,6 +235,7 @@ typedef union { double d; ULong L[2]; } U;
#define Bias 1023
#define Emax 1023
#define Emin (-1022)
#define Etiny (-1074) /* smallest denormal is 2**Etiny */
#define Exp_1 0x3ff00000
#define Exp_11 0x3ff00000
#define Ebits 11
@ -244,7 +245,6 @@ typedef union { double d; ULong L[2]; } U;
#define Bletch 0x10
#define Bndry_mask 0xfffff
#define Bndry_mask1 0xfffff
#define LSB 1
#define Sign_bit 0x80000000
#define Log2P 1
#define Tiny0 0
@ -622,6 +622,15 @@ mult(Bigint *a, Bigint *b)
ULong z2;
#endif
if ((!a->x[0] && a->wds == 1) || (!b->x[0] && b->wds == 1)) {
c = Balloc(0);
if (c == NULL)
return NULL;
c->wds = 1;
c->x[0] = 0;
return c;
}
if (a->wds < b->wds) {
c = a;
a = b;
@ -820,6 +829,9 @@ lshift(Bigint *b, int k)
Bigint *b1;
ULong *x, *x1, *xe, z;
if (!k || (!b->x[0] && b->wds == 1))
return b;
n = k >> 5;
k1 = b->k;
n1 = n + b->wds + 1;
@ -1019,6 +1031,76 @@ b2d(Bigint *a, int *e)
return dval(&d);
}
/* Convert a scaled double to a Bigint plus an exponent. Similar to d2b,
except that it accepts the scale parameter used in _Py_dg_strtod (which
should be either 0 or 2*P), and the normalization for the return value is
different (see below). On input, d should be finite and nonnegative, and d
/ 2**scale should be exactly representable as an IEEE 754 double.
Returns a Bigint b and an integer e such that
dval(d) / 2**scale = b * 2**e.
Unlike d2b, b is not necessarily odd: b and e are normalized so
that either 2**(P-1) <= b < 2**P and e >= Etiny, or b < 2**P
and e == Etiny. This applies equally to an input of 0.0: in that
case the return values are b = 0 and e = Etiny.
The above normalization ensures that for all possible inputs d,
2**e gives ulp(d/2**scale).
Returns NULL on failure.
*/
static Bigint *
sd2b(U *d, int scale, int *e)
{
Bigint *b;
b = Balloc(1);
if (b == NULL)
return NULL;
/* First construct b and e assuming that scale == 0. */
b->wds = 2;
b->x[0] = word1(d);
b->x[1] = word0(d) & Frac_mask;
*e = Etiny - 1 + (int)((word0(d) & Exp_mask) >> Exp_shift);
if (*e < Etiny)
*e = Etiny;
else
b->x[1] |= Exp_msk1;
/* Now adjust for scale, provided that b != 0. */
if (scale && (b->x[0] || b->x[1])) {
*e -= scale;
if (*e < Etiny) {
scale = Etiny - *e;
*e = Etiny;
/* We can't shift more than P-1 bits without shifting out a 1. */
assert(0 < scale && scale <= P - 1);
if (scale >= 32) {
/* The bits shifted out should all be zero. */
assert(b->x[0] == 0);
b->x[0] = b->x[1];
b->x[1] = 0;
scale -= 32;
}
if (scale) {
/* The bits shifted out should all be zero. */
assert(b->x[0] << (32 - scale) == 0);
b->x[0] = (b->x[0] >> scale) | (b->x[1] << (32 - scale));
b->x[1] >>= scale;
}
}
}
/* Ensure b is normalized. */
if (!b->x[1])
b->wds = 1;
return b;
}
/* Convert a double to a Bigint plus an exponent. Return NULL on failure.
Given a finite nonzero double d, return an odd Bigint b and exponent *e
@ -1028,7 +1110,6 @@ b2d(Bigint *a, int *e)
If d is zero, then b == 0, *e == -1010, *bbits = 0.
*/
static Bigint *
d2b(U *d, int *e, int *bits)
{
@ -1299,45 +1380,29 @@ static int
bigcomp(U *rv, const char *s0, BCinfo *bc)
{
Bigint *b, *d;
int b2, bbits, d2, dd, i, nd, nd0, odd, p2, p5;
int b2, d2, dd, i, nd, nd0, odd, 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 because d2b doesn't handle 0.0 */
b = i2b(0);
if (b == NULL)
return -1;
p2 = Emin - P + 1; /* = -1074 for IEEE 754 binary64 */
bbits = 0;
}
else {
b = d2b(rv, &p2, &bbits);
if (b == NULL)
return -1;
p2 -= bc->scale;
}
/* now rv/2^(bc->scale) = b * 2**p2, and b has bbits significant bits */
/* Replace (b, p2) by (b << i, p2 - i), with i the largest integer such
that b << i has at most P significant bits and p2 - i >= Emin - P +
1. */
i = P - bbits;
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);
b = sd2b(rv, bc->scale, &p2);
if (b == NULL)
return -1;
/* record whether the lsb of rv/2^(bc->scale) is odd: in the exact halfway
case, this is used for round to even. */
odd = b->x[0] & 2;
b->x[0] |= 1;
odd = b->x[0] & 1;
p2 -= p5 + i;
/* left shift b by 1 bit and or a 1 into the least significant bit;
this gives us b * 2**p2 = rv/2^(bc->scale) + 0.5 ulp. */
b = lshift(b, 1);
if (b == NULL)
return -1;
b->x[0] |= 1;
p2--;
p2 -= p5;
d = i2b(1);
if (d == NULL) {
Bfree(b);
@ -1425,8 +1490,8 @@ 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, dsign, e, e1, error;
int esign, i, j, k, lz, nd, nd0, sign;
int bb2, bb5, bbe, bd2, bd5, bs2, c, dsign, e, e1, error;
int esign, i, j, k, lz, nd, nd0, odd, sign;
const char *s, *s0, *s1;
double aadj, aadj1;
U aadj2, adj, rv, rv0;
@ -1786,13 +1851,17 @@ _Py_dg_strtod(const char *s00, char **se)
goto failed_malloc;
}
Bcopy(bd, bd0);
bb = d2b(&rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
bb = sd2b(&rv, bc.scale, &bbe); /* srv = bb * 2^bbe */
if (bb == NULL) {
Bfree(bd);
Bfree(bd0);
goto failed_malloc;
}
/* tdv = bd * 10^e; srv = bb * 2^(bbe - scale) */
/* Record whether lsb of bb is odd, in case we need this
for the round-to-even step later. */
odd = bb->x[0] & 1;
/* tdv = bd * 10**e; srv = bb * 2**bbe */
bs = i2b(1);
if (bs == NULL) {
Bfree(bb);
@ -1813,44 +1882,28 @@ _Py_dg_strtod(const char *s00, char **se)
bb2 += bbe;
else
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;
j = bbe - bc.scale;
i = j + bbbits - 1; /* logb(rv) */
if (i < Emin) /* denormal */
j += P - Emin;
else
j = P + 1 - bbbits;
bb2++;
bd2++;
/* Now we have:
/* At this stage bd5 - bb5 == e == bd2 - bb2 + bbe, bb2 - bs2 == 1,
and bs == 1, so:
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
tdv == bd * 10**e = bd * 2**(bbe - bb2 + bd2) * 5**(bd5 - bb5)
srv == bb * 2**bbe = bb * 2**(bbe - bb2 + bb2)
0.5 ulp(srv) == 2**(bbe-1) = bs * 2**(bbe - bb2 + bs2)
where M is the constant (currently) represented by 2^(j + scale +
bb2 - bbe) * 5^bb5.
It follows that:
M * tdv = bd * 2**bd2 * 5**bd5
M * srv = bb * 2**bb2 * 5**bb5
M * 0.5 ulp(srv) = bs * 2**bs2 * 5**bb5
for some constant M. (Actually, M == 2**(bb2 - bbe) * 5**bb5, but
this fact is not needed below.)
*/
bb2 += j;
bd2 += j;
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). */
/* Remove factor of 2**i, where i = min(bb2, bd2, bs2). */
i = bb2 < bd2 ? bb2 : bd2;
if (i > bs2)
i = bs2;
@ -2028,12 +2081,12 @@ _Py_dg_strtod(const char *s00, char **se)
word1(&rv) = 0xffffffff;
break;
}
if (!(word1(&rv) & LSB))
if (!odd)
break;
if (dsign)
dval(&rv) += ulp(&rv);
dval(&rv) += sulp(&rv, &bc);
else {
dval(&rv) -= ulp(&rv);
dval(&rv) -= sulp(&rv, &bc);
if (!dval(&rv)) {
if (bc.nd >nd)
break;

View File

@ -104,7 +104,7 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr)
_Py_SET_53BIT_PRECISION_END;
if (*endptr == nptr)
/* string might represent and inf or nan */
/* string might represent an inf or nan */
result = _Py_parse_inf_or_nan(nptr, endptr);
return result;