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