Derived Array: Select Record

In my code, I have a 2D array

integer, allocatable :: elements(:,:)

      

and define some constants

integer, parameter :: TYP = 1
integer, parameter :: WIDTH = 2
integer, parameter :: HEIGHT = 3
! ...
integer, parameter :: NUM_ENTRIES = 10

      

and highlight something like

allocate(elements(NUM_ENTRIES,10000))

      

so that I can access elements like

write(*,*) elements(WIDTH,100) ! gives the width of the 100th element

      

Now I would like to have not only an integer, but a mixture of types for each element. So I define a derived type

type Element
    logical active
    integer type
    real width
    ! etc
end type

      

and use an array of elements

type(Element), allocatable :: elements(:)

      

With the 2d array version, I could call a subroutine telling it which entry to use. For example.

subroutine find_average(entry, avg)
    integer, intent(in) :: entry   
    real, intent(out) :: avg
    integer i, 
    real s

    s = 0
    do i = lbound(elements,1), ubound(elements,1)
        if (elements(TYP,i) .gt. 0) s = s + elements(entry,i)
    end do
    avg = s/(ubound(elements,1)-lbound(elements,1))
end subroutine       

      

So, I could call find_average(HEIGHT)

find the average height, or go through WIDTH

to get the average width. (And my routines do more complex things than finding the average height or width, this is just an example.)

Question: How can I use different types (as with a derived type), but also use my functions to work with different records (as in the example subroutine)?

+3


source to share


1 answer


For the case of an array, instead of passing array and index i in the argument, you can pass a single array of arguments (i). When you switch to the derived type, the same way you can pass variable_of_type% element, instead of transferring the entire peremennyy_i_i_i_i_i_i_i_i_i_i_i_i_i_po_i_po_i_po_i_po_ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee If the code has to be different for different types of items (eg, logical, integer, real), then you can write specific procedures for each, but then call with a common name via a common interface block. The compiler should be able to distinguish common interface procedures with some characteristics of the arguments, here is their type.For example code where the distinguishing characteristic is an array rank, seehow to write a wrapper for 'allocate'

EDIT: sample code. does it do what you want?



module my_subs

   implicit none

   interface my_sum
      module procedure sum_real, sum_int
   end interface my_sum

contains

subroutine sum_real (array, tot)
   real, dimension(:), intent (in) :: array
   real, intent (out) :: tot
   integer :: i

   tot = 1.0
   do i=1, size (array)
      tot = tot * array (i)
   end do
end subroutine sum_real

subroutine sum_int (array, tot)
   integer, dimension(:), intent (in) :: array
   integer, intent (out) :: tot
   integer :: i

   tot = 0
   do i=1, size (array)
      tot = tot + array (i)
   end do
end subroutine sum_int

end module my_subs


program test_dt

use my_subs

implicit none

type my_type
   integer weight
   real length
end type my_type

type (my_type), dimension (:), allocatable :: people
type (my_type) :: answer

allocate (people (2))

people (1) % weight = 1
people (1) % length = 1.0
people (2) % weight = 2
people (2) % length = 2.0

call my_sum ( people (:) % weight, answer % weight )
write (*, *)  answer % weight

call my_sum ( people (:) % length, answer % length )
write (*, *)  answer % length

end program test_dt

      

+4


source







All Articles