Reputation: 3785
I have a constant array that I would like to use, but I would prefer not to have to use an initialization call to set it up, rather it would be preferable to have it be a parameter. However, I haven't been able to figure out the correct syntax, assuming that it is possible, or to confirm that it is not possible.
Example code below. Is it possible?
module mymod
implicit none
private
public initmymod, printinit
integer, parameter :: n=11
real, parameter :: startval=10.,stopval=20.,step=(stopval-startval)/(n-1)
! would rather use something like this parameter statement than a protected array, is it possible?
! real, parameter :: vals_p(n) = startval+(i-1)*step,i,1,10
! using this, along with the initmymod setup. Works, but would prefer to use a parameter array
real, dimension(n), protected :: vals
contains
subroutine initmymod()
integer :: i
do i = 1,n
vals(i) = startval+(i-1)*step
end do
end subroutine
subroutine printinit()
print *, vals
end subroutine
end module
program main
use mymod
implicit none
call initmymod
call printinit
end program main
Upvotes: 1
Views: 958
Reputation: 32451
Ian Bush's answer gives an explicit example of how to set the value of the array constant. I'll give a little more detail on that.
The value of a named constant in
<type>, parameter[, <attr>] :: named_constant = initexpr
is given by the value of initexpr
, converted if necessary to the type of named_constant
.
initexpr
must be a constant expression and to be used for an array's value must be an array of the same shape or a scalar value (or of the same rank if the constant is an implied shape array).
What is it that we can use to make initexpr
an array constant expression? There are several ways, but naturally in this case we want to use an array constructor. The rules in Fortran 2018 10.1.12 tell us what we have to keep in mind to have a array constructor a constant expression.
From Ian Bush's answer, in [ ( startval+(i-1)*step,i=1,n ) ]
we have such a thing:
1
and n
(the loop control) are constantsstartval
and step
are constants, and i
is a constant, in the value calculation, so that whole expression is a constant expressionIf any of those things aren't constants, then the array constructor isn't a constant expression and would be unsuitable to be used. Otherwise, you've quite a bit of freedom. The rules referenced give other ideas beyond this array constructor.
Finally, you can also make the array named constant implied shape:
real, parameter, dimension(*) :: vals_p = [ ( startval+(i-1)*step,i=1,n ) ]
rather than repeating the size of the array.
Upvotes: 2
Reputation: 7432
Something like this? It uses an implied do loop and an array constructor
ian@eris:~/work/stack$ cat construct.f90
module mymod
implicit none
private
public :: printinit
integer, parameter :: n=11
real, parameter :: startval=10.,stopval=20.,step=(stopval-startval)/(n-1)
! would rather use something like this parameter statement than a protected array, is it possible?
!!$ real, parameter :: vals_p(n) = startval+(i-1)*step,i,1,10
Integer :: i
real, parameter, Dimension( 1:n ) :: vals_p = [ ( startval+(i-1)*step,i=1,n ) ]
! using this, along with the initmymod setup. Works, but would prefer to use a parameter array
contains
subroutine printinit()
print *, vals_p
end subroutine
end module
program main
use mymod
implicit none
call printinit
end program main
ian@eris:~/work/stack$ gfortran-8 --version
GNU Fortran (Ubuntu 8.3.0-6ubuntu1~18.04.1) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ian@eris:~/work/stack$ gfortran-8 -std=f2003 -Wall -Wextra -fcheck=all construct.f90
ian@eris:~/work/stack$ ./a.out
10.0000000 11.0000000 12.0000000 13.0000000 14.0000000 15.0000000 16.0000000 17.0000000 18.0000000 19.0000000 20.0000000
Upvotes: 4