! Copyright (c) 1994 Unicomp, Inc.
!
! Developed at Unicomp, Inc.
!
! Permission to use, copy, modify, and distribute this
! software is freely granted, provided that this notice 
! is preserved.

implicit none
real x(16), element
logical err
read*,x
call quick_select(x,1,element,err)
print "(f20.0,l9)", element, err
call quick_select(x,8,element,err)
print "(f20.0,l9)", element, err
call quick_select(x,16,element,err)
print "(f20.0,l9)", element, err
call quick_select(x,0,element,err)
print "(f20.0,l9)", element, err
call quick_select(x,17,element,err)
print "(f20.0,l9)", element, err

contains

recursive subroutine quick_select  &
      (list, k, element, error)

   real, dimension (:), intent (in) :: list
   integer, intent (in) :: k
   real, intent (out) :: element
   logical, intent (out) :: error
   real, dimension (size (list)) :: smaller, larger
   integer :: i,  &
         number_smaller, number_equal, number_larger
   real :: chosen

   if (size (list) <= 1) then
      error = .not. (size (list) == 1 .and. k == 1)
      if (error) then
         element = 0.0  ! A value must be assigned
                 ! because element is intent (out)
      else
         element = list (1)
      end if

   else
      chosen = list (1)
      number_smaller = 0
      number_equal = 1
      number_larger = 0

      do i = 2, size (list)
         if (list (i) < chosen) then
            number_smaller = number_smaller + 1
            smaller (number_smaller) = list (i)
         else if (list (i) == chosen) then
            number_equal = number_equal + 1
         else
            number_larger = number_larger + 1
            larger (number_larger) = list (i)
         end if
      end do

      if (k <= number_smaller) then
         call quick_select  &
               (smaller (1 : number_smaller),  &
                k, element, error)
      else if (k <= number_smaller + number_equal) then
         element = chosen
         error = .false.
      else
         call quick_select  &
               (larger (1 : number_larger),  &
                k - number_smaller - number_equal,  &
                element, error)
      end if
   end if

end subroutine quick_select

end
