# Re: Locate function for logical array

On Jan 25, 1:17 pm, jfh <john.har...@xxxxxxxxx> wrote:
On Jan 24, 1:17 pm, glen herrmannsfeldt <g...@xxxxxxxxxxxxxxxx> wrote:

Dave Allured <nos...@xxxxxxxxxx> wrote:
I am seeking a function that is like the "index" function for strings,
except for a 1-D logical array.  Is there an intrinsic function or more
elegant coding method to do this, rather than an explicit loop?  It
"seems" to me that there ought to be a nicer way in fortran.
integer i, p
logical x(6)
x = (/.false.,.false.,.true.,.false.,.true.,.false./)
p = 0
do i = 1, 6
if (x(i)) then
p = i
exit
end if
end do

...
Otherwise, you can write a logicalindex function pretty easily.
You do need two loops, though.

You could make strings of 'T' and 'F', and then use index.

The following program shows and tests a way to do it in F95 without
having to write the loops oneself, though they are presumably "under
the hood" of the intrinsics used. BTW, I used the variable reallyback
to work around a bug in one of the compilers I tried, which wouldn't
let an absent dummy argument be used as an actual optional argument,
in spite of the F95 standard 12.4.1.5 and F2003 standard 12.4.1.6. I
reported the bug to the compiler's developers some time ago. They may
have fixed it by now, but our systems people haven't yet installed the

program logicalindex
implicit none
logical,parameter:: &
larray(6) = (/.false.,.true.,.false.,.true.,.true.,.false./),&
farray(2) = larray(1:3:2)
print *,larray,lindex(larray)
print *,farray,lindex(farray)
print *,larray,lindex(larray,.true.)
print *,farray,lindex(farray,.true.)
print *,larray,lindex(larray,.false.)
print *,farray,lindex(farray,.false.)
contains
integer function lindex(larray,back) ! Pos. of first(last) true
element
logical,intent(in) :: larray(:)
logical,intent(in),optional::back
character(size(larray)) :: string
logical:: reallyback = .false.
if(present(back)) reallyback = back
lindex = index(transfer(merge('T','F',larray),string),'T',&
reallyback)
end function lindex
end program logicalindex

-- John Harper

Aargh! I fell into the intialization trap: if lindex is called without
its optional argument after being called with it true, the variable
reallyback will have the wrong value. What is worse, my test program
did not test that case. Also, one compiler warned that in
transfer(merge('T','F',larray),string) I was using the variable string
before it had been set. That didn't stop the program compiling and
running,though. Here is a revised version that avoids all those
troubles, with my apologies for causing them:

program logicalindex
implicit none
logical,parameter :: T = .true., F = .false., &
larray(6) = (/ F,T,F,T,T,F /),&
farray(2) = (/ F,F /)
print *,larray,lindex(larray,T),' should be 5'
print *,farray,lindex(farray,T),' should be 0'
print *,larray,lindex(larray) ,' should be 2'
print *,farray,lindex(farray) ,' should be 0'
print *,larray,lindex(larray,F),' should be 2'
print *,farray,lindex(farray,F),' should be 0'
contains
integer function lindex(larray,back) ! Pos. of first(last) true
element
logical,intent(in) :: larray(:)
logical,intent(in),optional::back
logical :: reallyback
character(size(larray)) :: string
reallyback = F
string = ' '
if(present(back)) reallyback = back
lindex = index(transfer(merge('T','F',larray),string),'T',&
reallyback)
end function lindex
end program logicalindex

-- John Harper
.