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

Can a function return an array?

Carsten_A_
Beginner
1,538 Views

Is it possible to return an array via function?

I tried following

program test
    !dec$ attributes dllimport :: Vector
    implicit none
    real(8), dimension(2) :: dir, Vec, newVec
    dir = [3, 5]
    newVec = Vec(dir)
    print*, newVec
    pause
end program
function Vector(direction)
    !dec$ attributes dllexport :: Vector
    implicit none
    real(8), intent(in), dimension(2) :: direction
    real(8), dimension(2) :: Vector
    Vector = direction * 2
end function

I get the error:

Subscript #1 of the array VEC has value 3 which is greater than the upper bound of 2

What am I doing wrong?

0 Kudos
1 Solution
FortranFan
Honored Contributor III
1,538 Views

Carsten A. wrote:

Is it possible to return an array via function?

...

You can also consider code along the following lines:

MODULE m

   USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY : R8 => REAL64, I4 => INT32

   !..
   IMPLICIT NONE

   !..
   PRIVATE

   PUBLIC :: Vector

CONTAINS

   PURE FUNCTION Vector(direction) RESULT(NewVec)

      !.. Argument list
      REAL(R8), INTENT(IN) :: direction(:)

      !.. Function result
      REAL(R8), DIMENSION(SIZE(direction)) :: NewVec

      !..
      NewVec = direction * REAL(2, KIND=R8)

      !..
      RETURN

   END FUNCTION Vector

END MODULE m

PROGRAM p

   USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY : R8 => REAL64

   USE m, ONLY : Vector

   IMPLICIT NONE

   !.. Local variables
   REAL(R8), DIMENSION(2) :: dir, newVec

   dir = [3, 5]
   newVec = Vector(dir)
   PRINT *, "newVec = ", newVec

   !..
   STOP

END PROGRAM p

 

Also, see Dr Fortran's blog at https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world.  As you may be well aware, Dr Fortran's blogs in general and the various books references in the particular blog on modern Fortran all point out to your benefit the various aspects including:

  • the benefit of using MODULEs, especially in terms of providing interface information on procedures, code readability, access control, information hiding, etc.
  • the various KIND, SHAPE, RANK features available in the language standard with various INTRINSIC modules (ISO_FORTRAN_ENV) and kinds (REAL64, INT32, etc.) and SIZE function that allows one to write portable as well as flexible code (notice how the function Vector in above snippet is not restricted to a dimension of 2),

Also, I suggest looking at Quote #5 in this post (https://software.intel.com/en-us/forums/topic/486623) about the option of .DEF files if you want to include your functions such as Vector in a DLL: this can be an alternate option to including the !DEC$ directives in the code which requires additional attention with respect to code portability in addition to causing code clutter (in the eyes of some).

View solution in original post

0 Kudos
5 Replies
mecej4
Honored Contributor III
1,538 Views

You probably meant to write "vector" where you wrote "vec" at two places in the main program.

A function that returns a array should be given an explicit interface in the caller. That is what the compiler is grumbling about, but in a roundabout way.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,538 Views

What you have done is something analogous to a gather statement (using an array of indicies)

Vec(dir) is equivalent to [Vec(dir(1)), Vec(dir(2))] which is equivalent to [Vec(3), Vec(5))]

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
1,538 Views

For more info on explicit interfaces, see Doctor Fortran Gets Explicit - Again!

0 Kudos
FortranFan
Honored Contributor III
1,539 Views

Carsten A. wrote:

Is it possible to return an array via function?

...

You can also consider code along the following lines:

MODULE m

   USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY : R8 => REAL64, I4 => INT32

   !..
   IMPLICIT NONE

   !..
   PRIVATE

   PUBLIC :: Vector

CONTAINS

   PURE FUNCTION Vector(direction) RESULT(NewVec)

      !.. Argument list
      REAL(R8), INTENT(IN) :: direction(:)

      !.. Function result
      REAL(R8), DIMENSION(SIZE(direction)) :: NewVec

      !..
      NewVec = direction * REAL(2, KIND=R8)

      !..
      RETURN

   END FUNCTION Vector

END MODULE m

PROGRAM p

   USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY : R8 => REAL64

   USE m, ONLY : Vector

   IMPLICIT NONE

   !.. Local variables
   REAL(R8), DIMENSION(2) :: dir, newVec

   dir = [3, 5]
   newVec = Vector(dir)
   PRINT *, "newVec = ", newVec

   !..
   STOP

END PROGRAM p

 

Also, see Dr Fortran's blog at https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world.  As you may be well aware, Dr Fortran's blogs in general and the various books references in the particular blog on modern Fortran all point out to your benefit the various aspects including:

  • the benefit of using MODULEs, especially in terms of providing interface information on procedures, code readability, access control, information hiding, etc.
  • the various KIND, SHAPE, RANK features available in the language standard with various INTRINSIC modules (ISO_FORTRAN_ENV) and kinds (REAL64, INT32, etc.) and SIZE function that allows one to write portable as well as flexible code (notice how the function Vector in above snippet is not restricted to a dimension of 2),

Also, I suggest looking at Quote #5 in this post (https://software.intel.com/en-us/forums/topic/486623) about the option of .DEF files if you want to include your functions such as Vector in a DLL: this can be an alternate option to including the !DEC$ directives in the code which requires additional attention with respect to code portability in addition to causing code clutter (in the eyes of some).

0 Kudos
Carsten_A_
Beginner
1,538 Views

I put the function in a module and it works fine!

Thanks at all!

0 Kudos
Reply