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 }