SORTP Subroutine

public subroutine SORTP(X, N, Y, Xpos)

NAME

sortp(3f) - [M_datapac:SORT] sorts and ranks a numeric
vector X

SYNOPSIS

 SUBROUTINE SORTP(X,N,Y,Xpos)

  Real(kind=wp) :: (In)    ::  X(N)
  Integer, Intent (In)     ::  N
  Real(kind=wp) :: (Out)   ::  Y(N)
  Real(kind=wp) :: (Out)   ::  XPOS(N)

DESCRIPTION

SORTP(3f) sorts (in ascending order) the N elements of the precision precision vector X, puts the resulting N sorted values into the precision precision vector Y; and puts the position (in the original vector X) of each of the sorted values into the REAL vector XPOS.

This subroutine gives the data analyst not only the ability to determine what the MIN and MAX (for example) of the data set are, but also where in the original data set the MIN and MAX occur.

This is especially useful for large data sets.

OPTIONS

 X   description of parameter
 Y   description of parameter

EXAMPLES

Sample program:

program demo_sortp
use M_datapac, only : sortp
implicit none
! call sortp(x,y)
end program demo_sortp

Results:

AUTHOR

The original DATAPAC library was written by James Filliben of the Statistical
Engineering Division, National Institute of Standards and Technology.

MAINTAINER

John Urban, 2022.05.31

LICENSE

CC0-1.0

REFERENCES

  • CACM March 1969, page 186 (Binary Sort Algorithm by Richard C. Singleton).
  • CACM January 1970, page 54.
  • CACM October 1970, page 624.
  • JACM January 1961, page 41.

Arguments

Type IntentOptional Attributes Name
real(kind=wp), dimension(:) :: X
integer :: N
real(kind=wp), dimension(:) :: Y
real(kind=wp), dimension(:) :: Xpos

Source Code

SUBROUTINE SORTP(X,N,Y,Xpos)
REAL(kind=wp) :: amed , bmed , hold , tt , X , Xpos , Y
INTEGER :: i , il , ip1 , itt , iu , j , jmi , jmk , k , l ,lmi , m , mid , N , nm1

!     INPUT ARGUMENTS--X      = THE  VECTOR OF
!                                OBSERVATIONS TO BE SORTED.
!                     --N      = THE INTEGER NUMBER OF OBSERVATIONS
!                                IN THE VECTOR X.
!     OUTPUT ARGUMENTS--Y      = THE  VECTOR
!                                INTO WHICH THE SORTED DATA VALUES
!                                FROM X WILL BE PLACED.
!                     --XPOS   = THE  VECTOR
!                                INTO WHICH THE POSITIONS
!                                (IN THE ORIGINAL VECTOR X)
!                                OF THE SORTED VALUES
!                                WILL BE PLACED.
!     OUTPUT--THE  VECTOR XS
!             CONTAINING THE SORTED
!             (IN ASCENDING ORDER) VALUES
!             OF THE  VECTOR X, AND
!             THE  VECTOR XPOS
!             CONTAINING THE POSITIONS
!             (IN THE ORIGINAL VECTOR X)
!             OF THE SORTED VALUES.
!     PRINTING--NONE UNLESS AN INPUT ARGUMENT ERROR CONDITION EXISTS.
!     RESTRICTIONS--THE DIMENSIONS OF THE VECTORS IL AND IU
!                   (DEFINED AND USED INTERNALLY WITHIN
!                   THIS SUBROUTINE) DICTATE THE MAXIMUM
!                   ALLOWABLE VALUE OF N FOR THIS SUBROUTINE.
!                   IF IL AND IU EACH HAVE DIMENSION K,
!                   THEN N MAY NOT EXCEED 2**(K+1) - 1.
!                   FOR THIS SUBROUTINE AS WRITTEN, THE DIMENSIONS
!                   OF IL AND IU HAVE BEEN SET TO 36,
!                   THUS THE MAXIMUM ALLOWABLE VALUE OF N IS
!                   APPROXIMATELY 137 BILLION.
!                   SINCE THIS EXCEEDS THE MAXIMUM ALLOWABLE
!                   VALUE FOR AN INTEGER VARIABLE IN MANY COMPUTERS,
!                   AND SINCE A SORT OF 137 BILLION ELEMENTS
!                   IS PRESENTLY IMPRACTICAL AND UNLIKELY,
!                   THEN THERE IS NO PRACTICAL RESTRICTION
!                   ON THE MAXIMUM VALUE OF N FOR THIS SUBROUTINE.
!                   (IN LIGHT OF THE ABOVE, NO CHECK OF THE
!                   UPPER LIMIT OF N HAS BEEN INCORPORATED
!                   INTO THIS SUBROUTINE.)

