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)?
source to share
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
source to share