Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29007 Discussions

How to get the size of a vector in a subroutine.

woshiwuxin
Novice
852 Views
Hi, everyone!

I want to get the size of a vector in a subroutine, and the vector itself is as a subroutine argument.

Below is a simple code:

[plain]      program ex
        implicit none
! The size of a vector, ap, is defined as 4 in the main program.
        integer(kind=2),parameter::n=4
        real(kind=4)::ap(n)
        ap=1.2E0
! Here I want to get the size of ap by calling sub(ap).
        call sub(ap)
        stop
      end program ex

! Sub should be able to find out the size of a, but it fails.
! Can anyone help me in this part?
      subroutine sub(a)
        implicit none
        real(kind=4),intent(in)::a(:)
        integer(kind=2)::n
        intrinsic::size
        n=size(a)
        write(*,*) n
        return
      end subroutine sub
[/plain]
In the above subroutine, sub(a), can not find out the size of a correctly. Can anyone help me on this?

Thanks in advance!
0 Kudos
1 Solution
Steven_L_Intel1
Employee
852 Views

If you have an existing library of routines, and you want to provide explicit interfaces for them, then it is reasonable to do so as a separate module as is done in Intel MKL with the BLAS routines. You can do that too if you wish. It all depends on how you want your program to be organized. If you do have a separate interface block, you have to make sure that if you change the actual routine's declarations that you make the corresponding change in the interface - making the routines module or internal procedures eliminates this opportunity for error.

View solution in original post

0 Kudos
6 Replies
woshiwuxin
Novice
852 Views
I have a solution for this problem by using module in Fortran 90. But for Fortran 77, an interface definition might be needed to solve the problem. I'm not very familiar with Fortran 77, so I could only provide the solution by using Fortran 90.

[plain]      module tools
      contains
        subroutine sub(a)
          implicit none
          integer(kind=2)::dima
          real(kind=4),intent(in)::a(:)
          intrinsic::size
          dima=size(a)
          write(*,*) dima
          return
        end subroutine sub
      end module tools

      program ex
        use tools
        implicit none
        integer(kind=2),parameter::n=50
        real(kind=4)::ap(n)
        ap=1.2E0
        call sub(ap)
        stop
      end program ex
[/plain]

I know some differences between Fortran 77 and 90, but I'm not very familiar with those details. Can the Fortran guru give me more infomation (references, books) on this topic?

Thanks in advance!


0 Kudos
woshiwuxin
Novice
852 Views
After reading some Fortran 77 books, I found the interface solution for this problem.

The code is attached.

[plain]      program ex
        implicit none
        interface
          subroutine sub(a)
            implicit none
            real(kind=4),intent(in)::a(:)
          end subroutine sub
        end interface
        integer(kind=2),parameter::n=48
        real(kind=4)::ap(n)
        ap=1.2E0
        call sub(ap)
        stop
      end program ex

      subroutine sub(a)
        implicit none
        integer(kind=2)::n
        real(kind=4),intent(in)::a(:)
        intrinsic::size
        n=size(a)
        write(*,*) n
        return
      end subroutine sub
[/plain]

Any comments on interface of Fortran 77 and module of Fortran 90 are highly appreciated!

0 Kudos
Steven_L_Intel1
Employee
852 Views
My general rule is: if you think you have to write an INTERFACE block for a Fortran routine, you're doing it wrong. Instead, the routine you're calling should be in a MODULE or be an internal procedure. An example of the latter is as follows:

[plain]     program ex
        implicit none
        integer(kind=2),parameter::n=48
        real(kind=4)::ap(n)
        ap=1.2E0
        call sub(ap)
        stop

      contains

      subroutine sub(a)
        implicit none
        integer(kind=2)::n
        real(kind=4),intent(in)::a(:)
        intrinsic::size
        n=size(a)
        write(*,*) n
        return
      end subroutine sub

      end program ex

[/plain]

0 Kudos
woshiwuxin
Novice
852 Views
Thank you, Steve!

I was actually inspired by the approach that Intel employed in order to create the Fortran 95 interface for BLAS and LAPACK libraries. There're two *.f90 files, namely blas_interfaces.f90 and lapack_interfaces.f90, located in $MKLROOT/interfaces/blas95(or lapack95)/source. I observe the general structure for those two files is:
[plain]MODULE MODULE_NAME
INTERFACE INTERFACE_NAME
  PURE FUNCTION FUNCTION_NAME
  ...
  END FUNCTION FUNCTION_NAME
  ...
  PURE SUBROUTINE SUBROUTINE_NAME
  ...
  END SUBROUTINE SUBROUTINE_NAME
  ...
END INTERFACE INTERFACE_NAME
END MODULE MODULE_NAME[/plain]
It seems that using this approach one can establish an explicit interface between the MODULE, i.e. MODULE_NAME, and the associated external procedures, i.e. FUNCTION_NAME and SUBROUTINE_NAME, and let the compiler to check the consistency of the actual and dummy arguments. Is there a better way to make such explicit interfaces between a module and the relevant external procedures?

One can, of course, put all those external procedures into the module just after "contains", which makes the external procedures like "internal procedures". However, this would increase the size of the module file and consume more compile time if one of the internal procedures is modified.



0 Kudos
Steven_L_Intel1
Employee
853 Views

If you have an existing library of routines, and you want to provide explicit interfaces for them, then it is reasonable to do so as a separate module as is done in Intel MKL with the BLAS routines. You can do that too if you wish. It all depends on how you want your program to be organized. If you do have a separate interface block, you have to make sure that if you change the actual routine's declarations that you make the corresponding change in the interface - making the routines module or internal procedures eliminates this opportunity for error.
0 Kudos
woshiwuxin
Novice
852 Views

If you have an existing library of routines, and you want to provide explicit interfaces for them, then it is reasonable to do so as a separate module as is done in Intel MKL with the BLAS routines. You can do that too if you wish. It all depends on how you want your program to be organized. If you do have a separate interface block, you have to make sure that if you change the actual routine's declarations that you make the corresponding change in the interface - making the routines module or internal procedures eliminates this opportunity for error.

Thank you, Steve!

Now I understand why people like module :-)
0 Kudos
Reply