0001: /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
0002: *
0003: * The contents of this file are subject to the Netscape Public
0004: * License Version 1.1 (the "License"); you may not use this file
0005: * except in compliance with the License. You may obtain a copy of
0006: * the License at http://www.mozilla.org/NPL/
0007: *
0008: * Software distributed under the License is distributed on an "AS
0009: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
0010: * implied. See the License for the specific language governing
0011: * rights and limitations under the License.
0012: *
0013: * The Original Code is Rhino code, released
0014: * May 6, 1999.
0015: *
0016: * The Initial Developer of the Original Code is Netscape
0017: * Communications Corporation. Portions created by Netscape are
0018: * Copyright (C) 1997-1999 Netscape Communications Corporation. All
0019: * Rights Reserved.
0020: *
0021: * Contributor(s):
0022: * Waldemar Horwat
0023: * Roger Lawrence
0024: *
0025: * Alternatively, the contents of this file may be used under the
0026: * terms of the GNU Public License (the "GPL"), in which case the
0027: * provisions of the GPL are applicable instead of those above.
0028: * If you wish to allow use of your version of this file only
0029: * under the terms of the GPL and not to allow others to use your
0030: * version of this file under the NPL, indicate your decision by
0031: * deleting the provisions above and replace them with the notice
0032: * and other provisions required by the GPL. If you do not delete
0033: * the provisions above, a recipient may use your version of this
0034: * file under either the NPL or the GPL.
0035: */
0036: // Modified by Google
0037: /****************************************************************
0038: *
0039: * The author of this software is David M. Gay.
0040: *
0041: * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
0042: *
0043: * Permission to use, copy, modify, and distribute this software for any
0044: * purpose without fee is hereby granted, provided that this entire notice
0045: * is included in all copies of any software which is or includes a copy
0046: * or modification of this software and in all copies of the supporting
0047: * documentation for such software.
0048: *
0049: * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
0050: * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
0051: * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
0052: * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
0053: *
0054: ***************************************************************/package com.google.gwt.dev.js.rhino;
0055:
0056: import java.math.BigInteger;
0057:
0058: class DToA {
0059:
0060: /* "-0.0000...(1073 zeros after decimal point)...0001\0" is the longest string that we could produce,
0061: * which occurs when printing -5e-324 in binary. We could compute a better estimate of the size of
0062: * the output string and malloc fewer bytes depending on d and base, but why bother? */
0063:
0064: static final int DTOBASESTR_BUFFER_SIZE = 1078;
0065:
0066: static char BASEDIGIT(int digit) {
0067: return (char) ((digit >= 10) ? 'a' - 10 + digit : '0' + digit);
0068: }
0069:
0070: static final int DTOSTR_STANDARD = 0, /* Either fixed or exponential format; round-trip */
0071: DTOSTR_STANDARD_EXPONENTIAL = 1, /* Always exponential format; round-trip */
0072: DTOSTR_FIXED = 2, /* Round to <precision> digits after the decimal point; exponential if number is large */
0073: DTOSTR_EXPONENTIAL = 3, /* Always exponential format; <precision> significant digits */
0074: DTOSTR_PRECISION = 4; /* Either fixed or exponential format; <precision> significant digits */
0075:
0076: static final int Frac_mask = 0xfffff;
0077: static final int Exp_shift = 20;
0078: static final int Exp_msk1 = 0x100000;
0079: static final int Bias = 1023;
0080: static final int P = 53;
0081:
0082: static final int Exp_shift1 = 20;
0083: static final int Exp_mask = 0x7ff00000;
0084: static final int Bndry_mask = 0xfffff;
0085: static final int Log2P = 1;
0086:
0087: static final int Sign_bit = 0x80000000;
0088: static final int Exp_11 = 0x3ff00000;
0089: static final int Ten_pmax = 22;
0090: static final int Quick_max = 14;
0091: static final int Bletch = 0x10;
0092: static final int Frac_mask1 = 0xfffff;
0093: static final int Int_max = 14;
0094: static final int n_bigtens = 5;
0095:
0096: static final double tens[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6,
0097: 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16,
0098: 1e17, 1e18, 1e19, 1e20, 1e21, 1e22 };
0099:
0100: static final double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
0101:
0102: static int lo0bits(int y) {
0103: int k;
0104: int x = y;
0105:
0106: if ((x & 7) != 0) {
0107: if ((x & 1) != 0)
0108: return 0;
0109: if ((x & 2) != 0) {
0110: return 1;
0111: }
0112: return 2;
0113: }
0114: k = 0;
0115: if ((x & 0xffff) == 0) {
0116: k = 16;
0117: x >>>= 16;
0118: }
0119: if ((x & 0xff) == 0) {
0120: k += 8;
0121: x >>>= 8;
0122: }
0123: if ((x & 0xf) == 0) {
0124: k += 4;
0125: x >>>= 4;
0126: }
0127: if ((x & 0x3) == 0) {
0128: k += 2;
0129: x >>>= 2;
0130: }
0131: if ((x & 1) == 0) {
0132: k++;
0133: x >>>= 1;
0134: if ((x & 1) == 0)
0135: return 32;
0136: }
0137: return k;
0138: }
0139:
0140: /* Return the number (0 through 32) of most significant zero bits in x. */
0141: static int hi0bits(int x) {
0142: int k = 0;
0143:
0144: if ((x & 0xffff0000) == 0) {
0145: k = 16;
0146: x <<= 16;
0147: }
0148: if ((x & 0xff000000) == 0) {
0149: k += 8;
0150: x <<= 8;
0151: }
0152: if ((x & 0xf0000000) == 0) {
0153: k += 4;
0154: x <<= 4;
0155: }
0156: if ((x & 0xc0000000) == 0) {
0157: k += 2;
0158: x <<= 2;
0159: }
0160: if ((x & 0x80000000) == 0) {
0161: k++;
0162: if ((x & 0x40000000) == 0)
0163: return 32;
0164: }
0165: return k;
0166: }
0167:
0168: static void stuffBits(byte bits[], int offset, int val) {
0169: bits[offset] = (byte) (val >> 24);
0170: bits[offset + 1] = (byte) (val >> 16);
0171: bits[offset + 2] = (byte) (val >> 8);
0172: bits[offset + 3] = (byte) (val);
0173: }
0174:
0175: /* Convert d into the form b*2^e, where b is an odd integer. b is the returned
0176: * Bigint and e is the returned binary exponent. Return the number of significant
0177: * bits in b in bits. d must be finite and nonzero. */
0178: static BigInteger d2b(double d, int[] e, int[] bits) {
0179: byte dbl_bits[];
0180: int i, k, y, z, de;
0181: long dBits = Double.doubleToLongBits(d);
0182: int d0 = (int) (dBits >>> 32);
0183: int d1 = (int) (dBits);
0184:
0185: z = d0 & Frac_mask;
0186: d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
0187:
0188: if ((de = (int) (d0 >>> Exp_shift)) != 0)
0189: z |= Exp_msk1;
0190:
0191: if ((y = d1) != 0) {
0192: dbl_bits = new byte[8];
0193: k = lo0bits(y);
0194: y >>>= k;
0195: if (k != 0) {
0196: stuffBits(dbl_bits, 4, y | z << (32 - k));
0197: z >>= k;
0198: } else
0199: stuffBits(dbl_bits, 4, y);
0200: stuffBits(dbl_bits, 0, z);
0201: i = (z != 0) ? 2 : 1;
0202: } else {
0203: // JS_ASSERT(z);
0204: dbl_bits = new byte[4];
0205: k = lo0bits(z);
0206: z >>>= k;
0207: stuffBits(dbl_bits, 0, z);
0208: k += 32;
0209: i = 1;
0210: }
0211: if (de != 0) {
0212: e[0] = de - Bias - (P - 1) + k;
0213: bits[0] = P - k;
0214: } else {
0215: e[0] = de - Bias - (P - 1) + 1 + k;
0216: bits[0] = 32 * i - hi0bits(z);
0217: }
0218: return new BigInteger(dbl_bits);
0219: }
0220:
0221: public static String JS_dtobasestr(int base, double d) {
0222: char[] buffer; /* The output string */
0223: int p; /* index to current position in the buffer */
0224: int pInt; /* index to the beginning of the integer part of the string */
0225:
0226: int q;
0227: int digit;
0228: double di; /* d truncated to an integer */
0229: double df; /* The fractional part of d */
0230:
0231: // JS_ASSERT(base >= 2 && base <= 36);
0232:
0233: buffer = new char[DTOBASESTR_BUFFER_SIZE];
0234:
0235: p = 0;
0236: if (d < 0.0) {
0237: buffer[p++] = '-';
0238: d = -d;
0239: }
0240:
0241: /* Check for Infinity and NaN */
0242: if (Double.isNaN(d))
0243: return "NaN";
0244: else if (Double.isInfinite(d))
0245: return "Infinity";
0246:
0247: /* Output the integer part of d with the digits in reverse order. */
0248: pInt = p;
0249: di = (int) d;
0250: BigInteger b = BigInteger.valueOf((int) di);
0251: String intDigits = b.toString(base);
0252: intDigits.getChars(0, intDigits.length(), buffer, p);
0253: p += intDigits.length();
0254:
0255: df = d - di;
0256: if (df != 0.0) {
0257: /* We have a fraction. */
0258: buffer[p++] = '.';
0259:
0260: long dBits = Double.doubleToLongBits(d);
0261: int word0 = (int) (dBits >> 32);
0262: int word1 = (int) (dBits);
0263:
0264: int[] e = new int[1];
0265: int[] bbits = new int[1];
0266:
0267: b = d2b(df, e, bbits);
0268: // JS_ASSERT(e < 0);
0269: /* At this point df = b * 2^e. e must be less than zero because 0 < df < 1. */
0270:
0271: int s2 = -(word0 >>> Exp_shift1 & Exp_mask >> Exp_shift1);
0272: if (s2 == 0)
0273: s2 = -1;
0274: s2 += Bias + P;
0275: /* 1/2^s2 = (nextDouble(d) - d)/2 */
0276: // JS_ASSERT(-s2 < e);
0277: BigInteger mlo = BigInteger.valueOf(1);
0278: BigInteger mhi = mlo;
0279: if ((word1 == 0) && ((word0 & Bndry_mask) == 0)
0280: && ((word0 & (Exp_mask & Exp_mask << 1)) != 0)) {
0281: /* The special case. Here we want to be within a quarter of the last input
0282: significant digit instead of one half of it when the output string's value is less than d. */
0283: s2 += Log2P;
0284: mhi = BigInteger.valueOf(1 << Log2P);
0285: }
0286:
0287: b = b.shiftLeft(e[0] + s2);
0288: BigInteger s = BigInteger.valueOf(1);
0289: s = s.shiftLeft(s2);
0290: /* At this point we have the following:
0291: * s = 2^s2;
0292: * 1 > df = b/2^s2 > 0;
0293: * (d - prevDouble(d))/2 = mlo/2^s2;
0294: * (nextDouble(d) - d)/2 = mhi/2^s2. */
0295: BigInteger bigBase = BigInteger.valueOf(base);
0296:
0297: boolean done = false;
0298: do {
0299: b = b.multiply(bigBase);
0300: BigInteger[] divResult = b.divideAndRemainder(s);
0301: b = divResult[1];
0302: digit = (char) (divResult[0].intValue());
0303: if (mlo == mhi)
0304: mlo = mhi = mlo.multiply(bigBase);
0305: else {
0306: mlo = mlo.multiply(bigBase);
0307: mhi = mhi.multiply(bigBase);
0308: }
0309:
0310: /* Do we yet have the shortest string that will round to d? */
0311: int j = b.compareTo(mlo);
0312: /* j is b/2^s2 compared with mlo/2^s2. */
0313: BigInteger delta = s.subtract(mhi);
0314: int j1 = (delta.signum() <= 0) ? 1 : b.compareTo(delta);
0315: /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
0316: if (j1 == 0 && ((word1 & 1) == 0)) {
0317: if (j > 0)
0318: digit++;
0319: done = true;
0320: } else if (j < 0 || (j == 0 && ((word1 & 1) == 0))) {
0321: if (j1 > 0) {
0322: /* Either dig or dig+1 would work here as the least significant digit.
0323: Use whichever would produce an output value closer to d. */
0324: b = b.shiftLeft(1);
0325: j1 = b.compareTo(s);
0326: if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output
0327: * such as 3.5 in base 3. */
0328: digit++;
0329: }
0330: done = true;
0331: } else if (j1 > 0) {
0332: digit++;
0333: done = true;
0334: }
0335: // JS_ASSERT(digit < (uint32)base);
0336: buffer[p++] = BASEDIGIT(digit);
0337: } while (!done);
0338: }
0339:
0340: return new String(buffer, 0, p);
0341: }
0342:
0343: /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
0344: *
0345: * Inspired by "How to Print Floating-Point Numbers Accurately" by
0346: * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
0347: *
0348: * Modifications:
0349: * 1. Rather than iterating, we use a simple numeric overestimate
0350: * to determine k = floor(log10(d)). We scale relevant
0351: * quantities using O(log2(k)) rather than O(k) multiplications.
0352: * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
0353: * try to generate digits strictly left to right. Instead, we
0354: * compute with fewer bits and propagate the carry if necessary
0355: * when rounding the final digit up. This is often faster.
0356: * 3. Under the assumption that input will be rounded nearest,
0357: * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
0358: * That is, we allow equality in stopping tests when the
0359: * round-nearest rule will give the same floating-point value
0360: * as would satisfaction of the stopping test with strict
0361: * inequality.
0362: * 4. We remove common factors of powers of 2 from relevant
0363: * quantities.
0364: * 5. When converting floating-point integers less than 1e16,
0365: * we use floating-point arithmetic rather than resorting
0366: * to multiple-precision integers.
0367: * 6. When asked to produce fewer than 15 digits, we first try
0368: * to get by with floating-point arithmetic; we resort to
0369: * multiple-precision integer arithmetic only if we cannot
0370: * guarantee that the floating-point calculation has given
0371: * the correctly rounded result. For k requested digits and
0372: * "uniformly" distributed input, the probability is
0373: * something like 10^(k-15) that we must resort to the Long
0374: * calculation.
0375: */
0376:
0377: static int word0(double d) {
0378: long dBits = Double.doubleToLongBits(d);
0379: return (int) (dBits >> 32);
0380: }
0381:
0382: static double setWord0(double d, int i) {
0383: long dBits = Double.doubleToLongBits(d);
0384: dBits = ((long) i << 32) | (dBits & 0x0FFFFFFFFL);
0385: return Double.longBitsToDouble(dBits);
0386: }
0387:
0388: static int word1(double d) {
0389: long dBits = Double.doubleToLongBits(d);
0390: return (int) (dBits);
0391: }
0392:
0393: /* Return b * 5^k. k must be nonnegative. */
0394: // XXXX the C version built a cache of these
0395: static BigInteger pow5mult(BigInteger b, int k) {
0396: return b.multiply(BigInteger.valueOf(5).pow(k));
0397: }
0398:
0399: static boolean roundOff(StringBuffer buf) {
0400: char lastCh;
0401: while ((lastCh = buf.charAt(buf.length() - 1)) == '9') {
0402: buf.setLength(buf.length() - 1);
0403: if (buf.length() == 0) {
0404: return true;
0405: }
0406: }
0407: buf.append((char) (lastCh + 1));
0408: return false;
0409: }
0410:
0411: /* Always emits at least one digit. */
0412: /* If biasUp is set, then rounding in modes 2 and 3 will round away from zero
0413: * when the number is exactly halfway between two representable values. For example,
0414: * rounding 2.5 to zero digits after the decimal point will return 3 and not 2.
0415: * 2.49 will still round to 2, and 2.51 will still round to 3. */
0416: /* bufsize should be at least 20 for modes 0 and 1. For the other modes,
0417: * bufsize should be two greater than the maximum number of output characters expected. */
0418: static int JS_dtoa(double d, int mode, boolean biasUp, int ndigits,
0419: boolean[] sign, StringBuffer buf) {
0420: /* Arguments ndigits, decpt, sign are similar to those
0421: of ecvt and fcvt; trailing zeros are suppressed from
0422: the returned string. If not null, *rve is set to point
0423: to the end of the return value. If d is +-Infinity or NaN,
0424: then *decpt is set to 9999.
0425:
0426: mode:
0427: 0 ==> shortest string that yields d when read in
0428: and rounded to nearest.
0429: 1 ==> like 0, but with Steele & White stopping rule;
0430: e.g. with IEEE P754 arithmetic , mode 0 gives
0431: 1e23 whereas mode 1 gives 9.999999999999999e22.
0432: 2 ==> max(1,ndigits) significant digits. This gives a
0433: return value similar to that of ecvt, except
0434: that trailing zeros are suppressed.
0435: 3 ==> through ndigits past the decimal point. This
0436: gives a return value similar to that from fcvt,
0437: except that trailing zeros are suppressed, and
0438: ndigits can be negative.
0439: 4-9 should give the same return values as 2-3, i.e.,
0440: 4 <= mode <= 9 ==> same return as mode
0441: 2 + (mode & 1). These modes are mainly for
0442: debugging; often they run slower but sometimes
0443: faster than modes 2-3.
0444: 4,5,8,9 ==> left-to-right digit generation.
0445: 6-9 ==> don't try fast floating-point estimate
0446: (if applicable).
0447:
0448: Values of mode other than 0-9 are treated as mode 0.
0449:
0450: Sufficient space is allocated to the return value
0451: to hold the suppressed trailing zeros.
0452: */
0453:
0454: int b2, b5, i, ieps, ilim, ilim0, ilim1, j, j1, k, k0, m2, m5, s2, s5;
0455: char dig;
0456: long L;
0457: long x;
0458: BigInteger b, b1, delta, mlo, mhi, S;
0459: int[] be = new int[1];
0460: int[] bbits = new int[1];
0461: double d2, ds, eps;
0462: boolean spec_case, denorm, k_check, try_quick, leftright;
0463:
0464: if ((word0(d) & Sign_bit) != 0) {
0465: /* set sign for everything, including 0's and NaNs */
0466: sign[0] = true;
0467: // word0(d) &= ~Sign_bit; /* clear sign bit */
0468: d = setWord0(d, word0(d) & ~Sign_bit);
0469: } else
0470: sign[0] = false;
0471:
0472: if ((word0(d) & Exp_mask) == Exp_mask) {
0473: /* Infinity or NaN */
0474: buf
0475: .append(((word1(d) == 0) && ((word0(d) & Frac_mask) == 0)) ? "Infinity"
0476: : "NaN");
0477: return 9999;
0478: }
0479: if (d == 0) {
0480: // no_digits:
0481: buf.setLength(0);
0482: buf.append('0'); /* copy "0" to buffer */
0483: return 1;
0484: }
0485:
0486: b = d2b(d, be, bbits);
0487: if ((i = (int) (word0(d) >>> Exp_shift1 & (Exp_mask >> Exp_shift1))) != 0) {
0488: d2 = setWord0(d, (word0(d) & Frac_mask1) | Exp_11);
0489: /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
0490: * log10(x) = log(x) / log(10)
0491: * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
0492: * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
0493: *
0494: * This suggests computing an approximation k to log10(d) by
0495: *
0496: * k = (i - Bias)*0.301029995663981
0497: * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
0498: *
0499: * We want k to be too large rather than too small.
0500: * The error in the first-order Taylor series approximation
0501: * is in our favor, so we just round up the constant enough
0502: * to compensate for any error in the multiplication of
0503: * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
0504: * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
0505: * adding 1e-13 to the constant term more than suffices.
0506: * Hence we adjust the constant term to 0.1760912590558.
0507: * (We could get a more accurate k by invoking log10,
0508: * but this is probably not worthwhile.)
0509: */
0510: i -= Bias;
0511: denorm = false;
0512: } else {
0513: /* d is denormalized */
0514: i = bbits[0] + be[0] + (Bias + (P - 1) - 1);
0515: x = (i > 32) ? word0(d) << (64 - i) | word1(d) >>> (i - 32)
0516: : word1(d) << (32 - i);
0517: // d2 = x;
0518: // word0(d2) -= 31*Exp_msk1; /* adjust exponent */
0519: d2 = setWord0(x, word0(x) - 31 * Exp_msk1);
0520: i -= (Bias + (P - 1) - 1) + 1;
0521: denorm = true;
0522: }
0523: /* At this point d = f*2^i, where 1 <= f < 2. d2 is an approximation of f. */
0524: ds = (d2 - 1.5) * 0.289529654602168 + 0.1760912590558 + i
0525: * 0.301029995663981;
0526: k = (int) ds;
0527: if (ds < 0.0 && ds != k)
0528: k--; /* want k = floor(ds) */
0529: k_check = true;
0530: if (k >= 0 && k <= Ten_pmax) {
0531: if (d < tens[k])
0532: k--;
0533: k_check = false;
0534: }
0535: /* At this point floor(log10(d)) <= k <= floor(log10(d))+1.
0536: If k_check is zero, we're guaranteed that k = floor(log10(d)). */
0537: j = bbits[0] - i - 1;
0538: /* At this point d = b/2^j, where b is an odd integer. */
0539: if (j >= 0) {
0540: b2 = 0;
0541: s2 = j;
0542: } else {
0543: b2 = -j;
0544: s2 = 0;
0545: }
0546: if (k >= 0) {
0547: b5 = 0;
0548: s5 = k;
0549: s2 += k;
0550: } else {
0551: b2 -= k;
0552: b5 = -k;
0553: s5 = 0;
0554: }
0555: /* At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5), where b is an odd integer,
0556: b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0. */
0557: if (mode < 0 || mode > 9)
0558: mode = 0;
0559: try_quick = true;
0560: if (mode > 5) {
0561: mode -= 4;
0562: try_quick = false;
0563: }
0564: leftright = true;
0565: ilim = ilim1 = 0;
0566: switch (mode) {
0567: case 0:
0568: case 1:
0569: ilim = ilim1 = -1;
0570: i = 18;
0571: ndigits = 0;
0572: break;
0573: case 2:
0574: leftright = false;
0575: /* no break */
0576: case 4:
0577: if (ndigits <= 0)
0578: ndigits = 1;
0579: ilim = ilim1 = i = ndigits;
0580: break;
0581: case 3:
0582: leftright = false;
0583: /* no break */
0584: case 5:
0585: i = ndigits + k + 1;
0586: ilim = i;
0587: ilim1 = i - 1;
0588: if (i <= 0)
0589: i = 1;
0590: }
0591: /* ilim is the maximum number of significant digits we want, based on k and ndigits. */
0592: /* ilim1 is the maximum number of significant digits we want, based on k and ndigits,
0593: when it turns out that k was computed too high by one. */
0594:
0595: boolean fast_failed = false;
0596: if (ilim >= 0 && ilim <= Quick_max && try_quick) {
0597:
0598: /* Try to get by with floating-point arithmetic. */
0599:
0600: i = 0;
0601: d2 = d;
0602: k0 = k;
0603: ilim0 = ilim;
0604: ieps = 2; /* conservative */
0605: /* Divide d by 10^k, keeping track of the roundoff error and avoiding overflows. */
0606: if (k > 0) {
0607: ds = tens[k & 0xf];
0608: j = k >> 4;
0609: if ((j & Bletch) != 0) {
0610: /* prevent overflows */
0611: j &= Bletch - 1;
0612: d /= bigtens[n_bigtens - 1];
0613: ieps++;
0614: }
0615: for (; (j != 0); j >>= 1, i++)
0616: if ((j & 1) != 0) {
0617: ieps++;
0618: ds *= bigtens[i];
0619: }
0620: d /= ds;
0621: } else if ((j1 = -k) != 0) {
0622: d *= tens[j1 & 0xf];
0623: for (j = j1 >> 4; (j != 0); j >>= 1, i++)
0624: if ((j & 1) != 0) {
0625: ieps++;
0626: d *= bigtens[i];
0627: }
0628: }
0629: /* Check that k was computed correctly. */
0630: if (k_check && d < 1.0 && ilim > 0) {
0631: if (ilim1 <= 0)
0632: fast_failed = true;
0633: else {
0634: ilim = ilim1;
0635: k--;
0636: d *= 10.;
0637: ieps++;
0638: }
0639: }
0640: /* eps bounds the cumulative error. */
0641: // eps = ieps*d + 7.0;
0642: // word0(eps) -= (P-1)*Exp_msk1;
0643: eps = ieps * d + 7.0;
0644: eps = setWord0(eps, word0(eps) - (P - 1) * Exp_msk1);
0645: if (ilim == 0) {
0646: S = mhi = null;
0647: d -= 5.0;
0648: if (d > eps) {
0649: buf.append('1');
0650: k++;
0651: return k + 1;
0652: }
0653: if (d < -eps) {
0654: buf.setLength(0);
0655: buf.append('0'); /* copy "0" to buffer */
0656: return 1;
0657: }
0658: fast_failed = true;
0659: }
0660: if (!fast_failed) {
0661: fast_failed = true;
0662: if (leftright) {
0663: /* Use Steele & White method of only
0664: * generating digits needed.
0665: */
0666: eps = 0.5 / tens[ilim - 1] - eps;
0667: for (i = 0;;) {
0668: L = (long) d;
0669: d -= L;
0670: buf.append((char) ('0' + L));
0671: if (d < eps) {
0672: return k + 1;
0673: }
0674: if (1.0 - d < eps) {
0675: // goto bump_up;
0676: char lastCh;
0677: while (true) {
0678: lastCh = buf.charAt(buf.length() - 1);
0679: buf.setLength(buf.length() - 1);
0680: if (lastCh != '9')
0681: break;
0682: if (buf.length() == 0) {
0683: k++;
0684: lastCh = '0';
0685: break;
0686: }
0687: }
0688: buf.append((char) (lastCh + 1));
0689: return k + 1;
0690: }
0691: if (++i >= ilim)
0692: break;
0693: eps *= 10.0;
0694: d *= 10.0;
0695: }
0696: } else {
0697: /* Generate ilim digits, then fix them up. */
0698: eps *= tens[ilim - 1];
0699: for (i = 1;; i++, d *= 10.0) {
0700: L = (long) d;
0701: d -= L;
0702: buf.append((char) ('0' + L));
0703: if (i == ilim) {
0704: if (d > 0.5 + eps) {
0705: // goto bump_up;
0706: char lastCh;
0707: while (true) {
0708: lastCh = buf
0709: .charAt(buf.length() - 1);
0710: buf.setLength(buf.length() - 1);
0711: if (lastCh != '9')
0712: break;
0713: if (buf.length() == 0) {
0714: k++;
0715: lastCh = '0';
0716: break;
0717: }
0718: }
0719: buf.append((char) (lastCh + 1));
0720: return k + 1;
0721: } else if (d < 0.5 - eps) {
0722: while (buf.charAt(buf.length() - 1) == '0')
0723: buf.setLength(buf.length() - 1);
0724: // while(*--s == '0') ;
0725: // s++;
0726: return k + 1;
0727: }
0728: break;
0729: }
0730: }
0731: }
0732: }
0733: if (fast_failed) {
0734: buf.setLength(0);
0735: d = d2;
0736: k = k0;
0737: ilim = ilim0;
0738: }
0739: }
0740:
0741: /* Do we have a "small" integer? */
0742:
0743: if (be[0] >= 0 && k <= Int_max) {
0744: /* Yes. */
0745: ds = tens[k];
0746: if (ndigits < 0 && ilim <= 0) {
0747: S = mhi = null;
0748: if (ilim < 0 || d < 5 * ds || (!biasUp && d == 5 * ds)) {
0749: buf.setLength(0);
0750: buf.append('0'); /* copy "0" to buffer */
0751: return 1;
0752: }
0753: buf.append('1');
0754: k++;
0755: return k + 1;
0756: }
0757: for (i = 1;; i++) {
0758: L = (long) (d / ds);
0759: d -= L * ds;
0760: buf.append((char) ('0' + L));
0761: if (i == ilim) {
0762: d += d;
0763: if ((d > ds)
0764: || (d == ds && (((L & 1) != 0) || biasUp))) {
0765: // bump_up:
0766: // while(*--s == '9')
0767: // if (s == buf) {
0768: // k++;
0769: // *s = '0';
0770: // break;
0771: // }
0772: // ++*s++;
0773: char lastCh;
0774: while (true) {
0775: lastCh = buf.charAt(buf.length() - 1);
0776: buf.setLength(buf.length() - 1);
0777: if (lastCh != '9')
0778: break;
0779: if (buf.length() == 0) {
0780: k++;
0781: lastCh = '0';
0782: break;
0783: }
0784: }
0785: buf.append((char) (lastCh + 1));
0786: }
0787: break;
0788: }
0789: d *= 10.0;
0790: if (d == 0)
0791: break;
0792: }
0793: return k + 1;
0794: }
0795:
0796: m2 = b2;
0797: m5 = b5;
0798: mhi = mlo = null;
0799: if (leftright) {
0800: if (mode < 2) {
0801: i = (denorm) ? be[0] + (Bias + (P - 1) - 1 + 1) : 1 + P
0802: - bbits[0];
0803: /* i is 1 plus the number of trailing zero bits in d's significand. Thus,
0804: (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k. */
0805: } else {
0806: j = ilim - 1;
0807: if (m5 >= j)
0808: m5 -= j;
0809: else {
0810: s5 += j -= m5;
0811: b5 += j;
0812: m5 = 0;
0813: }
0814: if ((i = ilim) < 0) {
0815: m2 -= i;
0816: i = 0;
0817: }
0818: /* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */
0819: }
0820: b2 += i;
0821: s2 += i;
0822: mhi = BigInteger.valueOf(1);
0823: /* (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed (when mode >= 2) or
0824: input (when mode < 2) significant digit, divided by 10^k. */
0825: }
0826: /* We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5). Reduce common factors in
0827: b2, m2, and s2 without changing the equalities. */
0828: if (m2 > 0 && s2 > 0) {
0829: i = (m2 < s2) ? m2 : s2;
0830: b2 -= i;
0831: m2 -= i;
0832: s2 -= i;
0833: }
0834:
0835: /* Fold b5 into b and m5 into mhi. */
0836: if (b5 > 0) {
0837: if (leftright) {
0838: if (m5 > 0) {
0839: mhi = pow5mult(mhi, m5);
0840: b1 = mhi.multiply(b);
0841: b = b1;
0842: }
0843: if ((j = b5 - m5) != 0)
0844: b = pow5mult(b, j);
0845: } else
0846: b = pow5mult(b, b5);
0847: }
0848: /* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and
0849: (mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input significant digit, divided by 10^k. */
0850:
0851: S = BigInteger.valueOf(1);
0852: if (s5 > 0)
0853: S = pow5mult(S, s5);
0854: /* Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and
0855: (mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input significant digit, divided by 10^k. */
0856:
0857: /* Check for special case that d is a normalized power of 2. */
0858: spec_case = false;
0859: if (mode < 2) {
0860: if ((word1(d) == 0) && ((word0(d) & Bndry_mask) == 0)
0861: && ((word0(d) & (Exp_mask & Exp_mask << 1)) != 0)) {
0862: /* The special case. Here we want to be within a quarter of the last input
0863: significant digit instead of one half of it when the decimal output string's value is less than d. */
0864: b2 += Log2P;
0865: s2 += Log2P;
0866: spec_case = true;
0867: }
0868: }
0869:
0870: /* Arrange for convenient computation of quotients:
0871: * shift left if necessary so divisor has 4 leading 0 bits.
0872: *
0873: * Perhaps we should just compute leading 28 bits of S once
0874: * and for all and pass them and a shift to quorem, so it
0875: * can do shifts and ors to compute the numerator for q.
0876: */
0877: byte[] S_bytes = S.toByteArray();
0878: int S_hiWord = 0;
0879: for (int idx = 0; idx < 4; idx++) {
0880: S_hiWord = (S_hiWord << 8);
0881: if (idx < S_bytes.length)
0882: S_hiWord |= (S_bytes[idx] & 0xFF);
0883: }
0884: if ((i = (((s5 != 0) ? 32 - hi0bits(S_hiWord) : 1) + s2) & 0x1f) != 0)
0885: i = 32 - i;
0886: /* i is the number of leading zero bits in the most significant word of S*2^s2. */
0887: if (i > 4) {
0888: i -= 4;
0889: b2 += i;
0890: m2 += i;
0891: s2 += i;
0892: } else if (i < 4) {
0893: i += 28;
0894: b2 += i;
0895: m2 += i;
0896: s2 += i;
0897: }
0898: /* Now S*2^s2 has exactly four leading zero bits in its most significant word. */
0899: if (b2 > 0)
0900: b = b.shiftLeft(b2);
0901: if (s2 > 0)
0902: S = S.shiftLeft(s2);
0903: /* Now we have d/10^k = b/S and
0904: (mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */
0905: if (k_check) {
0906: if (b.compareTo(S) < 0) {
0907: k--;
0908: b = b.multiply(BigInteger.valueOf(10)); /* we botched the k estimate */
0909: if (leftright)
0910: mhi = mhi.multiply(BigInteger.valueOf(10));
0911: ilim = ilim1;
0912: }
0913: }
0914: /* At this point 1 <= d/10^k = b/S < 10. */
0915:
0916: if (ilim <= 0 && mode > 2) {
0917: /* We're doing fixed-mode output and d is less than the minimum nonzero output in this mode.
0918: Output either zero or the minimum nonzero output depending on which is closer to d. */
0919: if ((ilim < 0)
0920: || ((i = b.compareTo(S = S.multiply(BigInteger
0921: .valueOf(5)))) < 0)
0922: || ((i == 0 && !biasUp))) {
0923: /* Always emit at least one digit. If the number appears to be zero
0924: using the current mode, then emit one '0' digit and set decpt to 1. */
0925: /*no_digits:
0926: k = -1 - ndigits;
0927: goto ret; */
0928: buf.setLength(0);
0929: buf.append('0'); /* copy "0" to buffer */
0930: return 1;
0931: // goto no_digits;
0932: }
0933: // one_digit:
0934: buf.append('1');
0935: k++;
0936: return k + 1;
0937: }
0938: if (leftright) {
0939: if (m2 > 0)
0940: mhi = mhi.shiftLeft(m2);
0941:
0942: /* Compute mlo -- check for special case
0943: * that d is a normalized power of 2.
0944: */
0945:
0946: mlo = mhi;
0947: if (spec_case) {
0948: mhi = mlo;
0949: mhi = mhi.shiftLeft(Log2P);
0950: }
0951: /* mlo/S = maximum acceptable error, divided by 10^k, if the output is less than d. */
0952: /* mhi/S = maximum acceptable error, divided by 10^k, if the output is greater than d. */
0953:
0954: for (i = 1;; i++) {
0955: BigInteger[] divResult = b.divideAndRemainder(S);
0956: b = divResult[1];
0957: dig = (char) (divResult[0].intValue() + '0');
0958: /* Do we yet have the shortest decimal string
0959: * that will round to d?
0960: */
0961: j = b.compareTo(mlo);
0962: /* j is b/S compared with mlo/S. */
0963: delta = S.subtract(mhi);
0964: j1 = (delta.signum() <= 0) ? 1 : b.compareTo(delta);
0965: /* j1 is b/S compared with 1 - mhi/S. */
0966: if ((j1 == 0) && (mode == 0) && ((word1(d) & 1) == 0)) {
0967: if (dig == '9') {
0968: buf.append('9');
0969: if (roundOff(buf)) {
0970: k++;
0971: buf.append('1');
0972: }
0973: return k + 1;
0974: // goto round_9_up;
0975: }
0976: if (j > 0)
0977: dig++;
0978: buf.append(dig);
0979: return k + 1;
0980: }
0981: if ((j < 0)
0982: || ((j == 0) && (mode == 0) && ((word1(d) & 1) == 0))) {
0983: if (j1 > 0) {
0984: /* Either dig or dig+1 would work here as the least significant decimal digit.
0985: Use whichever would produce a decimal value closer to d. */
0986: b = b.shiftLeft(1);
0987: j1 = b.compareTo(S);
0988: if (((j1 > 0) || (j1 == 0 && (((dig & 1) == 1) || biasUp)))
0989: && (dig++ == '9')) {
0990: buf.append('9');
0991: if (roundOff(buf)) {
0992: k++;
0993: buf.append('1');
0994: }
0995: return k + 1;
0996: // goto round_9_up;
0997: }
0998: }
0999: buf.append(dig);
1000: return k + 1;
1001: }
1002: if (j1 > 0) {
1003: if (dig == '9') { /* possible if i == 1 */
1004: // round_9_up:
1005: // *s++ = '9';
1006: // goto roundoff;
1007: buf.append('9');
1008: if (roundOff(buf)) {
1009: k++;
1010: buf.append('1');
1011: }
1012: return k + 1;
1013: }
1014: buf.append((char) (dig + 1));
1015: return k + 1;
1016: }
1017: buf.append(dig);
1018: if (i == ilim)
1019: break;
1020: b = b.multiply(BigInteger.valueOf(10));
1021: if (mlo == mhi)
1022: mlo = mhi = mhi.multiply(BigInteger.valueOf(10));
1023: else {
1024: mlo = mlo.multiply(BigInteger.valueOf(10));
1025: mhi = mhi.multiply(BigInteger.valueOf(10));
1026: }
1027: }
1028: } else
1029: for (i = 1;; i++) {
1030: // (char)(dig = quorem(b,S) + '0');
1031: BigInteger[] divResult = b.divideAndRemainder(S);
1032: b = divResult[1];
1033: dig = (char) (divResult[0].intValue() + '0');
1034: buf.append(dig);
1035: if (i >= ilim)
1036: break;
1037: b = b.multiply(BigInteger.valueOf(10));
1038: }
1039:
1040: /* Round off last digit */
1041:
1042: b = b.shiftLeft(1);
1043: j = b.compareTo(S);
1044: if ((j > 0) || (j == 0 && (((dig & 1) == 1) || biasUp))) {
1045: // roundoff:
1046: // while(*--s == '9')
1047: // if (s == buf) {
1048: // k++;
1049: // *s++ = '1';
1050: // goto ret;
1051: // }
1052: // ++*s++;
1053: if (roundOff(buf)) {
1054: k++;
1055: buf.append('1');
1056: return k + 1;
1057: }
1058: } else {
1059: /* Strip trailing zeros */
1060: while (buf.charAt(buf.length() - 1) == '0')
1061: buf.setLength(buf.length() - 1);
1062: // while(*--s == '0') ;
1063: // s++;
1064: }
1065: // ret:
1066: // Bfree(S);
1067: // if (mhi) {
1068: // if (mlo && mlo != mhi)
1069: // Bfree(mlo);
1070: // Bfree(mhi);
1071: // }
1072: // ret1:
1073: // Bfree(b);
1074: // JS_ASSERT(s < buf + bufsize);
1075: return k + 1;
1076: }
1077:
1078: /* Mapping of JSDToStrMode -> JS_dtoa mode */
1079: private static final int dtoaModes[] = { 0, /* DTOSTR_STANDARD */
1080: 0, /* DTOSTR_STANDARD_EXPONENTIAL, */
1081: 3, /* DTOSTR_FIXED, */
1082: 2, /* DTOSTR_EXPONENTIAL, */
1083: 2 }; /* DTOSTR_PRECISION */
1084:
1085: static void JS_dtostr(StringBuffer buffer, int mode, int precision,
1086: double d) {
1087: int decPt; /* Position of decimal point relative to first digit returned by JS_dtoa */
1088: boolean[] sign = new boolean[1]; /* true if the sign bit was set in d */
1089: int nDigits; /* Number of significand digits returned by JS_dtoa */
1090:
1091: // JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL ? DTOSTR_STANDARD_BUFFER_SIZE :
1092: // DTOSTR_VARIABLE_BUFFER_SIZE(precision)));
1093:
1094: if (mode == DTOSTR_FIXED && (d >= 1e21 || d <= -1e21))
1095: mode = DTOSTR_STANDARD; /* Change mode here rather than below because the buffer may not be large enough to hold a large integer. */
1096:
1097: decPt = JS_dtoa(d, dtoaModes[mode], mode >= DTOSTR_FIXED,
1098: precision, sign, buffer);
1099: nDigits = buffer.length();
1100:
1101: /* If Infinity, -Infinity, or NaN, return the string regardless of the mode. */
1102: if (decPt != 9999) {
1103: boolean exponentialNotation = false;
1104: int minNDigits = 0; /* Minimum number of significand digits required by mode and precision */
1105: int p;
1106: int q;
1107:
1108: switch (mode) {
1109: case DTOSTR_STANDARD:
1110: if (decPt < -5 || decPt > 21)
1111: exponentialNotation = true;
1112: else
1113: minNDigits = decPt;
1114: break;
1115:
1116: case DTOSTR_FIXED:
1117: if (precision >= 0)
1118: minNDigits = decPt + precision;
1119: else
1120: minNDigits = decPt;
1121: break;
1122:
1123: case DTOSTR_EXPONENTIAL:
1124: // JS_ASSERT(precision > 0);
1125: minNDigits = precision;
1126: /* Fall through */
1127: case DTOSTR_STANDARD_EXPONENTIAL:
1128: exponentialNotation = true;
1129: break;
1130:
1131: case DTOSTR_PRECISION:
1132: // JS_ASSERT(precision > 0);
1133: minNDigits = precision;
1134: if (decPt < -5 || decPt > precision)
1135: exponentialNotation = true;
1136: break;
1137: }
1138:
1139: /* If the number has fewer than minNDigits, pad it with zeros at the end */
1140: if (nDigits < minNDigits) {
1141: p = minNDigits;
1142: nDigits = minNDigits;
1143: do {
1144: buffer.append('0');
1145: } while (buffer.length() != p);
1146: }
1147:
1148: if (exponentialNotation) {
1149: /* Insert a decimal point if more than one significand digit */
1150: if (nDigits != 1) {
1151: buffer.insert(1, '.');
1152: }
1153: buffer.append('e');
1154: if ((decPt - 1) >= 0)
1155: buffer.append('+');
1156: buffer.append(decPt - 1);
1157: // JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d", decPt-1);
1158: } else if (decPt != nDigits) {
1159: /* Some kind of a fraction in fixed notation */
1160: // JS_ASSERT(decPt <= nDigits);
1161: if (decPt > 0) {
1162: /* dd...dd . dd...dd */
1163: buffer.insert(decPt, '.');
1164: } else {
1165: /* 0 . 00...00dd...dd */
1166: for (int i = 0; i < 1 - decPt; i++)
1167: buffer.insert(0, '0');
1168: buffer.insert(1, '.');
1169: }
1170: }
1171: }
1172:
1173: /* If negative and neither -0.0 nor NaN, output a leading '-'. */
1174: if (sign[0]
1175: && !(word0(d) == Sign_bit && word1(d) == 0)
1176: && !((word0(d) & Exp_mask) == Exp_mask && ((word1(d) != 0) || ((word0(d) & Frac_mask) != 0)))) {
1177: buffer.insert(0, '-');
1178: }
1179: }
1180:
1181: }
|