I have an array assignment that I formulated using forall
. The indices to one array have to be computed from the loop variables, so I tried to use temporary variables in a way analogous to ii
this simple example:
program test
integer :: i, ii, a(10), b(20)
a=(/(i, i=1,10)/)
forall (i=1:20)
ii = (i+1)/2
b(i) = a(ii)
end forall
print '(20I3)', b
end program test
But gfortran
warns me that “The FORALL with index 'i' is not used on the left side of the assignment at (1) and so might cause multiple assignment to this object”, and indeed the output is not what I wanted:
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
(ifort
even throws an error.) I realize I could just repeat the definition of ii
every time it appears, but that can get tedious in real-life cases.
Q1: Is there a way to do this sort of thing correctly using forall
?
Now, as you can read in some other questions, forall
no longer seems to be recommended, and a straight do
may even be faster.
However, my use of forall
in this instance was as much about readability as about speed. In my real program, I have something like forall (i=1:10, j=1:10, i<=j)
, and I like the way the forall
header lets me specify this without nested loops.
I also learned about do concurrent
in those questions, and that seems to solve the problem, i.e. replacing forall
above with do concurrent
, the output becomes:
1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10
and I still get to use a forall
header.
Q2: Is this use of a local variable, which does not work in forall
, guaranteed by the standard to work in do concurrent
? (Rather than it being a fluke that it worked in gfortran
.)
Unfortunately, for now I cannot use do concurrent
anyway, because slightly older ifort
and gfortran
versions do not support it.