1 /* Copyright (C
) 2007-2018 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 /* Determine the precision except for EN format. For G format
,
63 determines an upper bound to be used for sizing the buffer.
*/
66 determine_precision (st_parameter_dt
* dtp
, const fnode
* f
, int len
)
68 int precision
= f
->u.real.d
;
74 precision
+= dtp
->u.p.scale_factor
;
77 /* Scale factor has no effect on output.
*/
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;
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
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
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;
111 /* Build a real number according to its format which is FMT_G free.
*/
114 build_float_string (st_parameter_dt
*dtp
, const fnode
*f
, char
*buffer
,
115 size_t size
, int nprinted
, int precision
, int sign_bit
,
116 bool zero_flag
, int npad
, char
*result
, size_t
*len
)
123 /* Number of digits before the decimal point.
*/
125 /* Number of zeros after the decimal point.
*/
127 /* Number of digits after the decimal point.
*/
131 int ndigits
, edigits
;
137 p
= dtp
->u.p.scale_factor
;
142 /* We should always know the field width and precision.
*/
144 internal_error (&dtp
->common
, "Unspecified precision");
146 sign
= calculate_sign (dtp
, sign_bit
);
148 /* Calculate total number of digits.
*/
150 ndigits
= nprinted
- 2;
152 ndigits
= precision
+ 1;
154 /* Read the exponent back in.
*/
156 e
= atoi (&buffer
[ndigits
+ 3]) + 1;
160 /* Make sure zero comes out as
0.0e0.
*/
164 /* Normalize the fractional component.
*/
167 buffer
[2] = buffer
[1];
173 /* Figure out where to place the decimal point.
*/
177 nbefore
= ndigits
- precision
;
178 if ((w
> 0) && (nbefore
> (int
) size
))
181 star_fill (result
, w
);
185 /* Make sure the decimal point is a
'.'; depending on the
186 locale
, this might not be the case otherwise.
*/
187 digits
[nbefore
] = '.';
192 memmove (digits
+ nbefore
, digits
+ nbefore
+ 1, p
);
193 digits
[nbefore
+ p
] = '.';
200 if (nbefore
+ p
>= 0)
203 memmove (digits
+ nbefore
+ p
+ 1, digits
+ nbefore
+ p
, -p
);
205 digits
[nbefore
] = '.';
210 nzero
= -(nbefore
+ p
);
211 memmove (digits
+ 1, digits
, nbefore
);
213 if (nafter
== 0 && d
> 0)
215 /* This is needed to get the correct rounding.
*/
216 memmove (digits
+ 1, digits
, ndigits
- 1);
223 /* Reset digits to
0 in order to get correct rounding
225 for (i
= 0; i
< ndigits
; i
++)
227 digits
[ndigits
- 1] = '1';
241 while (digits
[0] == '0' && nbefore
> 0)
249 /* If we need to do rounding ourselves
, get rid of the dot by
250 moving the fractional part.
*/
251 if (dtp
->u.p.current_unit
->round_status
!= ROUND_UNSPECIFIED
252 && dtp
->u.p.current_unit
->round_status
!= ROUND_PROCDEFINED
)
253 memmove (digits
+ nbefore
, digits
+ nbefore
+ 1, ndigits
- nbefore
);
258 i
= dtp
->u.p.scale_factor
;
259 if (d
<= 0 && p
== 0)
261 generate_error (&dtp
->common
, LIBERROR_FORMAT
, "Precision not "
262 "greater than zero in format specifier 'E' or 'D'");
265 if (p
<= -d || p
>= d
+ 2)
267 generate_error (&dtp
->common
, LIBERROR_FORMAT
, "Scale factor "
268 "out of range in format specifier 'E' or 'D'");
284 nafter
= (d
- p
) + 1;
300 /* The exponent must be a multiple of three
, with
1-3 digits before
301 the decimal point.
*/
310 nbefore
= 3 - nbefore
;
329 /* Should never happen.
*/
330 internal_error (&dtp
->common
, "Unexpected format token");
336 /* Round the value. The value being rounded is an unsigned magnitude.
*/
337 switch (dtp
->u.p.current_unit
->round_status
)
339 /* For processor defined and unspecified rounding we use
340 snprintf to print the exact number of digits needed
, and thus
341 let snprintf handle the rounding. On system claiming support
342 for IEEE
754, this ought to be round to nearest
, ties to
343 even
, corresponding to the Fortran ROUND
='NEAREST'.
*/
344 case ROUND_PROCDEFINED
:
345 case ROUND_UNSPECIFIED
:
346 case ROUND_ZERO
: /* Do nothing and truncation occurs.
*/
357 /* Round compatible unless there is a tie. A tie is a
5 with
358 all trailing zero
's. */
359 i = nafter + nbefore;
360 if (digits[i] == '5')
362 for(i++ ; i < ndigits; i++)
364 if (digits[i] != '0')
367 /* It is a tie so round to even. */
368 switch (digits[nafter + nbefore - 1])
375 /* If odd, round away from zero to even. */
378 /* If even, skip rounding, truncate to even. */
383 /* The ROUND_COMPATIBLE is rounding away from zero when there is a tie. */
384 case ROUND_COMPATIBLE:
392 if (ft != FMT_F && w > 0 && d == 0 && p == 0)
394 /* Scan for trailing zeros to see if we really need to round it. */
395 for(i = nbefore + nafter; i < ndigits; i++)
397 if (digits[i] != '0')
404 if (nbefore + nafter == 0)
405 /* Handle the case Fw.0 and value < 1.0 */
408 if (digits[0] >= rchar)
410 /* We rounded to zero but shouldn't have
*/
417 else
if (nbefore
+ nafter
< ndigits
)
419 i
= ndigits
= nbefore
+ nafter
;
420 if (digits
[i
] >= rchar
)
422 /* Propagate the carry.
*/
423 for (i
--; i
>= 0; i
--)
425 if (digits
[i
] != '9')
435 /* The carry overflowed. Fortunately we have some spare
436 space at the start of the buffer. We may discard some
437 digits
, but this is ok because we already know they are
451 else
if (ft
== FMT_EN
)
468 /* Calculate the format of the exponent field.
*/
469 if (expchar
&& !(dtp
->u.p.g0_no_blanks
&& e
== 0))
472 for (i
= abs (e
); i
>= 10; i
/= 10)
477 /* Width not specified. Must be no more than
3 digits.
*/
478 if (e
> 999 || e
< -999)
483 if (e
> 99 || e
< -99)
489 /* Exponent width specified
, check it is wide enough.
*/
490 if (edigits
> f
->u.real.e
)
493 edigits
= f
->u.real.e
+ 2;
499 /* Scan the digits string and count the number of zeros. If we make it
500 all the way through the loop
, we know the value is zero after the
501 rounding completed above.
*/
503 for (i
= 0; i
< ndigits
+ hasdot
; i
++)
505 if (digits
[i
] == '.')
507 else
if (digits
[i
] != '0')
511 /* To format properly
, we need to know if the rounded result is zero and if
512 so
, we set the zero_flag which may have been already set for
514 if (i
== ndigits
+ hasdot
)
517 /* The output is zero
, so set the sign according to the sign bit unless
518 -fno
-sign
-zero was specified.
*/
519 if (compile_options.sign_zero
== 1)
520 sign
= calculate_sign (dtp
, sign_bit
);
522 sign
= calculate_sign (dtp
, 0);
525 /* Pick a field size if none was specified
, taking into account small
526 values that may have been rounded to zero.
*/
530 w
= d
+ (sign
!= S_NONE ?
2 : 1) + (d
== 0 ?
1 : 0);
533 w
= nbefore
+ nzero
+ nafter
+ (sign
!= S_NONE ?
2 : 1);
538 /* Work out how much padding is needed.
*/
539 nblanks
= w
- (nbefore
+ nzero
+ nafter
+ edigits
+ 1);
543 /* See if we have space for a zero before the decimal point.
*/
544 if (nbefore
== 0 && nblanks
> 0)
552 if (dtp
->u.p.g0_no_blanks
)
558 /* Create the final float string.
*/
562 /* Check the value fits in the specified field width.
*/
563 if (nblanks
< 0 || edigits
== -1 || w
== 1 ||
(w
== 2 && sign
!= S_NONE
))
565 star_fill (put
, *len
);
569 /* Pad to full field width.
*/
570 if ( ( nblanks
> 0 ) && !dtp
->u.p.no_leading_blank
)
572 memset (put
, ' ', nblanks
);
576 /* Set the initial
sign (if any
).
*/
579 else
if (sign
== S_MINUS
)
582 /* Set an optional leading zero.
*/
586 /* Set the part before the decimal point
, padding with zeros.
*/
589 if (nbefore
> ndigits
)
592 memcpy (put
, digits
, i
);
600 memcpy (put
, digits
, i
);
608 /* Set the decimal point.
*/
609 *(put
++) = dtp
->u.p.current_unit
->decimal_status
== DECIMAL_POINT ?
'.' : ',';
611 && (dtp
->u.p.current_unit
->round_status
== ROUND_UNSPECIFIED
612 || dtp
->u.p.current_unit
->round_status
== ROUND_PROCDEFINED
))
615 /* Set leading zeros after the decimal point.
*/
618 for (i
= 0; i
< nzero
; i
++)
622 /* Set digits after the decimal point
, padding with zeros.
*/
625 if (nafter
> ndigits
)
630 memcpy (put
, digits
, i
);
639 /* Set the exponent.
*/
640 if (expchar
&& !(dtp
->u.p.g0_no_blanks
&& e
== 0))
647 snprintf (buffer
, size
, "%+0*d", edigits
, e
);
648 memcpy (put
, buffer
, edigits
);
652 if (dtp
->u.p.no_leading_blank
)
654 memset (put
, ' ' , nblanks
);
655 dtp
->u.p.no_leading_blank
= 0;
659 if (npad
> 0 && !dtp
->u.p.g0_no_blanks
)
661 memset (put
, ' ' , npad
);
665 /* NULL terminate the string.
*/
672 /* Write
"Infinite" or
"Nan" as appropriate for the given format.
*/
675 build_infnan_string (st_parameter_dt
*dtp
, const fnode
*f
, int isnan_flag
,
676 int sign_bit
, char
*p
, size_t
*len
)
683 if (f
->format
!= FMT_B
&& f
->format
!= FMT_O
&& f
->format
!= FMT_Z
)
685 sign
= calculate_sign (dtp
, sign_bit
);
686 mark
= (sign
== S_PLUS || sign
== S_MINUS
) ?
8 : 7;
691 /* If the field width is zero
, the processor must select a width
692 not zero.
4 is chosen to allow output of
'-Inf' or
'+Inf' */
694 if ((nb
== 0) || dtp
->u.p.g0_no_blanks
)
699 nb
= (sign
== S_PLUS || sign
== S_MINUS
) ?
4 : 3;
716 /* If the sign is negative and the width is
3, there is
717 insufficient room to output
'-Inf', so output asterisks
*/
723 /* The negative sign is mandatory
*/
727 /* The positive sign is optional
, but we output it for
732 /* We have room
, so output
'Infinity' */
733 memcpy(p
+ nb
- 8, "Infinity", 8);
735 /* For the case of width equals
8, there is not enough room
736 for the sign and
'Infinity' so we go with
'Inf' */
737 memcpy(p
+ nb
- 3, "Inf", 3);
739 if (sign
== S_PLUS || sign
== S_MINUS
)
741 if (nb
< 9 && nb
> 3)
742 p
[nb
- 4] = fin
; /* Put the sign in front of Inf
*/
744 p
[nb
- 9] = fin
; /* Put the sign in front of Infinity
*/
748 memcpy(p
+ nb
- 3, "NaN", 3);
753 /* Returns the value of
10**d.
*/
755 #define
CALCULATE_EXP(x
) \
756 static GFC_REAL_ ## x \
757 calculate_exp_ ##
x (int d
)\
760 GFC_REAL_ ## x r
= 1.0;\
761 for (i
= 0; i
< (d
>= 0 ? d
: -d
); i
++)\
763 r
= (d
>= 0) ? r
: 1.0 / r
;\
771 #ifdef HAVE_GFC_REAL_10
775 #ifdef HAVE_GFC_REAL_16
781 /* Define macros to build code for format_float.
*/
783 /* Note
: Before output_float is called
, snprintf is used to print to buffer the
784 number in the format
+D.DDDDe
+ddd.
786 # The result will always contain a decimal point
, even if no
789 - The converted value is to be left adjusted on the field boundary
791 + A
sign (+ or
-) always be placed before a number
793 * prec is used as the precision
795 e format
: [-]d.ddde±dd where there is one digit before the
796 decimal
-point character and the number of digits after it is
797 equal to the precision. The exponent always contains at least two
798 digits
; if the value is zero
, the exponent is
00.
*/
801 #define
TOKENPASTE(x
, y
) TOKENPASTE2(x
, y
)
802 #define
TOKENPASTE2(x
, y
) x ## y
804 #define
DTOA(suff
,prec
,val
) TOKENPASTE(DTOA2
,suff
)(prec
,val
)
806 #define
DTOA2(prec
,val
) \
807 snprintf (buffer
, size
, "%+-#.*e", (prec
), (val
))
809 #define
DTOA2L(prec
,val
) \
810 snprintf (buffer
, size
, "%+-#.*Le", (prec
), (val
))
813 #if
defined(GFC_REAL_16_IS_FLOAT128
)
814 #define
DTOA2Q(prec
,val
) \
815 quadmath_snprintf (buffer
, size
, "%+-#.*Qe", (prec
), (val
))
818 #define
FDTOA(suff
,prec
,val
) TOKENPASTE(FDTOA2
,suff
)(prec
,val
)
820 /* For F format
, we print to the buffer with f format.
*/
821 #define
FDTOA2(prec
,val
) \
822 snprintf (buffer
, size
, "%+-#.*f", (prec
), (val
))
824 #define
FDTOA2L(prec
,val
) \
825 snprintf (buffer
, size
, "%+-#.*Lf", (prec
), (val
))
828 #if
defined(GFC_REAL_16_IS_FLOAT128
)
829 #define
FDTOA2Q(prec
,val
) \
830 quadmath_snprintf (buffer
, size
, "%+-#.*Qf", \
835 /* EN format is tricky since the number of significant digits depends
836 on the magnitude. Solve it by first printing a temporary value and
837 figure out the number of significant digits from the printed
838 exponent. Values y
, 0.95*10.0**e
<= y
<10.0**e
, are rounded to
839 10.0**e even when the final result will not be rounded to
10.0**e.
840 For these values the exponent returned by atoi has to be decremented
841 by one. The values y in the ranges
842 (1000.0-0.5*10.0**(-d
))*10.0**(3*n
) <= y
< 10.0*(3*(n
+1))
843 (100.0-0.5*10.0**(-d
))*10.0**(3*n
) <= y
< 10.0*(3*n
+2)
844 (10.0-0.5*10.0**(-d
))*10.0**(3*n
) <= y
< 10.0*(3*n
+1)
845 are correctly rounded respectively to
1.0..
.0*10.0*(3*(n
+1)),
846 100.0..
.0*10.0*(3*n
), and
10.0..
.0*10.0*(3*n
), where
0..
.0
847 represents d zeroes
, by the lines
279 to
297.
*/
848 #define
EN_PREC(x
,y
)\
850 volatile GFC_REAL_ ## x tmp
, one
= 1.0;\
851 tmp
= * (GFC_REAL_ ## x *)source
;\
854 nprinted
= DTOA(y
,0,tmp
);\
855 int e
= atoi (&buffer
[4]);\
856 if (buffer
[1] == '1')\
858 tmp
= (calculate_exp_ ##
x (-e
)) * tmp
;\
859 tmp
= one
- (tmp
< 0 ?
-tmp
: tmp
);\
865 nbefore
= 3 + nbefore
;\
872 determine_en_precision (st_parameter_dt
*dtp
, const fnode
*f
,
873 const char
*source
, int len
)
877 const size_t size
= 10;
878 int nbefore
; /* digits before decimal point
- 1.
*/
890 #ifdef HAVE_GFC_REAL_10
895 #ifdef HAVE_GFC_REAL_16
897 # ifdef GFC_REAL_16_IS_FLOAT128
905 internal_error (NULL
, "bad real kind");
911 int prec
= f
->u.real.d
+ nbefore
;
912 if (dtp
->u.p.current_unit
->round_status
!= ROUND_UNSPECIFIED
913 && dtp
->u.p.current_unit
->round_status
!= ROUND_PROCDEFINED
)
919 /* Generate corresponding I
/O format. and output.
920 The rules to translate FMT_G to FMT_E or FMT_F from
DEC fortran
921 LRM (table
11-2, Chapter
11, "I/O Formatting", P11
-25) is
:
923 Data Magnitude Equivalent Conversion
924 0< m
< 0.1-0.5*10**(-d
-1) Ew.d
[Ee
]
925 m
= 0 F(w
-n
).
(d
-1), n
' '
926 0.1-0.5*10**(-d
-1)<= m
< 1-0.5*10**(-d
) F(w
-n
).d
, n
' '
927 1-0.5*10**(-d
)<= m
< 10-0.5*10**(-d
+1) F(w
-n
).
(d
-1), n
' '
928 10-0.5*10**(-d
+1)<= m
< 100-0.5*10**(-d
+2) F(w
-n
).
(d
-2), n
' '
929 ................ ..........
930 10**(d
-1)-0.5*10**(-1)<= m
<10**d
-0.5 F(w
-n
).0,n(' ')
931 m
>= 10**d
-0.5 Ew.d
[Ee
]
933 notes
: for Gw.d
, n
' ' means
4 blanks
934 for Gw.dEe
, n
' ' means e
+2 blanks
935 for rounding modes adjustment
, r
, See Fortran F2008
10.7.5.2.2
936 the asm volatile is required for
32-bit x86 platforms.
*/
937 #define
FORMAT_FLOAT(x
,y
)\
941 m
= * (GFC_REAL_ ## x *)source
;\
942 sign_bit
= signbit (m
);\
945 build_infnan_string (dtp
, f
, isnan (m
), sign_bit
, result
, res_len
);\
948 m
= sign_bit ?
-m
: m
;\
949 zero_flag
= (m
== 0.0);\
950 if (f
->format
== FMT_G
)\
952 int e
= f
->u.real.e
;\
953 int d
= f
->u.real.d
;\
954 int w
= f
->u.real.w
;\
956 GFC_REAL_ ## x exp_d
, r
= 0.5, r_sc
;\
959 int save_scale_factor
;\
960 volatile GFC_REAL_ ## x temp
;\
961 save_scale_factor
= dtp
->u.p.scale_factor
;\
962 switch (dtp
->u.p.current_unit
->round_status
)\
965 r
= sign_bit ?
1.0 : 0.0;\
976 exp_d
= calculate_exp_ ##
x (d
);\
977 r_sc
= (1 - r
/ exp_d
);\
979 if ((m
> 0.0 && ((m
< temp
) ||
(r
>= (exp_d
- m
))))\
980 ||
((m
== 0.0) && !(compile_options.allow_std\
981 & (GFC_STD_F2003 | GFC_STD_F2008
)))\
984 newf.format
= FMT_E
;\
986 newf.u.real.d
= d
- comp_d
;\
989 precision
= determine_precision (dtp
, &newf
, x
);\
990 nprinted
= DTOA(y
,precision
,m
);\
1001 mid
= (low
+ high
) / 2;\
1002 temp
= (calculate_exp_ ##
x (mid
- 1) * r_sc
);\
1006 if (ubound
== lbound
+ 1)\
1013 if (ubound
== lbound
+ 1)\
1026 npad
= e
<= 0 ?
4 : e
+ 2;\
1027 npad
= npad
>= w ? w
- 1 : npad
;\
1028 npad
= dtp
->u.p.g0_no_blanks ?
0 : npad
;\
1029 newf.format
= FMT_F
;\
1030 newf.u.real.w
= w
- npad
;\
1031 newf.u.real.d
= m
== 0.0 ? d
- 1 : -(mid
- d
- 1) ;\
1032 dtp
->u.p.scale_factor
= 0;\
1033 precision
= determine_precision (dtp
, &newf
, x
);\
1034 nprinted
= FDTOA(y
,precision
,m
);\
1036 build_float_string (dtp
, &newf
, buffer
, size
, nprinted
, precision
,\
1037 sign_bit
, zero_flag
, npad
, result
, res_len
);\
1038 dtp
->u.p.scale_factor
= save_scale_factor
;\
1042 if (f
->format
== FMT_F
)\
1043 nprinted
= FDTOA(y
,precision
,m
);\
1045 nprinted
= DTOA(y
,precision
,m
);\
1046 build_float_string (dtp
, f
, buffer
, size
, nprinted
, precision
,\
1047 sign_bit
, zero_flag
, npad
, result
, res_len
);\
1051 /* Output a real number according to its format.
*/
1055 get_float_string (st_parameter_dt
*dtp
, const fnode
*f
, const char
*source
,
1056 int kind
, int comp_d
, char
*buffer
, int precision
,
1057 size_t size
, char
*result
, size_t
*res_len
)
1059 int sign_bit
, nprinted
;
1072 #ifdef HAVE_GFC_REAL_10
1077 #ifdef HAVE_GFC_REAL_16
1079 # ifdef GFC_REAL_16_IS_FLOAT128
1087 internal_error (NULL
, "bad real kind");