2

As per object, I'm struggling understanding the logic behind functions returning allocatable arrays. I like this construct because its clarity compared to subroutines, and because pure functions in fortran are an excellent way to write clean, functional programming code.

Assume I have to write a simple function, returning an array of indices, with arbitrary bounds, such as in this program:

program test_allocatable_functionReturn
      implicit none

      integer, allocatable :: fun(:),sub(:),noa(:)
      integer, parameter :: low = -4
      integer, parameter :: hi  = 3

      call testsub(sub,low,hi)
      fun = testfun(low,hi)
      noa = testfun_noalloc(low,hi)

      print '(4(a,i3),a)', 'testsub:  lbound=',lbound(sub),'(expected = ',low,'), ubound=',ubound(sub),'(expected = ',hi,')'
      print '(4(a,i3),a)', 'testfun:  lbound=',lbound(fun),'(expected = ',low,'), ubound=',ubound(fun),'(expected = ',hi,')'
      print '(4(a,i3),a)', 'no alloc: lbound=',lbound(noa),'(expected = ',low,'), ubound=',ubound(noa),'(expected = ',hi,')'


      contains
             pure function testfun_noalloc(low,hi) result(array)
                integer, intent(in) :: low,hi
                integer :: array(low:hi)
                integer :: i
                 forall(i=low:hi) array(i) = i
             end function testfun_noalloc


             pure function testfun(low,hi) result(array)
                integer, allocatable :: array(:)
                integer, intent(in) :: low,hi
                integer :: i
                 allocate(array(low:hi))
                 forall(i=low:hi) array(i) = i
             end function testfun


             pure subroutine testsub(array,low,hi)
                integer, intent(out), allocatable :: array(:)
                integer, intent(in) :: low,hi
                integer :: i
                 allocate(array(low:hi))
                 forall(i=low:hi) array(i) = i
             end subroutine testsub

end program

I have implemented it in three ways:

  • a function returning an allocatable array (testfun)
  • a subroutine (testsub)
  • a function returning a static array (testfun_noalloc)

The subroutine operates on the return array, and allocates it properly. In the example, an array sized (-4:3) should be returned. The function, in either implementation, returns an (1:hi-low+1) -sized array:

testsub:  lbound= -4(expected =  -4), ubound=  3(expected =   3)
testfun:  lbound=  1(expected =  -4), ubound=  8(expected =   3)
no alloc: lbound=  1(expected =  -4), ubound=  8(expected =   3)

Why is that happening? I get the fact that fortran may reallocate the array when assigning the function return value to my LHS array, but even so, why isn't it allocated with the proper bounds? I understand such may happen when passing the static array to an allocatable with f2003-style reallocation of the lhs, but with an allocatable array as input, I was expecting the bounds information to be conserved. Am I missing something here? BTW, this example was compiled with gfortran 9.2.0.

Thanks, Federico

Federico Perini
  • 1,414
  • 8
  • 13
  • As noted in answers to the linked questions, the lower bound of an array expression not a whole array is always 1, regardless of the bounds of the array used in that expression. – francescalus Jul 06 '20 at 17:28
  • Got it thanks - I understand the reasons. But, IMHO this makes working with value-sized arrays much less appealing.... – Federico Perini Jul 07 '20 at 06:49

0 Answers0