1 /* Copyright (C) 2007, 2008, 2009, 2010, 2011 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
6 This file is part of the GNU Fortran runtime library (libgfortran).
8 Libgfortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 Libgfortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
30 { S_NONE, S_MINUS, S_PLUS }
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. */
37 calculate_sign (st_parameter_dt *dtp, int negative_flag)
44 switch (dtp->u.p.sign_status)
46 case SIGN_SP: /* Show sign. */
49 case SIGN_SS: /* Suppress sign. */
52 case SIGN_S: /* Processor defined. */
53 case SIGN_UNSPECIFIED:
54 s = options.optional_plus ? S_PLUS : S_NONE;
62 /* Output a real number according to its format which is FMT_G free. */
65 output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
66 int sign_bit, bool zero_flag, int ndigits, int edigits)
73 /* Number of digits before the decimal point. */
75 /* Number of zeros after the decimal point. */
77 /* Number of digits after the decimal point. */
79 /* Number of zeros after the decimal point, whatever the precision. */
88 p = dtp->u.p.scale_factor;
93 /* We should always know the field width and precision. */
95 internal_error (&dtp->common, "Unspecified precision");
97 sign = calculate_sign (dtp, sign_bit);
99 /* The following code checks the given string has punctuation in the correct
100 places. Uncomment if needed for debugging.
101 if (d != 0 && ((buffer[2] != '.' && buffer[2] != ',')
102 || buffer[ndigits + 2] != 'e'))
103 internal_error (&dtp->common, "printf is broken"); */
105 /* Read the exponent back in. */
106 e = atoi (&buffer[ndigits + 3]) + 1;
108 /* Make sure zero comes out as 0.0e0. */
112 /* Normalize the fractional component. */
113 buffer[2] = buffer[1];
116 /* Figure out where to place the decimal point. */
120 if (d == 0 && e <= 0 && p == 0)
122 memmove (digits + 1, digits, ndigits - 1);
147 i = dtp->u.p.scale_factor;
148 if (d <= 0 && p == 0)
150 generate_error (&dtp->common, LIBERROR_FORMAT, "Precision not "
151 "greater than zero in format specifier 'E' or 'D'");
154 if (p <= -d || p >= d + 2)
156 generate_error (&dtp->common, LIBERROR_FORMAT, "Scale factor "
157 "out of range in format specifier 'E' or 'D'");
173 nafter = (d - p) + 1;
189 /* The exponent must be a multiple of three, with 1-3 digits before
190 the decimal point. */
199 nbefore = 3 - nbefore;
218 /* Should never happen. */
219 internal_error (&dtp->common, "Unexpected format token");
224 /* Round the value. The value being rounded is an unsigned magnitude.
225 The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */
226 switch (dtp->u.p.current_unit->round_status)
228 case ROUND_ZERO: /* Do nothing and truncation occurs. */
234 /* Scan for trailing zeros to see if we really need to round it. */
235 for(i = nbefore + nafter; i < ndigits; i++)
237 if (digits[i] != '0')
247 /* Round compatible unless there is a tie. A tie is a 5 with
248 all trailing zero's. */
249 i = nafter + nbefore;
250 if (digits[i] == '5')
252 for(i++ ; i < ndigits; i++)
254 if (digits[i] != '0')
257 /* It is a tie so round to even. */
258 switch (digits[nafter + nbefore - 1])
265 /* If odd, round away from zero to even. */
268 /* If even, skip rounding, truncate to even. */
273 case ROUND_PROCDEFINED:
274 case ROUND_UNSPECIFIED:
275 case ROUND_COMPATIBLE:
277 /* Just fall through and do the actual rounding. */
282 if (nbefore + nafter == 0)
285 if (nzero_real == d && digits[0] >= rchar)
287 /* We rounded to zero but shouldn't have */
294 else if (nbefore + nafter < ndigits)
296 i = ndigits = nbefore + nafter;
297 if (digits[i] >= rchar)
299 /* Propagate the carry. */
300 for (i--; i >= 0; i--)
302 if (digits[i] != '9')
312 /* The carry overflowed. Fortunately we have some spare
313 space at the start of the buffer. We may discard some
314 digits, but this is ok because we already know they are
328 else if (ft == FMT_EN)
345 /* Calculate the format of the exponent field. */
349 for (i = abs (e); i >= 10; i /= 10)
354 /* Width not specified. Must be no more than 3 digits. */
355 if (e > 999 || e < -999)
360 if (e > 99 || e < -99)
366 /* Exponent width specified, check it is wide enough. */
367 if (edigits > f->u.real.e)
370 edigits = f->u.real.e + 2;
376 /* Scan the digits string and count the number of zeros. If we make it
377 all the way through the loop, we know the value is zero after the
378 rounding completed above. */
379 for (i = 0; i < ndigits; i++)
381 if (digits[i] != '0')
385 /* To format properly, we need to know if the rounded result is zero and if
386 so, we set the zero_flag which may have been already set for
391 /* The output is zero, so set the sign according to the sign bit unless
392 -fno-sign-zero was specified. */
393 if (compile_options.sign_zero == 1)
394 sign = calculate_sign (dtp, sign_bit);
396 sign = calculate_sign (dtp, 0);
399 /* Pick a field size if none was specified, taking into account small
400 values that may have been rounded to zero. */
404 w = d + (sign != S_NONE ? 2 : 1) + (d == 0 ? 1 : 0);
407 w = nbefore + nzero + nafter + (sign != S_NONE ? 2 : 1);
412 /* Work out how much padding is needed. */
413 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
417 if (dtp->u.p.g0_no_blanks)
423 /* Create the ouput buffer. */
424 out = write_block (dtp, w);
428 /* Check the value fits in the specified field width. */
429 if (nblanks < 0 || edigits == -1 || w == 1 || (w == 2 && sign != S_NONE))
431 if (unlikely (is_char4_unit (dtp)))
433 gfc_char4_t *out4 = (gfc_char4_t *) out;
434 memset4 (out4, '*', w);
441 /* See if we have space for a zero before the decimal point. */
442 if (nbefore == 0 && nblanks > 0)
450 /* For internal character(kind=4) units, we duplicate the code used for
451 regular output slightly modified. This needs to be maintained
452 consistent with the regular code that follows this block. */
453 if (unlikely (is_char4_unit (dtp)))
455 gfc_char4_t *out4 = (gfc_char4_t *) out;
456 /* Pad to full field width. */
458 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
460 memset4 (out4, ' ', nblanks);
464 /* Output the initial sign (if any). */
467 else if (sign == S_MINUS)
470 /* Output an optional leading zero. */
474 /* Output the part before the decimal point, padding with zeros. */
477 if (nbefore > ndigits)
480 memcpy4 (out4, digits, i);
488 memcpy4 (out4, digits, i);
496 /* Output the decimal point. */
497 *(out4++) = dtp->u.p.current_unit->decimal_status
498 == DECIMAL_POINT ? '.' : ',';
500 /* Output leading zeros after the decimal point. */
503 for (i = 0; i < nzero; i++)
507 /* Output digits after the decimal point, padding with zeros. */
510 if (nafter > ndigits)
515 memcpy4 (out4, digits, i);
524 /* Output the exponent. */
532 snprintf (buffer, size, "%+0*d", edigits, e);
533 memcpy4 (out4, buffer, edigits);
536 if (dtp->u.p.no_leading_blank)
539 memset4 (out4, ' ' , nblanks);
540 dtp->u.p.no_leading_blank = 0;
543 } /* End of character(kind=4) internal unit code. */
545 /* Pad to full field width. */
547 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
549 memset (out, ' ', nblanks);
553 /* Output the initial sign (if any). */
556 else if (sign == S_MINUS)
559 /* Output an optional leading zero. */
563 /* Output the part before the decimal point, padding with zeros. */
566 if (nbefore > ndigits)
569 memcpy (out, digits, i);
577 memcpy (out, digits, i);
585 /* Output the decimal point. */
586 *(out++) = dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? '.' : ',';
588 /* Output leading zeros after the decimal point. */
591 for (i = 0; i < nzero; i++)
595 /* Output digits after the decimal point, padding with zeros. */
598 if (nafter > ndigits)
603 memcpy (out, digits, i);
612 /* Output the exponent. */
620 snprintf (buffer, size, "%+0*d", edigits, e);
621 memcpy (out, buffer, edigits);
624 if (dtp->u.p.no_leading_blank)
627 memset( out , ' ' , nblanks );
628 dtp->u.p.no_leading_blank = 0;
633 #undef MIN_FIELD_WIDTH
638 /* Write "Infinite" or "Nan" as appropriate for the given format. */
641 write_infnan (st_parameter_dt *dtp, const fnode *f, int isnan_flag, int sign_bit)
648 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
650 sign = calculate_sign (dtp, sign_bit);
651 mark = (sign == S_PLUS || sign == S_MINUS) ? 8 : 7;
655 /* If the field width is zero, the processor must select a width
656 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
658 if ((nb == 0) || dtp->u.p.g0_no_blanks)
663 nb = (sign == S_PLUS || sign == S_MINUS) ? 4 : 3;
665 p = write_block (dtp, nb);
670 if (unlikely (is_char4_unit (dtp)))
672 gfc_char4_t *p4 = (gfc_char4_t *) p;
673 memset4 (p4, '*', nb);
680 if (unlikely (is_char4_unit (dtp)))
682 gfc_char4_t *p4 = (gfc_char4_t *) p;
683 memset4 (p4, ' ', nb);
692 /* If the sign is negative and the width is 3, there is
693 insufficient room to output '-Inf', so output asterisks */
696 if (unlikely (is_char4_unit (dtp)))
698 gfc_char4_t *p4 = (gfc_char4_t *) p;
699 memset4 (p4, '*', nb);
705 /* The negative sign is mandatory */
709 /* The positive sign is optional, but we output it for
713 if (unlikely (is_char4_unit (dtp)))
715 gfc_char4_t *p4 = (gfc_char4_t *) p;
718 /* We have room, so output 'Infinity' */
719 memcpy4 (p4 + nb - 8, "Infinity", 8);
721 /* For the case of width equals mark, there is not enough room
722 for the sign and 'Infinity' so we go with 'Inf' */
723 memcpy4 (p4 + nb - 3, "Inf", 3);
725 if (sign == S_PLUS || sign == S_MINUS)
727 if (nb < 9 && nb > 3)
728 /* Put the sign in front of Inf */
729 p4[nb - 4] = (gfc_char4_t) fin;
731 /* Put the sign in front of Infinity */
732 p4[nb - 9] = (gfc_char4_t) fin;
738 /* We have room, so output 'Infinity' */
739 memcpy(p + nb - 8, "Infinity", 8);
741 /* For the case of width equals 8, there is not enough room
742 for the sign and 'Infinity' so we go with 'Inf' */
743 memcpy(p + nb - 3, "Inf", 3);
745 if (sign == S_PLUS || sign == S_MINUS)
747 if (nb < 9 && nb > 3)
748 p[nb - 4] = fin; /* Put the sign in front of Inf */
750 p[nb - 9] = fin; /* Put the sign in front of Infinity */
755 if (unlikely (is_char4_unit (dtp)))
757 gfc_char4_t *p4 = (gfc_char4_t *) p;
758 memcpy4 (p4 + nb - 3, "NaN", 3);
761 memcpy(p + nb - 3, "NaN", 3);
768 /* Returns the value of 10**d. */
770 #define CALCULATE_EXP(x) \
771 inline static GFC_REAL_ ## x \
772 calculate_exp_ ## x (int d)\
775 GFC_REAL_ ## x r = 1.0;\
776 for (i = 0; i< (d >= 0 ? d : -d); i++)\
778 r = (d >= 0) ? r : 1.0 / r;\
786 #ifdef HAVE_GFC_REAL_10
790 #ifdef HAVE_GFC_REAL_16
795 /* Generate corresponding I/O format for FMT_G and output.
796 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
797 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
799 Data Magnitude Equivalent Conversion
800 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
801 m = 0 F(w-n).(d-1), n' '
802 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
803 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
804 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
805 ................ ..........
806 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
807 m >= 10**d-0.5 Ew.d[Ee]
809 notes: for Gw.d , n' ' means 4 blanks
810 for Gw.dEe, n' ' means e+2 blanks
811 for rounding modes adjustment, r, See Fortran F2008 10.7.5.2.2
812 the asm volatile is required for 32-bit x86 platforms. */
814 #define OUTPUT_FLOAT_FMT_G(x) \
816 output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
817 GFC_REAL_ ## x m, char *buffer, size_t size, \
818 int sign_bit, bool zero_flag, int ndigits, \
819 int edigits, int comp_d) \
821 int e = f->u.real.e;\
822 int d = f->u.real.d;\
823 int w = f->u.real.w;\
825 GFC_REAL_ ## x rexp_d, r = 0.5;\
829 int save_scale_factor, nb = 0;\
832 save_scale_factor = dtp->u.p.scale_factor;\
833 newf = (fnode *) get_mem (sizeof (fnode));\
835 switch (dtp->u.p.current_unit->round_status)\
838 r = sign_bit ? 1.0 : 0.0;\
850 rexp_d = calculate_exp_ ## x (-d);\
851 if ((m > 0.0 && ((m < 0.1 - 0.1 * r * rexp_d) || (rexp_d * (m + r) >= 1.0)))\
852 || ((m == 0.0) && !(compile_options.allow_std\
853 & (GFC_STD_F2003 | GFC_STD_F2008))))\
855 newf->format = FMT_E;\
857 newf->u.real.d = d - comp_d;\
871 volatile GFC_REAL_ ## x temp;\
872 mid = (low + high) / 2;\
874 temp = (calculate_exp_ ## x (mid - 1) * (1 - r * rexp_d));\
879 if (ubound == lbound + 1)\
886 if (ubound == lbound + 1)\
900 nb = e <= 0 ? 4 : e + 2;\
901 nb = nb >= w ? w - 1 : nb;\
902 newf->format = FMT_F;\
903 newf->u.real.w = w - nb;\
904 newf->u.real.d = m == 0.0 ? d - 1 : -(mid - d - 1) ;\
905 dtp->u.p.scale_factor = 0;\
908 result = output_float (dtp, newf, buffer, size, sign_bit, zero_flag, \
910 dtp->u.p.scale_factor = save_scale_factor;\
914 if (nb > 0 && !dtp->u.p.g0_no_blanks)\
916 p = write_block (dtp, nb);\
919 if (result == FAILURE)\
921 if (unlikely (is_char4_unit (dtp)))\
923 gfc_char4_t *p4 = (gfc_char4_t *) p;\
924 memset4 (p4, pad, nb);\
927 memset (p, pad, nb);\
931 OUTPUT_FLOAT_FMT_G(4)
933 OUTPUT_FLOAT_FMT_G(8)
935 #ifdef HAVE_GFC_REAL_10
936 OUTPUT_FLOAT_FMT_G(10)
939 #ifdef HAVE_GFC_REAL_16
940 OUTPUT_FLOAT_FMT_G(16)
943 #undef OUTPUT_FLOAT_FMT_G
946 /* Define a macro to build code for write_float. */
948 /* Note: Before output_float is called, snprintf is used to print to buffer the
949 number in the format +D.DDDDe+ddd. For an N digit exponent, this gives us
950 (MIN_FIELD_WIDTH-5)-N digits after the decimal point, plus another one
951 before the decimal point.
953 # The result will always contain a decimal point, even if no
956 - The converted value is to be left adjusted on the field boundary
958 + A sign (+ or -) always be placed before a number
960 MIN_FIELD_WIDTH minimum field width
962 * (ndigits-1) is used as the precision
964 e format: [-]d.ddde±dd where there is one digit before the
965 decimal-point character and the number of digits after it is
966 equal to the precision. The exponent always contains at least two
967 digits; if the value is zero, the exponent is 00. */
970 snprintf (buffer, size, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
971 "e", ndigits - 1, tmp);
974 snprintf (buffer, size, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
975 "Le", ndigits - 1, tmp);
978 #if defined(GFC_REAL_16_IS_FLOAT128)
980 __qmath_(quadmath_snprintf) (buffer, sizeof buffer, \
981 "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
982 "Qe", ndigits - 1, tmp);
985 #define WRITE_FLOAT(x,y)\
988 tmp = * (GFC_REAL_ ## x *)source;\
989 sign_bit = signbit (tmp);\
990 if (!isfinite (tmp))\
992 write_infnan (dtp, f, isnan (tmp), sign_bit);\
995 tmp = sign_bit ? -tmp : tmp;\
996 zero_flag = (tmp == 0.0);\
1000 if (f->format != FMT_G)\
1001 output_float (dtp, f, buffer, size, sign_bit, zero_flag, ndigits, \
1004 output_float_FMT_G_ ## x (dtp, f, tmp, buffer, size, sign_bit, \
1005 zero_flag, ndigits, edigits, comp_d);\
1008 /* Output a real number according to its format. */
1011 write_float (st_parameter_dt *dtp, const fnode *f, const char *source, \
1012 int len, int comp_d)
1015 #if defined(HAVE_GFC_REAL_16) || __LDBL_DIG__ > 18
1016 # define MIN_FIELD_WIDTH 49
1018 # define MIN_FIELD_WIDTH 32
1020 #define STR(x) STR1(x)
1023 /* This must be large enough to accurately hold any value. */
1024 char buffer[MIN_FIELD_WIDTH+1];
1025 int sign_bit, ndigits, edigits;
1029 size = MIN_FIELD_WIDTH+1;
1031 /* printf pads blanks for us on the exponent so we just need it big enough
1032 to handle the largest number of exponent digits expected. */
1035 /* Always convert at full precision to avoid double rounding. */
1036 ndigits = MIN_FIELD_WIDTH - 4 - edigits;
1048 #ifdef HAVE_GFC_REAL_10
1053 #ifdef HAVE_GFC_REAL_16
1055 # ifdef GFC_REAL_16_IS_FLOAT128
1063 internal_error (NULL, "bad real kind");