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

时间:2013-12-07 08:01:08

标签: 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 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

2 个答案:

答案 0 :(得分:3)

为什么不能这样:

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

答案 1 :(得分:1)

有两种可能的方法:递归和非递归。取决于你如何跟随递归。

  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