Procedure for any type of array in Fortran

六月ゝ 毕业季﹏ 提交于 2020-05-24 02:25:24

问题


Basis: I want to write a procedure which make some operation for any input array type: integer, real(4), real(8), etc. The only idea i read on StackOverflow is to imitate C++ templates, using generic procedures for overriding and preprocessor for including duplicating code.

But searching for API of popular I/O software, i found this in manual:

function nf90_put_var(ncid, varid, values, start, count, stride, map)
    integer, intent(in) :: ncid, varid
    any valid type, scalar or array of any rank, intent(in) :: values
    ...

And it really works normally for every array type of every rank, passed to values.

Question: They can't predict any rank, so they cant make explicit templates for every case. How i can build the same friendly interface?


回答1:


This is the same situation as with the MPI procedures. The key is (at least in Fortran 2008 and older) to use implicit interface to the routine. In that case no argument checking takes place and you can pass whatever you want. You have the implicit interface if the procedure is external.This is the same situation as with the MPI procedures. The key is (at least in Fortran 2008 and older) to use implicit interface to the routine. In that case no argument checking takes place and you can pass whatever you want. You have the implicit interface if the procedure is external.

Example:

     subroutine store(A,count,sizeof)
         use iso_fortran_env, only: int8
         integer, intent(in) :: count, sizeof
         integer(int8) :: A(count*sizeof)
         integer :: u

         !here you can treat A just as an array of count*sizeof bytes
       open(newunit=u,file=out.bin,access=stream)
        write(u)  A
        close(u)

     end subroutine

     program p
       real :: A(5,6)
       call store(A, size(A), storage_size(A(1,1))/8)

     end program

When you need the explicit interface, you could (untested) do something like (not supported by many compilers, beyond Fortran 2008):

    subroutine typebound(self, A, count, sizeof)
      class(my_class) :: self
      TYPE(*),DIMENSION(..) :: A
      integer, intent(in) :: count, sizeof

      !subroutine
      call store(A, count, sizeof)

or use the directives which a few compilers support:

    !GCC$ attributes no_arg_check::A
    !DEC$ attributes no_arg_check::A

this disables the check of the arguments.




回答2:


To complement the last part of Vladimir's answer: The mpi_f08 module defines most routines with the following unportable part, which seems to suit most compilers (but most likely, not all):

!DEC$ ATTRIBUTES NO_ARG_CHECK :: sendbuf, recvbuf
!GCC$ ATTRIBUTES NO_ARG_CHECK :: sendbuf, recvbuf
!$PRAGMA IGNORE_TKR sendbuf, recvbuf
!DIR$ IGNORE_TKR sendbuf, recvbuf
!IBM* IGNORE_TKR sendbuf, recvbuf

(Adjust the variable names according to your needs.)



来源:https://stackoverflow.com/questions/26032511/procedure-for-any-type-of-array-in-fortran

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!