sort_int Subroutine

private subroutine sort_int(origlist, newind, unique)

Arguments

Type IntentOptional Attributes Name
integer(kind=ESMF_KIND_I4), intent(in) :: origlist(:)
integer(kind=ESMF_KIND_I4), intent(inout) :: newind(:)
integer(kind=ESMF_KIND_I4), intent(out) :: unique

Source Code

 subroutine sort_int(origlist, newind, unique)
!
! !ARGUMENTS:
 integer(ESMF_KIND_I4), intent(in) :: origlist(:)
 integer(ESMF_KIND_I4), intent(inout) :: newind(:)
 integer(ESMF_KIND_I4), intent(out) :: unique

 INTEGER, PARAMETER :: SELECT = 20
! ..
! .. Local Scalars ..
 INTEGER :: ENDD, I, J, START, STKPNT
 integer :: n , first, k
 integer(ESMF_KIND_I4) :: arrayel1, arrayel2, arrayel3, arrayel_minmax, arrayel_temp
 integer(ESMF_KIND_I4) :: indtemp, minind
 integer(ESMF_KIND_I4), allocatable :: list(:), origind(:), offset(:)

! ..
! .. Local Arrays ..
 INTEGER :: STACK( 2, 32 )
! ..
! .. Executable Statements ..

!
! Test the input paramters.

 n = size (origlist)
 allocate(list(n), origind(n), offset(n))
 list = origlist
 do i=1,n
  origind(i)=i
  newind(i)=i
 enddo
 STKPNT = 1
 STACK( 1, 1 ) = 1
 STACK( 2, 1 ) = N

 10 CONTINUE
 START = STACK( 1, STKPNT )
 ENDD = STACK( 2, STKPNT )
 STKPNT = STKPNT - 1
 IF( ENDD-START.LE.SELECT .AND. ENDD-START > 0 ) THEN
!
! Do Insertion sort on D( START:ENDD )
!
! Sort into increasing order
!
 DO 50 I = START + 1, ENDD
 DO, J = I, START + 1, -1
 IF( list( J ) < list( J-1 ) ) THEN
 arrayel_minmax = list( J )
 list( J ) = list( J-1 )
 list( J-1 ) = arrayel_minmax
 indtemp = origind(j)
 origind(j)=origind(j-1)
 origind(j-1)=indtemp
 ELSE
 GO TO 50
 END IF
 end do
 50 end do
!
 ELSE IF( ENDD-START > SELECT ) THEN
!
! Partition list( START:ENDD ) and stack parts, largest one first
!
! Choose partition entry as median of 3
!
 arrayel1 = list( START )
 arrayel2 = list( ENDD )
 I = ( START+ENDD ) / 2
 arrayel3 = list( I )
 IF( arrayel1 < arrayel2 ) THEN
 IF( arrayel3 < arrayel1 ) THEN
 arrayel_minmax = arrayel1
 ELSE IF( arrayel3 < arrayel2 ) THEN
 arrayel_minmax = arrayel3
 ELSE
 arrayel_minmax = arrayel2
 END IF
 ELSE
 IF( arrayel3 < arrayel2 ) THEN
 arrayel_minmax = arrayel2
 ELSE IF( arrayel3 < arrayel1 ) THEN
 arrayel_minmax = arrayel3
 ELSE
 arrayel_minmax = arrayel1
 END IF
 END IF
!
 I = START - 1
 J = ENDD + 1

 90 CONTINUE
 do
 J = J - 1
 IF( list( J ) <= arrayel_minmax )&
 & exit
 end do

 do
 I = I + 1
 IF( list( I ) >= arrayel_minmax )&
 & exit
 end do

 IF( I < J ) THEN
 arrayel_temp = list( I )
 list( I ) = list( J )
 list( J ) = arrayel_temp
 indtemp = origind(i)
 origind(i)=origind(j)
 origind(j)=indtemp
 GO TO 90
 END IF
 IF( J-START > ENDD-J-1 ) THEN
 STKPNT = STKPNT + 1
 STACK( 1, STKPNT ) = START
 STACK( 2, STKPNT ) = J
 STKPNT = STKPNT + 1
 STACK( 1, STKPNT ) = J + 1
 STACK( 2, STKPNT ) = ENDD
 ELSE
 STKPNT = STKPNT + 1
 STACK( 1, STKPNT ) = J + 1
 STACK( 2, STKPNT ) = ENDD
 STKPNT = STKPNT + 1
 STACK( 1, STKPNT ) = START
 STACK( 2, STKPNT ) = J
 END IF
 END IF
 IF( STKPNT > 0 ) &
 & GO TO 10

 ! find unique elements in list
offset = 0
 unique=1
 first=-1
 do i=2,n
  if (list(i) > list(i-1)) then
    unique=unique+1
    if (first>0) then
      !found duplicate, set the newIds to the smallest of the list
      minind = origind(first)
      do j=first+1,i-1
        if (origind(j)<minind) minind=origind(j)
      enddo
      do j=first,i-1
        if (origind(j) > minind) then
           do k=origind(j)+1,n
              offset(k)=offset(k)+1
           enddo
        endif
        newind(origind(j))=minind
      enddo
      first=-1
    endif
  else
    if (first<0) first=i-1
  endif
 enddo

 do i=1,n
   newind(i)=newind(i)-offset(newind(i))
 enddo

 RETURN

 end subroutine sort_int