是否可以消除do循环
Is it possible to eliminate do loop
据我们所知,较新版本的Fortran 支持数组操作,这可以消除许多循环。所以我想知道是否有可能消除以下代码片段中的最后一个剩余循环(使其成为单行代码):
subroutine test(n,x,lambda)
integer, intent(in) :: n
real, dimension(:), intent(in) :: x
real, dimension(:), intent(out) :: lambda
real :: eps
integer :: i
do i=1,n
lambda(i) = product(x(i)-x, mask=(abs(x(i)-x) > epsilon(eps)))
enddo
end subroutine
它的目的是计算 n
lambda(i)
个值,其中
lambda(i) = (x(i)-x(1))*(x(i)-x(2))*...*(x(i)-x(i-1)*(x(i)-x(i+1))*...*(x(i)-x(n))
是的,你可以缩短这个,product
可以使用二维数组:
- 您首先需要建立差异矩阵:
do i=1,n
mat(:,i) = x(i) - x
enddo
或者,作为单行:
forall ( i=1:n ) mat(:,i) = x(i) - x
- 现在可以沿着第二个维度做乘积了:
lambda = product(mat, dim=2, mask=(abs(mat) > epsilon(eps)))
整个节目:
program test
integer, parameter :: n = 3
real, dimension(n) :: x
real, dimension(n) :: lambda
real, dimension(n,n) :: mat
real :: eps = 1.
integer :: i
call random_number( x )
do i=1,n
lambda(i) = product(x(i)-x, mask=(abs(x(i)-x) > epsilon(eps)))
enddo
print *,lambda
forall ( i=1:n ) mat(:,i) = x(i) - x
lambda = product(mat, dim=2, mask=(abs(mat) > epsilon(eps)))
print *,lambda
end program
您是否尝试过在数组创建中使用隐含的 do 循环?像 real, dimension(:), intent(out):: lambda =(/product(x(i)-x, mask=(abs(x(i)-x)>epsilon(eps))), i=1, n/)
这样的东西……我不确定这里的语法,但类似的东西可能有用。
如果您的 x
-array 可用,您甚至可以在不调用子例程的情况下创建数组并在主程序中执行此操作。
希望对您有所帮助。
好的,试试这个
lambda = product(max(spread(x, dim=1, ncopies=size(x)) - &
spread(x, dim=2, ncopies=size(x)), eps), dim=2)
那是一条线。它也相当浪费内存,而且比原来的更难理解。
据我们所知,较新版本的Fortran 支持数组操作,这可以消除许多循环。所以我想知道是否有可能消除以下代码片段中的最后一个剩余循环(使其成为单行代码):
subroutine test(n,x,lambda)
integer, intent(in) :: n
real, dimension(:), intent(in) :: x
real, dimension(:), intent(out) :: lambda
real :: eps
integer :: i
do i=1,n
lambda(i) = product(x(i)-x, mask=(abs(x(i)-x) > epsilon(eps)))
enddo
end subroutine
它的目的是计算 n
lambda(i)
个值,其中
lambda(i) = (x(i)-x(1))*(x(i)-x(2))*...*(x(i)-x(i-1)*(x(i)-x(i+1))*...*(x(i)-x(n))
是的,你可以缩短这个,product
可以使用二维数组:
- 您首先需要建立差异矩阵:
do i=1,n
mat(:,i) = x(i) - x
enddo
或者,作为单行:
forall ( i=1:n ) mat(:,i) = x(i) - x
- 现在可以沿着第二个维度做乘积了:
lambda = product(mat, dim=2, mask=(abs(mat) > epsilon(eps)))
整个节目:
program test
integer, parameter :: n = 3
real, dimension(n) :: x
real, dimension(n) :: lambda
real, dimension(n,n) :: mat
real :: eps = 1.
integer :: i
call random_number( x )
do i=1,n
lambda(i) = product(x(i)-x, mask=(abs(x(i)-x) > epsilon(eps)))
enddo
print *,lambda
forall ( i=1:n ) mat(:,i) = x(i) - x
lambda = product(mat, dim=2, mask=(abs(mat) > epsilon(eps)))
print *,lambda
end program
您是否尝试过在数组创建中使用隐含的 do 循环?像 real, dimension(:), intent(out):: lambda =(/product(x(i)-x, mask=(abs(x(i)-x)>epsilon(eps))), i=1, n/)
这样的东西……我不确定这里的语法,但类似的东西可能有用。
如果您的 x
-array 可用,您甚至可以在不调用子例程的情况下创建数组并在主程序中执行此操作。
希望对您有所帮助。
好的,试试这个
lambda = product(max(spread(x, dim=1, ncopies=size(x)) - &
spread(x, dim=2, ncopies=size(x)), eps), dim=2)
那是一条线。它也相当浪费内存,而且比原来的更难理解。