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