1 /* Copyright (C) 2007, 2008, 2009 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 95 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, sign_bit);
117 sign = calculate_sign (dtp, 0);
119 /* Handle special cases. */
123 /* For this one we choose to not output a decimal point.
125 if (w == 1 && ft == FMT_F)
127 out = write_block (dtp, w);
136 /* Normalize the fractional component. */
137 buffer[2] = buffer[1];
140 /* Figure out where to place the decimal point. */
144 nbefore = e + dtp->u.p.scale_factor;
164 i = dtp->u.p.scale_factor;
165 if (d <= 0 && i == 0)
167 generate_error (&dtp->common, LIBERROR_FORMAT, "Precision not "
168 "greater than zero in format specifier 'E' or 'D'");
171 if (i <= -d || i >= d + 2)
173 generate_error (&dtp->common, LIBERROR_FORMAT, "Scale factor "
174 "out of range in format specifier 'E' or 'D'");
190 nafter = (d - i) + 1;
206 /* The exponent must be a multiple of three, with 1-3 digits before
207 the decimal point. */
216 nbefore = 3 - nbefore;
235 /* Should never happen. */
236 internal_error (&dtp->common, "Unexpected format token");
239 /* Round the value. The value being rounded is an unsigned magnitude.
240 The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */
241 switch (dtp->u.p.current_unit->round_status)
243 case ROUND_ZERO: /* Do nothing and truncation occurs. */
256 /* Round compatible unless there is a tie. A tie is a 5 with
257 all trailing zero's. */
259 if (digits[i] == '5')
261 for(i++ ; i < ndigits; i++)
263 if (digits[i] != '0')
266 /* It is a tie so round to even. */
267 switch (digits[nafter])
274 /* If odd, round away from zero to even. */
277 /* If even, skip rounding, truncate to even. */
282 case ROUND_PROCDEFINED:
283 case ROUND_UNSPECIFIED:
284 case ROUND_COMPATIBLE:
286 /* Just fall through and do the actual rounding. */
291 if (nbefore + nafter == 0)
294 if (nzero_real == d && digits[0] >= rchar)
296 /* We rounded to zero but shouldn't have */
303 else if (nbefore + nafter < ndigits)
305 ndigits = nbefore + nafter;
307 if (digits[i] >= rchar)
309 /* Propagate the carry. */
310 for (i--; i >= 0; i--)
312 if (digits[i] != '9')
322 /* The carry overflowed. Fortunately we have some spare
323 space at the start of the buffer. We may discard some
324 digits, but this is ok because we already know they are
338 else if (ft == FMT_EN)
355 /* Calculate the format of the exponent field. */
359 for (i = abs (e); i >= 10; i /= 10)
364 /* Width not specified. Must be no more than 3 digits. */
365 if (e > 999 || e < -999)
370 if (e > 99 || e < -99)
376 /* Exponent width specified, check it is wide enough. */
377 if (edigits > f->u.real.e)
380 edigits = f->u.real.e + 2;
386 /* Zero values always output as positive, even if the value was negative
388 for (i = 0; i < ndigits; i++)
390 if (digits[i] != '0')
395 /* The output is zero, so set the sign according to the sign bit unless
396 -fno-sign-zero was specified. */
397 if (compile_options.sign_zero == 1)
398 sign = calculate_sign (dtp, sign_bit);
400 sign = calculate_sign (dtp, 0);
403 /* Pick a field size if none was specified. */
405 w = nbefore + nzero + nafter + (sign != S_NONE ? 2 : 1);
407 /* Work out how much padding is needed. */
408 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
412 if (dtp->u.p.g0_no_blanks)
418 /* Create the ouput buffer. */
419 out = write_block (dtp, w);
423 /* Check the value fits in the specified field width. */
424 if (nblanks < 0 || edigits == -1)
430 /* See if we have space for a zero before the decimal point. */
431 if (nbefore == 0 && nblanks > 0)
439 /* Pad to full field width. */
441 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
443 memset (out, ' ', nblanks);
447 /* Output the initial sign (if any). */
450 else if (sign == S_MINUS)
453 /* Output an optional leading zero. */
457 /* Output the part before the decimal point, padding with zeros. */
460 if (nbefore > ndigits)
463 memcpy (out, digits, i);
471 memcpy (out, digits, i);
479 /* Output the decimal point. */
480 *(out++) = dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? '.' : ',';
482 /* Output leading zeros after the decimal point. */
485 for (i = 0; i < nzero; i++)
489 /* Output digits after the decimal point, padding with zeros. */
492 if (nafter > ndigits)
497 memcpy (out, digits, i);
506 /* Output the exponent. */
515 snprintf (buffer, size, "%+0*d", edigits, e);
517 sprintf (buffer, "%+0*d", edigits, e);
519 memcpy (out, buffer, edigits);
522 if (dtp->u.p.no_leading_blank)
525 memset( out , ' ' , nblanks );
526 dtp->u.p.no_leading_blank = 0;
531 #undef MIN_FIELD_WIDTH
535 /* Write "Infinite" or "Nan" as appropriate for the given format. */
538 write_infnan (st_parameter_dt *dtp, const fnode *f, int isnan_flag, int sign_bit)
543 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
547 /* If the field width is zero, the processor must select a width
548 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
551 p = write_block (dtp, nb);
566 /* If the sign is negative and the width is 3, there is
567 insufficient room to output '-Inf', so output asterisks */
575 /* The negative sign is mandatory */
581 /* The positive sign is optional, but we output it for
587 /* We have room, so output 'Infinity' */
588 memcpy(p + nb - 8, "Infinity", 8);
591 /* For the case of width equals 8, there is not enough room
592 for the sign and 'Infinity' so we go with 'Inf' */
593 memcpy(p + nb - 3, "Inf", 3);
595 if (nb < 9 && nb > 3)
596 p[nb - 4] = fin; /* Put the sign in front of Inf */
598 p[nb - 9] = fin; /* Put the sign in front of Infinity */
601 memcpy(p + nb - 3, "NaN", 3);
607 /* Returns the value of 10**d. */
609 #define CALCULATE_EXP(x) \
610 inline static GFC_REAL_ ## x \
611 calculate_exp_ ## x (int d)\
614 GFC_REAL_ ## x r = 1.0;\
615 for (i = 0; i< (d >= 0 ? d : -d); i++)\
617 r = (d >= 0) ? r : 1.0 / r;\
625 #ifdef HAVE_GFC_REAL_10
629 #ifdef HAVE_GFC_REAL_16
634 /* Generate corresponding I/O format for FMT_G and output.
635 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
636 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
638 Data Magnitude Equivalent Conversion
639 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
640 m = 0 F(w-n).(d-1), n' '
641 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
642 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
643 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
644 ................ ..........
645 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
646 m >= 10**d-0.5 Ew.d[Ee]
648 notes: for Gw.d , n' ' means 4 blanks
649 for Gw.dEe, n' ' means e+2 blanks */
651 #define OUTPUT_FLOAT_FMT_G(x) \
653 output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
654 GFC_REAL_ ## x m, char *buffer, size_t size, \
655 int sign_bit, bool zero_flag, int ndigits, int edigits) \
657 int e = f->u.real.e;\
658 int d = f->u.real.d;\
659 int w = f->u.real.w;\
661 GFC_REAL_ ## x rexp_d;\
665 int save_scale_factor, nb = 0;\
667 save_scale_factor = dtp->u.p.scale_factor;\
668 newf = (fnode *) get_mem (sizeof (fnode));\
670 rexp_d = calculate_exp_ ## x (-d);\
671 if ((m > 0.0 && m < 0.1 - 0.05 * rexp_d) || (rexp_d * (m + 0.5) >= 1.0) ||\
672 ((m == 0.0) && !(compile_options.allow_std & GFC_STD_F2003)))\
674 newf->format = FMT_E;\
690 GFC_REAL_ ## x temp;\
691 mid = (low + high) / 2;\
693 temp = (calculate_exp_ ## x (mid - 1) * (1 - 0.5 * rexp_d));\
698 if (ubound == lbound + 1)\
705 if (ubound == lbound + 1)\
724 newf->format = FMT_F;\
725 newf->u.real.w = f->u.real.w - nb;\
728 newf->u.real.d = d - 1;\
730 newf->u.real.d = - (mid - d - 1);\
732 dtp->u.p.scale_factor = 0;\
735 output_float (dtp, newf, buffer, size, sign_bit, zero_flag, ndigits, \
737 dtp->u.p.scale_factor = save_scale_factor;\
741 if (nb > 0 && !dtp->u.p.g0_no_blanks)\
743 p = write_block (dtp, nb);\
746 memset (p, ' ', nb);\
750 OUTPUT_FLOAT_FMT_G(4)
752 OUTPUT_FLOAT_FMT_G(8)
754 #ifdef HAVE_GFC_REAL_10
755 OUTPUT_FLOAT_FMT_G(10)
758 #ifdef HAVE_GFC_REAL_16
759 OUTPUT_FLOAT_FMT_G(16)
762 #undef OUTPUT_FLOAT_FMT_G
765 /* Define a macro to build code for write_float. */
767 /* Note: Before output_float is called, sprintf is used to print to buffer the
768 number in the format +D.DDDDe+ddd. For an N digit exponent, this gives us
769 (MIN_FIELD_WIDTH-5)-N digits after the decimal point, plus another one
770 before the decimal point.
772 # The result will always contain a decimal point, even if no
775 - The converted value is to be left adjusted on the field boundary
777 + A sign (+ or -) always be placed before a number
779 MIN_FIELD_WIDTH minimum field width
781 * (ndigits-1) is used as the precision
783 e format: [-]d.ddde±dd where there is one digit before the
784 decimal-point character and the number of digits after it is
785 equal to the precision. The exponent always contains at least two
786 digits; if the value is zero, the exponent is 00. */
791 snprintf (buffer, size, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
792 "e", ndigits - 1, tmp);
795 snprintf (buffer, size, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
796 "Le", ndigits - 1, tmp);
801 sprintf (buffer, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
802 "e", ndigits - 1, tmp);
805 sprintf (buffer, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
806 "Le", ndigits - 1, tmp);
810 #define WRITE_FLOAT(x,y)\
813 tmp = * (GFC_REAL_ ## x *)source;\
814 sign_bit = signbit (tmp);\
815 if (!isfinite (tmp))\
817 write_infnan (dtp, f, isnan (tmp), sign_bit);\
820 tmp = sign_bit ? -tmp : tmp;\
821 if (f->u.real.d == 0 && f->format == FMT_F\
822 && dtp->u.p.scale_factor == 0)\
829 zero_flag = (tmp == 0.0);\
833 if (f->format != FMT_G)\
834 output_float (dtp, f, buffer, size, sign_bit, zero_flag, ndigits, \
837 output_float_FMT_G_ ## x (dtp, f, tmp, buffer, size, sign_bit, \
838 zero_flag, ndigits, edigits);\
841 /* Output a real number according to its format. */
844 write_float (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
847 #if defined(HAVE_GFC_REAL_16) && __LDBL_DIG__ > 18
848 # define MIN_FIELD_WIDTH 46
850 # define MIN_FIELD_WIDTH 31
852 #define STR(x) STR1(x)
855 /* This must be large enough to accurately hold any value. */
856 char buffer[MIN_FIELD_WIDTH+1];
857 int sign_bit, ndigits, edigits;
861 size = MIN_FIELD_WIDTH+1;
863 /* printf pads blanks for us on the exponent so we just need it big enough
864 to handle the largest number of exponent digits expected. */
867 if (f->format == FMT_F || f->format == FMT_EN || f->format == FMT_G
868 || ((f->format == FMT_D || f->format == FMT_E)
869 && dtp->u.p.scale_factor != 0))
871 /* Always convert at full precision to avoid double rounding. */
872 ndigits = MIN_FIELD_WIDTH - 4 - edigits;
876 /* The number of digits is known, so let printf do the rounding. */
877 if (f->format == FMT_ES)
878 ndigits = f->u.real.d + 1;
880 ndigits = f->u.real.d;
881 if (ndigits > MIN_FIELD_WIDTH - 4 - edigits)
882 ndigits = MIN_FIELD_WIDTH - 4 - edigits;
895 #ifdef HAVE_GFC_REAL_10
900 #ifdef HAVE_GFC_REAL_16
906 internal_error (NULL, "bad real kind");