Re: [patch] Flag-controlled type conversions/promotions

2011-12-26 Thread Zydrunas Gimbutas
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

2011-12-27 Thread Zydrunas Gimbutas
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

2012-01-15 Thread Zydrunas Gimbutas
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