Update copyright years in libgfortran.
[gcc.git] / libgfortran / io / write_float.def
1 /* Copyright (C) 2007-2013 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
5
6 This file is part of the GNU Fortran runtime library (libgfortran).
7
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.
12
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.
17
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.
21
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/>. */
26
27 #include "config.h"
28
29 typedef enum
30 { S_NONE, S_MINUS, S_PLUS }
31 sign_t;
32
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. */
35
36 static sign_t
37 calculate_sign (st_parameter_dt *dtp, int negative_flag)
38 {
39 sign_t s = S_NONE;
40
41 if (negative_flag)
42 s = S_MINUS;
43 else
44 switch (dtp->u.p.sign_status)
45 {
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;
56 }
57
58 return s;
59 }
60
61
62 /* Determine the precision except for EN format. For G format,
63 determines an upper bound to be used for sizing the buffer. */
64
65 static int
66 determine_precision (st_parameter_dt * dtp, const fnode * f, int len)
67 {
68 int precision = f->u.real.d;
69
70 switch (f->format)
71 {
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;
87 }
88
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;
96
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)
101 {
102 precision += 2 * len + 4;
103 if (precision < 0)
104 precision = 0;
105 }
106
107 return precision;
108 }
109
110
111 /* Output a real number according to its format which is FMT_G free. */
112
113 static try
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)
116 {
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 /* Number of zeros after the decimal point, whatever the precision. */
129 int nzero_real;
130 int leadzero;
131 int nblanks;
132 int ndigits, edigits;
133 sign_t sign;
134
135 ft = f->format;
136 w = f->u.real.w;
137 d = f->u.real.d;
138 p = dtp->u.p.scale_factor;
139
140 rchar = '5';
141 nzero_real = -1;
142
143 /* We should always know the field width and precision. */
144 if (d < 0)
145 internal_error (&dtp->common, "Unspecified precision");
146
147 sign = calculate_sign (dtp, sign_bit);
148
149 /* Calculate total number of digits. */
150 if (ft == FMT_F)
151 ndigits = nprinted - 2;
152 else
153 ndigits = precision + 1;
154
155 /* Read the exponent back in. */
156 if (ft != FMT_F)
157 e = atoi (&buffer[ndigits + 3]) + 1;
158 else
159 e = 0;
160
161 /* Make sure zero comes out as 0.0e0. */
162 if (zero_flag)
163 e = 0;
164
165 /* Normalize the fractional component. */
166 if (ft != FMT_F)
167 {
168 buffer[2] = buffer[1];
169 digits = &buffer[2];
170 }
171 else
172 digits = &buffer[1];
173
174 /* Figure out where to place the decimal point. */
175 switch (ft)
176 {
177 case FMT_F:
178 nbefore = ndigits - precision;
179 /* Make sure the decimal point is a '.'; depending on the
180 locale, this might not be the case otherwise. */
181 digits[nbefore] = '.';
182 if (p != 0)
183 {
184 if (p > 0)
185 {
186
187 memmove (digits + nbefore, digits + nbefore + 1, p);
188 digits[nbefore + p] = '.';
189 nbefore += p;
190 nafter = d - p;
191 if (nafter < 0)
192 nafter = 0;
193 nafter = d;
194 nzero = nzero_real = 0;
195 }
196 else /* p < 0 */
197 {
198 if (nbefore + p >= 0)
199 {
200 nzero = 0;
201 memmove (digits + nbefore + p + 1, digits + nbefore + p, -p);
202 nbefore += p;
203 digits[nbefore] = '.';
204 nafter = d;
205 }
206 else
207 {
208 nzero = -(nbefore + p);
209 memmove (digits + 1, digits, nbefore);
210 digits++;
211 nafter = d + nbefore;
212 nbefore = 0;
213 }
214 nzero_real = nzero;
215 if (nzero > d)
216 nzero = d;
217 }
218 }
219 else
220 {
221 nzero = nzero_real = 0;
222 nafter = d;
223 }
224
225 while (digits[0] == '0' && nbefore > 0)
226 {
227 digits++;
228 nbefore--;
229 ndigits--;
230 }
231
232 expchar = 0;
233 /* If we need to do rounding ourselves, get rid of the dot by
234 moving the fractional part. */
235 if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED
236 && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED)
237 memmove (digits + nbefore, digits + nbefore + 1, ndigits - nbefore);
238 break;
239
240 case FMT_E:
241 case FMT_D:
242 i = dtp->u.p.scale_factor;
243 if (d <= 0 && p == 0)
244 {
245 generate_error (&dtp->common, LIBERROR_FORMAT, "Precision not "
246 "greater than zero in format specifier 'E' or 'D'");
247 return FAILURE;
248 }
249 if (p <= -d || p >= d + 2)
250 {
251 generate_error (&dtp->common, LIBERROR_FORMAT, "Scale factor "
252 "out of range in format specifier 'E' or 'D'");
253 return FAILURE;
254 }
255
256 if (!zero_flag)
257 e -= p;
258 if (p < 0)
259 {
260 nbefore = 0;
261 nzero = -p;
262 nafter = d + p;
263 }
264 else if (p > 0)
265 {
266 nbefore = p;
267 nzero = 0;
268 nafter = (d - p) + 1;
269 }
270 else /* p == 0 */
271 {
272 nbefore = 0;
273 nzero = 0;
274 nafter = d;
275 }
276
277 if (ft == FMT_E)
278 expchar = 'E';
279 else
280 expchar = 'D';
281 break;
282
283 case FMT_EN:
284 /* The exponent must be a multiple of three, with 1-3 digits before
285 the decimal point. */
286 if (!zero_flag)
287 e--;
288 if (e >= 0)
289 nbefore = e % 3;
290 else
291 {
292 nbefore = (-e) % 3;
293 if (nbefore != 0)
294 nbefore = 3 - nbefore;
295 }
296 e -= nbefore;
297 nbefore++;
298 nzero = 0;
299 nafter = d;
300 expchar = 'E';
301 break;
302
303 case FMT_ES:
304 if (!zero_flag)
305 e--;
306 nbefore = 1;
307 nzero = 0;
308 nafter = d;
309 expchar = 'E';
310 break;
311
312 default:
313 /* Should never happen. */
314 internal_error (&dtp->common, "Unexpected format token");
315 }
316
317 if (zero_flag)
318 goto skip;
319
320 /* Round the value. The value being rounded is an unsigned magnitude. */
321 switch (dtp->u.p.current_unit->round_status)
322 {
323 /* For processor defined and unspecified rounding we use
324 snprintf to print the exact number of digits needed, and thus
325 let snprintf handle the rounding. On system claiming support
326 for IEEE 754, this ought to be round to nearest, ties to
327 even, corresponding to the Fortran ROUND='NEAREST'. */
328 case ROUND_PROCDEFINED:
329 case ROUND_UNSPECIFIED:
330 case ROUND_ZERO: /* Do nothing and truncation occurs. */
331 goto skip;
332 case ROUND_UP:
333 if (sign_bit)
334 goto skip;
335 goto updown;
336 case ROUND_DOWN:
337 if (!sign_bit)
338 goto skip;
339 goto updown;
340 case ROUND_NEAREST:
341 /* Round compatible unless there is a tie. A tie is a 5 with
342 all trailing zero's. */
343 i = nafter + nbefore;
344 if (digits[i] == '5')
345 {
346 for(i++ ; i < ndigits; i++)
347 {
348 if (digits[i] != '0')
349 goto do_rnd;
350 }
351 /* It is a tie so round to even. */
352 switch (digits[nafter + nbefore - 1])
353 {
354 case '1':
355 case '3':
356 case '5':
357 case '7':
358 case '9':
359 /* If odd, round away from zero to even. */
360 break;
361 default:
362 /* If even, skip rounding, truncate to even. */
363 goto skip;
364 }
365 }
366 /* Fall through. */
367 /* The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */
368 case ROUND_COMPATIBLE:
369 rchar = '5';
370 goto do_rnd;
371 }
372
373 updown:
374
375 rchar = '0';
376 if (w > 0 && d == 0 && p == 0)
377 nbefore = 1;
378 /* Scan for trailing zeros to see if we really need to round it. */
379 for(i = nbefore + nafter; i < ndigits; i++)
380 {
381 if (digits[i] != '0')
382 goto do_rnd;
383 }
384 goto skip;
385
386 do_rnd:
387
388 if (nbefore + nafter == 0)
389 {
390 ndigits = 0;
391 if (nzero_real == d && digits[0] >= rchar)
392 {
393 /* We rounded to zero but shouldn't have */
394 nzero--;
395 nafter = 1;
396 digits[0] = '1';
397 ndigits = 1;
398 }
399 }
400 else if (nbefore + nafter < ndigits)
401 {
402 i = ndigits = nbefore + nafter;
403 if (digits[i] >= rchar)
404 {
405 /* Propagate the carry. */
406 for (i--; i >= 0; i--)
407 {
408 if (digits[i] != '9')
409 {
410 digits[i]++;
411 break;
412 }
413 digits[i] = '0';
414 }
415
416 if (i < 0)
417 {
418 /* The carry overflowed. Fortunately we have some spare
419 space at the start of the buffer. We may discard some
420 digits, but this is ok because we already know they are
421 zero. */
422 digits--;
423 digits[0] = '1';
424 if (ft == FMT_F)
425 {
426 if (nzero > 0)
427 {
428 nzero--;
429 nafter++;
430 }
431 else
432 nbefore++;
433 }
434 else if (ft == FMT_EN)
435 {
436 nbefore++;
437 if (nbefore == 4)
438 {
439 nbefore = 1;
440 e += 3;
441 }
442 }
443 else
444 e++;
445 }
446 }
447 }
448
449 skip:
450
451 /* Calculate the format of the exponent field. */
452 if (expchar)
453 {
454 edigits = 1;
455 for (i = abs (e); i >= 10; i /= 10)
456 edigits++;
457
458 if (f->u.real.e < 0)
459 {
460 /* Width not specified. Must be no more than 3 digits. */
461 if (e > 999 || e < -999)
462 edigits = -1;
463 else
464 {
465 edigits = 4;
466 if (e > 99 || e < -99)
467 expchar = ' ';
468 }
469 }
470 else
471 {
472 /* Exponent width specified, check it is wide enough. */
473 if (edigits > f->u.real.e)
474 edigits = -1;
475 else
476 edigits = f->u.real.e + 2;
477 }
478 }
479 else
480 edigits = 0;
481
482 /* Scan the digits string and count the number of zeros. If we make it
483 all the way through the loop, we know the value is zero after the
484 rounding completed above. */
485 int hasdot = 0;
486 for (i = 0; i < ndigits + hasdot; i++)
487 {
488 if (digits[i] == '.')
489 hasdot = 1;
490 else if (digits[i] != '0')
491 break;
492 }
493
494 /* To format properly, we need to know if the rounded result is zero and if
495 so, we set the zero_flag which may have been already set for
496 actual zero. */
497 if (i == ndigits + hasdot)
498 {
499 zero_flag = true;
500 /* The output is zero, so set the sign according to the sign bit unless
501 -fno-sign-zero was specified. */
502 if (compile_options.sign_zero == 1)
503 sign = calculate_sign (dtp, sign_bit);
504 else
505 sign = calculate_sign (dtp, 0);
506 }
507
508 /* Pick a field size if none was specified, taking into account small
509 values that may have been rounded to zero. */
510 if (w <= 0)
511 {
512 if (zero_flag)
513 w = d + (sign != S_NONE ? 2 : 1) + (d == 0 ? 1 : 0);
514 else
515 {
516 w = nbefore + nzero + nafter + (sign != S_NONE ? 2 : 1);
517 w = w == 1 ? 2 : w;
518 }
519 }
520
521 /* Work out how much padding is needed. */
522 nblanks = w - (nbefore + nzero + nafter + edigits + 1);
523 if (sign != S_NONE)
524 nblanks--;
525
526 if (dtp->u.p.g0_no_blanks)
527 {
528 w -= nblanks;
529 nblanks = 0;
530 }
531
532 /* Create the ouput buffer. */
533 out = write_block (dtp, w);
534 if (out == NULL)
535 return FAILURE;
536
537 /* Check the value fits in the specified field width. */
538 if (nblanks < 0 || edigits == -1 || w == 1 || (w == 2 && sign != S_NONE))
539 {
540 if (unlikely (is_char4_unit (dtp)))
541 {
542 gfc_char4_t *out4 = (gfc_char4_t *) out;
543 memset4 (out4, '*', w);
544 return FAILURE;
545 }
546 star_fill (out, w);
547 return FAILURE;
548 }
549
550 /* See if we have space for a zero before the decimal point. */
551 if (nbefore == 0 && nblanks > 0)
552 {
553 leadzero = 1;
554 nblanks--;
555 }
556 else
557 leadzero = 0;
558
559 /* For internal character(kind=4) units, we duplicate the code used for
560 regular output slightly modified. This needs to be maintained
561 consistent with the regular code that follows this block. */
562 if (unlikely (is_char4_unit (dtp)))
563 {
564 gfc_char4_t *out4 = (gfc_char4_t *) out;
565 /* Pad to full field width. */
566
567 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
568 {
569 memset4 (out4, ' ', nblanks);
570 out4 += nblanks;
571 }
572
573 /* Output the initial sign (if any). */
574 if (sign == S_PLUS)
575 *(out4++) = '+';
576 else if (sign == S_MINUS)
577 *(out4++) = '-';
578
579 /* Output an optional leading zero. */
580 if (leadzero)
581 *(out4++) = '0';
582
583 /* Output the part before the decimal point, padding with zeros. */
584 if (nbefore > 0)
585 {
586 if (nbefore > ndigits)
587 {
588 i = ndigits;
589 memcpy4 (out4, digits, i);
590 ndigits = 0;
591 while (i < nbefore)
592 out4[i++] = '0';
593 }
594 else
595 {
596 i = nbefore;
597 memcpy4 (out4, digits, i);
598 ndigits -= i;
599 }
600
601 digits += i;
602 out4 += nbefore;
603 }
604
605 /* Output the decimal point. */
606 *(out4++) = dtp->u.p.current_unit->decimal_status
607 == DECIMAL_POINT ? '.' : ',';
608 if (ft == FMT_F
609 && (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED
610 || dtp->u.p.current_unit->round_status == ROUND_PROCDEFINED))
611 digits++;
612
613 /* Output leading zeros after the decimal point. */
614 if (nzero > 0)
615 {
616 for (i = 0; i < nzero; i++)
617 *(out4++) = '0';
618 }
619
620 /* Output digits after the decimal point, padding with zeros. */
621 if (nafter > 0)
622 {
623 if (nafter > ndigits)
624 i = ndigits;
625 else
626 i = nafter;
627
628 memcpy4 (out4, digits, i);
629 while (i < nafter)
630 out4[i++] = '0';
631
632 digits += i;
633 ndigits -= i;
634 out4 += nafter;
635 }
636
637 /* Output the exponent. */
638 if (expchar)
639 {
640 if (expchar != ' ')
641 {
642 *(out4++) = expchar;
643 edigits--;
644 }
645 snprintf (buffer, size, "%+0*d", edigits, e);
646 memcpy4 (out4, buffer, edigits);
647 }
648
649 if (dtp->u.p.no_leading_blank)
650 {
651 out4 += edigits;
652 memset4 (out4, ' ' , nblanks);
653 dtp->u.p.no_leading_blank = 0;
654 }
655 return SUCCESS;
656 } /* End of character(kind=4) internal unit code. */
657
658 /* Pad to full field width. */
659
660 if ( ( nblanks > 0 ) && !dtp->u.p.no_leading_blank)
661 {
662 memset (out, ' ', nblanks);
663 out += nblanks;
664 }
665
666 /* Output the initial sign (if any). */
667 if (sign == S_PLUS)
668 *(out++) = '+';
669 else if (sign == S_MINUS)
670 *(out++) = '-';
671
672 /* Output an optional leading zero. */
673 if (leadzero)
674 *(out++) = '0';
675
676 /* Output the part before the decimal point, padding with zeros. */
677 if (nbefore > 0)
678 {
679 if (nbefore > ndigits)
680 {
681 i = ndigits;
682 memcpy (out, digits, i);
683 ndigits = 0;
684 while (i < nbefore)
685 out[i++] = '0';
686 }
687 else
688 {
689 i = nbefore;
690 memcpy (out, digits, i);
691 ndigits -= i;
692 }
693
694 digits += i;
695 out += nbefore;
696 }
697
698 /* Output the decimal point. */
699 *(out++) = dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? '.' : ',';
700 if (ft == FMT_F
701 && (dtp->u.p.current_unit->round_status == ROUND_UNSPECIFIED
702 || dtp->u.p.current_unit->round_status == ROUND_PROCDEFINED))
703 digits++;
704
705 /* Output leading zeros after the decimal point. */
706 if (nzero > 0)
707 {
708 for (i = 0; i < nzero; i++)
709 *(out++) = '0';
710 }
711
712 /* Output digits after the decimal point, padding with zeros. */
713 if (nafter > 0)
714 {
715 if (nafter > ndigits)
716 i = ndigits;
717 else
718 i = nafter;
719
720 memcpy (out, digits, i);
721 while (i < nafter)
722 out[i++] = '0';
723
724 digits += i;
725 ndigits -= i;
726 out += nafter;
727 }
728
729 /* Output the exponent. */
730 if (expchar)
731 {
732 if (expchar != ' ')
733 {
734 *(out++) = expchar;
735 edigits--;
736 }
737 snprintf (buffer, size, "%+0*d", edigits, e);
738 memcpy (out, buffer, edigits);
739 }
740
741 if (dtp->u.p.no_leading_blank)
742 {
743 out += edigits;
744 memset( out , ' ' , nblanks );
745 dtp->u.p.no_leading_blank = 0;
746 }
747
748 return SUCCESS;
749 }
750
751
752 /* Write "Infinite" or "Nan" as appropriate for the given format. */
753
754 static void
755 write_infnan (st_parameter_dt *dtp, const fnode *f, int isnan_flag, int sign_bit)
756 {
757 char * p, fin;
758 int nb = 0;
759 sign_t sign;
760 int mark;
761
762 if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
763 {
764 sign = calculate_sign (dtp, sign_bit);
765 mark = (sign == S_PLUS || sign == S_MINUS) ? 8 : 7;
766
767 nb = f->u.real.w;
768
769 /* If the field width is zero, the processor must select a width
770 not zero. 4 is chosen to allow output of '-Inf' or '+Inf' */
771
772 if ((nb == 0) || dtp->u.p.g0_no_blanks)
773 {
774 if (isnan_flag)
775 nb = 3;
776 else
777 nb = (sign == S_PLUS || sign == S_MINUS) ? 4 : 3;
778 }
779 p = write_block (dtp, nb);
780 if (p == NULL)
781 return;
782 if (nb < 3)
783 {
784 if (unlikely (is_char4_unit (dtp)))
785 {
786 gfc_char4_t *p4 = (gfc_char4_t *) p;
787 memset4 (p4, '*', nb);
788 }
789 else
790 memset (p, '*', nb);
791 return;
792 }
793
794 if (unlikely (is_char4_unit (dtp)))
795 {
796 gfc_char4_t *p4 = (gfc_char4_t *) p;
797 memset4 (p4, ' ', nb);
798 }
799 else
800 memset(p, ' ', nb);
801
802 if (!isnan_flag)
803 {
804 if (sign_bit)
805 {
806 /* If the sign is negative and the width is 3, there is
807 insufficient room to output '-Inf', so output asterisks */
808 if (nb == 3)
809 {
810 if (unlikely (is_char4_unit (dtp)))
811 {
812 gfc_char4_t *p4 = (gfc_char4_t *) p;
813 memset4 (p4, '*', nb);
814 }
815 else
816 memset (p, '*', nb);
817 return;
818 }
819 /* The negative sign is mandatory */
820 fin = '-';
821 }
822 else
823 /* The positive sign is optional, but we output it for
824 consistency */
825 fin = '+';
826
827 if (unlikely (is_char4_unit (dtp)))
828 {
829 gfc_char4_t *p4 = (gfc_char4_t *) p;
830
831 if (nb > mark)
832 /* We have room, so output 'Infinity' */
833 memcpy4 (p4 + nb - 8, "Infinity", 8);
834 else
835 /* For the case of width equals mark, there is not enough room
836 for the sign and 'Infinity' so we go with 'Inf' */
837 memcpy4 (p4 + nb - 3, "Inf", 3);
838
839 if (sign == S_PLUS || sign == S_MINUS)
840 {
841 if (nb < 9 && nb > 3)
842 /* Put the sign in front of Inf */
843 p4[nb - 4] = (gfc_char4_t) fin;
844 else if (nb > 8)
845 /* Put the sign in front of Infinity */
846 p4[nb - 9] = (gfc_char4_t) fin;
847 }
848 return;
849 }
850
851 if (nb > mark)
852 /* We have room, so output 'Infinity' */
853 memcpy(p + nb - 8, "Infinity", 8);
854 else
855 /* For the case of width equals 8, there is not enough room
856 for the sign and 'Infinity' so we go with 'Inf' */
857 memcpy(p + nb - 3, "Inf", 3);
858
859 if (sign == S_PLUS || sign == S_MINUS)
860 {
861 if (nb < 9 && nb > 3)
862 p[nb - 4] = fin; /* Put the sign in front of Inf */
863 else if (nb > 8)
864 p[nb - 9] = fin; /* Put the sign in front of Infinity */
865 }
866 }
867 else
868 {
869 if (unlikely (is_char4_unit (dtp)))
870 {
871 gfc_char4_t *p4 = (gfc_char4_t *) p;
872 memcpy4 (p4 + nb - 3, "NaN", 3);
873 }
874 else
875 memcpy(p + nb - 3, "NaN", 3);
876 }
877 return;
878 }
879 }
880
881
882 /* Returns the value of 10**d. */
883
884 #define CALCULATE_EXP(x) \
885 static GFC_REAL_ ## x \
886 calculate_exp_ ## x (int d)\
887 {\
888 int i;\
889 GFC_REAL_ ## x r = 1.0;\
890 for (i = 0; i< (d >= 0 ? d : -d); i++)\
891 r *= 10;\
892 r = (d >= 0) ? r : 1.0 / r;\
893 return r;\
894 }
895
896 CALCULATE_EXP(4)
897
898 CALCULATE_EXP(8)
899
900 #ifdef HAVE_GFC_REAL_10
901 CALCULATE_EXP(10)
902 #endif
903
904 #ifdef HAVE_GFC_REAL_16
905 CALCULATE_EXP(16)
906 #endif
907 #undef CALCULATE_EXP
908
909
910 /* Define a macro to build code for write_float. */
911
912 /* Note: Before output_float is called, snprintf is used to print to buffer the
913 number in the format +D.DDDDe+ddd.
914
915 # The result will always contain a decimal point, even if no
916 digits follow it
917
918 - The converted value is to be left adjusted on the field boundary
919
920 + A sign (+ or -) always be placed before a number
921
922 * prec is used as the precision
923
924 e format: [-]d.ddde±dd where there is one digit before the
925 decimal-point character and the number of digits after it is
926 equal to the precision. The exponent always contains at least two
927 digits; if the value is zero, the exponent is 00. */
928
929
930 #define TOKENPASTE(x, y) TOKENPASTE2(x, y)
931 #define TOKENPASTE2(x, y) x ## y
932
933 #define DTOA(suff,prec,val) TOKENPASTE(DTOA2,suff)(prec,val)
934
935 #define DTOA2(prec,val) \
936 snprintf (buffer, size, "%+-#.*e", (prec), (val))
937
938 #define DTOA2L(prec,val) \
939 snprintf (buffer, size, "%+-#.*Le", (prec), (val))
940
941
942 #if defined(GFC_REAL_16_IS_FLOAT128)
943 #define DTOA2Q(prec,val) \
944 __qmath_(quadmath_snprintf) (buffer, size, "%+-#.*Qe", (prec), (val))
945 #endif
946
947 #define FDTOA(suff,prec,val) TOKENPASTE(FDTOA2,suff)(prec,val)
948
949 /* For F format, we print to the buffer with f format. */
950 #define FDTOA2(prec,val) \
951 snprintf (buffer, size, "%+-#.*f", (prec), (val))
952
953 #define FDTOA2L(prec,val) \
954 snprintf (buffer, size, "%+-#.*Lf", (prec), (val))
955
956
957 #if defined(GFC_REAL_16_IS_FLOAT128)
958 #define FDTOA2Q(prec,val) \
959 __qmath_(quadmath_snprintf) (buffer, size, "%+-#.*Qf", \
960 (prec), (val))
961 #endif
962
963
964 /* Generate corresponding I/O format for FMT_G and output.
965 The rules to translate FMT_G to FMT_E or FMT_F from DEC fortran
966 LRM (table 11-2, Chapter 11, "I/O Formatting", P11-25) is:
967
968 Data Magnitude Equivalent Conversion
969 0< m < 0.1-0.5*10**(-d-1) Ew.d[Ee]
970 m = 0 F(w-n).(d-1), n' '
971 0.1-0.5*10**(-d-1)<= m < 1-0.5*10**(-d) F(w-n).d, n' '
972 1-0.5*10**(-d)<= m < 10-0.5*10**(-d+1) F(w-n).(d-1), n' '
973 10-0.5*10**(-d+1)<= m < 100-0.5*10**(-d+2) F(w-n).(d-2), n' '
974 ................ ..........
975 10**(d-1)-0.5*10**(-1)<= m <10**d-0.5 F(w-n).0,n(' ')
976 m >= 10**d-0.5 Ew.d[Ee]
977
978 notes: for Gw.d , n' ' means 4 blanks
979 for Gw.dEe, n' ' means e+2 blanks
980 for rounding modes adjustment, r, See Fortran F2008 10.7.5.2.2
981 the asm volatile is required for 32-bit x86 platforms. */
982
983 #define OUTPUT_FLOAT_FMT_G(x,y) \
984 static void \
985 output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
986 GFC_REAL_ ## x m, char *buffer, size_t size, \
987 int sign_bit, bool zero_flag, int comp_d) \
988 { \
989 int e = f->u.real.e;\
990 int d = f->u.real.d;\
991 int w = f->u.real.w;\
992 fnode newf;\
993 GFC_REAL_ ## x rexp_d, r = 0.5;\
994 int low, high, mid;\
995 int ubound, lbound;\
996 char *p, pad = ' ';\
997 int save_scale_factor, nb = 0;\
998 try result;\
999 int nprinted, precision;\
1000 \
1001 save_scale_factor = dtp->u.p.scale_factor;\
1002 \
1003 switch (dtp->u.p.current_unit->round_status)\
1004 {\
1005 case ROUND_ZERO:\
1006 r = sign_bit ? 1.0 : 0.0;\
1007 break;\
1008 case ROUND_UP:\
1009 r = 1.0;\
1010 break;\
1011 case ROUND_DOWN:\
1012 r = 0.0;\
1013 break;\
1014 default:\
1015 break;\
1016 }\
1017 \
1018 rexp_d = calculate_exp_ ## x (-d);\
1019 if ((m > 0.0 && ((m < 0.1 - 0.1 * r * rexp_d) || (rexp_d * (m + r) >= 1.0)))\
1020 || ((m == 0.0) && !(compile_options.allow_std\
1021 & (GFC_STD_F2003 | GFC_STD_F2008))))\
1022 { \
1023 newf.format = FMT_E;\
1024 newf.u.real.w = w;\
1025 newf.u.real.d = d - comp_d;\
1026 newf.u.real.e = e;\
1027 nb = 0;\
1028 precision = determine_precision (dtp, &newf, x);\
1029 nprinted = DTOA(y,precision,m); \
1030 goto finish;\
1031 }\
1032 \
1033 mid = 0;\
1034 low = 0;\
1035 high = d + 1;\
1036 lbound = 0;\
1037 ubound = d + 1;\
1038 \
1039 while (low <= high)\
1040 { \
1041 volatile GFC_REAL_ ## x temp;\
1042 mid = (low + high) / 2;\
1043 \
1044 temp = (calculate_exp_ ## x (mid - 1) * (1 - r * rexp_d));\
1045 \
1046 if (m < temp)\
1047 { \
1048 ubound = mid;\
1049 if (ubound == lbound + 1)\
1050 break;\
1051 high = mid - 1;\
1052 }\
1053 else if (m > temp)\
1054 { \
1055 lbound = mid;\
1056 if (ubound == lbound + 1)\
1057 { \
1058 mid ++;\
1059 break;\
1060 }\
1061 low = mid + 1;\
1062 }\
1063 else\
1064 {\
1065 mid++;\
1066 break;\
1067 }\
1068 }\
1069 \
1070 nb = e <= 0 ? 4 : e + 2;\
1071 nb = nb >= w ? w - 1 : nb;\
1072 newf.format = FMT_F;\
1073 newf.u.real.w = w - nb;\
1074 newf.u.real.d = m == 0.0 ? d - 1 : -(mid - d - 1) ;\
1075 dtp->u.p.scale_factor = 0;\
1076 precision = determine_precision (dtp, &newf, x); \
1077 nprinted = FDTOA(y,precision,m); \
1078 \
1079 finish:\
1080 result = output_float (dtp, &newf, buffer, size, nprinted, precision,\
1081 sign_bit, zero_flag);\
1082 dtp->u.p.scale_factor = save_scale_factor;\
1083 \
1084 \
1085 if (nb > 0 && !dtp->u.p.g0_no_blanks)\
1086 {\
1087 p = write_block (dtp, nb);\
1088 if (p == NULL)\
1089 return;\
1090 if (result == FAILURE)\
1091 pad = '*';\
1092 if (unlikely (is_char4_unit (dtp)))\
1093 {\
1094 gfc_char4_t *p4 = (gfc_char4_t *) p;\
1095 memset4 (p4, pad, nb);\
1096 }\
1097 else \
1098 memset (p, pad, nb);\
1099 }\
1100 }\
1101
1102 OUTPUT_FLOAT_FMT_G(4,)
1103
1104 OUTPUT_FLOAT_FMT_G(8,)
1105
1106 #ifdef HAVE_GFC_REAL_10
1107 OUTPUT_FLOAT_FMT_G(10,L)
1108 #endif
1109
1110 #ifdef HAVE_GFC_REAL_16
1111 # ifdef GFC_REAL_16_IS_FLOAT128
1112 OUTPUT_FLOAT_FMT_G(16,Q)
1113 #else
1114 OUTPUT_FLOAT_FMT_G(16,L)
1115 #endif
1116 #endif
1117
1118 #undef OUTPUT_FLOAT_FMT_G
1119
1120
1121 /* EN format is tricky since the number of significant digits depends
1122 on the magnitude. Solve it by first printing a temporary value and
1123 figure out the number of significant digits from the printed
1124 exponent. */
1125
1126 #define EN_PREC(x,y)\
1127 {\
1128 GFC_REAL_ ## x tmp; \
1129 tmp = * (GFC_REAL_ ## x *)source; \
1130 if (isfinite (tmp)) \
1131 nprinted = DTOA(y,0,tmp); \
1132 else\
1133 nprinted = -1;\
1134 }\
1135
1136 static int
1137 determine_en_precision (st_parameter_dt *dtp, const fnode *f,
1138 const char *source, int len)
1139 {
1140 int nprinted;
1141 char buffer[10];
1142 const size_t size = 10;
1143
1144 switch (len)
1145 {
1146 case 4:
1147 EN_PREC(4,)
1148 break;
1149
1150 case 8:
1151 EN_PREC(8,)
1152 break;
1153
1154 #ifdef HAVE_GFC_REAL_10
1155 case 10:
1156 EN_PREC(10,L)
1157 break;
1158 #endif
1159 #ifdef HAVE_GFC_REAL_16
1160 case 16:
1161 # ifdef GFC_REAL_16_IS_FLOAT128
1162 EN_PREC(16,Q)
1163 # else
1164 EN_PREC(16,L)
1165 # endif
1166 break;
1167 #endif
1168 default:
1169 internal_error (NULL, "bad real kind");
1170 }
1171
1172 if (nprinted == -1)
1173 return -1;
1174
1175 int e = atoi (&buffer[5]);
1176 int nbefore; /* digits before decimal point - 1. */
1177 if (e >= 0)
1178 nbefore = e % 3;
1179 else
1180 {
1181 nbefore = (-e) % 3;
1182 if (nbefore != 0)
1183 nbefore = 3 - nbefore;
1184 }
1185 int prec = f->u.real.d + nbefore;
1186 if (dtp->u.p.current_unit->round_status != ROUND_UNSPECIFIED
1187 && dtp->u.p.current_unit->round_status != ROUND_PROCDEFINED)
1188 prec += 2 * len + 4;
1189 return prec;
1190 }
1191
1192
1193 #define WRITE_FLOAT(x,y)\
1194 {\
1195 GFC_REAL_ ## x tmp;\
1196 tmp = * (GFC_REAL_ ## x *)source;\
1197 sign_bit = signbit (tmp);\
1198 if (!isfinite (tmp))\
1199 { \
1200 write_infnan (dtp, f, isnan (tmp), sign_bit);\
1201 return;\
1202 }\
1203 tmp = sign_bit ? -tmp : tmp;\
1204 zero_flag = (tmp == 0.0);\
1205 if (f->format == FMT_G)\
1206 output_float_FMT_G_ ## x (dtp, f, tmp, buffer, size, sign_bit, \
1207 zero_flag, comp_d);\
1208 else\
1209 {\
1210 if (f->format == FMT_F)\
1211 nprinted = FDTOA(y,precision,tmp); \
1212 else\
1213 nprinted = DTOA(y,precision,tmp); \
1214 output_float (dtp, f, buffer, size, nprinted, precision,\
1215 sign_bit, zero_flag);\
1216 }\
1217 }\
1218
1219 /* Output a real number according to its format. */
1220
1221 static void
1222 write_float (st_parameter_dt *dtp, const fnode *f, const char *source, \
1223 int len, int comp_d)
1224 {
1225 int sign_bit, nprinted;
1226 int precision; /* Precision for snprintf call. */
1227 bool zero_flag;
1228
1229 if (f->format != FMT_EN)
1230 precision = determine_precision (dtp, f, len);
1231 else
1232 precision = determine_en_precision (dtp, f, source, len);
1233
1234 /* 4932 is the maximum exponent of long double and quad precision, 3
1235 extra characters for the sign, the decimal point, and the
1236 trailing null, and finally some extra digits depending on the
1237 requested precision. */
1238 const size_t size = 4932 + 3 + precision;
1239 char buffer[size];
1240
1241 switch (len)
1242 {
1243 case 4:
1244 WRITE_FLOAT(4,)
1245 break;
1246
1247 case 8:
1248 WRITE_FLOAT(8,)
1249 break;
1250
1251 #ifdef HAVE_GFC_REAL_10
1252 case 10:
1253 WRITE_FLOAT(10,L)
1254 break;
1255 #endif
1256 #ifdef HAVE_GFC_REAL_16
1257 case 16:
1258 # ifdef GFC_REAL_16_IS_FLOAT128
1259 WRITE_FLOAT(16,Q)
1260 # else
1261 WRITE_FLOAT(16,L)
1262 # endif
1263 break;
1264 #endif
1265 default:
1266 internal_error (NULL, "bad real kind");
1267 }
1268 }