Rhino.DToA.JS_dtoa C# (CSharp) Method

JS_dtoa() static private method

static private JS_dtoa ( double d, int mode, bool biasUp, int ndigits, bool sign, StringBuilder buf ) : int
d double
mode int
biasUp bool
ndigits int
sign bool
buf StringBuilder
return int
		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;
		}