Search code examples
fortran

Fortran sorting/ordering


I am looking for fortran routines that perform ranking. That is given a one dimensional array I would like a routine that returns the indices in that array of the (descending) sorted values. All I could fined are routines that perform sorting. Additionally it would be nice to have a routine that performs partial ordering. That is returning for a given number M the indices of the M biggest values - and others in any order. I found dlasrt but it only does sorting...


Solution

  • Well, for partial-sorting you just can just choose a sorting algorithm like selection sort and terminate after the first required number of elements rather than all of them. Make sure that you (partial-)sort a parallel array of indices rather than the array itself.

    There's a partial_sort algorithm built into the standard library of C++, but not Fortran. Maybe you could check out how that is implemented.

    module sorting
       implicit none
    
    contains
    
       subroutine swap( a, b )
          integer, intent(inout) :: a, b
          integer temp
    
          temp = a
          a = b
          b = temp
    
       end subroutine swap
    
       function best_n( A, nfirst ) result( indices )
          integer, intent(in) :: A(:)
          integer, intent(in) :: nfirst
          integer, allocatable :: indices(:)
          integer n
          integer i, j, jmin
          
          n = size( A )
          indices = [ ( i, i = 1, n ) ]
    
          do i = 1, nfirst
             jmin = i
             do j = i + 1, n
                if ( A(indices(j)) > A(indices(jmin)) ) jmin = j
             end do
             if ( jmin /= i ) call swap( indices(i), indices(jmin) )
          end do
       
       end function best_n
       
    end module sorting
    
    !======================================================================
       
    program main
       use sorting
       implicit none
       integer, allocatable :: A(:), indices(:)
       integer n
       character(len=*), parameter :: fmt = "( a, *(i3,1x) )"
    
       A = [ 1, -1, 2, -2, 3, -3 ]
       n = 3
       indices = best_n( A, n )
    
       write( *, fmt ) "Original array: ", A
       write( *, fmt ) "Best indices: ", indices(1:n)
       write( *, fmt ) "Best values: ", A(indices(1:n))
    
    end program main
    

    Original array: 1 -1 2 -2 3 -3
    Best indices: 5 3 1
    Best values: 3 2 1