!     COMMENT--THE SMALLEST ELEMENT OF THE VECTOR X
!              WILL BE PLACED IN THE FIRST POSITION
!              OF THE VECTOR Y,
!              THE SECOND SMALLEST ELEMENT IN THE VECTOR X
!              WILL BE PLACED IN THE SECOND POSITION
!              OF THE VECTOR Y,
!              ETC.
!     COMMENT--THE POSITION (1 THROUGH N) IN X
!              OF THE SMALLEST ELEMENT IN X
!              WILL BE PLACED IN THE FIRST POSITION
!              OF THE VECTOR XPOS,
!              THE POSITION (1 THROUGH N) IN X
!              OF THE SECOND SMALLEST ELEMENT IN X
!              WILL BE PLACED IN THE SECOND POSITION
!              OF THE VECTOR XPOS,
!              ETC.
!              ALTHOUGH THESE POSITIONS ARE NECESSARILY
!              INTEGRAL VALUES FROM 1 TO N, IT IS TO BE
!              NOTED THAT THEY ARE OUTPUTED AS SINGLE
!              PRECISION INTEGERS IN THE
!              VECTOR XPOS.
!              XPOS IS  SO AS TO BE
!              CONSISTENT WITH THE FACT THAT ALL
!              VECTOR ARGUMENTS IN ALL OTHER
!              DATAPAC SUBROUTINES ARE .
!     COMMENT--THE INPUT VECTOR X REMAINS UNALTERED.
!     COMMENT--IF THE ANALYST DESIRES A SORT 'IN PLACE',
!              THIS IS DONE BY HAVING THE SAME
!              OUTPUT VECTOR AS INPUT VECTOR IN THE CALLING SEQUENCE.
!              THUS, FOR EXAMPLE, THE CALLING SEQUENCE
!              CALL SORTP(X,N,X,XPOS)
!              IS ALLOWABLE AND WILL RESULT IN
!              THE DESIRED 'IN-PLACE' SORT.
!     COMMENT--THE SORTING ALGORTHM USED HEREIN
!              IS THE BINARY SORT.
!              THIS ALGORTHIM IS EXTREMELY FAST AS THE
!              FOLLOWING TIME TRIALS INDICATE.
!              THESE TIME TRIALS WERE CARRIED OUT ON THE
!              UNIVAC 1108 EXEC 8 SYSTEM AT NBS
!              IN AUGUST OF 1974.
!              BY WAY OF COMPARISON, THE TIME TRIAL VALUES
!              FOR THE EASY-TO-PROGRAM BUT EXTREMELY
!              INEFFICIENT BUBBLE SORT ALGORITHM HAVE
!              ALSO BEEN INCLUDED--
!              NUMBER OF RANDOM        BINARY SORT       BUBBLE SORT
!               NUMBERS SORTED
!                N = 10                 .002 SEC          .002 SEC
!                N = 100                .011 SEC          .045 SEC
!                N = 1000               .141 SEC         4.332 SEC
!                N = 3000               .476 SEC        37.683 SEC
!                N = 10000             1.887 SEC      NOT COMPUTED
!     ORIGINAL VERSION--JUNE      1972.
!     UPDATED         --NOVEMBER  1975.
!
!---------------------------------------------------------------------
!
      DIMENSION X(:) , Y(:) , Xpos(:)
      DIMENSION iu(36) , il(36)
!
!     CHECK THE INPUT ARGUMENTS FOR ERRORS
!
      IF ( N<1 ) THEN
         WRITE (G_IO,99001)
99001    FORMAT (' ','***** FATAL ERROR--THE SECOND INPUT ARGUMENT TO THE SORTP  SUBROUTINE IS NON-POSITIVE *****')
         WRITE (G_IO,99002) N
99002    FORMAT (' ','***** THE VALUE OF THE ARGUMENT IS ',I0,' *****')
         RETURN
      ELSE
         IF ( N==1 ) THEN
            WRITE (G_IO,99003)
