使用指针属性调整矩阵大小

时间:2015-01-02 23:54:24

标签: module fortran fortran90

我有一个Fortran程序,它使用模块中的例程来调整矩阵的大小,如:

module resizemod

contains

 subroutine ResizeMatrix(A,newSize,lindx)
  integer,dimension(:,:),intent(inout),pointer :: A
  integer,intent(in) :: newSize(2)
  integer,dimension(:,:),allocatable :: B
  integer,optional,intent(in) :: lindx(2)
  integer :: i,j

  allocate(B(lbound(A,1):ubound(A,1),lbound(A,2):ubound(A,2)))
  forall (i=lbound(A,1):ubound(A,1),j=lbound(A,2):ubound(A,2))
    B(i,j)=A(i,j)
  end forall
  if (associated(A)) deallocate(A)
  if (present(lindx)) then
    allocate(A(lindx(1):lindx(1)+newSize(1)-1,lindx(2):lindx(2)+newSize(2)-1))
  else
    allocate(A(newSize(1),newSize(2)))
  end if
  do i=lbound(B,1),ubound(B,1)
    do j=lbound(B,2), ubound(B,2)
      A(i,j)=B(i,j)
    end do
  end do
  deallocate(B)
 end subroutine ResizeMatrix
end module resizemod

主程序如下:

program resize

 use :: resizemod

 implicit none
 integer,pointer :: mtest(:,:)

 allocate(mtest(0:1,3))
 mtest(0,:)=[1,2,3]
 mtest(1,:)=[1,4,5]
 call ResizeMatrix(mtest,[3,3],lindx=[0,1])
 mtest(2,:)=0
 print *,mtest(0,:)
 print *,mtest(1,:)
 print *,mtest(2,:)

end program resize

我使用ifort 14.0来编译代码。我面临的问题是有时候我没有得到理想的结果:

       1           0           0
       1           0           5
       0           0  -677609912

实际上,我无法使用最小测试代码重现问题(存在于我的原始程序中)。但我注意到的一点是,当我删除编译器选项-fast时,这个问题就消失了。

然后我的问题就是

  1. 如果我使用的代码完全合法?

  2. 如果建议使用任何其他调整矩阵大小的方法,这种方法优于此处提供的方法吗?

  3. 所述问题与编译器选项的相关性" -fast"。

1 个答案:

答案 0 :(得分:1)

如果我已经阅读了该代码,那么它是合法但不正确的。在您的示例中,您已将2x3数组的大小调整为3x3,但例程ResizeMatrix并未执行任何操作来设置额外元素的值。您看到的奇怪值(例如-677609912)是整数的解释。当读取与未设置的数组元素相对应的存储器位置时,存储器中存在的任何位数(以便可以写出它的值)。

-fast的相关性是,在调试或低优化模式下,编译器通常会将内存位置清零,但在打开更高优化时不要打扰。该程序是合法的,因为它不包含编译器可确定的语法错误。但是,从某种意义上说,读取其值尚未初始化或分配的变量并不是您经常应该做的事情;这样做会使你的程序本质上是非确定性的。

至于你的问题2,它提出了你不熟悉内在函数reshape或(F2003)move_alloc的可能性。后者几乎可以肯定你想要的,前者也可能有所帮助。

顺便说一句:这些天我很少在数组上使用pointerallocatable更有用,而且通常也更容易和更安全。但是你可能有我不知道的要求。