Fortran DO循环通用指数集?

时间:2018-06-19 05:08:11

标签: fortran do-loops

我有一个N维数据集(比如实数),它存储为一维数组,附加一个维度数组,用于指定原始维度。

此外,还给出了从N-D指数中推导出1-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数组并使用内部循环,但我无法正确编写该过程。

另一个对我不起作用的选项(可能因为我使用不正确?)是FORALL,因为这需要单独指定每个索引。

2 个答案:

答案 0 :(得分:2)

如果您在编译时知道数组的维度,则可以执行一系列嵌套的DO循环,每个循环都在MinIndexMaxIndex的成对组之间运行。由于您不了解尺寸,因此无法做到。

我能想到的最简单的策略是在所有1D索引上循环使用单个DO循环。对于它们中的每一个,计算N维索引,并检查它是否在MinIndexMaxIndex提供的范围内:如果是,继续做你需要的;如果不是,则丢弃该1D索引并转到下一个索引。如果指数是连续的,你可以做一些更聪明的事情,跳过你不会感兴趣的指数块。

do OneDindex = 1, size(Array)
   CurrInd = GetNDInd(OneDindex, Dims)
   if ((any(CurrInd<MinIndex)) .or. (any(CurrInd>MaxIndex))) cycle
   ! <Some operation>
end do

请注意,就索引操作而言,此策略与并行循环兼容。

另请注意,Fortran变量必须以字母开头:1Dindex不是有效的Fortran变量名。

答案 1 :(得分:2)

这是我最终完成的实际过程。 我已经验证了它,并希望它对您像我一样有用。 (我知道这没有得到很好的评论,但是问题有所有细节,目前我的时间非常短)

此外,感谢rippero的帮助! 我决定不使用CYCLE方法,因为我假设只有执行实际的循环次数时,代码才能更有效地工作。

type Panel struct {
  Width  int
  Height int
  Message string

  State [][]bool
}

func (state Panel.State) String() string {
  line := state.parent.Message + "\n"
  for x := 0; x < state.parent.Width; x++ {
    for y := 0; y < state.parent.Height; y++ {
      cell = state[x][y]
      if cell {
        line += "⚫️"
      } else {
        line += "⚪️"
      }
    }
    line += "\n"
  }

  return line
}