Loops 如何处理子程序中的不确定循环?

Loops 如何处理子程序中的不确定循环?,loops,math,fortran,Loops,Math,Fortran,如您所见,如何在下面的子例程中处理nn(作为输入参数)循环?还是有更好的方法来解决以下问题?谢谢 subroutine sub(nn,kk,cc,d,res) implicit none integer res0,res integer nn,kk(nn),kk2(nn),d(nn),cc(nn) res=0 do kk(1)=0,d(1) do kk(2)=0,d(2) do kk(3)=0,d(3) ... do kK(nn)=0,d(nn) res0=0 kk2=kk ! They

如您所见,如何在下面的子例程中处理nn(作为输入参数)循环?还是有更好的方法来解决以下问题?谢谢

subroutine sub(nn,kk,cc,d,res)
implicit none
integer res0,res
integer nn,kk(nn),kk2(nn),d(nn),cc(nn) 

res=0

do kk(1)=0,d(1)
do kk(2)=0,d(2)
do kk(3)=0,d(3)
...
do kK(nn)=0,d(nn)

res0=0
kk2=kk ! They are arrays.  
call othersub(kk2,nn,res0)!So array kk should be obtained for this othersub().
res=res+res0

end do
...
end do
end subroutine

有两种可能的方法:递归和非递归。这取决于您对递归的理解程度

  module NestedMod
  contains
     ! Dummy routine to do something
     subroutine Something(loop, loopMax, res)
        integer, dimension(:), intent(in):: loop
        integer, intent(in):: loopMax
        real, intent(inout):: res

        res = res + sum(loop)
     end subroutine Something

     recursive subroutine descend(current, maxDepth, loop, maxLoop, DoSomething, res)
        integer, intent(in):: current
        integer, intent(in):: maxDepth
        integer, dimension(:), intent(inout):: loop
        integer, dimension(:), intent(in):: maxLoop
        real, intent(out):: res
        interface
           subroutine DoSomething(a, asize, res)
               integer, dimension(:), intent(in):: a
               integer, intent(in):: asize
               real, intent(inout):: res
           end subroutine DoSomething
        end interface

        ! More efficient timewise to do it separately
        if (current .eq. maxDepth) then
           do ii = 0, maxLoop(current)
              loop(current) = ii
              call DoSomething(loop, maxDepth, res)      
           end do
        else
           do ii = 0, maxLoop(current)
              loop(current) = ii
              call descend(current + 1, maxDepth, loop, maxLoop, DoSomething, res)
           end do
        end if
     end subroutine descend

     subroutine ascend(maxDepth, maxLoop, DoSomething, res)
        integer, intent(in):: maxDepth
        integer, dimension(:), intent(in):: maxLoop
        real, intent(out):: res
        interface
           subroutine DoSomething(a, asize, res)
               integer, dimension(:), intent(in):: a
               integer, intent(in):: asize
               real, intent(inout):: res
           end subroutine DoSomething
        end interface
        integer, allocatable:: loop(:)
        integer:: depth

        allocate(loop(maxDepth))
        loop = -1
        depth = 1
        do while (depth .gt. 0)
           loop(depth) = loop(depth) + 1
           if (loop(depth) .gt. maxLoop(depth)) then
              ! reset loop counter
              loop(depth) = -1
              ! ascend
              depth = depth - 1
              ! off the top?
              if (depth .eq. 0) exit
           else if (depth .lt. maxDepth) then
              ! descend
              depth = depth + 1
           else
              call DoSomething(loop, maxDepth, res)
           end if         
        end do
        deallocate(loop)
     end subroutine ascend
  end module NestedMod
  program main
     use NestedMod
     integer, parameter:: DEPTH = 5
     integer, dimension(DEPTH):: loop, loopMax
     integer:: size, index
     real:: res
     loopmax = (/2, 3, 5, 2, 3 /)
     res = 0
     call descend(1, DEPTH, loop, loopMax, Something, res)
     print *, 'Recursive res = ', res

     res = 0
     call ascend(DEPTH, loopMax, Something, res)
     print *, 'Non recursive res = ', res
  end program

有两种可能的方法:递归和非递归。这取决于您对递归的理解程度

  module NestedMod
  contains
     ! Dummy routine to do something
     subroutine Something(loop, loopMax, res)
        integer, dimension(:), intent(in):: loop
        integer, intent(in):: loopMax
        real, intent(inout):: res

        res = res + sum(loop)
     end subroutine Something

     recursive subroutine descend(current, maxDepth, loop, maxLoop, DoSomething, res)
        integer, intent(in):: current
        integer, intent(in):: maxDepth
        integer, dimension(:), intent(inout):: loop
        integer, dimension(:), intent(in):: maxLoop
        real, intent(out):: res
        interface
           subroutine DoSomething(a, asize, res)
               integer, dimension(:), intent(in):: a
               integer, intent(in):: asize
               real, intent(inout):: res
           end subroutine DoSomething
        end interface

        ! More efficient timewise to do it separately
        if (current .eq. maxDepth) then
           do ii = 0, maxLoop(current)
              loop(current) = ii
              call DoSomething(loop, maxDepth, res)      
           end do
        else
           do ii = 0, maxLoop(current)
              loop(current) = ii
              call descend(current + 1, maxDepth, loop, maxLoop, DoSomething, res)
           end do
        end if
     end subroutine descend

     subroutine ascend(maxDepth, maxLoop, DoSomething, res)
        integer, intent(in):: maxDepth
        integer, dimension(:), intent(in):: maxLoop
        real, intent(out):: res
        interface
           subroutine DoSomething(a, asize, res)
               integer, dimension(:), intent(in):: a
               integer, intent(in):: asize
               real, intent(inout):: res
           end subroutine DoSomething
        end interface
        integer, allocatable:: loop(:)
        integer:: depth

        allocate(loop(maxDepth))
        loop = -1
        depth = 1
        do while (depth .gt. 0)
           loop(depth) = loop(depth) + 1
           if (loop(depth) .gt. maxLoop(depth)) then
              ! reset loop counter
              loop(depth) = -1
              ! ascend
              depth = depth - 1
              ! off the top?
              if (depth .eq. 0) exit
           else if (depth .lt. maxDepth) then
              ! descend
              depth = depth + 1
           else
              call DoSomething(loop, maxDepth, res)
           end if         
        end do
        deallocate(loop)
     end subroutine ascend
  end module NestedMod
  program main
     use NestedMod
     integer, parameter:: DEPTH = 5
     integer, dimension(DEPTH):: loop, loopMax
     integer:: size, index
     real:: res
     loopmax = (/2, 3, 5, 2, 3 /)
     res = 0
     call descend(1, DEPTH, loop, loopMax, Something, res)
     print *, 'Recursive res = ', res

     res = 0
     call ascend(DEPTH, loopMax, Something, res)
     print *, 'Non recursive res = ', res
  end program

为什么不这样做呢:

ntot=1
do i=1,nn
  ntot=ntot*(d(i)+1)
enddo

do k=1,ntot

  n=k

  do i=1,nn
    kk(i)=mod(n,d(i)+1)
    n=n/(d(i)+1)
  enddo

  !... use the array kk as you want

enddo

为什么不这样做呢:

ntot=1
do i=1,nn
  ntot=ntot*(d(i)+1)
enddo

do k=1,ntot

  n=k

  do i=1,nn
    kk(i)=mod(n,d(i)+1)
    n=n/(d(i)+1)
  enddo

  !... use the array kk as you want

enddo

也许有人会更成功,但我不知道这个问题的头绪。另外,为什么要将此标记为
[c]
?您需要向我们提供更多信息。在您的示例中,循环嵌套得很深-这是绝对必要的吗?我同意@Rob。更可能的是,您可以重构它,使其不需要未知数量的循环。但是如果没有更多信息,我们将无法帮助您。谢谢您的考虑。我在问题中补充了一些信息。事实上,我也不想使用循环。如您所见,我想计算othersub(),它与数组kk相关。有没有更好的方法来生成这个数组?@AlexanderVogt,没有,我只想使用循环变量的不同值作为othersub()的输入值。再看一遍这个问题,我对它做了一点修改。也许有人会更成功,但我无法理解这个问题。另外,为什么要将此标记为
[c]
?您需要向我们提供更多信息。在您的示例中,循环嵌套得很深-这是绝对必要的吗?我同意@Rob。更可能的是,您可以重构它,使其不需要未知数量的循环。但是如果没有更多信息,我们将无法帮助您。谢谢您的考虑。我在问题中补充了一些信息。事实上,我也不想使用循环。如您所见,我想计算othersub(),它与数组kk相关。有没有更好的方法来生成这个数组?@AlexanderVogt,没有,我只想使用循环变量的不同值作为othersub()的输入值。再看看这个问题,我把它改了一点。