Search code examples
arraysalgorithmfortrandoubledouble-precision

What methods are there for finding the element of an array containing a specific real value?


In a Fortran code, I have an array a with values ranging uniformly from 0.0 to 1.2 and I am looking for the index of the value which is closest to 1.0.

There don't seem to be any intrinsics to do this in Fortran, so I made a hacky workaround with MINLOC: (note that temp is the same shape as a)

do i=1,n
  temp(i) = 1.0 - a(i)
end do
loc = 0    !note that loc is an integer array, declared as 'loc(1)'
index_1 = minloc(abs(temp(:))) !this is the index of a closest to 1.0

This seems to do the trick.

I'm interested in other methods to achieve this, so have a few questions:

  • How does MINLOC work?
  • Are there other routines to just get straight there (i.e. without having to make a second array)?
  • How is this handled in other languages?

Thanks.


EDIT: I previously linked to this article, citing it as partial motivation to finding alternatives to MINLOC, but have removed it as some commenters have pointed out it is somewhat irrelevant. Including it seemed to be detracting from my aim which is to find alternatives to this method.


Solution

  • First note that the linked article does not criticize the performance of MINLOC itself, but it criticize the performance for finding a particular value.

    In Fortran 2008 there is the intrinsic FINDLOC for this exact purpose, but it may not be the right thing for the problem. It would, however, be the right thing for the problem in the referenced article. See also Fortran findloc intrinsic

    One reason for the slowness, which is visible immediately, is that a temporary array has to be created for abs(temp(:)) when calling MINLOC(abs(temp(:))). The other reason is that the loop in the article can exit immediately, when the match is found. That is however not important for your application.

    The intrinsic MINLOC itself is probably not slow, it just searches the array in a simple loop.

    These results will also differ among compilers. Did you check the performance difference for your compiler?

    The final advice: just write a simple loop which avoids the temporary array.


    A simple loop for finding the closest floating point element. Simple CS101 stuff.

    min_diff = huge(1.0)
    idx = 0
    
    do i = 1, size(a)
      diff = abs(a(i)-to_find)
      if ( diff < min_diff) then
        idx = i
        min_diff = diff
      end if
    end do