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 /* Normalize the fractional component. */
115 buffer[2] = buffer[1];
118 /* Figure out where to place the decimal point. */
122 if (d == 0 && e <= 0 && dtp->u.p.scale_factor == 0)
124 memmove (digits + 1, digits, ndigits - 1);
129 nbefore = e + dtp->u.p.scale_factor;
149 i = dtp->u.p.scale_factor;
150 if (d <= 0 && i == 0)
152 generate_error (&dtp->common, LIBERROR_FORMAT, "Precision not "
153 "greater than zero in format specifier 'E' or 'D'");
156 if (i <= -d || i >= d + 2)
158 generate_error (&dtp->common, LIBERROR_FORMAT, "Scale factor "
159 "out of range in format specifier 'E' or 'D'");
175 nafter = (d - i) + 1;
191 /* The exponent must be a multiple of three, with 1-3 digits before
192 the decimal point. */
201 nbefore = 3 - nbefore;
220 /* Should never happen. */
221 internal_error (&dtp->common, "Unexpected format token");
226 /* Round the value. The value being rounded is an unsigned magnitude.
227 The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */
228 switch (dtp->u.p.current_unit->round_status)
230 case ROUND_ZERO: /* Do nothing and truncation occurs. */
243 /* Round compatible unless there is a tie. A tie is a 5 with
244 all trailing zero's. */
245 i = nafter + nbefore;
246 if (digits[i] == '5')
248 for(i++ ; i < ndigits; i++)
250 if (digits[i] != '0')
253 /* It is a tie so round to even. */
254 switch (digits[nafter + nbefore - 1])
261 /* If odd, round away from zero to even. */
264 /* If even, skip rounding, truncate to even. */
269 case ROUND_PROCDEFINED:
270 case ROUND_UNSPECIFIED:
271 case ROUND_COMPATIBLE:
273 /* Just fall through and do the actual rounding. */
278 if (nbefore + nafter == 0)
281 if (nzero_real == d && digits[0] >= rchar)
283 /* We rounded to zero but shouldn't have */
290 else if (nbefore + nafter < ndigits)
292 ndigits = nbefore + nafter;
294 if (digits[i] >= rchar)
296 /* Propagate the carry. */
297 for (i--; i >= 0; i--)
299 if (digits[i] != '9')
309 /* The carry overflowed. Fortunately we have some spare
310 space at the start of the buffer. We may discard some
311 digits, but this is ok because we already know they are
325 else if (ft == FMT_EN)
342 /* Calculate the format of the exponent field. */
346 for (i = abs (e); i >= 10; i /= 10)
351 /* Width not specified. Must be no more than 3 digits. */
352 if (e > 999 || e < -999)
357 if (e > 99 || e < -99)
363 /* Exponent width specified, check it is wide enough. */
364 if (edigits > f->u.real.e)
367 edigits = f->u.real.e + 2;
373 /* Scan the digits string and count the number of zeros. If we make it
374 all the way through the loop, we know the value is zero after the
375 rounding completed above. */
376 for (i = 0; i < ndigits; i++)
378 if (digits[i] != '0')
382 /* To format properly, we need to know if the rounded result is zero and if
383 so, we set the zero_flag which may have been already set for
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, taking into account small
397 values that may have been rounded to zero. */
401 w = d + (sign != S_NONE ? 2 : 1) + (d == 0 ? 1 : 0);
404 w = nbefore + nzero + nafter + (sign != S_NONE ? 2 : 1);
409 /* Work out how much padding is needed. */
410 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
414 if (dtp->u.p.g0_no_blanks)
420 /* Create the ouput buffer. */
421 out = write_block (dtp, w);
425 /* Check the value fits in the specified field width. */
426 if (nblanks < 0 || edigits == -1 || w == 1 || (w == 2 && sign != S_NONE))
428 if (unlikely (is_char4_unit (dtp)))
430 gfc_char4_t *out4 = (gfc_char4_t *) out;
431 memset4 (out4, '*', w);
438 /* See if we have space for a zero before the decimal point. */
439 if (nbefore == 0 && nblanks > 0)
447 /* For internal character(kind=4) units, we duplicate the code used for
448 regular output slightly modified. This needs to be maintained
449 consistent with the regular code that follows this block. */
450 if (unlikely (is_char4_unit (dtp)))
452 gfc_char4_t *out4 = (gfc_char4_t *) out;
453 /* Pad to full field width. */
455 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
457 memset4 (out4, ' ', nblanks);
461 /* Output the initial sign (if any). */
464 else if (sign == S_MINUS)
467 /* Output an optional leading zero. */
471 /* Output the part before the decimal point, padding with zeros. */
474 if (nbefore > ndigits)
477 memcpy4 (out4, digits, i);
485 memcpy4 (out4, digits, i);
493 /* Output the decimal point. */
494 *(out4++) = dtp->u.p.current_unit->decimal_status
495 == DECIMAL_POINT ? '.' : ',';
497 /* Output leading zeros after the decimal point. */
500 for (i = 0; i < nzero; i++)
504 /* Output digits after the decimal point, padding with zeros. */
507 if (nafter > ndigits)
512 memcpy4 (out4, digits, i);
521 /* Output the exponent. */
529 snprintf (buffer, size, "%+0*d", edigits, e);
530 memcpy4 (out4, buffer, edigits);
533 if (dtp->u.p.no_leading_blank)
536 memset4 (out4, ' ' , nblanks);
537 dtp->u.p.no_leading_blank = 0;
540 } /* End of character(kind=4) internal unit code. */
542 /* Pad to full field width. */
544 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
546 memset (out, ' ', nblanks);
550 /* Output the initial sign (if any). */
553 else if (sign == S_MINUS)
556 /* Output an optional leading zero. */
560 /* Output the part before the decimal point, padding with zeros. */
563 if (nbefore > ndigits)
566 memcpy (out, digits, i);
574 memcpy (out, digits, i);
582 /* Output the decimal point. */
583 *(out++) = dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? '.' : ',';
585 /* Output leading zeros after the decimal point. */
588 for (i = 0; i < nzero; i++)
592 /* Output digits after the decimal point, padding with zeros. */
595 if (nafter > ndigits)
600 memcpy (out, digits, i);
609 /* Output the exponent. */
617 snprintf (buffer, size, "%+0*d", edigits, e);
618 memcpy (out, buffer, edigits);
621 if (dtp->u.p.no_leading_blank)
624 memset( out , ' ' , nblanks );
625 dtp->u.p.no_leading_blank = 0;
630 #undef MIN_FIELD_WIDTH
635 /* Write "Infinite" or "Nan" as appropriate for the given format. */
638 write_infnan (st_parameter_dt *dtp, const fnode *f, int isnan_flag, int sign_bit)
645 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
647 sign = calculate_sign (dtp, sign_bit);
648 mark = (sign == S_PLUS || sign == S_MINUS) ? 8 : 7;
652 /* If the field width is zero, the processor must select a width
653 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
655 if ((nb == 0) || dtp->u.p.g0_no_blanks)
660 nb = (sign == S_PLUS || sign == S_MINUS) ? 4 : 3;
662 p = write_block (dtp, nb);
667 if (unlikely (is_char4_unit (dtp)))
669 gfc_char4_t *p4 = (gfc_char4_t *) p;
670 memset4 (p4, '*', nb);
677 if (unlikely (is_char4_unit (dtp)))
679 gfc_char4_t *p4 = (gfc_char4_t *) p;
680 memset4 (p4, ' ', nb);
689 /* If the sign is negative and the width is 3, there is
690 insufficient room to output '-Inf', so output asterisks */
693 if (unlikely (is_char4_unit (dtp)))
695 gfc_char4_t *p4 = (gfc_char4_t *) p;
696 memset4 (p4, '*', nb);
702 /* The negative sign is mandatory */
706 /* The positive sign is optional, but we output it for
710 if (unlikely (is_char4_unit (dtp)))
712 gfc_char4_t *p4 = (gfc_char4_t *) p;
715 /* We have room, so output 'Infinity' */
716 memcpy4 (p4 + nb - 8, "Infinity", 8);
718 /* For the case of width equals mark, there is not enough room
719 for the sign and 'Infinity' so we go with 'Inf' */
720 memcpy4 (p4 + nb - 3, "Inf", 3);
722 if (sign == S_PLUS || sign == S_MINUS)
724 if (nb < 9 && nb > 3)
725 /* Put the sign in front of Inf */
726 p4[nb - 4] = (gfc_char4_t) fin;
728 /* Put the sign in front of Infinity */
729 p4[nb - 9] = (gfc_char4_t) fin;
735 /* We have room, so output 'Infinity' */
736 memcpy(p + nb - 8, "Infinity", 8);
738 /* For the case of width equals 8, there is not enough room
739 for the sign and 'Infinity' so we go with 'Inf' */
740 memcpy(p + nb - 3, "Inf", 3);
742 if (sign == S_PLUS || sign == S_MINUS)
744 if (nb < 9 && nb > 3)
745 p[nb - 4] = fin; /* Put the sign in front of Inf */
747 p[nb - 9] = fin; /* Put the sign in front of Infinity */
752 if (unlikely (is_char4_unit (dtp)))
754 gfc_char4_t *p4 = (gfc_char4_t *) p;
755 memcpy4 (p4 + nb - 3, "NaN", 3);
758 memcpy(p + nb - 3, "NaN", 3);
765 /* Returns the value of 10**d. */
767 #define CALCULATE_EXP(x) \
768 inline static GFC_REAL_ ## x \
769 calculate_exp_ ## x (int d)\
772 GFC_REAL_ ## x r = 1.0;\
773 for (i = 0; i< (d >= 0 ? d : -d); i++)\
775 r = (d >= 0) ? r : 1.0 / r;\
783 #ifdef HAVE_GFC_REAL_10
787 #ifdef HAVE_GFC_REAL_16
792 /* Generate corresponding I/O format for FMT_G and output.
793 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
794 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
796 Data Magnitude Equivalent Conversion
797 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
798 m = 0 F(w-n).(d-1), n' '
799 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
800 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
801 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
802 ................ ..........
803 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
804 m >= 10**d-0.5 Ew.d[Ee]
806 notes: for Gw.d , n' ' means 4 blanks
807 for Gw.dEe, n' ' means e+2 blanks
808 for rounding modes adjustment, r, See Fortran F2008 10.7.5.2.2
809 the asm volatile is required for 32-bit x86 platforms. */
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, r = 0.5;\
825 int save_scale_factor, nb = 0;\
828 save_scale_factor = dtp->u.p.scale_factor;\
829 newf = (fnode *) get_mem (sizeof (fnode));\
831 switch (dtp->u.p.current_unit->round_status)\
834 r = sign_bit ? 1.0 : 0.0;\
846 rexp_d = calculate_exp_ ## x (-d);\
847 if ((m > 0.0 && ((m < 0.1 - 0.1 * r * rexp_d) || (rexp_d * (m + r) >= 1.0)))\
848 || ((m == 0.0) && !(compile_options.allow_std\
849 & (GFC_STD_F2003 | GFC_STD_F2008))))\
851 newf->format = FMT_E;\
867 GFC_REAL_ ## x temp;\
868 mid = (low + high) / 2;\
870 temp = (calculate_exp_ ## x (mid - 1) * (1 - r * rexp_d));\
871 asm volatile ("" : "+m" (temp));\
876 if (ubound == lbound + 1)\
883 if (ubound == lbound + 1)\
904 nb = nb >= w ? 0 : nb;\
905 newf->format = FMT_F;\
906 newf->u.real.w = f->u.real.w - nb;\
909 newf->u.real.d = d - 1;\
911 newf->u.real.d = - (mid - d - 1);\
913 dtp->u.p.scale_factor = 0;\
916 result = output_float (dtp, newf, buffer, size, sign_bit, zero_flag, \
918 dtp->u.p.scale_factor = save_scale_factor;\
922 if (nb > 0 && !dtp->u.p.g0_no_blanks)\
924 p = write_block (dtp, nb);\
927 if (result == FAILURE)\
929 if (unlikely (is_char4_unit (dtp)))\
931 gfc_char4_t *p4 = (gfc_char4_t *) p;\
932 memset4 (p4, pad, nb);\
935 memset (p, pad, nb);\
939 OUTPUT_FLOAT_FMT_G(4)
941 OUTPUT_FLOAT_FMT_G(8)
943 #ifdef HAVE_GFC_REAL_10
944 OUTPUT_FLOAT_FMT_G(10)
947 #ifdef HAVE_GFC_REAL_16
948 OUTPUT_FLOAT_FMT_G(16)
951 #undef OUTPUT_FLOAT_FMT_G
954 /* Define a macro to build code for write_float. */
956 /* Note: Before output_float is called, snprintf is used to print to buffer the
957 number in the format +D.DDDDe+ddd. For an N digit exponent, this gives us
958 (MIN_FIELD_WIDTH-5)-N digits after the decimal point, plus another one
959 before the decimal point.
961 # The result will always contain a decimal point, even if no
964 - The converted value is to be left adjusted on the field boundary
966 + A sign (+ or -) always be placed before a number
968 MIN_FIELD_WIDTH minimum field width
970 * (ndigits-1) is used as the precision
972 e format: [-]d.ddde±dd where there is one digit before the
973 decimal-point character and the number of digits after it is
974 equal to the precision. The exponent always contains at least two
975 digits; if the value is zero, the exponent is 00. */
978 snprintf (buffer, size, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
979 "e", ndigits - 1, tmp);
982 snprintf (buffer, size, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
983 "Le", ndigits - 1, tmp);
986 #if defined(GFC_REAL_16_IS_FLOAT128)
988 __qmath_(quadmath_snprintf) (buffer, sizeof buffer, \
989 "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
990 "Qe", ndigits - 1, tmp);
993 #define WRITE_FLOAT(x,y)\
996 tmp = * (GFC_REAL_ ## x *)source;\
997 sign_bit = signbit (tmp);\
998 if (!isfinite (tmp))\
1000 write_infnan (dtp, f, isnan (tmp), sign_bit);\
1003 tmp = sign_bit ? -tmp : tmp;\
1004 zero_flag = (tmp == 0.0);\
1008 if (f->format != FMT_G)\
1009 output_float (dtp, f, buffer, size, sign_bit, zero_flag, ndigits, \
1012 output_float_FMT_G_ ## x (dtp, f, tmp, buffer, size, sign_bit, \
1013 zero_flag, ndigits, edigits);\
1016 /* Output a real number according to its format. */
1019 write_float (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
1022 #if defined(HAVE_GFC_REAL_16) || __LDBL_DIG__ > 18
1023 # define MIN_FIELD_WIDTH 48
1025 # define MIN_FIELD_WIDTH 31
1027 #define STR(x) STR1(x)
1030 /* This must be large enough to accurately hold any value. */
1031 char buffer[MIN_FIELD_WIDTH+1];
1032 int sign_bit, ndigits, edigits;
1036 size = MIN_FIELD_WIDTH+1;
1038 /* printf pads blanks for us on the exponent so we just need it big enough
1039 to handle the largest number of exponent digits expected. */
1042 if (f->format == FMT_F || f->format == FMT_EN || f->format == FMT_G
1043 || ((f->format == FMT_D || f->format == FMT_E)
1044 && dtp->u.p.scale_factor != 0))
1046 /* Always convert at full precision to avoid double rounding. */
1047 ndigits = MIN_FIELD_WIDTH - 4 - edigits;
1051 /* The number of digits is known, so let printf do the rounding. */
1052 if (f->format == FMT_ES)
1053 ndigits = f->u.real.d + 1;
1055 ndigits = f->u.real.d;
1056 if (ndigits > MIN_FIELD_WIDTH - 4 - edigits)
1057 ndigits = MIN_FIELD_WIDTH - 4 - edigits;
1070 #ifdef HAVE_GFC_REAL_10
1075 #ifdef HAVE_GFC_REAL_16
1077 # ifdef GFC_REAL_16_IS_FLOAT128
1085 internal_error (NULL, "bad real kind");