1/* Copyright (C) 2007-2022 Free Software Foundation, Inc. 2 Contributed by Andy Vaught 3 Write float code factoring to this file by Jerry DeLisle 4 F2003 I/O support contributed by Jerry DeLisle 5 6This file is part of the GNU Fortran runtime library (libgfortran). 7 8Libgfortran is free software; you can redistribute it and/or modify 9it under the terms of the GNU General Public License as published by 10the Free Software Foundation; either version 3, or (at your option) 11any later version. 12 13Libgfortran is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16GNU General Public License for more details. 17 18Under Section 7 of GPL version 3, you are granted additional 19permissions described in the GCC Runtime Library Exception, version 203.1, as published by the Free Software Foundation. 21 22You should have received a copy of the GNU General Public License and 23a copy of the GCC Runtime Library Exception along with this program; 24see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 25<http://www.gnu.org/licenses/>. */ 26 27#include "config.h" 28 29typedef enum 30{ S_NONE, S_MINUS, S_PLUS } 31sign_t; 32 33/* Given a flag that indicates if a value is negative or not, return a 34 sign_t that gives the sign that we need to produce. */ 35 36static sign_t 37calculate_sign (st_parameter_dt *dtp, int negative_flag) 38{ 39 sign_t s = S_NONE; 40 41 if (negative_flag) 42 s = S_MINUS; 43 else 44 switch (dtp->u.p.sign_status) 45 { 46 case SIGN_SP: /* Show sign. */ 47 s = S_PLUS; 48 break; 49 case SIGN_SS: /* Suppress sign. */ 50 s = S_NONE; 51 break; 52 case SIGN_S: /* Processor defined. */ 53 case SIGN_UNSPECIFIED: 54 s = options.optional_plus ? S_PLUS : S_NONE; 55 break; 56 } 57 58 return s; 59} 60 61 62/* Determine the precision except for EN format. For G format, 63 determines an upper bound to be used for sizing the buffer. */ 64 65static int 66determine_precision (st_parameter_dt * dtp, const fnode * f, int len) 67{ 68 int precision = f->u.real.d; 69 70 switch (f->format) 71 { 72 case FMT_F: 73 case FMT_G: 74 precision += dtp->u.p.scale_factor; 75 break; 76 case FMT_ES: 77 /* Scale factor has no effect on output. */ 78 break; 79 case FMT_E: 80 case FMT_D: 81 /* See F2008 10.7.2.3.3.6 */ 82 if (dtp->u.p.scale_factor <= 0) 83 precision += dtp->u.p.scale_factor - 1; 84 break; 85 default: 86 return -1; 87 } 88 89 /* If the scale factor has a large negative value, we must do our 90 own rounding? Use ROUND='NEAREST', which should be what snprintf 91 is using as well. */ 92 if (precision < 0 && 93 (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED 94 || dtp->u.p.current_unit->round_status == ROUND_PROCDEFINED)) 95 dtp->u.p.current_unit->round_status = ROUND_NEAREST; 96 97 /* Add extra guard digits up to at least full precision when we do 98 our own rounding. */ 99 if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED 100 && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED) 101 { 102 precision += 2 * len + 4; 103 if (precision < 0) 104 precision = 0; 105 } 106 107 return precision; 108} 109 110 111/* Build a real number according to its format which is FMT_G free. */ 112 113static void 114build_float_string (st_parameter_dt *dtp, const fnode *f, char *buffer, 115 size_t size, int nprinted, int precision, int sign_bit, 116 bool zero_flag, int npad, int default_width, char *result, 117 size_t *len) 118{ 119 char *put; 120 char *digits; 121 int e, w, d, p, i; 122 char expchar, rchar; 123 format_token ft; 124 /* Number of digits before the decimal point. */ 125 int nbefore; 126 /* Number of zeros after the decimal point. */ 127 int nzero; 128 /* Number of digits after the decimal point. */ 129 int nafter; 130 int leadzero; 131 int nblanks; 132 int ndigits, edigits; 133 sign_t sign; 134 135 ft = f->format; 136 if (f->u.real.w == DEFAULT_WIDTH) 137 /* This codepath can only be reached with -fdec-format-defaults. */ 138 { 139 w = default_width; 140 d = precision; 141 } 142 else 143 { 144 w = f->u.real.w; 145 d = f->u.real.d; 146 } 147 p = dtp->u.p.scale_factor; 148 *len = 0; 149 150 rchar = '5'; 151 152 /* We should always know the field width and precision. */ 153 if (d < 0) 154 internal_error (&dtp->common, "Unspecified precision"); 155 156 sign = calculate_sign (dtp, sign_bit); 157 158 /* Calculate total number of digits. */ 159 if (ft == FMT_F) 160 ndigits = nprinted - 2; 161 else 162 ndigits = precision + 1; 163 164 /* Read the exponent back in. */ 165 if (ft != FMT_F) 166 e = atoi (&buffer[ndigits + 3]) + 1; 167 else 168 e = 0; 169 170 /* Make sure zero comes out as 0.0e0. */ 171 if (zero_flag) 172 e = 0; 173 174 /* Normalize the fractional component. */ 175 if (ft != FMT_F) 176 { 177 buffer[2] = buffer[1]; 178 digits = &buffer[2]; 179 } 180 else 181 digits = &buffer[1]; 182 183 /* Figure out where to place the decimal point. */ 184 switch (ft) 185 { 186 case FMT_F: 187 nbefore = ndigits - precision; 188 if ((w > 0) && (nbefore > (int) size)) 189 { 190 *len = w; 191 star_fill (result, w); 192 result[w] = '\0'; 193 return; 194 } 195 /* Make sure the decimal point is a '.'; depending on the 196 locale, this might not be the case otherwise. */ 197 digits[nbefore] = '.'; 198 if (p != 0) 199 { 200 if (p > 0) 201 { 202 memmove (digits + nbefore, digits + nbefore + 1, p); 203 digits[nbefore + p] = '.'; 204 nbefore += p; 205 nafter = d; 206 nzero = 0; 207 } 208 else /* p < 0 */ 209 { 210 if (nbefore + p >= 0) 211 { 212 nzero = 0; 213 memmove (digits + nbefore + p + 1, digits + nbefore + p, -p); 214 nbefore += p; 215 digits[nbefore] = '.'; 216 nafter = d; 217 } 218 else 219 { 220 nzero = -(nbefore + p); 221 memmove (digits + 1, digits, nbefore); 222 nafter = d - nzero; 223 if (nafter == 0 && d > 0) 224 { 225 /* This is needed to get the correct rounding. */ 226 memmove (digits + 1, digits, ndigits - 1); 227 digits[1] = '0'; 228 nafter = 1; 229 nzero = d - 1; 230 } 231 else if (nafter < 0) 232 { 233 /* Reset digits to 0 in order to get correct rounding 234 towards infinity. */ 235 for (i = 0; i < ndigits; i++) 236 digits[i] = '0'; 237 digits[ndigits - 1] = '1'; 238 nafter = d; 239 nzero = 0; 240 } 241 nbefore = 0; 242 } 243 } 244 } 245 else 246 { 247 nzero = 0; 248 nafter = d; 249 } 250 251 while (digits[0] == '0' && nbefore > 0) 252 { 253 digits++; 254 nbefore--; 255 ndigits--; 256 } 257 258 expchar = 0; 259 /* If we need to do rounding ourselves, get rid of the dot by 260 moving the fractional part. */ 261 if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED 262 && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED) 263 memmove (digits + nbefore, digits + nbefore + 1, ndigits - nbefore); 264 break; 265 266 case FMT_E: 267 case FMT_D: 268 i = dtp->u.p.scale_factor; 269 if (d < 0 && p == 0) 270 { 271 generate_error (&dtp->common, LIBERROR_FORMAT, "Precision not " 272 "greater than zero in format specifier 'E' or 'D'"); 273 return; 274 } 275 if (p <= -d || p >= d + 2) 276 { 277 generate_error (&dtp->common, LIBERROR_FORMAT, "Scale factor " 278 "out of range in format specifier 'E' or 'D'"); 279 return; 280 } 281 282 if (!zero_flag) 283 e -= p; 284 if (p < 0) 285 { 286 nbefore = 0; 287 nzero = -p; 288 nafter = d + p; 289 } 290 else if (p > 0) 291 { 292 nbefore = p; 293 nzero = 0; 294 nafter = (d - p) + 1; 295 } 296 else /* p == 0 */ 297 { 298 nbefore = 0; 299 nzero = 0; 300 nafter = d; 301 } 302 303 if (ft == FMT_E) 304 expchar = 'E'; 305 else 306 expchar = 'D'; 307 break; 308 309 case FMT_EN: 310 /* The exponent must be a multiple of three, with 1-3 digits before 311 the decimal point. */ 312 if (!zero_flag) 313 e--; 314 if (e >= 0) 315 nbefore = e % 3; 316 else 317 { 318 nbefore = (-e) % 3; 319 if (nbefore != 0) 320 nbefore = 3 - nbefore; 321 } 322 e -= nbefore; 323 nbefore++; 324 nzero = 0; 325 nafter = d; 326 expchar = 'E'; 327 break; 328 329 case FMT_ES: 330 if (!zero_flag) 331 e--; 332 nbefore = 1; 333 nzero = 0; 334 nafter = d; 335 expchar = 'E'; 336 break; 337 338 default: 339 /* Should never happen. */ 340 internal_error (&dtp->common, "Unexpected format token"); 341 } 342 343 if (zero_flag) 344 goto skip; 345 346 /* Round the value. The value being rounded is an unsigned magnitude. */ 347 switch (dtp->u.p.current_unit->round_status) 348 { 349 /* For processor defined and unspecified rounding we use 350 snprintf to print the exact number of digits needed, and thus 351 let snprintf handle the rounding. On system claiming support 352 for IEEE 754, this ought to be round to nearest, ties to 353 even, corresponding to the Fortran ROUND='NEAREST'. */ 354 case ROUND_PROCDEFINED: 355 case ROUND_UNSPECIFIED: 356 case ROUND_ZERO: /* Do nothing and truncation occurs. */ 357 goto skip; 358 case ROUND_UP: 359 if (sign_bit) 360 goto skip; 361 goto updown; 362 case ROUND_DOWN: 363 if (!sign_bit) 364 goto skip; 365 goto updown; 366 case ROUND_NEAREST: 367 /* Round compatible unless there is a tie. A tie is a 5 with 368 all trailing zero's. */ 369 i = nafter + nbefore; 370 if (digits[i] == '5') 371 { 372 for(i++ ; i < ndigits; i++) 373 { 374 if (digits[i] != '0') 375 goto do_rnd; 376 } 377 /* It is a tie so round to even. */ 378 switch (digits[nafter + nbefore - 1]) 379 { 380 case '1': 381 case '3': 382 case '5': 383 case '7': 384 case '9': 385 /* If odd, round away from zero to even. */ 386 break; 387 default: 388 /* If even, skip rounding, truncate to even. */ 389 goto skip; 390 } 391 } 392 /* Fall through. */ 393 /* The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */ 394 case ROUND_COMPATIBLE: 395 rchar = '5'; 396 goto do_rnd; 397 } 398 399 updown: 400 401 rchar = '0'; 402 /* Do not reset nbefore for FMT_F and FMT_EN. */ 403 if (ft != FMT_F && ft !=FMT_EN && w > 0 && d == 0 && p == 0) 404 nbefore = 1; 405 /* Scan for trailing zeros to see if we really need to round it. */ 406 for(i = nbefore + nafter; i < ndigits; i++) 407 { 408 if (digits[i] != '0') 409 goto do_rnd; 410 } 411 goto skip; 412 413 do_rnd: 414 415 if (nbefore + nafter == 0) 416 /* Handle the case Fw.0 and value < 1.0 */ 417 { 418 ndigits = 0; 419 if (digits[0] >= rchar) 420 { 421 /* We rounded to zero but shouldn't have */ 422 nbefore = 1; 423 digits--; 424 digits[0] = '1'; 425 ndigits = 1; 426 } 427 } 428 else if (nbefore + nafter < ndigits) 429 { 430 i = ndigits = nbefore + nafter; 431 if (digits[i] >= rchar) 432 { 433 /* Propagate the carry. */ 434 for (i--; i >= 0; i--) 435 { 436 if (digits[i] != '9') 437 { 438 digits[i]++; 439 break; 440 } 441 digits[i] = '0'; 442 } 443 444 if (i < 0) 445 { 446 /* The carry overflowed. Fortunately we have some spare 447 space at the start of the buffer. We may discard some 448 digits, but this is ok because we already know they are 449 zero. */ 450 digits--; 451 digits[0] = '1'; 452 if (ft == FMT_F) 453 { 454 if (nzero > 0) 455 { 456 nzero--; 457 nafter++; 458 } 459 else 460 nbefore++; 461 } 462 else if (ft == FMT_EN) 463 { 464 nbefore++; 465 if (nbefore == 4) 466 { 467 nbefore = 1; 468 e += 3; 469 } 470 } 471 else 472 e++; 473 } 474 } 475 } 476 477 skip: 478 479 /* Calculate the format of the exponent field. */ 480 if (expchar && !(dtp->u.p.g0_no_blanks && e == 0)) 481 { 482 edigits = 1; 483 for (i = abs (e); i >= 10; i /= 10) 484 edigits++; 485 486 if (f->u.real.e < 0) 487 { 488 /* Width not specified. Must be no more than 3 digits. */ 489 if (e > 999 || e < -999) 490 edigits = -1; 491 else 492 { 493 edigits = 4; 494 if (e > 99 || e < -99) 495 expchar = ' '; 496 } 497 } 498 else if (f->u.real.e == 0) 499 { 500 /* Zero width specified, no leading zeros in exponent */ 501 if (e > 999 || e < -999) 502 edigits = 6; 503 else if (e > 99 || e < -99) 504 edigits = 5; 505 else if (e > 9 || e < -9) 506 edigits = 4; 507 else 508 edigits = 3; 509 } 510 else 511 { 512 /* Exponent width specified, check it is wide enough. */ 513 if (edigits > f->u.real.e) 514 edigits = -1; 515 else 516 edigits = f->u.real.e + 2; 517 } 518 } 519 else 520 edigits = 0; 521 522 /* Scan the digits string and count the number of zeros. If we make it 523 all the way through the loop, we know the value is zero after the 524 rounding completed above. */ 525 int hasdot = 0; 526 for (i = 0; i < ndigits + hasdot; i++) 527 { 528 if (digits[i] == '.') 529 hasdot = 1; 530 else if (digits[i] != '0') 531 break; 532 } 533 534 /* To format properly, we need to know if the rounded result is zero and if 535 so, we set the zero_flag which may have been already set for 536 actual zero. */ 537 if (i == ndigits + hasdot) 538 { 539 zero_flag = true; 540 /* The output is zero, so set the sign according to the sign bit unless 541 -fno-sign-zero was specified. */ 542 if (compile_options.sign_zero == 1) 543 sign = calculate_sign (dtp, sign_bit); 544 else 545 sign = calculate_sign (dtp, 0); 546 } 547 548 /* Pick a field size if none was specified, taking into account small 549 values that may have been rounded to zero. */ 550 if (w <= 0) 551 { 552 if (zero_flag) 553 w = d + (sign != S_NONE ? 2 : 1) + (d == 0 ? 1 : 0); 554 else 555 { 556 w = nbefore + nzero + nafter + (sign != S_NONE ? 2 : 1); 557 w = w == 1 ? 2 : w; 558 } 559 } 560 561 /* Work out how much padding is needed. */ 562 nblanks = w - (nbefore + nzero + nafter + edigits + 1); 563 if (sign != S_NONE) 564 nblanks--; 565 566 /* See if we have space for a zero before the decimal point. */ 567 if (nbefore == 0 && nblanks > 0) 568 { 569 leadzero = 1; 570 nblanks--; 571 } 572 else 573 leadzero = 0; 574 575 if (dtp->u.p.g0_no_blanks) 576 { 577 w -= nblanks; 578 nblanks = 0; 579 } 580 581 /* Create the final float string. */ 582 *len = w + npad; 583 put = result; 584 585 /* Check the value fits in the specified field width. */ 586 if (nblanks < 0 || edigits == -1 || w == 1 || (w == 2 && sign != S_NONE)) 587 { 588 star_fill (put, *len); 589 return; 590 } 591 592 /* Pad to full field width. */ 593 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank) 594 { 595 memset (put, ' ', nblanks); 596 put += nblanks; 597 } 598 599 /* Set the initial sign (if any). */ 600 if (sign == S_PLUS) 601 *(put++) = '+'; 602 else if (sign == S_MINUS) 603 *(put++) = '-'; 604 605 /* Set an optional leading zero. */ 606 if (leadzero) 607 *(put++) = '0'; 608 609 /* Set the part before the decimal point, padding with zeros. */ 610 if (nbefore > 0) 611 { 612 if (nbefore > ndigits) 613 { 614 i = ndigits; 615 memcpy (put, digits, i); 616 ndigits = 0; 617 while (i < nbefore) 618 put[i++] = '0'; 619 } 620 else 621 { 622 i = nbefore; 623 memcpy (put, digits, i); 624 ndigits -= i; 625 } 626 627 digits += i; 628 put += nbefore; 629 } 630 631 /* Set the decimal point. */ 632 *(put++) = dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? '.' : ','; 633 if (ft == FMT_F 634 && (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED 635 || dtp->u.p.current_unit->round_status == ROUND_PROCDEFINED)) 636 digits++; 637 638 /* Set leading zeros after the decimal point. */ 639 if (nzero > 0) 640 { 641 for (i = 0; i < nzero; i++) 642 *(put++) = '0'; 643 } 644 645 /* Set digits after the decimal point, padding with zeros. */ 646 if (ndigits >= 0 && nafter > 0) 647 { 648 if (nafter > ndigits) 649 i = ndigits; 650 else 651 i = nafter; 652 653 if (i > 0) 654 memcpy (put, digits, i); 655 while (i < nafter) 656 put[i++] = '0'; 657 658 digits += i; 659 ndigits -= i; 660 put += nafter; 661 } 662 663 /* Set the exponent. */ 664 if (expchar && !(dtp->u.p.g0_no_blanks && e == 0)) 665 { 666 if (expchar != ' ') 667 { 668 *(put++) = expchar; 669 edigits--; 670 } 671 snprintf (buffer, size, "%+0*d", edigits, e); 672 memcpy (put, buffer, edigits); 673 put += edigits; 674 } 675 676 if (dtp->u.p.no_leading_blank) 677 { 678 memset (put , ' ' , nblanks); 679 dtp->u.p.no_leading_blank = 0; 680 put += nblanks; 681 } 682 683 if (npad > 0 && !dtp->u.p.g0_no_blanks) 684 { 685 memset (put , ' ' , npad); 686 put += npad; 687 } 688 689 /* NULL terminate the string. */ 690 *put = '\0'; 691 692 return; 693} 694 695 696/* Write "Infinite" or "Nan" as appropriate for the given format. */ 697 698static void 699build_infnan_string (st_parameter_dt *dtp, const fnode *f, int isnan_flag, 700 int sign_bit, char *p, size_t *len) 701{ 702 char fin; 703 int nb = 0; 704 sign_t sign; 705 int mark; 706 707 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z) 708 { 709 sign = calculate_sign (dtp, sign_bit); 710 mark = (sign == S_PLUS || sign == S_MINUS) ? 8 : 7; 711 712 nb = f->u.real.w; 713 *len = nb; 714 715 /* If the field width is zero, the processor must select a width 716 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */ 717 718 if ((nb == 0) || dtp->u.p.g0_no_blanks) 719 { 720 if (isnan_flag) 721 nb = 3; 722 else 723 nb = (sign == S_PLUS || sign == S_MINUS) ? 4 : 3; 724 *len = nb; 725 } 726 727 p[*len] = '\0'; 728 if (nb < 3) 729 { 730 memset (p, '*', nb); 731 return; 732 } 733 734 memset(p, ' ', nb); 735 736 if (!isnan_flag) 737 { 738 if (sign_bit) 739 { 740 /* If the sign is negative and the width is 3, there is 741 insufficient room to output '-Inf', so output asterisks */ 742 if (nb == 3) 743 { 744 memset (p, '*', nb); 745 return; 746 } 747 /* The negative sign is mandatory */ 748 fin = '-'; 749 } 750 else 751 /* The positive sign is optional, but we output it for 752 consistency */ 753 fin = '+'; 754 755 if (nb > mark) 756 /* We have room, so output 'Infinity' */ 757 memcpy(p + nb - 8, "Infinity", 8); 758 else 759 /* For the case of width equals 8, there is not enough room 760 for the sign and 'Infinity' so we go with 'Inf' */ 761 memcpy(p + nb - 3, "Inf", 3); 762 763 if (sign == S_PLUS || sign == S_MINUS) 764 { 765 if (nb < 9 && nb > 3) 766 p[nb - 4] = fin; /* Put the sign in front of Inf */ 767 else if (nb > 8) 768 p[nb - 9] = fin; /* Put the sign in front of Infinity */ 769 } 770 } 771 else 772 memcpy(p + nb - 3, "NaN", 3); 773 } 774} 775 776 777/* Returns the value of 10**d. */ 778 779#define CALCULATE_EXP(x) \ 780static GFC_REAL_ ## x \ 781calculate_exp_ ## x (int d)\ 782{\ 783 int i;\ 784 GFC_REAL_ ## x r = 1.0;\ 785 for (i = 0; i< (d >= 0 ? d : -d); i++)\ 786 r *= 10;\ 787 r = (d >= 0) ? r : 1.0 / r;\ 788 return r;\ 789} 790 791CALCULATE_EXP(4) 792 793CALCULATE_EXP(8) 794 795#ifdef HAVE_GFC_REAL_10 796CALCULATE_EXP(10) 797#endif 798 799#ifdef HAVE_GFC_REAL_16 800CALCULATE_EXP(16) 801#endif 802 803#ifdef HAVE_GFC_REAL_17 804CALCULATE_EXP(17) 805#endif 806#undef CALCULATE_EXP 807 808 809/* Define macros to build code for format_float. */ 810 811 /* Note: Before output_float is called, snprintf is used to print to buffer the 812 number in the format +D.DDDDe+ddd. 813 814 # The result will always contain a decimal point, even if no 815 digits follow it 816 817 - The converted value is to be left adjusted on the field boundary 818 819 + A sign (+ or -) always be placed before a number 820 821 * prec is used as the precision 822 823 e format: [-]d.ddde±dd where there is one digit before the 824 decimal-point character and the number of digits after it is 825 equal to the precision. The exponent always contains at least two 826 digits; if the value is zero, the exponent is 00. */ 827 828 829#define TOKENPASTE(x, y) TOKENPASTE2(x, y) 830#define TOKENPASTE2(x, y) x ## y 831 832#define DTOA(suff,prec,val) TOKENPASTE(DTOA2,suff)(prec,val) 833 834#define DTOA2(prec,val) \ 835snprintf (buffer, size, "%+-#.*e", (prec), (val)) 836 837#define DTOA2L(prec,val) \ 838snprintf (buffer, size, "%+-#.*Le", (prec), (val)) 839 840 841#if defined(HAVE_GFC_REAL_17) 842# if defined(POWER_IEEE128) 843# define DTOA2Q(prec,val) \ 844__snprintfieee128 (buffer, size, "%+-#.*Le", (prec), (val)) 845# else 846# define DTOA2Q(prec,val) \ 847quadmath_snprintf (buffer, size, "%+-#.*Qe", (prec), (val)) 848# endif 849#elif defined(GFC_REAL_16_IS_FLOAT128) 850# define DTOA2Q(prec,val) \ 851quadmath_snprintf (buffer, size, "%+-#.*Qe", (prec), (val)) 852#endif 853 854#define FDTOA(suff,prec,val) TOKENPASTE(FDTOA2,suff)(prec,val) 855 856/* For F format, we print to the buffer with f format. */ 857#define FDTOA2(prec,val) \ 858snprintf (buffer, size, "%+-#.*f", (prec), (val)) 859 860#define FDTOA2L(prec,val) \ 861snprintf (buffer, size, "%+-#.*Lf", (prec), (val)) 862 863 864#if defined(HAVE_GFC_REAL_17) 865# if defined(POWER_IEEE128) 866# define FDTOA2Q(prec,val) \ 867__snprintfieee128 (buffer, size, "%+-#.*Lf", (prec), (val)) 868# else 869# define FDTOA2Q(prec,val) \ 870quadmath_snprintf (buffer, size, "%+-#.*Qf", (prec), (val)) 871# endif 872#elif defined(GFC_REAL_16_IS_FLOAT128) 873# define FDTOA2Q(prec,val) \ 874quadmath_snprintf (buffer, size, "%+-#.*Qf", (prec), (val)) 875#endif 876 877 878/* EN format is tricky since the number of significant digits depends 879 on the magnitude. Solve it by first printing a temporary value and 880 figure out the number of significant digits from the printed 881 exponent. Values y, 0.95*10.0**e <= y <10.0**e, are rounded to 882 10.0**e even when the final result will not be rounded to 10.0**e. 883 For these values the exponent returned by atoi has to be decremented 884 by one. The values y in the ranges 885 (1000.0-0.5*10.0**(-d))*10.0**(3*n) <= y < 10.0*(3*(n+1)) 886 (100.0-0.5*10.0**(-d))*10.0**(3*n) <= y < 10.0*(3*n+2) 887 (10.0-0.5*10.0**(-d))*10.0**(3*n) <= y < 10.0*(3*n+1) 888 are correctly rounded respectively to 1.0...0*10.0*(3*(n+1)), 889 100.0...0*10.0*(3*n), and 10.0...0*10.0*(3*n), where 0...0 890 represents d zeroes, by the lines 279 to 297. */ 891#define EN_PREC(x,y)\ 892{\ 893 volatile GFC_REAL_ ## x tmp, one = 1.0;\ 894 tmp = * (GFC_REAL_ ## x *)source;\ 895 if (isfinite (tmp))\ 896 {\ 897 nprinted = DTOA(y,0,tmp);\ 898 int e = atoi (&buffer[4]);\ 899 if (buffer[1] == '1')\ 900 {\ 901 tmp = (calculate_exp_ ## x (-e)) * tmp;\ 902 tmp = one - (tmp < 0 ? -tmp : tmp);\ 903 if (tmp > 0)\ 904 e = e - 1;\ 905 }\ 906 nbefore = e%3;\ 907 if (nbefore < 0)\ 908 nbefore = 3 + nbefore;\ 909 }\ 910 else\ 911 nprinted = -1;\ 912}\ 913 914static int 915determine_en_precision (st_parameter_dt *dtp, const fnode *f, 916 const char *source, int len) 917{ 918 int nprinted; 919 char buffer[10]; 920 const size_t size = 10; 921 int nbefore; /* digits before decimal point - 1. */ 922 923 switch (len) 924 { 925 case 4: 926 EN_PREC(4,) 927 break; 928 929 case 8: 930 EN_PREC(8,) 931 break; 932 933#ifdef HAVE_GFC_REAL_10 934 case 10: 935 EN_PREC(10,L) 936 break; 937#endif 938#ifdef HAVE_GFC_REAL_16 939 case 16: 940# ifdef GFC_REAL_16_IS_FLOAT128 941 EN_PREC(16,Q) 942# else 943 EN_PREC(16,L) 944# endif 945 break; 946#endif 947#ifdef HAVE_GFC_REAL_17 948 case 17: 949 EN_PREC(17,Q) 950#endif 951 break; 952 default: 953 internal_error (NULL, "bad real kind"); 954 } 955 956 if (nprinted == -1) 957 return -1; 958 959 int prec = f->u.real.d + nbefore; 960 if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED 961 && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED) 962 prec += 2 * len + 4; 963 return prec; 964} 965 966 967/* Generate corresponding I/O format. and output. 968 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran 969 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is: 970 971 Data Magnitude Equivalent Conversion 972 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee] 973 m = 0 F(w-n).(d-1), n' ' 974 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' ' 975 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' ' 976 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' ' 977 ................ .......... 978 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ') 979 m >= 10**d-0.5 Ew.d[Ee] 980 981 notes: for Gw.d , n' ' means 4 blanks 982 for Gw.dEe, n' ' means e+2 blanks 983 for rounding modes adjustment, r, See Fortran F2008 10.7.5.2.2 984 the asm volatile is required for 32-bit x86 platforms. */ 985#define FORMAT_FLOAT(x,y)\ 986{\ 987 int npad = 0;\ 988 GFC_REAL_ ## x m;\ 989 m = * (GFC_REAL_ ## x *)source;\ 990 sign_bit = signbit (m);\ 991 if (!isfinite (m))\ 992 { \ 993 build_infnan_string (dtp, f, isnan (m), sign_bit, result, res_len);\ 994 return;\ 995 }\ 996 m = sign_bit ? -m : m;\ 997 zero_flag = (m == 0.0);\ 998 if (f->format == FMT_G)\ 999 {\ 1000 int e = f->u.real.e;\ 1001 int d = f->u.real.d;\ 1002 int w = f->u.real.w;\ 1003 fnode newf;\ 1004 GFC_REAL_ ## x exp_d, r = 0.5, r_sc;\ 1005 int low, high, mid;\ 1006 int ubound, lbound;\ 1007 int save_scale_factor;\ 1008 volatile GFC_REAL_ ## x temp;\ 1009 save_scale_factor = dtp->u.p.scale_factor;\ 1010 if (w == DEFAULT_WIDTH)\ 1011 {\ 1012 w = default_width;\ 1013 d = precision;\ 1014 }\ 1015 /* The switch between FMT_E and FMT_F is based on the absolute value. \ 1016 Set r=0 for rounding toward zero and r = 1 otherwise. \ 1017 If (exp_d - m) == 1 there is no rounding needed. */\ 1018 switch (dtp->u.p.current_unit->round_status)\ 1019 {\ 1020 case ROUND_ZERO:\ 1021 r = 0.0;\ 1022 break;\ 1023 case ROUND_UP:\ 1024 r = sign_bit ? 0.0 : 1.0;\ 1025 break;\ 1026 case ROUND_DOWN:\ 1027 r = sign_bit ? 1.0 : 0.0;\ 1028 break;\ 1029 default:\ 1030 break;\ 1031 }\ 1032 exp_d = calculate_exp_ ## x (d);\ 1033 r_sc = (1 - r / exp_d);\ 1034 temp = 0.1 * r_sc;\ 1035 if ((m > 0.0 && ((m < temp) || (r < 1 && r >= (exp_d - m))\ 1036 || (r == 1 && 1 > (exp_d - m))))\ 1037 || ((m == 0.0) && !(compile_options.allow_std\ 1038 & (GFC_STD_F2003 | GFC_STD_F2008)))\ 1039 || d == 0)\ 1040 { \ 1041 newf.format = FMT_E;\ 1042 newf.u.real.w = w;\ 1043 newf.u.real.d = d - comp_d;\ 1044 newf.u.real.e = e;\ 1045 npad = 0;\ 1046 precision = determine_precision (dtp, &newf, x);\ 1047 nprinted = DTOA(y,precision,m);\ 1048 }\ 1049 else \ 1050 {\ 1051 mid = 0;\ 1052 low = 0;\ 1053 high = d + 1;\ 1054 lbound = 0;\ 1055 ubound = d + 1;\ 1056 while (low <= high)\ 1057 {\ 1058 mid = (low + high) / 2;\ 1059 temp = (calculate_exp_ ## x (mid - 1) * r_sc);\ 1060 if (m < temp)\ 1061 { \ 1062 ubound = mid;\ 1063 if (ubound == lbound + 1)\ 1064 break;\ 1065 high = mid - 1;\ 1066 }\ 1067 else if (m > temp)\ 1068 { \ 1069 lbound = mid;\ 1070 if (ubound == lbound + 1)\ 1071 { \ 1072 mid ++;\ 1073 break;\ 1074 }\ 1075 low = mid + 1;\ 1076 }\ 1077 else\ 1078 {\ 1079 mid++;\ 1080 break;\ 1081 }\ 1082 }\ 1083 npad = e <= 0 ? 4 : e + 2;\ 1084 npad = npad >= w ? w - 1 : npad;\ 1085 npad = dtp->u.p.g0_no_blanks ? 0 : npad;\ 1086 newf.format = FMT_F;\ 1087 newf.u.real.w = w - npad;\ 1088 newf.u.real.d = m == 0.0 ? d - 1 : -(mid - d - 1) ;\ 1089 dtp->u.p.scale_factor = 0;\ 1090 precision = determine_precision (dtp, &newf, x);\ 1091 nprinted = FDTOA(y,precision,m);\ 1092 }\ 1093 build_float_string (dtp, &newf, buffer, size, nprinted, precision,\ 1094 sign_bit, zero_flag, npad, default_width,\ 1095 result, res_len);\ 1096 dtp->u.p.scale_factor = save_scale_factor;\ 1097 }\ 1098 else\ 1099 {\ 1100 if (f->format == FMT_F)\ 1101 nprinted = FDTOA(y,precision,m);\ 1102 else\ 1103 nprinted = DTOA(y,precision,m);\ 1104 build_float_string (dtp, f, buffer, size, nprinted, precision,\ 1105 sign_bit, zero_flag, npad, default_width,\ 1106 result, res_len);\ 1107 }\ 1108}\ 1109 1110/* Output a real number according to its format. */ 1111 1112 1113static void 1114get_float_string (st_parameter_dt *dtp, const fnode *f, const char *source, 1115 int kind, int comp_d, char *buffer, int precision, 1116 size_t size, char *result, size_t *res_len) 1117{ 1118 int sign_bit, nprinted; 1119 bool zero_flag; 1120 int default_width = 0; 1121 1122 if (f->u.real.w == DEFAULT_WIDTH) 1123 /* This codepath can only be reached with -fdec-format-defaults. The default 1124 * values are based on those used in the Oracle Fortran compiler. 1125 */ 1126 { 1127 default_width = default_width_for_float (kind); 1128 precision = default_precision_for_float (kind); 1129 } 1130 1131 switch (kind) 1132 { 1133 case 4: 1134 FORMAT_FLOAT(4,) 1135 break; 1136 1137 case 8: 1138 FORMAT_FLOAT(8,) 1139 break; 1140 1141#ifdef HAVE_GFC_REAL_10 1142 case 10: 1143 FORMAT_FLOAT(10,L) 1144 break; 1145#endif 1146#ifdef HAVE_GFC_REAL_16 1147 case 16: 1148# ifdef GFC_REAL_16_IS_FLOAT128 1149 FORMAT_FLOAT(16,Q) 1150# else 1151 FORMAT_FLOAT(16,L) 1152# endif 1153 break; 1154#endif 1155#ifdef HAVE_GFC_REAL_17 1156 case 17: 1157 FORMAT_FLOAT(17,Q) 1158 break; 1159#endif 1160 default: 1161 internal_error (NULL, "bad real kind"); 1162 } 1163 return; 1164} 1165