我有一个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
时,这个问题就消失了。
然后我的问题就是
如果我使用的代码完全合法?
如果建议使用任何其他调整矩阵大小的方法,这种方法优于此处提供的方法吗?
所述问题与编译器选项的相关性" -fast"。
答案 0 :(得分:1)
如果我已经阅读了该代码,那么它是合法但不正确的。在您的示例中,您已将2x3
数组的大小调整为3x3
,但例程ResizeMatrix
并未执行任何操作来设置额外元素的值。您看到的奇怪值(例如-677609912
)是整数的解释。当读取与未设置的数组元素相对应的存储器位置时,存储器中存在的任何位数(以便可以写出它的值)。
-fast
的相关性是,在调试或低优化模式下,编译器通常会将内存位置清零,但在打开更高优化时不要打扰。该程序是合法的,因为它不包含编译器可确定的语法错误。但是,从某种意义上说,读取其值尚未初始化或分配的变量并不是您经常应该做的事情;这样做会使你的程序本质上是非确定性的。
至于你的问题2,它提出了你不熟悉内在函数reshape
或(F2003)move_alloc
的可能性。后者几乎可以肯定你想要的,前者也可能有所帮助。
顺便说一句:这些天我很少在数组上使用pointer
,allocatable
更有用,而且通常也更容易和更安全。但是你可能有我不知道的要求。