module m_find

!$$$ module documentation block
!           .      .    .                                       .
! module:   m_find   similar to IDL's "where" function, but needs to know the
!                    dimension of the outupt e.g., index=find(mask,count)  
!   prgmmr: eliu
!
! abstract:  module similar to IDL's "where" function 
!
! program history log:
!   1997-08-13  Joiner  - initial coding from NASA/GMAO
!   2012-02-15  eliu    - reformat to use in GSI
!
! subroutines included:
!
! variable definitions:
!
! attributes:
!   language: f90
!   machine:
!
!$$$ end documentation block

  use kinds,only : i_kind, r_kind

  interface find
    module procedure find2
    module procedure find1
  end interface

  contains

  function find2(mask,count) result (index)
  implicit none

  !input parameters:
  logical, dimension(:),intent(in) :: mask  ! mask vector
  integer(i_kind),      intent(in) :: count ! size of output vector
  !output parameters:
  integer(i_kind), dimension(count):: index ! vector of indices where mask is true         

  !local variables
  integer(i_kind):: i, j

  j = 1
  index=-1
  if (count > 0) then
     do i=1, size(mask,1)
        if (mask(i)) then
           index(j) = i
           j = j + 1
         endif
     enddo
     j = j - 1
  endif
  if (j /= count .or. count <= 0) then
     print *, 'ERROR!!! in find (dimensions not correct)', j, count
  endif

  end function find2
 
  subroutine findp(mask,counts,index)
  implicit none
  logical, dimension(:), intent(in)      :: mask   ! mask vector
  integer(i_kind),       intent(out)     :: counts ! size of output vector
  integer(i_kind), dimension(:), pointer :: index  ! vector of indices where mask is true                                        

  !local variables
  integer(i_kind) :: i
  integer(i_kind) :: j
  integer(i_kind) :: tempsize
  integer(i_kind) :: error

  j = 1
  counts = count(mask)
  if (counts > 0) then
     allocate(index(counts))
     do i=1, size(mask,1)
        if (mask(i)) then
           index(j) = i
           j = j + 1
        endif
     enddo
  else
     allocate(index(1))
     index=-1
  endif
  j = j - 1
  if (j /= counts ) then
     print *, 'ERROR!!! in find (dimensions not correct)', j, counts
  endif

  end subroutine findp

  function find1(mask ) result (index)
  implicit none

  logical, dimension(:), intent(in)          :: mask
  !integer(i_kind),      intent(in), optional:: iprt

  integer(i_kind):: n, index    
  integer(i_kind), dimension(1):: temp
  integer(i_kind), dimension(:), allocatable:: temp2

  n = count(mask)
  if (n == 1) then
     temp(1:1)=find2(mask,1)
     index=temp(1)
  else
     !if (present(iprt)) then
     ! if (iprt >= 3) then
     !   print *,'find: WARNING, found more than 1 value'
     !   print *,'taking the first'
     ! endif
     !endif
     if (n > 1) then
        allocate(temp2(n))
        temp2 = find2(mask,n)
        index=temp2(1)
        deallocate(temp2)
     else
        index=-1
     endif
  endif
  end function find1

end module m_find
