1 /*******************************************************************************
2 
3         copyright:      Copyright (c) 2004 Kris Bell. All rights reserved
4 
5         license:        BSD style: $(LICENSE)
6         
7         version:        Nov 2005: Initial release
8                         Jan 2010: added internal ecvt() 
9 
10         author:         Kris
11 
12         A set of functions for converting between string and floating-
13         point values.
14 
15         Applying the D "import alias" mechanism to this module is highly
16         recommended, in order to limit namespace pollution:
17         ---
18         import Float = tango.text.convert.Float;
19 
20         auto f = Float.parse ("3.14159");
21         ---
22         
23 *******************************************************************************/
24 
25 module tango.text.convert.Float;
26 
27 import tango.core.Exception;
28 import tango.math.IEEE;
29 
30 /******************************************************************************
31 
32         select an internal version
33                 
34 ******************************************************************************/
35 
36 version = float_internal;
37 
38 private alias real NumType;
39 
40 /******************************************************************************
41 
42         optional math functions
43                 
44 ******************************************************************************/
45 
46 private extern (C)
47 {
48         double log10 (double x);
49         double ceil (double num);
50         double modf (double num, double *i);
51         double pow  (double base, double exp);
52 
53         real log10l (real x);
54         real ceill (real num);
55         real modfl (real num, real *i);
56         real powl  (real base, real exp);
57 
58         int printf (char*, ...);
59         version (float_lib)
60         {
61             version (Windows)
62             {
63                 alias ecvt econvert;
64                 alias ecvt fconvert;
65                 char* ecvt (double d, int digits, int* decpt, int* sign);
66                 char* fcvt (double d, int digits, int* decpt, int* sign);
67             }
68             else
69             {
70                 alias ecvtl econvert;
71                 alias ecvtl fconvert;
72                 char* ecvtl (real d, int digits, int* decpt, int* sign);
73                 char* fcvtl (real d, int digits, int* decpt, int* sign);
74             }
75         }
76 }
77 
78 /******************************************************************************
79 
80         Constants
81                 
82 ******************************************************************************/
83 
84 private enum 
85 {
86         Pad = 0,                // default trailing decimal zero
87         Dec = 2,                // default decimal places
88         Exp = 10,               // default switch to scientific notation
89 }
90 
91 /******************************************************************************
92 
93         Convert a formatted string of digits to a floating-point
94         number. Throws an exception where the input text is not
95         parsable in its entirety.
96         
97 ******************************************************************************/
98 
99 NumType toFloat(T) (const(T[]) src)
100 {
101         size_t len;
102 
103         auto x = parse (src, &len);
104         if (len < src.length || len == 0)
105             throw new IllegalArgumentException ("Float.toFloat :: invalid number");
106         return x;
107 }
108 
109 /******************************************************************************
110 
111         Template wrapper to make life simpler. Returns a text version
112         of the provided value.
113 
114         See format() for details
115 
116 ******************************************************************************/
117 
118 char[] toString (NumType d, uint decimals=Dec, int e=Exp)
119 {
120         char[64] tmp = void;
121         
122         return format (tmp, d, cast(int)decimals, e).dup;
123 }
124                
125 /******************************************************************************
126 
127         Template wrapper to make life simpler. Returns a text version
128         of the provided value.
129 
130         See format() for details
131 
132 ******************************************************************************/
133 
134 wchar[] toString16 (NumType d, uint decimals=Dec, int e=Exp)
135 {
136         wchar[64] tmp = void;
137         
138         return format (tmp, d, cast(int)decimals, e).dup;
139 }
140                
141 /******************************************************************************
142 
143         Template wrapper to make life simpler. Returns a text version
144         of the provided value.
145 
146         See format() for details
147 
148 ******************************************************************************/
149 
150 dchar[] toString32 (NumType d, uint decimals=Dec, int e=Exp)
151 {
152         dchar[64] tmp = void;
153         
154         return format (tmp, d, cast(int)decimals, e).dup;
155 }
156                
157 /******************************************************************************
158 
159         Truncate trailing '0' and '.' from a string, such that 200.000 
160         becomes 200, and 20.10 becomes 20.1
161 
162         Returns a potentially shorter slice of what you give it.
163 
164 ******************************************************************************/
165 
166 T[] truncate(T) (T[] s)
167 {
168         auto tmp = s;
169         int i = tmp.length;
170         foreach (int idx, T c; tmp)
171                  if (c is '.')
172                      while (--i >= idx)
173                             if (tmp[i] != '0')
174                                {  
175                                if (tmp[i] is '.')
176                                    --i;
177                                s = tmp [0 .. i+1];
178                                while (--i >= idx)
179                                       if (tmp[i] is 'e')
180                                           return tmp;
181                                break;
182                                }
183         return s;
184 }
185 
186 /******************************************************************************
187 
188         Extract a sign-bit
189 
190 ******************************************************************************/
191 
192 private bool negative (NumType x)
193 {
194         static if (NumType.sizeof is 4) 
195                    return ((*cast(uint *)&x) & 0x8000_0000) != 0;
196         else
197            static if (NumType.sizeof is 8) 
198                       return ((*cast(ulong *)&x) & 0x8000_0000_0000_0000) != 0;
199                 else
200                    {
201                    auto pe = cast(ubyte *)&x;
202                    return (pe[9] & 0x80) != 0;
203                    }
204 }
205 
206 
207 /******************************************************************************
208 
209         Convert a floating-point number to a string. 
210 
211         The e parameter controls the number of exponent places emitted, 
212         and can thus control where the output switches to the scientific 
213         notation. For example, setting e=2 for 0.01 or 10.0 would result
214         in normal output. Whereas setting e=1 would result in both those
215         values being rendered in scientific notation instead. Setting e
216         to 0 forces that notation on for everything. Parameter pad will
217         append trailing '0' decimals when set ~ otherwise trailing '0's 
218         will be elided
219 
220 ******************************************************************************/
221 T[] format(T) (T[] dst, NumType x, int decimals=Dec, int e=Exp, bool pad=Pad)
222 {
223         char*           end,
224                         str;
225         int             exp,
226                         sign,
227                         mode=5;
228         char[32]        buf = void;
229 
230         // test exponent to determine mode
231         exp = (x is 0) ? 1 : cast(int) log10l (x < 0 ? -x : x);
232         if (exp <= -e || exp >= e)
233             mode = 2, ++decimals;
234 
235 version (float_internal)
236          str = convertl (buf.ptr, x, decimals, &exp, &sign, mode is 5);
237 version (float_dtoa)
238          str = dtoa (x, mode, decimals, &exp, &sign, &end);
239 version (float_lib)
240         {
241         if (mode is 5)
242             str = fconvert (x, decimals, &exp, &sign);
243         else
244            str = econvert (x, decimals, &exp, &sign);
245         }
246 
247         auto p = dst.ptr;
248         if (sign)
249             *p++ = '-';
250 
251         if (exp is 9999)
252             while (*str) 
253                    *p++ = *str++;
254         else
255            {
256            if (mode is 2)
257               {
258               --exp;
259               *p++ = *str++;
260               if (*str || pad)
261                  {
262                  auto d = p;
263                  *p++ = '.';
264                  while (*str)
265                         *p++ = *str++;
266                  if (pad)
267                      while (p-d < decimals)
268                             *p++ = '0';
269                  }
270               *p++ = 'e';
271               if (exp < 0)
272                   *p++ = '-', exp = -exp;
273               else
274                  *p++ = '+';
275               if (exp >= 1000)
276                  {
277                  *p++ = cast(T)((exp/1000) + '0');
278                  exp %= 1000;
279                  }
280               if (exp >= 100)
281                  {
282                  *p++ = cast(char)(exp / 100 + '0');
283                  exp %= 100;
284                  }
285               *p++ = cast(char)(exp / 10 + '0');
286               *p++ = cast(char)(exp % 10 + '0');
287               }
288            else
289               {
290               if (exp <= 0)
291                   *p++ = '0';
292               else
293                  for (; exp > 0; --exp)
294                         *p++ = (*str) ? *str++ : '0';
295               if (*str || pad)
296                  {
297                  *p++ = '.';
298                  auto d = p;
299                  for (; exp < 0; ++exp)
300                         *p++ = '0';
301                  while (*str)
302                         *p++ = *str++;
303                  if (pad)
304                      while (p-d < decimals)
305                             *p++ = '0';
306                  }
307               } 
308            }
309 
310         // stuff a C terminator in there too ...
311         *p = 0;
312         return dst[0..(p - dst.ptr)];
313 }
314 
315 
316 /******************************************************************************
317 
318         ecvt() and fcvt() for 80bit FP, which DMD does not include. Based
319         upon the following:
320 
321         Copyright (c) 2009 Ian Piumarta
322         
323         All rights reserved.
324 
325         Permission is hereby granted, free of charge, to any person 
326         obtaining a copy of this software and associated documentation 
327         files (the 'Software'), to deal in the Software without restriction, 
328         including without limitation the rights to use, copy, modify, merge, 
329         publish, distribute, and/or sell copies of the Software, and to permit 
330         persons to whom the Software is furnished to do so, provided that the 
331         above copyright notice(s) and this permission notice appear in all 
332         copies of the Software.  
333 
334 ******************************************************************************/
335 
336 version (float_internal)
337 {
338 private char *convertl (char* buf, real value, int ndigit, int *decpt, int *sign, int fflag)
339 {
340         if ((*sign = negative(value)) != 0)
341              value = -value;
342 
343         *decpt = 9999;
344         if (isNaN(value))
345             return cast(char*)"nan\0";
346 
347         if (value is value.infinity)
348             return cast(char*)"inf\0";
349 
350         int exp10 = (value is 0) ? !fflag : cast(int) ceill(log10l(value));
351         if (exp10 < -4931) 
352             exp10 = -4931;	
353         value *= powl (10.0, -exp10);
354         if (value) 
355            {
356            while (value <  0.1) { value *= 10;  --exp10; }
357            while (value >= 1.0) { value /= 10;  ++exp10; }
358            }
359         assert(value == 0 || (0.1 <= value && value < 1.0));
360         //auto zero = pad ? int.max : 1;
361         auto zero = 1;
362         if (fflag) 
363            {
364            // if (! pad)
365                  zero = exp10;
366            if (ndigit + exp10 < 0) 
367               {
368               *decpt= -ndigit;
369               return cast(char*)"\0";
370               }
371            ndigit += exp10;
372            }
373         *decpt = exp10;
374         int ptr = 1;
375 
376         if (ndigit > real.dig) 
377             ndigit = real.dig;
378         //printf ("< flag %d, digits %d, exp10 %d, decpt %d\n", fflag, ndigit, exp10, *decpt);
379         while (ptr <= ndigit) 
380               {
381               real i = void;
382               value = modfl (value * 10, &i);
383               buf [ptr++]= cast(char)('0' + cast(int) i);
384               }
385 
386         if (value >= 0.5)
387             while (--ptr && ++buf[ptr] > '9')
388                    buf[ptr] = (ptr > zero) ? '\0' : '0';
389         else
390            for (auto i=ptr; i && --i > zero && buf[i] is '0';)
391                 buf[i] = '\0';
392 
393         if (ptr) 
394            {
395            buf [ndigit + 1] = '\0';
396            return buf + 1;
397            }
398         if (fflag) 
399            {
400            ++ndigit;
401            }
402         buf[0]= '1';
403         ++*decpt;
404         buf[ndigit]= '\0';
405         return buf;
406 }
407 }
408 
409 
410 /******************************************************************************
411 
412         David Gay's extended conversions between string and floating-point
413         numeric representations. Use these where you need extended accuracy
414         for convertions. 
415 
416         Note that this class requires the attendent file dtoa.c be compiled 
417         and linked to the application
418 
419 ******************************************************************************/
420 
421 version (float_dtoa)
422 {
423         private extern(C)
424         {
425         // these should be linked in via dtoa.c
426         double strtod (const(char*) s00, const(char*)* se);
427         char*  dtoa (double d, int mode, int ndigits, int* decpt, int* sign, char** rve);
428         }
429 
430         /**********************************************************************
431 
432                 Convert a formatted string of digits to a floating-
433                 point number. 
434 
435         **********************************************************************/
436 
437         NumType parse (const(char[]) src, size_t* ate=null)
438         {
439                 const(char)* end;
440 
441                 auto value = strtod (src.ptr, &end);
442                 assert (end <= src.ptr + src.length);
443                 if (ate)
444                     *ate = end - src.ptr;
445                 return value;
446         }
447 
448         /**********************************************************************
449 
450                 Convert a formatted string of digits to a floating-
451                 point number.
452 
453         **********************************************************************/
454 
455         NumType parse (const(wchar[]) src, size_t* ate=null)
456         {
457                 // cheesy hack to avoid pre-parsing :: max digits == 100
458                 char[100] tmp = void;
459                 auto p = tmp.ptr;
460                 auto e = p + tmp.length;
461                 foreach (c; src)
462                          if (p < e && (c & 0x80) is 0)
463                              *p++ = c;                        
464                          else
465                             break;
466 
467                 return parse (tmp[0..p-tmp.ptr], ate);
468         }
469 
470         /**********************************************************************
471 
472                 Convert a formatted string of digits to a floating-
473                 point number. 
474 
475         **********************************************************************/
476 
477         NumType parse (const(dchar[]) src, size_t* ate=null)
478         {
479                 // cheesy hack to avoid pre-parsing :: max digits == 100
480                 char[100] tmp = void;
481                 auto p = tmp.ptr;
482                 auto e = p + tmp.length;
483                 foreach (c; src)
484                          if (p < e && (c & 0x80) is 0)
485                              *p++ = c;
486                          else
487                             break;
488                 return parse (tmp[0..p-tmp.ptr], ate);
489         }
490 }
491 else
492 {
493 private import Integer = tango.text.convert.Integer;
494 
495 /******************************************************************************
496 
497         Convert a formatted string of digits to a floating-point number.
498         Good for general use, but use David Gay's dtoa package if serious
499         rounding adjustments should be applied.
500 
501 ******************************************************************************/
502 
503 NumType parse(T) (const(T[]) src, size_t* ate=null)
504 {
505         T               c;
506         const(T)*       p;
507         int             exp;
508         bool            sign;
509         uint            radix;
510         NumType         value = 0.0;
511 
512         static bool match (const(T)* aa, const(T[]) bb)
513         {
514                 foreach (b; bb)
515                         {
516                         auto a = cast(T)*aa++;
517                         if (a >= 'A' && a <= 'Z')
518                             a += 'a' - 'A';
519                         if (a != b)
520                             return false;
521                         }
522                 return true;
523         }
524 
525         // remove leading space, and sign
526         p = src.ptr + Integer.trim (src, sign, radix);
527 
528         // bail out if the string is empty
529         if (src.length is 0 || p > &src[$-1])
530             return NumType.nan;
531         c = *p;
532 
533         // handle non-decimal representations
534         if (radix != 10)
535            {
536            long v = Integer.parse (src, radix, ate); 
537            return cast(NumType) v;
538            }
539 
540         // set begin and end checks
541         auto begin = p;
542         auto end = src.ptr + src.length;
543 
544         // read leading digits; note that leading
545         // zeros are simply multiplied away
546         while (c >= '0' && c <= '9' && p < end)
547               {
548               value = value * 10 + (c - '0');
549               c = *++p;
550               }
551 
552         // gobble up the point
553         if (c is '.' && p < end)
554             c = *++p;
555 
556         // read fractional digits; note that we accumulate
557         // all digits ... very long numbers impact accuracy
558         // to a degree, but perhaps not as much as one might
559         // expect. A prior version limited the digit count,
560         // but did not show marked improvement. For maximum
561         // accuracy when reading and writing, use David Gay's
562         // dtoa package instead
563         while (c >= '0' && c <= '9' && p < end)
564               {
565               value = value * 10 + (c - '0');
566               c = *++p;
567               --exp;
568               } 
569 
570         // did we get something?
571         if (p > begin)
572            {
573            // parse base10 exponent?
574            if ((c is 'e' || c is 'E') && p < end )
575               {
576               size_t eaten;
577               exp += Integer.parse (src[(++p-src.ptr) .. $], 0, &eaten);
578               p += eaten;
579               }
580 
581            // adjust mantissa; note that the exponent has
582            // already been adjusted for fractional digits
583            if (exp < 0)
584                value /= pow10 (-exp);
585            else
586               value *= pow10 (exp);
587            }
588         else
589            if (end - p >= 3)
590                switch (*p)
591                       {
592                       case 'I': case 'i':
593                            if (match (p+1, "nf"))
594                               {
595                               value = value.infinity;
596                               p += 3;
597                               if (end - p >= 5 && match (p, "inity"))
598                                   p += 5;
599                               }
600                            break;
601 
602                       case 'N': case 'n':
603                            if (match (p+1, "an"))
604                               {
605                               value = value.nan;
606                               p += 3;
607                               }
608                            break;
609                       default:
610                            break;
611                       }
612 
613         // set parse length, and return value
614         if (ate)
615             *ate = p - src.ptr;
616 
617         if (sign)
618             value = -value;
619         return value;
620 }
621 
622 /******************************************************************************
623 
624         Internal function to convert an exponent specifier to a floating
625         point value.
626 
627 ******************************************************************************/
628 
629 private NumType pow10 (uint exp)
630 {
631         static  NumType[] Powers = 
632                 [
633                 1.0e1L,
634                 1.0e2L,
635                 1.0e4L,
636                 1.0e8L,
637                 1.0e16L,
638                 1.0e32L,
639                 1.0e64L,
640                 1.0e128L,
641                 1.0e256L,
642                 1.0e512L,
643                 1.0e1024L,
644                 1.0e2048L,
645                 1.0e4096L,
646                 1.0e8192L,
647                 ];
648 
649         if (exp >= 16384)
650             throw new IllegalArgumentException ("Float.pow10 :: exponent too large");
651 
652         NumType mult = 1.0;
653         foreach (NumType power; Powers)
654                 {
655                 if (exp & 1)
656                     mult *= power;
657                 if ((exp >>= 1) is 0)
658                      break;
659                 }
660         return mult;
661 }
662 }
663 
664 version (float_old)
665 {
666 /******************************************************************************
667 
668         Convert a float to a string. This produces pretty good results
669         for the most part, though one should use David Gay's dtoa package
670         for best accuracy.
671 
672         Note that the approach first normalizes a base10 mantissa, then
673         pulls digits from the left side whilst emitting them (rightward)
674         to the output.
675 
676         The e parameter controls the number of exponent places emitted, 
677         and can thus control where the output switches to the scientific 
678         notation. For example, setting e=2 for 0.01 or 10.0 would result
679         in normal output. Whereas setting e=1 would result in both those
680         values being rendered in scientific notation instead. Setting e
681         to 0 forces that notation on for everything.
682 
683         TODO: this should be replaced, as it is not sufficiently accurate 
684 
685 ******************************************************************************/
686 
687 T[] format(T, D=double, U=uint) (T[] dst, D x, U decimals=Dec, int e=Exp, bool pad=Pad)
688 {return format!(T)(dst, x, decimals, e, pad);}
689 
690 T[] format(T) (T[] dst, NumType x, uint decimals=Dec, int e=Exp, bool pad=Pad)
691 {
692         __gshared immutable immutable(T)[] inf = "-inf";
693         __gshared immutable immutable(T)[] nan = "-nan";
694 
695         // strip digits from the left of a normalized base-10 number
696         static int toDigit (ref NumType v, ref int count)
697         {
698                 int digit;
699 
700                 // Don't exceed max digits storable in a real
701                 // (-1 because the last digit is not always storable)
702                 if (--count <= 0)
703                     digit = 0;
704                 else
705                    {
706                    // remove leading digit, and bump
707                    digit = cast(int) v;
708                    v = (v - digit) * 10.0;
709                    }
710                 return digit + '0';
711         }
712 
713         // extract the sign
714         bool sign = negative (x);
715         if (sign)
716             x = -x;
717 
718         if (isNaN(x))
719             return sign ? nan : nan[1..$];
720 
721         if (x is x.infinity)
722             return sign ? inf : inf[1..$];
723 
724         // assume no exponent
725         int exp = 0;
726         int abs = 0;
727 
728         // don't scale if zero
729         if (x > 0.0)
730            {
731            // extract base10 exponent
732            exp = cast(int) log10l (x);
733 
734            // round up a bit
735            auto d = decimals;
736            if (exp < 0)
737                d -= exp;
738            x += 0.5 / pow10 (d);
739 
740            // normalize base10 mantissa (0 < m < 10)
741            abs = exp = cast(int) log10l (x);
742            if (exp > 0)
743                x /= pow10 (exp);
744            else
745               abs = -exp;
746 
747            // switch to exponent display as necessary
748            if (abs >= e)
749                e = 0; 
750            }
751 
752         T* p = dst.ptr;
753         int count = NumType.dig;
754 
755         // emit sign
756         if (sign)
757             *p++ = '-';
758         
759         // are we doing +/-exp format?
760         if (e is 0)
761            {
762            assert (dst.length > decimals + 7);
763 
764            if (exp < 0)
765                x *= pow10 (abs+1);
766 
767            // emit first digit, and decimal point
768            *p++ = cast(T) toDigit (x, count);
769            if (decimals)
770               {
771               *p++ = '.';
772 
773               // emit rest of mantissa
774               while (decimals-- > 0)
775                      *p++ = cast(T) toDigit (x, count);
776               
777               if (pad is false)
778                  {
779                  while (*(p-1) is '0')
780                         --p;
781                  if (*(p-1) is '.')
782                      --p;
783                  }
784               }
785 
786            // emit exponent, if non zero
787            if (abs)
788               {
789               *p++ = 'e';
790               *p++ = (exp < 0) ? '-' : '+';
791               if (abs >= 1000)
792                  {
793                  *p++ = cast(T)((abs/1000) + '0');
794                  abs %= 1000;
795                  *p++ = cast(T)((abs/100) + '0');
796                  abs %= 100;
797                  }
798               else
799                  if (abs >= 100)
800                     {
801                     *p++ = cast(T)((abs/100) + '0');
802                     abs %= 100;
803                     }
804               *p++ = cast(T)((abs/10) + '0');
805               *p++ = cast(T)((abs%10) + '0');
806               }
807            }
808         else
809            {
810            assert (dst.length >= (((exp < 0) ? 0 : exp) + decimals + 1));
811 
812            // if fraction only, emit a leading zero
813            if (exp < 0)
814               {
815               x *= pow10 (abs);
816               *p++ = '0';
817               }
818            else
819               // emit all digits to the left of point
820               for (; exp >= 0; --exp)
821                      *p++ = cast(T )toDigit (x, count);
822 
823            // emit point
824            if (decimals)
825               {
826               *p++ = '.';
827 
828               // emit leading fractional zeros?
829               for (++exp; exp < 0 && decimals > 0; --decimals, ++exp)
830                    *p++ = '0';
831 
832               // output remaining digits, if any. Trailing
833               // zeros are also returned from toDigit()
834               while (decimals-- > 0)
835                      *p++ = cast(T) toDigit (x, count);
836 
837               if (pad is false)
838                  {
839                  while (*(p-1) is '0')
840                         --p;
841                  if (*(p-1) is '.')
842                      --p;
843                  }
844               }
845            }
846 
847         return dst [0..(p - dst.ptr)];
848 }
849 }
850 
851 /******************************************************************************
852 
853 ******************************************************************************/
854 
855 debug (UnitTest)
856 {
857         import tango.io.Console;
858       
859         unittest
860         {
861                 char[164] tmp;
862 
863                 auto f = parse ("nan");
864                 assert (format(tmp, f) == "nan");
865                 f = parse ("inf");
866                 assert (format(tmp, f) == "inf");
867                 f = parse ("-nan");
868                 assert (format(tmp, f) == "-nan");
869                 f = parse (" -inf");
870                 assert (format(tmp, f) == "-inf");
871 
872                 assert (format (tmp, 3.14159, 6) == "3.14159");
873                 assert (format (tmp, 3.14159, 4) == "3.1416");
874 
875                 assert (parse ("3.5".dup) == 3.5);
876                 assert (format(tmp, parse ("3.14159".dup), 6) == "3.14159");
877                 assert (format(tmp, 0.09999, 2,  0, true) == "1.00e-01");
878         }
879 }
880 
881 
882 debug (Float)
883 {
884         import tango.io.Console;
885 
886         void main() 
887         {
888                 char[500] tmp;
889 /+
890                 Cout (format(tmp, NumType.max)).newline;
891                 Cout (format(tmp, -NumType.nan)).newline;
892                 Cout (format(tmp, -NumType.infinity)).newline;
893                 Cout (format(tmp, toFloat("nan"w))).newline;
894                 Cout (format(tmp, toFloat("-nan"d))).newline;
895                 Cout (format(tmp, toFloat("inf"))).newline;
896                 Cout (format(tmp, toFloat("-inf"))).newline;
897 +/
898                 Cout (format(tmp, toFloat ("0.000000e+00"))).newline;
899                 Cout (format(tmp, toFloat("0x8000000000000000"))).newline;
900                 Cout (format(tmp, 1)).newline;
901                 Cout (format(tmp, -0)).newline;
902                 Cout (format(tmp, 0.000001)).newline.newline;
903 
904                 Cout (format(tmp, 3.14159, 6, 0)).newline;
905                 Cout (format(tmp, 3.0e10, 6, 3)).newline;
906                 Cout (format(tmp, 314159, 6)).newline;
907                 Cout (format(tmp, 314159123213, 6, 15)).newline;
908                 Cout (format(tmp, 3.14159, 6, 2)).newline;
909                 Cout (format(tmp, 3.14159, 3, 2)).newline;
910                 Cout (format(tmp, 0.00003333, 6, 2)).newline;
911                 Cout (format(tmp, 0.00333333, 6, 3)).newline;
912                 Cout (format(tmp, 0.03333333, 6, 2)).newline;
913                 Cout.newline;
914 
915                 Cout (format(tmp, -3.14159, 6, 0)).newline;
916                 Cout (format(tmp, -3e100, 6, 3)).newline;
917                 Cout (format(tmp, -314159, 6)).newline;
918                 Cout (format(tmp, -314159123213, 6, 15)).newline;
919                 Cout (format(tmp, -3.14159, 6, 2)).newline;
920                 Cout (format(tmp, -3.14159, 2, 2)).newline;
921                 Cout (format(tmp, -0.00003333, 6, 2)).newline;
922                 Cout (format(tmp, -0.00333333, 6, 3)).newline;
923                 Cout (format(tmp, -0.03333333, 6, 2)).newline;
924                 Cout.newline;
925 
926                 Cout (format(tmp, -0.9999999, 7, 3)).newline;
927                 Cout (format(tmp, -3.0e100, 6, 3)).newline;
928                 Cout ((format(tmp, 1.0, 6))).newline;
929                 Cout ((format(tmp, 30, 6))).newline;
930                 Cout ((format(tmp, 3.14159, 6, 0))).newline;
931                 Cout ((format(tmp, 3e100, 6, 3))).newline;
932                 Cout ((format(tmp, 314159, 6))).newline;
933                 Cout ((format(tmp, 314159123213.0, 3, 15))).newline;
934                 Cout ((format(tmp, 3.14159, 6, 2))).newline;
935                 Cout ((format(tmp, 3.14159, 4, 2))).newline;
936                 Cout ((format(tmp, 0.00003333, 6, 2))).newline;
937                 Cout ((format(tmp, 0.00333333, 6, 3))).newline;
938                 Cout ((format(tmp, 0.03333333, 6, 2))).newline;
939                 Cout (format(tmp, NumType.min, 6)).newline;
940                 Cout (format(tmp, -1)).newline;
941                 Cout (format(tmp, toFloat(format(tmp, -1)))).newline;
942                 Cout.newline;
943         }
944 }