num_sort.F90 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. !
  2. ! Sorting.
  3. !
  4. !
  5. ! call Sort( x, xsort, isort, status )
  6. !
  7. ! Sorts the values of x(:) in increasing order.
  8. ! Sorted x is stored in xsort,
  9. ! indices in isort such that x(isort) = xsort .
  10. !
  11. module num_sort
  12. implicit none
  13. ! --- in/out ---------------------------------
  14. private
  15. public :: Sort
  16. ! --- const ---------------------------------
  17. character(len=*), parameter :: mname = 'num_sort'
  18. ! --- interfaces ------------------------------
  19. interface Sort
  20. module procedure sort_r_1d
  21. module procedure sort_r_2d
  22. end interface
  23. contains
  24. ! ===================================================
  25. !
  26. ! call Sort( x, xsort, isort, status )
  27. !
  28. ! Sorts the values of x(:) in increasing order.
  29. ! Sorted x is stored in xsort,
  30. ! indices in isort such that:
  31. ! xsort(i) = x(isort(i))
  32. !
  33. subroutine sort_r_1d( x, xsort, isort, status )
  34. use GO , only : gol, goErr
  35. use Num_Tools, only : Interval
  36. ! --- in/out --------------------------------
  37. real, intent(in) :: x(:)
  38. real, intent(out) :: xsort(:)
  39. integer, intent(out) :: isort(:)
  40. integer, intent(out) :: status
  41. ! --- const ---------------------------------
  42. character(len=*), parameter :: rname = mname//'/sort_r_1d'
  43. ! --- local ---------------------------------
  44. integer :: ns
  45. real :: a
  46. integer :: i
  47. integer :: ileft
  48. integer :: iflag
  49. ! --- begin ---------------------------------
  50. ! check input
  51. if ( any(shape(xsort) /= shape(x)) .or. any(shape(isort) /= shape(x)) ) then
  52. write (gol,'("shape of output arrays should be same as input:")'); call goErr
  53. write (gol,'(" shape(x) : ",i6)') shape(x); call goErr
  54. write (gol,'(" shape(xsort) : ",i6)') shape(xsort); call goErr
  55. write (gol,'(" shape(isort) : ",i6)') shape(isort); call goErr
  56. write (gol,'("in ",a)') rname; call goErr; status=1; return
  57. end if
  58. ! init
  59. xsort(1) = x(1) ! sorted input
  60. isort(1) = 1 ! sorted indices
  61. ns = 1 ! number of yet sorted values
  62. ! no interval searched yet
  63. ileft = 1
  64. ! loop over other elements
  65. do i = 2, size(x)
  66. ! current value
  67. a = x(i)
  68. ! where in sorted array ?
  69. call Interval( xsort(1:ns), a, ileft, iflag )
  70. if ( iflag < 0 ) then
  71. isort(1:ns+1) = (/ i, isort(1:ns) /)
  72. xsort(1:ns+1) = (/ a, xsort(1:ns) /)
  73. else if ( iflag > 0 ) then
  74. isort(1:ns+1) = (/ isort(1:ns), i /)
  75. xsort(1:ns+1) = (/ xsort(1:ns), a /)
  76. else
  77. isort(1:ns+1) = (/ isort(1:ileft), i, isort(ileft+1:ns) /)
  78. xsort(1:ns+1) = (/ xsort(1:ileft), a, xsort(ileft+1:ns) /)
  79. end if
  80. ns = ns + 1
  81. end do
  82. ! ok
  83. status = 0
  84. end subroutine sort_r_1d
  85. !
  86. ! call Sort( x, xsort, isort, status )
  87. !
  88. ! Sorts the values of x(:) in increasing order.
  89. ! Sorted x is stored in xsort,
  90. ! indices in isort such that:
  91. ! xsort(i,j) = x(isort(i,j,1),isort(i,j,2))
  92. !
  93. subroutine sort_r_2d( x, xsort, isort, status )
  94. use GO , only : gol, goErr
  95. use Num_Tools, only : Interval
  96. ! --- in/out --------------------------------
  97. real, intent(in) :: x(:,:)
  98. real, intent(out) :: xsort(:,:)
  99. integer, intent(out) :: isort(:,:,:)
  100. integer, intent(out) :: status
  101. ! --- const ---------------------------------
  102. character(len=*), parameter :: rname = mname//'/sort_r_2d'
  103. ! --- local ---------------------------------
  104. real :: x_1d(size(x))
  105. real :: xsort_1d(size(x))
  106. integer :: isort_1d(size(x))
  107. integer :: ns
  108. real :: a
  109. integer :: i
  110. integer :: ileft
  111. integer :: iflag
  112. ! --- begin ---------------------------------
  113. ! check xsort
  114. if ( any(shape(xsort) /= shape(x)) ) then
  115. write (gol,'("shape of sorted output should be same as input:")'); call goErr
  116. write (gol,'(" shape(x) : ",2i6)') shape(x); call goErr
  117. write (gol,'(" shape(xsort) : ",2i6)') shape(xsort); call goErr
  118. write (gol,'("in ",a)') rname; call goErr; status=1; return
  119. end if
  120. ! check isort
  121. if ( any(shape(isort) /= (/size(x,1),size(x,2),2/)) ) then
  122. write (gol,'("shape of isort be (/x1,x2,2/) :")'); call goErr
  123. write (gol,'(" shape(x) : ",2i6)') shape(x); call goErr
  124. write (gol,'(" shape(isort) : ",3i6)') shape(isort); call goErr
  125. write (gol,'("in ",a)') rname; call goErr; status=1; return
  126. end if
  127. ! store in 1d arrays:
  128. x_1d = reshape(x ,(/size(x)/))
  129. xsort_1d = reshape(xsort,(/size(x)/))
  130. isort_1d = reshape(isort,(/size(x)/))
  131. ! sort 1d array:
  132. call Sort( x_1d, xsort_1d, isort_1d, status )
  133. if (status/=0) then; write (gol,'("in ",a)') rname; call goErr; status=1; return; end if
  134. ! fill sorted x :
  135. xsort = reshape(xsort_1d,shape(x))
  136. ! fill indices
  137. isort(:,:,1) = modulo(reshape(isort_1d,shape(x))-1,size(x,1))+1
  138. isort(:,:,2) = ceiling(reshape(isort_1d,shape(x))/real(size(x,1)))
  139. ! ok
  140. status = 0
  141. end subroutine sort_r_2d
  142. end module num_sort
  143. ! ######################################################################
  144. !program test
  145. !
  146. ! use num_sort, only : Sort
  147. !
  148. ! implicit none
  149. !
  150. ! integer, parameter :: n1=10, n2=5
  151. ! real :: x(n1,n2)
  152. ! real :: xsort(n1,n2)
  153. ! integer :: isort(n1,n2,2)
  154. ! integer :: status
  155. !
  156. ! integer :: i, j
  157. !
  158. ! call Random_Seed()
  159. ! call Random_Number( x )
  160. !
  161. ! call Sort( x, xsort, isort, status )
  162. ! if (status/=0) stop 'error from sort'
  163. !
  164. ! do j=1, n2
  165. ! do i = 1, n1
  166. ! write (*,'(2i4,f8.4,2i4,2f8.4)') i, j, x(i,j), isort(i,j,:), xsort(i,j), x(isort(i,j,1),isort(i,j,2))
  167. ! end do
  168. ! end do
  169. !
  170. !end program test