Silverfrost Forums

Welcome to our forums

Array asignment problem

20 Jan 2017 11:59 #18732

The following example of array assignment fails with FTN95 Ver 8.05 for both 32 and /64. The array a is not correctly assigned, as LHS = calculation of RHS array. I am assuming this is valid Fortran 90/95 syntax ? 32 and 64 give different wrong results. ! Test of array assignment ! expected result ! a = 1 1 2 3 4 ! b = 1 1 2 4 8 ! ! fails with ftn95 /lgo ! fails with ftn95 /64 /lgo ! implicit none integer :: i, a(5) = 1, b(5) = 1 ! ! array assignment
a(2:5) = (/ (sum(a(1:i-1)),i = 2,5) /) write (,) ' a=',a ! ! DO loop asignment
do i = 2,5 b(i) = sum(b(1:i-1)) end do print '(A,5I2)',' a =',a,' b =',b end program

21 Jan 2017 2:02 #18733

With the 32-bit compiler, the option /check causes integer overflow to be detected during the array expression evaluation and assignment.

21 Jan 2017 12:41 #18736

I have logged this for investigation.

15 Apr 2019 12:02 #23497

I have carried out an initial investigation of this issue. There is certainly a bug in FTN95 when SUM is used within this particular array constructor. But there is a more fundamental issue which arises with similar cases when calling any function (not just the intrinsic SUM).

If the value of A(3) say depends on A(2) and/or A(1) then FTN95 will probably give an 'incorrect' result. This is also the case with gFortran and perhaps other compilers as well.

The Fortran Standard does indeed say that an implied DO within an array constructor should be expanded element by element but the issue of feedback is not mentioned and one might naturally assume that the RHS can be evaluated as a block before copying to the LHS.

My initial investigation suggests that a vast amount of work would be needed in order to 'fix' this more fundamental issue and I am not convinced that it ought to be 'fixed'.

If anyone has the interest and has access to other compilers then you might like to test the output from following code.

  integer function mysum(a)
  integer a(:)
    mysum = sum(a)
  end function
  
  program main
  interface
   integer function mysum(a)
   integer a(:)
   end function
  end interface
  integer :: i, a(5) = 1 
  a(2:5) = (/ (mysum(a(1:i-1)),i = 2,5) /) 
  print*, a
  do i = 2,5 
     a(i) = sum(a(1:i-1)) 
  end do 
  print*, a
  end program
16 Apr 2019 4:41 #23501

Paul,

FTN95 and gFortran results are the same when run in Plato (with slight changes)

  integer function mysum(a) 
  integer a(:) 
    mysum = sum(a) 
  end function 
  
  program main 
  interface 
   integer function mysum(a) 
   integer a(:) 
   end function 
  end interface 
  integer :: i, a(5) = 1 

  open (unit=98,file='mysum.log',position='append')
  call echo_dll_version

  a(2:5) = (/ (mysum(a(1:i-1)),i = 2,5) /) 
  write ( *,*) a , '  = (/ (mysum(a(1:i-1)),i = 2,5) /) '
  write (98,*) a , '  = (/ (mysum(a(1:i-1)),i = 2,5) /) '

  do i = 2,5 
     a(i) = sum(a(1:i-1)) 
  end do 
  write ( *,*) a , '  = do i=2,5; a(i) = sum(a(1:i-1)); end do '
  write (98,*) a , '  = do i=2,5; a(i) = sum(a(1:i-1)); end do '
  end program

      subroutine echo_dll_version
!
      character str_info*256
!
      call get_compiler_version (str_info)
      write ( *,1000) ' compiler_version : ', trim (str_info)
      write (98,1000) ' compiler_version : ', trim (str_info)

      call get_compiler_options (str_info)
      write ( *,1000) ' compiler_options : ', trim (str_info)
      write (98,1000) ' compiler_options : ', trim (str_info)

      write ( *,1000) ' '
      write (98,1000) ' '
 1000 FORMAT (a,a)
!
      RETURN
!
      END

      subroutine get_compiler_version ( version )
!gf use iso_fortran_env

      character version*(*)
      character ftn95_ver*80
!
!gf   version = compiler_version ()
!
      include <ftn95_ver.ins>
      version = ftn95_ver
      end
      
      subroutine get_compiler_options ( options )
!gf use iso_fortran_env

      character options*(*)
!
!gf      options = compiler_options ()
      options = 'FTN95 options not available'
      end
 
 compiler_version : GCC version 8.2.0
 compiler_options : -cpp -iprefix c:\program files (x86)\gcc_eq\gcc_8.2.0\bin\../lib/gcc/x86_64-w64-mingw32/8.2.0/
 -U_REENTRANT -mtune=generic -march=x86-64 -fno-underscoring -fdollar-ok
 
           1           1           2           3           4   = (/ (mysum(a(1:i-1)),i = 2,5) /) 
           1           1           2           4           8   = do i=2,5; a(i) = sum(a(1:i-1)); end do 
 compiler_version : [FTN95/x64 Ver. 8.40.0 Nov18 Copyright (c) Silverfrost Ltd 1993-2018]
 compiler_options : FTN95 options not available

            1           1           2           3           4  = (/ (mysum(a(1:i-1)),i = 2,5) /)
            1           1           2           4           8  = do i=2,5; a(i) = sum(a(1:i-1)); end do
16 Apr 2019 6:54 (Edited: 17 Apr 2019 8:14) #23504

In an assignment statement, the effect should be the same as if the expression on the right of the '=' is completely evaluated before the variable or array section on the left is assigned the value(s) calculated. In other words, there can be no feedback of newly computed values of array elements into the remaining expression evaluations.

The calculations of the elements of the array valued expression and putting those values into the elements of the array section may be carried out in any order -- not necessarily in the order of increasing index i.

Consider the following modification of John's original example program:

! Test of array assignment
! expected result
! a = 4 3 2 1 1
!
!  garbage output with ftn95 /lgo
!  access violation with ftn95 /64 /lgo
!
  implicit none
  integer :: i, a(5) = 1
!
! array assignment
  a(1:4) = (/ (sum(a(i+1:5)),i = 1,4) /)
  write (*,*) ' a=',a
  end program

Each element of a is to be set equal to the sum of the original values of the elements that come after it in increasing index order. The EXE from the 32-bit FTN95 compiler gives garbage output, and the 64-bit compiler produces a program that aborts with an access violation. If /check or /checkmate are used, further errors occur.

16 Apr 2019 6:58 #23505

John

Your results confirm my experience. If these results are both 'correct' then an implied DO within an array constructor is not equivalent to a explicit DO loop in situations like this where there is 'feedback'.

4 May 2019 3:11 #23581

This issue has now been fixed for the next release of FTN95 after 8.50.

Please login to reply.