internal static int JS_dtoa(double d, int mode, bool biasUp, int ndigits, bool[] sign, StringBuilder buf)
{
int b2;
int b5;
int i;
int ieps;
int ilim;
int ilim0;
int ilim1;
int j;
int j1;
int k;
int k0;
int m2;
int m5;
int s2;
int s5;
char dig;
long L;
long x;
BigInteger b;
BigInteger b1;
BigInteger delta;
BigInteger mlo;
BigInteger mhi;
BigInteger S;
int[] be = new int[1];
int[] bbits = new int[1];
double d2;
double ds;
double eps;
bool spec_case;
bool denorm;
bool k_check;
bool try_quick;
bool leftright;
if ((Word0(d) & Sign_bit) != 0)
{
sign[0] = true;
// word0(d) &= ~Sign_bit; /* clear sign bit */
d = SetWord0(d, Word0(d) & ~Sign_bit);
}
else
{
sign[0] = false;
}
if ((Word0(d) & Exp_mask) == Exp_mask)
{
buf.Append(((Word1(d) == 0) && ((Word0(d) & Frac_mask) == 0)) ? "Infinity" : "NaN");
return 9999;
}
if (d == 0)
{
// no_digits:
buf.Length = 0;
buf.Append('0');
return 1;
}
b = D2b(d, be, bbits);
if ((i = ((int)(((uint)Word0(d)) >> Exp_shift1) & (Exp_mask >> Exp_shift1))) != 0)
{
d2 = SetWord0(d, (Word0(d) & Frac_mask1) | Exp_11);
i -= Bias;
denorm = false;
}
else
{
i = bbits[0] + be[0] + (Bias + (P - 1) - 1);
x = (i > 32) ? ((long)Word0(d)) << (64 - i) | (int)(((uint)Word1(d)) >> (i - 32)) : ((long)Word1(d)) << (32 - i);
// d2 = x;
// word0(d2) -= 31*Exp_msk1; /* adjust exponent */
d2 = SetWord0(x, Word0(x) - 31 * Exp_msk1);
i -= (Bias + (P - 1) - 1) + 1;
denorm = true;
}
ds = (d2 - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981;
k = (int)ds;
if (ds < 0.0 && ds != k)
{
k--;
}
k_check = true;
if (k >= 0 && k <= Ten_pmax)
{
if (d < tens[k])
{
k--;
}
k_check = false;
}
j = bbits[0] - i - 1;
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;
}
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;
goto case 4;
}
case 4:
{
if (ndigits <= 0)
{
ndigits = 1;
}
ilim = ilim1 = i = ndigits;
break;
}
case 3:
{
leftright = false;
goto case 5;
}
case 5:
{
i = ndigits + k + 1;
ilim = i;
ilim1 = i - 1;
if (i <= 0)
{
i = 1;
}
break;
}
}
bool fast_failed = false;
if (ilim >= 0 && ilim <= Quick_max && try_quick)
{
i = 0;
d2 = d;
k0 = k;
ilim0 = ilim;
ieps = 2;
if (k > 0)
{
ds = tens[k & unchecked((int)(0xf))];
j = k >> 4;
if ((j & Bletch) != 0)
{
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 & unchecked((int)(0xf))];
for (j = j1 >> 4; (j != 0); j >>= 1, i++)
{
if ((j & 1) != 0)
{
ieps++;
d *= bigtens[i];
}
}
}
}
if (k_check && d < 1.0 && ilim > 0)
{
if (ilim1 <= 0)
{
fast_failed = true;
}
else
{
ilim = ilim1;
k--;
d *= 10.;
ieps++;
}
}
// eps = ieps*d + 7.0;
// word0(eps) -= (P-1)*Exp_msk1;
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.Length = 0;
buf.Append('0');
return 1;
}
fast_failed = true;
}
if (!fast_failed)
{
fast_failed = true;
if (leftright)
{
eps = 0.5 / tens[ilim - 1] - eps;
for (i = 0; ; )
{
L = (long)d;
d -= L;
buf.Append((char)('0' + L));
if (d < eps)
{
return k + 1;
}
if (1.0 - d < eps)
{
// goto bump_up;
char lastCh;
while (true)
{
lastCh = buf[buf.Length - 1];
buf.Length = buf.Length - 1;
if (lastCh != '9')
{
break;
}
if (buf.Length == 0)
{
k++;
lastCh = '0';
break;
}
}
buf.Append((char)(lastCh + 1));
return k + 1;
}
if (++i >= ilim)
{
break;
}
eps *= 10.0;
d *= 10.0;
}
}
else
{
eps *= tens[ilim - 1];
for (i = 1; ; i++, d *= 10.0)
{
L = (long)d;
d -= L;
buf.Append((char)('0' + L));
if (i == ilim)
{
if (d > 0.5 + eps)
{
// goto bump_up;
char lastCh;
while (true)
{
lastCh = buf[buf.Length - 1];
buf.Length = buf.Length - 1;
if (lastCh != '9')
{
break;
}
if (buf.Length == 0)
{
k++;
lastCh = '0';
break;
}
}
buf.Append((char)(lastCh + 1));
return k + 1;
}
else
{
if (d < 0.5 - eps)
{
StripTrailingZeroes(buf);
// while(*--s == '0') ;
// s++;
return k + 1;
}
}
break;
}
}
}
}
if (fast_failed)
{
buf.Length = 0;
d = d2;
k = k0;
ilim = ilim0;
}
}
if (be[0] >= 0 && k <= Int_max)
{
ds = tens[k];
if (ndigits < 0 && ilim <= 0)
{
S = mhi = null;
if (ilim < 0 || d < 5 * ds || (!biasUp && d == 5 * ds))
{
buf.Length = 0;
buf.Append('0');
return 1;
}
buf.Append('1');
k++;
return k + 1;
}
for (i = 1; ; i++)
{
L = (long)(d / ds);
d -= L * ds;
buf.Append((char)('0' + L));
if (i == ilim)
{
d += d;
if ((d > ds) || (d == ds && (((L & 1) != 0) || biasUp)))
{
// bump_up:
// while(*--s == '9')
// if (s == buf) {
// k++;
// *s = '0';
// break;
// }
// ++*s++;
char lastCh;
while (true)
{
lastCh = buf[buf.Length - 1];
buf.Length = buf.Length - 1;
if (lastCh != '9')
{
break;
}
if (buf.Length == 0)
{
k++;
lastCh = '0';
break;
}
}
buf.Append((char)(lastCh + 1));
}
break;
}
d *= 10.0;
if (d == 0)
{
break;
}
}
return k + 1;
}
m2 = b2;
m5 = b5;
mhi = mlo = null;
if (leftright)
{
if (mode < 2)
{
i = (denorm) ? be[0] + (Bias + (P - 1) - 1 + 1) : 1 + P - bbits[0];
}
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;
}
}
b2 += i;
s2 += i;
mhi = Sharpen.Extensions.ValueOf(1);
}
if (m2 > 0 && s2 > 0)
{
i = (m2 < s2) ? m2 : s2;
b2 -= i;
m2 -= i;
s2 -= i;
}
if (b5 > 0)
{
if (leftright)
{
if (m5 > 0)
{
mhi = Pow5mult(mhi, m5);
b1 = System.Numerics.BigInteger.Multiply(mhi, b);
b = b1;
}
if ((j = b5 - m5) != 0)
{
b = Pow5mult(b, j);
}
}
else
{
b = Pow5mult(b, b5);
}
}
S = Sharpen.Extensions.ValueOf(1);
if (s5 > 0)
{
S = Pow5mult(S, s5);
}
spec_case = false;
if (mode < 2)
{
if ((Word1(d) == 0) && ((Word0(d) & Bndry_mask) == 0) && ((Word0(d) & (Exp_mask & Exp_mask << 1)) != 0))
{
b2 += Log2P;
s2 += Log2P;
spec_case = true;
}
}
byte[] S_bytes = S.ToByteArray();
int S_hiWord = 0;
for (int idx = 0; idx < 4; idx++)
{
S_hiWord = (S_hiWord << 8);
if (idx < S_bytes.Length)
{
S_hiWord |= (S_bytes[idx] & unchecked((int)(0xFF)));
}
}
if ((i = (((s5 != 0) ? 32 - Hi0bits(S_hiWord) : 1) + s2) & unchecked((int)(0x1f))) != 0)
{
i = 32 - i;
}
if (i > 4)
{
i -= 4;
b2 += i;
m2 += i;
s2 += i;
}
else
{
if (i < 4)
{
i += 28;
b2 += i;
m2 += i;
s2 += i;
}
}
if (b2 > 0)
{
b = b.ShiftLeft(b2);
}
if (s2 > 0)
{
S = S.ShiftLeft(s2);
}
if (k_check)
{
if (b.CompareTo(S) < 0)
{
k--;
b = System.Numerics.BigInteger.Multiply(b, Sharpen.Extensions.ValueOf(10));
if (leftright)
{
mhi = System.Numerics.BigInteger.Multiply(mhi, Sharpen.Extensions.ValueOf(10));
}
ilim = ilim1;
}
}
if (ilim <= 0 && mode > 2)
{
if ((ilim < 0) || ((i = b.CompareTo(S = System.Numerics.BigInteger.Multiply(S, Sharpen.Extensions.ValueOf(5)))) < 0) || ((i == 0 && !biasUp)))
{
buf.Length = 0;
buf.Append('0');
return 1;
}
// goto no_digits;
// one_digit:
buf.Append('1');
k++;
return k + 1;
}
if (leftright)
{
if (m2 > 0)
{
mhi = mhi.ShiftLeft(m2);
}
mlo = mhi;
if (spec_case)
{
mhi = mlo;
mhi = mhi.ShiftLeft(Log2P);
}
for (i = 1; ; i++)
{
BigInteger[] divResult = b.DivideAndRemainder(S);
b = divResult[1];
dig = (char)(System.Convert.ToInt32(divResult[0]) + '0');
j = b.CompareTo(mlo);
delta = System.Numerics.BigInteger.Subtract(S, mhi);
j1 = (delta.Sign <= 0) ? 1 : b.CompareTo(delta);
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;
}
// goto round_9_up;
if (j > 0)
{
dig++;
}
buf.Append(dig);
return k + 1;
}
if ((j < 0) || ((j == 0) && (mode == 0) && ((Word1(d) & 1) == 0)))
{
if (j1 > 0)
{
b = b.ShiftLeft(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;
}
}
// goto round_9_up;
buf.Append(dig);
return k + 1;
}
if (j1 > 0)
{
if (dig == '9')
{
// round_9_up:
// *s++ = '9';
// goto roundoff;
buf.Append('9');
if (RoundOff(buf))
{
k++;
buf.Append('1');
}
return k + 1;
}
buf.Append((char)(dig + 1));
return k + 1;
}
buf.Append(dig);
if (i == ilim)
{
break;
}
b = System.Numerics.BigInteger.Multiply(b, Sharpen.Extensions.ValueOf(10));
if (mlo == mhi)
{
mlo = mhi = System.Numerics.BigInteger.Multiply(mhi, Sharpen.Extensions.ValueOf(10));
}
else
{
mlo = System.Numerics.BigInteger.Multiply(mlo, Sharpen.Extensions.ValueOf(10));
mhi = System.Numerics.BigInteger.Multiply(mhi, Sharpen.Extensions.ValueOf(10));
}
}
}
else
{
for (i = 1; ; i++)
{
// (char)(dig = quorem(b,S) + '0');
BigInteger[] divResult = b.DivideAndRemainder(S);
b = divResult[1];
dig = (char)(System.Convert.ToInt32(divResult[0]) + '0');
buf.Append(dig);
if (i >= ilim)
{
break;
}
b = System.Numerics.BigInteger.Multiply(b, Sharpen.Extensions.ValueOf(10));
}
}
b = b.ShiftLeft(1);
j = b.CompareTo(S);
if ((j > 0) || (j == 0 && (((dig & 1) == 1) || biasUp)))
{
// roundoff:
// while(*--s == '9')
// if (s == buf) {
// k++;
// *s++ = '1';
// goto ret;
// }
// ++*s++;
if (RoundOff(buf))
{
k++;
buf.Append('1');
return k + 1;
}
}
else
{
StripTrailingZeroes(buf);
}
// while(*--s == '0') ;
// s++;
// ret:
// Bfree(S);
// if (mhi) {
// if (mlo && mlo != mhi)
// Bfree(mlo);
// Bfree(mhi);
// }
// ret1:
// Bfree(b);
// JS_ASSERT(s < buf + bufsize);
return k + 1;
}