sp_radix_sort Module Subroutine

module subroutine sp_radix_sort(array, work, reverse)

Uses

  • proc~~sp_radix_sort~~UsesGraph proc~sp_radix_sort sp_radix_sort iso_c_binding iso_c_binding proc~sp_radix_sort->iso_c_binding

Arguments

Type IntentOptional Attributes Name
real(kind=sp), intent(inout), dimension(:), target :: array
real(kind=sp), intent(inout), optional, dimension(:), target :: work
logical, intent(in), optional :: reverse

Calls

proc~~sp_radix_sort~~CallsGraph proc~sp_radix_sort sp_radix_sort interface~pic_optional pic_optional proc~sp_radix_sort->interface~pic_optional proc~radix_sort_u32_helper radix_sort_u32_helper proc~sp_radix_sort->proc~radix_sort_u32_helper proc~optional_char optional_char interface~pic_optional->proc~optional_char proc~optional_dp optional_dp interface~pic_optional->proc~optional_dp proc~optional_int32 optional_int32 interface~pic_optional->proc~optional_int32 proc~optional_int64 optional_int64 interface~pic_optional->proc~optional_int64 proc~optional_logical optional_logical interface~pic_optional->proc~optional_logical proc~optional_sp optional_sp interface~pic_optional->proc~optional_sp

Variables

Type Visibility Attributes Name Initial
integer(kind=int_index), private :: N
integer(kind=int32), private, dimension(:), pointer :: arri32
integer(kind=int32), private, dimension(:), pointer :: buffer
integer(kind=int_index), private :: i
real(kind=sp), private :: item
integer(kind=int_index), private :: pos
integer(kind=int_index), private :: rev_pos
logical, private :: use_internal_buffer

Source Code

   module subroutine sp_radix_sort(array, work, reverse)
      use iso_c_binding, only: c_loc, c_f_pointer
      real(kind=sp), dimension(:), intent(inout), target :: array
      real(kind=sp), dimension(:), intent(inout), target, optional :: work
      logical, intent(in), optional :: reverse
      integer(kind=int_index) :: i, N, pos, rev_pos
      integer(kind=int32), dimension(:), pointer :: arri32
      integer(kind=int32), dimension(:), pointer :: buffer
      real(kind=sp) :: item
      logical :: use_internal_buffer
      N = size(array, kind=int_index)
      if (present(work)) then
         if (size(work, kind=int_index) < N) then
            error stop "sp_radix_sort: work array is too small."
         end if
         use_internal_buffer = .false.
         call c_f_pointer(c_loc(work), buffer, [N])
      else
         use_internal_buffer = .true.
         allocate (buffer(N))
      end if
      call c_f_pointer(c_loc(array), arri32, [N])
      call radix_sort_u32_helper(N, arri32, buffer)
! After calling `radix_sort_u<width>_helper. The array is sorted as unsigned integers.
! The positive real number is sorted, guaranteed by IEEE-754 standard.
! But the negative real number is sorted in a reversed order, and also in the tail of array.
! Remark that -0.0 is the minimum nagative integer, so using radix sort, -0.0 is naturally lesser than 0.0.
! In IEEE-754 standard, the bit representation of `Inf` is greater than all positive real numbers,
! and the `-Inf` is lesser than all negative real numbers. So the order of `Inf, -Inf` is ok.
! The bit representation of `NaN` may be positive or negative integers in different machine,
! thus if the array contains `NaN`, the result is undefined.
      if (arri32(1) >= 0 .and. arri32(N) < 0) then
         pos = 1
         rev_pos = N
         do while (arri32(rev_pos) < 0)
            buffer(pos) = arri32(rev_pos)
            pos = pos + 1
            rev_pos = rev_pos - 1
         end do
         buffer(pos:N) = arri32(1:rev_pos)
         arri32(:) = buffer(:)
      end if
      if (pic_optional(reverse, .false.)) then
         do i = 1, N/2
            item = array(i)
            array(i) = array(N - i + 1)
            array(N - i + 1) = item
         end do
      end if
      if (use_internal_buffer) then
         deallocate (buffer)
      end if
   end subroutine sp_radix_sort