Commit c80bf763 authored by Alexey Kopytov's avatar Alexey Kopytov

Bug #45882: dtoa.c might not work with gcc 4.4.0

- Ported relevant changes from the upstream version to not
break strict-aliasing rules and to fix compiler warnings and
and infinite loops caused by that issue.

- Fixed compilation with Honor_FLT_ROUNDS defined.

- Fixed an unused variable warning.
parent ec4033b5
...@@ -551,14 +551,14 @@ typedef union { double d; ULong L[2]; } U; ...@@ -551,14 +551,14 @@ typedef union { double d; ULong L[2]; } U;
#if defined(WORDS_BIGENDIAN) || (defined(__FLOAT_WORD_ORDER) && \ #if defined(WORDS_BIGENDIAN) || (defined(__FLOAT_WORD_ORDER) && \
(__FLOAT_WORD_ORDER == __BIG_ENDIAN)) (__FLOAT_WORD_ORDER == __BIG_ENDIAN))
#define word0(x) ((U*)&x)->L[0] #define word0(x) (x)->L[0]
#define word1(x) ((U*)&x)->L[1] #define word1(x) (x)->L[1]
#else #else
#define word0(x) ((U*)&x)->L[1] #define word0(x) (x)->L[1]
#define word1(x) ((U*)&x)->L[0] #define word1(x) (x)->L[0]
#endif #endif
#define dval(x) ((U*)&x)->d #define dval(x) (x)->d
/* #define P DBL_MANT_DIG */ /* #define P DBL_MANT_DIG */
/* Ten_pmax= floor(P*log(2)/log(5)) */ /* Ten_pmax= floor(P*log(2)/log(5)) */
...@@ -1159,15 +1159,15 @@ static Bigint *diff(Bigint *a, Bigint *b, Stack_alloc *alloc) ...@@ -1159,15 +1159,15 @@ static Bigint *diff(Bigint *a, Bigint *b, Stack_alloc *alloc)
} }
static double ulp(double x) static double ulp(U *x)
{ {
register Long L; register Long L;
double a; U u;
L= (word0(x) & Exp_mask) - (P - 1)*Exp_msk1; L= (word0(x) & Exp_mask) - (P - 1)*Exp_msk1;
word0(a) = L; word0(&u) = L;
word1(a) = 0; word1(&u) = 0;
return dval(a); return dval(&u);
} }
...@@ -1175,9 +1175,9 @@ static double b2d(Bigint *a, int *e) ...@@ -1175,9 +1175,9 @@ static double b2d(Bigint *a, int *e)
{ {
ULong *xa, *xa0, w, y, z; ULong *xa, *xa0, w, y, z;
int k; int k;
double d; U d;
#define d0 word0(d) #define d0 word0(&d)
#define d1 word1(d) #define d1 word1(&d)
xa0= a->p.x; xa0= a->p.x;
xa= xa0 + a->wds; xa= xa0 + a->wds;
...@@ -1206,11 +1206,11 @@ static double b2d(Bigint *a, int *e) ...@@ -1206,11 +1206,11 @@ static double b2d(Bigint *a, int *e)
ret_d: ret_d:
#undef d0 #undef d0
#undef d1 #undef d1
return dval(d); return dval(&d);
} }
static Bigint *d2b(double d, int *e, int *bits, Stack_alloc *alloc) static Bigint *d2b(U *d, int *e, int *bits, Stack_alloc *alloc)
{ {
Bigint *b; Bigint *b;
int de, k; int de, k;
...@@ -1262,20 +1262,20 @@ static Bigint *d2b(double d, int *e, int *bits, Stack_alloc *alloc) ...@@ -1262,20 +1262,20 @@ static Bigint *d2b(double d, int *e, int *bits, Stack_alloc *alloc)
static double ratio(Bigint *a, Bigint *b) static double ratio(Bigint *a, Bigint *b)
{ {
double da, db; U da, db;
int k, ka, kb; int k, ka, kb;
dval(da)= b2d(a, &ka); dval(&da)= b2d(a, &ka);
dval(db)= b2d(b, &kb); dval(&db)= b2d(b, &kb);
k= ka - kb + 32*(a->wds - b->wds); k= ka - kb + 32*(a->wds - b->wds);
if (k > 0) if (k > 0)
word0(da)+= k*Exp_msk1; word0(&da)+= k*Exp_msk1;
else else
{ {
k= -k; k= -k;
word0(db)+= k*Exp_msk1; word0(&db)+= k*Exp_msk1;
} }
return dval(da) / dval(db); return dval(&da) / dval(&db);
} }
static const double tens[] = static const double tens[] =
...@@ -1329,10 +1329,11 @@ static const double tinytens[]= ...@@ -1329,10 +1329,11 @@ static const double tinytens[]=
static double my_strtod_int(const char *s00, char **se, int *error, char *buf, size_t buf_size) static double my_strtod_int(const char *s00, char **se, int *error, char *buf, size_t buf_size)
{ {
int scale; int scale;
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, UNINIT_VAR(c), dsign,
e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
const char *s, *s0, *s1, *end = *se; const char *s, *s0, *s1, *end = *se;
double aadj, aadj1, adj, rv, rv0; double aadj, aadj1;
U aadj2, adj, rv, rv0;
Long L; Long L;
ULong y, z; ULong y, z;
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
...@@ -1343,7 +1344,6 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1343,7 +1344,6 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
int rounding; int rounding;
#endif #endif
Stack_alloc alloc; Stack_alloc alloc;
LINT_INIT(c);
*error= 0; *error= 0;
...@@ -1352,7 +1352,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1352,7 +1352,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
memset(alloc.freelist, 0, sizeof(alloc.freelist)); memset(alloc.freelist, 0, sizeof(alloc.freelist));
sign= nz0= nz= 0; sign= nz0= nz= 0;
dval(rv)= 0.; dval(&rv)= 0.;
for (s= s00; s < end; s++) for (s= s00; s < end; s++)
switch (*s) { switch (*s) {
case '-': case '-':
...@@ -1488,14 +1488,14 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1488,14 +1488,14 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
if (!nd0) if (!nd0)
nd0= nd; nd0= nd;
k= nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; k= nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
dval(rv)= y; dval(&rv)= y;
if (k > 9) if (k > 9)
{ {
#ifdef SET_INEXACT #ifdef SET_INEXACT
if (k > DBL_DIG) if (k > DBL_DIG)
oldinexact = get_inexact(); oldinexact = get_inexact();
#endif #endif
dval(rv)= tens[k - 9] * dval(rv) + z; dval(&rv)= tens[k - 9] * dval(&rv) + z;
} }
bd0= 0; bd0= 0;
if (nd <= DBL_DIG if (nd <= DBL_DIG
...@@ -1514,11 +1514,11 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1514,11 +1514,11 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
/* round correctly FLT_ROUNDS = 2 or 3 */ /* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) if (sign)
{ {
rv= -rv; rv.d= -rv.d;
sign= 0; sign= 0;
} }
#endif #endif
/* rv = */ rounded_product(dval(rv), tens[e]); /* rv = */ rounded_product(dval(&rv), tens[e]);
goto ret; goto ret;
} }
i= DBL_DIG - nd; i= DBL_DIG - nd;
...@@ -1532,13 +1532,13 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1532,13 +1532,13 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
/* round correctly FLT_ROUNDS = 2 or 3 */ /* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) if (sign)
{ {
rv= -rv; rv.d= -rv.d;
sign= 0; sign= 0;
} }
#endif #endif
e-= i; e-= i;
dval(rv)*= tens[i]; dval(&rv)*= tens[i];
/* rv = */ rounded_product(dval(rv), tens[e]); /* rv = */ rounded_product(dval(&rv), tens[e]);
goto ret; goto ret;
} }
} }
...@@ -1549,11 +1549,11 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1549,11 +1549,11 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
/* round correctly FLT_ROUNDS = 2 or 3 */ /* round correctly FLT_ROUNDS = 2 or 3 */
if (sign) if (sign)
{ {
rv= -rv; rv.d= -rv.d;
sign= 0; sign= 0;
} }
#endif #endif
/* rv = */ rounded_quotient(dval(rv), tens[-e]); /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
goto ret; goto ret;
} }
#endif #endif
...@@ -1582,7 +1582,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1582,7 +1582,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
if (e1 > 0) if (e1 > 0)
{ {
if ((i= e1 & 15)) if ((i= e1 & 15))
dval(rv)*= tens[i]; dval(&rv)*= tens[i];
if (e1&= ~15) if (e1&= ~15)
{ {
if (e1 > DBL_MAX_10_EXP) if (e1 > DBL_MAX_10_EXP)
...@@ -1595,21 +1595,21 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1595,21 +1595,21 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
{ {
case 0: /* toward 0 */ case 0: /* toward 0 */
case 3: /* toward -infinity */ case 3: /* toward -infinity */
word0(rv)= Big0; word0(&rv)= Big0;
word1(rv)= Big1; word1(&rv)= Big1;
break; break;
default: default:
word0(rv)= Exp_mask; word0(&rv)= Exp_mask;
word1(rv)= 0; word1(&rv)= 0;
} }
#else /*Honor_FLT_ROUNDS*/ #else /*Honor_FLT_ROUNDS*/
word0(rv)= Exp_mask; word0(&rv)= Exp_mask;
word1(rv)= 0; word1(&rv)= 0;
#endif /*Honor_FLT_ROUNDS*/ #endif /*Honor_FLT_ROUNDS*/
#ifdef SET_INEXACT #ifdef SET_INEXACT
/* set overflow bit */ /* set overflow bit */
dval(rv0)= 1e300; dval(&rv0)= 1e300;
dval(rv0)*= dval(rv0); dval(&rv0)*= dval(&rv0);
#endif #endif
if (bd0) if (bd0)
goto retfree; goto retfree;
...@@ -1618,27 +1618,27 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1618,27 +1618,27 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
e1>>= 4; e1>>= 4;
for(j= 0; e1 > 1; j++, e1>>= 1) for(j= 0; e1 > 1; j++, e1>>= 1)
if (e1 & 1) if (e1 & 1)
dval(rv)*= bigtens[j]; dval(&rv)*= bigtens[j];
/* The last multiplication could overflow. */ /* The last multiplication could overflow. */
word0(rv)-= P*Exp_msk1; word0(&rv)-= P*Exp_msk1;
dval(rv)*= bigtens[j]; dval(&rv)*= bigtens[j];
if ((z= word0(rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P)) if ((z= word0(&rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P))
goto ovfl; goto ovfl;
if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P))
{ {
/* set to largest number (Can't trust DBL_MAX) */ /* set to largest number (Can't trust DBL_MAX) */
word0(rv)= Big0; word0(&rv)= Big0;
word1(rv)= Big1; word1(&rv)= Big1;
} }
else else
word0(rv)+= P*Exp_msk1; word0(&rv)+= P*Exp_msk1;
} }
} }
else if (e1 < 0) else if (e1 < 0)
{ {
e1= -e1; e1= -e1;
if ((i= e1 & 15)) if ((i= e1 & 15))
dval(rv)/= tens[i]; dval(&rv)/= tens[i];
if ((e1>>= 4)) if ((e1>>= 4))
{ {
if (e1 >= 1 << n_bigtens) if (e1 >= 1 << n_bigtens)
...@@ -1647,25 +1647,25 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1647,25 +1647,25 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
scale= 2 * P; scale= 2 * P;
for(j= 0; e1 > 0; j++, e1>>= 1) for(j= 0; e1 > 0; j++, e1>>= 1)
if (e1 & 1) if (e1 & 1)
dval(rv)*= tinytens[j]; dval(&rv)*= tinytens[j];
if (scale && (j = 2 * P + 1 - ((word0(rv) & Exp_mask) >> Exp_shift)) > 0) if (scale && (j = 2 * P + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0)
{ {
/* scaled rv is denormal; zap j low bits */ /* scaled rv is denormal; zap j low bits */
if (j >= 32) if (j >= 32)
{ {
word1(rv)= 0; word1(&rv)= 0;
if (j >= 53) if (j >= 53)
word0(rv)= (P + 2) * Exp_msk1; word0(&rv)= (P + 2) * Exp_msk1;
else else
word0(rv)&= 0xffffffff << (j - 32); word0(&rv)&= 0xffffffff << (j - 32);
} }
else else
word1(rv)&= 0xffffffff << j; word1(&rv)&= 0xffffffff << j;
} }
if (!dval(rv)) if (!dval(&rv))
{ {
undfl: undfl:
dval(rv)= 0.; dval(&rv)= 0.;
if (bd0) if (bd0)
goto retfree; goto retfree;
goto ret; goto ret;
...@@ -1683,7 +1683,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1683,7 +1683,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
{ {
bd= Balloc(bd0->k, &alloc); bd= Balloc(bd0->k, &alloc);
Bcopy(bd, bd0); Bcopy(bd, bd0);
bb= d2b(dval(rv), &bbe, &bbbits, &alloc); /* rv = bb * 2^bbe */ bb= d2b(&rv, &bbe, &bbbits, &alloc); /* rv = bb * 2^bbe */
bs= i2b(1, &alloc); bs= i2b(1, &alloc);
if (e >= 0) if (e >= 0)
...@@ -1748,7 +1748,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1748,7 +1748,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
if (i < 0) if (i < 0)
{ {
/* Error is less than an ulp */ /* Error is less than an ulp */
if (!delta->x[0] && delta->wds <= 1) if (!delta->p.x[0] && delta->wds <= 1)
{ {
/* exact */ /* exact */
#ifdef SET_INEXACT #ifdef SET_INEXACT
...@@ -1760,51 +1760,51 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1760,51 +1760,51 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
{ {
if (dsign) if (dsign)
{ {
adj= 1.; adj.d= 1.;
goto apply_adj; goto apply_adj;
} }
} }
else if (!dsign) else if (!dsign)
{ {
adj= -1.; adj.d= -1.;
if (!word1(rv) && !(word0(rv) & Frac_mask)) if (!word1(&rv) && !(word0(&rv) & Frac_mask))
{ {
y= word0(rv) & Exp_mask; y= word0(&rv) & Exp_mask;
if (!scale || y > 2*P*Exp_msk1) if (!scale || y > 2*P*Exp_msk1)
{ {
delta= lshift(delta,Log2P); delta= lshift(delta, Log2P, &alloc);
if (cmp(delta, bs) <= 0) if (cmp(delta, bs) <= 0)
adj= -0.5; adj.d= -0.5;
} }
} }
apply_adj: apply_adj:
if (scale && (y= word0(rv) & Exp_mask) <= 2 * P * Exp_msk1) if (scale && (y= word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1)
word0(adj)+= (2 * P + 1) * Exp_msk1 - y; word0(&adj)+= (2 * P + 1) * Exp_msk1 - y;
dval(rv)+= adj * ulp(dval(rv)); dval(&rv)+= adj.d * ulp(&rv);
} }
break; break;
} }
adj= ratio(delta, bs); adj.d= ratio(delta, bs);
if (adj < 1.) if (adj.d < 1.)
adj= 1.; adj.d= 1.;
if (adj <= 0x7ffffffe) if (adj.d <= 0x7ffffffe)
{ {
/* adj = rounding ? ceil(adj) : floor(adj); */ /* adj = rounding ? ceil(adj) : floor(adj); */
y= adj; y= adj.d;
if (y != adj) if (y != adj.d)
{ {
if (!((rounding >> 1) ^ dsign)) if (!((rounding >> 1) ^ dsign))
y++; y++;
adj= y; adj.d= y;
} }
} }
if (scale && (y= word0(rv) & Exp_mask) <= 2 * P * Exp_msk1) if (scale && (y= word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1)
word0(adj)+= (2 * P + 1) * Exp_msk1 - y; word0(&adj)+= (2 * P + 1) * Exp_msk1 - y;
adj*= ulp(dval(rv)); adj.d*= ulp(&rv);
if (dsign) if (dsign)
dval(rv)+= adj; dval(&rv)+= adj.d;
else else
dval(rv)-= adj; dval(&rv)-= adj.d;
goto cont; goto cont;
} }
#endif /*Honor_FLT_ROUNDS*/ #endif /*Honor_FLT_ROUNDS*/
...@@ -1815,8 +1815,8 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1815,8 +1815,8 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
Error is less than half an ulp -- check for special case of mantissa Error is less than half an ulp -- check for special case of mantissa
a power of two. a power of two.
*/ */
if (dsign || word1(rv) || word0(rv) & Bndry_mask || if (dsign || word1(&rv) || word0(&rv) & Bndry_mask ||
(word0(rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1) (word0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1)
{ {
#ifdef SET_INEXACT #ifdef SET_INEXACT
if (!delta->x[0] && delta->wds <= 1) if (!delta->x[0] && delta->wds <= 1)
...@@ -1842,26 +1842,26 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1842,26 +1842,26 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
/* exactly half-way between */ /* exactly half-way between */
if (dsign) if (dsign)
{ {
if ((word0(rv) & Bndry_mask1) == Bndry_mask1 && if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 &&
word1(rv) == word1(&rv) ==
((scale && (y = word0(rv) & Exp_mask) <= 2 * P * Exp_msk1) ? ((scale && (y = word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1) ?
(0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
0xffffffff)) 0xffffffff))
{ {
/*boundary case -- increment exponent*/ /*boundary case -- increment exponent*/
word0(rv)= (word0(rv) & Exp_mask) + Exp_msk1; word0(&rv)= (word0(&rv) & Exp_mask) + Exp_msk1;
word1(rv) = 0; word1(&rv) = 0;
dsign = 0; dsign = 0;
break; break;
} }
} }
else if (!(word0(rv) & Bndry_mask) && !word1(rv)) else if (!(word0(&rv) & Bndry_mask) && !word1(&rv))
{ {
drop_down: drop_down:
/* boundary case -- decrement exponent */ /* boundary case -- decrement exponent */
if (scale) if (scale)
{ {
L= word0(rv) & Exp_mask; L= word0(&rv) & Exp_mask;
if (L <= (2 *P + 1) * Exp_msk1) if (L <= (2 *P + 1) * Exp_msk1)
{ {
if (L > (P + 2) * Exp_msk1) if (L > (P + 2) * Exp_msk1)
...@@ -1871,19 +1871,19 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1871,19 +1871,19 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
goto undfl; goto undfl;
} }
} }
L= (word0(rv) & Exp_mask) - Exp_msk1; L= (word0(&rv) & Exp_mask) - Exp_msk1;
word0(rv)= L | Bndry_mask1; word0(&rv)= L | Bndry_mask1;
word1(rv)= 0xffffffff; word1(&rv)= 0xffffffff;
break; break;
} }
if (!(word1(rv) & LSB)) if (!(word1(&rv) & LSB))
break; break;
if (dsign) if (dsign)
dval(rv)+= ulp(dval(rv)); dval(&rv)+= ulp(&rv);
else else
{ {
dval(rv)-= ulp(dval(rv)); dval(&rv)-= ulp(&rv);
if (!dval(rv)) if (!dval(&rv))
goto undfl; goto undfl;
} }
dsign= 1 - dsign; dsign= 1 - dsign;
...@@ -1893,9 +1893,9 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1893,9 +1893,9 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
{ {
if (dsign) if (dsign)
aadj= aadj1= 1.; aadj= aadj1= 1.;
else if (word1(rv) || word0(rv) & Bndry_mask) else if (word1(&rv) || word0(&rv) & Bndry_mask)
{ {
if (word1(rv) == Tiny1 && !word0(rv)) if (word1(&rv) == Tiny1 && !word0(&rv))
goto undfl; goto undfl;
aadj= 1.; aadj= 1.;
aadj1= -1.; aadj1= -1.;
...@@ -1929,26 +1929,26 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1929,26 +1929,26 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
aadj1+= 0.5; aadj1+= 0.5;
#endif /*Check_FLT_ROUNDS*/ #endif /*Check_FLT_ROUNDS*/
} }
y= word0(rv) & Exp_mask; y= word0(&rv) & Exp_mask;
/* Check for overflow */ /* Check for overflow */
if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1))
{ {
dval(rv0)= dval(rv); dval(&rv0)= dval(&rv);
word0(rv)-= P * Exp_msk1; word0(&rv)-= P * Exp_msk1;
adj= aadj1 * ulp(dval(rv)); adj.d= aadj1 * ulp(&rv);
dval(rv)+= adj; dval(&rv)+= adj.d;
if ((word0(rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) if ((word0(&rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P))
{ {
if (word0(rv0) == Big0 && word1(rv0) == Big1) if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
goto ovfl; goto ovfl;
word0(rv)= Big0; word0(&rv)= Big0;
word1(rv)= Big1; word1(&rv)= Big1;
goto cont; goto cont;
} }
else else
word0(rv)+= P * Exp_msk1; word0(&rv)+= P * Exp_msk1;
} }
else else
{ {
...@@ -1961,12 +1961,21 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1961,12 +1961,21 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
aadj= z; aadj= z;
aadj1= dsign ? aadj : -aadj; aadj1= dsign ? aadj : -aadj;
} }
word0(aadj1)+= (2 * P + 1) * Exp_msk1 - y; dval(&aadj2) = aadj1;
word0(&aadj2)+= (2 * P + 1) * Exp_msk1 - y;
aadj1= dval(&aadj2);
adj.d= aadj1 * ulp(&rv);
dval(&rv)+= adj.d;
if (rv.d == 0.)
goto undfl;
}
else
{
adj.d= aadj1 * ulp(&rv);
dval(&rv)+= adj.d;
} }
adj = aadj1 * ulp(dval(rv));
dval(rv) += adj;
} }
z= word0(rv) & Exp_mask; z= word0(&rv) & Exp_mask;
#ifndef SET_INEXACT #ifndef SET_INEXACT
if (!scale) if (!scale)
if (y == z) if (y == z)
...@@ -1975,7 +1984,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1975,7 +1984,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
L= (Long)aadj; L= (Long)aadj;
aadj-= L; aadj-= L;
/* The tolerances below are conservative. */ /* The tolerances below are conservative. */
if (dsign || word1(rv) || word0(rv) & Bndry_mask) if (dsign || word1(&rv) || word0(&rv) & Bndry_mask)
{ {
if (aadj < .4999999 || aadj > .5000001) if (aadj < .4999999 || aadj > .5000001)
break; break;
...@@ -1995,9 +2004,9 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -1995,9 +2004,9 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
{ {
if (!oldinexact) if (!oldinexact)
{ {
word0(rv0)= Exp_1 + (70 << Exp_shift); word0(&rv0)= Exp_1 + (70 << Exp_shift);
word1(rv0)= 0; word1(&rv0)= 0;
dval(rv0)+= 1.; dval(&rv0)+= 1.;
} }
} }
else if (!oldinexact) else if (!oldinexact)
...@@ -2005,16 +2014,16 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -2005,16 +2014,16 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
#endif #endif
if (scale) if (scale)
{ {
word0(rv0)= Exp_1 - 2 * P * Exp_msk1; word0(&rv0)= Exp_1 - 2 * P * Exp_msk1;
word1(rv0)= 0; word1(&rv0)= 0;
dval(rv)*= dval(rv0); dval(&rv)*= dval(&rv0);
} }
#ifdef SET_INEXACT #ifdef SET_INEXACT
if (inexact && !(word0(rv) & Exp_mask)) if (inexact && !(word0(&rv) & Exp_mask))
{ {
/* set underflow bit */ /* set underflow bit */
dval(rv0)= 1e-300; dval(&rv0)= 1e-300;
dval(rv0)*= dval(rv0); dval(&rv0)*= dval(&rv0);
} }
#endif #endif
retfree: retfree:
...@@ -2025,7 +2034,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s ...@@ -2025,7 +2034,7 @@ static double my_strtod_int(const char *s00, char **se, int *error, char *buf, s
Bfree(delta, &alloc); Bfree(delta, &alloc);
ret: ret:
*se= (char *)s; *se= (char *)s;
return sign ? -dval(rv) : dval(rv); return sign ? -dval(&rv) : dval(&rv);
} }
...@@ -2128,7 +2137,7 @@ static int quorem(Bigint *b, Bigint *S) ...@@ -2128,7 +2137,7 @@ static int quorem(Bigint *b, Bigint *S)
calculation. calculation.
*/ */
static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, static char *dtoa(double dd, int mode, int ndigits, int *decpt, int *sign,
char **rve, char *buf, size_t buf_size) char **rve, char *buf, size_t buf_size)
{ {
/* /*
...@@ -2173,7 +2182,8 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, ...@@ -2173,7 +2182,8 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
int denorm; int denorm;
ULong x; ULong x;
Bigint *b, *b1, *delta, *mlo, *mhi, *S; Bigint *b, *b1, *delta, *mlo, *mhi, *S;
double d2, ds, eps; U d2, eps, u;
double ds;
char *s, *s0; char *s, *s0;
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
int rounding; int rounding;
...@@ -2184,18 +2194,19 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, ...@@ -2184,18 +2194,19 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
alloc.end= buf + buf_size; alloc.end= buf + buf_size;
memset(alloc.freelist, 0, sizeof(alloc.freelist)); memset(alloc.freelist, 0, sizeof(alloc.freelist));
if (word0(d) & Sign_bit) u.d= dd;
if (word0(&u) & Sign_bit)
{ {
/* set sign for everything, including 0's and NaNs */ /* set sign for everything, including 0's and NaNs */
*sign= 1; *sign= 1;
word0(d) &= ~Sign_bit; /* clear sign bit */ word0(&u) &= ~Sign_bit; /* clear sign bit */
} }
else else
*sign= 0; *sign= 0;
/* If infinity, set decpt to DTOA_OVERFLOW, if 0 set it to 1 */ /* If infinity, set decpt to DTOA_OVERFLOW, if 0 set it to 1 */
if (((word0(d) & Exp_mask) == Exp_mask && (*decpt= DTOA_OVERFLOW)) || if (((word0(&u) & Exp_mask) == Exp_mask && (*decpt= DTOA_OVERFLOW)) ||
(!dval(d) && (*decpt= 1))) (!dval(&u) && (*decpt= 1)))
{ {
/* Infinity, NaN, 0 */ /* Infinity, NaN, 0 */
char *res= (char*) dtoa_alloc(2, &alloc); char *res= (char*) dtoa_alloc(2, &alloc);
...@@ -2217,12 +2228,12 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, ...@@ -2217,12 +2228,12 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
} }
#endif #endif
b= d2b(dval(d), &be, &bbits, &alloc); b= d2b(&u, &be, &bbits, &alloc);
if ((i= (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) if ((i= (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1))))
{ {
dval(d2)= dval(d); dval(&d2)= dval(&u);
word0(d2) &= Frac_mask1; word0(&d2) &= Frac_mask1;
word0(d2) |= Exp_11; word0(&d2) |= Exp_11;
/* /*
log(x) ~=~ log(1.5) + (x-1.5)/1.5 log(x) ~=~ log(1.5) + (x-1.5)/1.5
...@@ -2255,21 +2266,21 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, ...@@ -2255,21 +2266,21 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
/* d is denormalized */ /* d is denormalized */
i= bbits + be + (Bias + (P-1) - 1); i= bbits + be + (Bias + (P-1) - 1);
x= i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) x= i > 32 ? word0(&u) << (64 - i) | word1(&u) >> (i - 32)
: word1(d) << (32 - i); : word1(&u) << (32 - i);
dval(d2)= x; dval(&d2)= x;
word0(d2)-= 31*Exp_msk1; /* adjust exponent */ word0(&d2)-= 31*Exp_msk1; /* adjust exponent */
i-= (Bias + (P-1) - 1) + 1; i-= (Bias + (P-1) - 1) + 1;
denorm= 1; denorm= 1;
} }
ds= (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; ds= (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
k= (int)ds; k= (int)ds;
if (ds < 0. && ds != k) if (ds < 0. && ds != k)
k--; /* want k= floor(ds) */ k--; /* want k= floor(ds) */
k_check= 1; k_check= 1;
if (k >= 0 && k <= Ten_pmax) if (k >= 0 && k <= Ten_pmax)
{ {
if (dval(d) < tens[k]) if (dval(&u) < tens[k])
k--; k--;
k_check= 0; k_check= 0;
} }
...@@ -2347,7 +2358,7 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, ...@@ -2347,7 +2358,7 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
{ {
/* Try to get by with floating-point arithmetic. */ /* Try to get by with floating-point arithmetic. */
i= 0; i= 0;
dval(d2)= dval(d); dval(&d2)= dval(&u);
k0= k; k0= k;
ilim0= ilim; ilim0= ilim;
ieps= 2; /* conservative */ ieps= 2; /* conservative */
...@@ -2359,7 +2370,7 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, ...@@ -2359,7 +2370,7 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
{ {
/* prevent overflows */ /* prevent overflows */
j&= Bletch - 1; j&= Bletch - 1;
dval(d)/= bigtens[n_bigtens-1]; dval(&u)/= bigtens[n_bigtens-1];
ieps++; ieps++;
} }
for (; j; j>>= 1, i++) for (; j; j>>= 1, i++)
...@@ -2370,75 +2381,75 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, ...@@ -2370,75 +2381,75 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
ds*= bigtens[i]; ds*= bigtens[i];
} }
} }
dval(d)/= ds; dval(&u)/= ds;
} }
else if ((j1= -k)) else if ((j1= -k))
{ {
dval(d)*= tens[j1 & 0xf]; dval(&u)*= tens[j1 & 0xf];
for (j= j1 >> 4; j; j>>= 1, i++) for (j= j1 >> 4; j; j>>= 1, i++)
{ {
if (j & 1) if (j & 1)
{ {
ieps++; ieps++;
dval(d)*= bigtens[i]; dval(&u)*= bigtens[i];
} }
} }
} }
if (k_check && dval(d) < 1. && ilim > 0) if (k_check && dval(&u) < 1. && ilim > 0)
{ {
if (ilim1 <= 0) if (ilim1 <= 0)
goto fast_failed; goto fast_failed;
ilim= ilim1; ilim= ilim1;
k--; k--;
dval(d)*= 10.; dval(&u)*= 10.;
ieps++; ieps++;
} }
dval(eps)= ieps*dval(d) + 7.; dval(&eps)= ieps*dval(&u) + 7.;
word0(eps)-= (P-1)*Exp_msk1; word0(&eps)-= (P-1)*Exp_msk1;
if (ilim == 0) if (ilim == 0)
{ {
S= mhi= 0; S= mhi= 0;
dval(d)-= 5.; dval(&u)-= 5.;
if (dval(d) > dval(eps)) if (dval(&u) > dval(&eps))
goto one_digit; goto one_digit;
if (dval(d) < -dval(eps)) if (dval(&u) < -dval(&eps))
goto no_digits; goto no_digits;
goto fast_failed; goto fast_failed;
} }
if (leftright) if (leftright)
{ {
/* Use Steele & White method of only generating digits needed. */ /* Use Steele & White method of only generating digits needed. */
dval(eps)= 0.5/tens[ilim-1] - dval(eps); dval(&eps)= 0.5/tens[ilim-1] - dval(&eps);
for (i= 0;;) for (i= 0;;)
{ {
L= (Long) dval(d); L= (Long) dval(&u);
dval(d)-= L; dval(&u)-= L;
*s++= '0' + (int)L; *s++= '0' + (int)L;
if (dval(d) < dval(eps)) if (dval(&u) < dval(&eps))
goto ret1; goto ret1;
if (1. - dval(d) < dval(eps)) if (1. - dval(&u) < dval(&eps))
goto bump_up; goto bump_up;
if (++i >= ilim) if (++i >= ilim)
break; break;
dval(eps)*= 10.; dval(&eps)*= 10.;
dval(d)*= 10.; dval(&u)*= 10.;
} }
} }
else else
{ {
/* Generate ilim digits, then fix them up. */ /* Generate ilim digits, then fix them up. */
dval(eps)*= tens[ilim-1]; dval(&eps)*= tens[ilim-1];
for (i= 1;; i++, dval(d)*= 10.) for (i= 1;; i++, dval(&u)*= 10.)
{ {
L= (Long)(dval(d)); L= (Long)(dval(&u));
if (!(dval(d)-= L)) if (!(dval(&u)-= L))
ilim= i; ilim= i;
*s++= '0' + (int)L; *s++= '0' + (int)L;
if (i == ilim) if (i == ilim)
{ {
if (dval(d) > 0.5 + dval(eps)) if (dval(&u) > 0.5 + dval(&eps))
goto bump_up; goto bump_up;
else if (dval(d) < 0.5 - dval(eps)) else if (dval(&u) < 0.5 - dval(&eps))
{ {
while (*--s == '0'); while (*--s == '0');
s++; s++;
...@@ -2450,7 +2461,7 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, ...@@ -2450,7 +2461,7 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
} }
fast_failed: fast_failed:
s= s0; s= s0;
dval(d)= dval(d2); dval(&u)= dval(&d2);
k= k0; k= k0;
ilim= ilim0; ilim= ilim0;
} }
...@@ -2464,24 +2475,24 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, ...@@ -2464,24 +2475,24 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
if (ndigits < 0 && ilim <= 0) if (ndigits < 0 && ilim <= 0)
{ {
S= mhi= 0; S= mhi= 0;
if (ilim < 0 || dval(d) <= 5*ds) if (ilim < 0 || dval(&u) <= 5*ds)
goto no_digits; goto no_digits;
goto one_digit; goto one_digit;
} }
for (i= 1;; i++, dval(d)*= 10.) for (i= 1;; i++, dval(&u)*= 10.)
{ {
L= (Long)(dval(d) / ds); L= (Long)(dval(&u) / ds);
dval(d)-= L*ds; dval(&u)-= L*ds;
#ifdef Check_FLT_ROUNDS #ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
if (dval(d) < 0) if (dval(&u) < 0)
{ {
L--; L--;
dval(d)+= ds; dval(&u)+= ds;
} }
#endif #endif
*s++= '0' + (int)L; *s++= '0' + (int)L;
if (!dval(d)) if (!dval(&u))
{ {
break; break;
} }
...@@ -2496,8 +2507,8 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, ...@@ -2496,8 +2507,8 @@ static char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign,
} }
} }
#endif #endif
dval(d)+= dval(d); dval(&u)+= dval(&u);
if (dval(d) > ds || (dval(d) == ds && L & 1)) if (dval(&u) > ds || (dval(&u) == ds && L & 1))
{ {
bump_up: bump_up:
while (*--s == '9') while (*--s == '9')
...@@ -2562,8 +2573,8 @@ bump_up: ...@@ -2562,8 +2573,8 @@ bump_up:
#endif #endif
) )
{ {
if (!word1(d) && !(word0(d) & Bndry_mask) && if (!word1(&u) && !(word0(&u) & Bndry_mask) &&
word0(d) & (Exp_mask & ~Exp_msk1) word0(&u) & (Exp_mask & ~Exp_msk1)
) )
{ {
/* The special case */ /* The special case */
...@@ -2652,7 +2663,7 @@ one_digit: ...@@ -2652,7 +2663,7 @@ one_digit:
delta= diff(S, mhi, &alloc); delta= diff(S, mhi, &alloc);
j1= delta->sign ? 1 : cmp(b, delta); j1= delta->sign ? 1 : cmp(b, delta);
Bfree(delta, &alloc); Bfree(delta, &alloc);
if (j1 == 0 && mode != 1 && !(word1(d) & 1) if (j1 == 0 && mode != 1 && !(word1(&u) & 1)
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
&& rounding >= 1 && rounding >= 1
#endif #endif
...@@ -2665,7 +2676,7 @@ one_digit: ...@@ -2665,7 +2676,7 @@ one_digit:
*s++= dig; *s++= dig;
goto ret; goto ret;
} }
if (j < 0 || (j == 0 && mode != 1 && !(word1(d) & 1))) if (j < 0 || (j == 0 && mode != 1 && !(word1(&u) & 1)))
{ {
if (!b->p.x[0] && b->wds <= 1) if (!b->p.x[0] && b->wds <= 1)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment