Fortran在通用索引集上进行循环?

Fortran在通用索引集上进行循环?,fortran,do-loops,Fortran,Do Loops,我有一个N维数据集(比如实数),它存储为一个1D数组,另外还有一个指定原始维度的维度数组 此外,还给出了从N-D指数推导一维指数和从N-D指数推导一维指数的函数 我试图弄清楚如何为通用的N维索引(当然,它将被转换为1D索引)创建一个do循环(或等效循环),从一组限制性的较低索引到一组较高的索引。 因此,我需要一个“N维”循环,不会遍历所有的值——只遍历数组的一部分,因此对等效1D数组进行线性索引是不相关的(至少没有修改) 这是我的问题的示意图: subroutine Test(Array,Dim

我有一个N维数据集(比如实数),它存储为一个1D数组,另外还有一个指定原始维度的维度数组

此外,还给出了从N-D指数推导一维指数和从N-D指数推导一维指数的函数

我试图弄清楚如何为通用的N维索引(当然,它将被转换为1D索引)创建一个do循环(或等效循环),从一组限制性的较低索引到一组较高的索引。 因此,我需要一个“N维”循环,不会遍历所有的值——只遍历数组的一部分,因此对等效1D数组进行线性索引是不相关的(至少没有修改)

这是我的问题的示意图:

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
结束循环
结束循环
结束子程序测试

所以这就是我最后的实际步骤。 我已经核实过了,希望它能像对我一样对你有用。 (我知道这个问题没有得到很好的评论,但问题有所有的细节,我现在的时间非常短)

还有,谢谢