2

I have a few parameter arrays with different names in a module:

real*8, parameter :: para1(*) = [43.234, 34.0498, ...
real*8, parameter :: para2...

In a routine in this module

subroutine sub(n,...
...
end

I want to use para1 when n=1, para2 when n=2, etc. There are some solutions to that, one is to make an array paras=[para1,para2...] and index properly which works fine. But I want to try using a pointer

real*8, pointer :: ptr(:) 

and assign it to different parameter arrays depending on n, but the problem is that "PARAMETER attribute conflicts with TARGET attribute at (1)". If I remove the parameter attribute, the routine is less safe and the SAVE attribute is assumed.

Am I missing something or why can we not combine parameter and target? And is there a good way around it for this purpose?

5
  • Yes, you are missing something. Fortran 2018, Constraint C860: An entity with the TARGET attribute shall be a variable. A entity with the PARAMETER attribute is a named constant. A named constant is not a variable. Commented Jun 5, 2019 at 15:22
  • 1
    Can you use a single 2D array for the parameters? Commented Jun 6, 2019 at 1:53
  • @ja72 They have different lengths so a structured 2D parameter array is trickier to construct. Then you still need to store the lengths. In 1D you stack them and store the positions so it's much easier. Commented Jun 7, 2019 at 20:24
  • It seems you need a jagged array in Fortran. Commented Jun 7, 2019 at 20:32
  • @ja72 No I don't need that :) Also it is not a parameter. See the answer of 'roygvib' for a 2D solution. Commented Jun 8, 2019 at 14:05

2 Answers 2

2

The parameter and target attributes indeed conflict. An object with the target attribute must be a variable (Fortran 2018 8.5.17, C861); a named constant (object with the parameter attribute) is not a variable (F2018, 8.5.13, C850).

To use target arrays you must, then, use variables. It is tricky to have a variable which is "safe" from having its value modified by a programming mistake or such. There are several considerations which prohibit a variable from appearing in a variable definition context. If you can arrange such a state, then the compiler may have a chance of detecting your mistake. Can that happen easily?

Outside a pure procedure and an intent(in) dummy argument, the most tempting prohibition is with a protected module variable:

module pars
  real, save, target, protected :: para1(74) = [...]
  real, save, target, protected :: para2(1) = [6]
end module

subroutine sub (...)
  use pars
  real, pointer :: p
  p => para1
end subroutine sub

Being protected, the values are safe from modification outside the module pars? Alas, even if this were true it isn't helpful: being protected, we can't even point a pointer to module variables.

In summary, your compiler isn't going to find it easy to detect a programming mistake which modifies the variable target array, so if you want to use an array as a target, you'll have to be careful.

Sign up to request clarification or add additional context in comments.

4 Comments

The last paragraph is a bit of a stretch. It is trivial to modify the values of those module variables in a procedure outside the module.
It's worse than that, isn't it? The whole target, protected part is nonsense.
Do you know if there is a specific reason that that targets must be variables?
@Jonatan, I can't speak for the writers of the standard, but a couple of points: if a pointer can be a variable then whatever it points to must for simplicity be a variable; a named constant needn't exist at "run time".
0

Following the suggestion by @ja72 in the comment, this is an attempt to use a single 2D array for the parameters. This works nicely with gfortran-8.2 (on MacOS10.11).

program main
    implicit none
    integer i
    integer, parameter :: para1(*) = [1, 2, 3, 4, 5]
    integer, parameter :: para2(*) = [6, 7]
    integer, parameter :: N1 = size(para1), N2 = size(para2), N = max(N1, N2)
    integer, parameter :: params(N, 2) = &
            reshape( [ para1, (0, i = 1, N - N1), &
                       para2, (0, i = 1, N - N2) ], [N, 2] )

    print *, "para1 = ", params( :, 1 )
    print *, "para2 = ", params( :, 2 )

    print *, "Input i"
    read *, i
    print *, params( :, i )
end

$ gfortran-8 test.f90 && ./a.out

 para1 =            1           2           3           4           5
 para2 =            6           7           0           0           0
 Input i
1
           1           2           3           4           5

However, because the code becomes a bit complicated (because of reshape) and may not work with old compilers, things may be more straightforward to just use non-parameter arrays...

1 Comment

Nice, but the 1D is indeed simpler:)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.