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