Last commit for src/ext/sortlib.f90: 5874abaa643d4472a2aa9d1c5dbe454dadbd8d1f

Initial commit of the AENET code.

Bruno Mundim [2017-01-02 17:48:39]
Initial commit of the AENET code.
!-----------------------------------------------------------------------
!             sortlib.f90 - Library with sorting routines
!-----------------------------------------------------------------------
!+ This file is part of the AENET package.
!+
!+ Copyright (C) 2012-2016 Nongnuch Artrith and Alexander Urban
!+
!+ This program is free software: you can redistribute it and/or modify
!+ it under the terms of the GNU General Public License as published by
!+ the Free Software Foundation, either version 3 of the License, or
!+ (at your option) any later version.
!+
!+ This program is distributed in the hope that it will be useful, but
!+ WITHOUT ANY WARRANTY; without even the implied warranty of
!+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
!+ General Public License for more details.
!+
!+ You should have received a copy of the GNU General Public License
!+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
!-----------------------------------------------------------------------
! sort(A)        : sort double precision array A
! sort(A,n)      : sort first n elements in double precision array A
! argsort(A,idx) : return index idx that sorts dp array A
!-----------------------------------------------------------------------
! 2010-02-11 Nongnuch Artrith (NA), Alexander Urban (AU)
!-----------------------------------------------------------------------

module sortlib

  implicit none

  public  :: sort,           &
             sort_i,         &
             sort_d,         &
             argsort,        &
             argsort_d,      &
             argsort_i

  private :: qsort_d,        &
             qsort_i,        &
             qargsort_d,     &
             qargsort_i,     &
             partition_d,    &
             partition_i,    &
             argpartition_d, &
             argpartition_i

  interface sort
     module procedure sort_i, sort_d
  end interface
  interface argsort
     module procedure argsort_i, argsort_d
  end interface

