rqsort Subroutine

private subroutine rqsort(n, a, p)

Return integer array p which indexes array a in increasing order. Array a is not disturbed. The Quicksort algorithm is used.

Reference

  • N. Wirth, "Algorithms and Data Structures", Prentice-Hall, 1986

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n
real(kind=wp), intent(in), dimension(n) :: a
integer, intent(out), dimension(n) :: p

Called by

proc~~rqsort~~CalledByGraph proc~rqsort pikaia_module::rqsort proc~rnkpop pikaia_module::pikaia_class%rnkpop proc~rnkpop->proc~rqsort proc~newpop pikaia_module::pikaia_class%newpop proc~newpop->proc~rnkpop proc~pikaia pikaia_module::pikaia_class%pikaia proc~pikaia->proc~rnkpop proc~pikaia->proc~newpop proc~solve_with_pikaia pikaia_module::pikaia_class%solve_with_pikaia proc~solve_with_pikaia->proc~pikaia

Source Code

    subroutine rqsort(n,a,p)

    implicit none

    integer,intent(in)               :: n
    real(wp),dimension(n),intent(in) :: a
    integer,dimension(n),intent(out) :: p

    !Constants
    integer,parameter :: LGN = 32      !! log base 2 of maximum n
    integer,parameter :: Q   = 11      !! smallest subfile to use quicksort on

    !Local:
    integer,dimension(LGN) :: stackl,stackr
    real(wp) :: x
    integer :: s,t,l,m,r,i,j

    !Initialize the stack
    stackl(1) = 1
    stackr(1) = n
    l = stackl(1)
    r = stackr(1)
    s = 1

    !Initialize the pointer array
    p = [(i, i=1,n)]

    do while (s>0)

        s = s - 1

        if ((r-l)<Q) then

            !Use straight insertion
            insertion: do i=l+1,r
                t = p(i)
                x = a(t)
                do j=i-1,l,-1
                    if (a(p(j))<=x) then
                        p(j+1) = t
                        cycle insertion
                    end if
                    p(j+1) = p(j)
                end do
                j=l-1
                p(j+1) = t
            end do insertion

        else

            !Use quicksort, with pivot as median of a(l), a(m), a(r)
            m=(l+r)/2
            t=p(m)
            if (a(t)<a(p(l))) then
                p(m)=p(l)
                p(l)=t
                t=p(m)
            end if
            if (a(t)>a(p(r))) then
                p(m)=p(r)
                p(r)=t
                t=p(m)
                if (a(t)<a(p(l))) then
                    p(m)=p(l)
                    p(l)=t
                    t=p(m)
                end if
            end if

            !Partition
            x=a(t)
            i=l+1
            j=r-1
            do while (i<=j)

                do while (a(p(i))<x)
                    i=i+1
                end do

                do while (x<a(p(j)))
                    j=j-1
                end do

                if (i<=j) then
                    t=p(i)
                    p(i)=p(j)
                    p(j)=t
                    i=i+1
                    j=j-1
                end if

            end do

            !Stack the larger subfile
            s=s+1
            if ((j-l)>(r-i)) then
                stackl(s)=l
                stackr(s)=j
                l=i
            else
                stackl(s)=i
                stackr(s)=r
                r=j
            end if

            s = s + 1 ! since it will be decremented next cycle
            cycle
        end if

        if (s>0) then
            l = stackl(s)
            r = stackr(s)
        end if

    end do

    end subroutine rqsort