Currently, there is no efficient way of finding the location of the
first or last TRUE element in a logical array using array operations.
There are three workarounds
1- SUM intrinsic
Example: (note: I have not tested these with a compiler, typos
are possible)
c='a'
n = sum((/(j,j=1,4)/),mask=c==(/'d','a','z','u'/))
This is inefficient as all the comparisons have to be made and
will give an incorrect result if more than one element in the
mask is TRUE
2- MERGE and MAXLOC
Example:
c = 'a'
n = maxloc (merge(1,0,c==(/'d','a','z','u'/)),dim=1)
All the comparisons are required (unless the compiler has a very
clever optimizer), but safe if more than one TRUE condition is present.
The DIM specifier in maxloc is a Fortran 95 feature.
3- DO loop
character :: list(4)=(/'d','a','z','u'/)
character c
c = 'a'
do n = 1,4
if(c == list(n)) exit
end do
This is the only way to guarantee efficiency.
In appendix F of the first draft of Fortran 90 (called at that time
Fortran 8x), two intrinsic functions, FIRSTLOC and LASTLOC, were defined
to find respectively the first and last location of TRUE elements in a
logical array, following the array element order.
For example
n = firstloc (c==(/'d','a','z','u'/),dim=1)
is the equivalent of the three alternatives presented before.
Much simpler than the three and also probably more efficient than the
first two alternatives.
These functions were dropped in Fortran 8x as a compromise to simplify
the language. The CM Fortran compiler, however, implemented them.
Now it is time to reconsider them. Searching the position of an item
in an unordered list is a very frequent programming task and resorting
to DO loops is necessary now to guarantee efficiency.
Adding these two functions to F2K is mostly a matter of cut and paste
as the definitions are already in the first Fortran 8X draft.
I know that the Fortran committee is overloaded by work but if little
time is found, these additions would be valuable.
Regards,
Jean Vezina
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|