Puzzle computing arrays
Tim Prince
TimothyPrince@sbcglobal.net
Tue Jun 10 10:41:00 GMT 2008
Angelo Graziosi wrote:
> Tim Prince ha scritto:
>> Angelo Graziosi wrote:
>>> The following happens on Cygwin with GFortran 4.3.1 and on GNU/Linux
>>> Kubuntu 8.04 with GFortran 4.3.1 and 4.2.3.
>>>
>>> In the following test case (reduced to the simplest form), the array
>>> elements of BB() and b() are computed exactly with the same
>>> expression (copy/pasted), but the results seem a little different
>>> (only on 14-15th digit)
>>>
>>> $ cat test_case.f90
>>> !
>>> ! gfortran test_case.f90 -o test_case
>>> !
>>> program test_case
>>> implicit none
>>> integer :: k
>>> integer, parameter :: DP = kind(1.D0),&
>>> N = 3
>>> real(DP), parameter :: A(0:N) = &
>>> (/1.0000000000D0,3.8860009363D0,7.4167881843D0,&
>>> 9.8599837415D0/)
>>> real(DP), parameter :: BB(0:N-1) = &
>>> (/((A(k+1)*(A(1)+k+1)),k = 0,N-2),(A(N)*(A(1)+N))/)
>>> real(DP) :: b(0:N-1)
>>> do k = 0,N-2
>>> b(k) = A(k+1)*(A(1)+k+1)
>>> enddo
>>> b(N-1) = A(N)*(A(1)+N)
>>> do k = 0,N-1
>>> !print *, k,b(k),BB(k),b(k)-BB(k)
>>> print *, k,b(k)-BB(k)
>>> enddo
>>> end program test_case
>>>
>>> $ gfortran test_case.f90 -o test_case
>>>
>>> $ ./test_case.exe
>>> 0 0.0000000000000000
>>> 1 -7.10542735760100186E-015
>>> 2 0.0000000000000000
>>>
>>> Since BB() and b() are computed with the same expression, I would
>>> expect the same results. But BB() is a PARAMETER (computed at
>>> compile time???) and b() is computed at run time...
>>>
>>> So, what could be the difference? What explanation may you give?
>>>
>> Don't the compile time calculations get extra precision from mpfr and
>> friends? The run-time calculation would make more sense with
>> parentheses (k+1) to specify a single round-off.
>>
>
> Another test case (the previous++):
>
> $ cat test_case.f90
> !
> ! gfortran test_case.f90 -o test_case
> !
> program test_case
> implicit none
> integer :: k
> integer, parameter :: DP = kind(1.D0),&
> N = 3
> real(DP), parameter :: A(0:N) = &
> (/1.0000000000D0,3.8860009363D0,7.4167881843D0,&
> 9.8599837415D0/)
> real(DP), parameter :: BB(0:N-1) = &
> (/((A(k+1)*(A(1)+(k+1))),k = 0,N-2),(A(N)*(A(1)+N))/)
> real(DP) :: b(0:N-1),bbb(0:N-1)
> do k = 0,N-2
> b(k) = A(k+1)*(A(1)+(k+1))
> enddo
> b(N-1) = A(N)*(A(1)+N)
> bbb(0:N-1) = (/((A(k+1)*(A(1)+(k+1))),k = 0,N-2),(A(N)*(A(1)+N))/)
> do k = 0,N-1
> !print *, k,b(k),BB(k),b(k)-BB(k)
> print *, k,b(k)-BB(k),b(k)-bbb(k),BB(k)-bbb(k)
> enddo
> end program test_case
>
> $ ./test_case.exe
> 0 0.0000000000000000 0.0000000000000000 0.0000000000000000
> 1 -7.10542735760100186E-015 -7.10542735760100186E-015 0.0000000000000000
> 2 0.0000000000000000 0.0000000000000000 0.0000000000000000
>
> Now bbb() is NOT a PARAMETER but is still computed with an implied DO.
>
> It looks that computing the same expression with an implied DO is a
> little different when using an explicit DO.
>
Ideally, a short array constructor would be expanded at compile time,
when that is possible, using mpfr rather than native code. Your native
code could produce different round-off according to whether you
specified -mfpmath=387 or -mfpmath=sse.
More information about the Fortran
mailing list