Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have generic subroutine to work in fortran with assumed size array

I have an interface block to define a generic subroutine which have an assumed size array as dummy argument (in order to be able to act on 'the middle' of a passed array, like a C pointer) and it does not compile. Here is simple exemple:

module foo

  interface sub
     module procedure isub
     module procedure dsub
  end interface

  contains

  subroutine isub(a,n)
    integer, intent(in) :: a(*), n
    integer :: i
    print*, 'isub'
    do i=1,n
     print*, a(i)
    enddo
  end subroutine isub

  subroutine dsub(a)
    real(8), intent(in) :: a(*)
    integer, intent(in) :: n
    integer :: i
    print*, 'dsub'
    do i=1,n
     print*, a(i)
    enddo
  end subroutine dsub

end module foo

program test

  use foo

  implicit none

  integer :: ai(4)
  real(8) :: ad(4)

  ai=(/1,2,3,4/)
  ad=(/1.,2.,3.,4./)

  call sub(ai,3)
  call sub(ad,3)

  call isub(ai(2),3)
  !call sub(ai(2),3)

end program test

The commented line does not compile, whereas it is ok when calling directly the subroutine with call isub(ai(2),3) (tested with gfortran and ifort). Why and is it possible to have it to work with call sub(ai(2),3)?

edit: with ifort, it says:

$ ifort overload.f90
overload.f90(37): error #6285: There is no matching specific subroutine for this generic subroutine call.   [SUB]
  call sub(ai(2),3)
-------^
compilation aborted for overload.f90 (code 1)

Thanks

like image 948
janou195 Avatar asked Oct 24 '25 18:10

janou195


1 Answers

You are passing a scalar to a function that is expecting an array. Try

call sub(ai(2:2))

which is passing an array of length one. I'm wondering why call isub(ai(2)) is accepted, though...

To answer your new question (partly in the comments):

If you restrict yourself to contiguous arrays, you can use call sub(ai(2:4)) without loss of performance using deferred shape arrays:

subroutine isub(a)
  integer,intent(in) :: a(:)
  integer            :: i

  print*, 'isub'
  do i=1,size(a)
    print*, a(i)
  enddo
end subroutine isub

There are no temporary arrays created with ifort or gfortran. You can check for this using:

  • ifort -check arg_temp_created

  • gfortran -Warray-temporaries

like image 183
Alexander Vogt Avatar answered Oct 27 '25 08:10

Alexander Vogt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!