Фортран: выбор ранга выделяемого массива
Я пытаюсь написать программу, в которой я хочу разместить массив A
иметь ранг 1, 2 или 3, в зависимости от моего ввода во время выполнения. Я хочу сделать это, так как последующие операции на A
похожи, и я определил в модуле интерфейс work
с модульными процедурами, которые при действии A
, дает желаемый результат.
Что я делаю в настоящее время это:
program main
implicit none
integer :: rank,n=10
real*8, allocatable :: A1(:)
real*8, allocatable :: A2(:,:)
read (*,*) rank
if (rank.eq.1) then
allocate (A1(n))
else if (rank.eq.2) then
allocate (A2(n,n))
end if
! operate on the array
if (rank.eq.1) then
call work(A1)
else if (rank.eq.2) then
call work(A2)
end if
end program
Все было бы намного проще, если бы я мог выбрать звание A
, как тогда if
заявления не нужны. Может быть, это невозможно, но вся помощь приветствуется.
2 ответа
Объявите массив как ранг три. Если требуется массив более низкого ранга, выделите соответствующие конечные измерения для размера один.
real, allocatable :: array(:,:,:)
...
select case (desired_rank)
case (1) ; allocate(array(n,1,1))
case (2) ; allocate(array(n,n,1))
case (3) ; allocate(array(n,n,n))
case default ; error stop 'bad desired rank'
end select
Затем вы можете использовать секцию массива, чтобы получить непрерывный фрагмент array
это соответствует вашему желаемому званию. В качестве альтернативы, напишите соответствующие процедуры, которые работают с массивом, чтобы получить аргумент ранга три, и дайте им понять значение размера один экстент для более высоких измерений.
Следующий стандарт Fortran (2015) имеет select rank
построить аналогично select case
, Мой пример использует select case
построить на rank
внутренняя часть фиктивной переменной предполагаемого ранга.
module my_type
use, intrinsic :: iso_fortran_env, &
ip => INT32, &
wp => REAL64
implicit none
private
public :: MyType
type MyType
real (wp) :: rank0
real (wp), allocatable :: rank1(:)
real (wp), allocatable :: rank2(:,:)
real (wp), allocatable :: rank3(:,:,:)
contains
procedure :: create => create_my_type
procedure :: destroy => destroy_my_type
end type MyType
contains
subroutine create_my_type(this, array)
! calling arguments
class (MyType), intent (in out) :: this
real (wp), intent (in) :: array(..) !! Assumed-rank dummy variable
! local variables
integer (ip), allocatable :: r(:)
select case(rank(array))
case (0)
return
case (1)
r = shape(array)
allocate( this%rank1(r(1)) )
case (2)
r = shape(array)
allocate( this%rank2(r(1), r(2)) )
case (3)
r = shape(array)
allocate( this%rank3(r(1), r(2), r(3)) )
case default
error stop 'array must have rank 0,1,2, or 3'
end select
! Release memory
if (allocated(r)) deallocate( r )
end subroutine create_my_type
subroutine destroy_my_type(this)
! calling arguments
class (MyType), intent (in out) :: this
if (allocated(this%rank1)) deallocate( this%rank1 )
if (allocated(this%rank2)) deallocate( this%rank2 )
if (allocated(this%rank3)) deallocate( this%rank3 )
end subroutine destroy_my_type
end module my_type
program main
use, intrinsic :: iso_fortran_env, only: &
ip => INT32, &
wp => REAL64
use my_type, only: &
MyType
implicit none
type (MyType) :: foo
real (wp) :: a0, a1(42), a2(42,42), a3(42,42,42)
print *, rank(a0)
print *, rank(a1)
print *, rank(a2)
print *, rank(a3)
! Allocate array of rank 3
call foo%create(a3)
print *, rank(foo%rank3)
print *, shape(foo%rank3)
print *, size(foo%rank3)
! Release memory
call foo%destroy()
end program main