2005-01-31 Kazuki Oikawa <kazuki@panicode.com>
authorMiguel de Icaza <miguel@gnome.org>
Mon, 31 Jan 2005 05:35:20 +0000 (05:35 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Mon, 31 Jan 2005 05:35:20 +0000 (05:35 -0000)
* Patch from Kazuki Oikawa <kazuki@panicode.com> that replaces the
old Integer and Floating point number string formatter with a new
formatter that is more compliant.

This fixes: http://bugzilla.ximian.com/show_bug.cgi?id=71286

svn path=/trunk/mcs/; revision=39817

mcs/class/corlib/ChangeLog
mcs/class/corlib/System/FloatingPointFormatter.cs [deleted file]
mcs/class/corlib/System/IntegerFormatter.cs [deleted file]
mcs/class/corlib/System/NumberFormatter.cs [new file with mode: 0644]
mcs/class/corlib/System/SingleFormatter.cs
mcs/class/corlib/corlib.dll.sources

index b49996a17b3bcf7a135e0c1bae98ddfcaacbbd74..946133a21df5611873acf8a180caef0d4da401ec 100644 (file)
@@ -1,3 +1,9 @@
+2005-01-31  Kazuki Oikawa <kazuki@panicode.com>
+
+       * Patch from Kazuki Oikawa <kazuki@panicode.com> that replaces the
+       old Integer and Floating point number string formatter with a new
+       formatter that is more compliant. 
+
 2005-01-17  Atsushi Enomoto  <atsushi@ximian.com>
 
        * corlib.dll.sources : added CharUnicodeInfo.cs.
diff --git a/mcs/class/corlib/System/FloatingPointFormatter.cs b/mcs/class/corlib/System/FloatingPointFormatter.cs
deleted file mode 100644 (file)
index 29e337e..0000000
+++ /dev/null
@@ -1,1202 +0,0 @@
-//
-// System.FloatingPointFormatter.cs
-//
-// Authors:
-//     Pedro Martinez Julia <yoros@wanadoo.es>
-//     Jon Skeet <skeet@pobox.com>
-//     Sebastien Pouliot  <sebastien@ximian.com>
-//
-// Copyright (C) 2003 Pedro Martíez Juliá <yoros@wanadoo.es>
-// Copyright (C) 2004 Jon Skeet
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Text;
-using System.Collections;
-using System.Globalization;
-
-
-namespace System {
-
-       internal class FloatingPointFormatter {
-
-               struct Format {
-                       public double p;
-                       public double p10;
-                       public int dec_len;
-                       public int dec_len_min;
-               }
-               
-               Format format1;
-               Format format2;
-
-               public FloatingPointFormatter
-                       (double p, double p10, int dec_len, int dec_len_min,
-                        double p2, double p102, int dec_len2, int dec_len_min2) {
-                        
-                       format1.p = p;
-                       format1.p10 = p10;
-                       format1.dec_len = dec_len;
-                       format1.dec_len_min = dec_len_min;
-                       
-                       format2.p = p2;
-                       format2.p10 = p102;
-                       format2.dec_len = dec_len2;
-                       format2.dec_len_min = dec_len_min2;
-               }
-
-               public string GetStringFrom
-                               (string format, NumberFormatInfo nfi, double value) {
-                               
-                       if (format == null || format == "") {
-                               format = "G";
-                       }
-                       if (nfi == null) {
-                               nfi = NumberFormatInfo.CurrentInfo;
-                       }
-                       if (Double.IsNaN(value)) {
-                               return nfi.NaNSymbol;
-                       }
-                       if (Double.IsNegativeInfinity(value)) {
-                               return nfi.NegativeInfinitySymbol;
-                       }
-                       if (Double.IsPositiveInfinity(value)) {
-                               return nfi.PositiveInfinitySymbol;
-                       }
-                       
-                       char specifier;
-                       int precision;
-                       if (!ParseFormat(format, out specifier, out precision)) {
-                               return FormatCustom (format1, value, nfi, format);
-                       }
-                       
-                       Format formatData = format1;//(precision > format1.dec_len+1) ? format2 : format1;
-                       
-                       switch (specifier) {
-                       case 'C':
-                               return FormatCurrency (formatData, value, nfi, precision);
-                       case 'D':
-                               throw new FormatException(Locale.GetText(
-                                       "The specified format is invalid") + ": " + format);
-                       case 'E':
-                               formatData = (precision > format1.dec_len) ? format2 : format1;
-                               return FormatExponential (formatData, value, nfi, precision, format[0]);
-                       case 'F':
-                               return FormatFixedPoint (formatData, value, nfi, precision);
-                       case 'G':
-                               return FormatGeneral (formatData, value, nfi, precision);
-                       case 'N':
-                               return FormatNumber (formatData, value, nfi, precision);
-                       case 'P':
-                               return FormatPercent (formatData, value, nfi, precision);
-                       case 'R':
-                               return FormatReversible (value, nfi, precision);
-                       case 'X':
-                               throw new FormatException(Locale.GetText(
-                                       "The specified format is invalid") + ": " + format);
-                       default:
-                               throw new FormatException(Locale.GetText(
-                                       "The specified format is invalid") + ": " + format);
-                       }
-               }
-
-               private bool ParseFormat (string format,
-                               out char specifier, out int precision) {
-                       specifier = '\0';
-                       precision = format2.dec_len;
-                       
-                       // FIXME: Math.Round is used and the max is 15.
-                       
-                       if (precision > 15)
-                               precision = 15;
-                               
-                       switch (format.Length) {
-                       case 1:
-                               specifier = Char.ToUpperInvariant(format[0]);
-                               precision = -1;
-                               return true;
-                       case 2:
-                               if (Char.IsLetter(format[0]) && Char.IsDigit(format[1])) {
-                                       specifier = Char.ToUpperInvariant(format[0]);
-                                       precision = Convert.ToInt32(format[1] - '0');
-                                       return true;
-                               }
-                               break;
-                       case 3:
-                               if (Char.IsLetter(format[0]) && Char.IsDigit(format[1])
-                                               && Char.IsDigit(format[2])) {
-                                       specifier = Char.ToUpperInvariant(format[0]);
-                                       precision = Convert.ToInt32(format.Substring(1, 2));
-                                       return true;
-                               }
-                               break;
-                       }
-                       return false;
-               }
-
-               // Math.Round use banker's rounding while this is not what must
-               // be used for string formatting (see bug #60111)
-               // http://bugzilla.ximian.com/show_bug.cgi?id=60111
-
-               // FIXME: should be moved out of here post Mono 1.0
-               private double Round (double value) 
-               {
-                       double int_part = Math.Floor (value);\r
-                       double dec_part = value - int_part;\r
-                       if (dec_part >= 0.5) {\r
-                               int_part++;\r
-                       }\r
-                       return int_part;\r
-               }
-               
-               // FIXME: should be moved out of here post Mono 1.0
-               private double Round (double value, int digits) 
-               {
-                       if (digits == 0)\r
-                               return Round (value);\r
-                       double p = Math.Pow (10, digits);\r
-                       double int_part = Math.Floor (value);\r
-                       double dec_part = value - int_part;\r
-                       dec_part *= 1000000000000000L;\r
-                       dec_part = Math.Floor (dec_part);\r
-                       dec_part /= (1000000000000000L / p);\r
-                       dec_part = Round (dec_part);\r
-                       dec_part /= p;\r
-                       return int_part + dec_part;\r
-               }
-
-               private void Normalize (Format formatData, double value, int precision,
-                               out long mantissa, out int exponent) {
-                       mantissa = 0;
-                       exponent = 0;
-                       if (value == 0.0 ||
-                               Double.IsInfinity(value) ||
-                               Double.IsNaN(value)) {
-                               return;
-                       }
-                       value = Math.Abs(value);
-                       if (precision <= (formatData.dec_len) && precision >= 0) {
-                               value = Round (value, precision);
-                       }
-                       
-                       if (value == 0.0 ||
-                               Double.IsInfinity(value) ||
-                               Double.IsNaN(value)) {
-                               return;
-                       }
-                       
-                       if (value >= formatData.p10) {
-                               while (value >= formatData.p10) {
-                                       value /= 10;
-                                       exponent++;
-                               }
-                       }
-                       else if (value < formatData.p) {
-                               while (value < formatData.p) {
-                                       value *= 10;
-                                       exponent--;
-                               }
-                       }
-                       mantissa = (long) Round(value);
-               }
-
-               private string FormatCurrency (Format formatData, double value,
-                               NumberFormatInfo nfi, int precision) {
-                               
-                       precision = (precision >= 0) ? precision : nfi.CurrencyDecimalDigits;
-                       string numb = FormatNumberInternal (formatData, value, nfi, precision);
-                       if (value < 0) {
-                               switch (nfi.CurrencyNegativePattern) {
-                               case 0:
-                                       return "(" + nfi.CurrencySymbol + numb + ")";
-                               case 1:
-                                       return nfi.NegativeSign + nfi.CurrencySymbol + numb;
-                               case 2:
-                                       return nfi.CurrencySymbol + nfi.NegativeSign + numb;
-                               case 3:
-                                       return nfi.CurrencySymbol + numb + nfi.NegativeSign;
-                               case 4:
-                                       return "(" + numb + nfi.CurrencySymbol + ")";
-                               case 5:
-                                       return nfi.NegativeSign + numb + nfi.CurrencySymbol;
-                               case 6:
-                                       return numb + nfi.NegativeSign + nfi.CurrencySymbol;
-                               case 7:
-                                       return numb + nfi.CurrencySymbol + nfi.NegativeSign;
-                               case 8:
-                                       return nfi.NegativeSign + numb + " " + nfi.CurrencySymbol;
-                               case 9:
-                                       return nfi.NegativeSign + nfi.CurrencySymbol + " " + numb;
-                               case 10:
-                                       return numb + " " + nfi.CurrencySymbol + nfi.NegativeSign;
-                               case 11:
-                                       return nfi.CurrencySymbol + " " + numb + nfi.NegativeSign;
-                               case 12:
-                                       return nfi.CurrencySymbol + " " + nfi.NegativeSign + numb;
-                               case 13:
-                                       return numb + nfi.NegativeSign + " " + nfi.CurrencySymbol;
-                               case 14:
-                                       return "(" + nfi.CurrencySymbol + " " + numb + ")";
-                               case 15:
-                                       return "(" + numb + " " + nfi.CurrencySymbol + ")";
-                               default:
-                                       throw new ArgumentException(Locale.GetText(
-                                               "Invalid CurrencyNegativePattern"));
-                               }
-                       }
-                       else {
-                               switch (nfi.CurrencyPositivePattern) {
-                               case 0:
-                                       return nfi.CurrencySymbol + numb ;
-                               case 1:
-                                       return numb + nfi.CurrencySymbol;
-                               case 2:
-                                       return nfi.CurrencySymbol + " " + numb;
-                               case 3:
-                                       return numb + " " + nfi.CurrencySymbol;
-                               default:
-                                       throw new ArgumentException(Locale.GetText(
-                                               "invalid CurrencyPositivePattern"));
-                               }
-                       }
-               }
-
-               private string FormatExponential (Format formatData, double value, NumberFormatInfo nfi,
-                               int precision, char exp_char) {
-                       StringBuilder sb = new StringBuilder();
-                       precision = (precision >= 0) ? precision : 6;
-                       int decimals = precision;
-                       long mantissa;
-                       int exponent;
-                       Normalize (formatData, value, precision, out mantissa, out exponent);
-                       if (formatData.dec_len > precision) {
-                               double aux = mantissa;
-                               for (int i = 0; i < formatData.dec_len - precision; i++) {
-                                       aux /= 10;
-                               }
-                               mantissa = (long) Round(aux);
-                               for (int i = 0; i < formatData.dec_len - precision; i++) {
-                                       mantissa *= 10;
-                               }
-                       }
-                       bool not_null = false;
-                       if (mantissa != 0.0) {
-                               for (int i = 0; i < formatData.dec_len || mantissa >= 10; i++) {
-                                       if ((not_null == false) && ((mantissa % 10) != 0)) {
-                                               not_null = true;
-                                       }
-                                       if (not_null) {
-                                               sb.Insert(0, (char)('0' + (mantissa % 10)));
-                                               precision--;
-                                       }
-                                       mantissa /= 10;
-                                       exponent++;
-                               }
-                       }
-                       if (decimals == 0) {
-                               sb = new StringBuilder();
-                               sb.Append((char)('0' + (mantissa % 10)));
-                       }
-                       else {
-                               while (precision > 0) {
-                                       sb.Append('0');
-                                       precision--;
-                               }
-                               if (sb.Length == 0) {
-                                       sb.Insert(0, "0");
-                               }
-                               sb.Insert (0, (char)('0' + (mantissa % 10)) +
-                                               nfi.NumberDecimalSeparator);
-                       }
-                       if (exponent >= 0) {
-                               sb.Append(exp_char + nfi.PositiveSign);
-                       }
-                       else {
-                               sb.Append(exp_char + nfi.NegativeSign);
-                       }
-                       sb.Append(Math.Abs(exponent).ToString("000"));
-                       if (value < 0.0) {
-                               sb.Insert(0, nfi.NegativeSign);
-                       }
-                       return sb.ToString();
-               }
-
-               private string FormatFixedPoint (Format formatData, double value,
-                               NumberFormatInfo nfi, int precision) {
-                       StringBuilder sb = new StringBuilder();
-                       precision = (precision >= 0) ? precision : nfi.NumberDecimalDigits;
-                       int decimals = precision;
-                       long mantissa;
-                       int exponent;
-                       Normalize (formatData, value, precision, out mantissa, out exponent);
-                       if (exponent >= 0) {
-                               while (decimals > 0) {
-                                       sb.Append("0");
-                                       decimals--;
-                               }
-                       }
-                       else {
-                               int decimal_limit = -(decimals + 1);
-                               while (exponent < 0) {
-                                       if (exponent > decimal_limit) {
-                                               sb.Insert(0, (char)('0' + (mantissa % 10)));
-                                       }
-                                       mantissa /= 10;
-                                       exponent++;
-                                       decimals--;
-                               }
-                               if (decimals > 0) {
-                                       sb.Append ('0', decimals);
-                                       decimals = 0;
-                               }
-                       }
-                       if (precision != 0) {
-                               sb.Insert(0, nfi.NumberDecimalSeparator);
-                       }
-                       if (mantissa == 0) {
-                               sb.Insert(0, "0");
-                       }
-                       else {
-                               while (exponent > 0) {
-                                       sb.Insert(0, "0");
-                                       exponent--;
-                               }
-                               while (mantissa != 0) {
-                                       sb.Insert(0, (char)('0' + (mantissa % 10)));
-                                       mantissa /= 10;
-                               }
-                       }
-                       if (value < 0.0) {
-                               sb.Insert(0, nfi.NegativeSign);
-                       }
-                       return sb.ToString();
-               }
-
-               private string FormatGeneral (Format formatData, double value,
-                               NumberFormatInfo nfi, int precision) {
-                       StringBuilder sb = new StringBuilder();
-                       if (value == 0.0) {
-                               sb.Append("0");
-                       }
-                       else {
-                               precision = (precision > 0) ?
-                                       precision : formatData.dec_len+1;
-                                       
-                               long mantissa;
-                               int exponent;
-                               Normalize (formatData, value, precision, out mantissa, out exponent);
-                               if (precision > 0) {
-                                       double dmant = mantissa;
-                                       for (int i = 0; i < formatData.dec_len - precision + 1; i++) {
-                                               dmant /= 10;
-                                       }
-                                       mantissa = (long) Round (dmant);
-                                       for (int i = 0; i < formatData.dec_len - precision + 1; i++) {
-                                               mantissa *= 10;
-                                       }
-                               }
-                               
-                               /* Calculate the exponent we would get using the scientific notation */
-                               int snExponent = exponent;
-                               long snMantissa = mantissa;
-                       
-                               while (snMantissa >= 10) {
-                                       snMantissa /= 10;
-                                       snExponent++;
-                               }
-                               
-                               if (snExponent > -5 && snExponent < precision) {
-                                       bool not_null = false;
-                                       while (exponent < 0) {
-                                               if ((not_null == false) && ((mantissa % 10) != 0)) {
-                                                       not_null = true;
-                                               }
-                                               if (not_null) {
-                                                       sb.Insert(0, (char)('0' + (mantissa % 10)));
-                                               }
-                                               mantissa /= 10;
-                                               exponent++;
-                                       }
-                                       if (sb.Length != 0) {
-                                               sb.Insert(0, nfi.NumberDecimalSeparator);
-                                       }
-                                       if (mantissa == 0) {
-                                               sb.Insert(0, "0");
-                                       }
-                                       else {
-                                               while (mantissa > 0) {
-                                                       sb.Insert(0, (char)('0' + (mantissa % 10)));
-                                                       mantissa /= 10;
-                                               }
-                                       }
-                               }
-                               else {
-                                       bool not_null = false;
-                                       while (mantissa >= 10) {
-                                               if ((not_null == false) && ((mantissa % 10) != 0)) {
-                                                       not_null = true;
-                                               }
-                                               if (not_null) {
-                                                       sb.Insert (0, (char)('0' + (mantissa % 10)));
-                                               }
-                                               mantissa /= 10;
-                                               exponent++;
-                                       }
-                                       if (sb.Length != 0)
-                                         sb.Insert(0, nfi.NumberDecimalSeparator);
-                                       
-                                       sb.Insert(0, (char)('0' + (mantissa % 10)) );
-
-                                       if (exponent > 0) {
-                                               sb.Append("E" + nfi.PositiveSign);
-                                       }
-                                       else {
-                                               sb.Append("E" + nfi.NegativeSign);
-                                       }
-                                       sb.Append(Math.Abs(exponent).ToString("00"));
-                               }
-                               if (value < 0.0) {
-                                       sb.Insert(0, nfi.NegativeSign);
-                               }
-                       }
-                       return sb.ToString();
-               }
-
-               private string FormatNumber (Format formatData, double value, NumberFormatInfo nfi, int precision) {
-               
-                       precision = (precision >= 0) ? precision : nfi.NumberDecimalDigits;
-                       string numb = FormatNumberInternal (formatData, value, nfi, precision);
-                       if (value < 0) {
-                               switch (nfi.NumberNegativePattern) {
-                               case 0:
-                                       return "(" + numb + ")";
-                               case 1:
-                                       return nfi.NegativeSign + numb;
-                               case 2:
-                                       return nfi.NegativeSign + " " + numb;
-                               case 3:
-                                       return numb + nfi.NegativeSign;
-                               case 4:
-                                       return numb + " " + nfi.NegativeSign;
-                               default:
-                                       throw new ArgumentException(Locale.GetText(
-                                               "Invalid NumberNegativePattern"));
-                               }
-                       }
-                       return numb;
-               }
-
-               private string FormatPercent (Format formatData, double value, NumberFormatInfo nfi,
-                               int precision) {
-
-                       precision = (precision >= 0) ? precision : nfi.PercentDecimalDigits;
-                       string numb = FormatNumberInternal (formatData, value*100, nfi, precision);
-                       if (value < 0) {
-                               switch (nfi.PercentNegativePattern) {
-                               case 0:
-                                       return nfi.NegativeSign + numb + " " + nfi.PercentSymbol;
-                               case 1:
-                                       return nfi.NegativeSign + numb + nfi.PercentSymbol;
-                               case 2:
-                                       return nfi.NegativeSign + nfi.PercentSymbol + numb;
-                               default:
-                                       throw new ArgumentException(Locale.GetText(
-                                               "Invalid PercentNegativePattern"));
-                               }
-                       }
-                       else {
-                               switch (nfi.PercentPositivePattern) {
-                               case 0:
-                                       return numb + " " + nfi.PercentSymbol;
-                               case 1:
-                                       return numb + nfi.PercentSymbol;
-                               case 2:
-                                       return nfi.PercentSymbol + numb;
-                               default:
-                                       throw new ArgumentException(Locale.GetText(
-                                               "invalid PercehtPositivePattern"));
-                               }
-                       }
-               }
-
-               private string FormatNumberInternal (Format formatData, double value, NumberFormatInfo nfi, int precision) 
-               {
-                       StringBuilder sb = new StringBuilder();
-                       int decimals = precision;
-                       long mantissa;
-                       int exponent;
-                       Normalize (formatData, value, precision, out mantissa, out exponent);
-                       if (exponent >= 0) {
-                               while (decimals > 0) {
-                                       sb.Append("0");
-                                       decimals--;
-                               }
-                       }
-                       else {
-                               int decimal_limit = -(decimals + 1);
-                               while (exponent < 0) {
-                                       if (exponent > decimal_limit) {
-                                               sb.Insert(0, (char)('0' + (mantissa % 10)));
-                                       }
-                                       mantissa /= 10;
-                                       exponent++;
-                                       decimals--;
-                               }
-                               if (decimals > 0) {
-                                       sb.Append ('0', decimals);
-                                       decimals = 0;
-                               }
-                       }
-                       if (precision != 0) {
-                               sb.Insert(0, nfi.NumberDecimalSeparator);
-                       }
-                       if (mantissa == 0) {
-                               sb.Insert(0, "0");
-                       }
-                       else {
-                               int groupIndex = 0;
-                               int groupPos = 0;
-                               int groupSize = nfi.NumberGroupSizes[0];
-                               if (groupSize == 0) groupSize = int.MaxValue;
-                               
-                               while (exponent > 0 || mantissa != 0) {
-                                       
-                                       if (groupPos == groupSize) {
-                                               sb.Insert (0, nfi.NumberGroupSeparator);
-                                               groupPos = 0;
-                                               if (groupIndex < nfi.NumberGroupSizes.Length - 1) {
-                                                       groupIndex++;
-                                                       groupSize = nfi.NumberGroupSizes[groupIndex];
-                                                       if (groupSize == 0) groupSize = int.MaxValue;
-                                               }
-                                       }
-                                       
-                                       if (exponent > 0) {
-                                               sb.Insert (0, "0");
-                                               exponent--;
-                                       }
-                                       else {
-                                               sb.Insert(0, (char)('0' + (mantissa % 10)));
-                                               mantissa /= 10;
-                                       }
-                                       
-                                       groupPos++;
-                               }
-                       }
-                       return sb.ToString();
-               }
-
-               // from http://www.yoda.arachsys.com/csharp/floatingpoint.html
-               // used with permission from original author
-               private string FormatReversible (double value, NumberFormatInfo nfi, int precision)
-               {
-                       // Translate the double into sign, exponent and mantissa.
-                       long bits = BitConverter.DoubleToInt64Bits (value);
-                       bool negative = ((bits >> 63) == -1);
-                       int exponent = (int) ((bits >> 52) & 0x7ffL);
-                       long mantissa = bits & 0xfffffffffffffL;
-
-                       // Subnormal numbers; exponent is effectively one higher,
-                       // but there's no extra normalisation bit in the mantissa
-                       if (exponent == 0) {
-                               exponent++;
-                       }
-                       // Normal numbers; leave exponent as it is but add extra
-                       // bit to the front of the mantissa
-                       else {
-                               mantissa = mantissa | (1L<<52);
-                       }
-        
-                       // Bias the exponent. It's actually biased by 1023, but we're
-                       // treating the mantissa as m.0 rather than 0.m, so we need
-                       // to subtract another 52 from it.
-                       exponent -= 1075;
-        
-                       if (mantissa == 0) {
-                               return "0";
-                       }
-        
-                       // Normalize
-                       while((mantissa & 1) == 0) {
-                               //  i.e., Mantissa is even
-                               mantissa >>= 1;
-                               exponent++;
-                       }
-        
-                       // Construct a new decimal expansion with the mantissa
-                       ArbitraryDecimal ad = new ArbitraryDecimal (mantissa);
-        
-                       // If the exponent is less than 0, we need to repeatedly
-                       // divide by 2 - which is the equivalent of multiplying
-                       // by 5 and dividing by 10.
-                       if (exponent < 0) {
-                               for (int i=0; i < -exponent; i++)
-                                       ad.MultiplyBy (5);
-                               ad.Shift (-exponent);
-                       }
-                       // Otherwise, we need to repeatedly multiply by 2
-                       else {
-                               for (int i=0; i < exponent; i++)
-                                       ad.MultiplyBy(2);
-                       }
-        
-                       // Finally, return the string with an appropriate sign
-                       if (negative)
-                               return nfi.NegativeSign + ad.ToString (nfi);
-                       else
-                               return ad.ToString (nfi);
-               }
-
-               private string FormatCustom (Format formatData, double value,
-                               NumberFormatInfo nfi, string format) {
-                       int first_semicolon, second_semicolon, third_semicolon;
-                       first_semicolon = format.IndexOf(';');
-                       second_semicolon = format.IndexOf(';', first_semicolon + 1);
-                       if (second_semicolon < 0) {
-                               if (first_semicolon == -1) {
-                                       if (value < 0.0) {
-                                               string result = FormatCustomParser (formatData, value, nfi, format);
-                                               if (result == "0") {
-                                                       return "0";
-                                               }
-                                               if (result.Length > 0) {
-                                                       result = nfi.NegativeSign + result;
-                                               }
-                                               return result;
-                                       }
-                                       return FormatCustomParser (formatData, value, nfi, format);
-                                       
-                               }
-                               if (value < 0.0) {
-                                       return FormatCustomParser
-                                               (formatData, value, nfi, format.Substring(first_semicolon + 1));
-                               }
-                               return FormatCustomParser (formatData, value, nfi,
-                                               format.Substring(0, first_semicolon - 1));
-                       }
-                       if (value > 0.0) {
-                               return FormatCustomParser (formatData, value, nfi,
-                                               format.Substring(0, first_semicolon - 1));
-                       }
-                       else if (value < 0.0) {
-                               return FormatCustomParser (formatData, value, nfi,
-                                               format.Substring (first_semicolon + 1,
-                                                       second_semicolon - first_semicolon - 1));
-                       }
-                       third_semicolon = second_semicolon < 0 ?  - 1 : format.IndexOf (';', second_semicolon + 1);
-                       if (third_semicolon < 0)
-                               return FormatCustomParser (formatData, value,
-                                       nfi, format.Substring(second_semicolon + 1));
-                       else
-                               return FormatCustomParser (formatData, value,
-                                       nfi, format.Substring(second_semicolon + 1, third_semicolon - second_semicolon - 1));
-               }
-
-               private struct Flags {
-                       public int NumberOfColons;
-                       public bool Groupping;
-                       public bool Percent;
-                       public bool Permille;
-                       public int DotPos;
-                       public int ExpPos;
-                       public int FirstFormatPos;
-                       public int IntegralLength;
-                       public int DecimalLength;
-                       public int ExponentialLength;
-               }
-
-               private Flags AnalizeFormat (string format) {
-                       Flags f = new Flags();
-                       f.NumberOfColons = 0;
-                       f.DotPos = -1;
-                       f.ExpPos = -1;
-                       f.Groupping = false;
-                       f.Percent = false;
-                       f.FirstFormatPos = -1;
-                       int aux = 0, i = 0, count = 0;
-                       bool inQuote = false;
-                       foreach (char c in format) {
-                               if (c == '\'') {
-                                       if (inQuote)
-                                               inQuote = false;
-                                       else
-                                               inQuote = true;
-                                       i++;
-                                       continue;
-                               } else if (inQuote) {
-                                       i++;
-                                       continue;
-                               }
-
-                               switch (c) {
-                               case ',':
-                                       aux++;
-                                       break;
-                               case '0':
-                               case '#':
-                                       if (f.FirstFormatPos < 0) {
-                                               f.FirstFormatPos = i;
-                                       }
-                                       if (aux > 0) {
-                                               f.Groupping = true;
-                                               aux = 0;
-                                       }
-                                       if (count < 15)
-                                               count++;
-                                       break;
-                               case '.':
-                                       if (f.DotPos >= 0)
-                                               break; // ignore
-                                       f.DotPos = i;
-                                       f.IntegralLength = count;
-                                       count = 0;
-                                       if (aux > 0) {
-                                               f.NumberOfColons = aux;
-                                               aux = 0;
-                                       }
-                                       break;
-                               case '%':
-                                       f.Percent = true;
-                                       break;
-                               case '\u2030':
-                                       f.Permille = true;
-                                       break;
-                               case 'e':
-                               case 'E':
-                                       f.DecimalLength = count;
-                                       count = 0;
-                                       f.ExpPos = i;
-                                       break;
-                               }
-                               i++;
-                       }
-                       if (inQuote)
-                               throw new FormatException ("Literal in format string is not correctly terminated.");
-                       if (aux > 0) {
-                               f.NumberOfColons = aux;
-                       }
-                       if (f.DecimalLength > 0) {
-                               f.ExponentialLength = count;
-                       }
-                       else {
-                               f.DecimalLength = count;
-                       }
-                       return f;
-               }
-
-               private string FormatCustomParser (Format formatData, double value,
-                               NumberFormatInfo nfi, string format) {
-                       long mantissa;
-                       int exponent;
-                       Flags f = AnalizeFormat(format);
-                       if (f.FirstFormatPos < 0) {
-                               return format;
-                       }
-                       if (((f.Percent) || (f.Permille) || (f.NumberOfColons > 0)) && (f.ExpPos < 0)) {
-                               int len = f.DecimalLength;
-                               int exp = 0;
-                               if (f.Percent) {
-                                       len += 2;
-                                       exp += 2;
-                               }
-                               else if (f.Permille) {
-                                       len += 3;
-                                       exp += 3;
-                               }
-                               if (f.NumberOfColons > 0) {
-                                       len -= (3 * f.NumberOfColons);
-                                       exp -= 3 * f.NumberOfColons;
-                               }
-                               if (len < 0) {
-                                       len = 0;
-                               }
-                               value = Round(value, len);
-                               Normalize (formatData, value, 15, out mantissa, out exponent);
-                               exponent += exp;
-                       }
-                       else {
-                               value = Round(value, f.DecimalLength);
-                               Normalize (formatData, value, 15, out mantissa, out exponent);
-                       }
-                       StringBuilder sb = new StringBuilder();
-                       if (f.ExpPos > 0) {
-                               StringBuilder sb_decimal = new StringBuilder();
-                               while (mantissa > 0) {
-                                       sb_decimal.Insert(0, (char)('0' + (mantissa % 10)));
-                                       mantissa /= 10;
-                                       exponent++;
-                               }
-                               exponent--;
-                               int k;
-                               for (k = sb_decimal.Length - 1;
-                                       k >= 0 && sb_decimal[k] == '0'; k--);
-                               sb_decimal.Remove(k + 1, sb_decimal.Length - k - 1);
-                               for (int i = f.DotPos - 2; i >= 0; i--) {
-                                       char c = format[i];
-                                       if (i > 0 && format[i-1] == '\\') {
-                                               sb.Insert(0, c);
-                                               i -= 2;
-                                               continue;
-                                       }
-                                       switch (c) {
-                                       case ',':
-                                       case '#':
-                                               break;
-                                       case '0':
-                                               sb.Insert(0, '0');
-                                               break;
-                                       default:
-                                               sb.Insert(0, c);
-                                               break;
-                                       }
-                               }
-                               sb.Append(sb_decimal[0]);
-                               sb.Append(nfi.NumberDecimalSeparator);
-                               for (int j = 1, i = f.DotPos + 1; i < f.ExpPos; i++) {
-                                       char c = format[i];
-                                       switch (c) {
-                                       case '\\':
-                                               sb.Append(format[++i]);
-                                               break;
-                                       case '0':
-                                               if (j >= sb_decimal.Length) {
-                                                       sb.Append('0');
-                                                       break;
-                                               }
-                                               goto case '#';
-                                       case '#':
-                                               if (j < sb_decimal.Length) {
-                                                       if ((i == f.ExpPos - 1) &&
-                                                                       (j < sb_decimal.Length - 1)) {
-                                                               int a = sb_decimal[j] - '0';
-                                                               int b = sb_decimal[j+1] - '0';
-                                                               if (((b == 5) && ((a % 2) == 0)) || (b > 5)) {
-                                                                       a++;
-                                                               }
-                                                               sb.Append((char)('0' + (a % 10)));
-                                                       }
-                                                       else {
-                                                               sb.Append(sb_decimal[j++]);
-                                                       }
-                                               }
-                                               break;
-                                       default:
-                                               sb.Append(c);
-                                               break;
-                                       }
-                               }
-                               sb.Append(format[f.ExpPos]);
-                               if (exponent < 0) {
-                                       sb.Append('-');
-                               }
-                               int fin, inicio;
-                               inicio = f.ExpPos + 1;
-                               if (format[inicio] == '-') {
-                                       inicio++;
-                               }
-                               else if (format[inicio] == '+') {
-                                       if (exponent >= 0) {
-                                               sb.Append('+');
-                                       }
-                                       inicio++;
-                               }
-                               fin = inicio;
-                               while (fin < format.Length && format[fin++] == '0');
-                               StringBuilder sb_exponent = new StringBuilder();
-                               exponent = Math.Abs(exponent);
-                               while (exponent > 0) {
-                                       sb_exponent.Insert(0, (char)('0' + (exponent % 10)));
-                                       exponent /= 10;
-                               }
-                               while (sb_exponent.Length < (fin - inicio)) {
-                                       sb_exponent.Insert(0, '0');
-                               }
-                               sb.Append(sb_exponent.ToString());
-                               for (int i = fin; i < format.Length; i++) {
-                                       sb.Append(format[i]);
-                               }
-                               return sb.ToString();
-                       }
-                       else {
-                               f.ExpPos = format.Length;
-                       }
-                       if (f.DotPos < 0) {
-                               while (exponent < 0) {
-                                       mantissa = (long) Round((double)mantissa / 10);
-                                       exponent++;
-                               }
-                               f.DotPos = format.Length;
-                       }
-                       else {
-                               StringBuilder sb_decimal = new StringBuilder();
-                               while (exponent < 0) {
-                                       sb_decimal.Insert(0, (char)('0' + (mantissa % 10)));
-                                       mantissa /= 10;
-                                       exponent++;
-                               }
-                               int k;
-                               for (k = sb_decimal.Length - 1;
-                                       k >= 0 && sb_decimal[k] == '0'; k--);
-                               sb_decimal.Remove(k + 1, sb_decimal.Length - k - 1);
-                               if (sb_decimal.Length > 0) {
-                                       sb.Append(nfi.NumberDecimalSeparator);
-                               }
-                               else if (format[f.DotPos + 1] == '0') {
-                                       sb.Append(nfi.NumberDecimalSeparator);
-                               }
-                               bool terminado = false;
-                               for (int j = 0, i = f.DotPos + 1; i < f.ExpPos; i++) {
-                                       if (format[i] == '0' || format[i] == '#') {
-                                               if (j < sb_decimal.Length) {
-                                                       sb.Append(sb_decimal[j++]);
-                                               }
-                                               else if (format[i] == '0' && !terminado) {
-                                                       sb.Append('0');
-                                               }
-                                               else if (format[i] == '#' && !terminado) {
-                                                       terminado = true;
-                                               }
-                                       }
-                                       else if (format[i] == '\\') {
-                                               sb.Append(format[++i]);
-                                       }
-                                       else if (format [i] == '%')
-                                               sb.Append (nfi.PercentSymbol);
-                                       else if (format [i] == '\u2030')
-                                               sb.Append (nfi.PerMilleSymbol);
-                                       else if (format [i] == '\'') {
-                                               int l = ++i;
-                                               while (i < format.Length) {
-                                                       if (format [i] == '\'')
-                                                               break;
-                                                       i++;
-                                               }
-                                               sb.Insert (0, format.Substring (l, i - l));
-                                       }
-                                       else {
-                                               sb.Append(format[i]);
-                                       }
-                               }
-                       }
-                       int gro = 0;
-                       for (int i = f.DotPos - 1; i >= f.FirstFormatPos; i--) {
-                               if (format[i] == '#' || format[i] == '0') {
-                                       if (exponent > 0 || mantissa > 0 || format[i] == '0') {
-                                               if (f.Groupping && gro == nfi.NumberGroupSizes[0]) {
-                                                       sb.Insert(0, nfi.NumberGroupSeparator);
-                                                       gro = 0;
-                                               }
-                                               gro++;
-                                               if (exponent > 0) {
-                                                       sb.Insert(0, '0');
-                                                       exponent--;
-                                               }
-                                               else if (mantissa > 0) {
-                                                       sb.Insert(0, (char)('0' + (mantissa % 10)));
-                                                       mantissa /= 10;
-                                               }
-                                               else if (format[i] == '0') {
-                                                       sb.Insert(0, '0');
-                                               }
-                                       }
-                               }
-                               else if (format [i] == '%')
-                                       sb.Insert (0, nfi.PercentSymbol);
-                               else if (format [i] == '\u2030')
-                                       sb.Insert (0, nfi.PerMilleSymbol);
-                               else if (format [i] == '\'') {
-                                       int l = i;
-                                       while (i >= 0) {
-                                               if (format [i] == '\'')
-                                                       break;
-                                               i--;
-                                       }
-                                       sb.Insert (0, format.Substring (i, l - i));
-                               }
-                               else if (format[i] != ',') {
-                                       sb.Insert(0, format[i]);
-                               }
-                               else if (i > 0 && format[i-1] == '\\') {
-                                       sb.Insert(0, format[i]);
-                                       i -= 2;
-                               }
-                       }
-                       while (exponent > 0) {
-                               if (f.Groupping && gro == nfi.NumberGroupSizes[0]) {
-                                       sb.Insert(0, nfi.NumberGroupSeparator);
-                                       gro = 0;
-                               }
-                               gro++;
-                               sb.Insert(0, '0');
-                               exponent--;
-                       }
-                       while (mantissa > 0) {
-                               if (f.Groupping && gro == nfi.NumberGroupSizes[0]) {
-                                       sb.Insert(0, nfi.NumberGroupSeparator);
-                                       gro = 0;
-                               }
-                               gro++;
-                               sb.Insert(0, (char)('0' + (mantissa % 10)));
-                               mantissa /= 10;
-                       }
-                       for (int i = f.FirstFormatPos - 1; i >= 0; i--) {
-                               if (format [i] == '%')
-                                       sb.Insert (0, nfi.PercentSymbol);
-                               else if (format [i] == '\u2030')
-                                       sb.Insert (0, nfi.PerMilleSymbol);
-                               else if (format [i] == '\'') {
-                                       int l = i;
-                                       while (i >= 0) {
-                                               if (format [i] == '\'')
-                                                       break;
-                                               i--;
-                                       }
-                                       sb.Insert (0, format.Substring (i, l - i));
-                               }
-                               else if (format [i] != '.')
-                                       sb.Insert(0, format[i]);
-                       }
-                       return sb.ToString();
-               }
-
-       }
-
-       // from http://www.yoda.arachsys.com/csharp/floatingpoint.html
-       // used with permission from original author
-       internal class ArbitraryDecimal {
-               /// <summary>Digits in the decimal expansion, one byte per digit
-               byte[] digits;
-               /// <summary> 
-               /// How many digits are *after* the decimal point
-               /// </summary>
-               int decimalPoint=0;
-
-               /// <summary> 
-               /// Constructs an arbitrary decimal expansion from the given long.
-               /// The long must not be negative.
-               /// </summary>
-               internal ArbitraryDecimal (long x)
-               {
-                       string tmp = x.ToString (CultureInfo.InvariantCulture);
-                       digits = new byte [tmp.Length];
-                       for (int i=0; i < tmp.Length; i++)
-                               digits[i] = (byte) (tmp[i] - '0');
-                       Normalize ();
-               }
-        
-               /// <summary>
-               /// Multiplies the current expansion by the given amount, which should
-               /// only be 2 or 5.
-               /// </summary>
-               internal void MultiplyBy (int amount)
-               {
-                       byte[] result = new byte [digits.Length+1];
-                       for (int i=digits.Length-1; i >= 0; i--) {
-                               int resultDigit = digits [i] * amount + result [i+1];
-                               result [i] = (byte)(resultDigit / 10);
-                               result [i+1] = (byte)(resultDigit % 10);
-                       }
-                       if (result [0] != 0) {
-                               digits = result;
-                       }
-                       else {
-                               Array.Copy (result, 1, digits, 0, digits.Length);
-                       }
-                       Normalize ();
-               }
-        
-               /// <summary>
-               /// Shifts the decimal point; a negative value makes
-               /// the decimal expansion bigger (as fewer digits come after the
-               /// decimal place) and a positive value makes the decimal
-               /// expansion smaller.
-               /// </summary>
-               internal void Shift (int amount)
-               {
-                       decimalPoint += amount;
-               }
-
-               /// <summary>
-               /// Removes leading/trailing zeroes from the expansion.
-               /// </summary>
-               internal void Normalize ()
-               {
-                       int first;
-                       for (first=0; first < digits.Length; first++) {
-                               if (digits [first] != 0)
-                                       break;
-                       }
-
-                       int last;
-                       for (last = digits.Length - 1; last >= 0; last--) {
-                               if (digits [last] != 0)
-                                       break;
-                       }
-            
-                       if ((first == 0) && (last == digits.Length - 1))
-                               return;
-            
-                       byte[] tmp = new byte [last-first+1];
-                       for (int i=0; i < tmp.Length; i++)
-                               tmp [i] = digits [i + first];
-            
-                       decimalPoint -= digits.Length - (last + 1);
-                       digits = tmp;
-               }
-
-               /// <summary>
-               /// Converts the value to a proper decimal string representation.
-               /// </summary>
-               public string ToString (NumberFormatInfo nfi)
-               {
-                       char[] digitString = new char [digits.Length];            
-                       for (int i=0; i < digits.Length; i++)
-                               digitString [i] = (char)(digits [i] + '0');
-            
-                       // Simplest case - nothing after the decimal point,
-                       // and last real digit is non-zero, eg value=35
-                       if (decimalPoint == 0) {
-                               return new string (digitString);
-                       }
-            
-                       // Fairly simple case - nothing after the decimal
-                       // point, but some 0s to add, eg value=350
-                       if (decimalPoint < 0) {
-                               return new string (digitString) + new string ('0', -decimalPoint);
-                       }
-            
-                       // Nothing before the decimal point, eg 0.035
-                       if (decimalPoint >= digitString.Length) {
-                               return "0" + nfi.NumberDecimalSeparator + 
-                                       new string ('0',(decimalPoint-digitString.Length))+ new string (digitString);
-                       }
-
-                       // Most complicated case - part of the string comes
-                       // before the decimal point, part comes after it,
-                       // eg 3.5
-                       return new string (digitString, 0, digitString.Length - decimalPoint) +
-                               nfi.NumberDecimalSeparator + 
-                               new string (digitString, digitString.Length - decimalPoint, decimalPoint);
-               }
-       }
-}
diff --git a/mcs/class/corlib/System/IntegerFormatter.cs b/mcs/class/corlib/System/IntegerFormatter.cs
deleted file mode 100644 (file)
index a437529..0000000
+++ /dev/null
@@ -1,2275 +0,0 @@
-//
-// System.IntegerFormatter.cs
-//
-// Author:
-//   Derek Holden  (dholden@draper.com)
-//
-// (C) Derek Holden  dholden@draper.com
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-// 
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-//
-// Format integer types. Completely based off ECMA docs
-// for IFormattable specification. Has been tested w/ 
-// all integral types, from boundry to boundry, w/ all 
-// formats A## ("G", "G0" ... "G99", "P", "P0" ... "P99").
-//
-// If you make any changes, please make sure to check the
-// boundry format precisions (0, 99) and the min / max values
-// of the data types (Int32.[Max/Min]Value).
-//
-// Using int as an example, it is currently set up as
-//
-// Int32 {
-//   int value;
-//   public string ToString (string format, NumberFormatInfo nfi) {
-//      return IntegerFormatter.NumberToString (format, nfi, value);
-//   }
-//
-// IntegerFormatter {
-//   public string NumberToString (string format, NumberFormatInfo nfi, int value) {
-//      ParseFormat (format);
-//      switch (format type) {
-//        case 'G' FormatGeneral(value, precision);
-//        case 'R' throw Exception("Invalid blah blah");
-//        case 'C' FromatCurrency(value, precision, nfi);
-//        etc...
-//      }
-//   }
-// }
-//
-// There is a property in NumberFormatInfo for NegativeSign, though the 
-// definition of IFormattable just uses '-' in context. So all the 
-// hardcoded uses of '-' in here may need to be changed to nfi.NegativeSign
-//
-// For every integral type.
-//
-// Before every Format<Format Type> block there is a small paragraph
-// detailing its requirements, and a blurb of what I was thinking
-// at the time.
-//
-// Some speedup suggestions to be done when after this appears
-// to be working properly:
-//
-//   * Deal w/ out of range numbers better. Specifically with
-//     regards to boundry cases such as Long.MinValue etc.
-//     The previous way of if (value < 0) value = -value;
-//     fails under this assumption, since the largest
-//     possible MaxValue is < absolute value of the MinValue.
-//     I do the first iteration outside of the loop, and then
-//     convert the number to positive, then continue in the loop.
-//
-//   * Replace all occurances of max<Type>Length with their 
-//     numerical values. Plus the places where things are set
-//     to max<Type>Length - 1. Hardcode these to numbers.
-//
-//   * Move the code for all the NumberToString()'s into the
-//     the main ToString (string, NumberFormatInfo) method in
-//     the data types themselves. That way they'd be throwing
-//     their own exceptions on error and it'd save a function
-//     call.
-//
-//   * For integer to char buffer transformation, you could
-//     implement the calculations of the 10's and 100's place
-//     the same time w/ another table to shorten loop time.
-//
-//   * Someone smarter can prolly find a much more efficient 
-//     way of formatting the exponential notation. It's still
-//     done in pass, just may have too many repositioning
-//     calculations.
-//   
-//   * Decide whether it be better to have functions that
-//     handle formatting for all types, or just cast their
-//     values out and format them. Just if library size is
-//     more important than speed in saving a cast and a 
-//     function call.
-//
-
-using System;
-using System.Collections;
-using System.Globalization;
-
-namespace System {
-
-       class IntegerFormatter {
-
-               const int maxByteLength = 4;
-               const int maxShortLength = 6;
-               const int maxIntLength = 12;
-               const int maxLongLength = 22;
-
-               static readonly char [] digitLowerTable =
-               { '0', '1', '2', '3', '4', '5', '6', '7', 
-                 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-
-               static readonly char [] digitUpperTable =
-               { '0', '1', '2', '3', '4', '5', '6', '7', 
-                 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
-               static bool ParseFormat (string format, out char specifier,  out int precision, out bool custom)
-               {                                
-                       precision = -1;
-                       specifier = '\0';
-                       custom = false;
-                       
-                       int length = format.Length;
-                       // TODO: Could an empty string be a custom format string?
-                       if (length < 1)
-                               return false;
-                       
-                       specifier = format [0];
-
-                       if (Char.IsLetter (specifier)) {
-                               switch (length) {
-                               case 1:
-                                       return true;
-                               case 2:
-                                       if (Char.IsDigit (format [1])) {
-                                               precision = format [1] - '0';
-                                               return true;
-                                       }
-                                       break;
-                               case 3:
-                                       if (Char.IsDigit (format [1]) && Char.IsDigit (format [2])) {
-                                               precision = ((format [1] - '0') * 10) + format[2] - '0';
-                                               return true;
-                                       }
-                                       break;
-                               }
-                               
-                       }
-                       
-                       // We've got a custom format string.
-                       custom = true;
-                       return true;
-               }        
-
-               // ============ Public Interface to all the integer types ============ //
-               
-               public static string NumberToString (string format, NumberFormatInfo nfi, short value)
-               {
-                       return NumberToString (format, nfi, maxIntLength, 2, (long)value);
-               }
-
-               public static string NumberToString (string format, NumberFormatInfo nfi, int value)
-               {
-                       return NumberToString (format, nfi, maxIntLength, 4, (long)value);
-               }
-
-               public static string NumberToString (string format, NumberFormatInfo nfi, long value)
-               {
-                       return NumberToString (format, nfi, maxLongLength, 8, value);
-               }
-
-               public static string NumberToString (string format, NumberFormatInfo nfi, sbyte value)
-               {
-                       return NumberToString (format, nfi, maxIntLength, 1, (long)value);
-               }
-               
-               public static string NumberToString (string format, NumberFormatInfo nfi, int maxLength, int integerSize, long value)
-               {
-                       char specifier;
-                       int precision;
-                       bool custom;
-                       
-                       if (!ParseFormat (format, out specifier, out precision, out custom))
-                               throw new FormatException (Locale.GetText ("The specified format '" + format + "' is invalid"));
-                       
-                       if (custom){
-                               return FormatCustom (format, value, nfi, maxLength);
-                       }
-
-                       switch(specifier) {
-                       case 'c': return FormatCurrency (value, precision, nfi, maxLength);
-                       case 'C': return FormatCurrency (value, precision, nfi, maxLength);
-                       case 'd': return FormatDecimal (value, precision, maxLength);
-                       case 'D': return FormatDecimal (value, precision, maxLength);
-                       case 'e': return FormatExponential (value, precision, false, maxLength);
-                       case 'E': return FormatExponential (value, precision, true, maxLength);
-                       case 'f': return FormatFixedPoint (value, precision, nfi, maxLength);   
-                       case 'F': return FormatFixedPoint (value, precision, nfi, maxLength);   
-                       case 'g': return FormatGeneral (value, precision, nfi, false, maxLength);
-                       case 'G': return FormatGeneral (value, precision, nfi, true, maxLength);
-                       case 'n': return FormatNumber (value, precision, nfi, maxLength);
-                       case 'N': return FormatNumber (value, precision, nfi, maxLength);
-                       case 'p': return FormatPercent (value, precision, nfi, maxLength);
-                       case 'P': return FormatPercent (value, precision, nfi, maxLength);
-                       case 'r': throw new FormatException (Locale.GetText ("The specified format cannot be used in this instance"));
-                       case 'R': throw new FormatException (Locale.GetText ("The specified format cannot be used in this instance"));
-                       case 'x': return FormatHexadecimal (value, precision, false, maxLength, integerSize);
-                       case 'X': return FormatHexadecimal (value, precision, true, maxLength, integerSize);
-                       default: 
-                               throw new FormatException (Locale.GetText ("The specified format '" + format + "' is invalid"));
-                       }                       
-               }
-
-               public static string NumberToString (string format, NumberFormatInfo nfi, byte value)
-               {
-                       return NumberToString (format, nfi, maxIntLength, 1, (ulong)value);
-               }               
-
-               public static string NumberToString (string format, NumberFormatInfo nfi, ushort value)
-               {
-                       return NumberToString (format, nfi, maxIntLength, 2, (ulong)value);
-               }
-
-               public static string NumberToString (string format, NumberFormatInfo nfi, uint value)
-               {
-                       return NumberToString (format, nfi, maxIntLength, 4, (ulong)value);
-               }
-
-               public static string NumberToString (string format, NumberFormatInfo nfi, ulong value)
-               {
-                       return NumberToString (format, nfi, maxLongLength, 8, value);
-               }
-               
-               public static string NumberToString (string format, NumberFormatInfo nfi, int maxLength, int integerSize, ulong value)
-               {
-                       char specifier;
-                       int precision;
-                       bool custom;
-                       
-                       if (!ParseFormat (format, out specifier, out precision, out custom))
-                               throw new FormatException (Locale.GetText ("The specified format '" + format + "' is invalid"));
-                       
-                       if (custom){
-                               return FormatCustom (format, value, nfi, maxLength);
-                       }
-                       
-                       switch(specifier) {
-                       case 'c': return FormatCurrency (value, precision, nfi, maxLength);
-                       case 'C': return FormatCurrency (value, precision, nfi, maxLength);
-                       case 'd': return FormatDecimal (value, precision, maxLength);
-                       case 'D': return FormatDecimal (value, precision, maxLength);
-                       case 'e': return FormatExponential (value, precision, false, maxLength);
-                       case 'E': return FormatExponential (value, precision, true, maxLength);
-                       case 'f': return FormatFixedPoint (value, precision, nfi, maxLength);   
-                       case 'F': return FormatFixedPoint (value, precision, nfi, maxLength);   
-                       case 'g': return FormatGeneral (value, precision, nfi, false, maxLength);
-                       case 'G': return FormatGeneral (value, precision, nfi, true, maxLength);
-                       case 'n': return FormatNumber (value, precision, nfi, maxLength);
-                       case 'N': return FormatNumber (value, precision, nfi, maxLength);
-                       case 'p': return FormatPercent (value, precision, nfi, maxLength);
-                       case 'P': return FormatPercent (value, precision, nfi, maxLength);
-                       case 'r': throw new FormatException (Locale.GetText ("The specified format cannot be used in this instance"));
-                       case 'R': throw new FormatException (Locale.GetText ("The specified format cannot be used in this instance"));
-                       case 'x': return FormatHexadecimal (value, precision, false, maxLength);
-                       case 'X': return FormatHexadecimal (value, precision, true, maxLength);
-                       default: 
-                               throw new FormatException (Locale.GetText ("The specified format '" + format + "' is invalid"));
-                       }
-               }
-
-               // ============ Currency Type Formating ============ //
-
-               //
-               //  Currency Format: Used for strings containing a monetary value. The
-               //  CurrencySymbol, CurrencyGroupSizes, CurrencyGroupSeparator, and
-               //  CurrencyDecimalSeparator members of a NumberFormatInfo supply
-               //  the currency symbol, size and separator for digit groupings, and
-               //  decimal separator, respectively.
-               //  CurrencyNegativePattern and CurrencyPositivePattern determine the
-               //  symbols used to represent negative and positive values. For example,
-               //  a negative value may be prefixed with a minus sign, or enclosed in
-               //  parentheses.
-               //  If the precision specifier is omitted
-               //  NumberFormatInfo.CurrencyDecimalDigits determines the number of
-               //  decimal places in the string. Results are rounded to the nearest
-               //  representable value when necessary.
-               //
-               //  The pattern of the NumberFormatInfo determines how the output looks, where
-               //  the dollar sign goes, where the negative sign goes, etc.
-               //  IFormattable documentation lists the patterns and their values,
-               //  I have them commented out in the large switch statement
-               //
-
-               static string FormatCurrency (long value, int precision, NumberFormatInfo nfi, int maxLength)
-               {
-                       int i, j, k;
-                       bool negative = (value < 0);
-
-                       string groupSeparator = nfi.CurrencyGroupSeparator;
-                       string decimalSeparator = nfi.CurrencyDecimalSeparator;
-                       string currencySymbol = nfi.CurrencySymbol;
-                       int[] groupSizes = nfi.CurrencyGroupSizes;
-                       int pattern = negative ? nfi.CurrencyNegativePattern : nfi.CurrencyPositivePattern;
-                       int symbolLength = currencySymbol.Length;
-                       
-                       int padding = (precision >= 0) ? precision : nfi.CurrencyDecimalDigits;      
-                       int size = maxLength + (groupSeparator.Length * maxLength) + padding + 2 + 
-                       decimalSeparator.Length + symbolLength; 
-                       char [] buffy = new char [size];
-                       int position = size;
-
-                       // set up the pattern from IFormattible
-                       if (negative) {
-                               i = symbolLength; 
-                               switch (pattern) {
-                               case 0: // ($nnn)
-                                       buffy[--position] = ')'; 
-                                       break;
-                               // case 1: // -$nnn
-                               //      break;
-                               // case 2: // $-nnn
-                               //      break;
-                               case 3: // $nnn-
-                                       buffy[--position] = '-';
-                                       break;
-                               case 4: // (nnn$)
-                                       buffy[--position] = ')'; 
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               case 5: // -nnn$
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               case 6: // nnn-$
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = '-'; 
-                                       break;
-                               case 7: // nnn$-
-                                       buffy[--position] = '-'; 
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               case 8: // -nnn $
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = ' '; 
-                                       break;
-                               // case 9: // -$ nnn
-                               //      break;
-                               case 10: // nnn $-
-                                       buffy[--position] = '-'; 
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = ' '; 
-                                       break;
-                               case 11: // $ nnn-
-                                       buffy[--position] = '-'; 
-                                       break;
-                               // case 12: // $ -nnn
-                               //      break;
-                               case 13: // nnn- $
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = ' '; 
-                                       buffy[--position] = '-'; 
-                                       break;
-                               case 14: // ($ nnn)
-                                       buffy[--position] = ')'; 
-                                       break;
-                               case 15: // (nnn $)
-                                       buffy[--position] = ')'; 
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;                          
-                               }
-                       } else {
-                               i = symbolLength; 
-                               switch (pattern) {
-                               // case 0: // $nnn
-                               //      break;
-                               case 1: // nnn$
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               // case 2: // $ nnn
-                               //      break;
-                               case 3: // nnn $
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = ' '; 
-                                       break;
-                               }
-                       }
-                       
-                       // right pad it w/ precision 0's
-                       while (padding-- > 0)
-                               buffy[--position] = '0';
-
-                       // put on decimal separator if we moved over and put a 0 
-                       if (position < size && buffy[position] == '0') {
-                               i = decimalSeparator.Length; 
-                               do {
-                                       buffy[--position] = decimalSeparator[--i];
-                               } while (i > 0);                        
-                       }
-
-                       // loop through, keeping track of where you are in the
-                       // group sizes array and putting out the group separator
-                       // when needed
-                       j = 0;
-                       k = groupSizes[j++];
-                      
-                       if (negative) {
-                               if (value <= -10) {
-                                       buffy[--position] = digitLowerTable[-(value % 10)];
-                                       value = value / -10;
-                                       
-                                       if (--k == 0) {
-                                               i = groupSeparator.Length; 
-                                               do {
-                                                       buffy[--position] = groupSeparator[--i];
-                                               } while (i > 0);
-                                               
-                                               k = (j < groupSizes.Length) ? 
-                                               groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                                       }
-                               } else value = -value;
-                       }
-
-                       while (value >= 10) {
-                               buffy[--position] = digitLowerTable[(value % 10)];
-                               value /= 10;
-
-                               if (--k == 0) {
-                                       i = groupSeparator.Length; 
-                                       do {
-                                               buffy[--position] = groupSeparator[--i];
-                                       } while (i > 0);
-                                       
-                                       k = (j < groupSizes.Length) ? 
-                                       groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                               }
-                       }                
-
-                       buffy[--position] = digitLowerTable[value];
-
-                       // end the pattern on the left hand side
-                       if (negative) {
-                               i = symbolLength; 
-                               switch (pattern) {
-                               case 0: // ($nnn)
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = '('; 
-                                       break;
-                               case 1: // -$nnn
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = '-'; 
-                                       break;
-                               case 2: // $-nnn
-                                       buffy[--position] = '-'; 
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               case 3: // $nnn-
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               case 4: // (nnn$)
-                                       buffy[--position] = '('; 
-                                       break;
-                               case 5: // -nnn$
-                                       buffy[--position] = '-'; 
-                                       break;
-                               // case 6: // nnn-$
-                               //      break;
-                               // case 7: // nnn$-
-                               //      break;
-                               case 8: // -nnn $
-                                       buffy[--position] = '-'; 
-                                       break;
-                               // case 9: // -$ nnn
-                               //      break;
-                               // case 10: // nnn $-
-                               //      break;
-                               case 11: // $ nnn-
-                                       buffy[--position] = ' '; 
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               case 12: // $ -nnn
-                                       buffy[--position] = '-'; 
-                                       buffy[--position] = ' '; 
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               // case 13: // nnn- $
-                               //      break;
-                               case 14: // ($ nnn)
-                                       buffy[--position] = ' '; 
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = '('; 
-                                       break;
-                               case 15: // (nnn $)
-                                       buffy[--position] = '('; 
-                                       break;                          
-                               }
-                       } else {
-                               i = symbolLength; 
-                               switch (pattern) {
-                               case 0: // $nnn
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               // case 1: // nnn$
-                               //      break;
-                               case 2: // $ nnn
-                                       buffy[--position] = ' '; 
-                                       do {
-                                               buffy[--position] = currencySymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               // case 3: // nnn $
-                               //      break;
-                               }
-                       }
-                       
-                       return new string (buffy, position, (size - position));
-               }
-
-               static string FormatCurrency (ulong value, int precision, NumberFormatInfo nfi, int maxLength) 
-               {
-                       int i, j, k;
-
-                       string groupSeparator = nfi.CurrencyGroupSeparator;
-                       string decimalSeparator = nfi.CurrencyDecimalSeparator;
-                       string currencySymbol = nfi.CurrencySymbol;
-                       int[] groupSizes = nfi.CurrencyGroupSizes;
-                       int pattern = nfi.CurrencyPositivePattern;
-                       int symbolLength = currencySymbol.Length;
-                       
-                       int padding = (precision >= 0) ? precision : nfi.CurrencyDecimalDigits;      
-                       int size = maxLength + (groupSeparator.Length * maxLength) + padding + 2 + 
-                       decimalSeparator.Length + symbolLength; 
-                       char [] buffy = new char [size];
-                       int position = size;
-
-                       // set up the pattern from IFormattible, no negative
-                       i = symbolLength; 
-                       switch (pattern) {
-                       // case 0: // $nnn
-                       //      break;
-                       case 1: // nnn$
-                               do {
-                                       buffy[--position] = currencySymbol[--i];
-                               } while (i > 0);
-                               break;
-                       // case 2: // $ nnn
-                       //      break;
-                       case 3: // nnn $
-                               do {
-                                       buffy[--position] = currencySymbol[--i];
-                               } while (i > 0);
-                               buffy[--position] = ' '; 
-                               break;
-                       }
-                       
-                       // right pad it w/ precision 0's
-                       while (padding-- > 0)
-                               buffy[--position] = '0';
-
-                       // put on decimal separator if we moved over and put a 0 
-                       if (position < size && buffy[position] == '0') {
-                               i = decimalSeparator.Length; 
-                               do {
-                                       buffy[--position] = decimalSeparator[--i];
-                               } while (i > 0);                        
-                       }
-
-                       // loop through, keeping track of where you are in the
-                       // group sizes array and putting out the group separator
-                       // when needed
-                       j = 0;
-                       k = groupSizes[j++];
-                      
-                       while (value >= 10) {
-                               buffy[--position] = digitLowerTable[(value % 10)];
-                               value /= 10;
-
-                               if (--k == 0) {
-                                       i = groupSeparator.Length; 
-                                       do {
-                                               buffy[--position] = groupSeparator[--i];
-                                       } while (i > 0);
-                                       
-                                       k = (j < groupSizes.Length) ? 
-                                       groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                               }
-                       }                
-
-                       buffy[--position] = digitLowerTable[value];
-
-                       // end the pattern on the left hand side
-                       i = symbolLength; 
-                       switch (pattern) {
-                       case 0: // $nnn
-                               do {
-                                       buffy[--position] = currencySymbol[--i];
-                               } while (i > 0);
-                               break;
-                       // case 1: // nnn$
-                       //      break;
-                       case 2: // $ nnn
-                               buffy[--position] = ' '; 
-                               do {
-                                       buffy[--position] = currencySymbol[--i];
-                               } while (i > 0);
-                               break;
-                       // case 3: // nnn $
-                               //      break;
-                       }
-                       
-                       return new string (buffy, position, (size - position));
-               }
-               
-               // ============ Format Decimal Types ============ //
-
-               //
-               // Used only for integral data types. Negative values are 
-               // represented by using a '-' sign. The precision specifies
-               // how many digits are to appear in the string. If it is >
-               // how many digits we need, the left side is padded w/ 0's.
-               // If it is smaller than what we need, it is discarded.
-               //
-               // Fairly simple implementation. Fill the buffer from right
-               // to left w/ numbers, then if we still have precision left
-               // over, pad w/ zeros.
-               //
-
-               internal static string FormatDecimal (long value, int precision, int maxLength)
-               {
-                       int size = (precision > 0) ? (maxLength + precision) : maxLength;
-                       char [] buffy = new char [size];
-                       int position = size;
-                       bool negative = (value < 0);
-
-                       if (negative) 
-                               if (value <= -10) {
-                                       buffy[--position] = digitLowerTable[-(value % 10)];
-                                       value = value / -10;
-                               } else value = -value;
-
-                       // get our value into a buffer from right to left
-                       while (value >= 10) {
-                               buffy[--position] = digitLowerTable[(value % 10)];
-                               value /= 10;
-                       }
-                               
-                       buffy[--position] = digitLowerTable[value];
-                       
-                       // if we have precision left over, fill with 0's
-                       precision -= (size - position); 
-                       while (precision-- > 0 && position > 1)
-                               buffy[--position] = '0';
-
-                       if (negative) 
-                               buffy[--position] = '-';
-                       
-                       return new string (buffy, position, (size - position));  
-               }
-
-               internal static string FormatDecimal (ulong value, int precision, int maxLength)
-               {
-                       int size = (precision > 0) ? (maxLength + precision) : maxLength;
-                       char [] buffy = new char [size];
-                       int position = size;
-
-                       // get our value into a buffer from right to left
-                       while (value >= 10) {
-                               buffy[--position] = digitLowerTable[(value % 10)];
-                               value /= 10;
-                       }
-                               
-                       buffy[--position] = digitLowerTable[value];
-                       
-                       // if we have precision left over, fill with 0's
-                       precision -= (size - position); 
-                       while (precision-- > 0 && position > 1)
-                               buffy[--position] = '0';
-
-                       return new string (buffy, position, (size - position));  
-               }
-
-               // ============ Format Exponentials ============ //
-
-               //
-               // Used for strings in the format [-]M.DDDDDDe+XXX.
-               // Exaclty one non-zero digit must appear in M, w/ 
-               // a '-' sign if negative. The precision determines 
-               // number of decimal places, if not given go 6 places.
-               // If precision > the number of places we need, it
-               // is right padded w/ 0's. If it is smaller than what
-               // we need, we cut off and round. The format specifier
-               // decides whether we use an uppercase E or lowercase e.
-               // 
-               // Tried to do this in one pass of one buffer, but it
-               // wasn't happening. Get a buffer + 7 extra slots for
-               // the -, ., E, +, and XXX. Parse the value into another
-               // temp buffer, then build the new string. For the
-               // integral data types, there are a couple things that
-               // can be hardcoded. Since an int and a long can't be
-               // larger than 20 something spaces, the first X w/ 
-               // always be 0, and the the exponential value will only
-               // be 2 digits long. Also integer types w/ always
-               // have a positive exponential.
-               //
-               
-               static string FormatExponential (long value, int precision, bool upper, int maxLength)
-               {
-                       bool negative = (value < 0);
-                       int padding = (precision >= 0) ? precision : 6;
-                       char [] buffy = new char [(padding + 8)];
-                       char [] tmp = new char [maxLength];
-                       int exponent = 0, position = maxLength;
-                       int exp = 0, idx = 0;
-                       ulong pow = 10;
-
-                       // ugly, but doing it since abs(Int32.MinValue) > Int.MaxValue
-                       ulong number = (negative) ? (ulong)((-(value + 1)) + 1) : (ulong)value;
-
-                       // need to calculate the number of places to know if we need to round later
-                       if (negative && value <= -10) {
-                               value /= -10;
-                               exp++;
-                       }
-
-                       while (value >= 10) {
-                               value /= 10;
-                               exp++;
-                       }
-                                                       
-                       if (exp > padding) {
-                               
-                               // highest number we should goto before we round
-                               while (idx++ <= padding)
-                                       pow *= 10;
-                               
-                               // get our value into a buffer
-                               while (number > pow) {
-                                       tmp[--position] = digitLowerTable[(number % 10)];
-                                       number /= 10;
-                                       exponent++;
-                               }
-                       
-                               number += 5;
-                       }
-
-                       while (number >= 10) {
-                               tmp[--position] = digitLowerTable[(number% 10)];
-                               number /= 10;
-                               exponent++;
-                       }                      
-
-                       tmp[--position] = digitLowerTable[number];
-                       idx = 0;
-
-                       // go left to right in filling up new string
-                       if (negative)
-                               buffy[idx++] = '-';
-
-                       // we know we have at least one in there, followed 
-                       // by a decimal point
-                       buffy[idx++] = tmp[position++];
-                       if (precision != 0)
-                               buffy[idx++] = '.';
-
-                       // copy over the remaining digits until we run out,
-                       // or we've passed our specified precision
-                       while (padding > 0 && position < maxLength) {
-                               buffy[idx++] = tmp[position++];
-                               padding--;
-                       }
-                       
-                       // if we still have more precision to go, add some
-                       // zeros
-                       while (padding > 0) {
-                               buffy[idx++] = '0';
-                               padding--;
-                       }
-                       
-                       // we know these next 3 spots
-                       buffy[idx++] = upper ? 'E' : 'e';
-                       buffy[idx++] = '+';
-                       buffy[idx++] = '0';
-                       
-                       // next two digits depend on our length
-                       if (exponent >= 10) {
-                               buffy[idx++] = digitLowerTable[(exponent / 10)];
-                               buffy[idx] = digitLowerTable[(exponent % 10)];
-                       } else { 
-                               buffy[idx++] = '0';
-                               buffy[idx] = digitLowerTable[exponent];
-                       }
-
-                       return new string(buffy, 0, ++idx); 
-               }
-
-               private static string FormatExponential (ulong value, int precision, bool upper, int maxLength)
-               {
-                       int padding = (precision >= 0) ? precision : 6;
-                       char [] buffy = new char [(padding + 8)];
-                       char [] tmp = new char [maxLength];
-                       int exponent = 0, position = maxLength;
-                       int exp = 0, idx = 0;
-                       ulong pow = 10;
-                       ulong number = value;
-
-                       // need to calculate the number of places to know if we need to round later
-                       while (value >= 10) {
-                               value /= 10;
-                               exp++;
-                       }
-                                                       
-                       if (exp > padding) {
-
-                               // highest number we should goto before we round
-                               while (idx++ <= padding)
-                                       pow *= 10;
-
-                               // get our value into a buffer
-                               while (number > pow) {
-                                       tmp[--position] = digitLowerTable[(number % 10)];
-                                       number /= 10;
-                                       exponent++;
-                               }
-                       
-                               number += 5;
-                       }
-
-                       while (number >= 10) {
-                               tmp[--position] = digitLowerTable[(number% 10)];
-                               number /= 10;
-                               exponent++;
-                       }                      
-
-                       tmp[--position] = digitLowerTable[number];
-                       idx = 0;
-
-                       // we know we have at least one in there, followed 
-                       // by a decimal point
-                       buffy[idx++] = tmp[position++];
-                       if (precision != 0)
-                               buffy[idx++] = '.';
-
-                       // copy over the remaining digits until we run out,
-                       // or we've passed our specified precision
-                       while (padding > 0 && position < maxLength) {
-                               buffy[idx++] = tmp[position++];
-                               padding--;
-                       }
-                       
-                       // if we still have more precision to go, add some
-                       // zeros
-                       while (padding > 0) {
-                               buffy[idx++] = '0';
-                               padding--;
-                       }
-                       
-                       // we know these next 3 spots
-                       buffy[idx++] = upper ? 'E' : 'e';
-                       buffy[idx++] = '+';
-                       buffy[idx++] = '0';
-                       
-                       // next two digits depend on our length
-                       if (exponent >= 10) {
-                               buffy[idx++] = digitLowerTable[(exponent / 10)];
-                               buffy[idx] = digitLowerTable[(exponent % 10)];
-                       } else { 
-                               buffy[idx++] = '0';
-                               buffy[idx] = digitLowerTable[exponent];
-                       }
-
-                       return new string(buffy, 0, ++idx); 
-               }
-
-               // ============ Format Fixed Points ============ //
-
-               //
-               // Used for strings in the following form "[-]M.DD...D"
-               // At least one non-zero digit precedes the '.', w/ a 
-               // '-' before that if negative. Precision specifies number
-               // of decimal places 'D' to go. If not given, use
-               // NumberFormatInfo.NumbeDecimalDigits. Results are rounded
-               // if necessary. 
-               //
-               // Fairly simple implementation for integral types. Going
-               // from right to left, fill up precision number of 0's,
-               // plop a . down, then go for our number. 
-               //
-
-               static string FormatFixedPoint (long value, int precision, NumberFormatInfo nfi, int maxLength)
-               {
-                       int padding = (precision >= 0) ? (precision + maxLength) : (nfi.NumberDecimalDigits + maxLength);
-                       char [] buffy = new char [padding];
-                       int position = padding;
-                       bool negative = (value < 0);
-                       
-                       // fill up w/ precision # of 0's
-                       while (position > (maxLength - 1)) 
-                               buffy[--position] = '0';
-
-                       if (precision != 0)
-                               buffy[position--] = '.';
-
-                       if (negative)
-                               if (value <= -10) {
-                                       buffy[position--] = digitLowerTable[-(value % 10)];
-                                       value = value / -10;
-                               } else value = -value;
-                       
-                       // fill up w/ the value
-                       while (value >= 10) {
-                               buffy[position--] = digitLowerTable[(value % 10)];
-                               value = value / 10;
-                       }
-
-                       buffy[position] = digitLowerTable[value];
-
-                       if (negative) 
-                               buffy[--position] = '-';
-                       
-                       return new string (buffy, position, (padding - position));
-               }
-
-
-               static string FormatFixedPoint (ulong value, int precision, NumberFormatInfo nfi, int maxLength)
-               {
-                       int padding = (precision >= 0) ? (precision + maxLength) : (nfi.NumberDecimalDigits + maxLength);
-                       char [] buffy = new char [padding];
-                       int position = padding;
-
-                       // fill up w/ precision # of 0's
-                       while (position > (maxLength - 1)) 
-                               buffy[--position] = '0';
-
-                       if (precision != 0)
-                               buffy[position--] = '.';
-
-                       // fill up w/ the value
-                       while (value >= 10) {
-                               buffy[position--] = digitLowerTable[(value % 10)];
-                               value = value / 10;
-                       }
-
-                       buffy[position] = digitLowerTable[value];
-                       
-                       return new string (buffy, position, (padding - position));
-               }
-
-               // ============ Format General ============ //
-               
-               //
-               // Strings are formatted in either Fixed Point or Exponential
-               // format. Results are rounded when needed. If no precision is
-               // given, the defaults are:
-               //
-               // short & ushort: 5
-               // int & uint: 10
-               // long & ulong: 19
-               // float: 7
-               // double: 15
-               // decimal: 29
-               //
-               // The value is formatted using fixed-point if exponent >= -4
-               // and exponent < precision, where exponent is he exponenent of
-               // the value in exponential format. The decimal point and trailing
-               // zeros are removed when possible.
-               //
-               // For all other values, exponential format is used. The case of
-               // the format specifier determines whether 'e' or 'E' prefixes
-               // the exponent.
-               // 
-               // In either case, the number of digits that appear in the result
-               // (not including the exponent) will not exceed the value of the
-               // precision. The result is rounded as needed.
-               //
-               // Integral values are formatted using Fixed Point whenever
-               // precision is omitted. (This actually doesn't make sense when
-               // coupled w/ the 1st paragraph).
-               //              
-               // Okay, so the decimal point is removed along with any trailing
-               // zeros. So, ignoring the last paragraph, we can consider an int
-               // ToString() to format it w/ exponential format w/ a default
-               // precision of 10, but since it will just be .00000000, it's
-               // discarded.
-               //
-
-               internal static string FormatGeneral (long value, int precision, NumberFormatInfo nfi, bool upper) 
-               {
-                       return FormatGeneral (value, precision, nfi, upper, maxIntLength);
-               }
-               
-               internal static string FormatGeneral (long value, int precision, NumberFormatInfo nfi, bool upper, int maxLength) 
-               {
-                       bool negative = (value < 0);
-                       char [] tmp = new char [maxLength];
-                       int exponent = 0;
-                       int position = maxLength;
-
-                       // ugly, but doing it since abs(Int32.MinValue) > Int.MaxValue
-                       ulong number = (negative) ? (ulong)(-(value + 1) + 1) : (ulong)value;
-
-                       // get number into a buffer, going to be doing this no matter what
-                       if (negative)
-                               if (value <= -10) {
-                                       tmp[--position] = digitLowerTable[-(value % 10)];
-                                       value /= -10;
-                               } else value = -value;
-
-                       while (value >= 10) {
-                               tmp[--position] = digitLowerTable[(value % 10)];
-                               value /= 10;
-                       }
-                       
-                       tmp[--position] = digitLowerTable[value];
-                       exponent = (maxLength - position) - 1;
-
-                       // integral values are formatted using fixed point when precision
-                       // is not specified. But also trailing decimal point and zeros are
-                       // discared. So for int's it will always be .00, so just compute
-                       // here and save the call to FormatFixedPoint & trim.
-                       if (precision <= 0 || exponent < precision) {
-                               if (negative) 
-                                       tmp[--position] = '-';
-                               
-                               return new string (tmp, position, (maxLength - position)); 
-                       }
-
-                       // else our exponent was > precision, use exponential format
-                       // precision = number of digits to show. 
-                       int idx = 0;
-                       ulong pow = 1;
-
-                       exponent = 0;
-                       position = maxLength;
-
-                       // Loop through while our number is less than the 10 ^ precision, then
-                       // add 5 to that to round it out, and keep continuing
-                       while (idx++ <= precision)
-                               pow *= 10;
-                       
-                       while (number > pow) {
-                               tmp[--position] = digitLowerTable[(number % 10)];
-                               number /= 10;
-                               exponent++;
-                       }
-
-                       number += 5;
-
-                       while (number >= 10) {
-                               tmp[--position] = digitLowerTable[(number % 10)];
-                               number /= 10;
-                               exponent++;
-                       }
-
-                       tmp[--position] = digitLowerTable[number];
-
-                       // finally, make our final buffer, at least precision + 6 for 'E+XX' and '-'
-                       idx = position;
-                       position = 0;
-                       char [] buffy = new char [precision + 6];
-
-                       if (negative)
-                               buffy[position++] = '-';
-                       
-                       buffy[position++] = tmp[idx++];
-                       buffy[position] = '.';
-
-                       // for the remaining precisions copy over rounded tmp
-                       precision--;
-                       while (precision-- > 0)
-                               buffy[++position] = tmp[idx++];
-
-                       // get rid of ending zeros
-                       while (buffy[position] == '0')
-                               position--;
-
-                       // if we backed up all the way to the ., over write it
-                       if (buffy[position] != '.')
-                               position++;                     
-
-                       // ints can only be +, e or E depending on format, plus XX
-                       buffy[position++] = upper ? 'E' : 'e';
-                       buffy[position++] = '+';
-
-                       if (exponent >= 10) {
-                               buffy[position++] = digitLowerTable[(exponent / 10)];
-                               buffy[position++] = digitLowerTable[(exponent % 10)];
-                       } else { 
-                               buffy[position++] = '0';
-                               buffy[position++] = digitLowerTable[exponent];
-                       }
-                       
-                       return new string (buffy, 0, position);
-               }
-
-               internal static string FormatGeneral (ulong value, int precision, NumberFormatInfo nfi, bool upper, int maxLength)
-               {
-                       char [] tmp = new char [maxLength];
-                       int exponent = 0;
-                       int position = maxLength;
-                       ulong number = value;
-
-                       // get number into a buffer, going to be doing this no matter what
-                       while (value >= 10) {
-                               tmp[--position] = digitLowerTable[(value % 10)];
-                               value /= 10;
-                               exponent++;
-                       }
-                       
-                       tmp[--position] = digitLowerTable[value];
-
-                       // integral values are formatted using fixed point when precision
-                       // is not specified. But also trailing decimal point and zeros are
-                       // discared. So for int's it will always be .00, so just compute
-                       // here and save the call to FormatFixedPoint & trim.
-                       if (precision <= 0 || exponent < precision) 
-                               return new string (tmp, position, (maxLength - position)); 
-
-                       // else our exponent was > precision, use exponential format
-                       // precision = number of digits to show. 
-                       int idx = 0;
-                       ulong pow = 1;
-
-                       exponent = 0;
-                       position = maxLength;
-
-                       // Loop through while our number is less than the 10 ^ precision, then
-                       // add 5 to that to round it out, and keep continuing
-                       while (idx++ <= precision)
-                               pow *= 10;
-                       
-                       while (number > pow) {
-                               tmp[--position] = digitLowerTable[(number % 10)];
-                               number /= 10;
-                               exponent++;
-                       }
-
-                       number += 5;
-
-                       while (number >= 10) {
-                               tmp[--position] = digitLowerTable[(number % 10)];
-                               number /= 10;
-                               exponent++;
-                       }
-
-                       tmp[--position] = digitLowerTable[number];
-
-                       // finally, make our final buffer, at least precision + 6 for 'E+XX' and '-'
-                       idx = position;
-                       position = 0;
-                       char [] buffy = new char [precision + 6];
-
-                       buffy[position++] = tmp[idx++];
-                       buffy[position] = '.';
-
-                       // for the remaining precisions copy over rounded tmp
-                       precision--;
-                       while (precision-- > 0)
-                               buffy[++position] = tmp[idx++];
-
-                       // get rid of ending zeros
-                       while (buffy[position] == '0')
-                               position--;
-
-                       // if we backed up all the way to the ., over write it
-                       if (buffy[position] != '.')
-                               position++;                     
-
-                       // ints can only be +, e or E depending on format, plus XX
-                       buffy[position++] = upper ? 'E' : 'e';
-                       buffy[position++] = '+';
-
-                       if (exponent >= 10) {
-                               buffy[position++] = digitLowerTable[(exponent / 10)];
-                               buffy[position++] = digitLowerTable[(exponent % 10)];
-                       } else { 
-                               buffy[position++] = '0';
-                               buffy[position++] = digitLowerTable[exponent];
-                       }
-                       
-                       return new string (buffy, 0, position);
-               }
-
-               // ============ Format Number ============ //
-
-               // 
-               // Used for strings in the following form "[-]d,ddd,ddd.dd...d"
-               // The minus sign only appears if it is negative. At least one
-               // non-zero digit preceeds the decimal separator. The precision
-               // specifier determines the number of decimal places. If it is 
-               // not given, use NumberFormatInfo.NumberDecimalDigits.
-               // The NumberGroupSizes, NumberGroupSeparator, and NumberDecimalSeparator
-               // members of NumberFormatInfo supply the size and separator
-               // for digit groupings. See IFormattable.
-               //
-               // The group sizes is an array of ints that determine the grouping
-               // of numbers. All digits are in the range 1-9, with the last digit
-               // being between 0-9. The number formats the string backwards, with
-               // the last digit being the group size for the rest of (leftmost) the
-               // the string, 0 being none.
-               //
-               // For instance:
-               //              groupSizes = { 3, 2, 1, 0 }; 
-               //              int n = 1234567890 => "1234,5,67,890"
-               //              groupSizes = { 3, 2, 1 }; 
-               //              int n = 1234567890 => "1,2,3,4,5,67,890"
-               //              groupSizes = { 2, 0 };
-               //              int n = 1234567890 => "1234567,90";
-               //
-               // Not too difficult, jsut keep track of where you are in the array
-               // and when to print the separator
-               //
-               // The max size of the buffer is assume we have a separator every 
-               // number, plus the precision on the end, plus a spot for the negative
-               // and a spot for decimal separator.
-               //
-
-               static string FormatNumber (long value, int precision, NumberFormatInfo nfi, int maxLength) 
-               {
-                       int i, j, k;
-                       string groupSeparator = nfi.NumberGroupSeparator;
-                       string decimalSeparator = nfi.NumberDecimalSeparator;
-                       int[] groupSizes = nfi.NumberGroupSizes;
-
-                       int padding = (precision >= 0) ? precision : nfi.NumberDecimalDigits;
-                       int pattern = nfi.NumberNegativePattern;
-                       int size = maxLength + (maxLength * groupSeparator.Length) + padding +
-                       decimalSeparator.Length + 4;
-                       char [] buffy = new char [size];
-                       int position = size;
-                       bool negative = (value < 0);
-                       
-                       // pattern for negative values, defined in NumberFormatInfo
-                       if (negative) {
-                               switch (pattern) {
-                               case 0: // (nnn)
-                                       buffy[--position] = ')'; 
-                                       break;
-                               // case 1: // -nnn
-                               //      break;
-                               // case 2: // - nnn
-                               //      break;
-                               case 3: // nnn-
-                                       buffy[--position] = '-'; 
-                                       break;
-                               case 4: // nnn -
-                                       buffy[--position] = '-'; 
-                                       buffy[--position] = ' '; 
-                                       break;
-                               }
-                       }
-
-                       // right pad it w/ precision 0's
-                       while (padding-- > 0)
-                               buffy[--position] = '0';
-                                               
-                       // put on decimal separator
-                       if (position != size) {
-                               i = decimalSeparator.Length; 
-                               do {
-                                       buffy[--position] = decimalSeparator[--i];
-                               } while (i > 0);                        
-                       }
-
-                       // loop through, keeping track of where you are in the
-                       // group sizes array and putting out the group separator
-                       // when needed
-                       j = 0;
-                       k = groupSizes[j++];
-
-                       // negative hack for numbers past MinValue
-                       if (negative)
-                               if (value <= -10) {
-                                       buffy[--position] = digitLowerTable[-(value % 10)];
-                                       value = value / -10;
-                                       
-                                       if (--k == 0) {
-                                               i = groupSeparator.Length; 
-                                               do {
-                                                       buffy[--position] = groupSeparator[--i];
-                                               } while (i > 0);
-                                               
-                                               k = (j < groupSizes.Length) ? 
-                                               groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                                       }
-                               } else value = -value;
-
-                       while (value >= 10) {
-                               buffy[--position] = digitLowerTable[(value % 10)];
-                               value /= 10;
-
-                               if (--k == 0) {
-                                       i = groupSeparator.Length; 
-                                       do {
-                                               buffy[--position] = groupSeparator[--i];
-                                       } while (i > 0);
-                                       
-                                       k = (j < groupSizes.Length) ? 
-                                       groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                               }
-                       }                
-
-                       buffy[--position] = digitLowerTable[value];
-
-                       // pattern for negative values, defined in NumberFormatInfo
-                       if (negative) {
-                               switch (pattern) {
-                               case 0: // (nnn)
-                                       buffy[--position] = '('; 
-                                       break;
-                               case 1: // -nnn
-                                       buffy[--position] = '-'; 
-                                       break;
-                               case 2: // - nnn
-                                       buffy[--position] = ' '; 
-                                       buffy[--position] = '-'; 
-                                       break;
-                               // case 3: // nnn-
-                               //      break;
-                               // case 4: // nnn -
-                               //      break;
-                               }
-                       }
-                       
-                       return new string (buffy, position, (size - position));
-               }
-
-               static string FormatNumber (ulong value, int precision, NumberFormatInfo nfi, int maxLength)
-               {
-                       int i, j, k;
-                       string groupSeparator = nfi.NumberGroupSeparator;
-                       string decimalSeparator = nfi.NumberDecimalSeparator;
-                       int[] groupSizes = nfi.NumberGroupSizes;
-
-                       int padding = (precision >= 0) ? precision : nfi.NumberDecimalDigits;
-                       int size = maxLength + (maxLength * groupSeparator.Length) + padding +
-                       decimalSeparator.Length + 2;
-                       char [] buffy = new char [size];
-                       int position = size;
-                       
-                       // right pad it w/ precision 0's
-                       while (padding-- > 0)
-                               buffy[--position] = '0';
-                       
-                       // put on decimal separator
-                       if (position != size) {
-                               i = decimalSeparator.Length; 
-                               do {
-                                       buffy[--position] = decimalSeparator[--i];
-                               } while (i > 0);                        
-                       }
-
-                       // loop through, keeping track of where you are in the
-                       // group sizes array and putting out the group separator
-                       // when needed
-                       j = 0;
-                       k = groupSizes[j++];
-
-                       while (value >= 10) {
-                               buffy[--position] = digitLowerTable[(value % 10)];
-                               value /= 10;
-
-                               if (--k == 0) {
-                                       i = groupSeparator.Length; 
-                                       do {
-                                               buffy[--position] = groupSeparator[--i];
-                                       } while (i > 0);
-                                       
-                                       k = (j < groupSizes.Length) ? 
-                                       groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                               }
-                       }                
-
-                       buffy[--position] = digitLowerTable[value];
-
-                       return new string (buffy, position, (size - position));
-               }               
-
-               // ============ Percent Formatting ============ //
-
-               //
-               //  Percent Format: Used for strings containing a percentage. The
-               //  PercentSymbol, PercentGroupSizes, PercentGroupSeparator, and
-               //  PercentDecimalSeparator members of a NumberFormatInfo supply
-               //  the Percent symbol, size and separator for digit groupings, and
-               //  decimal separator, respectively.
-               //  PercentNegativePattern and PercentPositivePattern determine the
-               //  symbols used to represent negative and positive values. For example,
-               //  a negative value may be prefixed with a minus sign, or enclosed in
-               //  parentheses.
-               //  If no precision is specified, the number of decimal places in the result
-               //  is set by NumberFormatInfo.PercentDecimalDigits. Results are
-               //  rounded to the nearest representable value when necessary.
-               //  The result is scaled by 100 (.99 becomes 99%).
-               //
-               //  The pattern of the number determines how the output looks, where
-               //  the percent sign goes, where the negative sign goes, etc.
-               //  IFormattable documentation lists the patterns and their values,
-               //  I have them commented out in the switch statement
-               //
-
-               static string FormatPercent (long value, int precision, NumberFormatInfo nfi, int maxLength)
-               {
-                       int i, j, k;
-                       bool negative = (value < 0);
-
-                       string groupSeparator = nfi.PercentGroupSeparator;
-                       string decimalSeparator = nfi.PercentDecimalSeparator;
-                       string percentSymbol = nfi.PercentSymbol;
-                       int[] groupSizes = nfi.PercentGroupSizes;
-                       int pattern = negative ? nfi.PercentNegativePattern : nfi.PercentPositivePattern;
-                       int symbolLength = percentSymbol.Length;
-                       
-                       int padding = (precision >= 0) ? precision : nfi.PercentDecimalDigits;       
-                       int size = maxLength + (groupSeparator.Length * maxLength) + padding + 2 + 
-                       decimalSeparator.Length + symbolLength; 
-                       char [] buffy = new char [size];
-                       int position = size;
-
-                       // set up the pattern from IFormattible
-                       if (negative) {
-                               i = symbolLength; 
-                               switch (pattern) {
-                               case 0: // -nnn %
-                                       do {
-                                               buffy[--position] = percentSymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = ' '; 
-                                       break;
-                               case 1: // -nnn%
-                                       do {
-                                               buffy[--position] = percentSymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               // case 2: // -%nnn
-                               //      break;
-                               }
-                       } else {
-                               i = symbolLength; 
-                               switch (pattern) {
-                               case 0: // nnn %
-                                       do {
-                                               buffy[--position] = percentSymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = ' ';                                        
-                                       break;
-                               case 1: // nnn%
-                                       do {
-                                               buffy[--position] = percentSymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               // case 2: // %nnn
-                               //      break;
-                               }
-                       }
-                       
-                       // right pad it w/ precision 0's
-                       while (padding-- > 0)
-                               buffy[--position] = '0';
-
-                       // put on decimal separator if we moved over and put a 0 
-                       if (position < size && buffy[position] == '0') {
-                               i = decimalSeparator.Length; 
-                               do {
-                                       buffy[--position] = decimalSeparator[--i];
-                               } while (i > 0);                        
-                       }
-
-                       // loop through, keeping track of where you are in the
-                       // group sizes array and putting out the group separator
-                       // when needed
-                       j = 0;
-                       k = groupSizes[j++];
-
-                       // all values are multiplied by 100, so tack on two 0's
-                       if (value != 0) 
-                               for (int c = 0; c < 2; c++) {
-                                       buffy[--position] = '0';
-                                       
-                                       if (--k == 0) {
-                                               i = groupSeparator.Length; 
-                                               do {
-                                                       buffy[--position] = groupSeparator[--i];
-                                               } while (i > 0);
-                                               
-                                               k = (j < groupSizes.Length) ? 
-                                               groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                                       }
-                               }
-
-                       // negative hack for numbers past MinValue
-                       if (negative)
-                               if (value <= -10) {
-                                       buffy[--position] = digitLowerTable[-(value % 10)];
-                                       value = value / -10;
-                                       
-                                       if (--k == 0) {
-                                               i = groupSeparator.Length; 
-                                               do {
-                                                       buffy[--position] = groupSeparator[--i];
-                                               } while (i > 0);
-                                               
-                                               k = (j < groupSizes.Length) ? 
-                                               groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                                       }
-                               } else value = -value;
-
-                       while (value >= 10) {
-                               buffy[--position] = digitLowerTable[(value % 10)];
-                               value /= 10;
-
-                               if (--k == 0) {
-                                       i = groupSeparator.Length; 
-                                       do {
-                                               buffy[--position] = groupSeparator[--i];
-                                       } while (i > 0);
-                                       
-                                       k = (j < groupSizes.Length) ? 
-                                       groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                               }
-                       }                
-
-                       buffy[--position] = digitLowerTable[value];
-
-                       // end the pattern on the left hand side
-                       if (negative) {
-                               i = symbolLength; 
-                               switch (pattern) {
-                               case 0: // -nnn %
-                                       buffy[--position] = '-'; 
-                                       break;
-                               case 1: // -nnn%
-                                       buffy[--position] = '-'; 
-                                       break;
-                               case 2: // -%nnn
-                                       do {
-                                               buffy[--position] = percentSymbol[--i];
-                                       } while (i > 0);
-                                       buffy[--position] = '-'; 
-                                       break;
-                               }
-                       } else {
-                               i = symbolLength; 
-                               switch (pattern) {
-                               // case 0: // nnn %
-                               //      break;
-                               // case 1: // nnn%
-                               //      break;
-                               case 2: // %nnn
-                                       do {
-                                               buffy[--position] = percentSymbol[--i];
-                                       } while (i > 0);
-                                       break;
-                               }
-                       }
-                       
-                       return new string (buffy, position, (size - position));
-               }
-
-               static string FormatPercent (ulong value, int precision, NumberFormatInfo nfi, int maxLength) 
-               {
-                       int i, j, k;
-
-                       string groupSeparator = nfi.PercentGroupSeparator;
-                       string decimalSeparator = nfi.PercentDecimalSeparator;
-                       string percentSymbol = nfi.PercentSymbol;
-                       int[] groupSizes = nfi.PercentGroupSizes;
-                       int pattern = nfi.PercentPositivePattern;
-                       int symbolLength = percentSymbol.Length;
-                       
-                       int padding = (precision >= 0) ? precision : nfi.PercentDecimalDigits;       
-                       int size = maxLength + (groupSeparator.Length * maxLength) + padding + 2 + 
-                       decimalSeparator.Length + symbolLength; 
-                       char [] buffy = new char [size];
-                       int position = size;
-
-                       // set up the pattern from IFormattible
-                       i = symbolLength;                       
-                       switch (pattern) {
-                       case 0: // -nnn %
-                               do {
-                                       buffy[--position] = percentSymbol[--i];
-                               } while (i > 0);
-                               buffy[--position] = ' '; 
-                               break;
-                       case 1: // -nnn%
-                               do {
-                                       buffy[--position] = percentSymbol[--i];
-                               } while (i > 0);
-                               break;
-                       // case 2: // -%nnn
-                       //      break;
-                       }
-
-                       // right pad it w/ precision 0's
-                       while (padding-- > 0)
-                               buffy[--position] = '0';
-
-                       // put on decimal separator if we moved over and put a 0 
-                       if (position < size && buffy[position] == '0') {
-                               i = decimalSeparator.Length; 
-                               do {
-                                       buffy[--position] = decimalSeparator[--i];
-                               } while (i > 0);                        
-                       }
-
-                       // loop through, keeping track of where you are in the
-                       // group sizes array and putting out the group separator
-                       // when needed
-                       j = 0;
-                       k = groupSizes[j++];
-
-                       if (value != 0) 
-                               for (int c = 0; c < 2; c++) {
-                                       buffy[--position] = '0';
-                                       
-                                       if (--k == 0) {
-                                               i = groupSeparator.Length; 
-                                               do {
-                                                       buffy[--position] = groupSeparator[--i];
-                                               } while (i > 0);
-                                               
-                                               k = (j < groupSizes.Length) ? 
-                                               groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                                       }
-                               }
-                       
-                       while (value >= 10) {
-                               buffy[--position] = digitLowerTable[(value % 10)];
-                               value /= 10;
-
-                               if (--k == 0) {
-                                       i = groupSeparator.Length; 
-                                       do {
-                                               buffy[--position] = groupSeparator[--i];
-                                       } while (i > 0);
-                                       
-                                       k = (j < groupSizes.Length) ? 
-                                       groupSizes[j++] : groupSizes[(groupSizes.Length - 1)];
-                               }
-                       }                
-
-                       buffy[--position] = digitLowerTable[value];
-
-                       i = symbolLength; 
-                       switch (pattern) {
-                       // case 0: // nnn %
-                       //      break;
-                       // case 1: // nnn%
-                       //      break;
-                       case 2: // %nnn
-                               do {
-                                       buffy[--position] = percentSymbol[--i];
-                               } while (i > 0);
-                               break;
-                       }
-                       
-                       return new string (buffy, position, (size - position));
-               }
-
-               // ============ Format Hexadecimal ============ //
-
-               // 
-               // For strings in base 16. Only valid w/ integers. Precision 
-               // specifies number of digits in the string, if it specifies
-               // more digits than we need, left pad w/ 0's. The case of the
-               // the format specifier 'X' or 'x' determines lowercase or
-               // capital digits in the output.
-               //
-               // Whew. Straight forward Hex formatting, however only
-               // go 8 places max when dealing with an int (not counting
-               // precision padding) and 16 when dealing with a long. This
-               // is to cut off the loop when dealing with negative values,
-               // which will loop forever when you hit -1;
-               //
-
-               static string FormatHexadecimal (long value, int precision, bool upper, int maxLength, int integerSize)
-               {
-                       if (precision < 0) precision = 0;
-                       int size = maxLength + precision;
-                       char [] buffy = new char [size];
-                       char[] table = upper ? digitUpperTable : digitLowerTable;
-                       int position = size;
-                       const long mask = (1 << 4) - 1;
-                       integerSize *= 2;
-                       
-                       // loop through right to left, shifting and looking up
-                       // our value. If value is negavite stop after 16 F's
-                       do {
-                               buffy[--position] = table[(value & mask)];
-                               value = value >> 4;
-                       } while (value != 0 && position > (size - integerSize));
-
-                       // pad w/ 0's if they want more length, if not, ignore
-                       precision -= (size - position);                         
-                       while (precision > 0 && position > 1) {
-                               buffy[--position] = '0';
-                               precision--;
-                       }
-                       
-                       return new string(buffy, position, (size - position));
-               }
-
-               static string FormatHexadecimal (ulong value, int precision, bool upper, int maxLength)
-               {                       
-                       if (precision < 0) precision = 0;
-                       int size = maxLength + precision;
-                       char [] buffy = new char [size];
-                       char[] table = upper ? digitUpperTable : digitLowerTable;
-                       int position = size;
-                       const ulong mask = (1 << 4) - 1;
-                       
-                       // loop through right to left, shifting and looking up
-                       // our value. Don't worry about negative
-                       do {
-                               buffy[--position] = table[value & mask];
-                               value = value >> 4;
-                       } while (value != 0);
-                       
-                       // pad w/ 0's if they want more length, if not, ignore
-                       precision -= (size - position);
-                       while (precision > 0 && position > 1) {
-                               buffy[--position] = '0';
-                               precision--;
-                       }
-
-                       return new string(buffy, position, (size - position));
-               }
-
-               // ============ Format Custom ============ //
-
-               static string FormatCustom (string format, long number, NumberFormatInfo nfi, int maxLength)
-               {
-                       string strnum = FormatGeneral (number, -1, nfi, true, maxLength);
-                       FormatParse fp = new FormatParse (format, nfi);
-                       int sign = (number < 0) ? -1 : (number > 0) ? 1 : 0;
-                       return fp.FormatNumber (strnum, sign);
-               }
-
-               static string FormatCustom (string format, ulong number, NumberFormatInfo nfi, int maxLength)
-               {
-                       string strnum = FormatGeneral (number, -1, nfi, true, maxLength);
-                       FormatParse fp = new FormatParse (format, nfi);
-                       return fp.FormatNumber (strnum, (number == 0) ? 0 : 1);
-               }
-       }
-
-class FormatSection {
-       public int nph;
-       public int nphPreDot;
-       public int npercent;
-       public int ndividers;
-       public int ntokens;
-       public string [] tokens;
-       public int [] TokenTypes;
-       public bool HaveDot;
-       public bool HaveSci;
-       public bool NegSign;
-       public bool sciSignAlways = false;
-       public int sciDigits;
-       public int numCommas;
-}
-
-class FormatParse {
-       const int AS_IS = 0;
-       const int PH_0 = 1;
-       const int PH_NUMBER = 2;
-       const int COMMA = 3;
-       const int PERCENT = 4;
-       const int DIVIDERS = 5;
-       const int DOT = 6;
-       const int ESCAPE_SEQ = 7;
-       const int SCIENTIFIC = 8;
-       const int NEW_SECTION = 9;
-       const int NEGSIGN = 10;
-       
-       private FormatSection [] sections = new FormatSection[3];
-       private int nsections = 0;
-       private int pos; // Position in the format string
-       private int group = 0; // Used in FormatPlain to insert a comma between groups of digits
-       private bool isNegative;
-       private NumberFormatInfo nfi;
-
-       private FormatParse ()
-       {
-       }
-       
-       public FormatParse (string format, NumberFormatInfo nfi)
-       {
-               this.nfi = nfi;
-               parseFormat (format);
-       }
-
-       private void FormatSci (char [] digits, ArrayList outputList, int section)
-       {
-               FormatSection sec = sections [section];
-               int tokidx = sec.ntokens - 1;
-
-               // Output everything until we get to the SCIENTIFIC
-               while (tokidx >= 0 && sec.TokenTypes [tokidx] != SCIENTIFIC){
-                       outputList.Add ((string) sec.tokens [tokidx--]);
-               }
-
-               // Exponent
-               int exponent = digits.Length - sec.nph;
-               outputList.Add ((string) exponent.ToString ());
-               if (sec.sciSignAlways && exponent > 0)
-                       outputList.Add (nfi.PositiveSign);
-               outputList.Add ((string) sec.tokens [tokidx--]);
-
-               if (exponent < 0) {
-                       char [] newDigits;
-                       exponent = -exponent;
-                       newDigits = new char [digits.Length + exponent];
-                       Array.Copy (digits, 0, newDigits, exponent, digits.Length);
-                       for (int i = 0; i < exponent; i++)
-                               newDigits[i] = '0';
-                       digits = newDigits;
-               }
-
-               // Now format the rest
-               int digitIdx = 0;
-               if (sec.HaveDot)
-                       FormatDot (digits, ref digitIdx, outputList, section, tokidx, 0);
-               else
-                       FormatPlain (digits, ref digitIdx, outputList, section, tokidx, 0, sec.numCommas > 0);
-       }
-
-       private void FormatDot (char [] digits, ref int digitIdx, ArrayList outputList, 
-                               int section, int lastToken, int firstToken)
-       {
-               int tokidx = lastToken;
-               int type;
-               FormatSection sec = sections [section];
-               
-               while (tokidx >= firstToken) {
-                       type = sec.TokenTypes [tokidx];
-                       if (type == DOT || type == PH_NUMBER || type == PH_0)
-                               break;
-                       tokidx--;
-               }
-
-               if (tokidx > 0) {
-                       char [] postDotDigits = new char [sec.nph - sec.nphPreDot];
-                       int max = (postDotDigits.Length > digits.Length) ? digits.Length : postDotDigits.Length;
-                       Array.Copy (digits, 0, postDotDigits, 0, max);
-                       int postDotDigitsIdx = 0;
-                       FormatPlain (postDotDigits, ref postDotDigitsIdx, outputList, section, lastToken, tokidx, false);
-                       tokidx--;
-                       digitIdx += max;
-                       FormatPlain (digits, ref digitIdx, outputList, section, tokidx, 0, sec.numCommas > 0);
-               }
-       }
-
-       private void FormatPlain (char [] digits, ref int digitIdx, ArrayList outputList, 
-                               int section, int lastToken, int firstToken, bool insertComma)
-       {
-               int tokidx = lastToken;
-               int type;
-               int leftMostZeroIdx = -1;
-               FormatSection sec = sections [section];
-
-               while (tokidx >= firstToken) {
-                       type = sec.TokenTypes [tokidx];
-                       if (type == PH_0 || type == PH_NUMBER) {
-                               if (type == PH_0)
-                                       leftMostZeroIdx = tokidx;
-                               // Console.WriteLine ("group : {0}", group);
-                               int i = sec.tokens [tokidx].Length - 1;
-                               while (i >= 0) {
-                                       if (insertComma && group == 3) {
-                                               outputList.Add (nfi.NumberGroupSeparator);
-                                               group = 0;
-                                       }
-
-                                       if (digitIdx < digits.Length)
-                                               outputList.Add ((string) digits[digitIdx++].ToString ());
-                                       else
-                                               outputList.Add ("0");
-
-                                       i--;
-                                       if (insertComma)
-                                               group++;
-                                       sec.nph--;
-                                       while (sec.nph == 0 && digitIdx < digits.Length) {
-                                               // Flush the numbers left
-                                               if (insertComma && group == 3){
-                                                       outputList.Add (nfi.NumberGroupSeparator);
-                                                       group = 0;
-                                               }
-                                               outputList.Add ((string) digits [digitIdx++].ToString ());
-                                               if (insertComma)
-                                                       group++;
-                                       }
-
-                                       if (sec.nph == 0 && isNegative){
-                                               if ((nsections > 0 && sections [1].NegSign) || nsections == 0)
-                                                       outputList.Add (nfi.NegativeSign);
-                                       }
-                               }
-                       } else {
-                               outputList.Add ((string) sec.tokens [tokidx]);
-                       }
-                       tokidx--;
-               }
-
-               // Remove any insignificant zeros we might have at the end
-               // if we never saw any zeros in the format string, leftMostZeroIdx will be -1
-               if (leftMostZeroIdx < 0)
-                       while ((string)outputList[outputList.Count-1] == "0")
-                               outputList.RemoveAt (outputList.Count-1);
-               else
-                       while (leftMostZeroIdx-- > 0)
-                               if ((string)outputList[outputList.Count-1] == "0")
-                                       outputList.RemoveAt (outputList.Count-1);
-       }
-
-       private char [] AdjustDigits (string number, FormatSection sec)
-       {
-               char [] digits = number.ToCharArray ();
-               char [] newDigits = digits;
-               int decPointIdx = 0;
-               int postDot = 0;
-               
-               decPointIdx -= sec.ndividers * 3;
-               decPointIdx += sec.npercent * 2;
-               if (sec.HaveDot){
-                       postDot = sec.nph - sec.nphPreDot;
-                       decPointIdx += postDot;
-               }
-
-               if (decPointIdx > 0) {
-                       newDigits = new char [digits.Length + decPointIdx];
-                       Array.Copy (digits, 0, newDigits, 0, digits.Length);
-                       for (int i = 0; i < decPointIdx; i++)
-                               newDigits[digits.Length + i] = '0';
-               } else if (decPointIdx < 0) {
-                       decPointIdx = -decPointIdx;
-                       if (decPointIdx >= digits.Length) {
-                               if (sec.HaveSci){
-                               } else {
-                                       // The numbers turns into 0 when formatting applied
-                                       digits = new char [1] {'0'};
-                               }
-                       } else {
-                               int newLength = digits.Length - decPointIdx + postDot - 1;
-                               newDigits = new char [newLength];
-                               int max = digits.Length >= newLength ? newLength : digits.Length;
-                               Array.Copy (digits, 0, newDigits, 0, max);
-                               if (newLength > digits.Length)
-                                       for (int i = 0; i < decPointIdx; i++)
-                                               newDigits[digits.Length + i] = '0';
-                       }
-               }
-
-               return newDigits;
-       }
-
-       public string FormatNumber (string number, int signValue)
-       {
-               char [] digits;
-
-               isNegative = signValue < 0;
-               int section = 0;
-               if (signValue < 0 && nsections > 0)
-                       section = 1;
-               if (signValue == 0 && nsections > 1)
-                       section = 2;
-
-               if (number [0] == '-')
-                       number = number.Substring (1);
-
-               FormatSection sec = sections [section];
-               digits = AdjustDigits (number.ToString (), sec);
-               
-               if (digits.Length == 1 && digits [0] == '0')
-                       if (nsections > 2)
-                               sec = sections [2]; // Format as a 0
-                       else
-                               sec = sections [0]; // Format as positive
-
-               ArrayList outputList = new ArrayList ();
-
-               int digitIdx = 0;
-               Array.Reverse (digits);
-
-               if (sec.HaveSci)
-                       FormatSci (digits, outputList, section);
-               else if (sec.HaveDot)
-                       FormatDot (digits, ref digitIdx, outputList, section, sec.ntokens - 1, 0);
-               else
-                       FormatPlain (digits, ref digitIdx, outputList, section, sec.ntokens - 1, 0, sec.numCommas > 0);
-
-               string result = "";
-               for (int i = outputList.Count - 1; i >= 0; i--) {
-                       result += (string) outputList[i];
-               }
-
-               return result;
-       }
-
-       private void parseFormat (string format)
-       {
-               char [] fmt_chars = format.ToCharArray ();
-               int fmtlen = fmt_chars.Length;
-               int type = AS_IS;
-               int prevType = AS_IS;
-               string token;
-               bool tokens_seen = false;
-
-               sections[0] = new FormatSection();
-               while (pos < fmtlen) {
-                       token = getNextToken (fmt_chars, fmtlen, out type, nsections == 1 && !tokens_seen);
-                       if (type == NEW_SECTION) {
-                               nsections++;
-                               if (nsections > 3)
-                                       break;
-                               sections[nsections] = new FormatSection();
-                               tokens_seen = false;
-                       } else {
-                               if (type != AS_IS)
-                                       tokens_seen = true;
-                               prevType = AddToken (token, type, prevType);
-                       }                       
-               }
-       }
-
-       private int AddToken (string token, int type, int prevType)
-       {
-               FormatSection sec = sections[nsections];
-               string [] newTokens = new string [sec.ntokens + 1];
-               int [] newTokenTypes = new int [sec.ntokens + 1];
-               for (int i = 0; i < sec.ntokens; i++) {
-                       newTokens[i] = sec.tokens[i];
-                       newTokenTypes[i] = sec.TokenTypes[i];
-               }
-
-               switch (type) {
-               case ESCAPE_SEQ :
-                       type = AS_IS;
-                       break;
-               case COMMA :
-                       if (!sec.HaveDot && (prevType == PH_0 || prevType == PH_NUMBER)) {
-                               sec.numCommas++;
-                       } else
-                               type = AS_IS;
-
-                       token = "";
-                       break;
-               case DOT :
-                       if (!sec.HaveDot && (prevType == PH_0 || prevType == PH_NUMBER ||
-                           prevType == DIVIDERS || prevType == COMMA)) {
-                               sec.HaveDot = true;
-                               sec.nphPreDot = sec.nph;
-                       } else
-                               type = AS_IS;
-
-                       break;
-               case PERCENT :
-                       sec.npercent++;
-                       break;
-               case DIVIDERS :
-                       token = "";
-                       if (!sec.HaveDot)
-                               sec.ndividers = token.Length;
-                       else
-                               type = AS_IS;
-                       break;
-               case PH_0 :
-                       if (!sec.HaveSci)
-                               sec.nph += token.Length;
-                       else
-                               type = AS_IS;
-                       break;
-               case PH_NUMBER :
-                       if (!sec.HaveSci)
-                               sec.nph += token.Length;
-                       else
-                               type = AS_IS;
-                       break;
-               case SCIENTIFIC :
-                       if (!sec.HaveSci && sec.nph > 0) {
-                               sec.HaveSci = true;
-                               char [] sci = token.ToCharArray ();
-                               sec.sciSignAlways = sci[1] == '+' ? true : false;
-                               int expLen = sci[1] == '0' ? token.Length - 1 : token.Length - 2;
-                               sec.sciDigits = expLen;
-                               token = sci[0].ToString ();
-                       } else {
-                               type = AS_IS;
-                       }
-                       break;
-
-               case NEGSIGN:
-                       sec.NegSign = true;
-                       break;
-               }
-
-               newTokens[sec.ntokens] = token;
-               newTokenTypes[sec.ntokens] = type;
-               sec.tokens = newTokens;
-               sec.TokenTypes = newTokenTypes;
-               sec.ntokens++;
-               return type;
-       }
-       
-       private string getNextToken (char [] fmt_chars, int fmtlen, out int type, bool negsection)
-       {
-               int curpos = pos;
-               string result = null;
-               char current;
-               
-               type = AS_IS; // Default
-               current = fmt_chars[curpos];
-               if (current == ';'){
-                       type = NEW_SECTION;
-                       result = "NEW_SECTION";
-                       pos++;
-               }
-               else if (current == '\'' || current == '"') {
-                       curpos++;
-                       int endpos = Array.IndexOf (fmt_chars, current, curpos);
-                       if (endpos == -1)
-                               endpos = fmtlen;
-                       result = new string (fmt_chars, curpos, endpos - curpos);
-                       pos = endpos + 1;
-               } 
-               else if (current == '\\') { //MS seems not to translate escape seqs!
-                       type = ESCAPE_SEQ;
-                       current = fmt_chars[++pos];
-                       result = current.ToString ();
-                       pos++;
-               }
-               else if (current == '%') {
-                       type = PERCENT;
-                       result = nfi.PercentSymbol;
-                       pos++;
-               }
-               else if (current == '.') {
-                       type = DOT;
-                       result = nfi.NumberDecimalSeparator;
-                       pos++;
-               }
-               else if (current == ',') {
-                       int begpos = curpos;
-
-                       while (++curpos < fmtlen && fmt_chars[curpos] == ',');
-                       if (curpos == fmtlen || fmt_chars[curpos] == '.') {
-                               // ,,,,
-                               result = new string (fmt_chars, begpos, curpos - begpos);
-                               type = DIVIDERS;
-                               pos = curpos;
-                       } else {
-                               result = ",";
-                               type = COMMA;
-                               pos++;
-                       }
-               }
-               else if (current == '0' || current == '#') {
-                       char placeHolder = current;
-                       int begpos = curpos;
-                       type = placeHolder == '0' ? PH_0 : PH_NUMBER;
-                       curpos++;
-                       while (curpos < fmtlen && fmt_chars [curpos] == placeHolder)
-                               curpos++;
-                       result = new string (fmt_chars, begpos, curpos - begpos);
-                       pos = curpos;
-               }
-               else if (current == 'e' || current == 'E') {
-                       if (fmtlen <= curpos + 1){
-                               result = current.ToString ();
-                               pos++;
-                       }
-                       else {
-                               char next1 = fmt_chars [curpos + 1];
-
-                               if (next1 != '-' && next1 != '+' && next1 != '0') {
-                                       result = new string (fmt_chars, curpos, 2);
-                                       pos += 2;
-                               }
-                               else {
-                                       int begpos = curpos;
-
-                                       if (next1 == '-' || next1 == '+')
-                                               curpos++;
-
-                                       curpos++;
-
-                                       if (curpos < fmtlen && fmt_chars [curpos] == '0'){
-                                               type = SCIENTIFIC;
-                                               while (curpos < fmtlen && fmt_chars [curpos] == '0')
-                                                       curpos++;
-                                       }
-
-                                       result = new string (fmt_chars, begpos, curpos - begpos);
-                                       pos = curpos;
-                               }
-                       }
-               }
-               else if (negsection && current == '-'){
-                       type = NEGSIGN;
-                       pos++;
-               }
-               else {
-                       char [] format_spec = { '0', '#', ',', '.', '%', 'E', 'e', '"', '\'', '\\' };
-                       int nextFE;
-
-                       while (curpos < fmtlen) {
-                               current = fmt_chars[curpos];
-                               nextFE = Array.IndexOf (format_spec, current);
-                               if (nextFE != -1)
-                                       break;
-                               curpos++;
-                       }
-
-                       result = new string (fmt_chars, pos, curpos - pos);
-                       pos = curpos;
-               }
-
-               return result;
-       }
-}
-
-}
diff --git a/mcs/class/corlib/System/NumberFormatter.cs b/mcs/class/corlib/System/NumberFormatter.cs
new file mode 100644 (file)
index 0000000..580b469
--- /dev/null
@@ -0,0 +1,1873 @@
+//
+// System.NumberFormatter.cs
+//
+// Author:
+//   Kazuki Oikawa (kazuki@panicode.com)
+//
+
+using System.Collections;
+using System.Globalization;
+using System.Text;
+
+namespace System
+{
+       class NumberFormatter
+       {
+               static char[] digitLowerTable = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+               static char[] digitUpperTable = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+
+               #region NumberToString
+               public static string NumberToString (string format, sbyte value, NumberFormatInfo nfi)
+               {
+                       return NumberToString (format, NumberStore.CreateInstance (value), nfi);
+               }
+               public static string NumberToString (string format, byte value, NumberFormatInfo nfi)
+               {
+                       return NumberToString (format, NumberStore.CreateInstance (value), nfi);
+               }
+               public static string NumberToString (string format, ushort value, NumberFormatInfo nfi)
+               {
+                       return NumberToString (format, NumberStore.CreateInstance (value), nfi);
+               }
+               public static string NumberToString (string format, short value, NumberFormatInfo nfi)
+               {
+                       return NumberToString (format, NumberStore.CreateInstance (value), nfi);
+               }
+               public static string NumberToString (string format, uint value, NumberFormatInfo nfi)
+               {
+                       return NumberToString (format, NumberStore.CreateInstance (value), nfi);
+               }
+               public static string NumberToString (string format, int value, NumberFormatInfo nfi)
+               {
+                       return NumberToString (format, NumberStore.CreateInstance (value), nfi);
+               }
+               public static string NumberToString (string format, ulong value, NumberFormatInfo nfi)
+               {
+                       return NumberToString (format, NumberStore.CreateInstance (value), nfi);
+               }
+               public static string NumberToString (string format, long value, NumberFormatInfo nfi)
+               {
+                       return NumberToString (format, NumberStore.CreateInstance (value), nfi);
+               }
+               public static string NumberToString (string format, float value, NumberFormatInfo nfi)
+               {
+                       return NumberToString (format, NumberStore.CreateInstance (value), nfi);
+               }
+               public static string NumberToString (string format, double value, NumberFormatInfo nfi)
+               {
+                       return NumberToString (format, NumberStore.CreateInstance (value), nfi);
+               }
+               public static string NumberToString (string format, NumberStore ns, NumberFormatInfo nfi)
+               {
+                       if (ns.IsNaN) {
+                               return nfi.NaNSymbol;
+                       }
+                       if (ns.IsInfinity) {
+                               if (ns.Positive)
+                                       return nfi.PositiveInfinitySymbol;
+                               else
+                                       return nfi.NegativeInfinitySymbol;
+                       }
+
+                       char specifier;
+                       int precision;
+                       bool custom;
+
+                       if (format == null || format == "")
+                               format = "G";
+
+                       if (nfi == null)
+                               nfi = NumberFormatInfo.GetInstance (null);
+                       
+                       if (!ParseBasicFormat (format, out specifier, out precision, out custom))
+                               throw new FormatException (Locale.GetText ("The specified format '" + format + "' is invalid"));
+                       
+                       if (custom){
+                               if (ns.IsFloatingSource)
+                                       ns.RoundEffectiveDigits (ns.DefaultPrecision);
+                               return FormatCustom (format, ns, nfi);
+                       }
+
+                       if (ns.IsFloatingSource) {
+                               switch(specifier) {
+                               case 'p':
+                               case 'P':
+                               case 'c':
+                               case 'C':
+                               case 'f':
+                               case 'F':
+                               case 'N':
+                               case 'n':
+                                       ns.RoundEffectiveDigits (ns.DefaultPrecision);
+                                       break;
+                               case 'g':
+                               case 'G':
+                                       if (precision <= 0)
+                                               ns.RoundEffectiveDigits (ns.DefaultPrecision);
+                                       else
+                                               ns.RoundEffectiveDigits (precision);
+                                       break;
+                               case 'r':
+                               case 'R':
+                                       ns.RoundEffectiveDigits (ns.DefaultMaxPrecision);
+                                       break;
+                               default:
+                                       if (precision > ns.DefaultPrecision)
+                                               ns.RoundEffectiveDigits (precision + 1);
+                                       else
+                                               ns.RoundEffectiveDigits (ns.DefaultPrecision + 1);
+                                       break;
+                               }
+                       }
+
+                       switch(specifier) {
+                       case 'c':
+                       case 'C':
+                               return FormatCurrency (ns, precision, nfi);
+                       case 'd':
+                       case 'D':
+                               return FormatDecimal (ns, precision, nfi);
+                       case 'e':
+                       case 'E':
+                               return FormatExponential (ns, precision, nfi, specifier == 'E');
+                       case 'f': 
+                       case 'F':
+                               return FormatFixedPoint (ns, precision, nfi);
+                       case 'g':
+                       case 'G':
+                               return FormatGeneral (ns, precision, nfi, specifier == 'G');
+                       case 'n':
+                       case 'N':
+                               return FormatNumber (ns, precision, nfi);
+                       case 'p':
+                       case 'P':
+                               return FormatPercent (ns, precision, nfi);
+                       case 'r':
+                       case 'R':
+                               if (ns.IsFloatingSource) {
+                                       return FormatGeneral (ns, ns.DefaultMaxPrecision, nfi, true);
+                               } else {
+                                       throw new FormatException (Locale.GetText ("The specified format cannot be used in this instance"));
+                               }
+                       case 'x': 
+                       case 'X': return FormatHexadecimal (ns, precision, nfi, specifier == 'X');
+                       default: 
+                               throw new FormatException (Locale.GetText ("The specified format '" + format + "' is invalid"));
+                       }       
+               }
+               #endregion
+
+               #region BasicParser
+               private static bool ParseBasicFormat (string format, out char specifier, out int precision, out bool custom)
+               {                                
+                       precision = -1;
+                       specifier = '\0';
+                       custom = false;
+                       
+                       int length = format.Length;
+                       if (length < 1)
+                               return false;
+                       
+                       specifier = format [0];
+
+                       if (Char.IsLetter (specifier)) {
+                               if (format.Length == 1)
+                                       return true;
+
+                               bool flag = true;
+                               precision = 0;
+                               for (int i = 1; i < format.Length; i++) {
+                                       char c = format [i];
+                                       if (char.IsDigit (c)) {
+                                               precision = precision * 10 + (c - '0');
+                                               if (precision > 99) {
+                                                       flag = false;
+                                                       break;
+                                               }
+                                       }
+                                       else {
+                                               flag = false;
+                                               break;
+                                       }
+                               }
+                               if (flag)
+                                       return true;
+                       }
+
+                       custom = true;
+                       return true;
+               }       
+
+               #endregion
+
+               #region Helpers
+               private static void ZeroTrimEnd (StringBuilder sb)
+               {
+                       ZeroTrimEnd (sb, false);
+               }
+               private static void ZeroTrimEnd (StringBuilder sb, bool canEmpty)
+               {
+                       int len = 0;
+                       for (int i = sb.Length - 1; (canEmpty ? i >= 0 : i > 0); i --) {
+                               if (sb [i] != '0')
+                                       break;
+                               len ++;
+                       }
+
+                       if (len > 0)
+                               sb.Remove (sb.Length - len, len);
+               }
+               #endregion
+
+               #region Basic
+               internal static string FormatCurrency (NumberStore ns, int precision, NumberFormatInfo nfi)
+               {
+                       int[] groups = nfi.CurrencyGroupSizes;
+                       string groupSeparator = nfi.CurrencyGroupSeparator;
+                       precision = (precision >= 0 ? precision : nfi.CurrencyDecimalDigits);
+                       StringBuilder sb = new StringBuilder();
+
+                       ns.RoundDecimal (precision);
+                       if (precision > 0) {
+                               sb.Append (nfi.CurrencyDecimalSeparator);
+                               sb.Append (ns.GetDecimalString (precision));
+                       }
+
+                       string intPart = ns.GetIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1);
+                       int index = intPart.Length - 1;
+                       int counter = 0;
+                       int groupIndex = 0;
+                       int groupSize = (groups.Length > 0 ? groups [groupIndex++] : 0);
+                       while (index >= 0) {
+                               sb.Insert (0, intPart [index --]);
+                               counter ++;
+
+                               if (index >= 0 && groupSize > 0 && counter % groupSize == 0) {
+                                       sb.Insert (0, groupSeparator);
+                                       groupSize = (groupIndex < groups.Length ? groups [groupIndex++] : groupSize);
+                                       counter = 0;
+                               }
+                       }
+
+                       if (ns.Positive || NumberStore.IsZeroOnly (sb)) {
+                               switch (nfi.CurrencyPositivePattern) {
+                               case 0:
+                                       sb.Insert (0, nfi.CurrencySymbol);
+                                       break;
+                               case 1:
+                                       sb.Append (nfi.CurrencySymbol);
+                                       break;
+                               case 2:
+                                       sb.Insert (0, " ");
+                                       sb.Insert (0, nfi.CurrencySymbol);
+                                       break;
+                               case 3:
+                                       sb.Append (" ");
+                                       sb.Append (nfi.CurrencySymbol);
+                                       break;
+                               }
+                       } else {
+                               switch (nfi.CurrencyNegativePattern) {
+                               case 0:
+                                       sb.Insert (0, nfi.CurrencySymbol);
+                                       sb.Insert (0, '(');
+                                       sb.Append (')');
+                                       break;
+                               case 1:
+                                       sb.Insert (0, nfi.CurrencySymbol);
+                                       sb.Insert (0, nfi.NegativeSign);
+                                       break;
+                               case 2:
+                                       sb.Insert (0, nfi.NegativeSign);
+                                       sb.Insert (0, nfi.CurrencySymbol);
+                                       break;
+                               case 3:
+                                       sb.Insert (0, nfi.CurrencySymbol);
+                                       sb.Append (nfi.NegativeSign);
+                                       break;
+                               case 4:
+                                       sb.Insert (0, '(');
+                                       sb.Append (nfi.CurrencySymbol);
+                                       sb.Append (')');
+                                       break;
+                               case 5:
+                                       sb.Insert (0, nfi.NegativeSign);
+                                       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.Insert (0, nfi.NegativeSign);
+                                       sb.Append (' ');
+                                       sb.Append (nfi.CurrencySymbol);
+                                       break;
+                               case 9:
+                                       sb.Insert (0, ' ');
+                                       sb.Insert (0, nfi.CurrencySymbol);
+                                       sb.Insert (0, nfi.NegativeSign);
+                                       break;
+                               case 10:
+                                       sb.Append (' ');
+                                       sb.Append (nfi.CurrencySymbol);
+                                       sb.Append (nfi.NegativeSign);
+                                       break;
+                               case 11:
+                                       sb.Insert (0, ' ');
+                                       sb.Insert (0, nfi.CurrencySymbol);
+                                       sb.Append (nfi.NegativeSign);
+                                       break;
+                               case 12:
+                                       sb.Insert (0, nfi.NegativeSign);
+                                       sb.Insert (0, ' ');
+                                       sb.Insert (0, nfi.CurrencySymbol);
+                                       break;
+                               case 13:
+                                       sb.Append (nfi.NegativeSign);
+                                       sb.Append (' ');
+                                       sb.Append (nfi.CurrencySymbol);
+                                       break;
+                               case 14:
+                                       sb.Insert (0, ' ');
+                                       sb.Insert (0, nfi.CurrencySymbol);
+                                       sb.Insert (0, '(');
+                                       sb.Append (')');
+                                       break;
+                               case 15:
+                                       sb.Insert (0, '(');
+                                       sb.Append (' ');
+                                       sb.Append (nfi.CurrencySymbol);
+                                       sb.Append (')');
+                                       break;
+                               }
+                       }
+
+                       return sb.ToString ();
+               }
+               internal static string FormatDecimal (NumberStore ns, int precision, NumberFormatInfo nfi)
+               {
+                       if (ns.IsFloatingSource)
+                               throw new FormatException ();
+
+                       precision = precision > 0 ? precision : 1;
+                       StringBuilder sb = new StringBuilder();
+                       sb.Append (ns.GetIntegerString (ns.IntegerDigits > precision ? ns.IntegerDigits : precision));
+
+                       if (!ns.Positive && !NumberStore.IsZeroOnly (sb))
+                               sb.Insert (0, nfi.NegativeSign);
+
+                       return sb.ToString ();
+               }
+               internal static string FormatFixedPoint (NumberStore ns, int precision, NumberFormatInfo nfi)
+               {
+                       precision = precision >= 0 ? precision : nfi.NumberDecimalDigits;
+                       ns.RoundDecimal (precision);
+
+                       StringBuilder sb = new StringBuilder();
+                       sb.Append (ns.GetIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1));
+
+                       if (precision > 0) {
+                               sb.Append (nfi.NumberDecimalSeparator);
+                               sb.Append (ns.GetDecimalString (precision));
+                       }
+
+                       if (!ns.Positive && !NumberStore.IsZeroOnly (sb))
+                               sb.Insert (0, nfi.NegativeSign);
+
+                       return sb.ToString ();
+               }
+
+               internal static string FormatGeneral (NumberStore ns, int precision, NumberFormatInfo nfi, bool upper)
+               {
+                       if (ns.ZeroOnly)
+                               return "0";
+
+                       precision = precision > 0 ? precision : ns.DefaultPrecision;
+                       StringBuilder sb = new StringBuilder();
+
+                       int preExponent = 0;
+                       NumberStore prens = ns.GetClone ();
+                       while (!(prens.DecimalPointPosition == 1 && prens.GetChar (0) != '0')) {
+                               if (prens.DecimalPointPosition > 1) {
+                                       prens.Divide10 (1);
+                                       preExponent ++;
+                               } else {
+                                       prens.Multiply10 (1);
+                                       preExponent --;
+                               }
+                       }
+
+                       bool fixedPointMode = preExponent > -5 && preExponent < precision;
+
+                       precision = precision < ns.DefaultPrecision + 2 ? precision : ns.DefaultPrecision + 2;
+                       precision = precision < 17 ? precision : 17;
+                       if (fixedPointMode) {
+                               ns.RoundDecimal (precision);
+                       } else {
+                               ns = prens;
+                               if (ns.RoundDecimal (precision - 1)) {
+                                       ns.Divide10 (1);
+                                       preExponent ++;
+                               }
+                       }
+
+                       if (!ns.Positive) {
+                               sb.Append (nfi.NegativeSign);
+                       }
+                       sb.Append (ns.GetIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1));
+                       if (ns.DecimalDigits > 0) {
+                               sb.Append (nfi.NumberDecimalSeparator);
+                               sb.Append (ns.GetDecimalString (ns.DecimalDigits));
+                       }
+
+                       if (!fixedPointMode) {
+                               if (upper)
+                                       sb.Append ('E');
+                               else
+                                       sb.Append ('e');
+
+                               if (preExponent >= 0)
+                                       sb.Append (nfi.PositiveSign);
+                               else {
+                                       sb.Append (nfi.NegativeSign);
+                                       preExponent = -preExponent;
+                               }
+
+                               if (preExponent < 10)
+                                       sb.Append ('0');
+
+                               int pos = sb.Length;
+                               while (preExponent > 0) {
+                                       sb.Insert (pos, digitLowerTable [preExponent % 10]);
+                                       preExponent /= 10;
+                               }
+                       }
+
+                       return sb.ToString ();
+               }
+               internal static string FormatNumber (NumberStore ns, int precision, NumberFormatInfo nfi)
+               {
+                       int[] groups = nfi.NumberGroupSizes;
+                       string groupSeparator = nfi.NumberGroupSeparator;
+                       precision = (precision >= 0 ? precision : nfi.NumberDecimalDigits);
+                       StringBuilder sb = new StringBuilder();
+
+                       ns.RoundDecimal (precision);
+                       if (precision > 0) {
+                               sb.Append (nfi.NumberDecimalSeparator);
+                               sb.Append (ns.GetDecimalString (precision));
+                       }
+
+                       string intPart = ns.GetIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1);
+                       int index = intPart.Length - 1;
+                       int counter = 0;
+                       int groupIndex = 0;
+                       int groupSize = (groups.Length > 0 ? groups [groupIndex++] : 0);
+                       while (index >= 0) {
+                               sb.Insert (0, intPart [index --]);
+                               counter ++;
+
+                               if (index >= 0 && groupSize > 0 && counter % groupSize == 0) {
+                                       sb.Insert (0, groupSeparator);
+                                       groupSize = (groupIndex < groups.Length ? groups [groupIndex++] : groupSize);
+                                       counter = 0;
+                               }
+                       }
+
+                       if (!ns.Positive && !NumberStore.IsZeroOnly (sb)) {
+                               switch (nfi.NumberNegativePattern) {
+                               case 0:
+                                       sb.Insert (0, '(');
+                                       sb.Append (')');
+                                       break;
+                               case 1:
+                                       sb.Insert (0, nfi.NegativeSign);
+                                       break;
+                               case 2:
+                                       sb.Insert (0, ' ');
+                                       sb.Insert (0, nfi.NegativeSign);
+                                       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)
+               {
+                       int[] groups = nfi.PercentGroupSizes;
+                       string groupSeparator = nfi.PercentGroupSeparator;
+                       precision = (precision >= 0 ? precision : nfi.PercentDecimalDigits);
+                       StringBuilder sb = new StringBuilder();
+
+                       ns.Multiply10 (2);
+
+                       ns.RoundDecimal (precision);
+                       if (precision > 0) {
+                               sb.Append (nfi.PercentDecimalSeparator);
+                               sb.Append (ns.GetDecimalString (precision));
+                       }
+
+                       string intPart = ns.GetIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1);
+                       int index = intPart.Length - 1;
+                       int counter = 0;
+                       int groupIndex = 0;
+                       int groupSize = (groups.Length > 0 ? groups [groupIndex++] : 0);
+                       while (index >= 0) {
+                               sb.Insert (0, intPart [index --]);
+                               counter ++;
+
+                               if (index >= 0 && groupSize > 0 && counter % groupSize == 0) {
+                                       sb.Insert (0, groupSeparator);
+                                       groupSize = (groupIndex < groups.Length ? groups [groupIndex++] : groupSize);
+                                       counter = 0;
+                               }
+                       }
+
+                       if (ns.Positive || NumberStore.IsZeroOnly (sb)) {
+                               switch (nfi.PercentPositivePattern) {
+                               case 0:
+                                       sb.Append (' ');
+                                       sb.Append (nfi.PercentSymbol);
+                                       break;
+                               case 1:
+                                       sb.Append (nfi.PercentSymbol);
+                                       break;
+                               case 2:
+                                       sb.Insert (0, nfi.PercentSymbol);
+                                       break;
+                               }
+                       } else {
+                               switch (nfi.PercentNegativePattern) {
+                               case 0:
+                                       sb.Append (' ');
+                                       sb.Append (nfi.PercentSymbol);
+                                       sb.Insert (0, nfi.NegativeSign);
+                                       break;
+                               case 1:
+                                       sb.Append (nfi.PercentSymbol);
+                                       sb.Insert (0, nfi.NegativeSign);
+                                       break;
+                               case 2:
+                                       sb.Insert (0, nfi.PercentSymbol);
+                                       sb.Insert (0, nfi.NegativeSign);
+                                       break;
+                               }
+                       }
+
+                       return sb.ToString ();
+               }
+               internal static string FormatHexadecimal (NumberStore ns, int precision, NumberFormatInfo nfi, bool upper)
+               {
+                       if (ns.IsFloatingSource)
+                               throw new FormatException ();
+
+                       StringBuilder sb = new StringBuilder();
+
+                       int intSize = ns.DefaultByteSize;
+                       ulong value = ulong.Parse (ns.GetIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1));
+
+                       if (!ns.Positive) {
+                               value = (ulong)(Math.Pow (2, intSize * 8)) - value;
+                       }
+
+                       char[] digits = (upper ? digitUpperTable : digitLowerTable);
+
+                       while (value > 0) {
+                               sb.Insert (0, digits [value % 16]);
+                               value >>= 4;
+                       }
+
+                       if (sb.Length == 0)
+                               sb.Append ('0');
+
+                       if (sb.Length < precision)
+                               sb.Insert (0, "0", precision - sb.Length);
+
+                       return sb.ToString ();
+               }
+               internal static string FormatExponential (NumberStore ns, int precision, NumberFormatInfo nfi, bool upper)
+               {
+                       if (precision < 0)
+                               precision = 6;
+                       string decimalPart = (precision > 0 ? string.Concat(".", new string ('0', precision)) : "");
+                       return FormatCustom (string.Concat ("0", decimalPart , (upper ? "E": "e"), "+000"), ns, nfi);
+               }
+               #endregion
+
+               #region Custom
+               internal static string FormatCustom (string format, NumberStore ns, NumberFormatInfo nfi)
+               {
+                       bool p = ns.Positive;
+                       format = CustomInfo.GetActiveSection (format,ref p, ns.ZeroOnly);
+                       if (format == "") {
+                               return ns.Positive ? "" : nfi.NegativeSign;
+                       }
+                       ns.Positive = p;
+
+                       CustomInfo info = CustomInfo.Parse (format, nfi);
+#if false
+                       Console.WriteLine("Format : {0}",format);
+                       Console.WriteLine("DecimalDigits : {0}",info.DecimalDigits);
+                       Console.WriteLine("DecimalPointPos : {0}",info.DecimalPointPos);
+                       Console.WriteLine("DecimalTailSharpDigits : {0}",info.DecimalTailSharpDigits);
+                       Console.WriteLine("IntegerDigits : {0}",info.IntegerDigits);
+                       Console.WriteLine("IntegerHeadSharpDigits : {0}",info.IntegerHeadSharpDigits);
+                       Console.WriteLine("IntegerHeadPos : {0}",info.IntegerHeadPos);
+                       Console.WriteLine("UseExponent : {0}",info.UseExponent);
+                       Console.WriteLine("ExponentDigits : {0}",info.ExponentDigits);
+                       Console.WriteLine("ExponentTailSharpDigits : {0}",info.ExponentTailSharpDigits);
+                       Console.WriteLine("ExponentNegativeSignOnly : {0}",info.ExponentNegativeSignOnly);
+                       Console.WriteLine("DividePlaces : {0}",info.DividePlaces);
+                       Console.WriteLine("Percents : {0}",info.Percents);
+                       Console.WriteLine("Permilles : {0}",info.Permilles);
+#endif
+                       StringBuilder sb_int = new StringBuilder();
+                       StringBuilder sb_dec = new StringBuilder();
+                       StringBuilder sb_exp = new StringBuilder();
+
+                       int diff = 0;
+                       if (info.Percents > 0) {
+                               ns.Multiply10 (2 * info.Percents);
+                       }
+                       if (info.Permilles > 0) {
+                               ns.Multiply10 (3 * info.Permilles);
+                       }
+                       if (info.DividePlaces > 0) {
+                               ns.Divide10 (info.DividePlaces);
+                       }
+
+                       bool expPositive = true;
+                       if (info.UseExponent && (info.DecimalDigits > 0 || info.IntegerDigits > 0)) {
+                               if (!ns.ZeroOnly) {
+                                       while (true) {
+                                               while (ns.IntegerDigits > info.IntegerDigits) {
+                                                       ns.Divide10 (1);
+                                                       diff--;
+                                                       if (ns.IntegerDigits == 1 && ns.GetChar (0) == '0')
+                                                               break;
+                                               }
+                                               while (ns.IntegerDigits < info.IntegerDigits || (ns.IntegerDigits == info.IntegerDigits && ns.GetChar (0) == '0')) {
+                                                       ns.Multiply10 (1);
+                                                       diff++;
+                                               }
+
+                                               if (!ns.RoundDecimal (info.DecimalDigits))
+                                                       break;
+                                       }
+                               }
+
+                               int exp = diff >= 0 ? diff : -diff;
+                               expPositive = -diff >= 0;
+                               while (exp > 0) {
+                                       sb_exp.Insert (0, digitLowerTable [exp % 10]);
+                                       exp /= 10;
+                               }
+                       } else {
+                               ns.RoundDecimal (info.DecimalDigits);
+                               if (ns.ZeroOnly)
+                                       ns.Positive = true;
+                       }
+
+                       sb_int.Append (ns.GetIntegerString (ns.IntegerDigits));
+                       if (sb_int.Length > info.IntegerDigits) {
+                               int len = 0;
+                               while (sb_int.Length > info.IntegerDigits && len < sb_int.Length) {
+                                       if (sb_int [len] == '0')
+                                               len ++;
+                                       else
+                                               break;
+                               }
+                               sb_int.Remove (0, len);
+                       }
+                                       
+                       sb_dec.Append (ns.GetDecimalString (ns.DecimalDigits));
+
+                       if (info.UseExponent) {
+                               if (info.DecimalDigits <= 0 && info.IntegerDigits <= 0)
+                                       ns.Positive = true;
+
+                               if (sb_int.Length < info.IntegerDigits)
+                                       sb_int.Insert (0, "0", info.IntegerDigits - sb_int.Length);
+
+                               while (sb_exp.Length < info.ExponentDigits - info.ExponentTailSharpDigits)
+                                       sb_exp.Insert (0, "0");
+
+                               if (expPositive && !info.ExponentNegativeSignOnly)
+                                       sb_exp.Insert (0, nfi.PositiveSign);
+                               else if(!expPositive)
+                                       sb_exp.Insert (0, nfi.NegativeSign);
+                       } else {
+                               if (sb_int.Length < info.IntegerDigits - info.IntegerHeadSharpDigits)
+                                       sb_int.Insert (0, "0", info.IntegerDigits - info.IntegerHeadSharpDigits - sb_int.Length);
+                               if (info.IntegerDigits == info.IntegerHeadSharpDigits && NumberStore.IsZeroOnly (sb_int))
+                                       sb_int.Remove (0, sb_int.Length);
+                       }
+
+                       ZeroTrimEnd (sb_dec, true);
+                       while (sb_dec.Length < info.DecimalDigits - info.DecimalTailSharpDigits)
+                               sb_dec.Append ('0');
+                       if (sb_dec.Length > info.DecimalDigits)
+                               sb_dec.Remove (info.DecimalDigits, sb_dec.Length - info.DecimalDigits);
+
+                       return info.Format (format, nfi, ns.Positive, sb_int.ToString (), sb_dec.ToString (), sb_exp.ToString ());
+               }
+
+               private class CustomInfo
+               {
+                       public bool UseGroup = false;
+                       public int DecimalDigits = 0;
+                       public int DecimalPointPos = -1;
+                       public int DecimalTailSharpDigits = 0;
+                       public int IntegerDigits = 0;
+                       public int IntegerHeadSharpDigits = 0;
+                       public int IntegerHeadPos = -1;
+                       public bool UseExponent = false;
+                       public int ExponentDigits = 0;
+                       public int ExponentTailSharpDigits = 0;
+                       public bool ExponentNegativeSignOnly = true;
+                       public int DividePlaces = 0;
+                       public int Percents = 0;
+                       public int Permilles = 0;
+
+                       public static string GetActiveSection (string format, ref bool positive, bool zero)
+                       {
+                               int[] lens = new int [3];
+                               int index = 0;
+                               int lastPos = 0;
+                               char literal = '\0';
+                               for (int i = 0; i < format.Length; i++) {
+                                       char c = format [i];
+
+                                       if (c == literal || (literal == '\0' && (c == '\"' || c == '\''))) {
+                                               if (literal == '\0')
+                                                       literal = c;
+                                               else
+                                                       literal = '\0';
+                                               continue;
+                                       }
+                                       
+                                       if (literal == '\0' && format [i] == ';' && (i == 0 || format [i - 1] != '\\')) {
+                                               lens [index ++] = i - lastPos;
+                                               lastPos = i + 1;
+                                               if (index == 3)
+                                                       break;
+                                       }
+                               }
+
+                               if (index == 0)
+                                       return format;
+                               if (index == 1) {
+                                       if (positive || zero)
+                                               return format.Substring (0, lens [0]);
+                                       if (lens [0] + 1 < format.Length) {
+                                               positive = true;
+                                               return format.Substring (lens [0] + 1);
+                                       } else
+                                               return format.Substring (0, lens [0]);
+                               }
+                               if (index == 2) {
+                                       if (zero)
+                                               return format.Substring (lens [0] + lens [1] + 2);
+                                       if (positive)
+                                               return format.Substring (0, lens [0]);
+                                       if (lens [1] > 0) {
+                                               positive = true;
+                                               return format.Substring (lens [0] + 1, lens [1]);
+                                       } else
+                                               return format.Substring (0, lens [0]);
+                               }
+                               if (index == 3) {
+                                       if (zero)
+                                               return format.Substring (lens [0] + lens [1] + 2, lens [2]);
+                                       if (positive)
+                                               return format.Substring (0, lens [0]);
+                                       if (lens [1] > 0) {
+                                               positive = true;
+                                               return format.Substring (lens [0] + 1, lens [1]);
+                                       } else
+                                               return format.Substring (0, lens [0]);
+                               }
+
+                               throw new ArgumentException ();
+                       }
+
+                       public static CustomInfo Parse (string format, NumberFormatInfo nfi)
+                       {
+                               char literal = '\0';
+                               bool integerArea = true;
+                               bool decimalArea = false;
+                               bool exponentArea = false;
+                               bool sharpContinues = true;
+
+                               CustomInfo info = new CustomInfo ();
+                               int groupSeparatorCounter = 0;
+
+                               for (int i = 0; i < format.Length; i++) {
+                                       char c = format [i];
+
+                                       if (c == literal && c != '\0') {
+                                               literal = '\0';
+                                               continue;
+                                       }
+                                       if (literal != '\0')
+                                               continue;
+
+                                       if (exponentArea && (c != '\0' && c != '0' && c != '#')) {
+                                               exponentArea = false;
+                                               integerArea = (info.DecimalPointPos < 0);
+                                               decimalArea = !integerArea;
+                                               i--;
+                                               continue;
+                                       }
+
+                                       switch (c) {
+                                       case '\\':
+                                               i ++;
+                                               continue;
+                                       case '\'':
+                                       case '\"':
+                                               if (c == '\"' || c == '\'') {
+                                                       literal = c;
+                                               }
+                                               continue;
+                                       case '#':
+                                               if (sharpContinues && integerArea)
+                                                       info.IntegerHeadSharpDigits ++;
+                                               else if (decimalArea)
+                                                       info.DecimalTailSharpDigits ++;
+                                               else if (exponentArea)
+                                                       info.ExponentTailSharpDigits ++;
+
+                                               goto case '0';
+                                       case '0':
+                                               if (c != '#') {
+                                                       sharpContinues = false;
+                                                       if (decimalArea)
+                                                               info.DecimalTailSharpDigits = 0;
+                                                       else if (exponentArea)
+                                                               info.ExponentTailSharpDigits = 0;
+                                               }
+                                               if (info.IntegerHeadPos == -1)
+                                                       info.IntegerHeadPos = i;
+
+                                               if (integerArea) {
+                                                       info.IntegerDigits ++;
+                                                       if (groupSeparatorCounter > 0)
+                                                               info.UseGroup = true;
+                                                       groupSeparatorCounter = 0;
+                                               } else if (decimalArea) {
+                                                       info.DecimalDigits ++;
+                                               } else if (exponentArea) {
+                                                       info.ExponentDigits ++;
+                                               }
+                                               break;
+                                       case 'e':
+                                       case 'E':
+                                               if (info.UseExponent)
+                                                       break;
+
+                                               info.UseExponent = true;
+                                               integerArea = false;
+                                               decimalArea = false;
+                                               exponentArea = true;
+                                               if (i + 1 < format.Length) {
+                                                       char nc = format [i + 1];
+                                                       if (nc == '+')
+                                                               info.ExponentNegativeSignOnly = false;
+                                                       if (nc == '+' || nc == '-') {
+                                                               i ++;
+                                                       } else if (nc != '0' && nc != '#') {
+                                                               info.UseExponent = false;
+                                                               if (info.DecimalPointPos < 0)
+                                                                       integerArea = true;
+                                                       }
+                                                       c = '\0';
+                                               }
+                                               
+                                               break;
+                                       case '.':
+                                               integerArea = false;
+                                               decimalArea = true;
+                                               exponentArea = false;
+                                               if (info.DecimalPointPos == -1)
+                                                       info.DecimalPointPos = i;
+                                               break;
+                                       case '%':
+                                               info.Percents++;
+                                               break;
+                                       case '\u2030':
+                                               info.Permilles++;
+                                               break;
+                                       case ',':
+                                               if (integerArea && info.IntegerDigits > 0)
+                                                       groupSeparatorCounter ++;
+                                               break;
+                                       default:
+                                               break;
+                                       }
+                               }
+
+                               if (info.ExponentDigits == 0)
+                                       info.UseExponent = false;
+                               else
+                                       info.IntegerHeadSharpDigits = 0;
+
+                               if (info.DecimalDigits == 0)
+                                       info.DecimalPointPos = -1;
+
+                               info.DividePlaces += groupSeparatorCounter * 3;
+
+                               return info;
+                       }
+
+                       public string Format (string format, NumberFormatInfo nfi, bool positive, string sb_int, string sb_dec, string sb_exp)
+                       {
+                               StringBuilder sb = new StringBuilder ();
+                               char literal = '\0';
+                               bool integerArea = true;
+                               bool decimalArea = false;
+                               int  intSharpCounter = 0;
+                               int sb_int_index = 0;
+                               int sb_dec_index = 0;
+
+                               int[] groups = GetFormattedGroupSizes (sb_int.Length, nfi);
+                               int groupIndex = 0;
+                               int groupSize = (groups.Length > 0 ? groups [groupIndex++] : -1);
+                               int int_counter = 0;
+
+                               for (int i = 0; i < format.Length; i++) {
+                                       char c = format [i];
+
+                                       if (c == literal && c != '\0') {
+                                               literal = '\0';
+                                               continue;
+                                       }
+                                       if (literal != '\0') {
+                                               sb.Append (c);
+                                               continue;
+                                       }
+
+                                       switch (c) {
+                                       case '\\':
+                                               i ++;
+                                               if (i < format.Length)
+                                                       sb.Append (format [i]);
+                                               continue;
+                                       case '\'':
+                                       case '\"':
+                                               if (c == '\"' || c == '\'') {
+                                                       literal = c;
+                                               }
+                                               continue;
+                                       case '#':
+                                               goto case '0';
+                                       case '0':
+                                               if (integerArea) {
+                                                       intSharpCounter++;
+                                                       if (IntegerDigits - intSharpCounter < sb_int.Length + sb_int_index || c == '0')
+                                                               while (IntegerDigits - intSharpCounter + sb_int_index < sb_int.Length) {
+                                                                       sb.Append (sb_int[ sb_int_index++]);
+                                                                       int_counter ++;
+                                                                       if (UseGroup && groupSize > 0 && int_counter % groupSize == 0 && sb_int_index < sb_int.Length) {
+                                                                               sb.Append (nfi.NumberGroupSeparator);
+                                                                               groupSize = (groupIndex < groups.Length ? groups [groupIndex++] : groupSize);
+                                                                               int_counter = 0;
+                                                                       }
+                                                               }
+                                                       break;
+                                               } else if (decimalArea) {
+                                                       if (sb_dec_index < sb_dec.Length)
+                                                               sb.Append (sb_dec [sb_dec_index++]);
+                                                       break;
+                                               }
+
+                                               sb.Append (c);
+                                               break;
+                                       case 'e':
+                                       case 'E':
+                                               if (sb_exp == null || !UseExponent) {
+                                                       sb.Append (c);
+                                                       break;
+                                               }
+
+                                               bool flag1 = true;
+                                               bool flag2 = false;
+                                               
+                                               int q;
+                                               for (q = i + 1; q < format.Length; q++) {
+                                                       if (format [q] == '0') {
+                                                               flag2 = true;
+                                                               continue;
+                                                       }
+                                                       if (q == i + 1 && (format [q] == '+' || format [q] == '-')) {
+                                                               continue;
+                                                       }
+                                                       if (!flag2)
+                                                               flag1 = false;
+                                                       break;
+                                               }
+
+                                               if (flag1) {
+                                                       i = q - 1;
+                                                       integerArea = (DecimalPointPos < 0);
+                                                       decimalArea = !integerArea;
+
+                                                       sb.Append (c);
+                                                       sb.Append (sb_exp);
+                                                       sb_exp = null;
+                                               } else
+                                                       sb.Append (c);
+
+                                               break;
+                                       case '.':
+                                               if (DecimalPointPos == i) {
+                                                       if (DecimalDigits > 0) {
+                                                               while (sb_int_index < sb_int.Length)
+                                                                       sb.Append (sb_int [sb_int_index++]);
+                                                       }
+                                                       if (sb_dec.Length > 0)
+                                                               sb.Append (nfi.NumberDecimalSeparator);
+                                               }
+                                               integerArea = false;
+                                               decimalArea = true;
+                                               break;
+                                       case ',':
+                                               break;
+                                       case '%':
+                                               sb.Append (nfi.PercentSymbol);
+                                               break;
+                                       case '\u2030':
+                                               sb.Append (nfi.PerMilleSymbol);
+                                               break;
+                                       default:
+                                               sb.Append (c);
+                                               break;
+                                       }
+                               }
+
+                               if (!positive)
+                                       sb.Insert (0, nfi.NegativeSign);
+
+                               return sb.ToString ();
+                       }
+                       private int[] GetFormattedGroupSizes (int intLen, NumberFormatInfo nfi)
+                       {
+                               int[] sizes = new int [intLen];
+
+                               int index = 0;
+                               int counter = 0;
+                               int[] groups = nfi.NumberGroupSizes;
+                               int groupIndex = 0;
+                               int groupSize = (groups.Length > 0 ? groups [groupIndex++] : 0);
+                               for (int i = 0; i < intLen; i++) {
+                                       counter ++;
+                                       if (groupSize > 0 && counter % groupSize == 0) {
+                                               sizes [index++] = groupSize;
+                                               groupSize = (groupIndex < groups.Length ? groups [groupIndex++] : groupSize);
+                                               counter = 0;
+                                       }
+                               }
+
+                               if (counter > 0) {
+                                       sizes [index++] = counter;
+                               }
+
+                               int[] temp = new int[index];
+                               Array.Copy (sizes, 0, temp, 0, index);
+                               Array.Reverse (temp);
+
+                               return temp;
+                       }
+               }
+
+               #endregion
+
+               #region Internal Class
+               internal class NumberStore
+               {
+                       protected bool _NaN;
+                       protected bool _infinity;
+                       protected bool _positive;
+                       protected int  _decPointPos;
+                       protected int  _defPrecision;
+                       protected int  _defMaxPrecision;
+                       protected int  _defByteSize;
+
+                       protected byte[] _digits;
+
+                       #region Create
+                       public static DoubleStore CreateInstance (double value)
+                       {
+                               return new DoubleStore (value);
+                       }
+                       public static SingleStore CreateInstance (float value)
+                       {
+                               return new SingleStore (value);
+                       }
+                       public static IntegerStore CreateInstance (long value)
+                       {
+                               return new IntegerStore (value);
+                       }
+                       public static IntegerStore CreateInstance (ulong value)
+                       {
+                               return new IntegerStore (value);
+                       }
+                       public static IntegerStore CreateInstance (int value)
+                       {
+                               return new IntegerStore (value);
+                       }
+                       public static IntegerStore CreateInstance (uint value)
+                       {
+                               return new IntegerStore (value);
+                       }
+                       public static IntegerStore CreateInstance (short value)
+                       {
+                               return new IntegerStore (value);
+                       }
+                       public static IntegerStore CreateInstance (ushort value)
+                       {
+                               return new IntegerStore (value);
+                       }
+                       public static IntegerStore CreateInstance (byte value)
+                       {
+                               return new IntegerStore (value);
+                       }
+                       public static IntegerStore CreateInstance (sbyte value)
+                       {
+                               return new IntegerStore (value);
+                       }
+                       #endregion
+
+                       #region Public Property
+                       public virtual bool IsNaN 
+                       {
+                               get { return _NaN; }
+                       }
+                       public virtual bool IsInfinity {
+                               get { return _infinity; }
+                       }
+                       public virtual int DecimalPointPosition {
+                               get { return _decPointPos; }
+                       }
+                       public virtual bool Positive {
+                               get { return _positive; }
+                               set { _positive = value;}
+                       }
+                       public virtual int DefaultPrecision {
+                               get { return _defPrecision; }
+                       }
+                       public virtual int DefaultMaxPrecision {
+                               get { return _defMaxPrecision; }
+                       }
+                       public virtual int DefaultByteSize {
+                               get { return _defByteSize; }
+                       }
+                       public virtual bool HasDecimal {
+                               get { return _digits.Length > _decPointPos; }
+                       }
+                       public virtual int IntegerDigits {
+                               get { return _decPointPos > 0 ? _decPointPos : 1; }
+                       }
+                       public virtual int DecimalDigits {
+                               get { return HasDecimal ? _digits.Length - _decPointPos : 0; }
+                       }
+                       public virtual bool IsFloatingSource {
+                               get { return _defPrecision == 15 || _defPrecision == 7; }
+                       }
+                       public virtual bool ZeroOnly {
+                               get {
+                                       for (int i = 0; i < _digits.Length; i++)
+                                               if (_digits [i] != 0)
+                                                       return false;
+                                       return true;
+                               }
+                       }
+                       #endregion
+
+                       #region Public Method
+                       public virtual bool RoundPos (int pos)
+                       {
+                               return RoundPos (pos, true);
+                       }
+                       public virtual bool RoundPos (int pos, bool carryFive)
+                       {
+                               bool carry = false;
+
+                               if (_decPointPos <= 0)
+                                       pos = pos - _decPointPos - 1;
+
+                               if (pos >= _digits.Length)
+                                       return false;
+
+                               if (pos < 0) {
+                                       _digits = new byte [1];
+                                       _digits [0] = 0;
+                                       _decPointPos = 1;
+                                       _positive = true;
+                                       return false;
+                               }
+
+                               for (int i = pos; i >= 0; i--) {
+                                       RoundHelper (i, carryFive, ref carry);
+                                       if (!carry)
+                                               break;
+                               }
+
+                               if (carry) {
+                                       byte[] temp = new byte [_digits.Length + 1];
+                                       _digits.CopyTo (temp, 1);
+                                       temp [0] = 1;
+                                       _digits = temp;
+                                       _decPointPos ++;
+                                       pos ++;
+                               }
+
+                               for (int i = pos; i < _digits.Length; i++)
+                                       _digits [i] = 0;
+                               TrimDecimalEndZeros ();
+
+                               return carry;
+                       }
+                       public virtual bool RoundDecimal (int decimals)
+                       {
+                               return RoundDecimal (decimals, true);
+                       }
+                       public virtual bool RoundDecimal (int decimals, bool carryFive)
+                       {
+                               bool carry = false;
+
+                               decimals += _decPointPos;
+
+                               if (!HasDecimal || decimals >= _digits.Length)
+                                       return false;
+
+                               if (decimals < 0) {
+                                       _digits = new byte [1];
+                                       _digits [0] = 0;
+                                       _decPointPos = 1;
+                                       _positive = true;
+                                       return false;
+                               }
+
+                               for (int i = decimals; i >= 0; i--) {
+                                       RoundHelper (i, carryFive, ref carry);
+                                       if (!carry)
+                                               break;
+                               }
+
+                               if (carry) {
+                                       byte[] temp = new byte [_digits.Length + 1];
+                                       _digits.CopyTo (temp, 1);
+                                       temp [0] = 1;
+                                       _digits = temp;
+                                       _decPointPos ++;
+                                       decimals ++;
+                               }
+
+                               for (int i = decimals; i < _digits.Length; i++)
+                                       _digits [i] = 0;
+                               TrimDecimalEndZeros ();
+
+                               return carry;
+                       }
+                       protected virtual void RoundHelper (int index, bool carryFive, ref bool carry)
+                       {
+                               if (carry) {
+                                       if (_digits [index] == 9) {
+                                               carry = true;
+                                               _digits [index] = 0;
+                                       } else {
+                                               carry = false;
+                                               _digits [index] ++;
+                                       }
+                               } else if (_digits [index] >= (carryFive ? 5 : 6)) {
+                                       carry = true;
+                               }
+                       }
+                       public virtual bool RoundEffectiveDigits (int digits)
+                       {
+                               return RoundEffectiveDigits (digits, true, true);
+                       }
+                       public virtual bool RoundEffectiveDigits (int digits, bool carryFive, bool carryEven)
+                       {
+                               bool carry = false;
+
+                               if (digits >= _digits.Length || digits < 0)
+                                       return false;
+
+                               if (digits + 1 < _digits.Length && _digits [digits + 1] == 5 && _digits [digits] % 2 == (carryEven ? 0 : 1))
+                                       carryFive = false;
+
+                               for (int i = digits; i >= 0; i--) {
+                                       RoundHelper (i, carryFive, ref carry);
+                                       if (!carry)
+                                               break;
+                               }
+
+                               if (carry) {
+                                       byte[] temp = new byte [_digits.Length + 1];
+                                       _digits.CopyTo (temp, 1);
+                                       temp [0] = 1;
+                                       _digits = temp;
+                                       _decPointPos ++;
+                                       digits ++;
+                               }
+
+                               for (int i = digits; i < _digits.Length; i++)
+                                       _digits [i] = 0;
+                               TrimDecimalEndZeros ();
+
+                               return carry;
+                       }
+                       public virtual void TrimDecimalEndZeros ()
+                       {
+                               int len = 0;
+                               for (int i = _digits.Length - 1; i >= 0; i --) {
+                                       if (_digits [i] != 0)
+                                               break;
+                                       len ++;
+                               }
+
+                               if (len > 0) {
+                                       byte[] temp = new byte [_digits.Length - len];
+                                       Array.Copy (_digits, 0, temp, 0, temp.Length);
+                                       _digits = temp;
+                               }
+                       }
+                       public virtual void TrimIntegerStartZeros ()
+                       {
+                               if (_decPointPos < 0 && _decPointPos >= _digits.Length)
+                                       return;
+
+                               int len = 0;
+                               for (int i = 0; i < _decPointPos && i < _digits.Length; i++) {
+                                       if (_digits [i] != 0)
+                                               break;
+                                       len ++;
+                               }
+
+                               if (len == _decPointPos)
+                                       len --;
+
+                               if (len == _digits.Length) {
+                                       _digits = new byte [1];
+                                       _digits [0] = 0;
+                                       _decPointPos = 1;
+                                       _positive = true;
+                               } else if (len > 0) {
+                                       byte[] temp = new byte [_digits.Length - len];
+                                       Array.Copy (_digits, len, temp, 0, temp.Length);
+                                       _digits = temp;
+                                       _decPointPos -= len;
+                               }
+                       }
+
+                       public virtual string GetIntegerString (int minLength)
+                       {
+                               if (IntegerDigits == 0)
+                                       return new string ('0', minLength);
+
+                               StringBuilder sb = new StringBuilder (IntegerDigits > minLength ? IntegerDigits : minLength);
+                               for (int i = 0; i < _decPointPos; i++) {
+                                       if (i < _digits.Length)
+                                               sb.Append ((char)('0' + _digits [i]));
+                                       else
+                                               sb.Append ('0');
+                               }
+                               if (sb.Length < minLength)
+                                       sb.Insert (0, "0", minLength - sb.Length);
+                               return sb.ToString ();
+                       }
+                       public virtual string GetDecimalString (int precision)
+                       {
+                               if (!HasDecimal)
+                                       return new string ('0', precision);
+
+                               StringBuilder sb = new StringBuilder (precision);
+                               for (int i = _decPointPos; i < _digits.Length && i < precision + _decPointPos; i++) {
+                                       if (i >= 0)
+                                               sb.Append ((char)('0' + _digits [i]));
+                                       else
+                                               sb.Append ('0');
+                               }
+                               if (sb.Length < precision)
+                                       sb.Append ('0', precision - sb.Length);
+                               else if (sb.Length > precision)
+                                       sb.Remove (0, precision);
+                               return sb.ToString ();
+                       }
+                       public virtual void Multiply10 (int count)
+                       {
+                               if (count <= 0)
+                                       return;
+
+                               _decPointPos += count;
+
+                               TrimIntegerStartZeros ();
+                       }
+                       public virtual void Divide10 (int count)
+                       {
+                               if (count <= 0)
+                                       return;
+
+                               _decPointPos -= count;
+                       }
+                       public override string ToString()
+                       {
+                               StringBuilder sb = new StringBuilder ();
+                               sb.Append (GetIntegerString (IntegerDigits));
+                               if (HasDecimal) {
+                                       sb.Append (".");
+                                       sb.Append (GetDecimalString (DecimalDigits));
+                               }
+                               return sb.ToString ();
+                       }
+                       public virtual char GetChar (int pos)
+                       {
+                               if (_decPointPos <= 0)
+                                       pos += _decPointPos - 1;
+                               
+                               if (pos < 0 || pos >= _digits.Length)
+                                       return '0';
+                               else
+                                       return (char)('0' + _digits [pos]);
+                       }
+                       public virtual NumberStore GetClone ()
+                       {
+                               NumberStore ns = new NumberStore ();
+
+                               ns._decPointPos = this._decPointPos;
+                               ns._defMaxPrecision = this._defMaxPrecision;
+                               ns._defPrecision = this._defPrecision;
+                               ns._digits = (byte[])this._digits.Clone ();
+                               ns._infinity = this._infinity;
+                               ns._NaN = this._NaN;
+                               ns._positive = this._positive;
+
+                               return ns;
+                       }
+                       #endregion
+
+                       #region Public Static Method
+                       public static bool IsZeroOnly (StringBuilder sb)
+                       {
+                               for (int i = 0; i < sb.Length; i++)
+                                       if (char.IsDigit (sb [i]) && sb [i] != '0')
+                                               return false;
+                               return true;
+                       }
+                       #endregion
+               }
+
+               internal class IntegerStore : NumberStore
+               {
+                       public IntegerStore (long value)
+                       {
+                               _positive = value >= 0;
+                               ulong v = (ulong)(_positive ? value : -value);
+
+                               byte[] temp = new byte [30];
+                               int i = temp.Length - 1;
+
+                               while (v > 0) {
+                                       temp [i--] = (byte)(v % 10);
+                                       v /= 10;
+                               }
+
+                               if (temp.Length - i - 1 > 0) {
+                                       _digits = new byte [temp.Length - i - 1];
+                                       Array.Copy (temp, i + 1, _digits, 0, _digits.Length);
+                               } else {
+                                       _digits = new byte [1];
+                               }
+
+                               _defByteSize = 8;
+                               _defMaxPrecision = _defPrecision = 19;
+                               _decPointPos = _digits.Length;
+                       }
+                       public IntegerStore (int value) : this ((long)value)
+                       {
+                               _defByteSize = 4;
+                               _defMaxPrecision = _defPrecision = 10;
+                       }
+                       public IntegerStore (short value) : this ((long)value)
+                       {
+                               _defByteSize = 2;
+                               _defMaxPrecision = _defPrecision = 5;
+                       }
+                       public IntegerStore (sbyte value) : this ((long)value)
+                       {
+                               _defByteSize = 1;
+                               _defMaxPrecision = _defPrecision = 3;
+                       }
+
+                       public IntegerStore (ulong value)
+                       {
+                               _positive = true;
+
+                               byte[] temp = new byte [30];
+                               int i = temp.Length - 1;
+
+                               while (value > 0) {
+                                       temp [i--] = (byte)(value % 10);
+                                       value /= 10;
+                               }
+
+                               if (temp.Length - i - 1 > 0) {
+                                       _digits = new byte [temp.Length - i - 1];
+                                       Array.Copy (temp, i + 1, _digits, 0, _digits.Length);
+                               } else {
+                                       _digits = new byte [1];
+                               }
+
+                               _defByteSize = 8;
+                               _defMaxPrecision = _defPrecision = 20;
+                               _decPointPos = _digits.Length;
+                       }
+                       public IntegerStore (uint value) : this ((ulong)value)
+                       {
+                               _defByteSize = 4;
+                               _defMaxPrecision = _defPrecision = 10;
+                       }
+                       public IntegerStore (ushort value) : this ((ulong)value)
+                       {
+                               _defByteSize = 2;
+                               _defMaxPrecision = _defPrecision = 5;
+                       }
+                       public IntegerStore (byte value) : this ((ulong)value)
+                       {
+                               _defByteSize = 1;
+                               _defMaxPrecision = _defPrecision = 3;
+                       }
+               }
+               internal class DoubleStore : NumberStore
+               {
+                       public DoubleStore(double value)
+                       {
+                               _defPrecision = 15;
+                               _defMaxPrecision = _defPrecision + 2;
+
+                               if (double.IsNaN (value) || double.IsInfinity (value)) {
+                                       _NaN = double.IsNaN (value);
+                                       _infinity = double.IsInfinity (value);
+                                       _positive = value > 0;
+                                       return;
+                               }
+
+                               long bits = BitConverter.DoubleToInt64Bits (value);
+                               _positive = (bits >= 0);
+                               int e = (int) ((bits >> 52) & 0x7ffL);
+                               long m = bits & 0xfffffffffffffL;
+
+                               if (e == 0 && m == 0) {
+                                       _decPointPos = 1;
+                                       _digits = new byte []{0};
+                                       _positive = true;
+                                       return;
+                               }
+
+                               bool flag = true;
+                               if (e == 0) {
+                                       flag = false;
+                                       e ++;
+                               } else if (e != 0) {
+                                       m |= (1L << 52);
+                               }
+
+                               e -= 1075;
+
+                               int nsize = 0;
+                               while ((m & 1) == 0) {
+                                       m >>= 1;
+                                       e ++;
+                                       nsize ++;
+                               }
+
+                               long mt = m;
+                               int length = 1;
+                               byte[] temp = new byte [56];
+                               for (int i = temp.Length - 1; i >= 0; i--, length++) {
+                                       temp [i] = (byte)(mt % 10);
+                                       mt /= 10;
+                                       if (mt == 0)
+                                               break;
+                               }
+
+                               _decPointPos = temp.Length - 1;
+
+                               if (e >= 0) {
+                                       for (int i = 0; i < e; i++) {
+                                               if (MultiplyBy (ref temp, ref length, 2)) {
+                                                       _decPointPos ++;
+                                               }
+                                       }
+                               } else {
+                                       for (int i = 0; i < -e; i++) {
+                                               if (MultiplyBy (ref temp, ref length, 5)) {
+                                                       _decPointPos ++;
+                                               }
+                                       }
+                                       _decPointPos += e;
+                               }
+
+                               int ulvc = 1;
+                               ulong ulv = 0;
+                               for (int i = 0; i < temp.Length; i++)
+                                       if (temp [i] != 0) {
+                                               _decPointPos -= i - 1;
+                                               _digits = new byte [temp.Length - i];
+                                               for (int q = i; q < temp.Length; q++) {
+                                                       _digits [q - i] = temp [q];
+                                                       if (ulvc < 20) {
+                                                               ulv = ulv * 10 + temp [q];
+                                                               ulvc ++;
+                                                       }
+                                               }
+                                               break;
+                                       }
+
+                               RoundEffectiveDigits (17, true, true);
+                       }
+
+                       internal bool MultiplyBy (ref byte[] buffer,ref int length, int amount)
+                       {
+                               int mod = 0;
+                               int ret;
+                               int start = buffer.Length - length - 1;
+                               if (start < 0) start = 0;
+
+                               for (int i = buffer.Length - 1; i > start; i--) {
+                                       ret = buffer [i] * amount + mod;
+                                       mod = ret / 10;
+                                       buffer [i] = (byte)(ret % 10);
+                               }
+
+                               if (mod != 0) {
+                                       length = buffer.Length - start;
+
+                                       if (start == 0) {
+                                               buffer [0] = (byte)mod;
+                                               Array.Copy (buffer, 0, buffer, 1, buffer.Length - 1);
+                                               buffer [0] = 0;
+                                               return true;
+                                       }
+                                       else {
+                                               buffer [start] = (byte)mod;
+                                       }
+                               }
+
+                               return false;
+                       }
+               }
+
+               internal class SingleStore : NumberStore
+               {
+                       public SingleStore(float value)
+                       {
+                               _defPrecision = 7;
+                               _defMaxPrecision = _defPrecision + 2;
+
+                               if (float.IsNaN (value) || float.IsInfinity (value))
+                                       throw new ArgumentException ();
+
+                               long bits = BitConverter.DoubleToInt64Bits (value);
+                               _positive = (bits >= 0);
+                               int e = (int) ((bits >> 52) & 0x7ffL);
+                               long m = bits & 0xfffffffffffffL;
+
+                               if (e == 0 && m == 0) {
+                                       _decPointPos = 1;
+                                       _digits = new byte []{0};
+                                       _positive = true;
+                                       return;
+                               }
+
+                               if (e == 0) {
+                                       e ++;
+                               } else if (e != 0) {
+                                       m |= (1L << 52);
+                               }
+
+                               e -= 1075;
+
+                               int nsize = 0;
+                               while ((m & 1) == 0) {
+                                       m >>= 1;
+                                       e ++;
+                                       nsize ++;
+                               }
+
+                               long mt = m;
+                               int length = 1;
+                               byte[] temp = new byte [26];
+                               for (int i = temp.Length - 1; i >= 0; i--, length++) {
+                                       temp [i] = (byte)(mt % 10);
+                                       mt /= 10;
+                                       if (mt == 0)
+                                               break;
+                               }
+
+                               _decPointPos = temp.Length - 1;
+
+                               if (e >= 0) {
+                                       for (int i = 0; i < e; i++) {
+                                               if (MultiplyBy (ref temp, ref length, 2)) {
+                                                       _decPointPos ++;
+                                               }
+                                       }
+                               } else {
+                                       for (int i = 0; i < -e; i++) {
+                                               if (MultiplyBy (ref temp, ref length, 5)) {
+                                                       _decPointPos ++;
+                                               }
+                                       }
+                                       _decPointPos += e;
+                               }
+
+                               int ulvc = 1;
+                               ulong ulv = 0;
+                               for (int i = 0; i < temp.Length; i++)
+                                       if (temp [i] != 0) {
+                                               _decPointPos -= i - 1;
+                                               _digits = new byte [temp.Length - i];
+                                               for (int q = i; q < temp.Length; q++) {
+                                                       _digits [q - i] = temp [q];
+                                                       if (ulvc < 20) {
+                                                               ulv = ulv * 10 + temp [q];
+                                                               ulvc ++;
+                                                       }
+                                               }
+                                               break;
+                                       }
+
+                               RoundEffectiveDigits (9, true, true);
+                       }
+                       internal bool MultiplyBy (ref byte[] buffer,ref int length, int amount)
+                       {
+                               int mod = 0;
+                               int ret;
+                               int start = buffer.Length - length - 1;
+                               if (start < 0) start = 0;
+
+                               for (int i = buffer.Length - 1; i > start; i--) {
+                                       ret = buffer [i] * amount + mod;
+                                       mod = ret / 10;
+                                       buffer [i] = (byte)(ret % 10);
+                               }
+
+                               if (mod != 0) {
+                                       length = buffer.Length - start;
+
+                                       if (start == 0) {
+                                               buffer [0] = (byte)mod;
+                                               Array.Copy (buffer, 0, buffer, 1, buffer.Length - 1);
+                                               buffer [0] = 0;
+                                               return true;
+                                       }
+                                       else {
+                                               buffer [start] = (byte)mod;
+                                       }
+                               }
+
+                               return false;
+                       }
+               }
+
+               #endregion
+       }
+
+       #region Wrapper
+       class IntegerFormatter
+       {
+               #region NumberToString
+               public static string NumberToString (string format, NumberFormatInfo nfi, short value)
+               {
+                       return NumberFormatter.NumberToString (format, value, nfi);
+               }
+
+               public static string NumberToString (string format, NumberFormatInfo nfi, int value)
+               {
+                       return NumberFormatter.NumberToString (format, value, nfi);
+               }
+
+               public static string NumberToString (string format, NumberFormatInfo nfi, long value)
+               {
+                       return NumberFormatter.NumberToString (format, value, nfi);
+               }
+
+               public static string NumberToString (string format, NumberFormatInfo nfi, sbyte value)
+               {
+                       return NumberFormatter.NumberToString (format, value, nfi);
+               }
+
+               public static string NumberToString (string format, NumberFormatInfo nfi, byte value)
+               {
+                       return NumberFormatter.NumberToString (format, value, nfi);
+               }               
+
+               public static string NumberToString (string format, NumberFormatInfo nfi, ushort value)
+               {
+                       return NumberFormatter.NumberToString (format, value, nfi);
+               }
+
+               public static string NumberToString (string format, NumberFormatInfo nfi, uint value)
+               {
+                       return NumberFormatter.NumberToString (format, value, nfi);
+               }
+
+               public static string NumberToString (string format, NumberFormatInfo nfi, ulong value)
+               {
+                       return NumberFormatter.NumberToString (format, value, nfi);
+               }
+               #endregion
+
+               #region Wrapper
+               internal static string FormatDecimal (long value, int precision, int maxLength)
+               {
+                       return NumberFormatter.FormatDecimal (NumberFormatter.NumberStore.CreateInstance (value), precision, System.Globalization.CultureInfo.CurrentCulture.NumberFormat);
+               }
+               internal static string FormatGeneral (long value, int precision, NumberFormatInfo nfi, bool upper) 
+               {
+                       return NumberFormatter.FormatGeneral (NumberFormatter.NumberStore.CreateInstance (value), precision, System.Globalization.CultureInfo.CurrentCulture.NumberFormat, upper);
+               }
+               
+               internal static string FormatGeneral (long value, int precision, NumberFormatInfo nfi, bool upper, int maxLength) 
+               {
+                       return NumberFormatter.FormatGeneral (NumberFormatter.NumberStore.CreateInstance (value), precision, System.Globalization.CultureInfo.CurrentCulture.NumberFormat, upper);
+               }
+               #endregion
+       }
+
+       class FloatingPointFormatter
+       {
+               public FloatingPointFormatter (double p, double p10, int dec_len, int dec_len_min, double p2, double p102, int dec_len2, int dec_len_min2)
+               {
+
+               }
+
+               public string GetStringFrom (string format, NumberFormatInfo nfi, float value)
+               {
+                       if (nfi == null) nfi = CultureInfo.CurrentCulture.NumberFormat;
+                       return NumberFormatter.NumberToString (format, value, nfi);
+               }
+
+               public string GetStringFrom (string format, NumberFormatInfo nfi, double value)
+               {
+                       if (nfi == null) nfi = CultureInfo.CurrentCulture.NumberFormat;
+                       return NumberFormatter.NumberToString (format, value, nfi);
+               }
+       }
+       #endregion
+}
\ No newline at end of file
index f49214a8dc576a1e2d36e517b14e500c5f4e048d..a2e071d1ad6f19eeab72cdc0a432e6ec583674a6 100644 (file)
@@ -45,7 +45,7 @@ namespace System {
                const int dec_len2 = 7;
                const int dec_len_min2 = -16;
 
-               public static string NumberToString (string format, NumberFormatInfo nfi, double value)
+               public static string NumberToString (string format, NumberFormatInfo nfi, float value)
                {
                        if (fpf == null) {
                                fpf = new FloatingPointFormatter (p, p10, dec_len, dec_len_min, p2, p102, dec_len2, dec_len_min2);
index cc3f607923948a14f282b5ea28a92d9e02e3b188..ca5954f085ee044121a921f0798d10fce153bf3f 100755 (executable)
@@ -113,7 +113,6 @@ System/Exception.cs
 System/ExecutionEngineException.cs
 System/FieldAccessException.cs
 System/FlagsAttribute.cs
-System/FloatingPointFormatter.cs
 System/FormatException.cs
 System/GC.cs
 System/GenericParameterAttributes.cs
@@ -134,7 +133,6 @@ System/IndexOutOfRangeException.cs
 System/Int16.cs
 System/Int32.cs
 System/Int64.cs
-System/IntegerFormatter.cs
 System/IntPtr.cs
 System/InvalidCastException.cs
 System/InvalidOperationException.cs
@@ -162,6 +160,7 @@ System/NotImplementedException.cs
 System/NotSupportedException.cs
 System/Nullable.cs
 System/NullReferenceException.cs
+System/NumberFormatter.cs
 System/Object.cs
 System/ObjectDisposedException.cs
 System/ObsoleteAttribute.cs