/*
 * The contents of this file are subject to the Netscape Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/NPL/

 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.

 * The Original Code is Rhino code, released
 * May 6, 1999.

 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
 * Rights Reserved.

 * Contributor(s): 

 * Alternatively, the contents of this file may be used under the
 * terms of the GNU Public License (the "GPL"), in which case the
 * provisions of the GPL are applicable instead of those above.
 * If you wish to allow use of your version of this file only
 * under the terms of the GPL and not to allow others to use your
 * version of this file under the NPL, indicate your decision by
 * deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL.  If you do not delete
 * the provisions above, a recipient may use your version of this
 * file under either the NPL or the GPL.
 */
#ifdef DTOA

/* Header file */
#ifdef VX
#include <private/mathP.h>
#endif
#ifdef SUNOS5
#include <ieeefp.h>
#endif
#include <math.h>
#include "js-utils.h"
#include "js-dtoa.h"

/* Class data */
const double	JSDToA::tens[23] = {
    1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
    1e20, 1e21, 1e22
} ;
const double	JSDToA::bigtens[5] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
const int 	JSDToA::dtoaModes[5] = { 
	0,   /* DTOSTR_STANDARD */
	0,   /* DTOSTR_STANDARD_EXPONENTIAL, */
	3,   /* DTOSTR_FIXED, */
	2,   /* DTOSTR_EXPONENTIAL, */
	2	/* DTOSTR_PRECISION */
} ;

