Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs have moved to the Altera Community. Existing Intel Community members can sign in with their current credentials.

Getter functions for arrays

zp3
Beginner
705 Views

Hi,

I wonder if there exists an easy way to implement a getter function for an array valued attribute?

For instance, one has a derived item, for example the extensions of a process grid (pgrid). As this item can be retrieved lets say from an mpi subroutine using a given communcator, it would be cleaner not to store this informations redundantly:

...

type :: PGRID
    integer :: comm
  contains
    procedure :: psizes => get_psizes
end type PGRID

...

module function get_psizes(this) result(psizes)
    class(PGRID), intent(in) :: this
    integer :: psizes(2)
end function get_psizes

...

! now if one wants to access 'psizes' like an array, 
! that does obviously produce an error because indexing
! is interpreted as  a second argument

dim1=pgrid%psizes(1)  ! -> error

 

I have found this more complicated workaraound, so that indexing should work, but I'm not very happy with it:

type :: PGRID
    integer :: comm
  contains
    procedure psizes => get_psizes
end type PGRID

...

interface get_psizes
    module function get_psizes_array(this,k) result(psizes)
        class(PGRID), intent(in) :: this
        integer, optional, intent(in) :: k(:)
        integer :: psizes(size(k))
    end function get_psizes_array

    module function get_psizes_single(this,k) result(psizes)
        class(PGRID), intent(in) :: this
        integer, optional, intent(in) :: k
        integer :: psizes
    end function get_psizes_single
end interface get_psizes

So is there any better solution for this problem?

- Thanks in advance

0 Kudos
1 Solution
FortranFan
Honored Contributor III
705 Views

Are you looking for something like this?  Look at the couple of different options, a function accepting an index and returning a scalar and another that returns a vector that can be used in multiple ways but shown below with an ASSOCIATE construct.

module m

   implicit none

   type :: t
      integer :: i(2)
   contains
      private
      procedure, pass(this) :: get_i_scalar
      procedure, pass(this) :: get_i_vector
      generic, public :: get_i => get_i_scalar, get_i_vector
   end type

contains

   pure function get_i_scalar(this, idx) result(ival)

      class(t), intent(in) :: this
      integer, intent(in)  :: idx
      !.. function result
      integer :: ival

      !.. checks elided
      ival = this%i(idx)

      return

   end function get_i_scalar

   pure function get_i_vector(this) result(ival)

      class(t), intent(in) :: this
      !.. function result
      integer :: ival(size(this%i))

      !.. checks elided
      ival = this%i

      return

   end function get_i_vector

end module m
program p

   use m, only : t

   implicit none

   type(t) :: foo
   integer :: i1
   integer :: i2

   foo%i = [ 1, 2 ]

   i1 = foo%get_i(1)
   print *, " i1 = ", i1

   asc: associate ( i => foo%get_i() )
      i2 = i(2)
      print *, " i2 = ", i2
   end associate asc

   stop

end program p

 

View solution in original post

0 Kudos
1 Reply
FortranFan
Honored Contributor III
706 Views

Are you looking for something like this?  Look at the couple of different options, a function accepting an index and returning a scalar and another that returns a vector that can be used in multiple ways but shown below with an ASSOCIATE construct.

module m

   implicit none

   type :: t
      integer :: i(2)
   contains
      private
      procedure, pass(this) :: get_i_scalar
      procedure, pass(this) :: get_i_vector
      generic, public :: get_i => get_i_scalar, get_i_vector
   end type

contains

   pure function get_i_scalar(this, idx) result(ival)

      class(t), intent(in) :: this
      integer, intent(in)  :: idx
      !.. function result
      integer :: ival

      !.. checks elided
      ival = this%i(idx)

      return

   end function get_i_scalar

   pure function get_i_vector(this) result(ival)

      class(t), intent(in) :: this
      !.. function result
      integer :: ival(size(this%i))

      !.. checks elided
      ival = this%i

      return

   end function get_i_vector

end module m
program p

   use m, only : t

   implicit none

   type(t) :: foo
   integer :: i1
   integer :: i2

   foo%i = [ 1, 2 ]

   i1 = foo%get_i(1)
   print *, " i1 = ", i1

   asc: associate ( i => foo%get_i() )
      i2 = i(2)
      print *, " i2 = ", i2
   end associate asc

   stop

end program p

 

0 Kudos
Reply