Reputation: 5425
I'm compiling a simple fortran program with gfortran and ifort:
! acos.f90
function real8_to_int8(real8) result(int8)
real(8), intent (in) :: real8
integer(8) :: int8
int8 = transfer(real8, int8)
end function
function int8_to_real8(int8) result(real8)
integer(8), intent (in) :: int8
real(8) :: real8
real8 = transfer(int8, real8)
end function
program main
integer(8) :: real8_to_int8
real(8) :: int8_to_real8
real :: x, acos_x
x = int8_to_real8(4605852290655121993)
print *, " size of x: ", sizeof(x)
write (*, '(A, F65.60)') ' x: ', x
print *, ""
acos_x = acos(x)
write (*, '(A, F65.60)') ' acos(x): ', acos(x)
print *, "bits: ", real8_to_int8(acos_x)
print *, ""
print *, ""
end program
To compare the results as precisely as possible, I print out the variables' bit representations, and they are different:
ifort:
$ ifort -real-size 64 -o acos_ifort acos.f90; ./acos_ifort
size of x: 8
x: 0.852326110783516388558211929193930700421000000000000000000000
acos(x): 0.550379481046229246388179490168113261461000000000000000000000
bits: 4603132597196780746
gfortran:
$ gfortran -fdefault-integer-8 -fdefault-real-8 -o acos_gfortran acos.f90; ./acos_gfortran
size of x: 8
x: 0.852326110783516388558211929193930700421333312988281250000000
acos(x): 0.550379481046229357410481952683767303824424743652343750000000
bits: 4603132597196780747
Is the difference on variable acos(x)
normal? Or how can I change my gfortran compiling option to make the result of gfortran the same as ifortran?
ifort:
acos(x): 0.550379481046229246388179490168113261461000000000000000000000
bits: 4603132597196780746
gfortran:
acos(x): 0.550379481046229357410481952683767303824424743652343750000000
bits: 4603132597196780747
Upvotes: 1
Views: 204
Reputation: 37248
Yes, the difference in angle
is normal. You cannot generally assume different implementations of the trigonometrical functions to produce bit-exact results. As you can see from the integer representation there's only a 1 ulp difference between the two values, which is entirely reasonable.
EDIT And as a standards-conformance and style issue, here's a version of your code with
int64
and real64
from the iso_fortran_env
builtin module instead of the non-portable kind=8
.transfer
directly, but just to demonstrate usage of contained procedures).-fdefault-real-8
and similar options.
! acos.f90
program main
use iso_fortran_env
real(real64) :: x, acos_x
x = int8_to_real8(4605852290655121993_int64)
print *, " size of x: ", sizeof(x)
write (*, '(A, F65.60)') ' x: ', x
print *, ""
acos_x = acos(x)
write (*, '(A, F65.60)') ' acos(x): ', acos(x)
print *, "bits: ", real8_to_int8(acos_x)
print *, ""
print *, ""
contains
function real8_to_int8(real8) result(int8)
real(real64), intent (in) :: real8
integer(int64) :: int8
int8 = transfer(real8, int8)
end function
function int8_to_real8(int8) result(real8)
integer(int64), intent (in) :: int8
real(real64) :: real8
real8 = transfer(int8, real8)
end function
end program
Upvotes: 3