编译实值数组时键入错误。 Fortran错误#7113

时间:2017-06-09 17:26:13

标签: fortran intel-fortran

我编写了以下函数来接受六个实值参数并返回一维数组。

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]。这个错误似乎表明1和0被解释为与trig函数不同的类型,实际上,如果我将1更改为1.0并将0更改为0.0,则函数可以正确编译。然而,这是令人困惑的,因为我有许多类似的函数,除了正弦和角度的余弦之外,还有类似的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是REAL 3x3数组,j是REAL值角度。

1 个答案:

答案 0 :(得分:1)

从某些实验来看,上面观察到的reshape(或更确切地说,在reshape函数内创建的临时数组)的行为似乎是某些特定版本编译器的供应商扩展(可能是ifort14) ?)。请比较下面BC的结果,具体取决于所使用的编译器和版本。

! [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是隐含的"向下转换"到integer(这可能不是程序员的意图......)