是否有可能消除do循环

时间:2015-04-08 11:51:53

标签: fortran fortran90

众所周知,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

其目的是计算<{p>}中的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))

3 个答案:

答案 0 :(得分:2)

好的,试试这个

lambda = product(max(spread(x, dim=1, ncopies=size(x)) - &
            spread(x, dim=2, ncopies=size(x)), eps), dim=2)

这是一个单行。它也相当浪费记忆,而且比原来更难以理解。

答案 1 :(得分:1)

是的,你可以缩短它,product可以使用2D数组:

  1. 您首先需要设置差异矩阵:
  2.    do i=1,n
         mat(:,i) = x(i) - x
       enddo
    

    或者,作为一个单行:

       forall ( i=1:n ) mat(:,i) = x(i) - x
    
    1. 现在您可以沿第二个维度执行产品:
    2.    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
      

答案 2 :(得分:1)

您是否在阵列创建中使用隐含的do循环尝试了它?像real, dimension(:), intent(out):: lambda =(/product(x(i)-x, mask=(abs(x(i)-x)>epsilon(eps))), i=1, n/)之类的东西......我不确定这里的语法,但是这样的东西可能有效。 如果你的x - 数组可用,你甚至可以在不调用子程序的情况下创建数组并在主程序中执行。

希望它有所帮助。