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.0000000000000000
0.0000000000000000
0.0000000000000000
0.0000000000000000
0.0000000000000000
0.0000000000000000
0.0000000000000000
0.0000000000000000
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.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
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.0000000000000000000000000000000000
0.0000000000000000000000000000000000
1.40209065578162555042101269140459185E-0017 <- constant truncation
0.0000000000000000000000000000000000
1.40209065578162555042101269140459185E-0017 <- constant truncation
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
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.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
0.0000000000000000000000000000000000
The second promotion declaration is cleaner, but the declaration
chaining may be worth the effort.
The patch has been tested on Fortran 77 and Fortran 95 codes, so as
for the errors in coarray tests, it is quite possible that we have
simply missed some kind of type processing/declaration since this is a
relative new Fortran feature, sorry about that.
Zydrunas
implicit real *4 (a-h,o-z)
real(4) :: x, xdata
real get_real
real *4 get_real4
data xdata/0.90929742682568169539601986591174487_4/
data ydata/0.90929742682568169539601986591174487_4/
c
write(*,*) sin(2.0e0)
write(*,*) xdata
c
x=0.90929742682568169539601986591174487e0
write(*,*) x-sin(2.0e0)
y=0.90929742682568169539601986591174487e0
write(*,*) y-sin(2.0e0)
x=get_real()
write(*,*) x-sin(2.0e0)
x=get_real4()
write(*,*) x-sin(2.0e0)
y=get_real()
write(*,*) y-sin(2.0e0)
y=get_real4()
write(*,*) y-sin(2.0e0)
c
write(*,*) xdata-sin(2.0e0)
write(*,*) ydata-sin(2.0e0)
c
stop
end
real function get_real()
get_real=0.90929742682568169539601986591174487_4
return
end
real *4 function get_real4()
get_real4 =0.90929742682568169539601986591174487_4
return
end
implicit real *8 (a-h,o-z)
real(8) :: x, xdata
double precision get_double
real *8 get_real8
data xdata/0.90929742682568169539601986591174487_8/
data ydata/0.90929742682568169539601986591174487_8/
c
write(*,*) sin(2.0d0)
write(*,*) xdata
c
x=0.90929742682568169539601986591174487d0
write(*,*) x-sin(2.0d0)
y=0.90929742682568169539601986591174487d0
write(*,*) y-sin(2.0d0)
x=get_double()
write(*,*) x-sin(2.0d0)
x=get_real8()
write(*,*) x-sin(2.0d0)
y=get_double()
write(*,*) y-sin(2.0d0)
y=get_real8()
write(*,*) y-sin(2.0d0)
c
write(*,*) xdata-sin(2.0d0)
write(*,*) ydata-sin(2.0d0)
c
stop
end
double precision function get_double()
get_double=0.90929742682568169539601986591174487_8
return
end
real *8 function get_real8()
get_real8 =0.90929742682568169539601986591174487_8
return
end
implicit real *4 (a-h,o-z)
integer i
integer *4 j
c
i=2**40
j=2**40
c
write(*,*) i
write(*,*) j
c
stop
end