FINDLOC alternative

I used FINDLOC (in the standard since 2008) in a code. Ifort works fine with it, gfortran > 9.1 works fine, but older gfortran does not have it implemented. There is a user of my code that runs older gfortran and is stuck with it. Does anyone maybe have open source function that mimics the functionality of FINDLOC? If the performance is suboptimal, it does not matter much.

Thanks!!

Findloc works for arrays of all intrinsic types and ranks, and it has several optional arguments, listed here. How general of a findloc do you need? This could be determined empirically by writing a findloc interface and adding necessary module procedures until the code compiles. Writing a findloc that works for say 1d and 2d integer or character arrays would not be difficult. There was discussion of putting findloc in stdlib for your use case, but I don’t see it here, so I don’t it was implemented.

1 Like

It does not have to be general at all. It should actually work just for 1D arrays of integers or floats. Yes, I’m aware that this is easy, but I’m getting lazy when I have to do something that probably already exists. :slight_smile: I was a bit surprised that I couldn’t google it, so I thought of asking here before doing it myself.

I wrote my own FINDLOC workalike a few years back just so I could
compile code on gfortran and PGI compilers that did not support
FINDLOC at that time. My code supports rank 1 through rank3 arrays of
Integer and real (both 32 and 64 bit) and logicals. I can bundle the code into
a standalone package and put it on github if there is sufficient interest

2 Likes

Maybe try

findloc(array,value) = minloc(abs(array-value))

but test the resulting code and see if it does what you want when value is not found in array.

2 Likes

Thanks! I’ll write my ad-hoc function taking care of the exceptions.

@rwmsu I guess that such a code is always useful.

My code is based on using MAXLOC and MERGE. Here is my code for a 1D interger
array. The multi-dimensional arrays follow the same basic template

  Pure Function findloc1D_I32(a, value, mask, back) Result(index)

    Implicit NONE

    Integer(INT32), Intent(IN)           :: a(:)
    Integer(INT32), Intent(IN)           :: value
    Logical,        Intent(IN), OPTIONAL :: mask(:)
    Logical,        Intent(IN), OPTIONAL :: back

    Integer                              :: index(1)

    Logical :: reverse
    Logical, ALLOCATABLE :: m(:)

    index = 0
    ALLOCATE(m(SIZE(a,DIM=1)))
    m = .TRUE.
    If (PRESENT(mask)) m = mask

    If(COUNT(a==value .AND. m) == 0) RETURN

    reverse = .FALSE.

    If (PRESENT(back)) reverse = back

    If (reverse) Then

      index(1) = MAXLOC(MERGE(1,0, (a(SIZE(a):1:-1) == value)      &
                .AND.       m(SIZE(a):1:-1)),DIM=1)
      If (index(1) > 0) index(1) = UBOUND(a,DIM=1)-index(1) + 1
    Else

      index(1) = MAXLOC(MERGE(1,0, a == value .AND. m), dim=1)

    EndIf

  End Function findloc1D_I32
1 Like

The emulators project of @everythingfunctional and @rouson implements findloc.

Motivation and Usage

Are you hoping for a world with full compiler support for recent Fortran standards? Emulating an unsupported feature facilitates using the feature prior to compiler support. This path offers minimal impact on future code.

Contents

Emulated features:

  • Fortran 2008 intrinsic function: findloc
  • Fortran 2018 collective subroutines: co_sum , co_broadcast

Those who find the collective subroutines useful might also be interested in language extensions such as the Sourcery library’s co_all subroutine, which provides a parallel, collective logical operation analogous to the all intrinsic function.

1 Like

I have added my findloc implementations to my github ModForUtils repository

Go to:

2 Likes

Just in case, the array is large and sorted, a binary search would likely be much faster than the intrinsic findloc which presumably uses a linear search.

1 Like

Oh, thanks! I wasn’t aware of this effort to emulate unsupported features! What a noble intention. :slight_smile:

@rwmsu Excellent work! Many thanks!!

@shahmoradi That’s an excellent point. I will do some experiments to see how does findloc perform in terms of speed in the case of interest. Thank you!