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.