|
@ -90,7 +90,7 @@ |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
#if defined(LIBC_SCCS) && !defined(lint) |
|
|
#if defined(LIBC_SCCS) && !defined(lint) |
|
|
static char *rcsid = "$OpenBSD: strtod.c,v 1.10 1998/08/11 22:04:29 niklas Exp $"; |
|
|
|
|
|
|
|
|
static char *rcsid = "$OpenBSD: strtod.c,v 1.11 1998/08/12 22:16:38 niklas Exp $"; |
|
|
#endif /* LIBC_SCCS and not lint */ |
|
|
#endif /* LIBC_SCCS and not lint */ |
|
|
|
|
|
|
|
|
#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ |
|
|
#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ |
|
@ -222,12 +222,17 @@ Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or |
|
|
IBM should be defined. |
|
|
IBM should be defined. |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
typedef union { |
|
|
|
|
|
double d; |
|
|
|
|
|
ULong ul[2]; |
|
|
|
|
|
} _double; |
|
|
|
|
|
#define value(x) ((x).d) |
|
|
#ifdef IEEE_LITTLE_ENDIAN |
|
|
#ifdef IEEE_LITTLE_ENDIAN |
|
|
#define word0(x) ((ULong *)&x)[1] |
|
|
|
|
|
#define word1(x) ((ULong *)&x)[0] |
|
|
|
|
|
|
|
|
#define word0(x) ((x).ul[1]) |
|
|
|
|
|
#define word1(x) ((x).ul[0]) |
|
|
#else |
|
|
#else |
|
|
#define word0(x) ((ULong *)&x)[0] |
|
|
|
|
|
#define word1(x) ((ULong *)&x)[1] |
|
|
|
|
|
|
|
|
#define word0(x) ((x).ul[0]) |
|
|
|
|
|
#define word1(x) ((x).ul[1]) |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
/* The following definition of Storeinc is appropriate for MIPS processors. |
|
|
/* The following definition of Storeinc is appropriate for MIPS processors. |
|
@ -909,14 +914,16 @@ diff |
|
|
static double |
|
|
static double |
|
|
ulp |
|
|
ulp |
|
|
#ifdef KR_headers |
|
|
#ifdef KR_headers |
|
|
(x) double x; |
|
|
|
|
|
|
|
|
(_x) double _x; |
|
|
#else |
|
|
#else |
|
|
(double x) |
|
|
|
|
|
|
|
|
(double _x) |
|
|
#endif |
|
|
#endif |
|
|
{ |
|
|
{ |
|
|
|
|
|
_double x; |
|
|
register Long L; |
|
|
register Long L; |
|
|
double a; |
|
|
|
|
|
|
|
|
_double a; |
|
|
|
|
|
|
|
|
|
|
|
value(x) = _x; |
|
|
L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; |
|
|
L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; |
|
|
#ifndef Sudden_Underflow |
|
|
#ifndef Sudden_Underflow |
|
|
if (L > 0) { |
|
|
if (L > 0) { |
|
@ -941,7 +948,7 @@ ulp |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
return a; |
|
|
|
|
|
|
|
|
return value(a); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static double |
|
|
static double |
|
@ -954,7 +961,7 @@ b2d |
|
|
{ |
|
|
{ |
|
|
ULong *xa, *xa0, w, y, z; |
|
|
ULong *xa, *xa0, w, y, z; |
|
|
int k; |
|
|
int k; |
|
|
double d; |
|
|
|
|
|
|
|
|
_double d; |
|
|
#ifdef VAX |
|
|
#ifdef VAX |
|
|
ULong d0, d1; |
|
|
ULong d0, d1; |
|
|
#else |
|
|
#else |
|
@ -1011,22 +1018,27 @@ b2d |
|
|
#undef d0 |
|
|
#undef d0 |
|
|
#undef d1 |
|
|
#undef d1 |
|
|
#endif |
|
|
#endif |
|
|
return d; |
|
|
|
|
|
|
|
|
return value(d); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static Bigint * |
|
|
static Bigint * |
|
|
d2b |
|
|
d2b |
|
|
#ifdef KR_headers |
|
|
#ifdef KR_headers |
|
|
(d, e, bits) double d; int *e, *bits; |
|
|
|
|
|
|
|
|
(_d, e, bits) double d; int *e, *bits; |
|
|
#else |
|
|
#else |
|
|
(double d, int *e, int *bits) |
|
|
|
|
|
|
|
|
(double _d, int *e, int *bits) |
|
|
#endif |
|
|
#endif |
|
|
{ |
|
|
{ |
|
|
Bigint *b; |
|
|
Bigint *b; |
|
|
int de, i, k; |
|
|
int de, i, k; |
|
|
ULong *x, y, z; |
|
|
ULong *x, y, z; |
|
|
|
|
|
_double d; |
|
|
#ifdef VAX |
|
|
#ifdef VAX |
|
|
ULong d0, d1; |
|
|
ULong d0, d1; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
value(d) = _d; |
|
|
|
|
|
#ifdef VAX |
|
|
d0 = word0(d) >> 16 | word0(d) << 16; |
|
|
d0 = word0(d) >> 16 | word0(d) << 16; |
|
|
d1 = word1(d) >> 16 | word1(d) << 16; |
|
|
d1 = word1(d) >> 16 | word1(d) << 16; |
|
|
#else |
|
|
#else |
|
@ -1151,11 +1163,11 @@ ratio |
|
|
(Bigint *a, Bigint *b) |
|
|
(Bigint *a, Bigint *b) |
|
|
#endif |
|
|
#endif |
|
|
{ |
|
|
{ |
|
|
double da, db; |
|
|
|
|
|
|
|
|
_double da, db; |
|
|
int k, ka, kb; |
|
|
int k, ka, kb; |
|
|
|
|
|
|
|
|
da = b2d(a, &ka); |
|
|
|
|
|
db = b2d(b, &kb); |
|
|
|
|
|
|
|
|
value(da) = b2d(a, &ka); |
|
|
|
|
|
value(db) = b2d(b, &kb); |
|
|
#ifdef Pack_32 |
|
|
#ifdef Pack_32 |
|
|
k = ka - kb + 32*(a->wds - b->wds); |
|
|
k = ka - kb + 32*(a->wds - b->wds); |
|
|
#else |
|
|
#else |
|
@ -1181,7 +1193,7 @@ ratio |
|
|
word0(db) += k*Exp_msk1; |
|
|
word0(db) += k*Exp_msk1; |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
return da / db; |
|
|
|
|
|
|
|
|
return value(da) / value(db); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static CONST double |
|
|
static CONST double |
|
@ -1221,7 +1233,8 @@ strtod |
|
|
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, |
|
|
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, 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; |
|
|
CONST char *s, *s0, *s1; |
|
|
double aadj, aadj1, adj, rv, rv0; |
|
|
|
|
|
|
|
|
double aadj, aadj1, adj; |
|
|
|
|
|
_double 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; |
|
@ -1233,7 +1246,7 @@ strtod |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
sign = nz0 = nz = 0; |
|
|
sign = nz0 = nz = 0; |
|
|
rv = 0.; |
|
|
|
|
|
|
|
|
value(rv) = 0.; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(s = s00; isspace((unsigned char) *s); s++) |
|
|
for(s = s00; isspace((unsigned char) *s); s++) |
|
@ -1350,9 +1363,9 @@ strtod |
|
|
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; |
|
|
rv = y; |
|
|
|
|
|
|
|
|
value(rv) = y; |
|
|
if (k > 9) |
|
|
if (k > 9) |
|
|
rv = tens[k - 9] * rv + z; |
|
|
|
|
|
|
|
|
value(rv) = tens[k - 9] * value(rv) + z; |
|
|
bd0 = 0; |
|
|
bd0 = 0; |
|
|
if (nd <= DBL_DIG |
|
|
if (nd <= DBL_DIG |
|
|
#ifndef RND_PRODQUOT |
|
|
#ifndef RND_PRODQUOT |
|
@ -1366,7 +1379,8 @@ strtod |
|
|
#ifdef VAX |
|
|
#ifdef VAX |
|
|
goto vax_ovfl_check; |
|
|
goto vax_ovfl_check; |
|
|
#else |
|
|
#else |
|
|
/* rv = */ rounded_product(rv, tens[e]); |
|
|
|
|
|
|
|
|
/* value(rv) = */ rounded_product(value(rv), |
|
|
|
|
|
tens[e]); |
|
|
goto ret; |
|
|
goto ret; |
|
|
#endif |
|
|
#endif |
|
|
} |
|
|
} |
|
@ -1376,27 +1390,30 @@ strtod |
|
|
* this for larger i values. |
|
|
* this for larger i values. |
|
|
*/ |
|
|
*/ |
|
|
e -= i; |
|
|
e -= i; |
|
|
rv *= tens[i]; |
|
|
|
|
|
|
|
|
value(rv) *= tens[i]; |
|
|
#ifdef VAX |
|
|
#ifdef VAX |
|
|
/* VAX exponent range is so narrow we must |
|
|
/* VAX exponent range is so narrow we must |
|
|
* worry about overflow here... |
|
|
* worry about overflow here... |
|
|
*/ |
|
|
*/ |
|
|
vax_ovfl_check: |
|
|
vax_ovfl_check: |
|
|
word0(rv) -= P*Exp_msk1; |
|
|
word0(rv) -= P*Exp_msk1; |
|
|
/* rv = */ rounded_product(rv, tens[e]); |
|
|
|
|
|
|
|
|
/* value(rv) = */ rounded_product(value(rv), |
|
|
|
|
|
tens[e]); |
|
|
if ((word0(rv) & Exp_mask) |
|
|
if ((word0(rv) & Exp_mask) |
|
|
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) |
|
|
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) |
|
|
goto ovfl; |
|
|
goto ovfl; |
|
|
word0(rv) += P*Exp_msk1; |
|
|
word0(rv) += P*Exp_msk1; |
|
|
#else |
|
|
#else |
|
|
/* rv = */ rounded_product(rv, tens[e]); |
|
|
|
|
|
|
|
|
/* value(rv) = */ rounded_product(value(rv), |
|
|
|
|
|
tens[e]); |
|
|
#endif |
|
|
#endif |
|
|
goto ret; |
|
|
goto ret; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
#ifndef Inaccurate_Divide |
|
|
#ifndef Inaccurate_Divide |
|
|
else if (e >= -Ten_pmax) { |
|
|
else if (e >= -Ten_pmax) { |
|
|
/* rv = */ rounded_quotient(rv, tens[-e]); |
|
|
|
|
|
|
|
|
/* value(rv) = */ rounded_quotient(value(rv), |
|
|
|
|
|
tens[-e]); |
|
|
goto ret; |
|
|
goto ret; |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
@ -1407,13 +1424,13 @@ strtod |
|
|
|
|
|
|
|
|
if (e1 > 0) { |
|
|
if (e1 > 0) { |
|
|
if (i = e1 & 15) |
|
|
if (i = e1 & 15) |
|
|
rv *= tens[i]; |
|
|
|
|
|
|
|
|
value(rv) *= tens[i]; |
|
|
if (e1 &= ~15) { |
|
|
if (e1 &= ~15) { |
|
|
if (e1 > DBL_MAX_10_EXP) { |
|
|
if (e1 > DBL_MAX_10_EXP) { |
|
|
ovfl: |
|
|
ovfl: |
|
|
errno = ERANGE; |
|
|
errno = ERANGE; |
|
|
#ifdef __STDC__ |
|
|
#ifdef __STDC__ |
|
|
rv = HUGE_VAL; |
|
|
|
|
|
|
|
|
value(rv) = HUGE_VAL; |
|
|
#else |
|
|
#else |
|
|
/* Can't trust HUGE_VAL */ |
|
|
/* Can't trust HUGE_VAL */ |
|
|
#ifdef IEEE_Arith |
|
|
#ifdef IEEE_Arith |
|
@ -1431,10 +1448,10 @@ strtod |
|
|
if (e1 >>= 4) { |
|
|
if (e1 >>= 4) { |
|
|
for(j = 0; e1 > 1; j++, e1 >>= 1) |
|
|
for(j = 0; e1 > 1; j++, e1 >>= 1) |
|
|
if (e1 & 1) |
|
|
if (e1 & 1) |
|
|
rv *= bigtens[j]; |
|
|
|
|
|
|
|
|
value(rv) *= bigtens[j]; |
|
|
/* The last multiplication could overflow. */ |
|
|
/* The last multiplication could overflow. */ |
|
|
word0(rv) -= P*Exp_msk1; |
|
|
word0(rv) -= P*Exp_msk1; |
|
|
rv *= bigtens[j]; |
|
|
|
|
|
|
|
|
value(rv) *= bigtens[j]; |
|
|
if ((z = word0(rv) & Exp_mask) |
|
|
if ((z = word0(rv) & Exp_mask) |
|
|
> Exp_msk1*(DBL_MAX_EXP+Bias-P)) |
|
|
> Exp_msk1*(DBL_MAX_EXP+Bias-P)) |
|
|
goto ovfl; |
|
|
goto ovfl; |
|
@ -1453,23 +1470,23 @@ strtod |
|
|
else if (e1 < 0) { |
|
|
else if (e1 < 0) { |
|
|
e1 = -e1; |
|
|
e1 = -e1; |
|
|
if (i = e1 & 15) |
|
|
if (i = e1 & 15) |
|
|
rv /= tens[i]; |
|
|
|
|
|
|
|
|
value(rv) /= tens[i]; |
|
|
if (e1 &= ~15) { |
|
|
if (e1 &= ~15) { |
|
|
e1 >>= 4; |
|
|
e1 >>= 4; |
|
|
if (e1 >= 1 << n_bigtens) |
|
|
if (e1 >= 1 << n_bigtens) |
|
|
goto undfl; |
|
|
goto undfl; |
|
|
for(j = 0; e1 > 1; j++, e1 >>= 1) |
|
|
for(j = 0; e1 > 1; j++, e1 >>= 1) |
|
|
if (e1 & 1) |
|
|
if (e1 & 1) |
|
|
rv *= tinytens[j]; |
|
|
|
|
|
|
|
|
value(rv) *= tinytens[j]; |
|
|
/* The last multiplication could underflow. */ |
|
|
/* The last multiplication could underflow. */ |
|
|
rv0 = rv; |
|
|
|
|
|
rv *= tinytens[j]; |
|
|
|
|
|
if (!rv) { |
|
|
|
|
|
rv = 2.*rv0; |
|
|
|
|
|
rv *= tinytens[j]; |
|
|
|
|
|
if (!rv) { |
|
|
|
|
|
|
|
|
value(rv0) = value(rv); |
|
|
|
|
|
value(rv) *= tinytens[j]; |
|
|
|
|
|
if (!value(rv)) { |
|
|
|
|
|
value(rv) = 2.*value(rv0); |
|
|
|
|
|
value(rv) *= tinytens[j]; |
|
|
|
|
|
if (!value(rv)) { |
|
|
undfl: |
|
|
undfl: |
|
|
rv = 0.; |
|
|
|
|
|
|
|
|
value(rv) = 0.; |
|
|
errno = ERANGE; |
|
|
errno = ERANGE; |
|
|
if (bd0) |
|
|
if (bd0) |
|
|
goto retfree; |
|
|
goto retfree; |
|
@ -1493,7 +1510,7 @@ strtod |
|
|
for(;;) { |
|
|
for(;;) { |
|
|
bd = Balloc(bd0->k); |
|
|
bd = Balloc(bd0->k); |
|
|
Bcopy(bd, bd0); |
|
|
Bcopy(bd, bd0); |
|
|
bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ |
|
|
|
|
|
|
|
|
bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ |
|
|
bs = i2b(1); |
|
|
bs = i2b(1); |
|
|
|
|
|
|
|
|
if (e >= 0) { |
|
|
if (e >= 0) { |
|
@ -1605,12 +1622,12 @@ strtod |
|
|
break; |
|
|
break; |
|
|
#endif |
|
|
#endif |
|
|
if (dsign) |
|
|
if (dsign) |
|
|
rv += ulp(rv); |
|
|
|
|
|
|
|
|
value(rv) += ulp(value(rv)); |
|
|
#ifndef ROUND_BIASED |
|
|
#ifndef ROUND_BIASED |
|
|
else { |
|
|
else { |
|
|
rv -= ulp(rv); |
|
|
|
|
|
|
|
|
value(rv) -= ulp(value(rv)); |
|
|
#ifndef Sudden_Underflow |
|
|
#ifndef Sudden_Underflow |
|
|
if (!rv) |
|
|
|
|
|
|
|
|
if (!value(rv)) |
|
|
goto undfl; |
|
|
goto undfl; |
|
|
#endif |
|
|
#endif |
|
|
} |
|
|
} |
|
@ -1661,10 +1678,10 @@ strtod |
|
|
/* Check for overflow */ |
|
|
/* Check for overflow */ |
|
|
|
|
|
|
|
|
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { |
|
|
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { |
|
|
rv0 = rv; |
|
|
|
|
|
|
|
|
value(rv0) = value(rv); |
|
|
word0(rv) -= P*Exp_msk1; |
|
|
word0(rv) -= P*Exp_msk1; |
|
|
adj = aadj1 * ulp(rv); |
|
|
|
|
|
rv += adj; |
|
|
|
|
|
|
|
|
adj = aadj1 * ulp(value(rv)); |
|
|
|
|
|
value(rv) += adj; |
|
|
if ((word0(rv) & Exp_mask) >= |
|
|
if ((word0(rv) & Exp_mask) >= |
|
|
Exp_msk1*(DBL_MAX_EXP+Bias-P)) { |
|
|
Exp_msk1*(DBL_MAX_EXP+Bias-P)) { |
|
|
if (word0(rv0) == Big0 && word1(rv0) == Big1) |
|
|
if (word0(rv0) == Big0 && word1(rv0) == Big1) |
|
@ -1679,10 +1696,10 @@ strtod |
|
|
else { |
|
|
else { |
|
|
#ifdef Sudden_Underflow |
|
|
#ifdef Sudden_Underflow |
|
|
if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { |
|
|
if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { |
|
|
rv0 = rv; |
|
|
|
|
|
|
|
|
value(rv0) = value(rv); |
|
|
word0(rv) += P*Exp_msk1; |
|
|
word0(rv) += P*Exp_msk1; |
|
|
adj = aadj1 * ulp(rv); |
|
|
|
|
|
rv += adj; |
|
|
|
|
|
|
|
|
adj = aadj1 * ulp(value(rv)); |
|
|
|
|
|
value(rv) += adj; |
|
|
#ifdef IBM |
|
|
#ifdef IBM |
|
|
if ((word0(rv) & Exp_mask) < P*Exp_msk1) |
|
|
if ((word0(rv) & Exp_mask) < P*Exp_msk1) |
|
|
#else |
|
|
#else |
|
@ -1700,8 +1717,8 @@ strtod |
|
|
word0(rv) -= P*Exp_msk1; |
|
|
word0(rv) -= P*Exp_msk1; |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
adj = aadj1 * ulp(rv); |
|
|
|
|
|
rv += adj; |
|
|
|
|
|
|
|
|
adj = aadj1 * ulp(value(rv)); |
|
|
|
|
|
value(rv) += adj; |
|
|
} |
|
|
} |
|
|
#else |
|
|
#else |
|
|
/* Compute adj so that the IEEE rounding rules will |
|
|
/* Compute adj so that the IEEE rounding rules will |
|
@ -1716,8 +1733,8 @@ strtod |
|
|
if (!dsign) |
|
|
if (!dsign) |
|
|
aadj1 = -aadj1; |
|
|
aadj1 = -aadj1; |
|
|
} |
|
|
} |
|
|
adj = aadj1 * ulp(rv); |
|
|
|
|
|
rv += adj; |
|
|
|
|
|
|
|
|
adj = aadj1 * ulp(value(rv)); |
|
|
|
|
|
value(rv) += adj; |
|
|
#endif |
|
|
#endif |
|
|
} |
|
|
} |
|
|
z = word0(rv) & Exp_mask; |
|
|
z = word0(rv) & Exp_mask; |
|
@ -1748,7 +1765,7 @@ strtod |
|
|
ret: |
|
|
ret: |
|
|
if (se) |
|
|
if (se) |
|
|
*se = (char *)s; |
|
|
*se = (char *)s; |
|
|
return sign ? -rv : rv; |
|
|
|
|
|
|
|
|
return sign ? -value(rv) : value(rv); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static int |
|
|
static int |
|
@ -1894,10 +1911,10 @@ quorem |
|
|
char * |
|
|
char * |
|
|
__dtoa |
|
|
__dtoa |
|
|
#ifdef KR_headers |
|
|
#ifdef KR_headers |
|
|
(d, mode, ndigits, decpt, sign, rve) |
|
|
|
|
|
double d; int mode, ndigits, *decpt, *sign; char **rve; |
|
|
|
|
|
|
|
|
(_d, mode, ndigits, decpt, sign, rve) |
|
|
|
|
|
double _d; int mode, ndigits, *decpt, *sign; char **rve; |
|
|
#else |
|
|
#else |
|
|
(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) |
|
|
|
|
|
|
|
|
(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve) |
|
|
#endif |
|
|
#endif |
|
|
{ |
|
|
{ |
|
|
/* Arguments ndigits, decpt, sign are similar to those |
|
|
/* Arguments ndigits, decpt, sign are similar to those |
|
@ -1943,11 +1960,13 @@ __dtoa |
|
|
ULong x; |
|
|
ULong x; |
|
|
#endif |
|
|
#endif |
|
|
Bigint *b, *b1, *delta, *mlo, *mhi, *S; |
|
|
Bigint *b, *b1, *delta, *mlo, *mhi, *S; |
|
|
double d2, ds, eps; |
|
|
|
|
|
|
|
|
double ds; |
|
|
char *s, *s0; |
|
|
char *s, *s0; |
|
|
static Bigint *result; |
|
|
static Bigint *result; |
|
|
static int result_k; |
|
|
static int result_k; |
|
|
|
|
|
_double d, d2, eps; |
|
|
|
|
|
|
|
|
|
|
|
value(d) = _d; |
|
|
if (result) { |
|
|
if (result) { |
|
|
result->k = result_k; |
|
|
result->k = result_k; |
|
|
result->maxwds = 1 << result_k; |
|
|
result->maxwds = 1 << result_k; |
|
@ -1987,9 +2006,9 @@ __dtoa |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
#ifdef IBM |
|
|
#ifdef IBM |
|
|
d += 0; /* normalize */ |
|
|
|
|
|
|
|
|
value(d) += 0; /* normalize */ |
|
|
#endif |
|
|
#endif |
|
|
if (!d) { |
|
|
|
|
|
|
|
|
if (!value(d)) { |
|
|
*decpt = 1; |
|
|
*decpt = 1; |
|
|
s = "0"; |
|
|
s = "0"; |
|
|
if (rve) |
|
|
if (rve) |
|
@ -1997,22 +2016,18 @@ __dtoa |
|
|
return s; |
|
|
return s; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
b = d2b(d, &be, &bbits); |
|
|
|
|
|
|
|
|
b = d2b(value(d), &be, &bbits); |
|
|
#ifdef Sudden_Underflow |
|
|
#ifdef Sudden_Underflow |
|
|
i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); |
|
|
i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); |
|
|
#else |
|
|
#else |
|
|
if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) { |
|
|
if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) { |
|
|
#endif |
|
|
#endif |
|
|
d2 = d; |
|
|
|
|
|
#ifdef __GNUC__ |
|
|
|
|
|
/* Do not move instructions depending on d2 over this line. */ |
|
|
|
|
|
__asm__ __volatile__ ("" : : "X" (d2) : "memory"); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
value(d2) = value(d); |
|
|
word0(d2) &= Frac_mask1; |
|
|
word0(d2) &= Frac_mask1; |
|
|
word0(d2) |= Exp_11; |
|
|
word0(d2) |= Exp_11; |
|
|
#ifdef IBM |
|
|
#ifdef IBM |
|
|
if (j = 11 - hi0bits(word0(d2) & Frac_mask)) |
|
|
if (j = 11 - hi0bits(word0(d2) & Frac_mask)) |
|
|
d2 /= 1 << j; |
|
|
|
|
|
|
|
|
value(d2) /= 1 << j; |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5 |
|
|
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5 |
|
@ -2051,19 +2066,20 @@ __dtoa |
|
|
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(d) << 64 - i | word1(d) >> i - 32 |
|
|
: word1(d) << 32 - i; |
|
|
: word1(d) << 32 - i; |
|
|
d2 = x; |
|
|
|
|
|
|
|
|
value(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; |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; |
|
|
|
|
|
|
|
|
ds = (value(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 (d < tens[k]) |
|
|
|
|
|
|
|
|
if (value(d) < tens[k]) |
|
|
k--; |
|
|
k--; |
|
|
k_check = 0; |
|
|
k_check = 0; |
|
|
} |
|
|
} |
|
@ -2130,7 +2146,7 @@ __dtoa |
|
|
/* Try to get by with floating-point arithmetic. */ |
|
|
/* Try to get by with floating-point arithmetic. */ |
|
|
|
|
|
|
|
|
i = 0; |
|
|
i = 0; |
|
|
d2 = d; |
|
|
|
|
|
|
|
|
value(d2) = value(d); |
|
|
k0 = k; |
|
|
k0 = k; |
|
|
ilim0 = ilim; |
|
|
ilim0 = ilim; |
|
|
ieps = 2; /* conservative */ |
|
|
ieps = 2; /* conservative */ |
|
@ -2140,7 +2156,7 @@ __dtoa |
|
|
if (j & Bletch) { |
|
|
if (j & Bletch) { |
|
|
/* prevent overflows */ |
|
|
/* prevent overflows */ |
|
|
j &= Bletch - 1; |
|
|
j &= Bletch - 1; |
|
|
d /= bigtens[n_bigtens-1]; |
|
|
|
|
|
|
|
|
value(d) /= bigtens[n_bigtens-1]; |
|
|
ieps++; |
|
|
ieps++; |
|
|
} |
|
|
} |
|
|
for(; j; j >>= 1, i++) |
|
|
for(; j; j >>= 1, i++) |
|
@ -2148,32 +2164,32 @@ __dtoa |
|
|
ieps++; |
|
|
ieps++; |
|
|
ds *= bigtens[i]; |
|
|
ds *= bigtens[i]; |
|
|
} |
|
|
} |
|
|
d /= ds; |
|
|
|
|
|
|
|
|
value(d) /= ds; |
|
|
} |
|
|
} |
|
|
else if (j1 = -k) { |
|
|
else if (j1 = -k) { |
|
|
d *= tens[j1 & 0xf]; |
|
|
|
|
|
|
|
|
value(d) *= 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++; |
|
|
d *= bigtens[i]; |
|
|
|
|
|
|
|
|
value(d) *= bigtens[i]; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if (k_check && d < 1. && ilim > 0) { |
|
|
|
|
|
|
|
|
if (k_check && value(d) < 1. && ilim > 0) { |
|
|
if (ilim1 <= 0) |
|
|
if (ilim1 <= 0) |
|
|
goto fast_failed; |
|
|
goto fast_failed; |
|
|
ilim = ilim1; |
|
|
ilim = ilim1; |
|
|
k--; |
|
|
k--; |
|
|
d *= 10.; |
|
|
|
|
|
|
|
|
value(d) *= 10.; |
|
|
ieps++; |
|
|
ieps++; |
|
|
} |
|
|
} |
|
|
eps = ieps*d + 7.; |
|
|
|
|
|
|
|
|
value(eps) = ieps*value(d) + 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; |
|
|
d -= 5.; |
|
|
|
|
|
if (d > eps) |
|
|
|
|
|
|
|
|
value(d) -= 5.; |
|
|
|
|
|
if (value(d) > value(eps)) |
|
|
goto one_digit; |
|
|
goto one_digit; |
|
|
if (d < -eps) |
|
|
|
|
|
|
|
|
if (value(d) < -value(eps)) |
|
|
goto no_digits; |
|
|
goto no_digits; |
|
|
goto fast_failed; |
|
|
goto fast_failed; |
|
|
} |
|
|
} |
|
@ -2182,33 +2198,33 @@ __dtoa |
|
|
/* Use Steele & White method of only |
|
|
/* Use Steele & White method of only |
|
|
* generating digits needed. |
|
|
* generating digits needed. |
|
|
*/ |
|
|
*/ |
|
|
eps = 0.5/tens[ilim-1] - eps; |
|
|
|
|
|
|
|
|
value(eps) = 0.5/tens[ilim-1] - value(eps); |
|
|
for(i = 0;;) { |
|
|
for(i = 0;;) { |
|
|
L = d; |
|
|
|
|
|
d -= L; |
|
|
|
|
|
|
|
|
L = value(d); |
|
|
|
|
|
value(d) -= L; |
|
|
*s++ = '0' + (int)L; |
|
|
*s++ = '0' + (int)L; |
|
|
if (d < eps) |
|
|
|
|
|
|
|
|
if (value(d) < value(eps)) |
|
|
goto ret1; |
|
|
goto ret1; |
|
|
if (1. - d < eps) |
|
|
|
|
|
|
|
|
if (1. - value(d) < value(eps)) |
|
|
goto bump_up; |
|
|
goto bump_up; |
|
|
if (++i >= ilim) |
|
|
if (++i >= ilim) |
|
|
break; |
|
|
break; |
|
|
eps *= 10.; |
|
|
|
|
|
d *= 10.; |
|
|
|
|
|
|
|
|
value(eps) *= 10.; |
|
|
|
|
|
value(d) *= 10.; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
#endif |
|
|
#endif |
|
|
/* Generate ilim digits, then fix them up. */ |
|
|
/* Generate ilim digits, then fix them up. */ |
|
|
eps *= tens[ilim-1]; |
|
|
|
|
|
for(i = 1;; i++, d *= 10.) { |
|
|
|
|
|
L = d; |
|
|
|
|
|
d -= L; |
|
|
|
|
|
|
|
|
value(eps) *= tens[ilim-1]; |
|
|
|
|
|
for(i = 1;; i++, value(d) *= 10.) { |
|
|
|
|
|
L = value(d); |
|
|
|
|
|
value(d) -= L; |
|
|
*s++ = '0' + (int)L; |
|
|
*s++ = '0' + (int)L; |
|
|
if (i == ilim) { |
|
|
if (i == ilim) { |
|
|
if (d > 0.5 + eps) |
|
|
|
|
|
|
|
|
if (value(d) > 0.5 + value(eps)) |
|
|
goto bump_up; |
|
|
goto bump_up; |
|
|
else if (d < 0.5 - eps) { |
|
|
|
|
|
|
|
|
else if (value(d) < 0.5 - value(eps)) { |
|
|
while(*--s == '0'); |
|
|
while(*--s == '0'); |
|
|
s++; |
|
|
s++; |
|
|
goto ret1; |
|
|
goto ret1; |
|
@ -2221,7 +2237,7 @@ __dtoa |
|
|
#endif |
|
|
#endif |
|
|
fast_failed: |
|
|
fast_failed: |
|
|
s = s0; |
|
|
s = s0; |
|
|
d = d2; |
|
|
|
|
|
|
|
|
value(d) = value(d2); |
|
|
k = k0; |
|
|
k = k0; |
|
|
ilim = ilim0; |
|
|
ilim = ilim0; |
|
|
} |
|
|
} |
|
@ -2233,24 +2249,24 @@ __dtoa |
|
|
ds = tens[k]; |
|
|
ds = tens[k]; |
|
|
if (ndigits < 0 && ilim <= 0) { |
|
|
if (ndigits < 0 && ilim <= 0) { |
|
|
S = mhi = 0; |
|
|
S = mhi = 0; |
|
|
if (ilim < 0 || d <= 5*ds) |
|
|
|
|
|
|
|
|
if (ilim < 0 || value(d) <= 5*ds) |
|
|
goto no_digits; |
|
|
goto no_digits; |
|
|
goto one_digit; |
|
|
goto one_digit; |
|
|
} |
|
|
} |
|
|
for(i = 1;; i++) { |
|
|
for(i = 1;; i++) { |
|
|
L = d / ds; |
|
|
|
|
|
d -= L*ds; |
|
|
|
|
|
|
|
|
L = value(d) / ds; |
|
|
|
|
|
value(d) -= 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 (d < 0) { |
|
|
|
|
|
|
|
|
if (value(d) < 0) { |
|
|
L--; |
|
|
L--; |
|
|
d += ds; |
|
|
|
|
|
|
|
|
value(d) += ds; |
|
|
} |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
*s++ = '0' + (int)L; |
|
|
*s++ = '0' + (int)L; |
|
|
if (i == ilim) { |
|
|
if (i == ilim) { |
|
|
d += d; |
|
|
|
|
|
if (d > ds || d == ds && L & 1) { |
|
|
|
|
|
|
|
|
value(d) += value(d); |
|
|
|
|
|
if (value(d) > ds || value(d) == ds && L & 1) { |
|
|
bump_up: |
|
|
bump_up: |
|
|
while(*--s == '9') |
|
|
while(*--s == '9') |
|
|
if (s == s0) { |
|
|
if (s == s0) { |
|
@ -2262,7 +2278,7 @@ __dtoa |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
if (!(d *= 10.)) |
|
|
|
|
|
|
|
|
if (!(value(d) *= 10.)) |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
goto ret1; |
|
|
goto ret1; |
|
|