Index: base/third_party/dmg_fp/dtoa.cc |
diff --git a/base/third_party/dmg_fp/dtoa.cc b/base/third_party/dmg_fp/dtoa.cc |
index f3d793edc48be86dbf7e43839a0fe2e20f731d14..6dc0e9d3002026dd4c1fb48aa37886ef9eb1fa5a 100644 |
--- a/base/third_party/dmg_fp/dtoa.cc |
+++ b/base/third_party/dmg_fp/dtoa.cc |
@@ -32,6 +32,7 @@ |
*/ |
/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. |
+ * (Note that IEEE arithmetic is disabled by gcc's -ffast-math flag.) |
* |
* This strtod returns a nearest machine number to the input decimal |
* string (or sets errno to ERANGE). With IEEE arithmetic, ties are |
@@ -70,7 +71,8 @@ |
* #define IBM for IBM mainframe-style floating-point arithmetic. |
* #define VAX for VAX-style floating-point arithmetic (D_floating). |
* #define No_leftright to omit left-right logic in fast floating-point |
- * computation of dtoa. |
+ * computation of dtoa. This will cause dtoa modes 4 and 5 to be |
+ * treated the same as modes 2 and 3 for some inputs. |
* #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 |
* and strtod and dtoa should round accordingly. Unless Trust_FLT_ROUNDS |
* is also #defined, fegetround() will be queried for the rounding mode. |
@@ -78,13 +80,18 @@ |
* standard (and are specified to be consistent, with fesetround() |
* affecting the value of FLT_ROUNDS), but that some (Linux) systems |
* do not work correctly in this regard, so using fegetround() is more |
- * portable than using FLT_FOUNDS directly. |
+ * portable than using FLT_ROUNDS directly. |
* #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 |
* and Honor_FLT_ROUNDS is not #defined. |
* #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines |
* that use extended-precision instructions to compute rounded |
* products and quotients) with IBM. |
- * #define ROUND_BIASED for IEEE-format with biased rounding. |
+ * #define ROUND_BIASED for IEEE-format with biased rounding and arithmetic |
+ * that rounds toward +Infinity. |
+ * #define ROUND_BIASED_without_Round_Up for IEEE-format with biased |
+ * rounding when the underlying floating-point arithmetic uses |
+ * unbiased rounding. This prevent using ordinary floating-point |
+ * arithmetic when the result could be computed with one rounding error. |
* #define Inaccurate_Divide for IEEE-format with correctly rounded |
* products but inaccurate quotients, e.g., for Intel i860. |
* #define NO_LONG_LONG on machines that do not have a "long long" |
@@ -458,6 +465,11 @@ extern int strtod_diglim; |
#ifndef IEEE_Arith |
#define ROUND_BIASED |
+#else |
+#ifdef ROUND_BIASED_without_Round_Up |
+#undef ROUND_BIASED |
+#define ROUND_BIASED |
+#endif |
#endif |
#ifdef RND_PRODQUOT |
@@ -663,7 +675,7 @@ s2b |
#ifdef KR_headers |
(s, nd0, nd, y9, dplen) CONST char *s; int nd0, nd, dplen; ULong y9; |
#else |
- (CONST char *s, int nd0, int nd, ULong y9, int dplen) |
+ (const char *s, int nd0, int nd, ULong y9, int dplen) |
#endif |
{ |
Bigint *b; |
@@ -1500,14 +1512,11 @@ static CONST double tinytens[] = { 1e-16, 1e-32 }; |
#endif |
#ifdef Need_Hexdig /*{*/ |
+#if 0 |
static unsigned char hexdig[256]; |
static void |
-#ifdef KR_headers |
-htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc; |
-#else |
htinit(unsigned char *h, unsigned char *s, int inc) |
-#endif |
{ |
int i, j; |
for(i = 0; (j = s[i]) !=0; i++) |
@@ -1515,17 +1524,34 @@ htinit(unsigned char *h, unsigned char *s, int inc) |
} |
static void |
-#ifdef KR_headers |
-hexdig_init() |
-#else |
-hexdig_init(void) |
-#endif |
+hexdig_init(void) /* Use of hexdig_init omitted 20121220 to avoid a */ |
+ /* race condition when multiple threads are used. */ |
{ |
#define USC (unsigned char *) |
htinit(hexdig, USC "0123456789", 0x10); |
htinit(hexdig, USC "abcdef", 0x10 + 10); |
htinit(hexdig, USC "ABCDEF", 0x10 + 10); |
} |
+#else |
+static unsigned char hexdig[256] = { |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0, |
+ 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
+ }; |
+#endif |
#endif /* } Need_Hexdig */ |
#ifdef INFNAN_CHECK |
@@ -1543,7 +1569,7 @@ match |
#ifdef KR_headers |
(sp, t) char **sp, *t; |
#else |
- (CONST char **sp, CONST char *t) |
+ (const char **sp, const char *t) |
#endif |
{ |
int c, d; |
@@ -1565,15 +1591,14 @@ hexnan |
#ifdef KR_headers |
(rvp, sp) U *rvp; CONST char **sp; |
#else |
- (U *rvp, CONST char **sp) |
+ (U *rvp, const char **sp) |
#endif |
{ |
ULong c, x[2]; |
CONST char *s; |
int c1, havedig, udx0, xshift; |
- if (!hexdig['0']) |
- hexdig_init(); |
+ /**** if (!hexdig['0']) hexdig_init(); ****/ |
x[0] = x[1] = 0; |
havedig = xshift = 0; |
udx0 = 1; |
@@ -1640,6 +1665,41 @@ hexnan |
#define kshift 4 |
#define kmask 15 |
#endif |
+ |
+#if !defined(NO_HEX_FP) || defined(Honor_FLT_ROUNDS) /*{*/ |
+ static Bigint * |
+#ifdef KR_headers |
+increment(b) Bigint *b; |
+#else |
+increment(Bigint *b) |
+#endif |
+{ |
+ ULong *x, *xe; |
+ Bigint *b1; |
+ |
+ x = b->x; |
+ xe = x + b->wds; |
+ do { |
+ if (*x < (ULong)0xffffffffL) { |
+ ++*x; |
+ return b; |
+ } |
+ *x++ = 0; |
+ } while(x < xe); |
+ { |
+ if (b->wds >= b->maxwds) { |
+ b1 = Balloc(b->k+1); |
+ Bcopy(b1,b); |
+ Bfree(b); |
+ b = b1; |
+ } |
+ b->x[b->wds++] = 1; |
+ } |
+ return b; |
+ } |
+ |
+#endif /*}*/ |
+ |
#ifndef NO_HEX_FP /*{*/ |
static void |
@@ -1712,37 +1772,6 @@ enum { /* rounding values: same as FLT_ROUNDS */ |
Round_down = 3 |
}; |
- static Bigint * |
-#ifdef KR_headers |
-increment(b) Bigint *b; |
-#else |
-increment(Bigint *b) |
-#endif |
-{ |
- ULong *x, *xe; |
- Bigint *b1; |
- |
- x = b->x; |
- xe = x + b->wds; |
- do { |
- if (*x < (ULong)0xffffffffL) { |
- ++*x; |
- return b; |
- } |
- *x++ = 0; |
- } while(x < xe); |
- { |
- if (b->wds >= b->maxwds) { |
- b1 = Balloc(b->k+1); |
- Bcopy(b1,b); |
- Bfree(b); |
- b = b1; |
- } |
- b->x[b->wds++] = 1; |
- } |
- return b; |
- } |
- |
void |
#ifdef KR_headers |
gethex(sp, rvp, rounding, sign) |
@@ -1793,8 +1822,7 @@ gethex( CONST char **sp, U *rvp, int rounding, int sign) |
#endif |
#endif |
- if (!hexdig['0']) |
- hexdig_init(); |
+ /**** if (!hexdig['0']) hexdig_init(); ****/ |
havedig = 0; |
s0 = *(CONST unsigned char **)sp + 2; |
while(s0[havedig] == '0') |
@@ -1894,6 +1922,8 @@ gethex( CONST char **sp, U *rvp, int rounding, int sign) |
#endif |
goto retz; |
#ifdef IEEE_Arith |
+ ret_tinyf: |
+ Bfree(b); |
ret_tiny: |
#ifndef NO_ERRNO |
errno = ERANGE; |
@@ -1994,15 +2024,15 @@ gethex( CONST char **sp, U *rvp, int rounding, int sign) |
switch (rounding) { |
case Round_near: |
if (n == nbits && (n < 2 || any_on(b,n-1))) |
- goto ret_tiny; |
+ goto ret_tinyf; |
break; |
case Round_up: |
if (!sign) |
- goto ret_tiny; |
+ goto ret_tinyf; |
break; |
case Round_down: |
if (sign) |
- goto ret_tiny; |
+ goto ret_tinyf; |
} |
#endif /* } IEEE_Arith */ |
Bfree(b); |
@@ -2102,7 +2132,7 @@ gethex( CONST char **sp, U *rvp, int rounding, int sign) |
#endif |
Bfree(b); |
} |
-#endif /*}!NO_HEX_FP*/ |
+#endif /*!NO_HEX_FP}*/ |
static int |
#ifdef KR_headers |
@@ -2149,7 +2179,13 @@ quorem |
bxe = bx + n; |
q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ |
#ifdef DEBUG |
+#ifdef NO_STRTOD_BIGCOMP |
/*debug*/ if (q > 9) |
+#else |
+ /* An oversized q is possible when quorem is called from bigcomp and */ |
+ /* the input is near, e.g., twice the smallest denormalized number. */ |
+ /*debug*/ if (q > 15) |
+#endif |
/*debug*/ Bug("oversized quotient in quorem"); |
#endif |
if (q) { |
@@ -2235,15 +2271,36 @@ quorem |
return q; |
} |
-#ifndef NO_STRTOD_BIGCOMP |
+#if defined(Avoid_Underflow) || !defined(NO_STRTOD_BIGCOMP) /*{*/ |
+ static double |
+sulp |
+#ifdef KR_headers |
+ (x, bc) U *x; BCinfo *bc; |
+#else |
+ (U *x, BCinfo *bc) |
+#endif |
+{ |
+ U u; |
+ double rv; |
+ int i; |
+ rv = ulp(x); |
+ if (!bc->scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0) |
+ return rv; /* Is there an example where i <= 0 ? */ |
+ word0(&u) = Exp_1 + (i << Exp_shift); |
+ word1(&u) = 0; |
+ return rv * u.d; |
+ } |
+#endif /*}*/ |
+ |
+#ifndef NO_STRTOD_BIGCOMP |
static void |
bigcomp |
#ifdef KR_headers |
(rv, s0, bc) |
U *rv; CONST char *s0; BCinfo *bc; |
#else |
- (U *rv, CONST char *s0, BCinfo *bc) |
+ (U *rv, const char *s0, BCinfo *bc) |
#endif |
{ |
Bigint *b, *d; |
@@ -2375,7 +2432,7 @@ bigcomp |
b = multadd(b, 10, 0); |
dig = quorem(b,d); |
} |
- if (b->x[0] || b->wds > 1) |
+ if (dig > 0 || b->x[0] || b->wds > 1) |
dd = -1; |
ret: |
Bfree(b); |
@@ -2398,7 +2455,7 @@ bigcomp |
} |
if (!dsign) |
goto rethi1; |
- dval(rv) += 2.*ulp(rv); |
+ dval(rv) += 2.*sulp(rv,bc); |
} |
else { |
bc->inexact = 0; |
@@ -2415,17 +2472,27 @@ bigcomp |
else if (dd < 0) { |
if (!dsign) /* does not happen for round-near */ |
retlow1: |
- dval(rv) -= ulp(rv); |
+ dval(rv) -= sulp(rv,bc); |
} |
else if (dd > 0) { |
if (dsign) { |
rethi1: |
- dval(rv) += ulp(rv); |
+ dval(rv) += sulp(rv,bc); |
} |
} |
else { |
/* Exact half-way case: apply round-even rule. */ |
- if (word1(rv) & 1) { |
+ if ((j = ((word0(rv) & Exp_mask) >> Exp_shift) - bc->scale) <= 0) { |
+ i = 1 - j; |
+ if (i <= 31) { |
+ if (word1(rv) & (0x1 << i)) |
+ goto odd; |
+ } |
+ else if (word0(rv) & (0x1 << (i-32))) |
+ goto odd; |
+ } |
+ else if (word1(rv) & 1) { |
+ odd: |
if (dsign) |
goto rethi1; |
goto retlow1; |
@@ -2444,11 +2511,11 @@ strtod |
#ifdef KR_headers |
(s00, se) CONST char *s00; char **se; |
#else |
- (CONST char *s00, char **se) |
+ (const char *s00, char **se) |
#endif |
{ |
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1; |
- int esign, i, j, k, nd, nd0, nf, nz, nz0, sign; |
+ int esign, i, j, k, nd, nd0, nf, nz, nz0, nz1, sign; |
CONST char *s, *s0, *s1; |
double aadj, aadj1; |
Long L; |
@@ -2456,9 +2523,15 @@ strtod |
ULong y, z; |
BCinfo bc; |
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; |
+#ifdef Avoid_Underflow |
+ ULong Lsb, Lsb1; |
+#endif |
#ifdef SET_INEXACT |
int oldinexact; |
#endif |
+#ifndef NO_STRTOD_BIGCOMP |
+ int req_bigcomp = 0; |
+#endif |
#ifdef Honor_FLT_ROUNDS /*{*/ |
#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ |
bc.rounding = Flt_Rounds; |
@@ -2475,7 +2548,7 @@ strtod |
CONST char *s2; |
#endif |
- sign = nz0 = nz = bc.dplen = bc.uflchk = 0; |
+ sign = nz0 = nz1 = nz = bc.dplen = bc.uflchk = 0; |
dval(&rv) = 0.; |
for(s = s00;;s++) switch(*s) { |
case '-': |
@@ -2521,10 +2594,12 @@ strtod |
for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) |
if (nd < 9) |
y = 10*y + c - '0'; |
- else if (nd < 16) |
+ else if (nd < DBL_DIG + 2) |
z = 10*z + c - '0'; |
nd0 = nd; |
bc.dp0 = bc.dp1 = s - s0; |
+ for(s1 = s; s1 > s0 && *--s1 == '0'; ) |
+ ++nz1; |
#ifdef USE_LOCALE |
s1 = localeconv()->decimal_point; |
if (c == *s1) { |
@@ -2552,6 +2627,8 @@ strtod |
for(; c == '0'; c = *++s) |
nz++; |
if (c > '0' && c <= '9') { |
+ bc.dp0 = s0 - s; |
+ bc.dp1 = bc.dp0 + bc.dplen; |
s0 = s; |
nf += nz; |
nz = 0; |
@@ -2567,13 +2644,13 @@ strtod |
for(i = 1; i < nz; i++) |
if (nd++ < 9) |
y *= 10; |
- else if (nd <= DBL_DIG + 1) |
+ else if (nd <= DBL_DIG + 2) |
z *= 10; |
if (nd++ < 9) |
y = 10*y + c; |
- else if (nd <= DBL_DIG + 1) |
+ else if (nd <= DBL_DIG + 2) |
z = 10*z + c; |
- nz = 0; |
+ nz = nz1 = 0; |
} |
} |
} |
@@ -2663,7 +2740,7 @@ strtod |
if (!nd0) |
nd0 = nd; |
- k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; |
+ k = nd < DBL_DIG + 2 ? nd : DBL_DIG + 2; |
dval(&rv) = y; |
if (k > 9) { |
#ifdef SET_INEXACT |
@@ -2682,6 +2759,7 @@ strtod |
) { |
if (!e) |
goto ret; |
+#ifndef ROUND_BIASED_without_Round_Up |
if (e > 0) { |
if (e <= Ten_pmax) { |
#ifdef VAX |
@@ -2742,6 +2820,7 @@ strtod |
goto ret; |
} |
#endif |
+#endif /* ROUND_BIASED_without_Round_Up */ |
} |
e1 += nd - k; |
@@ -2774,9 +2853,6 @@ strtod |
if (e1 &= ~15) { |
if (e1 > DBL_MAX_10_EXP) { |
ovfl: |
-#ifndef NO_ERRNO |
- errno = ERANGE; |
-#endif |
/* Can't trust HUGE_VAL */ |
#ifdef IEEE_Arith |
#ifdef Honor_FLT_ROUNDS |
@@ -2803,6 +2879,17 @@ strtod |
word0(&rv) = Big0; |
word1(&rv) = Big1; |
#endif /*IEEE_Arith*/ |
+ range_err: |
+ if (bd0) { |
+ Bfree(bb); |
+ Bfree(bd); |
+ Bfree(bs); |
+ Bfree(bd0); |
+ Bfree(delta); |
+ } |
+#ifndef NO_ERRNO |
+ errno = ERANGE; |
+#endif |
goto ret; |
} |
e1 >>= 4; |
@@ -2843,6 +2930,8 @@ strtod |
>> Exp_shift)) > 0) { |
/* scaled rv is denormal; clear j low bits */ |
if (j >= 32) { |
+ if (j > 54) |
+ goto undfl; |
word1(&rv) = 0; |
if (j >= 53) |
word0(&rv) = (P+2)*Exp_msk1; |
@@ -2866,10 +2955,7 @@ strtod |
if (!dval(&rv)) { |
undfl: |
dval(&rv) = 0.; |
-#ifndef NO_ERRNO |
- errno = ERANGE; |
-#endif |
- goto ret; |
+ goto range_err; |
} |
#ifndef Avoid_Underflow |
word0(&rv) = Tiny0; |
@@ -2886,7 +2972,7 @@ strtod |
/* Put digits into bd: true value = bd * 10^e */ |
- bc.nd = nd; |
+ bc.nd = nd - nz1; |
#ifndef NO_STRTOD_BIGCOMP |
bc.nd0 = nd0; /* Only needed if nd > strtod_diglim, but done here */ |
/* to silence an erroneous warning about bc.nd0 */ |
@@ -2899,7 +2985,7 @@ strtod |
if (i > nd0) |
j += bc.dplen; |
for(;;) { |
- if (--j <= bc.dp1 && j >= bc.dp0) |
+ if (--j < bc.dp1 && j >= bc.dp0) |
j = bc.dp0 - 1; |
if (s0[j] != '0') |
break; |
@@ -2944,12 +3030,21 @@ strtod |
bs2++; |
#endif |
#ifdef Avoid_Underflow |
+ Lsb = LSB; |
+ Lsb1 = 0; |
j = bbe - bc.scale; |
i = j + bbbits - 1; /* logb(rv) */ |
- if (i < Emin) /* denormal */ |
- j += P - Emin; |
- else |
- j = P + 1 - bbbits; |
+ j = P + 1 - bbbits; |
+ if (i < Emin) { /* denormal */ |
+ i = Emin - i; |
+ j -= i; |
+ if (i < 32) |
+ Lsb <<= i; |
+ else if (i < 52) |
+ Lsb1 = Lsb << (i-32); |
+ else |
+ Lsb1 = Exp_mask; |
+ } |
#else /*Avoid_Underflow*/ |
#ifdef Sudden_Underflow |
#ifdef IBM |
@@ -2997,24 +3092,26 @@ strtod |
bc.dsign = delta->sign; |
delta->sign = 0; |
i = cmp(delta, bs); |
-#ifndef NO_STRTOD_BIGCOMP |
+#ifndef NO_STRTOD_BIGCOMP /*{*/ |
if (bc.nd > nd && i <= 0) { |
- if (bc.dsign) |
- break; /* Must use bigcomp(). */ |
+ if (bc.dsign) { |
+ /* Must use bigcomp(). */ |
+ req_bigcomp = 1; |
+ break; |
+ } |
#ifdef Honor_FLT_ROUNDS |
if (bc.rounding != 1) { |
- if (i < 0) |
+ if (i < 0) { |
+ req_bigcomp = 1; |
break; |
+ } |
} |
else |
#endif |
- { |
- bc.nd = nd; |
i = -1; /* Discarded digits make delta smaller. */ |
- } |
} |
-#endif |
-#ifdef Honor_FLT_ROUNDS |
+#endif /*}*/ |
+#ifdef Honor_FLT_ROUNDS /*{*/ |
if (bc.rounding != 1) { |
if (i < 0) { |
/* Error is less than an ulp */ |
@@ -3048,7 +3145,7 @@ strtod |
} |
} |
apply_adj: |
-#ifdef Avoid_Underflow |
+#ifdef Avoid_Underflow /*{*/ |
if (bc.scale && (y = word0(&rv) & Exp_mask) |
<= 2*P*Exp_msk1) |
word0(&adj) += (2*P+1)*Exp_msk1 - y; |
@@ -3062,7 +3159,7 @@ strtod |
} |
else |
#endif /*Sudden_Underflow*/ |
-#endif /*Avoid_Underflow*/ |
+#endif /*Avoid_Underflow}*/ |
dval(&rv) += adj.d*ulp(&rv); |
} |
break; |
@@ -3079,7 +3176,7 @@ strtod |
adj.d = y; |
} |
} |
-#ifdef Avoid_Underflow |
+#ifdef Avoid_Underflow /*{*/ |
if (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) |
word0(&adj) += (2*P+1)*Exp_msk1 - y; |
#else |
@@ -3095,7 +3192,7 @@ strtod |
goto cont; |
} |
#endif /*Sudden_Underflow*/ |
-#endif /*Avoid_Underflow*/ |
+#endif /*Avoid_Underflow}*/ |
adj.d *= ulp(&rv); |
if (bc.dsign) { |
if (word0(&rv) == Big0 && word1(&rv) == Big1) |
@@ -3106,20 +3203,20 @@ strtod |
dval(&rv) -= adj.d; |
goto cont; |
} |
-#endif /*Honor_FLT_ROUNDS*/ |
+#endif /*}Honor_FLT_ROUNDS*/ |
if (i < 0) { |
/* Error is less than half an ulp -- check for |
* special case of mantissa a power of two. |
*/ |
if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask |
-#ifdef IEEE_Arith |
+#ifdef IEEE_Arith /*{*/ |
#ifdef Avoid_Underflow |
|| (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1 |
#else |
|| (word0(&rv) & Exp_mask) <= Exp_msk1 |
#endif |
-#endif |
+#endif /*}*/ |
) { |
#ifdef SET_INEXACT |
if (!delta->x[0] && delta->wds <= 1) |
@@ -3150,6 +3247,8 @@ strtod |
#endif |
0xffffffff)) { |
/*boundary case -- increment exponent*/ |
+ if (word0(&rv) == Big0 && word1(&rv) == Big1) |
+ goto ovfl; |
word0(&rv) = (word0(&rv) & Exp_mask) |
+ Exp_msk1 |
#ifdef IBM |
@@ -3210,18 +3309,39 @@ strtod |
#ifdef IBM |
goto cont; |
#else |
+#ifndef NO_STRTOD_BIGCOMP |
+ if (bc.nd > nd) |
+ goto cont; |
+#endif |
break; |
#endif |
} |
#ifndef ROUND_BIASED |
+#ifdef Avoid_Underflow |
+ if (Lsb1) { |
+ if (!(word0(&rv) & Lsb1)) |
+ break; |
+ } |
+ else if (!(word1(&rv) & Lsb)) |
+ break; |
+#else |
if (!(word1(&rv) & LSB)) |
break; |
#endif |
+#endif |
if (bc.dsign) |
+#ifdef Avoid_Underflow |
+ dval(&rv) += sulp(&rv, &bc); |
+#else |
dval(&rv) += ulp(&rv); |
+#endif |
#ifndef ROUND_BIASED |
else { |
+#ifdef Avoid_Underflow |
+ dval(&rv) -= sulp(&rv, &bc); |
+#else |
dval(&rv) -= ulp(&rv); |
+#endif |
#ifndef Sudden_Underflow |
if (!dval(&rv)) { |
if (bc.nd >nd) { |
@@ -3314,9 +3434,22 @@ strtod |
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.) |
+#ifdef NO_STRTOD_BIGCOMP |
+ goto undfl; |
+#else |
+ { |
+ req_bigcomp = 1; |
+ break; |
+ } |
+#endif |
+ } |
+ else { |
+ adj.d = aadj1 * ulp(&rv); |
+ dval(&rv) += adj.d; |
} |
- adj.d = aadj1 * ulp(&rv); |
- dval(&rv) += adj.d; |
#else |
#ifdef Sudden_Underflow |
if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { |
@@ -3399,8 +3532,16 @@ strtod |
Bfree(bd0); |
Bfree(delta); |
#ifndef NO_STRTOD_BIGCOMP |
- if (bc.nd > nd) |
+ if (req_bigcomp) { |
+ bd0 = 0; |
+ bc.e0 += nz1; |
bigcomp(&rv, s0, &bc); |
+ y = word0(&rv) & Exp_mask; |
+ if (y == Exp_mask) |
+ goto ovfl; |
+ if (y == 0 && rv.d == 0.) |
+ goto undfl; |
+ } |
#endif |
#ifdef SET_INEXACT |
if (bc.inexact) { |
@@ -3473,7 +3614,7 @@ rv_alloc(int i) |
#ifdef KR_headers |
nrv_alloc(s, rve, n) char *s, **rve; int n; |
#else |
-nrv_alloc(CONST char *s, char **rve, int n) |
+nrv_alloc(const char *s, char **rve, int n) |
#endif |
{ |
char *rv, *t; |
@@ -3596,6 +3737,11 @@ dtoa |
U d2, eps, u; |
double ds; |
char *s, *s0; |
+#ifndef No_leftright |
+#ifdef IEEE_Arith |
+ U eps1; |
+#endif |
+#endif |
#ifdef SET_INEXACT |
int inexact, oldinexact; |
#endif |
@@ -3668,9 +3814,10 @@ dtoa |
#endif |
b = d2b(&u, &be, &bbits); |
+#ifdef Sudden_Underflow |
i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); |
-#ifndef Sudden_Underflow |
- if (i) { |
+#else |
+ if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) { |
#endif |
dval(&d2) = dval(&u); |
word0(&d2) &= Frac_mask1; |
@@ -3825,16 +3972,13 @@ dtoa |
} |
dval(&u) /= ds; |
} |
- else { |
- j1 = -k; |
- if (j1) { |
- dval(&u) *= tens[j1 & 0xf]; |
- for(j = j1 >> 4; j; j >>= 1, i++) |
- if (j & 1) { |
- ieps++; |
- dval(&u) *= bigtens[i]; |
- } |
- } |
+ else if ((j1 = -k)) { |
+ dval(&u) *= tens[j1 & 0xf]; |
+ for(j = j1 >> 4; j; j >>= 1, i++) |
+ if (j & 1) { |
+ ieps++; |
+ dval(&u) *= bigtens[i]; |
+ } |
} |
if (k_check && dval(&u) < 1. && ilim > 0) { |
if (ilim1 <= 0) |
@@ -3861,14 +4005,26 @@ dtoa |
* generating digits needed. |
*/ |
dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); |
+#ifdef IEEE_Arith |
+ if (k0 < 0 && j1 >= 307) { |
+ eps1.d = 1.01e256; /* 1.01 allows roundoff in the next few lines */ |
+ word0(&eps1) -= Exp_msk1 * (Bias+P-1); |
+ dval(&eps1) *= tens[j1 & 0xf]; |
+ for(i = 0, j = (j1-256) >> 4; j; j >>= 1, i++) |
+ if (j & 1) |
+ dval(&eps1) *= bigtens[i]; |
+ if (eps.d < eps1.d) |
+ eps.d = eps1.d; |
+ } |
+#endif |
for(i = 0;;) { |
- L = (long)dval(&u); |
+ L = dval(&u); |
dval(&u) -= L; |
- *s++ = '0' + (char)L; |
- if (dval(&u) < dval(&eps)) |
- goto ret1; |
+ *s++ = '0' + (int)L; |
if (1. - dval(&u) < dval(&eps)) |
goto bump_up; |
+ if (dval(&u) < dval(&eps)) |
+ goto ret1; |
if (++i >= ilim) |
break; |
dval(&eps) *= 10.; |
@@ -3916,7 +4072,7 @@ dtoa |
goto no_digits; |
goto one_digit; |
} |
- for(i = 1; i <= k + 1; i++, dval(&u) *= 10.) { |
+ for(i = 1;; i++, dval(&u) *= 10.) { |
L = (Long)(dval(&u) / ds); |
dval(&u) -= L*ds; |
#ifdef Check_FLT_ROUNDS |
@@ -3942,7 +4098,12 @@ dtoa |
} |
#endif |
dval(&u) += dval(&u); |
- if (dval(&u) > ds || (dval(&u) == ds && L & 1)) { |
+#ifdef ROUND_BIASED |
+ if (dval(&u) >= ds) |
+#else |
+ if (dval(&u) > ds || (dval(&u) == ds && L & 1)) |
+#endif |
+ { |
bump_up: |
while(*--s == '9') |
if (s == s0) { |
@@ -4027,16 +4188,6 @@ dtoa |
* and for all and pass them and a shift to quorem, so it |
* can do shifts and ors to compute the numerator for q. |
*/ |
-#ifdef Pack_32 |
- i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f; |
- if (i) |
- i = 32 - i; |
-#define iInc 28 |
-#else |
- if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) |
- i = 16 - i; |
-#define iInc 12 |
-#endif |
i = dshift(S, s2); |
b2 += i; |
m2 += i; |
@@ -4129,7 +4280,11 @@ dtoa |
if (j1 > 0) { |
b = lshift(b, 1); |
j1 = cmp(b, S); |
+#ifdef ROUND_BIASED |
+ if (j1 >= 0 /*)*/ |
+#else |
if ((j1 > 0 || (j1 == 0 && dig & 1)) |
+#endif |
&& dig++ == '9') |
goto round_9_up; |
} |
@@ -4190,7 +4345,12 @@ dtoa |
#endif |
b = lshift(b, 1); |
j = cmp(b, S); |
- if (j > 0 || (j == 0 && dig & 1)) { |
+#ifdef ROUND_BIASED |
+ if (j >= 0) |
+#else |
+ if (j > 0 || (j == 0 && dig & 1)) |
+#endif |
+ { |
roundoff: |
while(*--s == '9') |
if (s == s0) { |