Re: [patch] Flag-controlled type conversions/promotions
Hi all, Attached are three test file, that stress the type-promotion patch. >> The difference between -fdefault-*-8 and -f*-4-*-8 should probably also be >> documented. >> > > It is documented for the -freal-* options. The manual has, for example, > > -freal-4-real-8 > Promote REAL(KIND=4) entities to REAL(KIND=8) entities. If KIND=8 is > unavail- > able, then an error will be issued. All other real kind types are > unaffected > by this option. > > The last sentence is the same for the other options. This literally means > that only REAL(4) is effected by the -freal-4-real-8 option. If one reads > he description of -fdefault-*, one will that -freal-4-real-8 is equivalent > to specifying both -fdefault-real-8 and -fdefault-double-8. > -freal-4-real-8 is not equivalent to -fdefault-real-8 and -fdefault-double-8. -freal-4-real-8 interprets any 4-byte real type, whether it is a default real type or explicitly declared as 4-byte, as a 8-byte double precision type, and that applies to all variables, functions and constants. -fdefault-real-8 will promote only default real type to double precision and only variables and functions. Since constants are usually declared explicitly as 4-byte, e.g. 1.01223e0 is an explicitly defined 4-byte constant in gfortran, they will not be promoted. $ gfortran -freal-4-real-8 test-r4.f $ a.out 0.90929742682568171 0.90929742682568171 0. 0. 0. 0. 0. 0. 0. 0. but $ gfortran -fdefault-real-8 -fdefault-double-8 test-r4.f $ a.out 0.90929742682568171 0.90929741 -2.01522503129325514E-008 -2.01522503129325514E-008 -2.01522503129325514E-008 -2.01522503129325514E-008 -2.01522503129325514E-008 -2.01522503129325514E-008 -2.01522503129325514E-008 -2.01522503129325514E-008 Note how constants are truncated to single precision, while using -fdefault-real-8 -fdefault-double-8. The same promotion convention applies to other -freal-*-real-*, and -finteger-*-integer-* flags. For example, -fdefault-integer-8 is not equivalent to -finteger-4-integer-8, because integer*4 types and constants are being interpreted in a different way, see test-i4.f test: $ gfortran -fdefault-integer-8 test-i4.f test-i4.f:6.8: j=2**40 1 Error: Arithmetic overflow converting INTEGER(8) to INTEGER(4) at (1). This check can be disabled with the option -fno-range-check The error above is due to inability of standard gfortran to promote explicitly declared integer*4 type to integer*8. $ gfortran -finteger-4-integer-8 test-i4.f $ a.out 1099511627776 1099511627776 This fixes the above problem. Finally, $ gfortran -freal-8-real-16 test-r8.f $ a.out 0.90929742682568169539601986591174487 0.90929742682568169539601986591174487 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 We have nothing to compare this result with since, currently, gfortran has no facility to promote double precision to real*16 (no -fdefault-double-16 flag). >> Last point for this batch is that using '-freal-8-real-10 -freal-8-real-16' >> does not >> generate an error, the last option being the one used. > > Yes, that is correct. Consider it to be similar to '-Os -O -O2 -O0'. The > last one wins. Note, there is this combination: '-freal-4-real-8 > -freal-8-real-16' > which will promote both REAL(4) and (8) to REAL(16). > One caveat here, we have not attempted to chain constant conversion in this patch. This combination will promote real*4 constants to real*8, and real*8 constants to real*16, $ gfortran -freal-4-real-8 -freal-8-real-16 test-r4.f $ a.out 0.90929742682568169539601986591174487 0.90929742682568169539601986591174487 0.00 0.00 1.40209065578162555042101269140459185E-0017 <- constant truncation 0.00 1.40209065578162555042101269140459185E-0017 <- constant truncation 0.00 0.00 0.00 While this combination will promote real*4 constants to real*16, and real *8 constants to real*16, $ gfortran -freal-4-real-16 -freal-8-real-16 test-r4.f $ a.out 0.90929742682568169539601986591174487 0.90929742682568169539601986591174487 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Re: [patch] Flag-controlled type conversions/promotions
On Tue, Dec 27, 2011 at 6:52 AM, Dominique Dhumieres wrote: >> -freal-4-real-8 is not equivalent to -fdefault-real-8 and -fdefault-double-8. >> >> -freal-4-real-8 interprets any 4-byte real type, whether it is a >> default real type or explicitly declared as 4-byte, as a 8-byte double >> precision type, and that applies to all variables, functions and >> constants. >> >> -fdefault-real-8 will promote only default real type to double >> precision and only variables and functions. Since constants are >> usually declared explicitly as 4-byte, e.g. 1.01223e0 is an explicitly >> defined 4-byte constant in gfortran, they will not be promoted. > > I agree with the above and I think this should go into the manual. One > thing which can be done with -fdefault-real-8, but not with > -freal-4-real-8 is to work around some pitfalls of these otions by > specifying explicit kinds when needed (this probably explains why less > tests fail with the former option than with the later, see results at the > end of this mail). > That is correct. -fdefault-real-8 provides a finely tuned type promotion mechanism, while -freal-*-real-* overrides all type definitions via brute force. We actually like that: some of the codes we have date back to the 70's, we don't want to convert them into Fortran 95 and/or maintain several copies with different type definitions - this is just too expensive and time consuming. In such cases, we really do want to override all old-style definitions. In our work, this doesn't happen often, usually, we are running our code in double precision, but from time to time we would like to raise precision to pre-compute tables with more digits or to investigate ill-conditioning and numerical stability issues. > In my opinion, these options, while useful, have several pitfalls: > > (1) call to external procedures (especially in libraries), > (2) alignements in EQUIVALENCE and/or COMMON, > (3) generic interfaces, > (4) BOZ, > (5) I/Os, > (6) ... > > I wonder if they should not have their own page in the manual with a big > warning at the beginning telling the user that these options are likely to > break "legacy" codes. > We do recompile all codes with the promotion flags to address this, usually, with only minor modifications. Things like calls to external C functions need to be fixed, although this is also needed if using -fdefault-* flags. Alignment could be also a problem, especially if promoting to quad precision which currently requires 128-bit variable aligment, again this also might also happen with -fdefault-* flags. The user has to be somewhat aware of this and adjust the code accordingly. We tend to ignore such issues in practice and proceed anyway with fingers crossed: everything works 90% of the time just fine! Zydrunas
Re: [patch] Flag-controlled type conversions/promotions
Hi, Everything seems to be ok in this patch, except for minor typos in documentation: REAl -> REAL, alignement -> alignment. It would also be nice to extend the type conversion facility to include -fdefault-real-16, -fdefault-double-16, -fdefault-real-10, -fdefault-double-10, and add conversions for logical types, to complete the conversion table. These are not very commonly used (except for -fdefault-real-16, -fdefault-double-16, which would correspond to -r16 and -autodouble flags in some compilers), so we should be fine at this time. Thanks to everyone for making this work! Zydrunas On Fri, Jan 13, 2012 at 6:43 PM, Steve Kargl wrote: > On Wed, Nov 09, 2011 at 06:09:58PM -0500, Andreas Kloeckner wrote: >> Hi there, >> >> please find attached the patch and the Changelog entry for our work on >> the fortran bug #48426. >> >> The attached patch implements the options >> >> -finteger-4-integer-8 >> -freal-4-real-8 >> -freal-4-real-10 >> -freal-4-real-16 >> -freal-8-real-4 >> -freal-8-real-10 >> -freal-8-real-16 >> >> to implement a variety of automatic type promotions. (This is particularly >> helpful if one wants to quickly check whether a certain code has a bug >> limiting >> its precision away from full machine accuracy.) >> > > I plan to commit the attached patch this weekend. > > 2011-11-09 Zydrunas Gimbutas > Andreas Kloeckner > Steven G. Kargl > > PR fortran/48426 > * gfortran.h (gfc_option_t): Add members flag_*_kind to store kind. > * lang.opt: Add options -freal-4-real-8, -freal-4-real-10, > -freal-4-real-16, -freal-8-real-4, -freal-8-real-10, -freal-8-real-16 > and -finteger-4-integer-8. User-desired type conversion information. > * decl.c (gfc_match_old_kind_spec,kind_expr): Type conversions > in declaration parsing. > * trans-types.c (gfc_init_kinds): User-specified type conversion > checked for current backend. > * primary.c (match_integer_constant,match_real_constant): Implement > type conversion in constant parsing. > * options.c (gfc_init_options,gfc_handle_option): Translate input > options to flags in internal options data structure. > * invoke.texi: Document new options. Re-order options in Options > summary section. > > -- > Steve