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

Resizing matrix using pointer attribute

我有一个 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”的相关性。

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

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

关于你的问题2,可能是你对内函数reshape或(F2003)move_alloc不熟悉。后者几乎肯定是你想要的,前者也可能有帮助。

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