Loops 如何处理子程序中的不确定循环?
如您所见,如何在下面的子例程中处理nn(作为输入参数)循环?还是有更好的方法来解决以下问题?谢谢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
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()的输入值。再看看这个问题,我把它改了一点。