summaryrefslogtreecommitdiff
path: root/pr/src/misc/prdtoa.c
diff options
context:
space:
mode:
Diffstat (limited to 'pr/src/misc/prdtoa.c')
-rw-r--r--pr/src/misc/prdtoa.c209
1 files changed, 124 insertions, 85 deletions
diff --git a/pr/src/misc/prdtoa.c b/pr/src/misc/prdtoa.c
index e2e715fe..ee552229 100644
--- a/pr/src/misc/prdtoa.c
+++ b/pr/src/misc/prdtoa.c
@@ -123,6 +123,11 @@
* if memory is available and otherwise does something you deem
* appropriate. If MALLOC is undefined, malloc will be invoked
* directly -- and assumed always to succeed.
+ * #define YES_ALIAS to permit aliasing certain double values with
+ * arrays of unsigned Longs. This leads to slightly better code with
+ * some compilers and was always used prior to 19990916, but it
+ * is not strictly legal and can cause trouble with aggressively
+ * optimizing compilers (e.g., gcc 2.95.1 under -O2).
*/
#if defined(IS_LITTLE_ENDIAN)
#define IEEE_8087
@@ -197,6 +202,16 @@ extern void *MALLOC(size_t);
#endif
#else
#include "float.h"
+/*
+ * MacOS 10.2 defines the macro FLT_ROUNDS to an internal function
+ * which does not exist on 10.1. We can safely #define it to 1 here
+ * to allow 10.2 builds to run on 10.1, since we can't use fesetround()
+ * (which does not exist on 10.1 either).
+ */
+#if defined(MACOS_DEPLOYMENT_TARGET) && (MACOS_DEPLOYMENT_TARGET < 100200)
+#undef FLT_ROUNDS
+#define FLT_ROUNDS 1
+#endif
#endif
#ifndef __MATH_H__
#include "math.h"
@@ -216,6 +231,10 @@ extern void *MALLOC(size_t);
Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
#endif
+typedef union { double d; unsigned Long L[2]; } U;
+
+#ifdef YES_ALIAS
+#define dval(x) x
#ifdef IEEE_8087
#define word0(x) ((unsigned Long *)&x)[1]
#define word1(x) ((unsigned Long *)&x)[0]
@@ -223,6 +242,16 @@ Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
#define word0(x) ((unsigned Long *)&x)[0]
#define word1(x) ((unsigned Long *)&x)[1]
#endif
+#else
+#ifdef IEEE_8087
+#define word0(x) ((U*)&x)->L[1]
+#define word1(x) ((U*)&x)->L[0]
+#else
+#define word0(x) ((U*)&x)->L[0]
+#define word1(x) ((U*)&x)->L[1]
+#endif
+#define dval(x) ((U*)&x)->d
+#endif
/* The following definition of Storeinc is appropriate for MIPS processors.
* An alternative that might be better on some machines is
@@ -904,7 +933,7 @@ static double ulp(double x)
}
}
#endif
- return a;
+ return dval(a);
}
static double
@@ -974,7 +1003,7 @@ ret_d:
#undef d0
#undef d1
#endif
- return d;
+ return dval(d);
}
static Bigint *
@@ -1117,8 +1146,8 @@ ratio
double da, db;
PRInt32 k, ka, kb;
- da = b2d(a, &ka);
- db = b2d(b, &kb);
+ dval(da) = b2d(a, &ka);
+ dval(db) = b2d(b, &kb);
#ifdef Pack_32
k = ka - kb + 32*(a->wds - b->wds);
#else
@@ -1128,13 +1157,13 @@ ratio
if (k > 0) {
word0(da) += (k >> 2)*Exp_msk1;
if (k &= 3)
- da *= 1 << k;
+ dval(da) *= 1 << k;
}
else {
k = -k;
word0(db) += (k >> 2)*Exp_msk1;
if (k &= 3)
- db *= 1 << k;
+ dval(db) *= 1 << k;
}
#else
if (k > 0)
@@ -1144,7 +1173,7 @@ ratio
word0(db) += k*Exp_msk1;
}
#endif
- return da / db;
+ return dval(da) / dval(db);
}
static CONST double
@@ -1180,6 +1209,16 @@ void _PR_InitDtoa(void)
p5s_lock = PR_NewLock();
}
+void _PR_CleanupDtoa(void)
+{
+ PR_DestroyLock(freelist_lock);
+ freelist_lock = NULL;
+ PR_DestroyLock(p5s_lock);
+ p5s_lock = NULL;
+
+ /* FIXME: deal with freelist and p5s. */
+}
+
#if defined(HAVE_WATCOM_BUG_1)
PRFloat64 __pascal __loadds __export
#else
@@ -1199,7 +1238,7 @@ PR_strtod(CONST char *s00, char **se)
if (!_pr_initialized) _PR_ImplicitInitialization();
sign = nz0 = nz = 0;
- rv = 0.;
+ dval(rv) = 0.;
for(s = s00;;s++) switch(*s) {
case '-':
sign = 1;
@@ -1321,9 +1360,9 @@ dig_done:
if (!nd0)
nd0 = nd;
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
- rv = y;
+ dval(rv) = y;
if (k > 9)
- rv = tens[k - 9] * rv + z;
+ dval(rv) = tens[k - 9] * dval(rv) + z;
bd0 = 0;
if (nd <= DBL_DIG
#ifndef RND_PRODQUOT
@@ -1337,7 +1376,7 @@ dig_done:
#ifdef VAX
goto vax_ovfl_check;
#else
- /* rv = */ rounded_product(rv, tens[e]);
+ /* rv = */ rounded_product(dval(rv), tens[e]);
goto ret;
#endif
}
@@ -1347,27 +1386,27 @@ dig_done:
* this for larger i values.
*/
e -= i;
- rv *= tens[i];
+ dval(rv) *= tens[i];
#ifdef VAX
/* VAX exponent range is so narrow we must
* worry about overflow here...
*/
vax_ovfl_check:
word0(rv) -= P*Exp_msk1;
- /* rv = */ rounded_product(rv, tens[e]);
+ /* rv = */ rounded_product(dval(rv), tens[e]);
if ((word0(rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
goto ovfl;
word0(rv) += P*Exp_msk1;
#else
- /* rv = */ rounded_product(rv, tens[e]);
+ /* rv = */ rounded_product(dval(rv), tens[e]);
#endif
goto ret;
}
}
#ifndef Inaccurate_Divide
else if (e >= -Ten_pmax) {
- /* rv = */ rounded_quotient(rv, tens[-e]);
+ /* rv = */ rounded_quotient(dval(rv), tens[-e]);
goto ret;
}
#endif
@@ -1378,13 +1417,13 @@ dig_done:
if (e1 > 0) {
if ((i = e1 & 15) != 0)
- rv *= tens[i];
+ dval(rv) *= tens[i];
if (e1 &= ~15) {
if (e1 > DBL_MAX_10_EXP) {
ovfl:
PR_SetError(PR_RANGE_ERROR, 0);
#ifdef __STDC__
- rv = HUGE_VAL;
+ dval(rv) = HUGE_VAL;
#else
/* Can't trust HUGE_VAL */
#ifdef IEEE_Arith
@@ -1402,10 +1441,10 @@ dig_done:
if (e1 >>= 4) {
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- rv *= bigtens[j];
+ dval(rv) *= bigtens[j];
/* The last multiplication could overflow. */
word0(rv) -= P*Exp_msk1;
- rv *= bigtens[j];
+ dval(rv) *= bigtens[j];
if ((z = word0(rv) & Exp_mask)
> Exp_msk1*(DBL_MAX_EXP+Bias-P))
goto ovfl;
@@ -1424,23 +1463,23 @@ dig_done:
else if (e1 < 0) {
e1 = -e1;
if ((i = e1 & 15) != 0)
- rv /= tens[i];
+ dval(rv) /= tens[i];
if (e1 &= ~15) {
e1 >>= 4;
if (e1 >= 1 << n_bigtens)
goto undfl;
for(j = 0; e1 > 1; j++, e1 >>= 1)
if (e1 & 1)
- rv *= tinytens[j];
+ dval(rv) *= tinytens[j];
/* The last multiplication could underflow. */
- rv0 = rv;
- rv *= tinytens[j];
- if (!rv) {
- rv = 2.*rv0;
- rv *= tinytens[j];
- if (!rv) {
+ dval(rv0) = dval(rv);
+ dval(rv) *= tinytens[j];
+ if (!dval(rv)) {
+ dval(rv) = 2.*dval(rv0);
+ dval(rv) *= tinytens[j];
+ if (!dval(rv)) {
undfl:
- rv = 0.;
+ dval(rv) = 0.;
PR_SetError(PR_RANGE_ERROR, 0);
if (bd0)
goto retfree;
@@ -1464,7 +1503,7 @@ dig_done:
for(;;) {
bd = Balloc(bd0->k);
Bcopy(bd, bd0);
- bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
+ bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
bs = i2b(1);
if (e >= 0) {
@@ -1576,12 +1615,12 @@ dig_done:
break;
#endif
if (dsign)
- rv += ulp(rv);
+ dval(rv) += ulp(dval(rv));
#ifndef ROUND_BIASED
else {
- rv -= ulp(rv);
+ dval(rv) -= ulp(dval(rv));
#ifndef Sudden_Underflow
- if (!rv)
+ if (!dval(rv))
goto undfl;
#endif
}
@@ -1632,10 +1671,10 @@ dig_done:
/* Check for overflow */
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
- rv0 = rv;
+ dval(rv0) = dval(rv);
word0(rv) -= P*Exp_msk1;
- adj = aadj1 * ulp(rv);
- rv += adj;
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
if ((word0(rv) & Exp_mask) >=
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
if (word0(rv0) == Big0 && word1(rv0) == Big1)
@@ -1650,10 +1689,10 @@ dig_done:
else {
#ifdef Sudden_Underflow
if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
- rv0 = rv;
+ dval(rv0) = dval(rv);
word0(rv) += P*Exp_msk1;
- adj = aadj1 * ulp(rv);
- rv += adj;
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
#ifdef IBM
if ((word0(rv) & Exp_mask) < P*Exp_msk1)
#else
@@ -1671,8 +1710,8 @@ dig_done:
word0(rv) -= P*Exp_msk1;
}
else {
- adj = aadj1 * ulp(rv);
- rv += adj;
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
}
#else
/* Compute adj so that the IEEE rounding rules will
@@ -1687,8 +1726,8 @@ dig_done:
if (!dsign)
aadj1 = -aadj1;
}
- adj = aadj1 * ulp(rv);
- rv += adj;
+ adj = aadj1 * ulp(dval(rv));
+ dval(rv) += adj;
#endif
}
z = word0(rv) & Exp_mask;
@@ -1719,7 +1758,7 @@ retfree:
ret:
if (se)
*se = (char *)s;
- return sign ? -rv : rv;
+ return sign ? -dval(rv) : dval(rv);
}
static PRInt32
@@ -1952,9 +1991,9 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
}
#endif
#ifdef IBM
- d += 0; /* normalize */
+ dval(d) += 0; /* normalize */
#endif
- if (!d) {
+ if (!dval(d)) {
*decpt = 1;
if (bufsize < 2) {
PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
@@ -1968,18 +2007,18 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
return PR_SUCCESS;
}
- b = d2b(d, &be, &bbits);
+ b = d2b(dval(d), &be, &bbits);
#ifdef Sudden_Underflow
i = (PRInt32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
#else
if ((i = (PRInt32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
#endif
- d2 = d;
+ dval(d2) = dval(d);
word0(d2) &= Frac_mask1;
word0(d2) |= Exp_11;
#ifdef IBM
if (j = 11 - hi0bits(word0(d2) & Frac_mask))
- d2 /= 1 << j;
+ dval(d2) /= 1 << j;
#endif
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
@@ -2018,19 +2057,19 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
i = bbits + be + (Bias + (P-1) - 1);
x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32)
: word1(d) << (32 - i);
- d2 = x;
+ dval(d2) = x;
word0(d2) -= 31*Exp_msk1; /* adjust exponent */
i -= (Bias + (P-1) - 1) + 1;
denorm = 1;
}
#endif
- ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
k = (PRInt32)ds;
if (ds < 0. && ds != k)
k--; /* want k = floor(ds) */
k_check = 1;
if (k >= 0 && k <= Ten_pmax) {
- if (d < tens[k])
+ if (dval(d) < tens[k])
k--;
k_check = 0;
}
@@ -2097,7 +2136,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
/* Try to get by with floating-point arithmetic. */
i = 0;
- d2 = d;
+ dval(d2) = dval(d);
k0 = k;
ilim0 = ilim;
ieps = 2; /* conservative */
@@ -2107,7 +2146,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
if (j & Bletch) {
/* prevent overflows */
j &= Bletch - 1;
- d /= bigtens[n_bigtens-1];
+ dval(d) /= bigtens[n_bigtens-1];
ieps++;
}
for(; j; j >>= 1, i++)
@@ -2115,32 +2154,32 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
ieps++;
ds *= bigtens[i];
}
- d /= ds;
+ dval(d) /= ds;
}
else if ((j1 = -k) != 0) {
- d *= tens[j1 & 0xf];
+ dval(d) *= tens[j1 & 0xf];
for(j = j1 >> 4; j; j >>= 1, i++)
if (j & 1) {
ieps++;
- d *= bigtens[i];
+ dval(d) *= bigtens[i];
}
}
- if (k_check && d < 1. && ilim > 0) {
+ if (k_check && dval(d) < 1. && ilim > 0) {
if (ilim1 <= 0)
goto fast_failed;
ilim = ilim1;
k--;
- d *= 10.;
+ dval(d) *= 10.;
ieps++;
}
- eps = ieps*d + 7.;
+ dval(eps) = ieps*dval(d) + 7.;
word0(eps) -= (P-1)*Exp_msk1;
if (ilim == 0) {
S = mhi = 0;
- d -= 5.;
- if (d > eps)
+ dval(d) -= 5.;
+ if (dval(d) > dval(eps))
goto one_digit;
- if (d < -eps)
+ if (dval(d) < -dval(eps))
goto no_digits;
goto fast_failed;
}
@@ -2149,33 +2188,33 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
/* Use Steele & White method of only
* generating digits needed.
*/
- eps = 0.5/tens[ilim-1] - eps;
+ dval(eps) = 0.5/tens[ilim-1] - dval(eps);
for(i = 0;;) {
- L = (Long) d;
- d -= L;
+ L = (Long) (dval(d));
+ dval(d) -= L;
*s++ = '0' + (PRInt32)L;
- if (d < eps)
+ if (dval(d) < dval(eps))
goto ret1;
- if (1. - d < eps)
+ if (1. - dval(d) < dval(eps))
goto bump_up;
if (++i >= ilim)
break;
- eps *= 10.;
- d *= 10.;
+ dval(eps) *= 10.;
+ dval(d) *= 10.;
}
}
else {
#endif
/* Generate ilim digits, then fix them up. */
- eps *= tens[ilim-1];
- for(i = 1;; i++, d *= 10.) {
- L = (Long) d;
- d -= L;
+ dval(eps) *= tens[ilim-1];
+ for(i = 1;; i++, dval(d) *= 10.) {
+ L = (Long) (dval(d));
+ dval(d) -= L;
*s++ = '0' + (PRInt32)L;
if (i == ilim) {
- if (d > 0.5 + eps)
+ if (dval(d) > 0.5 + dval(eps))
goto bump_up;
- else if (d < 0.5 - eps) {
+ else if (dval(d) < 0.5 - dval(eps)) {
while(*--s == '0'){} /* just count -- nothing to execute */
s++;
goto ret1;
@@ -2188,7 +2227,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
#endif
fast_failed:
s = s0;
- d = d2;
+ dval(d) = dval(d2);
k = k0;
ilim = ilim0;
}
@@ -2200,24 +2239,24 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
ds = tens[k];
if (ndigits < 0 && ilim <= 0) {
S = mhi = 0;
- if (ilim < 0 || d <= 5*ds)
+ if (ilim < 0 || dval(d) <= 5*ds)
goto no_digits;
goto one_digit;
}
for(i = 1;; i++) {
- L = (Long) (d / ds);
- d -= L*ds;
+ L = (Long) (dval(d) / ds);
+ dval(d) -= L*ds;
#ifdef Check_FLT_ROUNDS
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
- if (d < 0) {
+ if (dval(d) < 0) {
L--;
- d += ds;
+ dval(d) += ds;
}
#endif
*s++ = '0' + (PRInt32)L;
if (i == ilim) {
- d += d;
- if ((d > ds) || (d == ds && L & 1)) {
+ dval(d) += dval(d);
+ if ((dval(d) > ds) || (dval(d) == ds && L & 1)) {
bump_up:
while(*--s == '9')
if (s == s0) {
@@ -2229,7 +2268,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
}
break;
}
- if (!(d *= 10.))
+ if (!(dval(d) *= 10.))
break;
}
goto ret1;
@@ -2514,7 +2553,7 @@ PR_cnvtf(char *buf,int bufsz, int prcsn,double fval)
return;
}
/* XXX Why use mode 1? */
- if (PR_dtoa(fval,1,prcsn,&decpt,&sign,&endnum,num,bufsz)
+ if (PR_dtoa(dval(fval),1,prcsn,&decpt,&sign,&endnum,num,bufsz)
== PR_FAILURE) {
buf[0] = '\0';
goto done;