考虑以下程序:
Subroutine foo(p,v)
implicit none
integer, intent(in) :: p
double precision, dimension(p), intent(in) :: v
!local variables
integer,parameter :: n=floor(par(p))
double precision :: z(2*n)
[...]
End Subroutine
我收到以下错误:
Error: Array ‘v’ at (1) is a variable, which does not reduce to a constant expression
这是非常明确但我想知道是否有办法管理这种情况:将子程序的intent(in)
参数分配给参数变量?
您可以使用零长度变量来保存可以通过规范查询从中提取的中间结果。举个例子的时间:
module mod_par
implicit none
contains
pure function par(x)
double precision par
integer, intent(in) :: x
par = 1+sqrt(real(1,kind(par))+x)
end function par
end module mod_par
module mod_foo
! use mod_par
implicit none
double precision par
contains
subroutine foo(p,v)
implicit none
integer p
double precision v
character(0) sv_i(floor(par(p)))
character(floor(par(p))) sv_j(0)
logical sv_k(floor(par(p)),0)
type t
! Intentionally empty
end type t
type(t) sv_L(floor(par(p)))
type u(len)
integer, len :: len
! intentionally empty
end type u
type(u(floor(par(p)))) sv_m
double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),sv_m%len,0)
! double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),0)
write(*,*) shape(z)
end subroutine foo
end module mod_foo
program bar
use mod_par
use mod_foo
implicit none
call foo(10,1.0d0)
end program bar
这在ifort和gfortran都失败了,因为规范函数par
必须是PURE
,并且它的接口必须是显式的。这里par
,虽然PURE
有一个隐含的接口,所以它被拒绝了。事实上,两个编译器似乎都感到困惑:
specvar.f90:21:25:
character(floor(par(p))) sv_j(0)
1
Error: Function 'par' at (1) has no IMPLICIT type
对于gfortran,ifort说
specvar.f90(31): error #6404: This name does not have a type, and must have an e
xplicit type. [PAR]
type(u(floor(par(p)))) sv_m
----------------------^
所以我们修复了这个编程错误......
module mod_par
implicit none
contains
pure function par(x)
double precision par
integer, intent(in) :: x
par = 1+sqrt(real(1,kind(par))+x)
end function par
end module mod_par
module mod_foo
use mod_par
implicit none
! double precision par
contains
subroutine foo(p,v)
implicit none
integer p
double precision v
character(0) sv_i(floor(par(p)))
character(floor(par(p))) sv_j(0)
logical sv_k(floor(par(p)),0)
type t
! Intentionally empty
end type t
type(t) sv_L(floor(par(p)))
type u(len)
integer, len :: len
! intentionally empty
end type u
type(u(floor(par(p)))) sv_m
double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),sv_m%len,0)
! double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),0)
write(*,*) shape(z)
end subroutine foo
end module mod_foo
program bar
use mod_par
use mod_foo
implicit none
call foo(10,1.0d0)
end program bar
但现在gfortran说
specvar.f90:32:73:
double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),sv_m%l
en,0)
1
Error: Variable 'sv_m' cannot appear in the expression at (1)
并且ifort:
specvar.f90(31): error #6279: A specification expression object must be a dummy
argument, a COMMON block object, or an object accessible through host or use ass
ociation. [SV_M]
type(u(floor(par(p)))) sv_m
--------------------------------^
所以我没有足够的最新版本的任何一个编译器来支持类型参数查询。游民。所以我们摆脱了最后一点......
module mod_par
implicit none
contains
pure function par(x)
double precision par
integer, intent(in) :: x
par = 1+sqrt(real(1,kind(par))+x)
end function par
end module mod_par
module mod_foo
use mod_par
implicit none
! double precision par
contains
subroutine foo(p,v)
implicit none
integer p
double precision v
character(0) sv_i(floor(par(p)))
character(floor(par(p))) sv_j(0)
logical sv_k(floor(par(p)),0)
type t
! Intentionally empty
end type t
type(t) sv_L(floor(par(p)))
type u(len)
integer, len :: len
! intentionally empty
end type u
type(u(floor(par(p)))) sv_m
! double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),sv_m%len,0)
double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),0)
write(*,*) shape(z)
end subroutine foo
end module mod_foo
program bar
use mod_par
use mod_foo
implicit none
call foo(10,1.0d0)
end program bar
现在两个编译器都生成了良好的代码。因此,您可以看到有许多方法可以在零长度自动变量的规范中保存临时整数变量,这些变量可以在其他规范表达式中使用。请注意,如果您对这种语法过于花哨,那么您将使编译器崩溃很多。
不,那是不可能的。参数是编译时常量。它的值不能来自任何参数或变量。
目前还不清楚为什么要这样做(参见https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。您不需要参数来声明数组
double precision :: z(2*floor(par(p)))
因为在自动数组中,边界可以是过程参数。