6
votes

I'm searching for intrinsic fortran functions to help me find the array index with zeros, or other value. I only found minloc function, but I think this is not suitable. Is there an matlab find function equivalent in Fortran?

Thanks

3

3 Answers

10
votes

Given an integer array such as:

testarr = [0,1,0,2,0,3,0,4]

then the expression

pack([(ix,ix=1,size(testarr))],testarr==0)

will return the indices of the elements in testarr equal to 0.

I'll leave you to generalise or enhance this to deal with real numbers or to wrap it into a function to suit your purposes.

The Fortran 2008 standard adds a new intrinsic function findloc which offers to be the replacement for Matlab's find that the question seeks; the compiler I use most (Intel Fortran 13.1.1) doesn't seem to implement this yet.

2
votes

Yes, see High Performance Mark's answer on how to do this with with the PACK instrinsic function.

If I needed to perform operations on all array elements that satisfy some condition, I would implement it using a combination of DO and IF constructs, for example:

INTEGER :: i
REAL,DIMENSION(10) :: a
REAL :: eps = someSmallNumber
...
DO i = 1,SIZE(a)
  IF( 0 > a(i)-eps .AND. 0 < a(i)+eps )THEN
    ...
  ENDIF
ENDDO

The range (a(i)-eps,a(i)+eps) is used above to prevent against comparison fail due to floating point arithmetic. If working with integers, an exact == comparison will do.

If only assignment operations to array elements are needed, you can achieve this using WHERE or FORALL constructs.

0
votes

High Performance Mark's solution based on the pack intrinsic is short and elegant. However, if your array is relatively small, searching for a specific value with pack tends to be slower than a brute force search based on a do loop:

do i = 1, size(testarr)

  if (testarr(i) == 0) then

    idx = i
    exit

  end if

end do

See Craig Finch's answer for details. I have also verified that brute force do loop is faster for small arrays (< 10 elements), compared to the pack based search.