contains

  !--------------------------------------------------------------------!
  !                          User interfaces                           !
  !--------------------------------------------------------------------!

  subroutine sort_d(A, n)

    implicit none

    integer, optional,              intent(in)    :: n
    double precision, dimension(:), intent(inout) :: A
    integer                                       :: m

    if (present(n)) then
       m = n
    else
       m = size(A)
    end if

    call qsort_d(A, m)

  end subroutine sort_d

  !--------------------------------------------------------------------!

  subroutine sort_i(A, n)

    implicit none

    integer, optional,     intent(in)    :: n
    integer, dimension(:), intent(inout) :: A
    integer                              :: m

    if (present(n)) then
       m = n
    else
       m = size(A)
    end if

    call qsort_i(A, m)

  end subroutine sort_i

  !--------------------------------------------------------------------!

  subroutine argsort_d(A, idx)

    implicit none

    double precision, dimension(:), intent(in)  :: A
    integer,          dimension(:), intent(out) :: idx
    integer                                     :: i, n

    n = size(idx)
    do i = 1, n
       idx(i) = i
    end do

    call qargsort_d(A, idx, n, n)

  end subroutine argsort_d

  !--------------------------------------------------------------------!

  subroutine argsort_i(A, idx)

    implicit none

    integer, dimension(:), intent(in)  :: A
    integer, dimension(:), intent(out) :: idx
    integer                            :: i, n

    n = size(idx)
    do i = 1, n
       idx(i) = i
    end do

    call qargsort_i(A, idx, n, n)

  end subroutine argsort_i

  !--------------------------------------------------------------------!
  !                      quicksort implementation                      !
  !--------------------------------------------------------------------!

  recursive subroutine qsort_d(A,n)

    implicit none

    integer,                        intent(in)    :: n
    double precision, dimension(n), intent(inout) :: A
    integer                                       :: iq

    if(n > 1) then
       call partition_d(A, n, iq)
       call qsort_d(A(:iq-1), iq-1)
       call qsort_d(A(iq:), n-iq+1)
    endif

  end subroutine qsort_d

  !--------------------------------------------------------------------!

  recursive subroutine qsort_i(A,n)

    implicit none

    integer,               intent(in)    :: n
    integer, dimension(n), intent(inout) :: A
    integer                              :: iq

    if(n > 1) then
       call partition_i(A, n, iq)
       call qsort_i(A(:iq-1), iq-1)
       call qsort_i(A(iq:), n-iq+1)
    endif

  end subroutine qsort_i

  !--------------------------------------------------------------------!

  subroutine partition_d(A, n, marker)

    implicit none

    integer,                        intent(in)    :: n
    double precision, dimension(n), intent(inout) :: A
    integer,                        intent(out)   :: marker
    integer                                       :: i, j
    double precision                              :: temp
    double precision                              :: x    ! pivot point

    x = A(1)
    i = 0
    j = n + 1

    do
       j = j-1
       do while (A(j) > x)
          j = j-1
       end do
       i = i+1
       do while (A(i) < x)
          i = i+1
       end do
       if (i < j) then
          ! exchange A(i) and A(j)
          temp = A(i)
          A(i) = A(j)
          A(j) = temp
       else if (i == j) then
          marker = i+1
          return
       else
          marker = i
          return
       endif
    end do

  end subroutine partition_d

  !--------------------------------------------------------------------!

  subroutine partition_i(A, n, marker)

    implicit none

    integer,               intent(in)    :: n
    integer, dimension(n), intent(inout) :: A
    integer,               intent(out)   :: marker
    integer                              :: i, j
    integer                              :: temp
    double precision                     :: x    ! pivot point

    x = A(1)
    i = 0
    j = n + 1

    do
       j = j-1
       do while (A(j) > x)
          j = j-1
       end do
       i = i+1
       do while (A(i) < x)
          i = i+1
       end do
       if (i < j) then
          ! exchange A(i) and A(j)
          temp = A(i)
          A(i) = A(j)
          A(j) = temp
       else if (i == j) then
          marker = i+1
          return
       else
          marker = i
          return
       endif
    end do

  end subroutine partition_i

  !--------------------------------------------------------------------!
  !                   Argument sort using quicksort                    !
  !--------------------------------------------------------------------!

  recursive subroutine qargsort_d(A, idx, n, m)

    implicit none

    integer,                        intent(in)    :: n
    integer,                        intent(in)    :: m
    double precision, dimension(n), intent(in)    :: A
    integer,          dimension(m), intent(inout) :: idx
    integer                                       :: iq

    if(m > 1) then
       call argpartition_d(A, idx, n, m, iq)
       call qargsort_d(A, idx(:iq-1), n, iq-1)
       call qargsort_d(A, idx(iq:),   n, m-iq+1)
    endif

  end subroutine qargsort_d

  !--------------------------------------------------------------------!

  recursive subroutine qargsort_i(A, idx, n, m)

    implicit none

    integer,               intent(in)    :: n
    integer,               intent(in)    :: m
    integer, dimension(n), intent(in)    :: A
    integer, dimension(m), intent(inout) :: idx
    integer                              :: iq

    if(m > 1) then
       call argpartition_i(A, idx, n, m, iq)
       call qargsort_i(A, idx(:iq-1), n, iq-1)
       call qargsort_i(A, idx(iq:),   n, m-iq+1)
    endif

  end subroutine qargsort_i

  !--------------------------------------------------------------------!

  subroutine argpartition_d(A, idx, n, m, marker)

    implicit none

    integer,                        intent(in)    :: n
    integer,                        intent(in)    :: m
    double precision, dimension(n), intent(in)    :: A
    integer,          dimension(m), intent(inout) :: idx
    integer,                        intent(out)   :: marker
    integer                                       :: i, j
    integer                                       :: temp
    double precision                              :: x    ! pivot point

    x = A(idx(1))
    i = 0
    j = m + 1

    do
       j = j-1
       do while (A(idx(j)) > x)
          j = j-1
       end do
       i = i+1
       do while (A(idx(i)) < x)
          i = i+1
       end do
       if (i < j) then
          ! exchange A(idx(i)) and A(idx(j))
          temp   = idx(i)
          idx(i) = idx(j)
          idx(j) = temp
       else if (i == j) then
          marker = i+1
          return
       else
          marker = i
          return
       endif
    end do

  end subroutine argpartition_d

  !--------------------------------------------------------------------!

  subroutine argpartition_i(A, idx, n, m, marker)

    implicit none

    integer,               intent(in)    :: n
    integer,               intent(in)    :: m
    integer, dimension(n), intent(in)    :: A
    integer, dimension(m), intent(inout) :: idx
    integer,               intent(out)   :: marker
    integer                              :: i, j
    integer                              :: temp
    double precision                     :: x    ! pivot point

    x = A(idx(1))
    i = 0
    j = m + 1

    do
       j = j-1
       do while (A(idx(j)) > x)
          j = j-1
       end do
       i = i+1
       do while (A(idx(i)) < x)
          i = i+1
       end do
       if (i < j) then
          ! exchange A(idx(i)) and A(idx(j))
          temp   = idx(i)
          idx(i) = idx(j)
          idx(j) = temp
       else if (i == j) then
          marker = i+1
          return
       else
          marker = i
          return
       endif
    end do

  end subroutine argpartition_i

end module sortlib
ViewGit