我尝试了编写standard C library subroutine qsort 接口的惰性方法。为了避免全局数据,我将比较函数作为调用qsort 并保存要排序的数组的子例程的内部函数。中间子例程分配qsort 实际排序的索引数组,然后索引数组用于拉直输入数组。以下是它的工作原理:
module sortmod
use ISO_C_BINDING
implicit none
interface
subroutine qsort(base,nitems,size,compar) bind(C,name='qsort')
import
implicit none
type(C_PTR), value :: base
integer(C_SIZE_T), value :: nitems
integer(C_SIZE_T), value :: size
interface
function compar(x,y) bind(C)
import
implicit none
integer(C_INT) compar
type(C_PTR),value :: x
type(C_PTR),value :: y
end function compar
end interface
end subroutine qsort
end interface
contains
recursive subroutine startsort(array)
integer(C_INT) array(:,:)
integer(C_INT), allocatable, target :: indices(:)
integer i
indices = [(i,i=1,size(array,1))]
call qsort(C_LOC(indices),size(indices,1,kind=C_SIZE_T),C_SIZEOF(indices(1)),callback)
array = array(indices,:)
contains
function callback(x,y) bind(C)
integer(C_INT) callback
type(C_PTR), value :: x, y
integer(C_INT), pointer :: ix,iy
integer j
call C_F_POINTER(x,ix)
call C_F_POINTER(y,iy)
callback = 0
do j = 1, size(array,2)
callback = array(ix,j) - array(iy,j)
if(callback /= 0) return
end do
end function callback
end subroutine startsort
end module sortmod
program testsort
use sortmod
implicit none
integer(C_INT), allocatable :: array(:,:)
character(20) fmt
array = reshape([2, 1, 4, &
1, 2, 3, &
2, 1, 2], &
[3, 3], order = [2, 1])
call startsort(array)
write(fmt,'(*(g0))') '(',size(array,2),'i3)'
write(*,fmt) transpose(array)
end program testsort
使用 gfortran 输出:
1 2 3
2 1 2
2 1 4