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