Hi all,
In an huge numerical simulation code, written by someone else, in many code lines 'implicit type conversion' between integer, real32 and real64 is used. During some tests I encountered a precision loss in intermediate data (a rigid body rotation of an input mesh) and I traced it down to a possible loss due to implicit type conversion.
To have a closer look on what happens I built a simple generic example, which uses some calculations similar to the simulation code:
program Implicit_Type_Conversion
use, intrinsic :: ISO_FORTRAN_ENV, only : i8 => int64, r4 => real32, r8 => real64, r16 => real128, output_unit
implicit none
! Variables
integer(i8) :: i, j
integer(i8), parameter :: leng = 10000
real(r4 ), dimension(leng) :: vec_r4
real(r8 ), dimension(leng) :: vec_r8
real(r16), dimension(leng) :: vec_r16
real(r16) :: sum_of_values_i8
real(r16) :: sum_of_values_r4
real(r16) :: sum_of_values_r8
real(r16) :: sum_of_values_r16
! Body of Implicit_Type_Conversion
write(output_unit,*) 'Implicit Type Conversion -> Impact on Precision'
! i8 -> r16
sum_of_values_i8 = 0.0_r16
do i = 1, leng
! implicit type conversion i8 to r16
sum_of_values_i8 = sum_of_values_i8 + sind((i*i)/2.0_r16)
end do
! r4 -> r16
sum_of_values_r4 = 0.0_r16
do i = 1, leng
! implicit type conversion r4 to r16
sum_of_values_r4 = sum_of_values_r4 + sind((real(i,r4)*real(i,r4))/2.0_r16)
end do
! r8 -> r16
sum_of_values_r8 = 0.0_r16
do i = 1, leng
! implicit type conversion r8 to r16
sum_of_values_r8 = sum_of_values_r8 + sind((real(i,r8)*real(i,r8))/2.0_r16)
end do
! r16 = r16
sum_of_values_r16 = 0.0_r16
do i = 1, leng
! no implicit type conversion
sum_of_values_r16 = sum_of_values_r16 + sind((real(i,r16)*real(i,r16))/2.0_r16)
end do
write(output_unit,'(2ES30.20)') sum_of_values_i8 , sum_of_values_r16-sum_of_values_i8
write(output_unit,'(2ES30.20)') sum_of_values_r4 , sum_of_values_r16-sum_of_values_r4
write(output_unit,'(2ES30.20)') sum_of_values_r8 , sum_of_values_r16-sum_of_values_r8
write(output_unit,'(2ES30.20)') sum_of_values_r16, sum_of_values_r16-sum_of_values_r16
end program Implicit_Type_ConversionThe results are:
Implicit Type Conversion -> Impact on Precision
3.69082119314211831229E+02 0.00000000000000000000E+00
3.69113651696722043610E+02 -3.15323825102123810941E-02
3.69082119314211831229E+02 0.00000000000000000000E+00
3.69082119314211831229E+02 0.00000000000000000000E+00I used PSXE 16.0.2, options: /nologo /debug:full /Od /warn:interfaces /Qinit:snan /fp:source /module:"x64\Debug\\" /object:"x64\Debug\\" /Fd"x64\Debug\vc140.pdb" /traceback /check:bounds /check:stack /libs:dll /threads /dbglibs /c
I would personally not use this mixture of different types, but it would be very interesting to know, why especially the second case (r4 -> r16) differs from the other that much.
gfortran supports the '-Wconversion'/'-Wconversion-extra', which help to find out, where a type conversion is happening. Is it possible to get a 'precision loss' warning? A warning where you might loose precision would be more useful IMHO. Is there some flag for the Intel compiler? Is it possible to do this at all?
Best regards, Johannes