Можно ли инициализировать массив параметров Fortran с выражением al oop? - PullRequest
1 голос
/ 14 июля 2020

У меня есть постоянный массив, который я хотел бы использовать, но я бы предпочел не использовать вызов инициализации для его настройки, скорее, было бы предпочтительнее, чтобы он был параметром. Однако мне не удалось определить правильный синтаксис, предполагая, что это возможно, или подтвердить, что это невозможно.

Пример кода ниже. Возможно ли это?

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

Ответы [ 2 ]

4 голосов
/ 14 июля 2020

Что-то вроде этого? Он использует подразумеваемый do l oop и конструктор массива

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  
2 голосов
/ 14 июля 2020

Ian Bu sh. Ответ дает явный пример того, как установить значение константы массива. Я расскажу об этом немного подробнее.

Значение именованной константы в

<type>, parameter[, <attr>] :: named_constant = initexpr

задается значением initexpr, преобразованным, если необходимо, в тип named_constant.

initexpr должно быть постоянным выражением и для использования в качестве значения массива должен быть массив той же формы или скалярное значение (или того же ранга если константа является подразумеваемым массивом форм).

Что мы можем использовать, чтобы сделать initexpr выражение константы массива? Есть несколько способов, но, естественно, в этом случае мы хотим использовать конструктор массива. Правила Fortran 2018 10.1.12 говорят нам, что мы должны помнить, чтобы конструктор массива был постоянным выражением.

Из ответа Яна Бу sh, в [ ( startval+(i-1)*step,i=1,n ) ] у нас есть такое вещь:

  • 1 и n (элемент управления l oop) - константы
  • startval и step - константы, а i - константа, при вычислении значения, так что все выражение является константным выражением

Если какие-либо из этих вещей не являются константами, то конструктор массива не является постоянным выражением и будет непригодным для использования используемый. В противном случае у вас довольно много свободы. Указанные правила дают другие идеи, выходящие за рамки этого конструктора массива.

Наконец, вы также можете сделать массив с именем постоянной подразумеваемой формы:

real, parameter, dimension(*) :: vals_p = [ ( startval+(i-1)*step,i=1,n ) ]

вместо того, чтобы повторять размер массива.

...