Fortran在通用索引集上进行循环?
我有一个N维数据集(比如实数),它存储为一个1D数组,另外还有一个指定原始维度的维度数组 此外,还给出了从N-D指数推导一维指数和从N-D指数推导一维指数的函数 我试图弄清楚如何为通用的N维索引(当然,它将被转换为1D索引)创建一个do循环(或等效循环),从一组限制性的较低索引到一组较高的索引。 因此,我需要一个“N维”循环,不会遍历所有的值——只遍历数组的一部分,因此对等效1D数组进行线性索引是不相关的(至少没有修改) 这是我的问题的示意图:Fortran在通用索引集上进行循环?,fortran,do-loops,Fortran,Do Loops,我有一个N维数据集(比如实数),它存储为一个1D数组,另外还有一个指定原始维度的维度数组 此外,还给出了从N-D指数推导一维指数和从N-D指数推导一维指数的函数 我试图弄清楚如何为通用的N维索引(当然,它将被转换为1D索引)创建一个do循环(或等效循环),从一组限制性的较低索引到一组较高的索引。 因此,我需要一个“N维”循环,不会遍历所有的值——只遍历数组的一部分,因此对等效1D数组进行线性索引是不相关的(至少没有修改) 这是我的问题的示意图: subroutine Test(Array,Dim
subroutine Test(Array,Dims,MinIndex,MaxIndex)
implicit none
real , dimension(1:), intent(inout) :: Array
integer, dimension(1:), intent(in) :: Dims,MinIndex,MaxIndex
integer, dimension(size(Dims)) :: CurrInd
integer :: 1Dindex
! size(Dims) can be 1, 2, 3 ,..., N
! size(MinIndex)==size(MaxIndex)==size(Dims)
! size(Array)==Product(Dims)
! 1Dindex=Get1dInd(NDindex,Dims)
! NDindex=GetNdInd(1Dindex,Dims)
! How do I actually preform this?
do CurrInd=MinIndex,MaxIndex
1Dindex=Get1dInd(CurrInd,Dims)
<Some operation>
enddo
end subroutine
子例程测试(数组、Dims、MinIndex、MaxIndex)
隐式无
实数,维度(1:),意图(inout)::数组
整数,维度(1:),意图(in)::Dims,MinIndex,MaxIndex
整数,维度(大小(Dims))::CurrInd
整数::1Dindex
! 尺寸(Dims)可以是1、2、3、…、N
! 大小(最小索引)=大小(最大索引)=大小(Dims)
! 大小(数组)==产品(Dims)
! 1Dindex=Get1Indd(NDindex,Dims)
! NDindex=GetNdInd(1Dindex,Dims)
! 我该怎么做呢?
do CurrInd=最小索引,最大索引
1Dindex=Get1Indd(当前索引,Dims)
结束循环
结束子程序
我想可以在Dims
数组上循环并使用内部循环,但我无法将过程正确地写下来
另一个对我不起作用的选项(可能是因为我使用不正确?)是
FORALL
,因为这要求单独指定每个索引。如果在编译时知道数组的维度,可以执行一系列嵌套的do
循环,它们中的每一个都在MinIndex
和MaxIndex
的成对组件之间运行。因为你不知道尺寸,那是不可能的
我能想到的最简单的策略是在所有1D索引上使用单个DO
循环。对于每个索引,计算N维索引,并检查它是否在MinIndex
和MaxIndex
提供的范围内:如果是,继续执行您需要的操作;如果不是,则放弃该1D索引并转到下一个索引。如果索引是连续的,您可能能够做一些更聪明的事情,跳过您知道您不会感兴趣的索引块
do OneDindex = 1, size(Array)
CurrInd = GetNDInd(OneDindex, Dims)
if ((any(CurrInd<MinIndex)) .or. (any(CurrInd>MaxIndex))) cycle
! <Some operation>
end do
do OneDindex=1,大小(数组)
CurrInd=GetNDInd(OneDindex,Dims)
if((任意(currendmaxindex))循环
!
结束
请注意,就索引操作而言,此策略与并行循环兼容
还请注意,Fortran变量必须以字母开头:
1Dindex
不是有效的Fortran变量名。如果您在编译时知道数组的维度,则可以执行一系列嵌套的do
循环,每个循环在MinIndex
和MaxIndex
的组件对之间运行。因为你不知道尺寸,那是不可能的
我能想到的最简单的策略是在所有1D索引上使用单个DO
循环。对于每个索引,计算N维索引,并检查它是否在MinIndex
和MaxIndex
提供的范围内:如果是,继续执行您需要的操作;如果不是,则放弃该1D索引并转到下一个索引。如果索引是连续的,您可能能够做一些更聪明的事情,跳过您知道您不会感兴趣的索引块
do OneDindex = 1, size(Array)
CurrInd = GetNDInd(OneDindex, Dims)
if ((any(CurrInd<MinIndex)) .or. (any(CurrInd>MaxIndex))) cycle
! <Some operation>
end do
do OneDindex=1,大小(数组)
CurrInd=GetNDInd(OneDindex,Dims)
if((任意(currendmaxindex))循环
!
结束
请注意,就索引操作而言,此策略与并行循环兼容
还请注意,Fortran变量必须以字母开头:
1index
不是有效的Fortran变量名。因此,这就是我结束的实际过程。
我已经核实过了,希望它能像对我一样对你有用。
(我知道这个问题没有得到很好的评论,但问题有所有的细节,我现在的时间非常短)
同时,感谢里佩罗的帮助!
我决定不使用循环方法,因为我假设当只执行实际数量的循环时,代码将更有效地工作
!-----------------------------------------------------------
subroutine Test(Array,Rank,Dims,InitInd,FinInd)
implicit none
real, dimension(1:), intent(inout) :: Array
integer, intent(in) :: Rank
integer, dimension(1:), intent(in) :: Dims
integer, dimension(1:), intent(in) :: InitInd,FinInd
!-----------------------------------------------------------
integer :: nOuter
integer :: i,j, OneDInd
integer, dimension(Rank) :: Curr
!-----------------------------------------------------------
! Check how many repetition for the outer-loop
Curr=FinInd-InitInd
nOuter=1
do i=2,Rank
nOuter=nOuter*(Curr(i)+1)
enddo
!-----------------------------------------------------------
! Actual looping:
Curr=InitInd
do j=1,nOuter
! Update minor indices (>1):
do i=1,Rank
if (Curr(i).GT.FinInd(i)) then
! Update next index:
Curr(i)=InitInd(i)
Curr(i+1)=Curr(i+1)+1
endif
enddo
! Loop over major index:
do i=InitInd(1),FinInd(1)
!OneDInd=Get1dInd(Curr,Dims)
!<operation>
! Advance major index:
Curr(1)=Curr(1)+1
enddo
enddo
end subroutine Test
-----------------------------------------------------------
子例程测试(数组、秩、Dims、InitInd、FinInd)
隐式无
实数,维度(1:),意图(inout)::数组
整数,意图(in)::秩
整数,维度(1:),意图(in)::Dims
整数,维度(1:),意图(in)::InitInd,FinInd
!-----------------------------------------------------------
整数::努特
整数::i,j,OneDInd
整数,维度(秩)::Curr
!-----------------------------------------------------------
! 检查外循环的重复次数
Curr=FinInd InitInd
努特=1
i=2,排名吗
努特=努特*(电流(i)+1)
结束循环
!-----------------------------------------------------------
! 实际循环:
Curr=InitInd
do j=1,努特
! 更新次要索引(>1):
i=1,排名吗
如果(Curr(i).GT.FinInd(i))那么
! 更新下一个索引:
当前(i)=初始索引(i)
当前(i+1)=当前(i+1)+1
恩迪夫
结束循环
! 循环主要索引:
i=InitInd(1),FinInd(1)
!OneDInd=Get1dInd(当前,Dims)
!
! 先进主要指标:
电流(1)=电流(1)+1
结束循环
结束循环
结束子程序测试
所以这就是我最后的实际步骤。
我已经核实过了,希望它能像对我一样对你有用。
(我知道这个问题没有得到很好的评论,但问题有所有的细节,我现在的时间非常短)
还有,谢谢