matmul 内在函数的 Fortran 数组排名
Posted
技术标签:
【中文标题】matmul 内在函数的 Fortran 数组排名【英文标题】:Fortran array rank for matmul intrinsic 【发布时间】:2017-06-02 14:56:33 【问题描述】:以下链接https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gfortran/MATMUL.html 明确指出,gfortran 期望输入到matmul
的矩阵排名为 1 或 2。但是以下 sn-p 无法编译:
Program scratch
real(kind=8) :: A(10)=(/0,1,2,3,4,5,6,7,8,9/)
real(kind=8) :: B(10)=(/0,1,2,3,4,5,6,7,8,9/)
real(kind=8) :: C(10,10)
print *,rank(A),rank(B)
C=matmul(A,B)
End Program scratch
gfortran 给出错误:
$gfortran scratch.f90
scratch.f90:6:13:
C=matmul(A,B)
1
Error: ‘matrix_b’ argument of ‘matmul’ intrinsic at (1) must be of rank 2
我的 gfortran 是 5.4.0(与上面的链接兼容)。我做的事情真的很愚蠢吗?
【问题讨论】:
是的,你这样做了,你正在使用kind=8
。
@VladimirF 谢谢你,不幸的是我将声明更改为real(kind=4)
并且 gfortran 报告了同样的错误。
这不是重点,请参阅 ***.com/questions/838310/fortran-90-kind-parameter 和 ***.com/documentation/fortran/939/data-types/4390/… 以及我的回答。与报错无关。
非常密切相关,但不是精确重复的***.com/questions/22305554/…
【参考方案1】:
您可以使用RESHAPE
将它们转换成MATMUL
喜欢的形式:
Program scratch
real(kind=8) :: A(10)=(/0,1,2,3,4,5,6,7,8,9/)
real(kind=8) :: B(10)=(/0,1,2,3,4,5,6,7,8,9/)
real(kind=8) :: C(10,10)
print *,rank(A),rank(B)
C = matmul( RESHAPE(A,(/10,1/)), RESHAPE(B,(/1,10/)) )
WRITE(*,"(10F7.2)") C
End Program scratch
【讨论】:
谢谢,这很有帮助,我真的很想知道 gfortran 文档和编译器之间的脱节。 @ClintonWinant 重塑是一种将 (10) 数组视为 (1,10) 或 (10,1) 数组的方法。解释保持不变。 @ClintonWinant 你是对的——gfortran 文档不正确。这是 Fortran 标准中的相关行:“MATRIX A 和 MATRIX B 不应都具有等级一。” j3-fortran.org/doc/year/10/10-007.pdf @Jack 谢谢,只是为了关闭循环,gfortran 只接受具有 2 级的数组,否则编译器返回:Error: Incompatible ranks 2 and 1 in assignment at (1)
,即使标准另有说明。我相信我们已经用尽了这个主题......
其实,没有。对于A(10)
和B(10)
,gfortran 将同时采用C = matmul( reshape(A,(/1,10/)), B )
和C = matmul( A, reshape(B,(/10,1/)) )
。但是,在这两种情况下,C 都必须是秩为 1 的单元素数组:C(1)
【参考方案2】:
您必须对两个向量的张量积执行此操作
Program scratch
integer, parameter :: dp = kind(1.d0)
real(dp) :: A(10,1)=reshape((/0,1,2,3,4,5,6,7,8,9/), (/ 10, 1 /))
real(dp) :: B(1,10)=reshape((/0,1,2,3,4,5,6,7,8,9/), (/ 1, 10 /))
real(dp) :: C(10,10)
print *,rank(A),rank(B)
C=matmul(A,B)
print *, C
End Program scratch
如果你这样做
A(1,10)
B(10,1)
您将得到一个标量积。只有两个一维数组,不清楚您想要两种产品中的哪一种(尽管对于点产品,有一个特殊的功能可用)。
当您将矩阵乘以向量时,A 或 B 可以是一维数组。
【讨论】:
所以关键是,尽管手册上说 1 阶矩阵输入是可接受的,但编译器更聪明,知道这是模棱两可的,并坚持 2 阶。因为 dot_product 内在存在,我以为 matmul 会默认为二元乘积,错了...谢谢 排名 1 是允许的,但不是两个参数。 这一行real(dp) :: A(10,1)=(/0,1,2,3,4,5,6,7,8,9/)
给了我错误 Error: Incompatible rank 2 and 1 in assignment at (1) in gfortran 和 PGF90-S-0155-初始值设定项的形状与 pgfortran 中 (scratch.f90: 4) 的形状不匹配。我在这里做错了吗?
不,我认为我有一个错误,但我的编译器出于某种原因允许这样做。我确实测试过。
那是什么编译器?以上是关于matmul 内在函数的 Fortran 数组排名的主要内容,如果未能解决你的问题,请参考以下文章