diff --git a/nsprpub/pr/src/misc/Makefile.in b/nsprpub/pr/src/misc/Makefile.in index 114e110b2da0..5949d507b846 100644 --- a/nsprpub/pr/src/misc/Makefile.in +++ b/nsprpub/pr/src/misc/Makefile.in @@ -82,14 +82,6 @@ RELEASE_BINS = $(srcdir)/compile-et.pl $(srcdir)/prerr.properties include $(topsrcdir)/config/rules.mk -# An AIX Optimization bug causes PR_dtoa() to produce wrong result. -# This suppresses optimization for this single compilation unit. -ifeq ($(OS_ARCH), AIX) -$(OBJDIR)/prdtoa.o: prdtoa.c - @$(MAKE_OBJDIR) - $(CC) -o $@ -c $(filter-out -O, $(CFLAGS)) $< -endif - # # Generate prerr.h, prerr.c, and prerr.properties from prerr.et. # diff --git a/nsprpub/pr/src/misc/prdtoa.c b/nsprpub/pr/src/misc/prdtoa.c index c3b9840cff3c..ee5522293edb 100644 --- a/nsprpub/pr/src/misc/prdtoa.c +++ b/nsprpub/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 @@ -226,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] @@ -233,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 @@ -914,7 +933,7 @@ static double ulp(double x) } } #endif - return a; + return dval(a); } static double @@ -984,7 +1003,7 @@ ret_d: #undef d0 #undef d1 #endif - return d; + return dval(d); } static Bigint * @@ -1127,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 @@ -1138,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) @@ -1154,7 +1173,7 @@ ratio word0(db) += k*Exp_msk1; } #endif - return da / db; + return dval(da) / dval(db); } static CONST double @@ -1219,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; @@ -1341,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 @@ -1357,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 } @@ -1367,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 @@ -1398,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 @@ -1422,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; @@ -1444,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; @@ -1484,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) { @@ -1596,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 } @@ -1652,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) @@ -1670,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 @@ -1691,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 @@ -1707,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; @@ -1739,7 +1758,7 @@ retfree: ret: if (se) *se = (char *)s; - return sign ? -rv : rv; + return sign ? -dval(rv) : dval(rv); } static PRInt32 @@ -1972,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); @@ -1988,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 @@ -2038,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; } @@ -2117,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 */ @@ -2127,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++) @@ -2135,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; } @@ -2169,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; @@ -2208,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; } @@ -2220,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) { @@ -2249,7 +2268,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits, } break; } - if (!(d *= 10.)) + if (!(dval(d) *= 10.)) break; } goto ret1; @@ -2534,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;