2005-03-13 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / class / corlib / System / NumberFormatter.cs
1 //
2 // System.NumberFormatter.cs
3 //
4 // Author:
5 //   Kazuki Oikawa (kazuki@panicode.com)
6 //
7
8 using System.Collections;
9 using System.Globalization;
10 using System.Text;
11
12 namespace System
13 {
14         class NumberFormatter
15         {
16                 static char[] digitLowerTable = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
17                 static char[] digitUpperTable = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
18
19                 #region NumberToString
20                 public static string NumberToString (string format, sbyte value, NumberFormatInfo nfi)
21                 {
22                         return NumberToString (format, new NumberStore (value), nfi);
23                 }
24                 public static string NumberToString (string format, byte value, NumberFormatInfo nfi)
25                 {
26                         return NumberToString (format, new NumberStore (value), nfi);
27                 }
28                 public static string NumberToString (string format, ushort value, NumberFormatInfo nfi)
29                 {
30                         return NumberToString (format, new NumberStore (value), nfi);
31                 }
32                 public static string NumberToString (string format, short value, NumberFormatInfo nfi)
33                 {
34                         return NumberToString (format, new NumberStore (value), nfi);
35                 }
36                 public static string NumberToString (string format, uint value, NumberFormatInfo nfi)
37                 {
38                         return NumberToString (format, new NumberStore (value), nfi);
39                 }
40                 public static string NumberToString (string format, int value, NumberFormatInfo nfi)
41                 {
42                         return NumberToString (format, new NumberStore (value), nfi);
43                 }
44                 public static string NumberToString (string format, ulong value, NumberFormatInfo nfi)
45                 {
46                         return NumberToString (format, new NumberStore (value), nfi);
47                 }
48                 public static string NumberToString (string format, long value, NumberFormatInfo nfi)
49                 {
50                         return NumberToString (format, new NumberStore (value), nfi);
51                 }
52                 public static string NumberToString (string format, float value, NumberFormatInfo nfi)
53                 {
54                         return NumberToString (format, new NumberStore (value), nfi);
55                 }
56                 public static string NumberToString (string format, double value, NumberFormatInfo nfi)
57                 {
58                         return NumberToString (format, new NumberStore (value), nfi);
59                 }
60                 public static string NumberToString (string format, NumberStore ns, NumberFormatInfo nfi)
61                 {
62                         if (ns.IsNaN) {
63                                 return nfi.NaNSymbol;
64                         }
65                         if (ns.IsInfinity) {
66                                 if (ns.Positive)
67                                         return nfi.PositiveInfinitySymbol;
68                                 else
69                                         return nfi.NegativeInfinitySymbol;
70                         }
71
72                         char specifier;
73                         int precision;
74                         bool custom;
75
76                         if (format == null || format.Length == 0)
77                                 format = "G";
78
79                         if (nfi == null)
80                                 nfi = NumberFormatInfo.GetInstance (null);
81                         
82                         if (!ParseBasicFormat (format, out specifier, out precision, out custom))
83                                 throw new FormatException (Locale.GetText ("The specified format '" + format + "' is invalid"));
84                         
85                         if (custom){
86                                 if (ns.IsFloatingSource)
87                                         ns.RoundEffectiveDigits (ns.DefaultPrecision);
88                                 return FormatCustom (format, ns, nfi);
89                         }
90
91                         if (ns.IsFloatingSource) {
92                                 switch(specifier) {
93                                 case 'p':
94                                 case 'P':
95                                 case 'c':
96                                 case 'C':
97                                 case 'f':
98                                 case 'F':
99                                 case 'N':
100                                 case 'n':
101                                         ns.RoundEffectiveDigits (ns.DefaultPrecision);
102                                         break;
103                                 case 'g':
104                                 case 'G':
105                                         if (precision <= 0)
106                                                 ns.RoundEffectiveDigits (ns.DefaultPrecision);
107                                         else
108                                                 ns.RoundEffectiveDigits (precision);
109                                         break;
110                                 case 'r':
111                                 case 'R':
112                                         ns.RoundEffectiveDigits (ns.DefaultMaxPrecision);
113                                         break;
114                                 default:
115                                         if (precision > ns.DefaultPrecision)
116                                                 ns.RoundEffectiveDigits (precision + 1);
117                                         else
118                                                 ns.RoundEffectiveDigits (ns.DefaultPrecision + 1);
119                                         break;
120                                 }
121                         }
122
123                         switch(specifier) {
124                         case 'c':
125                         case 'C':
126                                 return FormatCurrency (ns, precision, nfi);
127                         case 'd':
128                         case 'D':
129                                 return FormatDecimal (ns, precision, nfi);
130                         case 'e':
131                         case 'E':
132                                 return FormatExponential (ns, precision, nfi, specifier == 'E');
133                         case 'f': 
134                         case 'F':
135                                 return FormatFixedPoint (ns, precision, nfi);
136                         case 'g':
137                         case 'G':
138                                 return FormatGeneral (ns, precision, nfi, specifier == 'G');
139                         case 'n':
140                         case 'N':
141                                 return FormatNumber (ns, precision, nfi);
142                         case 'p':
143                         case 'P':
144                                 return FormatPercent (ns, precision, nfi);
145                         case 'r':
146                         case 'R':
147                                 if (ns.IsFloatingSource) {
148                                         return FormatGeneral (ns, ns.DefaultMaxPrecision, nfi, true);
149                                 } else {
150                                         throw new FormatException (Locale.GetText ("The specified format cannot be used in this instance"));
151                                 }
152                         case 'x': 
153                         case 'X': return FormatHexadecimal (ns, precision, nfi, specifier == 'X');
154                         default: 
155                                 throw new FormatException (Locale.GetText ("The specified format '" + format + "' is invalid"));
156                         }       
157                 }
158                 #endregion
159
160                 #region BasicParser
161                 private static bool ParseBasicFormat (string format, out char specifier, out int precision, out bool custom)
162                 {                                
163                         precision = -1;
164                         specifier = '\0';
165                         custom = false;
166                         
167                         if (format.Length < 1)
168                                 return false;
169                         
170                         specifier = format [0];
171
172                         if (Char.IsLetter (specifier)) {
173                                 if (format.Length == 1)
174                                         return true;
175
176                                 bool flag = true;
177                                 precision = 0;
178                                 for (int i = 1; i < format.Length; i++) {
179                                         char c = format [i];
180                                         if (char.IsDigit (c)) {
181                                                 precision = precision * 10 + (c - '0');
182                                                 if (precision > 99) {
183                                                         flag = false;
184                                                         break;
185                                                 }
186                                         }
187                                         else {
188                                                 flag = false;
189                                                 break;
190                                         }
191                                 }
192                                 if (flag)
193                                         return true;
194                         }
195
196                         custom = true;
197                         return true;
198                 }       
199
200                 #endregion
201
202                 #region Helpers
203                 private static void ZeroTrimEnd (StringBuilder sb)
204                 {
205                         ZeroTrimEnd (sb, false);
206                 }
207                 private static void ZeroTrimEnd (StringBuilder sb, bool canEmpty)
208                 {
209                         int len = 0;
210                         for (int i = sb.Length - 1; (canEmpty ? i >= 0 : i > 0); i --) {
211                                 if (sb [i] != '0')
212                                         break;
213                                 len ++;
214                         }
215
216                         if (len > 0)
217                                 sb.Remove (sb.Length - len, len);
218                 }
219                 #endregion
220
221                 #region Basic
222                 internal static string FormatCurrency (NumberStore ns, int precision, NumberFormatInfo nfi)
223                 {
224                         precision = (precision >= 0 ? precision : nfi.CurrencyDecimalDigits);
225                         ns.RoundDecimal (precision);
226                         StringBuilder sb = new StringBuilder (ns.IntegerDigits * 2 + precision * 2 + 16);
227                         bool needNegativeSign = !ns.Positive && !ns.ZeroOnly;
228
229                         if (!needNegativeSign) {
230                                 switch (nfi.CurrencyPositivePattern) {
231                                 case 0:
232                                         sb.Append (nfi.CurrencySymbol);
233                                         break;
234                                 case 2:
235                                         sb.Append (nfi.CurrencySymbol);
236                                         sb.Append (' ');
237                                         break;
238                                 }
239                         } else {
240                                 switch (nfi.CurrencyNegativePattern) {
241                                 case 0:
242                                         sb.Append ('(');
243                                         sb.Append (nfi.CurrencySymbol);
244                                         break;
245                                 case 1:
246                                         sb.Append (nfi.NegativeSign);
247                                         sb.Append (nfi.CurrencySymbol);
248                                         break;
249                                 case 2:
250                                         sb.Append (nfi.CurrencySymbol);
251                                         sb.Append (nfi.NegativeSign);
252                                         break;
253                                 case 3:
254                                         sb.Append (nfi.CurrencySymbol);
255                                         break;
256                                 case 4:
257                                         sb.Append ('(');
258                                         break;
259                                 case 5:
260                                         sb.Append (nfi.NegativeSign);
261                                         break;
262                                 case 8:
263                                         sb.Append (nfi.NegativeSign);
264                                         break;
265                                 case 9:
266                                         sb.Append (nfi.NegativeSign);
267                                         sb.Append (nfi.CurrencySymbol);
268                                         sb.Append (' ');                                        
269                                         break;
270                                 case 11:
271                                         sb.Append (nfi.CurrencySymbol);
272                                         sb.Append (' ');
273                                         break;
274                                 case 12:
275                                         sb.Append (nfi.CurrencySymbol);
276                                         sb.Append (' ');
277                                         sb.Append (nfi.NegativeSign);                                   
278                                         break;
279                                 case 14:
280                                         sb.Append ('(');
281                                         sb.Append (nfi.CurrencySymbol);
282                                         sb.Append (' ');
283                                         break;
284                                 case 15:
285                                         sb.Append ('(');
286                                         break;
287                                 }
288                         }
289
290                         ns.AppendIntegerStringWithGroupSeparator (sb, nfi.CurrencyGroupSizes, nfi.CurrencyGroupSeparator);
291
292                         if (precision > 0)
293                         {
294                                 sb.Append (nfi.CurrencyDecimalSeparator);
295                                 ns.AppendDecimalString (precision, sb);
296                         }
297
298                         if (!needNegativeSign) {
299                                 switch (nfi.CurrencyPositivePattern) {
300                                 case 1:
301                                         sb.Append (nfi.CurrencySymbol);
302                                         break;
303                                 case 3:
304                                         sb.Append (' ');
305                                         sb.Append (nfi.CurrencySymbol);
306                                         break;
307                                 }
308                         } else {
309                                 switch (nfi.CurrencyNegativePattern) {
310                                 case 0:
311                                         sb.Append (')');
312                                         break;
313                                 case 3:
314                                         sb.Append (nfi.NegativeSign);
315                                         break;
316                                 case 4:
317                                         sb.Append (nfi.CurrencySymbol);
318                                         sb.Append (')');
319                                         break;
320                                 case 5:
321                                         sb.Append (nfi.CurrencySymbol);
322                                         break;
323                                 case 6:
324                                         sb.Append (nfi.NegativeSign);
325                                         sb.Append (nfi.CurrencySymbol);
326                                         break;
327                                 case 7:
328                                         sb.Append (nfi.CurrencySymbol);
329                                         sb.Append (nfi.NegativeSign);
330                                         break;
331                                 case 8:
332                                         sb.Append (' ');
333                                         sb.Append (nfi.CurrencySymbol);
334                                         break;
335                                 case 10:
336                                         sb.Append (' ');
337                                         sb.Append (nfi.CurrencySymbol);
338                                         sb.Append (nfi.NegativeSign);
339                                         break;
340                                 case 11:
341                                         sb.Append (nfi.NegativeSign);
342                                         break;
343                                 case 13:
344                                         sb.Append (nfi.NegativeSign);
345                                         sb.Append (' ');
346                                         sb.Append (nfi.CurrencySymbol);
347                                         break;
348                                 case 14:
349                                         sb.Append (')');
350                                         break;
351                                 case 15:
352                                         sb.Append (' ');
353                                         sb.Append (nfi.CurrencySymbol);
354                                         sb.Append (')');
355                                         break;
356                                 }
357                         }
358
359                         return sb.ToString ();
360                 }
361                 internal static string FormatDecimal (NumberStore ns, int precision, NumberFormatInfo nfi)
362                 {
363                         if (ns.IsFloatingSource)
364                                 throw new FormatException ();
365
366                         precision = precision > 0 ? precision : 1;
367                         precision = ns.IntegerDigits > precision ? ns.IntegerDigits : precision;
368
369                         StringBuilder sb = new StringBuilder (precision + nfi.NegativeSign.Length);
370
371                         if (!ns.Positive && !ns.CheckZeroOnlyInteger ()) {
372                                 sb.Append (nfi.NegativeSign);
373                         }
374
375                         ns.AppendIntegerString (precision, sb);
376
377                         return sb.ToString ();
378                 }
379                 internal static string FormatFixedPoint (NumberStore ns, int precision, NumberFormatInfo nfi)
380                 {
381                         precision = precision >= 0 ? precision : nfi.NumberDecimalDigits;
382                         ns.RoundDecimal (precision);
383
384                         StringBuilder cb = new StringBuilder (ns.IntegerDigits + precision + nfi.NumberDecimalSeparator.Length);
385
386                         if (!ns.Positive && !ns.ZeroOnly)
387                                 cb.Append (nfi.NegativeSign);
388
389                         ns.AppendIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1, cb);
390
391                         if (precision > 0) {
392                                 cb.Append (nfi.NumberDecimalSeparator);
393                                 ns.AppendDecimalString (precision, cb);
394                         }
395
396                         return cb.ToString ();
397                 }
398
399                 internal static string FormatGeneral (NumberStore ns)
400                 {
401                         return FormatGeneral (ns, -1, NumberFormatInfo.CurrentInfo, true);
402                 }
403                 internal static string FormatGeneral (NumberStore ns, IFormatProvider provider)
404                 {
405                         return FormatGeneral (ns, -1, NumberFormatInfo.GetInstance (provider), true);
406                 }
407                 internal static string FormatGeneral (NumberStore ns, int precision, NumberFormatInfo nfi, bool upper)
408                 {
409                         if (ns.ZeroOnly)
410                                 return "0";
411
412                         precision = precision > 0 ? precision : ns.DefaultPrecision;
413
414                         int exponent = 0;
415                         bool expMode = (ns.IntegerDigits > precision || ns.DecimalPointPosition <= -4);
416                         if (expMode) {
417                                 while (!(ns.DecimalPointPosition == 1 && ns.GetChar (0) != '0')) {
418                                         if (ns.DecimalPointPosition > 1) {
419                                                 ns.Divide10 (1);
420                                                 exponent ++;
421                                         } else {
422                                                 ns.Multiply10 (1);
423                                                 exponent --;
424                                         }
425                                 }
426                         }
427
428                         precision = precision < ns.DefaultPrecision + 2 ? (precision < 17 ? precision : 17) : ns.DefaultPrecision + 2;
429                         StringBuilder cb = new StringBuilder (ns.IntegerDigits + precision + 16);
430                         if (expMode) {
431                                 if (ns.RoundDecimal (precision - 1)) {
432                                         ns.Divide10 (1);
433                                         exponent ++;
434                                 }
435                         } else {
436                                 ns.RoundDecimal (precision);
437                         }
438
439                         if (!ns.Positive) {
440                                 cb.Append (nfi.NegativeSign);
441                         }
442
443                         ns.AppendIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1, cb);
444
445                         if (ns.DecimalDigits > 0) {
446                                 cb.Append (nfi.NumberDecimalSeparator);
447                                 ns.AppendDecimalString (ns.DecimalDigits, cb);
448                         }
449
450                         if (expMode) {
451                                 if (upper)
452                                         cb.Append ('E');
453                                 else
454                                         cb.Append ('e');
455
456                                 if (exponent >= 0)
457                                         cb.Append (nfi.PositiveSign);
458                                 else {
459                                         cb.Append (nfi.NegativeSign);
460                                         exponent = -exponent;
461                                 }
462
463                                 if (exponent == 0) {
464                                         cb.Append ('0', 2);
465                                 } else if (exponent < 10) {
466                                         cb.Append ('0');
467                                         cb.Append (digitLowerTable [exponent]);
468                                 } else if (exponent < 100) {
469                                         cb.Append (digitLowerTable [exponent / 10 % 10]);
470                                         cb.Append (digitLowerTable [exponent % 10]);
471                                 } else if (exponent < 1000) {
472                                         cb.Append (digitLowerTable [exponent / 100 % 10]);
473                                         cb.Append (digitLowerTable [exponent / 10 % 10]);
474                                         cb.Append (digitLowerTable [exponent % 10]);
475                                 }
476                         }
477
478                         return cb.ToString ();
479                 }
480                 internal static string FormatNumber (NumberStore ns, int precision, NumberFormatInfo nfi)
481                 {
482                         precision = (precision >= 0 ? precision : nfi.NumberDecimalDigits);
483                         StringBuilder sb = new StringBuilder(ns.IntegerDigits * 3 + precision);
484
485                         ns.RoundDecimal (precision);
486                         bool needNegativeSign = (!ns.Positive && !ns.ZeroOnly);
487
488                         if (needNegativeSign) {
489                                 switch (nfi.NumberNegativePattern) {
490                                 case 0:
491                                         sb.Append ('(');
492                                         break;
493                                 case 1:
494                                         sb.Append (nfi.NegativeSign);
495                                         break;
496                                 case 2:
497                                         sb.Append (nfi.NegativeSign);
498                                         sb.Append (' ');
499                                         break;
500                                 }
501                         }
502
503                         ns.AppendIntegerStringWithGroupSeparator (sb, nfi.NumberGroupSizes, nfi.NumberGroupSeparator);
504
505                         if (precision > 0) {
506                                 sb.Append (nfi.NumberDecimalSeparator);
507                                 ns.AppendDecimalString (precision, sb);
508                         }
509
510                         if (needNegativeSign) {
511                                 switch (nfi.NumberNegativePattern) {
512                                 case 0:
513                                         sb.Append (')');
514                                         break;
515                                 case 3:
516                                         sb.Append (nfi.NegativeSign);
517                                         break;
518                                 case 4:
519                                         sb.Append (' ');
520                                         sb.Append (nfi.NegativeSign);
521                                         break;
522                                 }
523                         }
524
525                         return sb.ToString ();
526                 }
527                 internal static string FormatPercent (NumberStore ns, int precision, NumberFormatInfo nfi)
528                 {
529                         precision = (precision >= 0 ? precision : nfi.PercentDecimalDigits);
530                         ns.Multiply10 (2);
531                         ns.RoundDecimal (precision);
532                         bool needNegativeSign = (!ns.Positive && !ns.ZeroOnly);
533
534                         StringBuilder sb = new StringBuilder(ns.IntegerDigits * 2 + precision + 16);
535
536                         if (!needNegativeSign) {
537                                 if (nfi.PercentPositivePattern == 2) {
538                                         sb.Append (nfi.PercentSymbol);
539                                 }
540                         } else {
541                                 switch (nfi.PercentNegativePattern) {
542                                 case 0:
543                                         sb.Append (nfi.NegativeSign);
544                                         break;
545                                 case 1:
546                                         sb.Append (nfi.NegativeSign);
547                                         break;
548                                 case 2:
549                                         sb.Append (nfi.NegativeSign);
550                                         sb.Append (nfi.PercentSymbol);
551                                         break;
552                                 }
553                         }
554
555                         ns.AppendIntegerStringWithGroupSeparator (sb, nfi.PercentGroupSizes, nfi.PercentGroupSeparator);
556                         
557                         if (precision > 0) {
558                                 sb.Append (nfi.PercentDecimalSeparator);
559                                 ns.AppendDecimalString (precision, sb);
560                         }
561
562                         if (!needNegativeSign) {
563                                 switch (nfi.PercentPositivePattern) {
564                                 case 0:
565                                         sb.Append (' ');
566                                         sb.Append (nfi.PercentSymbol);
567                                         break;
568                                 case 1:
569                                         sb.Append (nfi.PercentSymbol);
570                                         break;
571                                 }
572                         } else {
573                                 switch (nfi.PercentNegativePattern) {
574                                 case 0:
575                                         sb.Append (' ');
576                                         sb.Append (nfi.PercentSymbol);
577                                         break;
578                                 case 1:
579                                         sb.Append (nfi.PercentSymbol);
580                                         break;
581                                 }
582                         }
583
584                         return sb.ToString ();
585                 }
586                 internal static string FormatHexadecimal (NumberStore ns, int precision, NumberFormatInfo nfi, bool upper)
587                 {
588                         if (ns.IsFloatingSource)
589                                 throw new FormatException ();
590
591                         int intSize = ns.DefaultByteSize;
592                         ulong value = 0;
593                         for (int i = 0; i < ns.IntegerDigits; i++) {
594                                 value *= 10;
595                                 value += ns.GetDigitByte (i);
596                         }
597
598                         if (!ns.Positive) {
599                                 value = (ulong)(Math.Pow (2, intSize * 8)) - value;
600                         }
601
602                         char[] digits = (upper ? digitUpperTable : digitLowerTable);
603                         CharBuffer sb = new CharBuffer (16 + precision + 1);
604
605                         while (value > 0) {
606                                 sb.InsertToFront (digits [value % 16]);
607                                 value >>= 4;
608                         }
609
610                         if (sb.Length == 0)
611                                 sb.InsertToFront ('0');
612
613                         if (sb.Length < precision)
614                                 sb.InsertToFront ('0', precision - sb.Length);
615
616                         return sb.ToString ();
617                 }
618                 internal static string FormatExponential (NumberStore ns, int precision, NumberFormatInfo nfi, bool upper)
619                 {
620                         if (precision < 0)
621                                 precision = 6;
622
623                         if (ns.ZeroOnly) {
624                                 StringBuilder sb = new StringBuilder (precision + nfi.PositiveSign.Length + 6);
625                                 sb.Append ('0');
626                                 if (precision > 0) {
627                                         sb.Append ('.');
628                                         sb.Append ('0', precision);
629                                 }
630
631                                 if (upper)
632                                         sb.Append ('E');
633                                 else
634                                         sb.Append ('e');
635
636                                 sb.Append (nfi.PositiveSign);
637                                 sb.Append ('0', 3);
638                                 
639                                 return sb.ToString ();
640                         }
641
642                         int exponent = 0;
643                         while (!(ns.DecimalPointPosition == 1 && ns.GetChar (0) != '0')) {
644                                 if (ns.DecimalPointPosition > 1) {
645                                         ns.Divide10 (1);
646                                         exponent ++;
647                                 } else {
648                                         ns.Multiply10 (1);
649                                         exponent --;
650                                 }
651                         }
652
653                         if (ns.RoundDecimal (precision)) {
654                                 ns.Divide10 (1);
655                                 exponent ++;
656                         }
657
658                         StringBuilder cb = new StringBuilder (ns.DecimalDigits + 1 + 8);
659
660                         if (!ns.Positive) {
661                                 cb.Append (nfi.NegativeSign);
662                         }
663
664                         ns.AppendIntegerString (ns.IntegerDigits > 0 ? ns.IntegerDigits : 1, cb);
665
666                         if (precision > 0) {
667                                 cb.Append (nfi.NumberDecimalSeparator);
668                                 ns.AppendDecimalString (precision, cb);
669                         }
670
671                         if (upper)
672                                 cb.Append ('E');
673                         else
674                                 cb.Append ('e');
675
676                         if (exponent >= 0)
677                                 cb.Append (nfi.PositiveSign);
678                         else {
679                                 cb.Append (nfi.NegativeSign);
680                                 exponent = -exponent;
681                         }
682
683                         if (exponent == 0) {
684                                 cb.Append ('0', 3);
685                         } else if (exponent < 10) {
686                                 cb.Append ('0', 2);
687                                 cb.Append (digitLowerTable [exponent]);
688                         } else if (exponent < 100) {
689                                 cb.Append ('0', 1);
690                                 cb.Append (digitLowerTable [exponent / 10 % 10]);
691                                 cb.Append (digitLowerTable [exponent % 10]);
692                         } else if (exponent < 1000) {
693                                 cb.Append (digitLowerTable [exponent / 100 % 10]);
694                                 cb.Append (digitLowerTable [exponent / 10 % 10]);
695                                 cb.Append (digitLowerTable [exponent % 10]);
696                         /*} else { // exponent range is 0\81`\81}324
697                                 int pos = cb.Length;
698                                 int count = 3;
699                                 while (exponent > 0 || --count > 0) {
700                                         cb.Insert (pos, digitLowerTable [exponent % 10]);
701                                         exponent /= 10;
702                                 }*/
703                         }
704
705                         return cb.ToString ();
706                 }
707                 #endregion
708
709                 #region Custom
710                 internal static string FormatCustom (string format, NumberStore ns, NumberFormatInfo nfi)
711                 {
712                         bool p = ns.Positive;
713                         int offset = 0;
714                         int length = 0;
715                         CustomInfo.GetActiveSection (format,ref p, ns.ZeroOnly, ref offset, ref length);
716                         if (length == 0) {
717                                 return ns.Positive ? "" : nfi.NegativeSign;
718                         }
719                         ns.Positive = p;
720
721                         CustomInfo info = CustomInfo.Parse (format, offset, length, nfi);
722 #if false
723                         Console.WriteLine("Format : {0}",format);
724                         Console.WriteLine("DecimalDigits : {0}",info.DecimalDigits);
725                         Console.WriteLine("DecimalPointPos : {0}",info.DecimalPointPos);
726                         Console.WriteLine("DecimalTailSharpDigits : {0}",info.DecimalTailSharpDigits);
727                         Console.WriteLine("IntegerDigits : {0}",info.IntegerDigits);
728                         Console.WriteLine("IntegerHeadSharpDigits : {0}",info.IntegerHeadSharpDigits);
729                         Console.WriteLine("IntegerHeadPos : {0}",info.IntegerHeadPos);
730                         Console.WriteLine("UseExponent : {0}",info.UseExponent);
731                         Console.WriteLine("ExponentDigits : {0}",info.ExponentDigits);
732                         Console.WriteLine("ExponentTailSharpDigits : {0}",info.ExponentTailSharpDigits);
733                         Console.WriteLine("ExponentNegativeSignOnly : {0}",info.ExponentNegativeSignOnly);
734                         Console.WriteLine("DividePlaces : {0}",info.DividePlaces);
735                         Console.WriteLine("Percents : {0}",info.Percents);
736                         Console.WriteLine("Permilles : {0}",info.Permilles);
737 #endif
738                         StringBuilder sb_int = new StringBuilder(info.IntegerDigits * 2);
739                         StringBuilder sb_dec = new StringBuilder(info.DecimalDigits * 2);
740                         StringBuilder sb_exp = (info.UseExponent ? new StringBuilder(info.ExponentDigits * 2) : null);
741
742                         int diff = 0;
743                         if (info.Percents > 0) {
744                                 ns.Multiply10 (2 * info.Percents);
745                         }
746                         if (info.Permilles > 0) {
747                                 ns.Multiply10 (3 * info.Permilles);
748                         }
749                         if (info.DividePlaces > 0) {
750                                 ns.Divide10 (info.DividePlaces);
751                         }
752
753                         bool expPositive = true;
754                         if (info.UseExponent && (info.DecimalDigits > 0 || info.IntegerDigits > 0)) {
755                                 if (!ns.ZeroOnly) {
756                                         while (true) {
757                                                 while (ns.IntegerDigits > info.IntegerDigits) {
758                                                         ns.Divide10 (1);
759                                                         diff--;
760                                                         if (ns.IntegerDigits == 1 && ns.GetChar (0) == '0')
761                                                                 break;
762                                                 }
763                                                 while (ns.IntegerDigits < info.IntegerDigits || (ns.IntegerDigits == info.IntegerDigits && ns.GetChar (0) == '0')) {
764                                                         ns.Multiply10 (1);
765                                                         diff++;
766                                                 }
767
768                                                 if (!ns.RoundDecimal (info.DecimalDigits))
769                                                         break;
770                                         }
771                                 }
772
773                                 expPositive = diff <= 0;
774                                 NumberStore.AppendIntegerStringFromUInt32 (sb_exp, (uint)(diff >= 0 ? diff : -diff));
775                         } else {
776                                 ns.RoundDecimal (info.DecimalDigits);
777                                 if (ns.ZeroOnly)
778                                         ns.Positive = true;
779                         }
780
781                         if (info.IntegerDigits != 0 || !ns.CheckZeroOnlyInteger ()) {
782                                 ns.AppendIntegerString (ns.IntegerDigits, sb_int);
783                         }
784                         /* if (sb_int.Length > info.IntegerDigits) {
785                                 int len = 0;
786                                 while (sb_int.Length > info.IntegerDigits && len < sb_int.Length) {
787                                         if (sb_int [len] == '0')
788                                                 len ++;
789                                         else
790                                                 break;
791                                 }
792                                 sb_int.Remove (0, len);
793                         } */
794
795                         ns.AppendDecimalString (ns.DecimalDigits, sb_dec);
796
797                         if (info.UseExponent) {
798                                 if (info.DecimalDigits <= 0 && info.IntegerDigits <= 0)
799                                         ns.Positive = true;
800
801                                 /*if (sb_int.Length < info.IntegerDigits)
802                                         sb_int.Insert (0, "0", info.IntegerDigits - sb_int.Length);*/
803
804                                 while (sb_exp.Length < info.ExponentDigits - info.ExponentTailSharpDigits)
805                                         sb_exp.Insert (0, '0');
806
807                                 if (expPositive && !info.ExponentNegativeSignOnly)
808                                         sb_exp.Insert (0, nfi.PositiveSign);
809                                 else if(!expPositive)
810                                         sb_exp.Insert (0, nfi.NegativeSign);
811                         } else {
812                                 if (sb_int.Length < info.IntegerDigits - info.IntegerHeadSharpDigits)
813                                         sb_int.Insert (0, "0", info.IntegerDigits - info.IntegerHeadSharpDigits - sb_int.Length);
814                                 if (info.IntegerDigits == info.IntegerHeadSharpDigits && NumberStore.IsZeroOnly (sb_int))
815                                         sb_int.Remove (0, sb_int.Length);
816                         }
817
818                         ZeroTrimEnd (sb_dec, true);
819                         while (sb_dec.Length < info.DecimalDigits - info.DecimalTailSharpDigits)
820                                 sb_dec.Append ('0');
821                         if (sb_dec.Length > info.DecimalDigits)
822                                 sb_dec.Remove (info.DecimalDigits, sb_dec.Length - info.DecimalDigits);
823
824                         return info.Format (format, offset, length, nfi, ns.Positive, sb_int, sb_dec, sb_exp);
825                 }
826
827                 private class CustomInfo
828                 {
829                         public bool UseGroup = false;
830                         public int DecimalDigits = 0;
831                         public int DecimalPointPos = -1;
832                         public int DecimalTailSharpDigits = 0;
833                         public int IntegerDigits = 0;
834                         public int IntegerHeadSharpDigits = 0;
835                         public int IntegerHeadPos = 0;
836                         public bool UseExponent = false;
837                         public int ExponentDigits = 0;
838                         public int ExponentTailSharpDigits = 0;
839                         public bool ExponentNegativeSignOnly = true;
840                         public int DividePlaces = 0;
841                         public int Percents = 0;
842                         public int Permilles = 0;
843
844                         public static void GetActiveSection (string format, ref bool positive, bool zero, ref int offset, ref int length)
845                         {
846                                 int[] lens = new int [3];
847                                 int index = 0;
848                                 int lastPos = 0;
849                                 char literal = '\0';
850                                 for (int i = 0; i < format.Length; i++) {
851                                         char c = format [i];
852
853                                         if (c == literal || (literal == '\0' && (c == '\"' || c == '\''))) {
854                                                 if (literal == '\0')
855                                                         literal = c;
856                                                 else
857                                                         literal = '\0';
858                                                 continue;
859                                         }
860                                         
861                                         if (literal == '\0' && format [i] == ';' && (i == 0 || format [i - 1] != '\\')) {
862                                                 lens [index ++] = i - lastPos;
863                                                 lastPos = i + 1;
864                                                 if (index == 3)
865                                                         break;
866                                         }
867                                 }
868
869                                 if (index == 0) {
870                                         offset = 0;
871                                         length = format.Length;
872                                         return;
873                                 }
874                                 if (index == 1) {
875                                         if (positive || zero) {
876                                                 offset = 0;
877                                                 length = lens [0];
878                                                 return;
879                                         }
880                                         if (lens [0] + 1 < format.Length) {
881                                                 positive = true;
882                                                 offset = lens [0] + 1;
883                                                 length = format.Length - offset;
884                                                 return;
885                                         } else {
886                                                 offset = 0;
887                                                 length = lens [0];
888                                                 return;
889                                         }
890                                 }
891                                 if (index == 2) {
892                                         if (zero) {
893                                                 offset = lens [0] + lens [1] + 2;
894                                                 length = format.Length - offset;
895                                                 return;
896                                         }
897                                         if (positive) {
898                                                 offset = 0;
899                                                 length = lens [0];
900                                                 return;
901                                         }
902                                         if (lens [1] > 0) {
903                                                 positive = true;
904                                                 offset = lens [0] + 1;
905                                                 length = lens [1];
906                                                 return;
907                                         } else {
908                                                 offset = 0;
909                                                 length = lens [0];
910                                                 return;
911                                         }
912                                 }
913                                 if (index == 3) {
914                                         if (zero) {
915                                                 offset = lens [0] + lens [1] + 2;
916                                                 length = lens [2];
917                                                 return;
918                                         }
919                                         if (positive) {
920                                                 offset = 0;
921                                                 length = lens [0];
922                                                 return;
923                                         }
924                                         if (lens [1] > 0) {
925                                                 positive = true;
926                                                 offset = lens [0] + 1;
927                                                 length = lens [1];
928                                                 return;
929                                         } else {
930                                                 offset = 0;
931                                                 length = lens [0];
932                                                 return;
933                                         }
934                                 }
935
936                                 throw new ArgumentException ();
937                         }
938
939                         public static CustomInfo Parse (string format, int offset, int length, NumberFormatInfo nfi)
940                         {
941                                 char literal = '\0';
942                                 bool integerArea = true;
943                                 bool decimalArea = false;
944                                 bool exponentArea = false;
945                                 bool sharpContinues = true;
946
947                                 CustomInfo info = new CustomInfo ();
948                                 int groupSeparatorCounter = 0;
949
950                                 for (int i = offset; i - offset < length; i++) {
951                                         char c = format [i];
952
953                                         if (c == literal && c != '\0') {
954                                                 literal = '\0';
955                                                 continue;
956                                         }
957                                         if (literal != '\0')
958                                                 continue;
959
960                                         if (exponentArea && (c != '\0' && c != '0' && c != '#')) {
961                                                 exponentArea = false;
962                                                 integerArea = (info.DecimalPointPos < 0);
963                                                 decimalArea = !integerArea;
964                                                 i--;
965                                                 continue;
966                                         }
967
968                                         switch (c) {
969                                         case '\\':
970                                                 i ++;
971                                                 continue;
972                                         case '\'':
973                                         case '\"':
974                                                 if (c == '\"' || c == '\'') {
975                                                         literal = c;
976                                                 }
977                                                 continue;
978                                         case '#':
979                                                 if (sharpContinues && integerArea)
980                                                         info.IntegerHeadSharpDigits ++;
981                                                 else if (decimalArea)
982                                                         info.DecimalTailSharpDigits ++;
983                                                 else if (exponentArea)
984                                                         info.ExponentTailSharpDigits ++;
985
986                                                 goto case '0';
987                                         case '0':
988                                                 if (c != '#') {
989                                                         sharpContinues = false;
990                                                         if (decimalArea)
991                                                                 info.DecimalTailSharpDigits = 0;
992                                                         else if (exponentArea)
993                                                                 info.ExponentTailSharpDigits = 0;
994                                                 }
995                                                 if (info.IntegerHeadPos == -1)
996                                                         info.IntegerHeadPos = i;
997
998                                                 if (integerArea) {
999                                                         info.IntegerDigits ++;
1000                                                         if (groupSeparatorCounter > 0)
1001                                                                 info.UseGroup = true;
1002                                                         groupSeparatorCounter = 0;
1003                                                 } else if (decimalArea) {
1004                                                         info.DecimalDigits ++;
1005                                                 } else if (exponentArea) {
1006                                                         info.ExponentDigits ++;
1007                                                 }
1008                                                 break;
1009                                         case 'e':
1010                                         case 'E':
1011                                                 if (info.UseExponent)
1012                                                         break;
1013
1014                                                 info.UseExponent = true;
1015                                                 integerArea = false;
1016                                                 decimalArea = false;
1017                                                 exponentArea = true;
1018                                                 if (i + 1 - offset < length) {
1019                                                         char nc = format [i + 1];
1020                                                         if (nc == '+')
1021                                                                 info.ExponentNegativeSignOnly = false;
1022                                                         if (nc == '+' || nc == '-') {
1023                                                                 i ++;
1024                                                         } else if (nc != '0' && nc != '#') {
1025                                                                 info.UseExponent = false;
1026                                                                 if (info.DecimalPointPos < 0)
1027                                                                         integerArea = true;
1028                                                         }
1029                                                         c = '\0';
1030                                                 }
1031                                                 
1032                                                 break;
1033                                         case '.':
1034                                                 integerArea = false;
1035                                                 decimalArea = true;
1036                                                 exponentArea = false;
1037                                                 if (info.DecimalPointPos == -1)
1038                                                         info.DecimalPointPos = i;
1039                                                 break;
1040                                         case '%':
1041                                                 info.Percents++;
1042                                                 break;
1043                                         case '\u2030':
1044                                                 info.Permilles++;
1045                                                 break;
1046                                         case ',':
1047                                                 if (integerArea && info.IntegerDigits > 0)
1048                                                         groupSeparatorCounter ++;
1049                                                 break;
1050                                         default:
1051                                                 break;
1052                                         }
1053                                 }
1054
1055                                 if (info.ExponentDigits == 0)
1056                                         info.UseExponent = false;
1057                                 else
1058                                         info.IntegerHeadSharpDigits = 0;
1059
1060                                 if (info.DecimalDigits == 0)
1061                                         info.DecimalPointPos = -1;
1062
1063                                 info.DividePlaces += groupSeparatorCounter * 3;
1064
1065                                 return info;
1066                         }
1067
1068                         public string Format (string format, int offset, int length, NumberFormatInfo nfi, bool positive, StringBuilder sb_int, StringBuilder sb_dec, StringBuilder sb_exp)
1069                         {
1070                                 StringBuilder sb = new StringBuilder ();
1071                                 char literal = '\0';
1072                                 bool integerArea = true;
1073                                 bool decimalArea = false;
1074                                 int  intSharpCounter = 0;
1075                                 int sb_int_index = 0;
1076                                 int sb_dec_index = 0;
1077
1078                                 int[] groups = nfi.NumberGroupSizes;
1079                                 string groupSeparator = nfi.NumberGroupSeparator;
1080                                 int intLen = 0, total = 0, groupIndex = 0, counter = 0, groupSize = 0, fraction = 0;
1081                                 if (UseGroup && groups.Length > 0) {
1082                                         intLen = sb_int.Length;
1083                                         for (int i = 0; i < groups.Length; i++) {
1084                                                 total += groups [i];
1085                                                 if (total <= intLen)
1086                                                         groupIndex = i;
1087                                         }
1088                                         groupSize = groups [groupIndex];
1089                                         fraction = intLen > total ? intLen - total : 0;
1090                                         if (groupSize == 0) {
1091                                                 while (groupIndex >= 0 && groups [groupIndex] == 0)
1092                                                         groupIndex --;
1093                                                 
1094                                                 groupSize = fraction > 0 ? fraction : groups [groupIndex];
1095                                         }
1096                                         if (fraction == 0) {
1097                                                 counter = groupSize;
1098                                         } else {
1099                                                 groupIndex += fraction / groupSize;
1100                                                 counter = fraction % groupSize;
1101                                                 if (counter == 0)
1102                                                         counter = groupSize;
1103                                                 else
1104                                                         groupIndex ++;
1105                                         }
1106                                 } else {
1107                                         UseGroup = false;
1108                                 }
1109
1110                                 for (int i = offset; i - offset < length; i++) {
1111                                         char c = format [i];
1112
1113                                         if (c == literal && c != '\0') {
1114                                                 literal = '\0';
1115                                                 continue;
1116                                         }
1117                                         if (literal != '\0') {
1118                                                 sb.Append (c);
1119                                                 continue;
1120                                         }
1121
1122                                         switch (c) {
1123                                         case '\\':
1124                                                 i ++;
1125                                                 if (i - offset < length)
1126                                                         sb.Append (format [i]);
1127                                                 continue;
1128                                         case '\'':
1129                                         case '\"':
1130                                                 if (c == '\"' || c == '\'') {
1131                                                         literal = c;
1132                                                 }
1133                                                 continue;
1134                                         case '#':
1135                                                 goto case '0';
1136                                         case '0':
1137                                                 if (integerArea) {
1138                                                         intSharpCounter++;
1139                                                         if (IntegerDigits - intSharpCounter < sb_int.Length + sb_int_index || c == '0')
1140                                                                 while (IntegerDigits - intSharpCounter + sb_int_index < sb_int.Length) {
1141                                                                         sb.Append (sb_int[ sb_int_index++]);
1142                                                                         if (UseGroup && --intLen > 0 && --counter == 0) {
1143                                                                                 sb.Append (groupSeparator);
1144                                                                                 if (--groupIndex < groups.Length && groupIndex >= 0)
1145                                                                                         groupSize = groups [groupIndex];
1146                                                                                 counter = groupSize;
1147                                                                         }
1148                                                                 }
1149                                                         break;
1150                                                 } else if (decimalArea) {
1151                                                         if (sb_dec_index < sb_dec.Length)
1152                                                                 sb.Append (sb_dec [sb_dec_index++]);
1153                                                         break;
1154                                                 }
1155
1156                                                 sb.Append (c);
1157                                                 break;
1158                                         case 'e':
1159                                         case 'E':
1160                                                 if (sb_exp == null || !UseExponent) {
1161                                                         sb.Append (c);
1162                                                         break;
1163                                                 }
1164
1165                                                 bool flag1 = true;
1166                                                 bool flag2 = false;
1167                                                 
1168                                                 int q;
1169                                                 for (q = i + 1; q - offset < length; q++) {
1170                                                         if (format [q] == '0') {
1171                                                                 flag2 = true;
1172                                                                 continue;
1173                                                         }
1174                                                         if (q == i + 1 && (format [q] == '+' || format [q] == '-')) {
1175                                                                 continue;
1176                                                         }
1177                                                         if (!flag2)
1178                                                                 flag1 = false;
1179                                                         break;
1180                                                 }
1181
1182                                                 if (flag1) {
1183                                                         i = q - 1;
1184                                                         integerArea = (DecimalPointPos < 0);
1185                                                         decimalArea = !integerArea;
1186
1187                                                         sb.Append (c);
1188                                                         sb.Append (sb_exp);
1189                                                         sb_exp = null;
1190                                                 } else
1191                                                         sb.Append (c);
1192
1193                                                 break;
1194                                         case '.':
1195                                                 if (DecimalPointPos == i) {
1196                                                         if (DecimalDigits > 0) {
1197                                                                 while (sb_int_index < sb_int.Length)
1198                                                                         sb.Append (sb_int [sb_int_index++]);
1199                                                         }
1200                                                         if (sb_dec.Length > 0)
1201                                                                 sb.Append (nfi.NumberDecimalSeparator);
1202                                                 }
1203                                                 integerArea = false;
1204                                                 decimalArea = true;
1205                                                 break;
1206                                         case ',':
1207                                                 break;
1208                                         case '%':
1209                                                 sb.Append (nfi.PercentSymbol);
1210                                                 break;
1211                                         case '\u2030':
1212                                                 sb.Append (nfi.PerMilleSymbol);
1213                                                 break;
1214                                         default:
1215                                                 sb.Append (c);
1216                                                 break;
1217                                         }
1218                                 }
1219
1220                                 if (!positive)
1221                                         sb.Insert (0, nfi.NegativeSign);
1222
1223                                 return sb.ToString ();
1224                         }
1225                 }
1226
1227                 #endregion
1228
1229                 #region Internal structures
1230                 internal struct NumberStore
1231                 {
1232                         bool _NaN;
1233                         bool _infinity;
1234                         bool _positive;
1235                         int  _decPointPos;
1236                         int  _defPrecision;
1237                         int  _defMaxPrecision;
1238                         int  _defByteSize;
1239
1240                         byte[] _digits;
1241
1242                         static uint [] IntList = new uint [] {
1243                                 1,
1244                                 10,
1245                                 100,
1246                                 1000,
1247                                 10000,
1248                                 100000,
1249                                 1000000,
1250                                 10000000,
1251                                 100000000,
1252                                 1000000000,
1253                         };
1254
1255                         static ulong [] ULongList = new ulong [] {
1256                                 1,
1257                                 10,
1258                                 100,
1259                                 1000,
1260                                 10000,
1261                                 100000,
1262                                 1000000,
1263                                 10000000,
1264                                 100000000,
1265                                 1000000000,
1266                                 10000000000,
1267                                 100000000000,
1268                                 1000000000000,
1269                                 10000000000000,
1270                                 100000000000000,
1271                                 1000000000000000,
1272                                 10000000000000000,
1273                                 100000000000000000,
1274                                 1000000000000000000,
1275                                 10000000000000000000,
1276                         };
1277
1278                         #region Constructors
1279                         public NumberStore (long value)
1280                         {
1281                                 _infinity = _NaN = false;
1282                                 _defByteSize = 8;
1283                                 _defMaxPrecision = _defPrecision = 19;
1284                                 _positive = value >= 0;
1285
1286                                 if (value == 0) {
1287                                         _digits = new byte []{0};
1288                                         _decPointPos = 1;
1289                                         return;
1290                                 }
1291                                 
1292                                 ulong v = (ulong)(_positive ? value : -value);
1293
1294                                 int i = 18, j = 0;
1295
1296                                 if (v < 10)
1297                                         i = 0;
1298                                 else if (v < 100)
1299                                         i = 1;
1300                                 else if (v < 1000)
1301                                         i = 2;
1302                                 else if (v < 10000)
1303                                         i = 3;
1304                                 else if (v < 100000)
1305                                         i = 4;
1306                                 else if (v < 1000000)
1307                                         i = 5;
1308                                 else if (v < 10000000)
1309                                         i = 6;
1310                                 else if (v < 100000000)
1311                                         i = 7;
1312                                 else if (v < 1000000000)
1313                                         i = 8;
1314                                 else if (v < 10000000000)
1315                                         i = 9;
1316                                 else if (v < 100000000000)
1317                                         i = 10;
1318                                 else if (v < 1000000000000)
1319                                         i = 11;
1320                                 else if (v < 10000000000000)
1321                                         i = 12;
1322                                 else if (v < 100000000000000)
1323                                         i = 13;
1324                                 else if (v < 1000000000000000)
1325                                         i = 14;
1326                                 else if (v < 10000000000000000)
1327                                         i = 15;
1328                                 else if (v < 100000000000000000)
1329                                         i = 16;
1330                                 else if (v < 1000000000000000000)
1331                                         i = 17;
1332                                 else
1333                                         i = 18;
1334
1335                                 _digits = new byte [i + 1];
1336                                 do {
1337                                         ulong n = v / ULongList [i];
1338                                         _digits [j++] = (byte)n;
1339                                         v -= ULongList [i--] * n;
1340                                 } while (i >= 0);
1341
1342                                 _decPointPos = _digits.Length;
1343                         }
1344                         public NumberStore (int value)
1345                         {
1346                                 _infinity = _NaN = false;
1347                                 _defByteSize = 4;
1348                                 _defMaxPrecision = _defPrecision = 10;
1349                                 _positive = value >= 0;
1350
1351                                 if (value == 0) {
1352                                         _digits = new byte []{0};
1353                                         _decPointPos = 1;
1354                                         return;
1355                                 }
1356                                 
1357                                 uint v = (uint)(_positive ? value : -value);
1358
1359                                 int i = 9, j = 0;
1360
1361                                 if (v < 10)
1362                                         i = 0;
1363                                 else if (v < 100)
1364                                         i = 1;
1365                                 else if (v < 1000)
1366                                         i = 2;
1367                                 else if (v < 10000)
1368                                         i = 3;
1369                                 else if (v < 100000)
1370                                         i = 4;
1371                                 else if (v < 1000000)
1372                                         i = 5;
1373                                 else if (v < 10000000)
1374                                         i = 6;
1375                                 else if (v < 100000000)
1376                                         i = 7;
1377                                 else if (v < 1000000000)
1378                                         i = 8;
1379                                 else
1380                                         i = 9;
1381
1382                                 _digits = new byte [i + 1];
1383                                 do {
1384                                         uint n = v / IntList [i];
1385                                         _digits [j++] = (byte)n;
1386                                         v -= IntList [i--] * n;
1387                                 } while (i >= 0);
1388
1389                                 _decPointPos = _digits.Length;
1390                         }
1391                         public NumberStore (short value) : this ((int)value)
1392                         {
1393                                 _defByteSize = 2;
1394                                 _defMaxPrecision = _defPrecision = 5;
1395                         }
1396                         public NumberStore (sbyte value) : this ((int)value)
1397                         {
1398                                 _defByteSize = 1;
1399                                 _defMaxPrecision = _defPrecision = 3;
1400                         }
1401
1402                         public NumberStore (ulong value)
1403                         {
1404                                 _infinity = _NaN = false;
1405                                 _defByteSize = 8;
1406                                 _defMaxPrecision = _defPrecision = 20;
1407                                 _positive = true;
1408
1409                                 if (value == 0) {
1410                                         _digits = new byte []{0};
1411                                         _decPointPos = 1;
1412                                         return;
1413                                 }
1414
1415                                 int i = 19, j = 0;
1416
1417                                 if (value < 10)
1418                                         i = 0;
1419                                 else if (value < 100)
1420                                         i = 1;
1421                                 else if (value < 1000)
1422                                         i = 2;
1423                                 else if (value < 10000)
1424                                         i = 3;
1425                                 else if (value < 100000)
1426                                         i = 4;
1427                                 else if (value < 1000000)
1428                                         i = 5;
1429                                 else if (value < 10000000)
1430                                         i = 6;
1431                                 else if (value < 100000000)
1432                                         i = 7;
1433                                 else if (value < 1000000000)
1434                                         i = 8;
1435                                 else if (value < 10000000000)
1436                                         i = 9;
1437                                 else if (value < 100000000000)
1438                                         i = 10;
1439                                 else if (value < 1000000000000)
1440                                         i = 11;
1441                                 else if (value < 10000000000000)
1442                                         i = 12;
1443                                 else if (value < 100000000000000)
1444                                         i = 13;
1445                                 else if (value < 1000000000000000)
1446                                         i = 14;
1447                                 else if (value < 10000000000000000)
1448                                         i = 15;
1449                                 else if (value < 100000000000000000)
1450                                         i = 16;
1451                                 else if (value < 1000000000000000000)
1452                                         i = 17;
1453                                 else if (value < 10000000000000000000)
1454                                         i = 18;
1455                                 else
1456                                         i = 19;
1457
1458                                 _digits = new byte [i + 1];
1459                                 do {
1460                                         ulong n = value / ULongList [i];
1461                                         _digits [j++] = (byte)n;
1462                                         value -= ULongList [i--] * n;
1463                                 } while (i >= 0);
1464
1465                                 _decPointPos = _digits.Length;
1466                         }
1467                         public NumberStore (uint value)
1468                         {
1469                                 _infinity = _NaN = false;
1470                                 _positive = true;
1471                                 _defByteSize = 4;
1472                                 _defMaxPrecision = _defPrecision = 10;
1473
1474                                 if (value == 0) {
1475                                         _digits = new byte []{0};
1476                                         _decPointPos = 1;
1477                                         return;
1478                                 }
1479                                 
1480                                 int i = 9, j = 0;
1481
1482                                 if (value < 10)
1483                                         i = 0;
1484                                 else if (value < 100)
1485                                         i = 1;
1486                                 else if (value < 1000)
1487                                         i = 2;
1488                                 else if (value < 10000)
1489                                         i = 3;
1490                                 else if (value < 100000)
1491                                         i = 4;
1492                                 else if (value < 1000000)
1493                                         i = 5;
1494                                 else if (value < 10000000)
1495                                         i = 6;
1496                                 else if (value < 100000000)
1497                                         i = 7;
1498                                 else if (value < 1000000000)
1499                                         i = 8;
1500                                 else
1501                                         i = 9;
1502
1503                                 _digits = new byte [i + 1];
1504                                 do {
1505                                         uint n = value / IntList [i];
1506                                         _digits [j++] = (byte)n;
1507                                         value -= IntList [i--] * n;
1508                                 } while (i >= 0);
1509
1510                                 _decPointPos = _digits.Length;
1511                         }
1512                         public NumberStore (ushort value) : this ((uint)value)
1513                         {
1514                                 _defByteSize = 2;
1515                                 _defMaxPrecision = _defPrecision = 5;
1516                         }
1517                         public NumberStore (byte value) : this ((uint)value)
1518                         {
1519                                 _defByteSize = 1;
1520                                 _defMaxPrecision = _defPrecision = 3;
1521                         }
1522
1523                         public NumberStore(double value)
1524                         {
1525                                 _digits = null;
1526                                 _defByteSize = 64;
1527                                 _defPrecision = 15;
1528                                 _defMaxPrecision = _defPrecision + 2;
1529
1530                                 if (double.IsNaN (value) || double.IsInfinity (value)) {
1531                                         _NaN = double.IsNaN (value);
1532                                         _infinity = double.IsInfinity (value);
1533                                         _positive = value > 0;
1534                                         _decPointPos = 0;
1535                                         return;
1536                                 } else {
1537                                         _NaN = _infinity = false;
1538                                 }
1539
1540                                 long bits = BitConverter.DoubleToInt64Bits (value);
1541                                 _positive = (bits >= 0);
1542                                 int e = (int) ((bits >> 52) & 0x7ffL);
1543                                 long m = bits & 0xfffffffffffffL;
1544
1545                                 if (e == 0 && m == 0) {
1546                                         _decPointPos = 1;
1547                                         _digits = new byte []{0};
1548                                         _positive = true;
1549                                         return;
1550                                 }
1551
1552                                 if (e == 0) {
1553                                         e ++;
1554                                 } else if (e != 0) {
1555                                         m |= (1L << 52);
1556                                 }
1557
1558                                 e -= 1075;
1559
1560                                 int nsize = 0;
1561                                 while ((m & 1) == 0) {
1562                                         m >>= 1;
1563                                         e ++;
1564                                         nsize ++;
1565                                 }
1566
1567                                 long mt = m;
1568                                 int length = 1;
1569                                 byte[] temp = new byte [56];
1570                                 for (int i = temp.Length - 1; i >= 0; i--, length++) {
1571                                         temp [i] = (byte)(mt % 10);
1572                                         mt /= 10;
1573                                         if (mt == 0)
1574                                                 break;
1575                                 }
1576
1577                                 _decPointPos = temp.Length - 1;
1578
1579                                 if (e >= 0) {
1580                                         for (int i = 0; i < e; i++) {
1581                                                 if (MultiplyBy (ref temp, ref length, 2)) {
1582                                                         _decPointPos ++;
1583                                                 }
1584                                         }
1585                                 } else {
1586                                         for (int i = 0; i < -e; i++) {
1587                                                 if (MultiplyBy (ref temp, ref length, 5)) {
1588                                                         _decPointPos ++;
1589                                                 }
1590                                         }
1591                                         _decPointPos += e;
1592                                 }
1593
1594                                 int ulvc = 1;
1595                                 ulong ulv = 0;
1596                                 for (int i = 0; i < temp.Length; i++)
1597                                         if (temp [i] != 0) {
1598                                                 _decPointPos -= i - 1;
1599                                                 _digits = new byte [temp.Length - i];
1600                                                 for (int q = i; q < temp.Length; q++) {
1601                                                         _digits [q - i] = temp [q];
1602                                                         if (ulvc < 20) {
1603                                                                 ulv = ulv * 10 + temp [q];
1604                                                                 ulvc ++;
1605                                                         }
1606                                                 }
1607                                                 break;
1608                                         }
1609
1610                                 RoundEffectiveDigits (17, true, true);
1611                         }
1612                         public NumberStore(float value)
1613                         {
1614                                 _digits = null;
1615                                 _defByteSize = 32;
1616                                 _defPrecision = 7;
1617                                 _defMaxPrecision = _defPrecision + 2;
1618
1619                                 if (float.IsNaN (value) || float.IsInfinity (value)) {
1620                                         _NaN = float.IsNaN (value);
1621                                         _infinity = float.IsInfinity (value);
1622                                         _positive = value > 0;
1623                                         _decPointPos = 0;
1624                                         return;
1625                                 } else
1626                                         _infinity = _NaN = false;
1627
1628                                 long bits = BitConverter.DoubleToInt64Bits (value);
1629                                 _positive = (bits >= 0);
1630                                 int e = (int) ((bits >> 52) & 0x7ffL);
1631                                 long m = bits & 0xfffffffffffffL;
1632
1633                                 if (e == 0 && m == 0) {
1634                                         _decPointPos = 1;
1635                                         _digits = new byte []{0};
1636                                         _positive = true;
1637                                         return;
1638                                 }
1639
1640                                 if (e == 0) {
1641                                         e ++;
1642                                 } else if (e != 0) {
1643                                         m |= (1L << 52);
1644                                 }
1645
1646                                 e -= 1075;
1647
1648                                 int nsize = 0;
1649                                 while ((m & 1) == 0) {
1650                                         m >>= 1;
1651                                         e ++;
1652                                         nsize ++;
1653                                 }
1654
1655                                 long mt = m;
1656                                 int length = 1;
1657                                 byte[] temp = new byte [26];
1658                                 for (int i = temp.Length - 1; i >= 0; i--, length++) {
1659                                         temp [i] = (byte)(mt % 10);
1660                                         mt /= 10;
1661                                         if (mt == 0)
1662                                                 break;
1663                                 }
1664
1665                                 _decPointPos = temp.Length - 1;
1666
1667                                 if (e >= 0) {
1668                                         for (int i = 0; i < e; i++) {
1669                                                 if (MultiplyBy (ref temp, ref length, 2)) {
1670                                                         _decPointPos ++;
1671                                                 }
1672                                         }
1673                                 } else {
1674                                         for (int i = 0; i < -e; i++) {
1675                                                 if (MultiplyBy (ref temp, ref length, 5)) {
1676                                                         _decPointPos ++;
1677                                                 }
1678                                         }
1679                                         _decPointPos += e;
1680                                 }
1681
1682                                 int ulvc = 1;
1683                                 ulong ulv = 0;
1684                                 for (int i = 0; i < temp.Length; i++)
1685                                         if (temp [i] != 0) {
1686                                                 _decPointPos -= i - 1;
1687                                                 _digits = new byte [temp.Length - i];
1688                                                 for (int q = i; q < temp.Length; q++) {
1689                                                         _digits [q - i] = temp [q];
1690                                                         if (ulvc < 20) {
1691                                                                 ulv = ulv * 10 + temp [q];
1692                                                                 ulvc ++;
1693                                                         }
1694                                                 }
1695                                                 break;
1696                                         }
1697
1698                                 RoundEffectiveDigits (9, true, true);
1699                         }
1700
1701                         internal bool MultiplyBy (ref byte[] buffer,ref int length, int amount)
1702                         {
1703                                 int mod = 0;
1704                                 int ret;
1705                                 int start = buffer.Length - length - 1;
1706                                 if (start < 0) start = 0;
1707
1708                                 for (int i = buffer.Length - 1; i > start; i--) {
1709                                         ret = buffer [i] * amount + mod;
1710                                         mod = ret / 10;
1711                                         buffer [i] = (byte)(ret % 10);
1712                                 }
1713
1714                                 if (mod != 0) {
1715                                         length = buffer.Length - start;
1716
1717                                         if (start == 0) {
1718                                                 buffer [0] = (byte)mod;
1719                                                 Array.Copy (buffer, 0, buffer, 1, buffer.Length - 1);
1720                                                 buffer [0] = 0;
1721                                                 return true;
1722                                         }
1723                                         else {
1724                                                 buffer [start] = (byte)mod;
1725                                         }
1726                                 }
1727
1728                                 return false;
1729                         }
1730                         #endregion
1731
1732                         #region Public Property
1733                         public bool IsNaN 
1734                         {
1735                                 get { return _NaN; }
1736                         }
1737                         public bool IsInfinity {
1738                                 get { return _infinity; }
1739                         }
1740                         public int DecimalPointPosition {
1741                                 get { return _decPointPos; }
1742                         }
1743                         public bool Positive {
1744                                 get { return _positive; }
1745                                 set { _positive = value;}
1746                         }
1747                         public int DefaultPrecision {
1748                                 get { return _defPrecision; }
1749                         }
1750                         public int DefaultMaxPrecision {
1751                                 get { return _defMaxPrecision; }
1752                         }
1753                         public int DefaultByteSize {
1754                                 get { return _defByteSize; }
1755                         }
1756                         public bool HasDecimal {
1757                                 get { return _digits.Length > _decPointPos; }
1758                         }
1759                         public int IntegerDigits {
1760                                 get { return _decPointPos > 0 ? _decPointPos : 1; }
1761                         }
1762                         public int DecimalDigits {
1763                                 get { return HasDecimal ? _digits.Length - _decPointPos : 0; }
1764                         }
1765                         public bool IsFloatingSource {
1766                                 get { return _defPrecision == 15 || _defPrecision == 7; }
1767                         }
1768                         public bool ZeroOnly {
1769                                 get {
1770                                         for (int i = 0; i < _digits.Length; i++)
1771                                                 if (_digits [i] != 0)
1772                                                         return false;
1773                                         return true;
1774                                 }
1775                         }
1776                         #endregion
1777
1778                         #region Public Method
1779
1780                         #region Round
1781                         public bool RoundPos (int pos)
1782                         {
1783                                 return RoundPos (pos, true);
1784                         }
1785                         public bool RoundPos (int pos, bool carryFive)
1786                         {
1787                                 bool carry = false;
1788
1789                                 if (_decPointPos <= 0)
1790                                         pos = pos - _decPointPos - 1;
1791
1792                                 if (pos >= _digits.Length)
1793                                         return false;
1794
1795                                 if (pos < 0) {
1796                                         _digits = new byte [1];
1797                                         _digits [0] = 0;
1798                                         _decPointPos = 1;
1799                                         _positive = true;
1800                                         return false;
1801                                 }
1802
1803                                 for (int i = pos; i >= 0; i--) {
1804                                         RoundHelper (i, carryFive, ref carry);
1805                                         if (!carry)
1806                                                 break;
1807                                 }
1808
1809                                 if (carry) {
1810                                         byte[] temp = new byte [_digits.Length + 1];
1811                                         _digits.CopyTo (temp, 1);
1812                                         temp [0] = 1;
1813                                         _digits = temp;
1814                                         _decPointPos ++;
1815                                         pos ++;
1816                                 }
1817
1818                                 for (int i = pos; i < _digits.Length; i++)
1819                                         _digits [i] = 0;
1820                                 TrimDecimalEndZeros ();
1821
1822                                 return carry;
1823                         }
1824                         public bool RoundDecimal (int decimals)
1825                         {
1826                                 return RoundDecimal (decimals, true);
1827                         }
1828                         public bool RoundDecimal (int decimals, bool carryFive)
1829                         {
1830                                 bool carry = false;
1831
1832                                 decimals += _decPointPos;
1833
1834                                 if (!HasDecimal || decimals >= _digits.Length)
1835                                         return false;
1836
1837                                 if (decimals < 0) {
1838                                         _digits = new byte [1];
1839                                         _digits [0] = 0;
1840                                         _decPointPos = 1;
1841                                         _positive = true;
1842                                         return false;
1843                                 }
1844
1845                                 for (int i = decimals; i >= 0; i--) {
1846                                         RoundHelper (i, carryFive, ref carry);
1847                                         if (!carry)
1848                                                 break;
1849                                 }
1850
1851                                 if (carry) {
1852                                         byte[] temp = new byte [_digits.Length + 1];
1853                                         _digits.CopyTo (temp, 1);
1854                                         temp [0] = 1;
1855                                         _digits = temp;
1856                                         _decPointPos ++;
1857                                         decimals ++;
1858                                 }
1859
1860                                 for (int i = decimals; i < _digits.Length; i++)
1861                                         _digits [i] = 0;
1862                                 TrimDecimalEndZeros ();
1863
1864                                 return carry;
1865                         }
1866                         void RoundHelper (int index, bool carryFive, ref bool carry)
1867                         {
1868                                 if (carry) {
1869                                         if (_digits [index] == 9) {
1870                                                 carry = true;
1871                                                 _digits [index] = 0;
1872                                         } else {
1873                                                 carry = false;
1874                                                 _digits [index] ++;
1875                                         }
1876                                 } else if (_digits [index] >= (carryFive ? 5 : 6)) {
1877                                         carry = true;
1878                                 }
1879                         }
1880                         public bool RoundEffectiveDigits (int digits)
1881                         {
1882                                 return RoundEffectiveDigits (digits, true, true);
1883                         }
1884                         public bool RoundEffectiveDigits (int digits, bool carryFive, bool carryEven)
1885                         {
1886                                 bool carry = false;
1887
1888                                 if (digits >= _digits.Length || digits < 0)
1889                                         return false;
1890
1891                                 if (digits + 1 < _digits.Length && _digits [digits + 1] == 5 && _digits [digits] % 2 == (carryEven ? 0 : 1))
1892                                         carryFive = false;
1893
1894                                 for (int i = digits; i >= 0; i--) {
1895                                         RoundHelper (i, carryFive, ref carry);
1896                                         if (!carry)
1897                                                 break;
1898                                 }
1899
1900                                 if (carry) {
1901                                         byte[] temp = new byte [_digits.Length + 1];
1902                                         _digits.CopyTo (temp, 1);
1903                                         temp [0] = 1;
1904                                         _digits = temp;
1905                                         _decPointPos ++;
1906                                         digits ++;
1907                                 }
1908
1909                                 for (int i = digits; i < _digits.Length; i++)
1910                                         _digits [i] = 0;
1911                                 TrimDecimalEndZeros ();
1912
1913                                 return carry;
1914                         }
1915                         #endregion
1916
1917                         #region Trim
1918                         public void TrimDecimalEndZeros ()
1919                         {
1920                                 int len = 0;
1921                                 for (int i = _digits.Length - 1; i >= 0; i --) {
1922                                         if (_digits [i] != 0)
1923                                                 break;
1924                                         len ++;
1925                                 }
1926
1927                                 if (len > 0) {
1928                                         byte[] temp = new byte [_digits.Length - len];
1929                                         Array.Copy (_digits, 0, temp, 0, temp.Length);
1930                                         _digits = temp;
1931                                 }
1932                         }
1933                         public void TrimIntegerStartZeros ()
1934                         {
1935                                 if (_decPointPos < 0 && _decPointPos >= _digits.Length)
1936                                         return;
1937
1938                                 int len = 0;
1939                                 for (int i = 0; i < _decPointPos && i < _digits.Length; i++) {
1940                                         if (_digits [i] != 0)
1941                                                 break;
1942                                         len ++;
1943                                 }
1944
1945                                 if (len == _decPointPos)
1946                                         len --;
1947
1948                                 if (len == _digits.Length) {
1949                                         _digits = new byte [1];
1950                                         _digits [0] = 0;
1951                                         _decPointPos = 1;
1952                                         _positive = true;
1953                                 } else if (len > 0) {
1954                                         byte[] temp = new byte [_digits.Length - len];
1955                                         Array.Copy (_digits, len, temp, 0, temp.Length);
1956                                         _digits = temp;
1957                                         _decPointPos -= len;
1958                                 }
1959                         }
1960
1961                         #endregion
1962
1963                         #region Integer
1964                         public void AppendIntegerString (int minLength, StringBuilder cb)
1965                         {
1966                                 if (IntegerDigits == 0) {
1967                                         cb.Append ('0', minLength);
1968                                         return;
1969                                 }
1970                                 if (_decPointPos <= 0) {
1971                                         cb.Append ('0', minLength);
1972                                         return;
1973                                 }
1974
1975                                 if (_decPointPos < minLength)
1976                                         cb.Append ('0', minLength - _decPointPos);
1977
1978                                 for (int i = 0; i < _decPointPos; i++) {
1979                                         if (i < _digits.Length)
1980                                                 cb.Append ((char)('0' + _digits [i]));
1981                                         else
1982                                                 cb.Append ('0');
1983                                 }
1984                         }
1985                         public void AppendIntegerStringWithGroupSeparator (StringBuilder sb, int[] groups, string groupSeparator)
1986                         {
1987                                 if (_decPointPos <= 0) {
1988                                         sb.Append ('0');
1989                                         return;
1990                                 }
1991
1992                                 int intLen = IntegerDigits;
1993                                 int total = 0;
1994                                 int groupIndex = 0;
1995                                 for (int i = 0; i < groups.Length; i++) {
1996                                         total += groups [i];
1997                                         if (total <= intLen)
1998                                                 groupIndex = i;
1999                                 }
2000
2001                                 if (groups.Length > 0 && total > 0) {
2002                                         int counter;
2003                                         int groupSize = groups [groupIndex];
2004                                         int fraction = intLen > total ? intLen - total : 0;
2005                                         if (groupSize == 0) {
2006                                                 while (groupIndex >= 0 && groups [groupIndex] == 0)
2007                                                         groupIndex --;
2008                                                 
2009                                                 groupSize = fraction > 0 ? fraction : groups [groupIndex];
2010                                         }
2011                                         if (fraction == 0) {
2012                                                 counter = groupSize;
2013                                         } else {
2014                                                 groupIndex += fraction / groupSize;
2015                                                 counter = fraction % groupSize;
2016                                                 if (counter == 0)
2017                                                         counter = groupSize;
2018                                                 else
2019                                                         groupIndex ++;
2020                                         }
2021                                         
2022                                         for (int i = 0; i < _decPointPos; i++) {
2023                                                 if (i < _digits.Length) {
2024                                                         sb.Append ((char)('0' + _digits [i]));
2025                                                 } else {
2026                                                         sb.Append ('0');
2027                                                 }
2028
2029                                                 if (i < intLen - 1 && --counter == 0) {
2030                                                         sb.Append (groupSeparator);
2031                                                         if (--groupIndex < groups.Length && groupIndex >= 0)
2032                                                                 groupSize = groups [groupIndex];
2033                                                         counter = groupSize;
2034                                                 }
2035                                         }
2036                                 } else {
2037                                         for (int i = 0; i < _decPointPos; i++) {
2038                                                 if (i < _digits.Length) {
2039                                                         sb.Append ((char)('0' + _digits [i]));
2040                                                 } else {
2041                                                         sb.Append ('0');
2042                                                 }
2043                                         }
2044                                 }
2045                         }
2046                         #endregion
2047
2048                         #region Decimal
2049                         public string GetDecimalString (int precision)
2050                         {
2051                                 if (!HasDecimal)
2052                                         return new string ('0', precision);
2053
2054                                 StringBuilder sb = new StringBuilder (precision);
2055                                 for (int i = _decPointPos; i < _digits.Length && i < precision + _decPointPos; i++) {
2056                                         if (i >= 0)
2057                                                 sb.Append ((char)('0' + _digits [i]));
2058                                         else
2059                                                 sb.Append ('0');
2060                                 }
2061                                 if (sb.Length < precision)
2062                                         sb.Append ('0', precision - sb.Length);
2063                                 else if (sb.Length > precision)
2064                                         sb.Remove (0, precision);
2065                                 return sb.ToString ();
2066                         }
2067
2068                         public void AppendDecimalString (int precision, StringBuilder cb)
2069                         {
2070                                 if (!HasDecimal) {
2071                                         cb.Append ('0', precision);
2072                                         return;
2073                                 }
2074
2075                                 int i = _decPointPos;
2076                                 for (; i < _digits.Length && i < precision + _decPointPos; i++) {
2077                                         if (i >= 0)
2078                                                 cb.Append ((char)('0' + _digits [i]));
2079                                         else
2080                                                 cb.Append ('0');
2081                                 }
2082
2083                                 i -= _decPointPos;
2084                                 if (i < precision)
2085                                         cb.Append ('0', precision - i);
2086                         }
2087                         #endregion
2088
2089                         #region others
2090                         public bool CheckZeroOnlyInteger ()
2091                         {
2092                                 for (int i = 0; i < _decPointPos && i < _digits.Length; i++) {
2093                                         if (_digits [i] != 0)
2094                                                 return false;
2095                                 }
2096                                 return true;
2097                         }
2098                         public void Multiply10 (int count)
2099                         {
2100                                 if (count <= 0)
2101                                         return;
2102
2103                                 _decPointPos += count;
2104
2105                                 TrimIntegerStartZeros ();
2106                         }
2107                         public void Divide10 (int count)
2108                         {
2109                                 if (count <= 0)
2110                                         return;
2111
2112                                 _decPointPos -= count;
2113                         }
2114                         public override string ToString()
2115                         {
2116                                 StringBuilder sb = new StringBuilder ();
2117                                 AppendIntegerString (IntegerDigits, sb);
2118                                 if (HasDecimal) {
2119                                         sb.Append ('.');
2120                                         AppendDecimalString (DecimalDigits, sb);
2121                                 }
2122                                 return sb.ToString ();
2123                         }
2124                         public char GetChar (int pos)
2125                         {
2126                                 if (_decPointPos <= 0)
2127                                         pos += _decPointPos - 1;
2128                                 
2129                                 if (pos < 0 || pos >= _digits.Length)
2130                                         return '0';
2131                                 else
2132                                         return (char)('0' + _digits [pos]);
2133                         }
2134                         public byte GetDigitByte (int pos)
2135                         {
2136                                 if (_decPointPos <= 0)
2137                                         pos += _decPointPos - 1;
2138                                 
2139                                 if (pos < 0 || pos >= _digits.Length)
2140                                         return 0;
2141                                 else
2142                                         return _digits [pos];
2143                         }
2144                         public NumberStore GetClone ()
2145                         {
2146                                 NumberStore ns = new NumberStore ();
2147
2148                                 ns._decPointPos = this._decPointPos;
2149                                 ns._defMaxPrecision = this._defMaxPrecision;
2150                                 ns._defPrecision = this._defPrecision;
2151                                 ns._digits = (byte[])this._digits.Clone ();
2152                                 ns._infinity = this._infinity;
2153                                 ns._NaN = this._NaN;
2154                                 ns._positive = this._positive;
2155
2156                                 return ns;
2157                         }
2158                         public int GetDecimalPointPos ()
2159                         {
2160                                 return _decPointPos;
2161                         }
2162                         public void SetDecimalPointPos (int dp)
2163                         {
2164                                 _decPointPos = dp;
2165                         }
2166                         #endregion
2167
2168                         #endregion
2169
2170                         #region Public Static Method
2171                         public static bool IsZeroOnly (StringBuilder sb)
2172                         {
2173                                 for (int i = 0; i < sb.Length; i++)
2174                                         if (char.IsDigit (sb [i]) && sb [i] != '0')
2175                                                 return false;
2176                                 return true;
2177                         }
2178                         public static void AppendIntegerStringFromUInt32 (StringBuilder sb, uint v)
2179                         {
2180                                 if (v < 0)
2181                                         throw new ArgumentException ();
2182
2183                                 int i = 9;
2184
2185                                 if (v >= 1000000000)
2186                                         i = 9;
2187                                 else if (v >= 100000000)
2188                                         i = 8;
2189                                 else if (v >= 10000000)
2190                                         i = 7;
2191                                 else if (v >= 1000000)
2192                                         i = 6;
2193                                 else if (v >= 100000)
2194                                         i = 5;
2195                                 else if (v >= 10000)
2196                                         i = 4;
2197                                 else if (v >= 1000)
2198                                         i = 3;
2199                                 else if (v >= 100)
2200                                         i = 2;
2201                                 else if (v >= 10)
2202                                         i = 1;
2203                                 else
2204                                         i = 0;
2205                                 do {
2206                                         uint n = v / IntList [i];
2207                                         sb.Append (NumberFormatter.digitLowerTable [n]);
2208                                         v -= IntList [i--] * n;
2209                                 } while (i >= 0);
2210                         }
2211                         #endregion
2212                 }
2213                 internal struct CharBuffer
2214                 {
2215                         int offset;
2216                         char[] buffer;
2217
2218                         public CharBuffer (int capacity)
2219                         {
2220                                 buffer = new char [capacity];
2221                                 offset = capacity;
2222                         }
2223
2224                         void AllocateBuffer (int size)
2225                         {
2226                                 size = size > buffer.Length * 2 ? size : buffer.Length * 2;
2227                                 char[] newBuffer = new char [size];
2228                                 offset += size - buffer.Length;
2229                                 Array.Copy (buffer, 0, newBuffer, size - buffer.Length, buffer.Length);
2230                                 buffer = newBuffer;
2231                         }
2232
2233                         void CheckInsert (int length)
2234                         {
2235                                 if (offset - length < 0) {
2236                                         AllocateBuffer (buffer.Length + length - offset);
2237                                 }
2238                         }
2239
2240                         public void InsertToFront (char c)
2241                         {
2242                                 CheckInsert (1);
2243                                 buffer [--offset] = c;
2244                         }
2245
2246                         public void InsertToFront (char c, int repeat)
2247                         {
2248                                 CheckInsert (repeat);
2249                                 while (repeat-- > 0) {
2250                                         buffer [--offset] = c;
2251                                 }
2252                         }
2253
2254                         public char this [int index] 
2255                         {
2256                                 get {
2257                                         return buffer [offset + index];
2258                                 }
2259                         }
2260
2261                         public override string ToString()
2262                         {
2263                                 if (offset == buffer.Length)
2264                                         return "";
2265                                 
2266                                 return new string (buffer, offset, buffer.Length - offset);
2267                         }
2268
2269                         public int Length {
2270                                 get { return buffer.Length - offset; }
2271                         }
2272                 }
2273                 #endregion
2274         }
2275 }