99003       FORMAT (' ','***** NON-FATAL DIAGNOSTIC--THE SECOND INPUT ARGUMENT TO THE SORTP SUBROUTINE HAS THE VALUE 1 *****')
            Y(1) = X(1)
            Xpos(1) = 1.0_wp
            RETURN
         ELSE
            hold = X(1)
            DO i = 2 , N
               IF ( X(i)/=hold ) GOTO 50
            ENDDO
            WRITE (G_IO,99004) hold
99004       FORMAT (' ',&
             & '***** NON-FATAL DIAGNOSTIC--THE FIRST  INPUT ARGUMENT (A VECTOR) TO THE SORTP  SUBROUTINE HAS ALL ELEMENTS =',&
             & E15.8,&
             & ' *****')
            DO i = 1 , N
               Y(i) = X(i)
               Xpos(i) = i
            ENDDO
            RETURN
         ENDIF
!
!-----START POINT-----------------------------------------------------
!
!     COPY THE VECTOR X INTO THE VECTOR Y
 50      DO i = 1 , N
            Y(i) = X(i)
         ENDDO
!
!     DEFINE THE XPOS (POSITION) VECTOR.  BEFORE SORTING, THIS WILL
!     BE A VECTOR WHOSE I-TH ELEMENT IS EQUAL TO I.
!
         DO i = 1 , N
            Xpos(i) = i
         ENDDO
!
!     CHECK TO SEE IF THE INPUT VECTOR IS ALREADY SORTED
!
         nm1 = N - 1
         DO i = 1 , nm1
            ip1 = i + 1
            IF ( Y(i)>Y(ip1) ) GOTO 100
         ENDDO
         RETURN
      ENDIF
 100  m = 1
      i = 1
      j = N
 200  IF ( i>=j ) GOTO 400
 300  k = i
      mid = (i+j)/2
      amed = Y(mid)
      bmed = Xpos(mid)
      IF ( Y(i)>amed ) THEN
         Y(mid) = Y(i)
         Xpos(mid) = Xpos(i)
         Y(i) = amed
         Xpos(i) = bmed
         amed = Y(mid)
         bmed = Xpos(mid)
      ENDIF
      l = j
      IF ( Y(j)<amed ) THEN
         Y(mid) = Y(j)
         Xpos(mid) = Xpos(j)
         Y(j) = amed
         Xpos(j) = bmed
         amed = Y(mid)
         bmed = Xpos(mid)
         IF ( Y(i)>amed ) THEN
            Y(mid) = Y(i)
            Xpos(mid) = Xpos(i)
            Y(i) = amed
            Xpos(i) = bmed
            amed = Y(mid)
            bmed = Xpos(mid)
         ENDIF
      ENDIF
      DO
         l = l - 1
         IF ( Y(l)<=amed ) THEN
            tt = Y(l)
            itt = Xpos(l)
            DO
               k = k + 1
               IF ( Y(k)>=amed ) THEN
                  IF ( k<=l ) THEN
                     Y(l) = Y(k)
                     Xpos(l) = Xpos(k)
                     Y(k) = tt
                     Xpos(k) = itt
                     EXIT
                  ELSE
                     lmi = l - i
                     jmk = j - k
                     IF ( lmi<=jmk ) THEN
                        il(m) = k
                        iu(m) = j
                        j = l
                        m = m + 1
                     ELSE
                        il(m) = i
                        iu(m) = l
                        i = k
                        m = m + 1
                     ENDIF
                     GOTO 500
                  ENDIF
               ENDIF
            ENDDO
         ENDIF
      ENDDO
 400  m = m - 1
      IF ( m==0 ) RETURN
      i = il(m)
      j = iu(m)
 500  jmi = j - i
      IF ( jmi>=11 ) GOTO 300
      IF ( i==1 ) GOTO 200
      i = i - 1
      DO
         i = i + 1
         IF ( i==j ) GOTO 400
         amed = Y(i+1)
         bmed = Xpos(i+1)
         IF ( Y(i)>amed ) THEN
            k = i
            DO
               Y(k+1) = Y(k)
               Xpos(k+1) = Xpos(k)
               k = k - 1
               IF ( amed>=Y(k) ) THEN
                  Y(k+1) = amed
                  Xpos(k+1) = bmed
                  EXIT
               ENDIF
            ENDDO
         ENDIF
      ENDDO
END SUBROUTINE SORTP