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)
75 /* Number of digits before the decimal point. */
77 /* Number of zeros after the decimal point. */
79 /* Number of digits after the decimal point. */
81 /* Number of zeros after the decimal point, whatever the precision. */
95 /* We should always know the field width and precision. */
97 internal_error (&dtp->common, "Unspecified precision");
99 sign = calculate_sign (dtp, sign_bit);
101 /* The following code checks the given string has punctuation in the correct
102 places. Uncomment if needed for debugging.
103 if (d != 0 && ((buffer[2] != '.' && buffer[2] != ',')
104 || buffer[ndigits + 2] != 'e'))
105 internal_error (&dtp->common, "printf is broken"); */
107 /* Read the exponent back in. */
108 e = atoi (&buffer[ndigits + 3]) + 1;
110 /* Make sure zero comes out as 0.0e0. */
114 if (compile_options.sign_zero != 1)
115 sign = calculate_sign (dtp, 0);
117 /* Handle special cases. */
119 w = d + (sign != S_NONE ? 2 : 1) + (d == 0 ? 1 : 0);
122 /* Normalize the fractional component. */
123 buffer[2] = buffer[1];
126 /* Figure out where to place the decimal point. */
130 if (d == 0 && e <= 0 && dtp->u.p.scale_factor == 0)
132 memmove (digits + 1, digits, ndigits - 1);
137 nbefore = e + dtp->u.p.scale_factor;
157 i = dtp->u.p.scale_factor;
158 if (d <= 0 && i == 0)
160 generate_error (&dtp->common, LIBERROR_FORMAT, "Precision not "
161 "greater than zero in format specifier 'E' or 'D'");
164 if (i <= -d || i >= d + 2)
166 generate_error (&dtp->common, LIBERROR_FORMAT, "Scale factor "
167 "out of range in format specifier 'E' or 'D'");
183 nafter = (d - i) + 1;
199 /* The exponent must be a multiple of three, with 1-3 digits before
200 the decimal point. */
209 nbefore = 3 - nbefore;
228 /* Should never happen. */
229 internal_error (&dtp->common, "Unexpected format token");
232 /* Round the value. The value being rounded is an unsigned magnitude.
233 The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */
234 switch (dtp->u.p.current_unit->round_status)
236 case ROUND_ZERO: /* Do nothing and truncation occurs. */
249 /* Round compatible unless there is a tie. A tie is a 5 with
250 all trailing zero's. */
251 i = nafter + nbefore;
252 if (digits[i] == '5')
254 for(i++ ; i < ndigits; i++)
256 if (digits[i] != '0')
259 /* It is a tie so round to even. */
260 switch (digits[nafter + nbefore - 1])
267 /* If odd, round away from zero to even. */
270 /* If even, skip rounding, truncate to even. */
275 case ROUND_PROCDEFINED:
276 case ROUND_UNSPECIFIED:
277 case ROUND_COMPATIBLE:
279 /* Just fall through and do the actual rounding. */
284 if (nbefore + nafter == 0)
287 if (nzero_real == d && digits[0] >= rchar)
289 /* We rounded to zero but shouldn't have */
296 else if (nbefore + nafter < ndigits)
298 ndigits = nbefore + nafter;
300 if (digits[i] >= rchar)
302 /* Propagate the carry. */
303 for (i--; i >= 0; i--)
305 if (digits[i] != '9')
315 /* The carry overflowed. Fortunately we have some spare
316 space at the start of the buffer. We may discard some
317 digits, but this is ok because we already know they are
331 else if (ft == FMT_EN)
348 /* Calculate the format of the exponent field. */
352 for (i = abs (e); i >= 10; i /= 10)
357 /* Width not specified. Must be no more than 3 digits. */
358 if (e > 999 || e < -999)
363 if (e > 99 || e < -99)
369 /* Exponent width specified, check it is wide enough. */
370 if (edigits > f->u.real.e)
373 edigits = f->u.real.e + 2;
379 /* Zero values always output as positive, even if the value was negative
381 for (i = 0; i < ndigits; i++)
383 if (digits[i] != '0')
388 /* The output is zero, so set the sign according to the sign bit unless
389 -fno-sign-zero was specified. */
390 if (compile_options.sign_zero == 1)
391 sign = calculate_sign (dtp, sign_bit);
393 sign = calculate_sign (dtp, 0);
396 /* Pick a field size if none was specified. */
399 w = nbefore + nzero + nafter + (sign != S_NONE ? 2 : 1);
403 /* Work out how much padding is needed. */
404 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
408 if (dtp->u.p.g0_no_blanks)
414 /* Create the ouput buffer. */
415 out = write_block (dtp, w);
419 /* Check the value fits in the specified field width. */
420 if (nblanks < 0 || edigits == -1 || w == 1 || (w == 2 && sign != S_NONE))
422 if (unlikely (is_char4_unit (dtp)))
424 gfc_char4_t *out4 = (gfc_char4_t *) out;
425 memset4 (out4, '*', w);
432 /* See if we have space for a zero before the decimal point. */
433 if (nbefore == 0 && nblanks > 0)
441 /* For internal character(kind=4) units, we duplicate the code used for
442 regular output slightly modified. This needs to be maintained
443 consistent with the regular code that follows this block. */
444 if (unlikely (is_char4_unit (dtp)))
446 gfc_char4_t *out4 = (gfc_char4_t *) out;
447 /* Pad to full field width. */
449 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
451 memset4 (out4, ' ', nblanks);
455 /* Output the initial sign (if any). */
458 else if (sign == S_MINUS)
461 /* Output an optional leading zero. */
465 /* Output the part before the decimal point, padding with zeros. */
468 if (nbefore > ndigits)
471 memcpy4 (out4, digits, i);
479 memcpy4 (out4, digits, i);
487 /* Output the decimal point. */
488 *(out4++) = dtp->u.p.current_unit->decimal_status
489 == DECIMAL_POINT ? '.' : ',';
491 /* Output leading zeros after the decimal point. */
494 for (i = 0; i < nzero; i++)
498 /* Output digits after the decimal point, padding with zeros. */
501 if (nafter > ndigits)
506 memcpy4 (out4, digits, i);
515 /* Output the exponent. */
524 snprintf (buffer, size, "%+0*d", edigits, e);
526 sprintf (buffer, "%+0*d", edigits, e);
528 memcpy4 (out4, buffer, edigits);
531 if (dtp->u.p.no_leading_blank)
534 memset4 (out4, ' ' , nblanks);
535 dtp->u.p.no_leading_blank = 0;
538 } /* End of character(kind=4) internal unit code. */
540 /* Pad to full field width. */
542 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
544 memset (out, ' ', nblanks);
548 /* Output the initial sign (if any). */
551 else if (sign == S_MINUS)
554 /* Output an optional leading zero. */
558 /* Output the part before the decimal point, padding with zeros. */
561 if (nbefore > ndigits)
564 memcpy (out, digits, i);
572 memcpy (out, digits, i);
580 /* Output the decimal point. */
581 *(out++) = dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? '.' : ',';
583 /* Output leading zeros after the decimal point. */
586 for (i = 0; i < nzero; i++)
590 /* Output digits after the decimal point, padding with zeros. */
593 if (nafter > ndigits)
598 memcpy (out, digits, i);
607 /* Output the exponent. */
616 snprintf (buffer, size, "%+0*d", edigits, e);
618 sprintf (buffer, "%+0*d", edigits, e);
620 memcpy (out, buffer, edigits);
623 if (dtp->u.p.no_leading_blank)
626 memset( out , ' ' , nblanks );
627 dtp->u.p.no_leading_blank = 0;
632 #undef MIN_FIELD_WIDTH
637 /* Write "Infinite" or "Nan" as appropriate for the given format. */
640 write_infnan (st_parameter_dt *dtp, const fnode *f, int isnan_flag, int sign_bit)
647 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
649 sign = calculate_sign (dtp, sign_bit);
650 mark = (sign == S_PLUS || sign == S_MINUS) ? 8 : 7;
654 /* If the field width is zero, the processor must select a width
655 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
662 nb = (sign == S_PLUS || sign == S_MINUS) ? 4 : 3;
664 p = write_block (dtp, nb);
669 if (unlikely (is_char4_unit (dtp)))
671 gfc_char4_t *p4 = (gfc_char4_t *) p;
672 memset4 (p4, '*', nb);
679 if (unlikely (is_char4_unit (dtp)))
681 gfc_char4_t *p4 = (gfc_char4_t *) p;
682 memset4 (p4, ' ', nb);
691 /* If the sign is negative and the width is 3, there is
692 insufficient room to output '-Inf', so output asterisks */
695 if (unlikely (is_char4_unit (dtp)))
697 gfc_char4_t *p4 = (gfc_char4_t *) p;
698 memset4 (p4, '*', nb);
704 /* The negative sign is mandatory */
708 /* The positive sign is optional, but we output it for
712 if (unlikely (is_char4_unit (dtp)))
714 gfc_char4_t *p4 = (gfc_char4_t *) p;
717 /* We have room, so output 'Infinity' */
718 memcpy4 (p4 + nb - 8, "Infinity", 8);
720 /* For the case of width equals mark, there is not enough room
721 for the sign and 'Infinity' so we go with 'Inf' */
722 memcpy4 (p4 + nb - 3, "Inf", 3);
724 if (sign == S_PLUS || sign == S_MINUS)
726 if (nb < 9 && nb > 3)
727 /* Put the sign in front of Inf */
728 p4[nb - 4] = (gfc_char4_t) fin;
730 /* Put the sign in front of Infinity */
731 p4[nb - 9] = (gfc_char4_t) fin;
737 /* We have room, so output 'Infinity' */
738 memcpy(p + nb - 8, "Infinity", 8);
740 /* For the case of width equals 8, there is not enough room
741 for the sign and 'Infinity' so we go with 'Inf' */
742 memcpy(p + nb - 3, "Inf", 3);
744 if (sign == S_PLUS || sign == S_MINUS)
746 if (nb < 9 && nb > 3)
747 p[nb - 4] = fin; /* Put the sign in front of Inf */
749 p[nb - 9] = fin; /* Put the sign in front of Infinity */
754 if (unlikely (is_char4_unit (dtp)))
756 gfc_char4_t *p4 = (gfc_char4_t *) p;
757 memcpy4 (p4 + nb - 3, "NaN", 3);
760 memcpy(p + nb - 3, "NaN", 3);
767 /* Returns the value of 10**d. */
769 #define CALCULATE_EXP(x) \
770 inline static GFC_REAL_ ## x \
771 calculate_exp_ ## x (int d)\
774 GFC_REAL_ ## x r = 1.0;\
775 for (i = 0; i< (d >= 0 ? d : -d); i++)\
777 r = (d >= 0) ? r : 1.0 / r;\
785 #ifdef HAVE_GFC_REAL_10
789 #ifdef HAVE_GFC_REAL_16
794 /* Generate corresponding I/O format for FMT_G and output.
795 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
796 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
798 Data Magnitude Equivalent Conversion
799 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
800 m = 0 F(w-n).(d-1), n' '
801 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
802 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
803 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
804 ................ ..........
805 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
806 m >= 10**d-0.5 Ew.d[Ee]
808 notes: for Gw.d , n' ' means 4 blanks
809 for Gw.dEe, n' ' means e+2 blanks */
811 #define OUTPUT_FLOAT_FMT_G(x) \
813 output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
814 GFC_REAL_ ## x m, char *buffer, size_t size, \
815 int sign_bit, bool zero_flag, int ndigits, int edigits) \
817 int e = f->u.real.e;\
818 int d = f->u.real.d;\
819 int w = f->u.real.w;\
821 GFC_REAL_ ## x rexp_d;\
825 int save_scale_factor, nb = 0;\
828 save_scale_factor = dtp->u.p.scale_factor;\
829 newf = (fnode *) get_mem (sizeof (fnode));\
831 rexp_d = calculate_exp_ ## x (-d);\
832 if ((m > 0.0 && m < 0.1 - 0.05 * rexp_d) || (rexp_d * (m + 0.5) >= 1.0) ||\
833 ((m == 0.0) && !(compile_options.allow_std & GFC_STD_F2003)))\
835 newf->format = FMT_E;\
851 GFC_REAL_ ## x temp;\
852 mid = (low + high) / 2;\
854 temp = (calculate_exp_ ## x (mid - 1) * (1 - 0.5 * rexp_d));\
859 if (ubound == lbound + 1)\
866 if (ubound == lbound + 1)\
887 nb = nb >= w ? 0 : nb;\
888 newf->format = FMT_F;\
889 newf->u.real.w = f->u.real.w - nb;\
892 newf->u.real.d = d - 1;\
894 newf->u.real.d = - (mid - d - 1);\
896 dtp->u.p.scale_factor = 0;\
899 result = output_float (dtp, newf, buffer, size, sign_bit, zero_flag, \
901 dtp->u.p.scale_factor = save_scale_factor;\
905 if (nb > 0 && !dtp->u.p.g0_no_blanks)\
907 p = write_block (dtp, nb);\
910 if (result == FAILURE)\
912 if (unlikely (is_char4_unit (dtp)))\
914 gfc_char4_t *p4 = (gfc_char4_t *) p;\
915 memset4 (p4, pad, nb);\
918 memset (p, pad, nb);\
922 OUTPUT_FLOAT_FMT_G(4)
924 OUTPUT_FLOAT_FMT_G(8)
926 #ifdef HAVE_GFC_REAL_10
927 OUTPUT_FLOAT_FMT_G(10)
930 #ifdef HAVE_GFC_REAL_16
931 OUTPUT_FLOAT_FMT_G(16)
934 #undef OUTPUT_FLOAT_FMT_G
937 /* Define a macro to build code for write_float. */
939 /* Note: Before output_float is called, sprintf is used to print to buffer the
940 number in the format +D.DDDDe+ddd. For an N digit exponent, this gives us
941 (MIN_FIELD_WIDTH-5)-N digits after the decimal point, plus another one
942 before the decimal point.
944 # The result will always contain a decimal point, even if no
947 - The converted value is to be left adjusted on the field boundary
949 + A sign (+ or -) always be placed before a number
951 MIN_FIELD_WIDTH minimum field width
953 * (ndigits-1) is used as the precision
955 e format: [-]d.ddde±dd where there is one digit before the
956 decimal-point character and the number of digits after it is
957 equal to the precision. The exponent always contains at least two
958 digits; if the value is zero, the exponent is 00. */
963 snprintf (buffer, size, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
964 "e", ndigits - 1, tmp);
967 snprintf (buffer, size, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
968 "Le", ndigits - 1, tmp);
973 sprintf (buffer, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
974 "e", ndigits - 1, tmp);
977 sprintf (buffer, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
978 "Le", ndigits - 1, tmp);
982 #if defined(GFC_REAL_16_IS_FLOAT128)
984 __qmath_(quadmath_snprintf) (buffer, sizeof buffer, \
985 "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
986 "Qe", ndigits - 1, tmp);
989 #define WRITE_FLOAT(x,y)\
992 tmp = * (GFC_REAL_ ## x *)source;\
993 sign_bit = signbit (tmp);\
994 if (!isfinite (tmp))\
996 write_infnan (dtp, f, isnan (tmp), sign_bit);\
999 tmp = sign_bit ? -tmp : tmp;\
1000 zero_flag = (tmp == 0.0);\
1004 if (f->format != FMT_G)\
1005 output_float (dtp, f, buffer, size, sign_bit, zero_flag, ndigits, \
1008 output_float_FMT_G_ ## x (dtp, f, tmp, buffer, size, sign_bit, \
1009 zero_flag, ndigits, edigits);\
1012 /* Output a real number according to its format. */
1015 write_float (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
1018 #if defined(HAVE_GFC_REAL_16) || __LDBL_DIG__ > 18
1019 # define MIN_FIELD_WIDTH 46
1021 # define MIN_FIELD_WIDTH 31
1023 #define STR(x) STR1(x)
1026 /* This must be large enough to accurately hold any value. */
1027 char buffer[MIN_FIELD_WIDTH+1];
1028 int sign_bit, ndigits, edigits;
1032 size = MIN_FIELD_WIDTH+1;
1034 /* printf pads blanks for us on the exponent so we just need it big enough
1035 to handle the largest number of exponent digits expected. */
1038 if (f->format == FMT_F || f->format == FMT_EN || f->format == FMT_G
1039 || ((f->format == FMT_D || f->format == FMT_E)
1040 && dtp->u.p.scale_factor != 0))
1042 /* Always convert at full precision to avoid double rounding. */
1043 ndigits = MIN_FIELD_WIDTH - 4 - edigits;
1047 /* The number of digits is known, so let printf do the rounding. */
1048 if (f->format == FMT_ES)
1049 ndigits = f->u.real.d + 1;
1051 ndigits = f->u.real.d;
1052 if (ndigits > MIN_FIELD_WIDTH - 4 - edigits)
1053 ndigits = MIN_FIELD_WIDTH - 4 - edigits;
1066 #ifdef HAVE_GFC_REAL_10
1071 #ifdef HAVE_GFC_REAL_16
1073 # ifdef GFC_REAL_16_IS_FLOAT128
1081 internal_error (NULL, "bad real kind");