FV3 Bundle
tools_qsort.F90
Go to the documentation of this file.
1 !----------------------------------------------------------------------
2 ! Module: tools_qsort
3 ! Purpose: qsort routines
4 ! Source: http://jblevins.org/mirror/amiller/qsort.f90
5 ! Author: Brainerd, W.S., Goldberg, C.H. & Adams, J.C. (1990) "Programmer's Guide to Fortran 90", McGraw-Hill ISBN 0-07-000248-7, pages 149-150.
6 ! Original licensing: none
7 ! Modified by Alan Miller
8 ! Modified by Benjamin Menetrier for BUMP
9 ! Licensing: this code is distributed under the CeCILL-C license
10 ! Copyright © 2015-... UCAR, CERFACS, METEO-FRANCE and IRIT
11 !----------------------------------------------------------------------
13 
14 use tools_kinds, only: kind_real
15 
16 implicit none
17 
18 interface qsort
19  module procedure qsort_integer
20  module procedure qsort_real
21 end interface
22 
23 interface quick_sort
24  module procedure quick_sort_integer
25  module procedure quick_sort_real
26 end interface
27 
29  module procedure interchange_sort_integer
30  module procedure interchange_sort_real
31 end interface
32 
33 private
34 public :: qsort
35 
36 contains
37 
38 !----------------------------------------------------------------------
39 ! Subroutine: qsort_integer
40 ! Purpose: sort an integer subvector
41 !----------------------------------------------------------------------
42 recursive subroutine qsort_integer(n,list,order)
43 
44 implicit none
45 
46 ! Passed variables
47 integer, intent(in) :: n ! Input vector size
48 integer,intent(inout) :: list(n) ! Vector to sort
49 integer,intent(inout) :: order(n) ! Positions of the elements in the original order
50 
51 ! Local variable
52 integer :: i
53 
54 do i=1,n
55  order(i) = i
56 end do
57 
58 call quick_sort(n,1,n,list,order)
59 
60 end subroutine qsort_integer
61 
62 !----------------------------------------------------------------------
63 ! Subroutine: qsort_real
64 ! Purpose: sort a real subvector
65 !----------------------------------------------------------------------
66 recursive subroutine qsort_real(n,list,order)
67 
68 implicit none
69 
70 ! Passed variables
71 integer, intent(in) :: n ! Input vector size
72 real(kind_real),intent(inout) :: list(n) ! Vector to sort
73 integer,intent(inout) :: order(n) ! Positions of the elements in the original order
74 
75 ! Local variable
76 integer :: i
77 
78 do i=1,n
79  order(i) = i
80 end do
81 
82 call quick_sort(n,1,n,list,order)
83 
84 end subroutine qsort_real
85 
86 !----------------------------------------------------------------------
87 ! Subroutine: quick_sort_integer
88 ! Purpose: sort an integer subvector
89 !----------------------------------------------------------------------
90 recursive subroutine quick_sort_integer(n,left_end,right_end,list,order)
91 
92 implicit none
93 
94 ! Passed variables
95 integer,intent(in) :: n ! Input vector size
96 integer,intent(in) :: left_end ! Left end of the vector
97 integer,intent(in) :: right_end ! Right end of the vector
98 integer,intent(inout) :: list(n) ! Vector to sort
99 integer,intent(inout) :: order(n) ! Positions of the elements in the original order
100 
101 ! Local variables
102 integer,parameter :: max_simple_sort_size = 6
103 integer :: i,j,itemp
104 integer :: reference,temp
105 
106 if (right_end<left_end+max_simple_sort_size) then
107  ! Use interchange sort for small lists
108  call interchange_sort(n,left_end,right_end,list,order)
109 else
110  ! Use partition ("quick") sort
111  reference = list((left_end+right_end)/2)
112  i = left_end-1
113  j = right_end+1
114  do
115  ! Scan list from left end until element >= reference is found
116  do
117  i = i+1
118  if (list(i)>=reference) exit
119  end do
120  ! Scan list from right end until element <= reference is found
121  do
122  j = j-1
123  if (list(j)<=reference) exit
124  end do
125 
126  if (i<j) then
127  ! Swap two out-of-order elements
128  temp = list(i)
129  list(i) = list(j)
130  list(j) = temp
131  itemp = order(i)
132  order(i) = order(j)
133  order(j) = itemp
134  elseif (i==j) then
135  i = i+1
136  exit
137  else
138  exit
139  end if
140  end do
141 
142  if (left_end<j) call quick_sort(n,left_end,j,list,order)
143  if (i<right_end) call quick_sort(n,i,right_end,list,order)
144 end if
145 
146 end subroutine quick_sort_integer
147 
148 !----------------------------------------------------------------------
149 ! Subroutine: quick_sort_real
150 ! Purpose: sort a real subvector
151 !----------------------------------------------------------------------
152 recursive subroutine quick_sort_real(n,left_end,right_end,list,order)
154 implicit none
155 
156 ! Passed variables
157 integer,intent(in) :: n ! Input vector size
158 integer,intent(in) :: left_end ! Left end of the vector
159 integer,intent(in) :: right_end ! Right end of the vector
160 real(kind_real),intent(inout) :: list(n) ! Vector to sort
161 integer,intent(inout) :: order(n) ! Positions of the elements in the original order
162 
163 ! Local variables
164 integer,parameter :: max_simple_sort_size = 6
165 integer :: i,j,itemp
166 real(kind_real) :: reference,temp
167 
168 if (right_end<left_end+max_simple_sort_size) then
169  ! Use interchange sort for small lists
170  call interchange_sort(n,left_end,right_end,list,order)
171 else
172  ! Use partition ("quick") sort
173  reference = list((left_end+right_end)/2)
174  i = left_end-1
175  j = right_end+1
176  do
177  ! Scan list from left end until element >= reference is found
178  do
179  i = i+1
180  if (list(i)>=reference) exit
181  end do
182  ! Scan list from right end until element <= reference is found
183  do
184  j = j-1
185  if (list(j)<=reference) exit
186  end do
187 
188  if (i<j) then
189  ! Swap two out-of-order elements
190  temp = list(i)
191  list(i) = list(j)
192  list(j) = temp
193  itemp = order(i)
194  order(i) = order(j)
195  order(j) = itemp
196  elseif (i==j) then
197  i = i+1
198  exit
199  else
200  exit
201  end if
202  end do
203 
204  if (left_end<j) call quick_sort(n,left_end,j,list,order)
205  if (i<right_end) call quick_sort(n,i,right_end,list,order)
206 end if
207 
208 end subroutine quick_sort_real
209 
210 !----------------------------------------------------------------------
211 ! Subroutine: interchange_sort_integer
212 ! Purpose: interchange integers
213 !----------------------------------------------------------------------
214 subroutine interchange_sort_integer(n,left_end,right_end,list,order)
216 implicit none
217 
218 ! Passed variables
219 integer,intent(in) :: n ! Input vector size
220 integer,intent(in) :: left_end ! Left end of the vector
221 integer,intent(in) :: right_end ! Right end of the vector
222 integer,intent(inout) :: list(n) ! Vector to sort
223 integer,intent(inout) :: order(n) ! Positions of the elements in the original order
224 
225 ! Local variables
226 integer :: i,j,itemp
227 integer :: temp
228 
229 do i=left_end,right_end-1
230  do j=i+1,right_end
231  if (list(i)>list(j)) then
232  temp = list(i)
233  list(i) = list(j)
234  list(j) = temp
235  itemp = order(i)
236  order(i) = order(j)
237  order(j) = itemp
238  end if
239  end do
240 end do
241 
242 end subroutine interchange_sort_integer
243 
244 !----------------------------------------------------------------------
245 ! Subroutine: interchange_sort_real
246 ! Purpose: interchange reals
247 !----------------------------------------------------------------------
248 subroutine interchange_sort_real(n,left_end,right_end,list,order)
250 implicit none
251 
252 ! Passed variables
253 integer,intent(in) :: n ! Input vector size
254 integer,intent(in) :: left_end ! Left end of the vector
255 integer,intent(in) :: right_end ! Right end of the vector
256 real(kind_real),intent(inout) :: list(n) ! Vector to sort
257 integer,intent(inout) :: order(n) ! Positions of the elements in the original order
258 
259 ! Local variables
260 integer :: i,j,itemp
261 real(kind_real) :: temp
262 
263 do i=left_end,right_end-1
264  do j=i+1,right_end
265  if (list(i)>list(j)) then
266  temp = list(i)
267  list(i) = list(j)
268  list(j) = temp
269  itemp = order(i)
270  order(i) = order(j)
271  order(j) = itemp
272  end if
273  end do
274 end do
275 
276 end subroutine interchange_sort_real
277 
278 end module tools_qsort
recursive subroutine quick_sort_integer(n, left_end, right_end, list, order)
Definition: tools_qsort.F90:91
subroutine interchange_sort_integer(n, left_end, right_end, list, order)
recursive subroutine qsort_real(n, list, order)
Definition: tools_qsort.F90:67
subroutine interchange_sort_real(n, left_end, right_end, list, order)
recursive subroutine quick_sort_real(n, left_end, right_end, list, order)
recursive subroutine qsort_integer(n, list, order)
Definition: tools_qsort.F90:43
integer, parameter, public kind_real