编译实值数组时出现类型错误。 Fortran 错误 #7113
Type error when compiling a real valued array. Fortran error #7113
我编写了以下函数来接收六个实值参数和 return 一个一维数组。
FUNCTION G(a, b, c, d, e, f)
IMPLICIT NONE
! SPECIFICATION SECTION
REAL, INTENT(IN) :: a
REAL, INTENT(IN) :: b
REAL, INTENT(IN) :: c
REAL, INTENT(IN) :: d
REAL, INTENT(IN) :: e
REAL, INTENT(IN) :: f
REAL, DIMENSION(1:3) :: G
REAL, DIMENSION(3,3) :: T
REAL, DIMENSION(1:3) :: H
! EXECUTION SECTION
T = RESHAPE( (/1, 0, -sin(b), &
0, cos(a), sin(a)*cos(b), &
0, -sin(a), cos(a)*cos(b)/), &
(/3,3/) )
H = (/d, e, f/)
G = someOtherUnimportantFunction(H,T)
! SUBPROGRAM SECTION
END FUNCTION G
此函数无法编译并导致调用 RESHAPE 函数的行出现错误:
error #7113: Each ac-value expression in an array-constructor must have the same type and type parameters. [COS]
此错误与上述文本共出现 5 个错误,但最后 4 个错误的末尾没有 [COS]
。这个错误似乎表明 1s 和 0s 被解释为与三角函数不同的类型,事实上,如果我将 1s 更改为 1.0s 并将 0s 更改为 0.0s,函数编译正确。然而,这令人困惑,因为我在这个函数之上有许多类似的函数,它们具有类似的 RESHAPE
调用,除了角度的正弦和余弦之外,还有 1 和 0 的整数类型表达式。那些 RESHAPE
函数调用编译得很好。为什么这个 RESHAPE 调用有什么不同?
据我了解,之前的 RESHAPE
命令是将整数隐式类型转换为 REAL 值变量。为什么这种类型转换现在没有发生?
使用混合整数和 REAL 数据类型正确编译 RESHAPE 调用的示例:
U = RESHAPE( (/cos(j), 0, sin(j), 0, 1, 0, -sin(j), 0, cos(j)/),(/3, 3/) )
U 是一个实数 3x3 数组,j 是一个实数角度。
从一些实验来看,上面观察到的 reshape
(或更准确地说,在 reshape
函数内创建的临时数组)的行为似乎是某些特定版本的编译器的供应商扩展(也许是 ifort14?)。请比较下面 B
和 C
的结果,这取决于所使用的编译器和版本。
! [compilers used]
! ifort 14 and 16 (both with an option '-standard-semantics')
! gfortran 4.8 and 7.1
! Oracle studio fortran 12.5
! PGI Fortran Community Edition 2017.4
program main
implicit none
real :: A( 3 ), B( 3 ), C( 3 )
!-------------------------
! RHS = uniform integer array
A = [ 1, 2, 3 ] !! an integer temporary array is created for RHS and assigned to A (with integer -> real conversion)
print *, [ 1, 2, 3 ]
print *, "A = ", A
! gfortran: PASS
! ifort16 : PASS
! ifort14 : PASS
! oracle : PASS
! pgi : PASS
!-------------------------
! RHS = [ real, integer, integer ]
B = [ 1.1, 2, 3 ]
print *, [ 1.1, 2, 3 ]
print *, "B = ", B
! gfortran: Error: Element in REAL(4) array constructor at (1) is INTEGER(4)
! ifort16 : Error: If type specification is omitted, each element
! in an array-constructor must have the same type
! and kind type parameters.
! ifort14 : PASS (*)
! oracle : Error: All ac-value expressions in an array constructor
! must have the same type and type parameters.
! pgi : PASS (*)
!-------------------------
! RHS = [ integer, real, integer ]
C = [ 1, 2.2, 3 ]
print *, [ 1, 2.2, 3 ]
print *, "C = ", C
! gfortran: Error: Element in INTEGER(4) array constructor at (1) is REAL(4)
! ifort16 : Error: (same message as for B)
! ifort14 : Error: Each ac-value expression in an array-constructor
! must have the same type and type parameters.
! oracle : Error: (same message as for B)
! pgi : PASS (**)
! The error message from ifort-14 is the same as that shown in the question.
end
结果:
!-------------------------
gfortran, ifort-16, oracle
1 2 3
A = 1.000000 2.000000 3.000000
! B and C => error
!-------------------------
ifort-14
1 2 3
A = 1.000000 2.000000 3.000000
1.100000 2.000000 3.000000 (*)
B = 1.100000 2.000000 3.000000 (*)
! C => error
!-------------------------
PGI
1 2 3
A = 1.000000 2.000000 3.000000
1.100000 2.000000 3.000000
B = 1.100000 2.000000 3.000000
1 2 3 (**)
C = 1.000000 2.000000 3.000000 (**)
因此,在数组构造函数中不混合不同类型的元素可能更便于移植(即使某些编译器允许...)。
另一方面,如果我们将数组构造函数的(统一)元素类型指定为 [ real :: ... ]
(如评论中所建议),我们可以混合不同类型的元素,例如:
B = [ real :: 1.1, 2, 3 ]
print *, [ real :: 1.1, 2, 3 ]
print *, "B = ", B
C = [ real :: 1, 2.2, 3 ]
print *, [ real :: 1, 2.2, 3 ]
print *, "C = ", C
这给出(对于上面的所有编译器):
1.100000 2.000000 3.000000
B = 1.100000 2.000000 3.000000
1.000000 2.200000 3.000000
C = 1.000000 2.200000 3.000000
(*) 这种模式似乎只是宽松的并且没有什么害处,因为 integer
被转换为 real
.
(**) 但我认为这种模式可能有问题(视情况而定),因为 real
隐式地 "down-converted" 到 integer
(这可能不是程序员...)
我编写了以下函数来接收六个实值参数和 return 一个一维数组。
FUNCTION G(a, b, c, d, e, f)
IMPLICIT NONE
! SPECIFICATION SECTION
REAL, INTENT(IN) :: a
REAL, INTENT(IN) :: b
REAL, INTENT(IN) :: c
REAL, INTENT(IN) :: d
REAL, INTENT(IN) :: e
REAL, INTENT(IN) :: f
REAL, DIMENSION(1:3) :: G
REAL, DIMENSION(3,3) :: T
REAL, DIMENSION(1:3) :: H
! EXECUTION SECTION
T = RESHAPE( (/1, 0, -sin(b), &
0, cos(a), sin(a)*cos(b), &
0, -sin(a), cos(a)*cos(b)/), &
(/3,3/) )
H = (/d, e, f/)
G = someOtherUnimportantFunction(H,T)
! SUBPROGRAM SECTION
END FUNCTION G
此函数无法编译并导致调用 RESHAPE 函数的行出现错误:
error #7113: Each ac-value expression in an array-constructor must have the same type and type parameters. [COS]
此错误与上述文本共出现 5 个错误,但最后 4 个错误的末尾没有 [COS]
。这个错误似乎表明 1s 和 0s 被解释为与三角函数不同的类型,事实上,如果我将 1s 更改为 1.0s 并将 0s 更改为 0.0s,函数编译正确。然而,这令人困惑,因为我在这个函数之上有许多类似的函数,它们具有类似的 RESHAPE
调用,除了角度的正弦和余弦之外,还有 1 和 0 的整数类型表达式。那些 RESHAPE
函数调用编译得很好。为什么这个 RESHAPE 调用有什么不同?
据我了解,之前的 RESHAPE
命令是将整数隐式类型转换为 REAL 值变量。为什么这种类型转换现在没有发生?
使用混合整数和 REAL 数据类型正确编译 RESHAPE 调用的示例:
U = RESHAPE( (/cos(j), 0, sin(j), 0, 1, 0, -sin(j), 0, cos(j)/),(/3, 3/) )
U 是一个实数 3x3 数组,j 是一个实数角度。
从一些实验来看,上面观察到的 reshape
(或更准确地说,在 reshape
函数内创建的临时数组)的行为似乎是某些特定版本的编译器的供应商扩展(也许是 ifort14?)。请比较下面 B
和 C
的结果,这取决于所使用的编译器和版本。
! [compilers used]
! ifort 14 and 16 (both with an option '-standard-semantics')
! gfortran 4.8 and 7.1
! Oracle studio fortran 12.5
! PGI Fortran Community Edition 2017.4
program main
implicit none
real :: A( 3 ), B( 3 ), C( 3 )
!-------------------------
! RHS = uniform integer array
A = [ 1, 2, 3 ] !! an integer temporary array is created for RHS and assigned to A (with integer -> real conversion)
print *, [ 1, 2, 3 ]
print *, "A = ", A
! gfortran: PASS
! ifort16 : PASS
! ifort14 : PASS
! oracle : PASS
! pgi : PASS
!-------------------------
! RHS = [ real, integer, integer ]
B = [ 1.1, 2, 3 ]
print *, [ 1.1, 2, 3 ]
print *, "B = ", B
! gfortran: Error: Element in REAL(4) array constructor at (1) is INTEGER(4)
! ifort16 : Error: If type specification is omitted, each element
! in an array-constructor must have the same type
! and kind type parameters.
! ifort14 : PASS (*)
! oracle : Error: All ac-value expressions in an array constructor
! must have the same type and type parameters.
! pgi : PASS (*)
!-------------------------
! RHS = [ integer, real, integer ]
C = [ 1, 2.2, 3 ]
print *, [ 1, 2.2, 3 ]
print *, "C = ", C
! gfortran: Error: Element in INTEGER(4) array constructor at (1) is REAL(4)
! ifort16 : Error: (same message as for B)
! ifort14 : Error: Each ac-value expression in an array-constructor
! must have the same type and type parameters.
! oracle : Error: (same message as for B)
! pgi : PASS (**)
! The error message from ifort-14 is the same as that shown in the question.
end
结果:
!-------------------------
gfortran, ifort-16, oracle
1 2 3
A = 1.000000 2.000000 3.000000
! B and C => error
!-------------------------
ifort-14
1 2 3
A = 1.000000 2.000000 3.000000
1.100000 2.000000 3.000000 (*)
B = 1.100000 2.000000 3.000000 (*)
! C => error
!-------------------------
PGI
1 2 3
A = 1.000000 2.000000 3.000000
1.100000 2.000000 3.000000
B = 1.100000 2.000000 3.000000
1 2 3 (**)
C = 1.000000 2.000000 3.000000 (**)
因此,在数组构造函数中不混合不同类型的元素可能更便于移植(即使某些编译器允许...)。
另一方面,如果我们将数组构造函数的(统一)元素类型指定为 [ real :: ... ]
(如评论中所建议),我们可以混合不同类型的元素,例如:
B = [ real :: 1.1, 2, 3 ]
print *, [ real :: 1.1, 2, 3 ]
print *, "B = ", B
C = [ real :: 1, 2.2, 3 ]
print *, [ real :: 1, 2.2, 3 ]
print *, "C = ", C
这给出(对于上面的所有编译器):
1.100000 2.000000 3.000000
B = 1.100000 2.000000 3.000000
1.000000 2.200000 3.000000
C = 1.000000 2.200000 3.000000
(*) 这种模式似乎只是宽松的并且没有什么害处,因为 integer
被转换为 real
.
(**) 但我认为这种模式可能有问题(视情况而定),因为 real
隐式地 "down-converted" 到 integer
(这可能不是程序员...)