Recursive quicksoft. Modified to also carry along a second array.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer(kind=ip), | intent(in) | :: | n | |||
| real(kind=wp), | intent(inout), | dimension(*) | :: | dx |
array of values to be sorted |
|
| real(kind=wp), | intent(inout), | optional, | dimension(*) | :: | dy |
array to be (optionally) carried along |
subroutine sort_ascending(n, dx, dy) integer(ip), intent(in) :: n real(wp), dimension(*), intent(inout) :: dx !! array of values to be sorted real(wp), dimension(*), intent(inout), optional :: dy !! array to be (optionally) carried along logical :: carry_dy !! if `dy` is to be also sorted integer(ip), parameter :: max_size_for_insertion_sort = 20 !! max size for using insertion sort. !! (otherwise, use quicksort) carry_dy = present(dy) call quicksort(1_ip, n) contains recursive subroutine quicksort(ilow, ihigh) !! Sort the array (ascending order). integer(ip), intent(in) :: ilow integer(ip), intent(in) :: ihigh integer(ip) :: ipivot !! pivot element integer(ip) :: i !! counter integer(ip) :: j !! counter if (ihigh - ilow <= max_size_for_insertion_sort .and. ihigh > ilow) then ! do insertion sort: do i = ilow + 1, ihigh do j = i, ilow + 1, -1 if (dx(j) < dx(j - 1)) then call swap(dx(j), dx(j - 1)) if (carry_dy) call swap(dy(j), dy(j - 1)) else exit end if end do end do else if (ihigh - ilow > max_size_for_insertion_sort) then ! do the normal quicksort: call partition(ilow, ihigh, ipivot) call quicksort(ilow, ipivot - 1) call quicksort(ipivot + 1, ihigh) end if end subroutine quicksort subroutine partition(ilow, ihigh, ipivot) !! Partition the array integer(ip), intent(in) :: ilow integer(ip), intent(in) :: ihigh integer(ip), intent(out) :: ipivot integer(ip) :: i, ipp, im im = (ilow + ihigh)/2 call swap(dx(ilow), dx(im)) if (carry_dy) call swap(dy(ilow), dy(im)) ipp = ilow do i = ilow + 1, ihigh if (dx(i) < dx(ilow)) then ipp = ipp + 1 call swap(dx(ipp), dx(i)) if (carry_dy) call swap(dy(ipp), dy(i)) end if end do call swap(dx(ilow), dx(ipp)) if (carry_dy) call swap(dy(ilow), dy(ipp)) ipivot = ipp end subroutine partition subroutine swap(v1, v2) !! swap two real values real(wp), intent(inout) :: v1 real(wp), intent(inout) :: v2 real(wp) :: tmp tmp = v1 v1 = v2 v2 = tmp end subroutine swap end subroutine sort_ascending