/* Procedures */
int64_t
JSDToA::doubleToLongBits(double d)
{
    union {
	double  d;
	int64_t l;
    } v;

#ifdef VX
    if (isNan(d)) {
#else
    if (isnan(d)) {
#endif
	return ((int64_t) 0x7ff80000) << ((int64_t) 32);
    }

    v.d = d;
    return v.l;
}
double
JSDToA::longBitsToDouble(int64_t bits)
{
    union {
	double  d;
	int64_t l;
    } v;

    v.l = bits;
    return v.d;
}
jsChar_t
JSDToA::BASEDIGIT(int digit)
{
    return (jsChar_t) ((digit >= 10) ? 'a' - 10 + digit : '0' + digit);
}
int
JSDToA::lo0bits(int32_t y)
{
    int k;
    uint32_t x = y;

    if ((x & 7) != 0) {
	if ((x & 1) != 0) {
	    return 0;
	}
	if ((x & 2) != 0) {
	    return 1;
	}
	return 2;
    }
    k = 0;
    if ((x & 0xffff) == 0) {
	k = 16;
	x >>= 16;
    }
    if ((x & 0xff) == 0) {
	k += 8;
	x >>= 8;
    }
    if ((x & 0xf) == 0) {
	k += 4;
	x >>= 4;
    }
    if ((x & 0x3) == 0) {
	k += 2;
	x >>= 2;
    }
    if ((x & 1) == 0) {
	k++;
	x >>= 1;
	if ((x & 1) == 0) {
	    return 32;
	}
    }
    return k;
}
/* Return the number (0 through 32) of most significant zero bits in x. */
int
JSDToA::hi0bits(int32_t x)
{
    int k = 0;

    if ((x & 0xffff0000) == 0) {
	k = 16;
	x <<= 16;
    }
    if ((x & 0xff000000) == 0) {
	k += 8;
	x <<= 8;
    }
    if ((x & 0xf0000000) == 0) {
	k += 4;
	x <<= 4;
    }
    if ((x & 0xc0000000) == 0) {
	k += 2;
	x <<= 2;
    }
    if ((x & 0x80000000) == 0) {
	k++;
	if ((x & 0x40000000) == 0) {
	    return 32;
	}
    }
    return k;
}
void
JSDToA::stuffBits(JSBigInteger::Digit *bits, int offset, int val)
{
    bits[offset] = (JSBigInteger::Digit) val;
}
/*
 * Convert d into the form b*2^e, where b is an odd integer.  b is the returned
 * Bigint and e is the returned binary exponent.  Return the number of
 * significant bits in b in bits.  d must be finite and nonzero.
 */
JSBigInteger
JSDToA::d2b(JSContext *cx, double d, int *e, int *bits)
{
    JSBigInteger::Digit *dbl_bits;
    int32_t i, k, de;
    uint32_t y, z;
    int64_t dBits = doubleToLongBits(d);
    uint32_t d0 = (uint32_t) (dBits >> 32);
    uint32_t d1 = (uint32_t) (dBits);
    int dbl_bitsLength;

    z = d0 & Frac_mask;
    d0 &= 0x7fffffff;   /* clear sign bit, which we ignore */

    if ((de = (uint32_t) (d0 >> Exp_shift)) != 0) {
	z |= Exp_msk1;
    }
    if ((y = d1) != 0) {
	dbl_bitsLength = 2;
	dbl_bits = (JSBigInteger::Digit *)
			JS_NewZoneObj(cx, sizeof (*dbl_bits) * dbl_bitsLength);
	k = lo0bits(y);
	y >>= k;
	if (k != 0) {
	    stuffBits(dbl_bits, 1, y | z << (32 - k));
	    z >>= k;
	} else {
	    stuffBits(dbl_bits, 1, y);
	}
	stuffBits(dbl_bits, 0, z);
	i = (z != 0) ? 2 : 1;
    } else {
	dbl_bitsLength = 1;
	dbl_bits = (JSBigInteger::Digit *)
			JS_NewZoneObj(cx, sizeof (*dbl_bits) * dbl_bitsLength);
	k = lo0bits(z);
	z >>= k;
	stuffBits(dbl_bits, 0, z);
	k += 32;
	i = 1;
    }
    if (de != 0) {
	*e = de - Bias - (P - 1) + k;
	*bits = P - k;
    } else {
	*e = de - Bias - (P - 1) + 1 + k;
	*bits = 32 * i - hi0bits(z);
    }
    JSBigInteger result(cx, dbl_bits, dbl_bitsLength);

    JS_DeleteZoneObj(cx, dbl_bits);
    return result;
}
int32_t
JSDToA::word0(double d)
{
    int64_t dBits = doubleToLongBits(d);

    return (int32_t)(dBits >> 32);
}
double
JSDToA::setWord0(double d, int32_t i)
{
    int64_t dBits = doubleToLongBits(d);

    dBits = ((int64_t) i << 32) | (dBits & 0x0FFFFFFFFL);
    return longBitsToDouble(dBits);
}
int32_t
JSDToA::word1(double d)
{
    int64_t dBits = doubleToLongBits(d);

    return (int32_t) dBits;
}
/* Return b * 5^k.  k must be nonnegative. */
JSBigInteger
JSDToA::pow5mult(JSContext *cx, JSBigInteger &b, int k)
{
    JSBigInteger five = JSBigInteger::valueOf(cx, 5);
    JSBigInteger pow = five.pow(cx, k);

    return b.multiply(cx, pow);
}
jsBool_t
JSDToA::roundOff(JSStringBuffer *buf)
{
    jsChar_t lastCh;

    while ((lastCh = buf->charAt(buf->length() - 1)) == '9') {
	buf->setLength(buf->length() - 1);
	if (buf->length() == 0) {
	    return TRUE;
	}
    }
    buf->append((jsChar_t) (lastCh + 1));
    return FALSE;
}

jsString_t
JSDToA::JS_dtobasestr(JSContext *cx, int base, double d)
{
    jsChar_t buffer[DTOBASESTR_BUFFER_SIZE];	/* The output string */
    int p;	/* index to current position in the buffer */
    int pInt;	/* index to the beginning of the integer part of the string */

    int digit;
    double di;	/* d truncated to an integer */
    double df;	/* The fractional part of d */

    p = 0;
    if (d < 0.0) {
	buffer[p++] = '-';
	d = -d;
    }

    /* Check for Infinity and NaN */
#ifdef VX
    if (isNan(d)) {
#else
    if (isnan(d)) {
#endif
	return JS_NewZoneString(cx, "NaN");
    } else {
#ifdef VX
	if (isNan(d) || isInf(d)) {
#else
	if (!finite(d)) {
#endif
	    return JS_NewZoneString(cx, "Infinity");
	}
    }

    /* Output the integer part of d with the digits in reverse order. */
    pInt = p;
    di = (int) d;

    JSBigInteger b = JSBigInteger::valueOf(cx, (int64_t) di);
    jsString_t intDigits = b.toString(cx, base);
    int length = strlen(intDigits);

    memcpy(buffer + p, intDigits, length * sizeof (*buffer)); 
    p += length;
    JS_DeleteZoneObj(cx, intDigits);

    df = d - di;
    if (df != 0.0) {
	/* We have a fraction. */
	buffer[p++] = '.';

	int64_t dBits = doubleToLongBits(d);
	int32_t word0 = (int32_t) (dBits >> 32);
	int32_t word1 = (int32_t) (dBits);
	int e, bbits;
					 
	b = d2b(cx, df, &e, &bbits);

	/* At this point df = b * 2^e.  e must be less than zero
	 * because 0 < df < 1.
	 */
	int s2 = -(((uint32_t) word0 >> Exp_shift1) & Exp_mask >> Exp_shift1);

	if (s2 == 0) {
	    s2 = -1;
	}
	s2 += Bias + P;

	/* 1/2^s2 = (nextDouble(d) - d)/2 */
	JSBigInteger mlo = JSBigInteger::valueOf(cx, 1);
	JSBigInteger mhi = mlo;

	if ((word1 == 0) && ((word0 & Bndry_mask) == 0)
	    && ((word0 & (Exp_mask & Exp_mask << 1)) != 0)) {
	    /* The special case.  Here we want to be within a quarter of the
	     * last input significant digit instead of one half of it when the
	     * output string's value is less than d.
	     */
	    s2 += Log2P;
	    mhi = JSBigInteger::valueOf(cx, 1 << Log2P);
	}
	b = b.shiftLeft(cx, e + s2);

	JSBigInteger s = JSBigInteger::valueOf(cx, 1);

	s = s.shiftLeft(cx, s2);
	/* At this point we have the following:
	 *   s = 2^s2;
	 *   1 > df = b/2^s2 > 0;
	 *   (d - prevDouble(d))/2 = mlo/2^s2;
	 *   (nextDouble(d) - d)/2 = mhi/2^s2. */
	JSBigInteger bigBase = JSBigInteger::valueOf(cx, base);

	jsBool_t done = FALSE;
	do {
	    b = b.multiply(cx, bigBase);

	    JSBigInteger div(cx), rem(cx);
	    JSBigInteger *divResult[] = { &div, &rem };

	    b.divideAndRemainder(cx, divResult, s);
	    b = rem;
	    digit = (jsChar_t) (divResult[0]->int64Value());
	    if (mlo.equals(mhi)) {
		mlo = mhi = mlo.multiply(cx, bigBase);
	    } else {
		mlo = mlo.multiply(cx, bigBase);
		mhi = mhi.multiply(cx, bigBase);
	    }

	    /* Do we yet have the shortest string that will round to d? */
	    int j = b.compareTo(mlo);

	    /* j is b/2^s2 compared with mlo/2^s2. */
	    JSBigInteger delta = s.subtract(cx, mhi);
	    int j1 = (delta.getSignum() <= 0) ? 1 : b.compareTo(delta);

	    /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
	    if (j1 == 0 && ((word1 & 1) == 0)) {
		if (j > 0) digit++;
		done = TRUE;
	    } else if (j < 0 || (j == 0 && ((word1 & 1) == 0))) {
		if (j1 > 0) {
		    /* Either dig or dig+1 would work here as the least
		     * significant digit.
		     * Use whichever would produce an output value closer
		     * to d.
		     */
		    b = b.shiftLeft(cx, 1);
		    j1 = b.compareTo(s);
		    if (j1 > 0) {
			/* The even test (|| (j1 == 0 && (digit & 1))) is not
			 * here because it messes up odd base output
			 * such as 3.5 in base 3. 
			 */
			digit++;
		    }
		}
		done = TRUE;
	    } else if (j1 > 0) {
		digit++;
		done = TRUE;
	    }
	    buffer[p++] = BASEDIGIT(digit);
	} while (!done);
    }
    return JS_Substring(cx, buffer, 0, p);
}
/*
 * dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
 *
 * Inspired by "How to Print Floating-Point Numbers Accurately" by
 * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
 *
 * Modifications:
 *  1. Rather than iterating, we use a simple numeric overestimate
 * to determine k = floor(log10(d)).  We scale relevant
 * quantities using O(log2(k)) rather than O(k) multiplications.
 *  2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
 * try to generate digits strictly left to right.  Instead, we
 * compute with fewer bits and propagate the carry if necessary
 * when rounding the final digit up.  This is often faster.
 *  3. Under the assumption that input will be rounded nearest,
 * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
 * That is, we allow equality in stopping tests when the
 * round-nearest rule will give the same floating-point value
 * as would satisfaction of the stopping test with strict
 * inequality.
 *  4. We remove common factors of powers of 2 from relevant
 * quantities.
 *  5. When converting floating-point integers less than 1e16,
 * we use floating-point arithmetic rather than resorting
 * to multiple-precision integers.
 *  6. When asked to produce fewer than 15 digits, we first try
 * to get by with floating-point arithmetic; we resort to
 * multiple-precision integer arithmetic only if we cannot
 * guarantee that the floating-point calculation has given
 * the correctly rounded result.  For k requested digits and
 * "uniformly" distributed input, the probability is
 * something like 10^(k-15) that we must resort to the Long
 * calculation.
 */
/*
 * Always emits at least one digit.
 * If biasUp is set, then rounding in modes 2 and 3 will round away from zero
 * when the number is exactly halfway between two representable values.
 * For example, rounding 2.5 to zero digits after the decimal point will
 * return 3 and not 2.
 * 2.49 will still round to 2, and 2.51 will still round to 3.
 * bufsize should be at least 20 for modes 0 and 1.  For the other modes,
 * bufsize should be two greater than the maximum number of output characters
 * expected.
*/
int
JSDToA::JS_dtoa(JSContext *cx, double d, int mode, jsBool_t biasUp,
		int ndigits, jsBool_t *sign, JSStringBuffer *buf)
{
    /*  Arguments ndigits, decpt, sign are similar to those
	of ecvt and fcvt; trailing zeros are suppressed from
	the returned string.  If not null, *rve is set to point
	to the end of the return value.  If d is +-Infinity or NaN,
	then *decpt is set to 9999.

	mode:
	0 ==> shortest string that yields d when read in
	and rounded to nearest.
	1 ==> like 0, but with Steele & White stopping rule;
	e.g. with IEEE P754 arithmetic , mode 0 gives
	1e23 whereas mode 1 gives 9.999999999999999e22.
	2 ==> max(1,ndigits) significant digits.  This gives a
	return value similar to that of ecvt, except
	that trailing zeros are suppressed.
	3 ==> through ndigits past the decimal point.  This
	gives a return value similar to that from fcvt,
	except that trailing zeros are suppressed, and
	ndigits can be negative.
	4-9 should give the same return values as 2-3, i.e.,
	4 <= mode <= 9 ==> same return as mode
	2 + (mode & 1).  These modes are mainly for
	debugging; often they run slower but sometimes
	faster than modes 2-3.
	4,5,8,9 ==> left-to-right digit generation.
	6-9 ==> don't try fast floating-point estimate
	(if applicable).

	Values of mode other than 0-9 are treated as mode 0.

	Sufficient space is allocated to the return value
	to hold the suppressed trailing zeros.
    */

    int b2, b5, i, ieps, ilim, ilim0, ilim1,
    	j, j1, k, k0, m2, m5, s2, s5;
    jsChar_t dig;
    long L;
    long x;
    JSBigInteger b(cx), b1(cx), delta(cx), mlo(cx), mhi(cx), S(cx);
    int be;
    int bbits;
    double d2, ds, eps;
    jsBool_t spec_case, denorm, k_check, try_quick, leftright;

    if ((word0(d) & Sign_bit) != 0) {
	/* set sign for everything, including 0's and NaNs */
	*sign = TRUE;
	// word0(d) &= ~Sign_bit;  /* clear sign bit */
	d = setWord0(d, word0(d) & ~Sign_bit);
    } else {
	*sign = FALSE;
    }

    if ((word0(d) & Exp_mask) == Exp_mask) {
	/* Infinity or NaN */
	buf->append(((word1(d) == 0) && ((word0(d) & Frac_mask) == 0)) ?
		(jsString_t) "Infinity" : (jsString_t) "NaN");
	return 9999;
    }
    if (d == 0) {
	buf->setLength(0);
	buf->append('0');		/* copy "0" to buffer */
	return 1;
    }

    b = d2b(cx, d, &be, &bbits);
    i = (int32_t)(((uint32_t) word0(d) >> Exp_shift1)
			& (Exp_mask >> Exp_shift1)) ;
    if (i != 0) {
	d2 = setWord0(d, (word0(d) & Frac_mask1) | Exp_11);

	/*
	 * log(x)   ~=~ log(1.5) + (x-1.5)/1.5
	 * log10(x)  =  log(x) / log(10)
	 *      ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
	 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
	 *
	 * This suggests computing an approximation k to log10(d) by
	 *
	 * k = (i - Bias)*0.301029995663981
	 *  + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
	 *
	 * We want k to be too large rather than too small.
	 * The error in the first-order Taylor series approximation
	 * is in our favor, so we just round up the constant enough
	 * to compensate for any error in the multiplication of
	 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
	 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
	 * adding 1e-13 to the constant term more than suffices.
	 * Hence we adjust the constant term to 0.1760912590558.
	 * (We could get a more accurate k by invoking log10,
	 *  but this is probably not worthwhile.)
	 */
	 i -= Bias;
	 denorm = FALSE;
    } else {
	/* d is denormalized */
	i = bbits + be + (Bias + (P-1) - 1);
	x = (i > 32) ? word0(d) << (64 - i)
				| ((uint32_t) word1(d)) >> (i - 32) :
		       word1(d) << (32 - i);
	d2 = setWord0(x, word0(x) - 31*Exp_msk1);
	i -= (Bias + (P-1) - 1) + 1;
	denorm = TRUE;
    }
    /*
     * At this point d = f*2^i, where 1 <= f < 2. 
     * d2 is an approximation of f.
     */
    ds = (d2 - 1.5) * 0.289529654602168 + 0.1760912590558
	+ i * 0.301029995663981;
    k = (int32_t) ds;
    if (ds < 0.0 && ds != k) {
	k--;	/* want k = floor(ds) */
    }
    k_check = TRUE;
    if (k >= 0 && k <= Ten_pmax) {
	if (d < tens[k]) {
	    k--;
	}
	k_check = FALSE;
    }
    /*
     * At this point floor(log10(d)) <= k <= floor(log10(d))+1.
     * If k_check is zero, we're guaranteed that k = floor(log10(d)).
     */
    j = bbits - i - 1;
    /* At this point d = b/2^j, where b is an odd integer. */
    if (j >= 0) {
	b2 = 0;
	s2 = j;
    } else {
	b2 = -j;
	s2 = 0;
    }
    if (k >= 0) {
	b5 = 0;
	s5 = k;
	s2 += k;
    } else {
	b2 -= k;
	b5 = -k;
	s5 = 0;
    }
    /*
     * At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5),
     * where b is an odd integer, b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0.
     */
    if (mode < 0 || mode > 9) {
	mode = 0;
    }
    try_quick = TRUE;
    if (mode > 5) {
	mode -= 4;
	try_quick = FALSE;
    }
    leftright = TRUE;
    ilim = ilim1 = 0;
    switch (mode) {
    case 0:
    case 1:
	ilim = ilim1 = -1;
	i = 18;
	ndigits = 0;
	break;
    case 2:
	leftright = FALSE;
	/* no break */
    case 4:
	if (ndigits <= 0) {
	    ndigits = 1;
	}
	ilim = ilim1 = i = ndigits;
	break;
    case 3:
	leftright = FALSE;
	/* no break */
    case 5:
	i = ndigits + k + 1;
	ilim = i;
	ilim1 = i - 1;
	if (i <= 0) {
	    i = 1;
	}
    }
    /*
     * ilim is the maximum number of significant digits we want, based on k and
     * ndigits.
     * ilim1 is the maximum number of significant digits we want, based on k
     * and ndigits, when it turns out that k was computed too high by one.
     */
    jsBool_t fast_failed = FALSE;

    if (ilim >= 0 && ilim <= Quick_max && try_quick) {
	/* Try to get by with floating-point arithmetic. */
	i = 0;
	d2 = d;
	k0 = k;
	ilim0 = ilim;
	ieps = 2; /* conservative */
	/*
	 * Divide d by 10^k, keeping track of the roundoff error and avoiding
	 * overflows.
	 */
	if (k > 0) {
	    ds = tens[k&0xf];
	    j = k >> 4;
	    if ((j & Bletch) != 0) {
		/* prevent overflows */
		j &= Bletch - 1;
		d /= bigtens[n_bigtens-1];
		ieps++;
	    }
	    for (; (j != 0); j >>= 1, i++) {
		if ((j & 1) != 0) {
		    ieps++;
		    ds *= bigtens[i];
		}
	    }
	    d /= ds;
	} else if ((j1 = -k) != 0) {
	    d *= tens[j1 & 0xf];
	    for (j = j1 >> 4; (j != 0); j >>= 1, i++) {
		if ((j & 1) != 0) {
		    ieps++;
		    d *= bigtens[i];
		}
	    }
	}
	/* Check that k was computed correctly. */
	if (k_check && d < 1.0 && ilim > 0) {
	    if (ilim1 <= 0) {
		fast_failed = TRUE;
	    } else {
		ilim = ilim1;
		k--;
		d *= 10.;
		ieps++;
	    }
	}
	/* eps bounds the cumulative error. */
	eps = ieps*d + 7.0;
	eps = setWord0(eps, word0(eps) - (P-1)*Exp_msk1);
	if (ilim == 0) {
	    // S = mhi = null;
	    d -= 5.0;
	    if (d > eps) {
		buf->append('1');
		k++;
		return (k + 1);
	    }
	    if (d < -eps) {
		buf->setLength(0);
		buf->append('0');		/* copy "0" to buffer */
		return 1;
	    }
	    fast_failed = TRUE;
	}
	if (!fast_failed) {
	    fast_failed = TRUE;
	    if (leftright) {
		/*
		 * Use Steele & White method of only
		 * generating digits needed.
		 */
		eps = 0.5 / tens[ilim-1] - eps;
		for (i = 0;; ) {
		    L = (int64_t) d;
		    d -= L;
		    buf->append((jsChar_t) ('0' + L));
		    if (d < eps) {
			return (k + 1);
		    }
		    if (1.0 - d < eps) {
			char lastCh;

			while (TRUE) {
			    lastCh = buf->charAt(buf->length() - 1);
			    buf->setLength(buf->length() - 1);
			    if (lastCh != '9') break;
			    if (buf->length() == 0) {
				k++;
				lastCh = '0';
				break;
			    }
			}								
			buf->append((jsChar_t) (lastCh + 1));
			return (k + 1);
		    }
		    if (++i >= ilim) break;
		    eps *= 10.0;
		    d *= 10.0;
		}
	    } else {
		/* Generate ilim digits, then fix them up. */
		eps *= tens[ilim-1];
		for (i = 1;; i++, d *= 10.0) {
		    L = (int64_t) d;
		    d -= L;
		    buf->append((jsChar_t) ('0' + L));
		    if (i == ilim) {
			if (d > 0.5 + eps) {
			    char lastCh;

			    while (TRUE) {
				lastCh = buf->charAt(buf->length() - 1);
				buf->setLength(buf->length() - 1);
				if (lastCh != '9') break;
				if (buf->length() == 0) {
				    k++;
				    lastCh = '0';
				    break;
				}
			    }								
			    buf->append((jsChar_t) (lastCh + 1));
			    return (k + 1);
			} else if (d < 0.5 - eps) {
			    while (buf->charAt(buf->length() - 1) == '0') {
				buf->setLength(buf->length() - 1);
			    }
			    return (k + 1);
			}
			break;
		    }
		}
	    }
	}
	if (fast_failed) {
	    buf->setLength(0);
	    d = d2;
	    k = k0;
	    ilim = ilim0;
	}
    }

    /* Do we have a "small" integer? */

    if (be >= 0 && k <= Int_max) {
	/* Yes. */
	ds = tens[k];
	if (ndigits < 0 && ilim <= 0) {
	    // S = mhi = null;
	    if (ilim < 0 || d < 5*ds || (!biasUp && d == 5*ds)) {
		buf->setLength(0);
		buf->append('0');	/* copy "0" to buffer */
		return 1;
	    }
	    buf->append('1');
	    k++;
	    return (k + 1);
	}
	for (i = 1;; i++) {
	    L = (int64_t) (d / ds);
	    d -= L*ds;
	    buf->append((jsChar_t) ('0' + L));
	    if (i == ilim) {
		d += d;
		if ((d > ds) || (d == ds && (((L & 1) != 0) || biasUp))) {
		    char lastCh;

		    while (TRUE) {
			lastCh = buf->charAt(buf->length() - 1);
			buf->setLength(buf->length() - 1);
			if (lastCh != '9') break;
			if (buf->length() == 0) {
			    k++;
			    lastCh = '0';
			    break;
			}
		    }								
		    buf->append((jsChar_t) (lastCh + 1));
		}
		break;
	    }
	    d *= 10.0;
	    if (d == 0) break;
	}
	return (k + 1);
    }

    m2 = b2;
    m5 = b5;
    if (leftright) {
	if (mode < 2) {
	    i = (denorm) ? be + (Bias + (P - 1) - 1 + 1) : 1 + P - bbits;
	    /*
	     * i is 1 plus the number of trailing zero bits in d's significand.
	     * Thus, (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k.
	     */
	} else {
	    j = ilim - 1;
	    if (m5 >= j) {
		m5 -= j;
	    } else {
		s5 += j -= m5;
		b5 += j;
		m5 = 0;
	    }
	    if ((i = ilim) < 0) {
		m2 -= i;
		i = 0;
	    }
	    /* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */
	}
	b2 += i;
	s2 += i;
	mhi = JSBigInteger::valueOf(cx, 1);
	/*
	 * (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed
	 * (when mode >= 2) or input (when mode < 2) significant digit,
	 * divided by 10^k.
	 */
    }
    /*
     * We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5).
     * Reduce common factors in b2, m2, and s2 without changing the equalities.
     */
    if (m2 > 0 && s2 > 0) {
	i = (m2 < s2) ? m2 : s2;
	b2 -= i;
	m2 -= i;
	s2 -= i;
    }

    /* Fold b5 into b and m5 into mhi. */
    if (b5 > 0) {
	if (leftright) {
	    if (m5 > 0) {
		mhi = pow5mult(cx, mhi, m5);
		b1 = mhi.multiply(cx, b);
		b = b1;
	    }
	    if ((j = b5 - m5) != 0) {
		    b = pow5mult(cx, b, j);
	    }
	} else {
	    b = pow5mult(cx, b, b5);
	}
    }
    /* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and
     * (mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input
     * significant digit, divided by 10^k.
     */

    S = JSBigInteger::valueOf(cx, 1);
    if (s5 > 0) {
	S = pow5mult(cx, S, s5);
    }
    /*
     * Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and
     * (mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input
     * significant digit, divided by 10^k.
     */

    /* Check for special case that d is a normalized power of 2. */
    spec_case = FALSE;
    if (mode < 2) {
	if (
	   (word1(d) == 0) && ((word0(d) & Bndry_mask) == 0)
	   && ((word0(d) & (Exp_mask & Exp_mask << 1)) != 0)
	) {
	    /*
	     * The special case.  Here we want to be within a quarter of
	     * the last input significant digit instead of one half of it
	     * when the decimal output string's value is less than d.
	     */
	    b2 += Log2P;
	    s2 += Log2P;
	    spec_case = TRUE;
	}
    }

    /*
     * Arrange for convenient computation of quotients:
     * shift left if necessary so divisor has 4 leading 0 bits.
     *
     * Perhaps we should just compute leading 28 bits of S once
     * and for all and pass them and a shift to quorem, so it
     * can do shifts and ors to compute the numerator for q.
     */
    int S_bytesLength;
    JSBigInteger::Digit *S_bytes = S.toDigitArray(cx, &S_bytesLength);
    int S_hiWord = 0;

    for (int idx = 0;
	idx < (int) (sizeof (S_hiWord) / sizeof (JSBigInteger::Digit)); idx++) {
	int mask = (1LL << (8 * sizeof (JSBigInteger::Digit))) - 1;

	if (sizeof (S_hiWord) != sizeof (JSBigInteger::Digit)) {
	    S_hiWord = S_hiWord << (8 * sizeof (JSBigInteger::Digit));
	}
	if (idx < S_bytesLength) {
	    S_hiWord |= (S_bytes[idx] & mask);
	}
    }
    JS_DeleteZoneObj(cx, S_bytes);

    if ((i = (((s5 != 0) ? 32 - hi0bits(S_hiWord) : 1) + s2) & 0x1f) != 0) {
	i = 32 - i;
    }
    /*
     * i is the number of leading zero bits in the most significant
     * word of S*2^s2.
     */
    if (i > 4) {
	i -= 4;
	b2 += i;
	m2 += i;
	s2 += i;
    } else if (i < 4) {
	i += 28;
	b2 += i;
	m2 += i;
	s2 += i;
    }
    /*
     * Now S*2^s2 has exactly four leading zero bits in its most
     * significant word.
     */
    if (b2 > 0) {
	b = b.shiftLeft(cx, b2);
    }
    if (s2 > 0) {
	S = S.shiftLeft(cx, s2);
    }
    /*
     * Now we have d/10^k = b/S and
     * (mhi * 2^m2) / S = maximum acceptable error, divided by 10^k.
     */
    if (k_check) {
	if (b.compareTo(S) < 0) {
	    k--;
	    /* we botched the k estimate */
	    JSBigInteger val = JSBigInteger::valueOf(cx, 10);

	    b = b.multiply(cx, val);
	    if (leftright) {
		mhi = mhi.multiply(cx, val);
	    }
	    ilim = ilim1;
	}
    }
    /* At this point 1 <= d/10^k = b/S < 10. */

    if (ilim <= 0 && mode > 2) {
	/*
	 * We're doing fixed-mode output and d is less than the minimum
	 * nonzero output in this mode.
	 * Output either zero or the minimum nonzero output depending on
	 * which is closer to d.
	 */
	JSBigInteger val = JSBigInteger::valueOf(cx, 5);

	if ((ilim < 0)
	    || ((i = b.compareTo(S = S.multiply(cx, val))) < 0)
	    || (i == 0 && !biasUp)) {
	    /*
	     * Always emit at least one digit.  If the number appears to
	     * be zero using the current mode, then emit one '0' digit
	     * and set decpt to 1.
	     */
	    buf->setLength(0);
	    buf->append('0');	/* copy "0" to buffer */
	    return 1;
	}
	buf->append('1');
	k++;
	return (k + 1);
    }
    if (leftright) {
	if (m2 > 0) {
	    mhi = mhi.shiftLeft(cx, m2);
	}
	/*
	 * Compute mlo -- check for special case
	 * that d is a normalized power of 2.
	 */

	mlo = mhi;
	if (spec_case) {
	    mhi = mlo;
	    mhi = mhi.shiftLeft(cx, Log2P);
	}
	/*
	 * mlo/S = maximum acceptable error, divided by 10^k, if the output
	 * is less than d.
	 * mhi/S = maximum acceptable error, divided by 10^k, if the output
	 * is greater than d.
	 */

	for (i = 1;;i++) {				
	    JSBigInteger div(cx), rem(cx);
	    JSBigInteger *divResult[] = { &div, &rem };

	    b.divideAndRemainder(cx, divResult, S);

	    b = *divResult[1];				
	    dig = (jsChar_t) (divResult[0]->int64Value() + '0');

	    /*
	     * Do we yet have the shortest decimal string
	     * that will round to d?
	     */
	    j = b.compareTo(mlo);

	    /* j is b/S compared with mlo/S. */
	    delta = S.subtract(cx, mhi);
	    j1 = (delta.getSignum() <= 0) ? 1 : b.compareTo(delta);

	    /* j1 is b/S compared with 1 - mhi/S. */
	    if ((j1 == 0) && (mode == 0) && ((word1(d) & 1) == 0)) {
		if (dig == '9') {
		    buf->append('9');
		    if (roundOff(buf)) {
			k++;
			buf->append('1');
		    }
		    return (k + 1);
		}
		if (j > 0) {
		    dig++;
		}
		buf->append(dig);
		return (k + 1);
	    }
	    if ((j < 0) 
		|| ((j == 0) && (mode == 0) && ((word1(d) & 1) == 0))) {
		if (j1 > 0) {
		    /*
		     * Either dig or dig+1 would work here as the least
		     * significant decimal digit.
		     * Use whichever would produce a decimal value closer to d.
		     */
		    b = b.shiftLeft(cx, 1);
		    j1 = b.compareTo(S);
		    if (((j1 > 0) || (j1 == 0 && (((dig & 1) == 1) || biasUp)))
			&& (dig++ == '9')) {
			buf->append('9');
			if (roundOff(buf)) {
			    k++;
			    buf->append('1');
			}
			return (k + 1);
		    }
		}
		buf->append(dig);
		return (k + 1);
	    }
	    if (j1 > 0) {
		if (dig == '9') { /* possible if i == 1 */
		    buf->append('9');
		    if (roundOff(buf)) {
			k++;
			buf->append('1');
		    }			
		    return (k + 1);
		}
		buf->append((jsChar_t) (dig + 1));
		return (k + 1);
	    }
	    buf->append(dig);
	    if (i == ilim) break;

	    JSBigInteger val = JSBigInteger::valueOf(cx, 10);

	    b = b.multiply(cx, val);
	    if (mlo.equals(mhi)) {
		mlo = mhi = mhi.multiply(cx, val);
	    } else {
		mlo = mlo.multiply(cx, val);
		mhi = mhi.multiply(cx, val);
	    }
	}
    } else {
	for (i = 1;; i++) {
	    JSBigInteger div(cx), rem(cx);
	    JSBigInteger *divResult[] = { &div, &rem };

	    b.divideAndRemainder(cx, divResult, S);
	    b = *divResult[1];				
	    dig = (jsChar_t) (divResult[0]->int64Value() + '0');
	    buf->append(dig);
	    if (i >= ilim) break;

	    JSBigInteger val = JSBigInteger::valueOf(cx, 10);
	    b = b.multiply(cx, val);
	}
    }

    /* Round off last digit */

    b = b.shiftLeft(cx, 1);
    j = b.compareTo(S);
    if ((j > 0) || (j == 0 && (((dig & 1) == 1) || biasUp))) {
	if (roundOff(buf)) {
	    k++;
	    buf->append('1');
	    return (k + 1);
	}			
    } else {
	/* Strip trailing zeros */
	while (buf->charAt(buf->length() - 1) == '0')
	buf->setLength(buf->length() - 1);
    }
    return k + 1;
}
void
JSDToA::JS_dtostr(JSContext *cx, JSStringBuffer *buffer, int mode,
		int precision, double d)
{
    int decPt;		/* Position of decimal point relative to first digit
			   returned by JS_dtoa */
    jsBool_t sign;	/* true if the sign bit was set in d */
    int nDigits;	/* Number of significand digits returned by JS_dtoa */

    if (mode == DTOSTR_FIXED && (d >= 1e21 || d <= -1e21)) {
	/*
	 * Change mode here rather than below because the buffer may not be
	 * large enough to hold a large integer.
	 */
	mode = DTOSTR_STANDARD;
    }

    decPt = JS_dtoa(cx, d, dtoaModes[mode], mode >= DTOSTR_FIXED,
		precision, &sign, buffer);
    nDigits = buffer->length();

    /*
     * If Infinity, -Infinity, or NaN, return the string regardless of
     * the mode.
     */
    if (decPt != 9999) {
	jsBool_t exponentialNotation = FALSE;
	int minNDigits = 0;	/* Minimum number of significand digits
				   required by mode and precision */
	int p;

	switch (mode) {
	case DTOSTR_STANDARD:
	    if (decPt < -5 || decPt > 21) {
		exponentialNotation = TRUE;
	    } else {
		minNDigits = decPt;
	    }
	    break;

	case DTOSTR_FIXED:
	    if (precision >= 0) {
		minNDigits = decPt + precision;
	    } else {
		minNDigits = decPt;
	    }
	    break;

	case DTOSTR_EXPONENTIAL:
	    minNDigits = precision;
	    /* Fall through */
	case DTOSTR_STANDARD_EXPONENTIAL:
	    exponentialNotation = TRUE;
	    break;

	case DTOSTR_PRECISION:
	    minNDigits = precision;
	    if (decPt < -5 || decPt > precision) {
		exponentialNotation = TRUE;
	    }
	    break;
	}

	/*
	 * If the number has fewer than minNDigits, pad it with zeros at the
	 * end
	 */
	if (nDigits < minNDigits) {
	    p = minNDigits;
	    nDigits = minNDigits;
	    do {
		buffer->append('0');
	    } while (buffer->length() != p);
	}
	    
	if (exponentialNotation) {
	    /* Insert a decimal point if more than one significand digit */
	    if (nDigits != 1) {
		buffer->insert(1, '.');
	    }
	    buffer->append('e');
	    if ((decPt - 1) >= 0) {
		buffer->append('+');
	    }
	    buffer->append(decPt - 1);
	} else if (decPt != nDigits) {
	    /* Some kind of a fraction in fixed notation */
	    if (decPt > 0) {
		/* dd...dd . dd...dd */
		buffer->insert(decPt, '.');
	    } else {
		/* 0 . 00...00dd...dd */
		for (int i = 0; i < 1 - decPt; i++) {
		    buffer->insert(0, '0');
		}
		buffer->insert(1, '.');
	    }
	}
    }

    /* If negative and neither -0.0 nor NaN, output a leading '-'. */
    if (sign &&
	!(word0(d) == Sign_bit && word1(d) == 0) &&
	!((word0(d) & Exp_mask) == Exp_mask &&
	((word1(d) != 0) || ((word0(d) & Frac_mask) != 0)))) {
	buffer->insert(0, '-');
    }
}

#endif /* DTOA */

