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");
225 /* Round the value. The value being rounded is an unsigned magnitude.
226 The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */
227 switch (dtp->u.p.current_unit->round_status)
229 case ROUND_ZERO: /* Do nothing and truncation occurs. */
240 /* Round compatible unless there is a tie. A tie is a 5 with
241 all trailing zero's. */
242 i = nafter + nbefore;
243 if (digits[i] == '5')
245 for(i++ ; i < ndigits; i++)
247 if (digits[i] != '0')
250 /* It is a tie so round to even. */
251 switch (digits[nafter + nbefore - 1])
258 /* If odd, round away from zero to even. */
261 /* If even, skip rounding, truncate to even. */
266 case ROUND_PROCDEFINED:
267 case ROUND_UNSPECIFIED:
268 case ROUND_COMPATIBLE:
276 if (w > 0 && d == 0 && p == 0)
278 /* Scan for trailing zeros to see if we really need to round it. */
279 for(i = nbefore + nafter; i < ndigits; i++)
281 if (digits[i] != '0')
288 if (nbefore + nafter == 0)
291 if (nzero_real == d && digits[0] >= rchar)
293 /* We rounded to zero but shouldn't have */
300 else if (nbefore + nafter < ndigits)
302 i = ndigits = nbefore + nafter;
303 if (digits[i] >= rchar)
305 /* Propagate the carry. */
306 for (i--; i >= 0; i--)
308 if (digits[i] != '9')
318 /* The carry overflowed. Fortunately we have some spare
319 space at the start of the buffer. We may discard some
320 digits, but this is ok because we already know they are
334 else if (ft == FMT_EN)
351 /* Calculate the format of the exponent field. */
355 for (i = abs (e); i >= 10; i /= 10)
360 /* Width not specified. Must be no more than 3 digits. */
361 if (e > 999 || e < -999)
366 if (e > 99 || e < -99)
372 /* Exponent width specified, check it is wide enough. */
373 if (edigits > f->u.real.e)
376 edigits = f->u.real.e + 2;
382 /* Scan the digits string and count the number of zeros. If we make it
383 all the way through the loop, we know the value is zero after the
384 rounding completed above. */
385 for (i = 0; i < ndigits; i++)
387 if (digits[i] != '0')
391 /* To format properly, we need to know if the rounded result is zero and if
392 so, we set the zero_flag which may have been already set for
397 /* The output is zero, so set the sign according to the sign bit unless
398 -fno-sign-zero was specified. */
399 if (compile_options.sign_zero == 1)
400 sign = calculate_sign (dtp, sign_bit);
402 sign = calculate_sign (dtp, 0);
405 /* Pick a field size if none was specified, taking into account small
406 values that may have been rounded to zero. */
410 w = d + (sign != S_NONE ? 2 : 1) + (d == 0 ? 1 : 0);
413 w = nbefore + nzero + nafter + (sign != S_NONE ? 2 : 1);
418 /* Work out how much padding is needed. */
419 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
423 if (dtp->u.p.g0_no_blanks)
429 /* Create the ouput buffer. */
430 out = write_block (dtp, w);
434 /* Check the value fits in the specified field width. */
435 if (nblanks < 0 || edigits == -1 || w == 1 || (w == 2 && sign != S_NONE))
437 if (unlikely (is_char4_unit (dtp)))
439 gfc_char4_t *out4 = (gfc_char4_t *) out;
440 memset4 (out4, '*', w);
447 /* See if we have space for a zero before the decimal point. */
448 if (nbefore == 0 && nblanks > 0)
456 /* For internal character(kind=4) units, we duplicate the code used for
457 regular output slightly modified. This needs to be maintained
458 consistent with the regular code that follows this block. */
459 if (unlikely (is_char4_unit (dtp)))
461 gfc_char4_t *out4 = (gfc_char4_t *) out;
462 /* Pad to full field width. */
464 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
466 memset4 (out4, ' ', nblanks);
470 /* Output the initial sign (if any). */
473 else if (sign == S_MINUS)
476 /* Output an optional leading zero. */
480 /* Output the part before the decimal point, padding with zeros. */
483 if (nbefore > ndigits)
486 memcpy4 (out4, digits, i);
494 memcpy4 (out4, digits, i);
502 /* Output the decimal point. */
503 *(out4++) = dtp->u.p.current_unit->decimal_status
504 == DECIMAL_POINT ? '.' : ',';
506 /* Output leading zeros after the decimal point. */
509 for (i = 0; i < nzero; i++)
513 /* Output digits after the decimal point, padding with zeros. */
516 if (nafter > ndigits)
521 memcpy4 (out4, digits, i);
530 /* Output the exponent. */
538 snprintf (buffer, size, "%+0*d", edigits, e);
539 memcpy4 (out4, buffer, edigits);
542 if (dtp->u.p.no_leading_blank)
545 memset4 (out4, ' ' , nblanks);
546 dtp->u.p.no_leading_blank = 0;
549 } /* End of character(kind=4) internal unit code. */
551 /* Pad to full field width. */
553 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
555 memset (out, ' ', nblanks);
559 /* Output the initial sign (if any). */
562 else if (sign == S_MINUS)
565 /* Output an optional leading zero. */
569 /* Output the part before the decimal point, padding with zeros. */
572 if (nbefore > ndigits)
575 memcpy (out, digits, i);
583 memcpy (out, digits, i);
591 /* Output the decimal point. */
592 *(out++) = dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? '.' : ',';
594 /* Output leading zeros after the decimal point. */
597 for (i = 0; i < nzero; i++)
601 /* Output digits after the decimal point, padding with zeros. */
604 if (nafter > ndigits)
609 memcpy (out, digits, i);
618 /* Output the exponent. */
626 snprintf (buffer, size, "%+0*d", edigits, e);
627 memcpy (out, buffer, edigits);
630 if (dtp->u.p.no_leading_blank)
633 memset( out , ' ' , nblanks );
634 dtp->u.p.no_leading_blank = 0;
639 #undef MIN_FIELD_WIDTH
644 /* Write "Infinite" or "Nan" as appropriate for the given format. */
647 write_infnan (st_parameter_dt *dtp, const fnode *f, int isnan_flag, int sign_bit)
654 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
656 sign = calculate_sign (dtp, sign_bit);
657 mark = (sign == S_PLUS || sign == S_MINUS) ? 8 : 7;
661 /* If the field width is zero, the processor must select a width
662 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
664 if ((nb == 0) || dtp->u.p.g0_no_blanks)
669 nb = (sign == S_PLUS || sign == S_MINUS) ? 4 : 3;
671 p = write_block (dtp, nb);
676 if (unlikely (is_char4_unit (dtp)))
678 gfc_char4_t *p4 = (gfc_char4_t *) p;
679 memset4 (p4, '*', nb);
686 if (unlikely (is_char4_unit (dtp)))
688 gfc_char4_t *p4 = (gfc_char4_t *) p;
689 memset4 (p4, ' ', nb);
698 /* If the sign is negative and the width is 3, there is
699 insufficient room to output '-Inf', so output asterisks */
702 if (unlikely (is_char4_unit (dtp)))
704 gfc_char4_t *p4 = (gfc_char4_t *) p;
705 memset4 (p4, '*', nb);
711 /* The negative sign is mandatory */
715 /* The positive sign is optional, but we output it for
719 if (unlikely (is_char4_unit (dtp)))
721 gfc_char4_t *p4 = (gfc_char4_t *) p;
724 /* We have room, so output 'Infinity' */
725 memcpy4 (p4 + nb - 8, "Infinity", 8);
727 /* For the case of width equals mark, there is not enough room
728 for the sign and 'Infinity' so we go with 'Inf' */
729 memcpy4 (p4 + nb - 3, "Inf", 3);
731 if (sign == S_PLUS || sign == S_MINUS)
733 if (nb < 9 && nb > 3)
734 /* Put the sign in front of Inf */
735 p4[nb - 4] = (gfc_char4_t) fin;
737 /* Put the sign in front of Infinity */
738 p4[nb - 9] = (gfc_char4_t) fin;
744 /* We have room, so output 'Infinity' */
745 memcpy(p + nb - 8, "Infinity", 8);
747 /* For the case of width equals 8, there is not enough room
748 for the sign and 'Infinity' so we go with 'Inf' */
749 memcpy(p + nb - 3, "Inf", 3);
751 if (sign == S_PLUS || sign == S_MINUS)
753 if (nb < 9 && nb > 3)
754 p[nb - 4] = fin; /* Put the sign in front of Inf */
756 p[nb - 9] = fin; /* Put the sign in front of Infinity */
761 if (unlikely (is_char4_unit (dtp)))
763 gfc_char4_t *p4 = (gfc_char4_t *) p;
764 memcpy4 (p4 + nb - 3, "NaN", 3);
767 memcpy(p + nb - 3, "NaN", 3);
774 /* Returns the value of 10**d. */
776 #define CALCULATE_EXP(x) \
777 static GFC_REAL_ ## x \
778 calculate_exp_ ## x (int d)\
781 GFC_REAL_ ## x r = 1.0;\
782 for (i = 0; i< (d >= 0 ? d : -d); i++)\
784 r = (d >= 0) ? r : 1.0 / r;\
792 #ifdef HAVE_GFC_REAL_10
796 #ifdef HAVE_GFC_REAL_16
801 /* Generate corresponding I/O format for FMT_G and output.
802 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
803 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
805 Data Magnitude Equivalent Conversion
806 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
807 m = 0 F(w-n).(d-1), n' '
808 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
809 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
810 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
811 ................ ..........
812 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
813 m >= 10**d-0.5 Ew.d[Ee]
815 notes: for Gw.d , n' ' means 4 blanks
816 for Gw.dEe, n' ' means e+2 blanks
817 for rounding modes adjustment, r, See Fortran F2008 10.7.5.2.2
818 the asm volatile is required for 32-bit x86 platforms. */
820 #define OUTPUT_FLOAT_FMT_G(x) \
822 output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
823 GFC_REAL_ ## x m, char *buffer, size_t size, \
824 int sign_bit, bool zero_flag, int ndigits, \
825 int edigits, int comp_d) \
827 int e = f->u.real.e;\
828 int d = f->u.real.d;\
829 int w = f->u.real.w;\
831 GFC_REAL_ ## x rexp_d, r = 0.5;\
835 int save_scale_factor, nb = 0;\
838 save_scale_factor = dtp->u.p.scale_factor;\
839 newf = (fnode *) get_mem (sizeof (fnode));\
841 switch (dtp->u.p.current_unit->round_status)\
844 r = sign_bit ? 1.0 : 0.0;\
856 rexp_d = calculate_exp_ ## x (-d);\
857 if ((m > 0.0 && ((m < 0.1 - 0.1 * r * rexp_d) || (rexp_d * (m + r) >= 1.0)))\
858 || ((m == 0.0) && !(compile_options.allow_std\
859 & (GFC_STD_F2003 | GFC_STD_F2008))))\
861 newf->format = FMT_E;\
863 newf->u.real.d = d - comp_d;\
877 volatile GFC_REAL_ ## x temp;\
878 mid = (low + high) / 2;\
880 temp = (calculate_exp_ ## x (mid - 1) * (1 - r * rexp_d));\
885 if (ubound == lbound + 1)\
892 if (ubound == lbound + 1)\
906 nb = e <= 0 ? 4 : e + 2;\
907 nb = nb >= w ? w - 1 : nb;\
908 newf->format = FMT_F;\
909 newf->u.real.w = w - nb;\
910 newf->u.real.d = m == 0.0 ? d - 1 : -(mid - d - 1) ;\
911 dtp->u.p.scale_factor = 0;\
914 result = output_float (dtp, newf, buffer, size, sign_bit, zero_flag, \
916 dtp->u.p.scale_factor = save_scale_factor;\
920 if (nb > 0 && !dtp->u.p.g0_no_blanks)\
922 p = write_block (dtp, nb);\
925 if (result == FAILURE)\
927 if (unlikely (is_char4_unit (dtp)))\
929 gfc_char4_t *p4 = (gfc_char4_t *) p;\
930 memset4 (p4, pad, nb);\
933 memset (p, pad, nb);\
937 OUTPUT_FLOAT_FMT_G(4)
939 OUTPUT_FLOAT_FMT_G(8)
941 #ifdef HAVE_GFC_REAL_10
942 OUTPUT_FLOAT_FMT_G(10)
945 #ifdef HAVE_GFC_REAL_16
946 OUTPUT_FLOAT_FMT_G(16)
949 #undef OUTPUT_FLOAT_FMT_G
952 /* Define a macro to build code for write_float. */
954 /* Note: Before output_float is called, snprintf is used to print to buffer the
955 number in the format +D.DDDDe+ddd. For an N digit exponent, this gives us
956 (MIN_FIELD_WIDTH-5)-N digits after the decimal point, plus another one
957 before the decimal point.
959 # The result will always contain a decimal point, even if no
962 - The converted value is to be left adjusted on the field boundary
964 + A sign (+ or -) always be placed before a number
966 MIN_FIELD_WIDTH minimum field width
968 * (ndigits-1) is used as the precision
970 e format: [-]d.ddde±dd where there is one digit before the
971 decimal-point character and the number of digits after it is
972 equal to the precision. The exponent always contains at least two
973 digits; if the value is zero, the exponent is 00. */
976 snprintf (buffer, size, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
977 "e", ndigits - 1, tmp);
980 snprintf (buffer, size, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
981 "Le", ndigits - 1, tmp);
984 #if defined(GFC_REAL_16_IS_FLOAT128)
986 __qmath_(quadmath_snprintf) (buffer, sizeof buffer, \
987 "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
988 "Qe", ndigits - 1, tmp);
991 #define WRITE_FLOAT(x,y)\
994 tmp = * (GFC_REAL_ ## x *)source;\
995 sign_bit = signbit (tmp);\
996 if (!isfinite (tmp))\
998 write_infnan (dtp, f, isnan (tmp), sign_bit);\
1001 tmp = sign_bit ? -tmp : tmp;\
1002 zero_flag = (tmp == 0.0);\
1006 if (f->format != FMT_G)\
1007 output_float (dtp, f, buffer, size, sign_bit, zero_flag, ndigits, \
1010 output_float_FMT_G_ ## x (dtp, f, tmp, buffer, size, sign_bit, \
1011 zero_flag, ndigits, edigits, comp_d);\
1014 /* Output a real number according to its format. */
1017 write_float (st_parameter_dt *dtp, const fnode *f, const char *source, \
1018 int len, int comp_d)
1021 #if defined(HAVE_GFC_REAL_16) || __LDBL_DIG__ > 18
1022 # define MIN_FIELD_WIDTH 49
1024 # define MIN_FIELD_WIDTH 32
1026 #define STR(x) STR1(x)
1029 /* This must be large enough to accurately hold any value. */
1030 char buffer[MIN_FIELD_WIDTH+1];
1031 int sign_bit, ndigits, edigits;
1035 size = MIN_FIELD_WIDTH+1;
1037 /* printf pads blanks for us on the exponent so we just need it big enough
1038 to handle the largest number of exponent digits expected. */
1041 /* Always convert at full precision to avoid double rounding. */
1042 ndigits = MIN_FIELD_WIDTH - 4 - edigits;
1054 #ifdef HAVE_GFC_REAL_10
1059 #ifdef HAVE_GFC_REAL_16
1061 # ifdef GFC_REAL_16_IS_FLOAT128
1069 internal_error (NULL, "bad real kind");