Fortran重塑 - N维转置 [英] Fortran reshape - N-dimensional transpose
问题描述
我试图在Fortran中编写一些需要重新排序n维数组的代码。我认为重塑内在结合订单
参数应该允许这样做,但是我遇到了困难。
考虑以下最简单的示例
程序测试
隐式无
实数,维(:,:,:,:,:),allocatable :: matA,matB
integer,parameter :: n1 = 3,n2 = 5,n3 = 7,n4 = 11,n5 = 13
integer :: i1,i2,i3,i4,i5
allocate(matA(n1,n2 ,n3,n4,n5))!源数组
allocate(matB(n3,n2,n4,n1,n5))!重构数组
!填充matA
do i5 = 1,n5
do i4 = 1,n4
do i3 = 1,n3
do i2 = 1,n2
do i1 = 1,n1
matA i1,i2,i3,i4,i5)= i1 + i2 * 10 + i3 * 100 + i4 * 10000 + i5 * 1000000
enddo
enddo
enddo
enddo
enddo
print *,Ad1:,matA( :,1,1,1,1),shape(matA)
matB = reshape(matA,shape(matB),order = [3,2,4,1,5])
print * ,Bd4:,matB(1,1,1,:1),shape(matB)!A的前导维是B
结束程序测试的第四维
我预计这会导致
Ad1:1010111.00 1010112.00 1010113.00 3 5 7 11 13
Bd4:1010111.00 1010112.00 1010113.00 7 5 11 3 13
但是我发现:
Ad1:1010111.00 1010112.00 1010113.00 3 5 7 11 13
Bd4:1010111.00 1010442.00 1020123.00 7 5 11 3 13
我试过这个 gfortran
(4.8.3和4.9)和 ifort
(11.0)一个d找到相同的结果,所以很可能我只是误解了重塑如何工作。
任何人都可以告诉我哪里出错,我如何实现目标?
reshape
中指定 order =
时,排列的下标顺序对应于源数组的元素。这可能不完全清楚。 Fortran 2008标准规定:(忽略关于 pad =
的部分)
结果的元素,以排列的下标顺序ORDER(1),...,ORDER(n)取得,它们是SOURCE的正常数组元素顺序。
这意味着从您的 order = [3,2,4,1,5]
的例子中,映射到
matA(1,1,1,1,1),matA(2,1,1,1,1),matA (3,1,1,1,1),matA(1,2,1,1,1),...
matB(1,1,1,1,1),matB(1,1 ,2,1,1),matB(1,1,3,1,1),matB(1,1,4,1,1),...
在 matB
的第三个指数中,偏移量变化最快,对应于第一个 MATA
。下一个在 matB
中变化最快的是尺寸2,然后是4,依此类推。
所以,它是元素<:code> matB(1,1,1:3,1,1)对应于 matA(:,1,1,1,1) code>。
我已经明确了 matB
切片的范围,因为您已经形状为 matB
的问题:您希望 matB
的形状成为由 order =
说明符。
您可以将您的示例写为
隐式无
整数,参数:: n1 = 3,n2 = 5,n3 = 7,n4 = 11,n5 = 13
整数matA(n1 ,n2,n3,n4,n5)
整数matB(n4,n2,n1,n3,n5)! (3 2 4 1 5)
整数i1,i2,i3,i4,i5
forall(i1 = 1:n1,i2 = 1:n2,i3 = 1: n3,i4 = 1:n4,i5 = 1:n5)&
matA(i1,i2,i3,i4,i5)= i1 + i2 * 10 + i3 * 100 + i4 * 10000 + i5 * 1000000
print *,Ad1: matA(:1,1,1,1),shape(matA)
matB = reshape(matA,shape(matB),order = [3,2,4,1,5])
print *,Bd3:,matB(1,1,:1,1),shape(matB)
end
另外,如果它是你想要的 matB
的形状,那么它就是需要反转的顺序置换:
matB = reshape(matA,shape(matB),order = [4,2,1,3,5])
I'm trying to write some code in Fortran which requires the re-ordering of an n-dimensional array. I thought the reshape intrinsic combined with the order
argument should allow this, however I'm running into difficulties.
Consider the following minimal example
program test
implicit none
real, dimension(:,:,:,:,:), allocatable :: matA, matB
integer, parameter :: n1=3, n2=5, n3=7, n4=11, n5=13
integer :: i1, i2, i3, i4, i5
allocate(matA(n1,n2,n3,n4,n5)) !Source array
allocate(matB(n3,n2,n4,n1,n5)) !Reshaped array
!Populate matA
do i5=1, n5
do i4=1, n4
do i3=1, n3
do i2=1, n2
do i1=1, n1
matA(i1,i2,i3,i4,i5) = i1+i2*10+i3*100+i4*10000+i5*1000000
enddo
enddo
enddo
enddo
enddo
print*,"Ad1 : ",matA(:,1,1,1,1),shape(matA)
matB = reshape(matA, shape(matB), order = [3,2,4,1,5])
print*,"Bd4 : ",matB(1,1,1,:,1),shape(matB) !Leading dimension of A is the fourth dimension of B
end program test
I would expect this to result in
Ad1 : 1010111.00 1010112.00 1010113.00 3 5 7 11 13
Bd4 : 1010111.00 1010112.00 1010113.00 7 5 11 3 13
But instead I find:
Ad1 : 1010111.00 1010112.00 1010113.00 3 5 7 11 13
Bd4 : 1010111.00 1010442.00 1020123.00 7 5 11 3 13
I've tried this with gfortran
(4.8.3 and 4.9) and ifort
(11.0) and find the same results, so it's likely that I am simply misunderstanding something about how reshape works.
Can anybody shed any light on where I'm going wrong and how I can achieve my goal?
When order=
is specified in reshape
the elements of the result taken with permuted subscript order correspond to the elements of the source array. That probably isn't entirely clear. The Fortran 2008 standard states this as (ignoring the part about pad=
)
The elements of the result, taken in permuted subscript order ORDER (1), ..., ORDER (n), are those of SOURCE in normal array element order ..
What this means is that from your example with order=[3,2,4,1,5]
there is the mapping to
matA(1,1,1,1,1), matA(2,1,1,1,1), matA(3,1,1,1,1), matA(1,2,1,1,1), ...
of
matB(1,1,1,1,1), matB(1,1,2,1,1), matB(1,1,3,1,1), matB(1,1,4,1,1), ...
with offset changing most rapidly in the third index of matB
corresponding to most rapidly varying in the first of matA
. The next fastest varying in matB
being dimension 2, then 4, and so on.
So, it's the elements matB(1,1,1:3,1,1)
that correspond the matA(:,1,1,1,1)
.
I've been explicit in the extent of that matB
slice because you've a problem with the shape of matB
: you want the shape of matB
to be the inverse of the permutation given by the order=
specifier.
You could write your example as
implicit none
integer, parameter :: n1=3, n2=5, n3=7, n4=11, n5=13
integer matA(n1,n2,n3,n4,n5)
integer matB(n4,n2,n1,n3,n5) ! Inverse of permutation (3 2 4 1 5)
integer i1, i2, i3, i4, i5
forall (i1=1:n1, i2=1:n2, i3=1:n3, i4=1:n4, i5=1:n5) &
matA(i1,i2,i3,i4,i5)=i1+i2*10+i3*100+i4*10000+i5*1000000
print*,"Ad1 : ",matA(:,1,1,1,1),shape(matA)
matB = reshape(matA, shape(matB), order = [3,2,4,1,5])
print*,"Bd3 : ",matB(1,1,:,1,1),shape(matB)
end
Alternatively, if it's the shape of matB
that you want, then it's the order permutation that wants inverting:
matB = reshape(matA, shape(matB), order = [4,2,1,3,5])
这篇关于Fortran重塑 - N维转置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!