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


Reply via email to