* ru.po: Update.
[official-gcc.git] / libgfortran / io / write_float.def
blobd32440f6f9bb600ff999aff7fb4989c036108c22
1 /* Copyright (C) 2007-2016 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)
11 any later version.
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/>. */
27 #include "config.h"
29 typedef enum
30 { S_NONE, S_MINUS, S_PLUS }
31 sign_t;
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. */
36 static sign_t
37 calculate_sign (st_parameter_dt *dtp, int negative_flag)
39 sign_t s = S_NONE;
41 if (negative_flag)
42 s = S_MINUS;
43 else
44 switch (dtp->u.p.sign_status)
46 case SIGN_SP: /* Show sign. */
47 s = S_PLUS;
48 break;
49 case SIGN_SS: /* Suppress sign. */
50 s = S_NONE;
51 break;
52 case SIGN_S: /* Processor defined. */
53 case SIGN_UNSPECIFIED:
54 s = options.optional_plus ? S_PLUS : S_NONE;
55 break;
58 return s;
62 /* Determine the precision except for EN format. For G format,
63 determines an upper bound to be used for sizing the buffer. */
65 static int
66 determine_precision (st_parameter_dt * dtp, const fnode * f, int len)
68 int precision = f->u.real.d;
70 switch (f->format)
72 case FMT_F:
73 case FMT_G:
74 precision += dtp->u.p.scale_factor;
75 break;
76 case FMT_ES:
77 /* Scale factor has no effect on output. */
78 break;
79 case FMT_E:
80 case FMT_D:
81 /* See F2008 10.7.2.3.3.6 */
82 if (dtp->u.p.scale_factor <= 0)
83 precision += dtp->u.p.scale_factor - 1;
84 break;
85 default:
86 return -1;
89 /* If the scale factor has a large negative value, we must do our
90 own rounding? Use ROUND='NEAREST', which should be what snprintf
91 is using as well. */
92 if (precision < 0 &&
93 (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED
94 || dtp->u.p.current_unit->round_status == ROUND_PROCDEFINED))
95 dtp->u.p.current_unit->round_status = ROUND_NEAREST;
97 /* Add extra guard digits up to at least full precision when we do
98 our own rounding. */
99 if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED
100 && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED)
102 precision += 2 * len + 4;
103 if (precision < 0)
104 precision = 0;
107 return precision;
111 /* Output a real number according to its format which is FMT_G free. */
113 static bool
114 output_float (st_parameter_dt *dtp, const fnode *f, char *buffer, size_t size,
115 int nprinted, int precision, int sign_bit, bool zero_flag)
117 char *out;
118 char *digits;
119 int e, w, d, p, i;
120 char expchar, rchar;
121 format_token ft;
122 /* Number of digits before the decimal point. */
123 int nbefore;
124 /* Number of zeros after the decimal point. */
125 int nzero;
126 /* Number of digits after the decimal point. */
127 int nafter;
128 int leadzero;
129 int nblanks;
130 int ndigits, edigits;
131 sign_t sign;
133 ft = f->format;
134 w = f->u.real.w;
135 d = f->u.real.d;
136 p = dtp->u.p.scale_factor;
138 rchar = '5';
140 /* We should always know the field width and precision. */
141 if (d < 0)
142 internal_error (&dtp->common, "Unspecified precision");
144 sign = calculate_sign (dtp, sign_bit);
146 /* Calculate total number of digits. */
147 if (ft == FMT_F)
148 ndigits = nprinted - 2;
149 else
150 ndigits = precision + 1;
152 /* Read the exponent back in. */
153 if (ft != FMT_F)
154 e = atoi (&buffer[ndigits + 3]) + 1;
155 else
156 e = 0;
158 /* Make sure zero comes out as 0.0e0. */
159 if (zero_flag)
160 e = 0;
162 /* Normalize the fractional component. */
163 if (ft != FMT_F)
165 buffer[2] = buffer[1];
166 digits = &buffer[2];
168 else
169 digits = &buffer[1];
171 /* Figure out where to place the decimal point. */
172 switch (ft)
174 case FMT_F:
175 nbefore = ndigits - precision;
176 /* Make sure the decimal point is a '.'; depending on the
177 locale, this might not be the case otherwise. */
178 digits[nbefore] = '.';
179 if (p != 0)
181 if (p > 0)
184 memmove (digits + nbefore, digits + nbefore + 1, p);
185 digits[nbefore + p] = '.';
186 nbefore += p;
187 nafter = d;
188 nzero = 0;
190 else /* p < 0 */
192 if (nbefore + p >= 0)
194 nzero = 0;
195 memmove (digits + nbefore + p + 1, digits + nbefore + p, -p);
196 nbefore += p;
197 digits[nbefore] = '.';
198 nafter = d;
200 else
202 nzero = -(nbefore + p);
203 memmove (digits + 1, digits, nbefore);
204 nafter = d - nzero;
205 if (nafter == 0 && d > 0)
207 /* This is needed to get the correct rounding. */
208 memmove (digits + 1, digits, ndigits - 1);
209 digits[1] = '0';
210 nafter = 1;
211 nzero = d - 1;
213 else if (nafter < 0)
215 /* Reset digits to 0 in order to get correct rounding
216 towards infinity. */
217 for (i = 0; i < ndigits; i++)
218 digits[i] = '0';
219 digits[ndigits - 1] = '1';
220 nafter = d;
221 nzero = 0;
223 nbefore = 0;
227 else
229 nzero = 0;
230 nafter = d;
233 while (digits[0] == '0' && nbefore > 0)
235 digits++;
236 nbefore--;
237 ndigits--;
240 expchar = 0;
241 /* If we need to do rounding ourselves, get rid of the dot by
242 moving the fractional part. */
243 if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED
244 && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED)
245 memmove (digits + nbefore, digits + nbefore + 1, ndigits - nbefore);
246 break;
248 case FMT_E:
249 case FMT_D:
250 i = dtp->u.p.scale_factor;
251 if (d <= 0 && p == 0)
253 generate_error (&dtp->common, LIBERROR_FORMAT, "Precision not "
254 "greater than zero in format specifier 'E' or 'D'");
255 return false;
257 if (p <= -d || p >= d + 2)
259 generate_error (&dtp->common, LIBERROR_FORMAT, "Scale factor "
260 "out of range in format specifier 'E' or 'D'");
261 return false;
264 if (!zero_flag)
265 e -= p;
266 if (p < 0)
268 nbefore = 0;
269 nzero = -p;
270 nafter = d + p;
272 else if (p > 0)
274 nbefore = p;
275 nzero = 0;
276 nafter = (d - p) + 1;
278 else /* p == 0 */
280 nbefore = 0;
281 nzero = 0;
282 nafter = d;
285 if (ft == FMT_E)
286 expchar = 'E';
287 else
288 expchar = 'D';
289 break;
291 case FMT_EN:
292 /* The exponent must be a multiple of three, with 1-3 digits before
293 the decimal point. */
294 if (!zero_flag)
295 e--;
296 if (e >= 0)
297 nbefore = e % 3;
298 else
300 nbefore = (-e) % 3;
301 if (nbefore != 0)
302 nbefore = 3 - nbefore;
304 e -= nbefore;
305 nbefore++;
306 nzero = 0;
307 nafter = d;
308 expchar = 'E';
309 break;
311 case FMT_ES:
312 if (!zero_flag)
313 e--;
314 nbefore = 1;
315 nzero = 0;
316 nafter = d;
317 expchar = 'E';
318 break;
320 default:
321 /* Should never happen. */
322 internal_error (&dtp->common, "Unexpected format token");
325 if (zero_flag)
326 goto skip;
328 /* Round the value. The value being rounded is an unsigned magnitude. */
329 switch (dtp->u.p.current_unit->round_status)
331 /* For processor defined and unspecified rounding we use
332 snprintf to print the exact number of digits needed, and thus
333 let snprintf handle the rounding. On system claiming support
334 for IEEE 754, this ought to be round to nearest, ties to
335 even, corresponding to the Fortran ROUND='NEAREST'. */
336 case ROUND_PROCDEFINED:
337 case ROUND_UNSPECIFIED:
338 case ROUND_ZERO: /* Do nothing and truncation occurs. */
339 goto skip;
340 case ROUND_UP:
341 if (sign_bit)
342 goto skip;
343 goto updown;
344 case ROUND_DOWN:
345 if (!sign_bit)
346 goto skip;
347 goto updown;
348 case ROUND_NEAREST:
349 /* Round compatible unless there is a tie. A tie is a 5 with
350 all trailing zero's. */
351 i = nafter + nbefore;
352 if (digits[i] == '5')
354 for(i++ ; i < ndigits; i++)
356 if (digits[i] != '0')
357 goto do_rnd;
359 /* It is a tie so round to even. */
360 switch (digits[nafter + nbefore - 1])
362 case '1':
363 case '3':
364 case '5':
365 case '7':
366 case '9':
367 /* If odd, round away from zero to even. */
368 break;
369 default:
370 /* If even, skip rounding, truncate to even. */
371 goto skip;
374 /* Fall through. */
375 /* The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */
376 case ROUND_COMPATIBLE:
377 rchar = '5';
378 goto do_rnd;
381 updown:
383 rchar = '0';
384 if (ft != FMT_F && w > 0 && d == 0 && p == 0)
385 nbefore = 1;
386 /* Scan for trailing zeros to see if we really need to round it. */
387 for(i = nbefore + nafter; i < ndigits; i++)
389 if (digits[i] != '0')
390 goto do_rnd;
392 goto skip;
394 do_rnd:
396 if (nbefore + nafter == 0)
397 /* Handle the case Fw.0 and value < 1.0 */
399 ndigits = 0;
400 if (digits[0] >= rchar)
402 /* We rounded to zero but shouldn't have */
403 nbefore = 1;
404 digits--;
405 digits[0] = '1';
406 ndigits = 1;
409 else if (nbefore + nafter < ndigits)
411 i = ndigits = nbefore + nafter;
412 if (digits[i] >= rchar)
414 /* Propagate the carry. */
415 for (i--; i >= 0; i--)
417 if (digits[i] != '9')
419 digits[i]++;
420 break;
422 digits[i] = '0';
425 if (i < 0)
427 /* The carry overflowed. Fortunately we have some spare
428 space at the start of the buffer. We may discard some
429 digits, but this is ok because we already know they are
430 zero. */
431 digits--;
432 digits[0] = '1';
433 if (ft == FMT_F)
435 if (nzero > 0)
437 nzero--;
438 nafter++;
440 else
441 nbefore++;
443 else if (ft == FMT_EN)
445 nbefore++;
446 if (nbefore == 4)
448 nbefore = 1;
449 e += 3;
452 else
453 e++;
458 skip:
460 /* Calculate the format of the exponent field. */
461 if (expchar && !(dtp->u.p.g0_no_blanks && e == 0))
463 edigits = 1;
464 for (i = abs (e); i >= 10; i /= 10)
465 edigits++;
467 if (f->u.real.e < 0)
469 /* Width not specified. Must be no more than 3 digits. */
470 if (e > 999 || e < -999)
471 edigits = -1;
472 else
474 edigits = 4;
475 if (e > 99 || e < -99)
476 expchar = ' ';
479 else
481 /* Exponent width specified, check it is wide enough. */
482 if (edigits > f->u.real.e)
483 edigits = -1;
484 else
485 edigits = f->u.real.e + 2;
488 else
489 edigits = 0;
491 /* Scan the digits string and count the number of zeros. If we make it
492 all the way through the loop, we know the value is zero after the
493 rounding completed above. */
494 int hasdot = 0;
495 for (i = 0; i < ndigits + hasdot; i++)
497 if (digits[i] == '.')
498 hasdot = 1;
499 else if (digits[i] != '0')
500 break;
503 /* To format properly, we need to know if the rounded result is zero and if
504 so, we set the zero_flag which may have been already set for
505 actual zero. */
506 if (i == ndigits + hasdot)
508 zero_flag = true;
509 /* The output is zero, so set the sign according to the sign bit unless
510 -fno-sign-zero was specified. */
511 if (compile_options.sign_zero == 1)
512 sign = calculate_sign (dtp, sign_bit);
513 else
514 sign = calculate_sign (dtp, 0);
517 /* Pick a field size if none was specified, taking into account small
518 values that may have been rounded to zero. */
519 if (w <= 0)
521 if (zero_flag)
522 w = d + (sign != S_NONE ? 2 : 1) + (d == 0 ? 1 : 0);
523 else
525 w = nbefore + nzero + nafter + (sign != S_NONE ? 2 : 1);
526 w = w == 1 ? 2 : w;
530 /* Work out how much padding is needed. */
531 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
532 if (sign != S_NONE)
533 nblanks--;
535 /* See if we have space for a zero before the decimal point. */
536 if (nbefore == 0 && nblanks > 0)
538 leadzero = 1;
539 nblanks--;
541 else
542 leadzero = 0;
544 if (dtp->u.p.g0_no_blanks)
546 w -= nblanks;
547 nblanks = 0;
550 /* Create the ouput buffer. */
551 out = write_block (dtp, w);
552 if (out == NULL)
553 return false;
555 /* Check the value fits in the specified field width. */
556 if (nblanks < 0 || edigits == -1 || w == 1 || (w == 2 && sign != S_NONE))
558 if (unlikely (is_char4_unit (dtp)))
560 gfc_char4_t *out4 = (gfc_char4_t *) out;
561 memset4 (out4, '*', w);
562 return false;
564 star_fill (out, w);
565 return false;
568 /* For internal character(kind=4) units, we duplicate the code used for
569 regular output slightly modified. This needs to be maintained
570 consistent with the regular code that follows this block. */
571 if (unlikely (is_char4_unit (dtp)))
573 gfc_char4_t *out4 = (gfc_char4_t *) out;
574 /* Pad to full field width. */
576 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
578 memset4 (out4, ' ', nblanks);
579 out4 += nblanks;
582 /* Output the initial sign (if any). */
583 if (sign == S_PLUS)
584 *(out4++) = '+';
585 else if (sign == S_MINUS)
586 *(out4++) = '-';
588 /* Output an optional leading zero. */
589 if (leadzero)
590 *(out4++) = '0';
592 /* Output the part before the decimal point, padding with zeros. */
593 if (nbefore > 0)
595 if (nbefore > ndigits)
597 i = ndigits;
598 memcpy4 (out4, digits, i);
599 ndigits = 0;
600 while (i < nbefore)
601 out4[i++] = '0';
603 else
605 i = nbefore;
606 memcpy4 (out4, digits, i);
607 ndigits -= i;
610 digits += i;
611 out4 += nbefore;
614 /* Output the decimal point. */
615 *(out4++) = dtp->u.p.current_unit->decimal_status
616 == DECIMAL_POINT ? '.' : ',';
617 if (ft == FMT_F
618 && (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED
619 || dtp->u.p.current_unit->round_status == ROUND_PROCDEFINED))
620 digits++;
622 /* Output leading zeros after the decimal point. */
623 if (nzero > 0)
625 for (i = 0; i < nzero; i++)
626 *(out4++) = '0';
629 /* Output digits after the decimal point, padding with zeros. */
630 if (nafter > 0)
632 if (nafter > ndigits)
633 i = ndigits;
634 else
635 i = nafter;
637 memcpy4 (out4, digits, i);
638 while (i < nafter)
639 out4[i++] = '0';
641 digits += i;
642 ndigits -= i;
643 out4 += nafter;
646 /* Output the exponent. */
647 if (expchar && !(dtp->u.p.g0_no_blanks && e == 0))
649 if (expchar != ' ')
651 *(out4++) = expchar;
652 edigits--;
654 snprintf (buffer, size, "%+0*d", edigits, e);
655 memcpy4 (out4, buffer, edigits);
658 if (dtp->u.p.no_leading_blank)
660 out4 += edigits;
661 memset4 (out4, ' ' , nblanks);
662 dtp->u.p.no_leading_blank = 0;
664 return true;
665 } /* End of character(kind=4) internal unit code. */
667 /* Pad to full field width. */
669 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
671 memset (out, ' ', nblanks);
672 out += nblanks;
675 /* Output the initial sign (if any). */
676 if (sign == S_PLUS)
677 *(out++) = '+';
678 else if (sign == S_MINUS)
679 *(out++) = '-';
681 /* Output an optional leading zero. */
682 if (leadzero)
683 *(out++) = '0';
685 /* Output the part before the decimal point, padding with zeros. */
686 if (nbefore > 0)
688 if (nbefore > ndigits)
690 i = ndigits;
691 memcpy (out, digits, i);
692 ndigits = 0;
693 while (i < nbefore)
694 out[i++] = '0';
696 else
698 i = nbefore;
699 memcpy (out, digits, i);
700 ndigits -= i;
703 digits += i;
704 out += nbefore;
707 /* Output the decimal point. */
708 *(out++) = dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? '.' : ',';
709 if (ft == FMT_F
710 && (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED
711 || dtp->u.p.current_unit->round_status == ROUND_PROCDEFINED))
712 digits++;
714 /* Output leading zeros after the decimal point. */
715 if (nzero > 0)
717 for (i = 0; i < nzero; i++)
718 *(out++) = '0';
721 /* Output digits after the decimal point, padding with zeros. */
722 if (nafter > 0)
724 if (nafter > ndigits)
725 i = ndigits;
726 else
727 i = nafter;
729 memcpy (out, digits, i);
730 while (i < nafter)
731 out[i++] = '0';
733 digits += i;
734 ndigits -= i;
735 out += nafter;
738 /* Output the exponent. */
739 if (expchar && !(dtp->u.p.g0_no_blanks && e == 0))
741 if (expchar != ' ')
743 *(out++) = expchar;
744 edigits--;
746 snprintf (buffer, size, "%+0*d", edigits, e);
747 memcpy (out, buffer, edigits);
750 if (dtp->u.p.no_leading_blank)
752 out += edigits;
753 memset( out , ' ' , nblanks );
754 dtp->u.p.no_leading_blank = 0;
757 return true;
761 /* Write "Infinite" or "Nan" as appropriate for the given format. */
763 static void
764 write_infnan (st_parameter_dt *dtp, const fnode *f, int isnan_flag, int sign_bit)
766 char * p, fin;
767 int nb = 0;
768 sign_t sign;
769 int mark;
771 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
773 sign = calculate_sign (dtp, sign_bit);
774 mark = (sign == S_PLUS || sign == S_MINUS) ? 8 : 7;
776 nb = f->u.real.w;
778 /* If the field width is zero, the processor must select a width
779 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
781 if ((nb == 0) || dtp->u.p.g0_no_blanks)
783 if (isnan_flag)
784 nb = 3;
785 else
786 nb = (sign == S_PLUS || sign == S_MINUS) ? 4 : 3;
788 p = write_block (dtp, nb);
789 if (p == NULL)
790 return;
791 if (nb < 3)
793 if (unlikely (is_char4_unit (dtp)))
795 gfc_char4_t *p4 = (gfc_char4_t *) p;
796 memset4 (p4, '*', nb);
798 else
799 memset (p, '*', nb);
800 return;
803 if (unlikely (is_char4_unit (dtp)))
805 gfc_char4_t *p4 = (gfc_char4_t *) p;
806 memset4 (p4, ' ', nb);
808 else
809 memset(p, ' ', nb);
811 if (!isnan_flag)
813 if (sign_bit)
815 /* If the sign is negative and the width is 3, there is
816 insufficient room to output '-Inf', so output asterisks */
817 if (nb == 3)
819 if (unlikely (is_char4_unit (dtp)))
821 gfc_char4_t *p4 = (gfc_char4_t *) p;
822 memset4 (p4, '*', nb);
824 else
825 memset (p, '*', nb);
826 return;
828 /* The negative sign is mandatory */
829 fin = '-';
831 else
832 /* The positive sign is optional, but we output it for
833 consistency */
834 fin = '+';
836 if (unlikely (is_char4_unit (dtp)))
838 gfc_char4_t *p4 = (gfc_char4_t *) p;
840 if (nb > mark)
841 /* We have room, so output 'Infinity' */
842 memcpy4 (p4 + nb - 8, "Infinity", 8);
843 else
844 /* For the case of width equals mark, there is not enough room
845 for the sign and 'Infinity' so we go with 'Inf' */
846 memcpy4 (p4 + nb - 3, "Inf", 3);
848 if (sign == S_PLUS || sign == S_MINUS)
850 if (nb < 9 && nb > 3)
851 /* Put the sign in front of Inf */
852 p4[nb - 4] = (gfc_char4_t) fin;
853 else if (nb > 8)
854 /* Put the sign in front of Infinity */
855 p4[nb - 9] = (gfc_char4_t) fin;
857 return;
860 if (nb > mark)
861 /* We have room, so output 'Infinity' */
862 memcpy(p + nb - 8, "Infinity", 8);
863 else
864 /* For the case of width equals 8, there is not enough room
865 for the sign and 'Infinity' so we go with 'Inf' */
866 memcpy(p + nb - 3, "Inf", 3);
868 if (sign == S_PLUS || sign == S_MINUS)
870 if (nb < 9 && nb > 3)
871 p[nb - 4] = fin; /* Put the sign in front of Inf */
872 else if (nb > 8)
873 p[nb - 9] = fin; /* Put the sign in front of Infinity */
876 else
878 if (unlikely (is_char4_unit (dtp)))
880 gfc_char4_t *p4 = (gfc_char4_t *) p;
881 memcpy4 (p4 + nb - 3, "NaN", 3);
883 else
884 memcpy(p + nb - 3, "NaN", 3);
886 return;
891 /* Returns the value of 10**d. */
893 #define CALCULATE_EXP(x) \
894 static GFC_REAL_ ## x \
895 calculate_exp_ ## x (int d)\
897 int i;\
898 GFC_REAL_ ## x r = 1.0;\
899 for (i = 0; i< (d >= 0 ? d : -d); i++)\
900 r *= 10;\
901 r = (d >= 0) ? r : 1.0 / r;\
902 return r;\
905 CALCULATE_EXP(4)
907 CALCULATE_EXP(8)
909 #ifdef HAVE_GFC_REAL_10
910 CALCULATE_EXP(10)
911 #endif
913 #ifdef HAVE_GFC_REAL_16
914 CALCULATE_EXP(16)
915 #endif
916 #undef CALCULATE_EXP
919 /* Define a macro to build code for write_float. */
921 /* Note: Before output_float is called, snprintf is used to print to buffer the
922 number in the format +D.DDDDe+ddd.
924 # The result will always contain a decimal point, even if no
925 digits follow it
927 - The converted value is to be left adjusted on the field boundary
929 + A sign (+ or -) always be placed before a number
931 * prec is used as the precision
933 e format: [-]d.ddde±dd where there is one digit before the
934 decimal-point character and the number of digits after it is
935 equal to the precision. The exponent always contains at least two
936 digits; if the value is zero, the exponent is 00. */
939 #define TOKENPASTE(x, y) TOKENPASTE2(x, y)
940 #define TOKENPASTE2(x, y) x ## y
942 #define DTOA(suff,prec,val) TOKENPASTE(DTOA2,suff)(prec,val)
944 #define DTOA2(prec,val) \
945 snprintf (buffer, size, "%+-#.*e", (prec), (val))
947 #define DTOA2L(prec,val) \
948 snprintf (buffer, size, "%+-#.*Le", (prec), (val))
951 #if defined(GFC_REAL_16_IS_FLOAT128)
952 #define DTOA2Q(prec,val) \
953 quadmath_snprintf (buffer, size, "%+-#.*Qe", (prec), (val))
954 #endif
956 #define FDTOA(suff,prec,val) TOKENPASTE(FDTOA2,suff)(prec,val)
958 /* For F format, we print to the buffer with f format. */
959 #define FDTOA2(prec,val) \
960 snprintf (buffer, size, "%+-#.*f", (prec), (val))
962 #define FDTOA2L(prec,val) \
963 snprintf (buffer, size, "%+-#.*Lf", (prec), (val))
966 #if defined(GFC_REAL_16_IS_FLOAT128)
967 #define FDTOA2Q(prec,val) \
968 quadmath_snprintf (buffer, size, "%+-#.*Qf", \
969 (prec), (val))
970 #endif
974 /* Generate corresponding I/O format for FMT_G and output.
975 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
976 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
978 Data Magnitude Equivalent Conversion
979 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
980 m = 0 F(w-n).(d-1), n' '
981 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
982 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
983 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
984 ................ ..........
985 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
986 m >= 10**d-0.5 Ew.d[Ee]
988 notes: for Gw.d , n' ' means 4 blanks
989 for Gw.dEe, n' ' means e+2 blanks
990 for rounding modes adjustment, r, See Fortran F2008 10.7.5.2.2
991 the asm volatile is required for 32-bit x86 platforms. */
993 #define OUTPUT_FLOAT_FMT_G(x,y) \
994 static void \
995 output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
996 GFC_REAL_ ## x m, char *buffer, size_t size, \
997 int sign_bit, bool zero_flag, int comp_d) \
999 int e = f->u.real.e;\
1000 int d = f->u.real.d;\
1001 int w = f->u.real.w;\
1002 fnode newf;\
1003 GFC_REAL_ ## x exp_d, r = 0.5, r_sc;\
1004 int low, high, mid;\
1005 int ubound, lbound;\
1006 char *p, pad = ' ';\
1007 int save_scale_factor, nb = 0;\
1008 bool result;\
1009 int nprinted, precision;\
1010 volatile GFC_REAL_ ## x temp;\
1012 save_scale_factor = dtp->u.p.scale_factor;\
1014 switch (dtp->u.p.current_unit->round_status)\
1016 case ROUND_ZERO:\
1017 r = sign_bit ? 1.0 : 0.0;\
1018 break;\
1019 case ROUND_UP:\
1020 r = 1.0;\
1021 break;\
1022 case ROUND_DOWN:\
1023 r = 0.0;\
1024 break;\
1025 default:\
1026 break;\
1029 exp_d = calculate_exp_ ## x (d);\
1030 r_sc = (1 - r / exp_d);\
1031 temp = 0.1 * r_sc;\
1032 if ((m > 0.0 && ((m < temp) || (r >= (exp_d - m))))\
1033 || ((m == 0.0) && !(compile_options.allow_std\
1034 & (GFC_STD_F2003 | GFC_STD_F2008)))\
1035 || d == 0)\
1037 newf.format = FMT_E;\
1038 newf.u.real.w = w;\
1039 newf.u.real.d = d - comp_d;\
1040 newf.u.real.e = e;\
1041 nb = 0;\
1042 precision = determine_precision (dtp, &newf, x);\
1043 nprinted = DTOA(y,precision,m); \
1044 goto finish;\
1047 mid = 0;\
1048 low = 0;\
1049 high = d + 1;\
1050 lbound = 0;\
1051 ubound = d + 1;\
1053 while (low <= high)\
1055 mid = (low + high) / 2;\
1057 temp = (calculate_exp_ ## x (mid - 1) * r_sc);\
1059 if (m < temp)\
1061 ubound = mid;\
1062 if (ubound == lbound + 1)\
1063 break;\
1064 high = mid - 1;\
1066 else if (m > temp)\
1068 lbound = mid;\
1069 if (ubound == lbound + 1)\
1071 mid ++;\
1072 break;\
1074 low = mid + 1;\
1076 else\
1078 mid++;\
1079 break;\
1083 nb = e <= 0 ? 4 : e + 2;\
1084 nb = nb >= w ? w - 1 : nb;\
1085 newf.format = FMT_F;\
1086 newf.u.real.w = w - nb;\
1087 newf.u.real.d = m == 0.0 ? d - 1 : -(mid - d - 1) ;\
1088 dtp->u.p.scale_factor = 0;\
1089 precision = determine_precision (dtp, &newf, x); \
1090 nprinted = FDTOA(y,precision,m); \
1092 finish:\
1093 result = output_float (dtp, &newf, buffer, size, nprinted, precision,\
1094 sign_bit, zero_flag);\
1095 dtp->u.p.scale_factor = save_scale_factor;\
1098 if (nb > 0 && !dtp->u.p.g0_no_blanks)\
1100 p = write_block (dtp, nb);\
1101 if (p == NULL)\
1102 return;\
1103 if (!result)\
1104 pad = '*';\
1105 if (unlikely (is_char4_unit (dtp)))\
1107 gfc_char4_t *p4 = (gfc_char4_t *) p;\
1108 memset4 (p4, pad, nb);\
1110 else \
1111 memset (p, pad, nb);\
1115 OUTPUT_FLOAT_FMT_G(4,)
1117 OUTPUT_FLOAT_FMT_G(8,)
1119 #ifdef HAVE_GFC_REAL_10
1120 OUTPUT_FLOAT_FMT_G(10,L)
1121 #endif
1123 #ifdef HAVE_GFC_REAL_16
1124 # ifdef GFC_REAL_16_IS_FLOAT128
1125 OUTPUT_FLOAT_FMT_G(16,Q)
1126 #else
1127 OUTPUT_FLOAT_FMT_G(16,L)
1128 #endif
1129 #endif
1131 #undef OUTPUT_FLOAT_FMT_G
1134 /* EN format is tricky since the number of significant digits depends
1135 on the magnitude. Solve it by first printing a temporary value and
1136 figure out the number of significant digits from the printed
1137 exponent. Values y, 0.95*10.0**e <= y <10.0**e, are rounded to
1138 10.0**e even when the final result will not be rounded to 10.0**e.
1139 For these values the exponent returned by atoi has to be decremented
1140 by one. The values y in the ranges
1141 (1000.0-0.5*10.0**(-d))*10.0**(3*n) <= y < 10.0*(3*(n+1))
1142 (100.0-0.5*10.0**(-d))*10.0**(3*n) <= y < 10.0*(3*n+2)
1143 (10.0-0.5*10.0**(-d))*10.0**(3*n) <= y < 10.0*(3*n+1)
1144 are correctly rounded respectively to 1.0...0*10.0*(3*(n+1)),
1145 100.0...0*10.0*(3*n), and 10.0...0*10.0*(3*n), where 0...0
1146 represents d zeroes, by the lines 279 to 297. */
1148 #define EN_PREC(x,y)\
1150 volatile GFC_REAL_ ## x tmp, one = 1.0;\
1151 tmp = * (GFC_REAL_ ## x *)source;\
1152 if (isfinite (tmp))\
1154 nprinted = DTOA(y,0,tmp);\
1155 int e = atoi (&buffer[4]);\
1156 if (buffer[1] == '1')\
1158 tmp = (calculate_exp_ ## x (-e)) * tmp;\
1159 tmp = one - (tmp < 0 ? -tmp : tmp); \
1160 if (tmp > 0)\
1161 e = e - 1;\
1163 nbefore = e%3;\
1164 if (nbefore < 0)\
1165 nbefore = 3 + nbefore;\
1167 else\
1168 nprinted = -1;\
1171 static int
1172 determine_en_precision (st_parameter_dt *dtp, const fnode *f,
1173 const char *source, int len)
1175 int nprinted;
1176 char buffer[10];
1177 const size_t size = 10;
1178 int nbefore; /* digits before decimal point - 1. */
1180 switch (len)
1182 case 4:
1183 EN_PREC(4,)
1184 break;
1186 case 8:
1187 EN_PREC(8,)
1188 break;
1190 #ifdef HAVE_GFC_REAL_10
1191 case 10:
1192 EN_PREC(10,L)
1193 break;
1194 #endif
1195 #ifdef HAVE_GFC_REAL_16
1196 case 16:
1197 # ifdef GFC_REAL_16_IS_FLOAT128
1198 EN_PREC(16,Q)
1199 # else
1200 EN_PREC(16,L)
1201 # endif
1202 break;
1203 #endif
1204 default:
1205 internal_error (NULL, "bad real kind");
1208 if (nprinted == -1)
1209 return -1;
1211 int prec = f->u.real.d + nbefore;
1212 if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED
1213 && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED)
1214 prec += 2 * len + 4;
1215 return prec;
1219 #define WRITE_FLOAT(x,y)\
1221 GFC_REAL_ ## x tmp;\
1222 tmp = * (GFC_REAL_ ## x *)source;\
1223 sign_bit = signbit (tmp);\
1224 if (!isfinite (tmp))\
1226 write_infnan (dtp, f, isnan (tmp), sign_bit);\
1227 return;\
1229 tmp = sign_bit ? -tmp : tmp;\
1230 zero_flag = (tmp == 0.0);\
1231 if (f->format == FMT_G)\
1232 output_float_FMT_G_ ## x (dtp, f, tmp, buffer, size, sign_bit, \
1233 zero_flag, comp_d);\
1234 else\
1236 if (f->format == FMT_F)\
1237 nprinted = FDTOA(y,precision,tmp); \
1238 else\
1239 nprinted = DTOA(y,precision,tmp); \
1240 output_float (dtp, f, buffer, size, nprinted, precision,\
1241 sign_bit, zero_flag);\
1245 /* Output a real number according to its format. */
1247 static void
1248 write_float (st_parameter_dt *dtp, const fnode *f, const char *source, \
1249 int len, int comp_d)
1251 int sign_bit, nprinted;
1252 int precision; /* Precision for snprintf call. */
1253 bool zero_flag;
1255 if (f->format != FMT_EN)
1256 precision = determine_precision (dtp, f, len);
1257 else
1258 precision = determine_en_precision (dtp, f, source, len);
1260 /* 4932 is the maximum exponent of long double and quad precision, 3
1261 extra characters for the sign, the decimal point, and the
1262 trailing null, and finally some extra digits depending on the
1263 requested precision. */
1264 const size_t size = 4932 + 3 + precision;
1265 #define BUF_STACK_SZ 5000
1266 char buf_stack[BUF_STACK_SZ];
1267 char *buffer;
1268 if (size > BUF_STACK_SZ)
1269 buffer = xmalloc (size);
1270 else
1271 buffer = buf_stack;
1273 switch (len)
1275 case 4:
1276 WRITE_FLOAT(4,)
1277 break;
1279 case 8:
1280 WRITE_FLOAT(8,)
1281 break;
1283 #ifdef HAVE_GFC_REAL_10
1284 case 10:
1285 WRITE_FLOAT(10,L)
1286 break;
1287 #endif
1288 #ifdef HAVE_GFC_REAL_16
1289 case 16:
1290 # ifdef GFC_REAL_16_IS_FLOAT128
1291 WRITE_FLOAT(16,Q)
1292 # else
1293 WRITE_FLOAT(16,L)
1294 # endif
1295 break;
1296 #endif
1297 default:
1298 internal_error (NULL, "bad real kind");
1300 if (size > BUF_STACK_SZ)
1301 free (buffer);