internal static string FormatNumber(NumberStore ns, int precision, NumberFormatInfo nfi)
		{
			precision = (precision >= 0 ? precision : nfi.NumberDecimalDigits);
			StringBuilder sb = new StringBuilder(ns.IntegerDigits * 3 + precision);

			ns.RoundDecimal(precision);
			bool needNegativeSign = (!ns.Positive && !ns.ZeroOnly);

			if (needNegativeSign)
			{
				switch (nfi.NumberNegativePattern)
				{
					case 0:
						sb.Append('(');
						break;
					case 1:
						sb.Append(nfi.NegativeSign);
						break;
					case 2:
						sb.Append(nfi.NegativeSign);
						sb.Append(' ');
						break;
				}
			}

			ns.AppendIntegerStringWithGroupSeparator(sb, nfi.NumberGroupSizes, nfi.NumberGroupSeparator);

			if (precision > 0)
			{
				sb.Append(nfi.NumberDecimalSeparator);
				ns.AppendDecimalString(precision, sb);
			}

			if (needNegativeSign)
			{
				switch (nfi.NumberNegativePattern)
				{
					case 0:
						sb.Append(')');
						break;
					case 3:
						sb.Append(nfi.NegativeSign);
						break;
					case 4:
						sb.Append(' ');
						sb.Append(nfi.NegativeSign);
						break;
				}
			}

			return sb.ToString();
		}
		internal static string FormatPercent(NumberStore ns, int precision, NumberFormatInfo nfi)
		{
			precision = (precision >= 0 ? precision : nfi.PercentDecimalDigits);
			ns.Multiply10(2);
			ns.RoundDecimal(precision);
			bool needNegativeSign = (!ns.Positive && !ns.ZeroOnly);

			StringBuilder sb = new StringBuilder(ns.IntegerDigits * 2 + precision + 16);

			if (!needNegativeSign)
			{
				if (nfi.PercentPositivePattern == 2)
				{
					sb.Append(nfi.PercentSymbol);
				}
			}
			else
			{
				switch (nfi.PercentNegativePattern)
				{
					case 0:
						sb.Append(nfi.NegativeSign);
						break;
					case 1:
						sb.Append(nfi.NegativeSign);
						break;
					case 2:
						sb.Append(nfi.NegativeSign);
						sb.Append(nfi.PercentSymbol);
						break;
				}
			}

			ns.AppendIntegerStringWithGroupSeparator(sb, nfi.PercentGroupSizes, nfi.PercentGroupSeparator);

			if (precision > 0)
			{
				sb.Append(nfi.PercentDecimalSeparator);
				ns.AppendDecimalString(precision, sb);
			}

			if (!needNegativeSign)
			{
				switch (nfi.PercentPositivePattern)
				{
					case 0:
						sb.Append(' ');
						sb.Append(nfi.PercentSymbol);
						break;
					case 1:
						sb.Append(nfi.PercentSymbol);
						break;
				}
			}
			else
			{
				switch (nfi.PercentNegativePattern)
				{
					case 0:
						sb.Append(' ');
						sb.Append(nfi.PercentSymbol);
						break;
					case 1:
						sb.Append(nfi.PercentSymbol);
						break;
				}
			}

			return sb.ToString();
		}
		internal static string FormatCurrency(NumberStore ns, int precision, NumberFormatInfo nfi)
		{
			precision = (precision >= 0 ? precision : nfi.CurrencyDecimalDigits);
			ns.RoundDecimal(precision);
			StringBuilder sb = new StringBuilder(ns.IntegerDigits * 2 + precision * 2 + 16);
			bool needNegativeSign = !ns.Positive && !ns.ZeroOnly;

			if (!needNegativeSign)
			{
				switch (nfi.CurrencyPositivePattern)
				{
					case 0:
						sb.Append(nfi.CurrencySymbol);
						break;
					case 2:
						sb.Append(nfi.CurrencySymbol);
						sb.Append(' ');
						break;
				}
			}
			else
			{
				switch (nfi.CurrencyNegativePattern)
				{
					case 0:
						sb.Append('(');
						sb.Append(nfi.CurrencySymbol);
						break;
					case 1:
						sb.Append(nfi.NegativeSign);
						sb.Append(nfi.CurrencySymbol);
						break;
					case 2:
						sb.Append(nfi.CurrencySymbol);
						sb.Append(nfi.NegativeSign);
						break;
					case 3:
						sb.Append(nfi.CurrencySymbol);
						break;
					case 4:
						sb.Append('(');
						break;
					case 5:
						sb.Append(nfi.NegativeSign);
						break;
					case 8:
						sb.Append(nfi.NegativeSign);
						break;
					case 9:
						sb.Append(nfi.NegativeSign);
						sb.Append(nfi.CurrencySymbol);
						sb.Append(' ');
						break;
					case 11:
						sb.Append(nfi.CurrencySymbol);
						sb.Append(' ');
						break;
					case 12:
						sb.Append(nfi.CurrencySymbol);
						sb.Append(' ');
						sb.Append(nfi.NegativeSign);
						break;
					case 14:
						sb.Append('(');
						sb.Append(nfi.CurrencySymbol);
						sb.Append(' ');
						break;
					case 15:
						sb.Append('(');
						break;
				}
			}

			ns.AppendIntegerStringWithGroupSeparator(sb, nfi.CurrencyGroupSizes, nfi.CurrencyGroupSeparator);

			if (precision > 0)
			{
				sb.Append(nfi.CurrencyDecimalSeparator);
				ns.AppendDecimalString(precision, sb);
			}

			if (!needNegativeSign)
			{
				switch (nfi.CurrencyPositivePattern)
				{
					case 1:
						sb.Append(nfi.CurrencySymbol);
						break;
					case 3:
						sb.Append(' ');
						sb.Append(nfi.CurrencySymbol);
						break;
				}
			}
			else
			{
				switch (nfi.CurrencyNegativePattern)
				{
					case 0:
						sb.Append(')');
						break;
					case 3:
						sb.Append(nfi.NegativeSign);
						break;
					case 4:
						sb.Append(nfi.CurrencySymbol);
						sb.Append(')');
						break;
					case 5:
						sb.Append(nfi.CurrencySymbol);
						break;
					case 6:
						sb.Append(nfi.NegativeSign);
						sb.Append(nfi.CurrencySymbol);
						break;
					case 7:
						sb.Append(nfi.CurrencySymbol);
						sb.Append(nfi.NegativeSign);
						break;
					case 8:
						sb.Append(' ');
						sb.Append(nfi.CurrencySymbol);
						break;
					case 10:
						sb.Append(' ');
						sb.Append(nfi.CurrencySymbol);
						sb.Append(nfi.NegativeSign);
						break;
					case 11:
						sb.Append(nfi.NegativeSign);
						break;
					case 13:
						sb.Append(nfi.NegativeSign);
						sb.Append(' ');
						sb.Append(nfi.CurrencySymbol);
						break;
					case 14:
						sb.Append(')');
						break;
					case 15:
						sb.Append(' ');
						sb.Append(nfi.CurrencySymbol);
						sb.Append(')');
						break;
				}
			}

			return sb.ToString();
		}