Line data Source code
1 : !> \file mo_orderpack.f90
2 : !> \brief \copybrief mo_orderpack
3 : !> \details \copydetails mo_orderpack
4 :
5 : !> \brief Sort and ranking routines
6 : !> \details
7 : !! This module is the Orderpack 2.0 from Michel Olagnon.
8 : !! It provides order and unconditional, unique, and partial
9 : !! ranking, sorting, and permutation.
10 : !!
11 : !! <b> Unconditional ranking </b>
12 : !!
13 : !! \code{.f90} subroutine MRGRNK (XVALT, IMULT) \endcode
14 : !!
15 : !! Ranks array XVALT into index array IRNGT, using merge-sort.
16 : !! For performance reasons, the first 2 passes are taken out of the
17 : !! standard loop, and use dedicated coding.
18 : !!
19 : !! \code{.f90} subroutine MRGREF (XVALT, IRNGT) \endcode
20 : !!
21 : !! Ranks array XVALT into index array
22 : !! IRNGT, using merge-sort. This version is not optimized for performance,
23 : !! and is thus not as difficult to read as the previous one.
24 : !!
25 : !! <b> Partial ranking </b>
26 : !!
27 : !! \code{.f90} subroutine RNKPAR (XVALT, IRNGT, NORD) \endcode
28 : !!
29 : !! Ranks partially XVALT by IRNGT,
30 : !! up to order NORD (refined for speed). This routine uses a pivoting
31 : !! strategy such as the one of finding the median based on the quicksort
32 : !! algorithm, but we skew the pivot choice to try to bring it to NORD as
33 : !! fast as possible. It uses 2 temporary arrays, one where it stores the
34 : !! indices of the values smaller than the pivot, and the other for the
35 : !! indices of values larger than the pivot that we might still need later
36 : !! on. It iterates until it can bring the number of values in ILOWT to
37 : !! exactly NORD, and then uses an insertion sort to rank this set, since
38 : !! it is supposedly small.
39 : !!
40 : !! \code{.f90} subroutine RAPKNR (XVALT, IRNGT, NORD) \endcode
41 : !!
42 : !! Same as RNKPAR, but in
43 : !! decreasing order (RAPKNR = RNKPAR spelt backwards).
44 : !!
45 : !! \code{.f90} subroutine REFPAR (XVALT, IRNGT, NORD) \endcode
46 : !!
47 : !! Ranks partially XVALT by IRNGT,
48 : !! up to order NORD This version is not optimized for performance, and is
49 : !! thus not as difficult to read as some other ones. It uses a pivoting
50 : !! strategy such as the one of finding the median based on the quicksort
51 : !! algorithm. It uses a temporary array, where it stores the partially
52 : !! ranked indices of the values. It iterates until it can bring the
53 : !! number of values lower than the pivot to exactly NORD, and then uses
54 : !! an insertion sort to rank this set, since it is supposedly small.
55 : !!
56 : !! \code{.f90} subroutine RINPAR (XVALT, IRNGT, NORD) \endcode
57 : !!
58 : !! Ranks partially XVALT by IRNGT,
59 : !! up to order NORD This version is not optimized for performance, and is
60 : !! thus not as difficult to read as some other ones. It uses insertion
61 : !! sort, limiting insertion to the first NORD values. It does not use any
62 : !! work array and is faster when NORD is very small (2-5), but worst case
63 : !! behavior (intially inverse sorted) can easily happen. In many cases,
64 : !! the refined quicksort method is faster.
65 : !!
66 : !! \code{.f90} integer function INDNTH (XVALT, NORD) \endcode
67 : !!
68 : !! Returns the index of the NORDth
69 : !! value of XVALT (in increasing order) This routine uses a pivoting
70 : !! strategy such as the one of finding the median based on the quicksort
71 : !! algorithm, but we skew the pivot choice to try to bring it to NORD as
72 : !! fast as possible. It uses 2 temporary arrays, one where it stores the
73 : !! indices of the values smaller than the pivot, and the other for the
74 : !! indices of values larger than the pivot that we might still need later
75 : !! on. It iterates until it can bring the number of values in ILOWT to
76 : !! exactly NORD, and then takes out the original index of the maximum
77 : !! value in this set.
78 : !!
79 : !! \code{.f90} subroutine INDMED (XVALT, INDM) \endcode
80 : !!
81 : !! Returns the index of the median
82 : !! (((Size(XVALT)+1))/2th value) of XVALT This routine uses the recursive
83 : !! procedure described in Knuth, The Art of Computer Programming, vol. 3,
84 : !! 5.3.3 - This procedure is linear in time, and does not require to be
85 : !! able to interpolate in the set as the one used in INDNTH. It also has
86 : !! better worst case behavior than INDNTH, but is about 10% slower in
87 : !! average for random uniformly distributed values.
88 : !!
89 : !! Note that in Orderpack 1.0, this routine was a Function procedure, and
90 : !! is now changed to a Subroutine.
91 : !!
92 : !! <b> Unique ranking </b>
93 : !!
94 : !! \code{.f90} subroutine UNIRNK (XVALT, IRNGT, NUNI) \endcode
95 : !!
96 : !! Ranks an array, removing
97 : !! duplicate entries (uses merge sort). The routine is similar to pure
98 : !! merge-sort ranking, but on the last pass, it discards indices that
99 : !! correspond to duplicate entries. For performance reasons, the first 2
100 : !! passes are taken out of the standard loop, and use dedicated coding.
101 : !!
102 : !! \code{.f90} subroutine UNIPAR (XVALT, IRNGT, NORD) \endcode
103 : !!
104 : !! Ranks partially XVALT by IRNGT,
105 : !! up to order NORD at most, removing duplicate entries This routine uses
106 : !! a pivoting strategy such as the one of finding the median based on the
107 : !! quicksort algorithm, but we skew the pivot choice to try to bring it
108 : !! to NORD as quickly as possible. It uses 2 temporary arrays, one where
109 : !! it stores the indices of the values smaller than the pivot, and the
110 : !! other for the indices of values larger than the pivot that we might
111 : !! still need later on. It iterates until it can bring the number of
112 : !! values in ILOWT to exactly NORD, and then uses an insertion sort to
113 : !! rank this set, since it is supposedly small. At all times, the NORD
114 : !! first values in ILOWT correspond to distinct values of the input
115 : !! array.
116 : !!
117 : !! \code{.f90} subroutine UNIINV (XVALT, IGOEST) \endcode
118 : !!
119 : !! Inverse ranking of an array, with
120 : !! removal of duplicate entries The routine is similar to pure merge-sort
121 : !! ranking, but on the last pass, it sets indices in IGOEST to the rank
122 : !! of the original value in an ordered set with duplicates removed. For
123 : !! performance reasons, the first 2 passes are taken out of the standard
124 : !! loop, and use dedicated coding.
125 : !!
126 : !! \code{.f90} subroutine MULCNT (XVALT, IMULT) \endcode
127 : !!
128 : !! Gives, for each array value, its
129 : !! multiplicity The number of times that a value appears in the array is
130 : !! computed by using inverse ranking, counting for each rank the number
131 : !! of values that ``collide'' to this rank, and returning this sum to the
132 : !! locations in the original set. Uses subroutine UNIINV.
133 : !!
134 : !! <b> Random permutation: an interesting use of ranking </b>
135 : !!
136 : !! A variation of the following problem was raised on the internet
137 : !! sci.math.num-analysis news group: Given an array, I would like to find
138 : !! a random permutation of this array that I could control with a
139 : !! "nearbyness" parameter so that elements stay close to their initial
140 : !! locations. The "nearbyness" parameter ranges from 0 to 1, with 0
141 : !! such that no element moves from its initial location, and 1 such that
142 : !! the permutation is fully random.
143 : !!
144 : !! \code{.f90} subroutine CTRPER (XVALT, PCLS) \endcode
145 : !!
146 : !! Permute array XVALT randomly, but
147 : !! leaving elements close to their initial locations The routine takes
148 : !! the 1...size(XVALT) index array as real values, takes a combination of
149 : !! these values and of random values as a perturbation of the index
150 : !! array, and sorts the initial set according to the ranks of these
151 : !! perturbated indices. The relative proportion of initial order and
152 : !! random order is 1-PCLS / PCLS, thus when PCLS = 0, there is no change
153 : !! in the order whereas the new order is fully random when PCLS = 1. Uses
154 : !! subroutine MRGRNK.
155 : !!
156 : !! The above solution found another application when I was asked the
157 : !! following question: I am given two arrays, representing parents'
158 : !! incomes and their children's incomes, but I do not know which parents
159 : !! correspond to which children. I know from an independent source the
160 : !! value of the correlation coefficient between the incomes of the
161 : !! parents and of their children. I would like to pair the elements of
162 : !! these arrays so that the given correlation coefficient is attained,
163 : !! i.e. to reconstruct a realistic dataset, though very likely not to be
164 : !! the true one.
165 : !!
166 : !! \code{.f90} program GIVCOR \endcode
167 : !!
168 : !! Given two arrays of equal length of unordered values,
169 : !! find a "matching value" in the second array for each value in the
170 : !! first so that the global correlation coefficient reaches exactly a
171 : !! given target The routine first sorts the two arrays, so as to get the
172 : !! match of maximum possible correlation. It then iterates, applying the
173 : !! random permutation algorithm of controlled disorder ctrper to the
174 : !! second array. When the resulting correlation goes beyond (lower than)
175 : !! the target correlation, one steps back and reduces the disorder
176 : !! parameter of the permutation. When the resulting correlation lies
177 : !! between the current one and the target, one replaces the array with
178 : !! the newly permuted one. When the resulting correlation increases from
179 : !! the current value, one increases the disorder parameter. That way, the
180 : !! target correlation is approached from above, by a controlled increase
181 : !! in randomness. Since full randomness leads to zero correlation, the
182 : !! iterations meet the desired coefficient at some point. It may be noted
183 : !! that there could be some cases when one would get stuck in a sort of
184 : !! local minimum, where local perturbations cannot further reduce the
185 : !! correlation and where global ones lead to overpass the target. It
186 : !! seems easier to restart the program with a different seed when this
187 : !! occurs than to design an avoidance scheme. Also, should a negative
188 : !! correlation be desired, the program should be modified to start with
189 : !! one array in reverse order with respect to the other, i.e. coorelation
190 : !! as close to -1 as possible.
191 : !!
192 : !! <b> Full sorting </b>
193 : !!
194 : !! \code{.f90} subroutine INSSOR (XVALT) \endcode
195 : !!
196 : !! Sorts XVALT into increasing order (Insertion
197 : !! sort) This subroutine uses insertion sort. It does not use any work
198 : !! array and is faster when XVALT is of very small size (< 20), or
199 : !! already almost sorted, but worst case behavior (intially inverse
200 : !! sorted) can easily happen. In most cases, the quicksort or merge sort
201 : !! method is faster.
202 : !!
203 : !! \code{.f90} subroutine REFSOR (XVALT) \endcode
204 : !!
205 : !! Sorts XVALT into increasing order (Quick
206 : !! sort) This version is not optimized for performance, and is thus not
207 : !! as difficult to read as some other ones. This subroutine uses
208 : !! quicksort in a recursive implementation, and insertion sort for the
209 : !! last steps with small subsets. It does not use any work array
210 : !!
211 : !! <b> Partial sorting </b>
212 : !!
213 : !! \code{.f90} subroutine INSPAR (XVALT, NORD) \endcode
214 : !!
215 : !! Sorts partially XVALT, bringing the
216 : !! NORD lowest values at the begining of the array. This subroutine uses
217 : !! insertion sort, limiting insertion to the first NORD values. It does
218 : !! not use any work array and is faster when NORD is very small (2-5),
219 : !! but worst case behavior can happen fairly probably (initially inverse
220 : !! sorted). In many cases, the refined quicksort method is faster.
221 : !!
222 : !! \code{.f90} function FNDNTH (XVALT, NORD) \endcode
223 : !!
224 : !! Finds out and returns the NORDth value
225 : !! in XVALT (ascending order) This subroutine uses insertion sort,
226 : !! limiting insertion to the first NORD values, and even less when one
227 : !! can know that the value that is considered will not be the NORDth. It
228 : !! uses only a work array of size NORD and is faster when NORD is very
229 : !! small (2-5), but worst case behavior can happen fairly probably
230 : !! (initially inverse sorted). In many cases, the refined quicksort
231 : !! method implemented by VALNTH / INDNTH is faster, though much more
232 : !! difficult to read and understand.
233 : !!
234 : !! \code{.f90} function VALNTH (XVALT, NORD) \endcode
235 : !!
236 : !! Finds out and returns the NORDth value
237 : !! in XVALT (ascending order) This subroutine simply calls INDNTH.
238 : !!
239 : !! \code{.f90} function VALMED (XVALT) \endcode
240 : !!
241 : !! Finds out and returns the median(((Size(XVALT)+1))/2th value) of XVALT This routine uses the recursive
242 : !! procedure described in Knuth, The Art of Computer Programming, vol. 3,
243 : !! 5.3.3 - This procedure is linear in time, and does not require to be
244 : !! able to interpolate in the set as the one used in VALNTH/INDNTH. It
245 : !! also has better worst case behavior than VALNTH/INDNTH, and is about
246 : !! 20% faster in average for random uniformly distributed values.
247 : !!
248 : !! \code{.f90} function OMEDIAN (XVALT) \endcode
249 : !!
250 : !! It is a modified version of VALMED that
251 : !! provides the average between the two middle values in the case
252 : !! Size(XVALT) is even.
253 : !!
254 : !! <b> Unique sorting </b>
255 : !!
256 : !! \code{.f90} subroutine UNISTA (XVALT, NUNI) \endcode
257 : !!
258 : !! Removes duplicates from an array This
259 : !! subroutine uses merge sort unique inverse ranking. It leaves in the
260 : !! initial set only those entries that are unique, packing the array, and
261 : !! leaving the order of the retained values unchanged.
262 : !> \authors Michel Olagnon
263 : !> \date 2000-2012
264 : !> \changelog
265 : !! - Matthias Cuntz, Apr 2014
266 : !! - adapted to UFZ library
267 : !! - one module, cleaned all warnings
268 : !! - Juliane Mai, Nov 2014
269 : !! - replaced floating comparison by ne(), eq(), etc. from mo_utils
270 : !! - Matthias Cuntz, Jul 2015
271 : !! - median -> omedian
272 : !> \copyright Copyright 2005-\today, the CHS Developers, Sabine Attinger: All rights reserved.
273 : !! FORCES is released under the LGPLv3+ license \license_note
274 : MODULE mo_orderpack
275 :
276 : USE mo_kind, ONLY : i4, sp, dp
277 : USE mo_utils, ONLY : ne, eq, le
278 :
279 : IMPLICIT NONE
280 :
281 : ! Public routines
282 : public :: sort ! alias for refsor
283 : public :: sort_index ! wrapper for mrgrnk
284 :
285 : public :: ctrper
286 : public :: fndnth
287 : public :: indmed
288 : public :: indnth
289 : public :: inspar
290 : public :: inssor
291 : public :: omedian
292 : public :: mrgref
293 : public :: mrgrnk
294 : public :: mulcnt
295 : public :: rapknr
296 : public :: refpar
297 : public :: refsor
298 : public :: rinpar
299 : public :: rnkpar
300 : public :: uniinv
301 : public :: unipar
302 : public :: unirnk
303 : public :: unista
304 : public :: valmed
305 : public :: valnth
306 :
307 : ! aliases/wrapper
308 :
309 : !> \brief Sorts the input array in ascending order.
310 : !> \param[in,out] "real(sp/dp) :: arr(:)" On input: unsorted 1D-array\n
311 : !! On output: ascendingly sorted input array
312 : interface sort
313 : module procedure d_refsor, r_refsor, i_refsor, c_refsor
314 : end interface sort
315 :
316 : !> \brief Gives the indeces that would sort an array in ascending order.
317 : !> \param[in] "real(sp/dp) :: arr(:)" Unsorted 1D-array
318 : !> \return integer(i4) :: indices(:) — Indices that would sort arr in ascending order
319 : interface sort_index
320 : module procedure sort_index_dp, sort_index_sp, sort_index_i4
321 : end interface sort_index
322 :
323 : !> \brief Random permutation ranking.
324 :
325 : !> \details
326 : !! Permute array XVALT randomly, but
327 : !! leaving elements close to their initial locations The routine takes
328 : !! the 1...size(XVALT) index array as real values, takes a combination of
329 : !! these values and of random values as a perturbation of the index
330 : !! array, and sorts the initial set according to the ranks of these
331 : !! perturbated indices. The relative proportion of initial order and
332 : !! random order is 1-PCLS / PCLS, thus when PCLS = 0, there is no change
333 : !! in the order whereas the new order is fully random when PCLS = 1. Uses
334 : !! subroutine MRGRNK.
335 : !!
336 : !! The above solution found another application when I was asked the
337 : !! following question: I am given two arrays, representing parents'
338 : !! incomes and their children's incomes, but I do not know which parents
339 : !! correspond to which children. I know from an independent source the
340 : !! value of the correlation coefficient between the incomes of the
341 : !! parents and of their children. I would like to pair the elements of
342 : !! these arrays so that the given correlation coefficient is attained,
343 : !! i.e. to reconstruct a realistic dataset, though very likely not to be
344 : !! the true one.
345 :
346 : !> \param[inout] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be randomly permuted.
347 : !> \param[in] "integer(i4)/real(sp,dp) :: PCLS" Nearbyness of permutation.
348 :
349 : interface ctrper
350 : module procedure d_ctrper, r_ctrper, i_ctrper
351 : end interface ctrper
352 :
353 : !> \brief Find N-th value in array from insertion sort
354 :
355 : !> \details
356 : !! Finds out and returns the NORDth value
357 : !! in XVALT (ascending order). This subroutine uses insertion sort,
358 : !! limiting insertion to the first NORD values, and even less when one
359 : !! can know that the value that is considered will not be the NORDth. It
360 : !! uses only a work array of size NORD and is faster when NORD is very
361 : !! small (2-5), but worst case behavior can happen fairly probably
362 : !! (initially inverse sorted). In many cases, the refined quicksort
363 : !! method implemented by VALNTH / INDNTH is faster, though much more
364 : !! difficult to read and understand.
365 :
366 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
367 : !> \param[in] "integer(i4) :: NORD" Number of ranked elements.
368 : !> \retval "integer(i4)/real(sp,dp) :: FNDNTH" Value of NORDth rank.
369 :
370 : interface fndnth
371 : module procedure d_fndnth, r_fndnth, i_fndnth
372 : end interface fndnth
373 :
374 : !> \brief Median index of skewed-pivot with quicksort ranking.
375 :
376 : !> \details
377 : !! Returns the index of the median
378 : !! `(((Size(XVALT)+1))/2th value)` of XVALT This routine uses the recursive
379 : !! procedure described in Knuth, The Art of Computer Programming, vol. 3,
380 : !! 5.3.3 - This procedure is linear in time, and does not require to be
381 : !! able to interpolate in the set as the one used in INDNTH. It also has
382 : !! better worst case behavior than INDNTH, but is about 10% slower in
383 : !! average for random uniformly distributed values.\n
384 : !! Note that in Orderpack 1.0, this routine was a Function procedure, and
385 : !! is now changed to a Subroutine.
386 :
387 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
388 : !> \param[out] "integer(i4) :: INDM" Index of Median.
389 :
390 : interface indmed
391 : module procedure d_indmed, r_indmed, i_indmed
392 : end interface indmed
393 :
394 : !> \brief Nth index of skewed-pivot with quicksort ranking.
395 :
396 : !> \details
397 : !! Returns the index of the NORDth
398 : !! value of XVALT (in increasing order). This routine uses a pivoting
399 : !! strategy such as the one of finding the median based on the quicksort
400 : !! algorithm, but we skew the pivot choice to try to bring it to NORD as
401 : !! fast as possible. It uses 2 temporary arrays, one where it stores the
402 : !! indices of the values smaller than the pivot, and the other for the
403 : !! indices of values larger than the pivot that we might still need later
404 : !! on. It iterates until it can bring the number of values in ILOWT to
405 : !! exactly NORD, and then takes out the original index of the maximum
406 : !! value in this set.
407 :
408 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
409 : !> \param[in] "integer(i4) :: NORD" Number of ranked elements.
410 : !> \retval "integer(i4) :: INDNTH" Index of NORDth rank.
411 :
412 : interface indnth
413 : module procedure d_indnth, r_indnth, i_indnth
414 : end interface indnth
415 :
416 : !> \brief Partial insertion sort ranking,
417 :
418 : !> \details
419 : !! Sorts partially XVALT, bringing the
420 : !! NORD lowest values at the begining of the array. This subroutine uses
421 : !! insertion sort, limiting insertion to the first NORD values. It does
422 : !! not use any work array and is faster when NORD is very small (2-5),
423 : !! but worst case behavior can happen fairly probably (initially inverse
424 : !! sorted). In many cases, the refined quicksort method is faster.
425 :
426 : !> \param[inout] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
427 : !> \param[in] "integer(i4) :: NORD" Number of ranked elements from beginning of array.
428 :
429 : interface inspar
430 : module procedure d_inspar, r_inspar, i_inspar
431 : end interface inspar
432 :
433 : !> \brief Insertion sort ranking
434 :
435 : !> \details
436 : !! Sorts XVALT into increasing order (Insertion
437 : !! sort) This subroutine uses insertion sort. It does not use any work
438 : !! array and is faster when XVALT is of very small size (< 20), or
439 : !! already almost sorted, but worst case behavior (intially inverse
440 : !! sorted) can easily happen. In most cases, the quicksort or merge sort
441 : !! method is faster.
442 :
443 : !> \param[inout] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
444 :
445 : interface inssor
446 : module procedure d_inssor, r_inssor, i_inssor, c_inssor
447 : end interface inssor
448 :
449 : !> \brief Find median value of array (case for even elements)
450 :
451 : !> \details
452 : !! It is a modified version of VALMED that
453 : !! provides the average between the two middle values in the case
454 : !! Size(XVALT) is even.
455 :
456 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
457 : !> \retval "integer(i4)/real(sp,dp) :: OMEDIAN" Value of median.
458 :
459 : interface omedian
460 : module procedure d_median, r_median, i_median
461 : end interface omedian
462 :
463 : !> \brief Merge-sort ranking (unoptimized)
464 :
465 : !> \details
466 : !! Ranks array XVALT into index array
467 : !! IRNGT, using merge-sort. This version is not optimized for performance,
468 : !! and is thus not as difficult to read as the previous one.
469 :
470 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
471 : !> \retval "integer(i4), dimension(:) :: IRNGT" Index of rank.
472 :
473 : interface mrgref
474 : module procedure d_mrgref, r_mrgref, i_mrgref
475 : end interface mrgref
476 :
477 : !> \brief Merge-sort ranking
478 :
479 : !> \details
480 : !! Ranks array XVALT into index array IRNGT, using merge-sort.\n
481 : !! For performance reasons, the first 2 passes are taken out of the
482 : !! standard loop, and use dedicated coding.
483 :
484 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
485 : !> \retval "integer(i4), dimension(:) :: IRNGT" Index of rank.
486 :
487 : interface mrgrnk
488 : module procedure D_mrgrnk, R_mrgrnk, I_mrgrnk, C_mrgrnk
489 : end interface mrgrnk
490 :
491 : !> \brief Multiplicity of array values.
492 :
493 : !> \details
494 : !! Gives, for each array value, its
495 : !! multiplicity. The number of times that a value appears in the array is
496 : !! computed by using inverse ranking, counting for each rank the number
497 : !! of values that ``collide'' to this rank, and returning this sum to the
498 : !! locations in the original set. Uses subroutine UNIINV.
499 :
500 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
501 : !> \param[out] "integer(i4), dimension(:) :: IMULT" Multiplicity of array values.
502 :
503 :
504 : interface mulcnt
505 : module procedure d_mulcnt, r_mulcnt, i_mulcnt
506 : end interface mulcnt
507 :
508 : !> \brief Skewed-pivot with quicksort ranking (reversed).
509 :
510 : !> \details
511 : !! Same as `RNKPAR`, but in
512 : !! decreasing order (RAPKNR = RNKPAR spelt backwards).
513 :
514 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
515 : !> \param[in] "integer(i4) :: NORD" Number of ranked elements.
516 : !> \retval "integer(i4), dimension(:) :: IRNGT" Index of rank.
517 :
518 : interface rapknr
519 : module procedure d_rapknr, r_rapknr, i_rapknr
520 : end interface rapknr
521 :
522 : !> \brief Skewed-pivot with quicksort ranking (unoptimized).
523 :
524 : !> \details
525 : !! Ranks partially XVALT by IRNGT,
526 : !! up to order NORD. This version is not optimized for performance, and is
527 : !! thus not as difficult to read as some other ones. It uses a pivoting
528 : !! strategy such as the one of finding the median based on the quicksort
529 : !! algorithm. It uses a temporary array, where it stores the partially
530 : !! ranked indices of the values. It iterates until it can bring the
531 : !! number of values lower than the pivot to exactly NORD, and then uses
532 : !! an insertion sort to rank this set, since it is supposedly small.
533 :
534 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
535 : !> \param[in] "integer(i4) :: NORD" Number of ranked elements.
536 : !> \retval "integer(i4), dimension(:) :: IRNGT" Index of rank.
537 :
538 : interface refpar
539 : module procedure d_refpar, r_refpar, i_refpar
540 : end interface refpar
541 :
542 : !> \brief Quicksort ranking, with insertion sort at last step (unoptimized)
543 :
544 : !> \details
545 : !! Sorts XVALT into increasing order (Quick
546 : !! sort). This version is not optimized for performance, and is thus not
547 : !! as difficult to read as some other ones. This subroutine uses
548 : !! quicksort in a recursive implementation, and insertion sort for the
549 : !! last steps with small subsets. It does not use any work array
550 :
551 : !> \param[inout] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
552 :
553 : interface refsor
554 : module procedure d_refsor, r_refsor, i_refsor, c_refsor
555 : end interface refsor
556 :
557 : !> \brief Insertion sort ranking (unoptimized).
558 :
559 : !> \details
560 : !! Ranks partially XVALT by IRNGT,
561 : !! up to order NORD This version is not optimized for performance, and is
562 : !! thus not as difficult to read as some other ones. It uses insertion
563 : !! sort, limiting insertion to the first NORD values. It does not use any
564 : !! work array and is faster when NORD is very small (2-5), but worst case
565 : !! behavior (intially inverse sorted) can easily happen. In many cases,
566 : !! refined quicksort method is faster.
567 :
568 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
569 : !> \param[in] "integer(i4) :: NORD" Number of ranked elements.
570 : !> \retval "integer(i4), dimension(:) :: IRNGT" Index of rank.
571 :
572 : interface rinpar
573 : module procedure d_rinpar, r_rinpar, i_rinpar
574 : end interface rinpar
575 :
576 : !> \brief Skewed-pivot with quicksort ranking.
577 :
578 : !> \details
579 : !! Ranks partially XVALT by IRNGT,
580 : !! up to order NORD (refined for speed). This routine uses a pivoting
581 : !! strategy such as the one of finding the median based on the quicksort
582 : !! algorithm, but we skew the pivot choice to try to bring it to NORD as
583 : !! fast as possible. It uses 2 temporary arrays, one where it stores the
584 : !! indices of the values smaller than the pivot, and the other for the
585 : !! indices of values larger than the pivot that we might still need later
586 : !! on. It iterates until it can bring the number of values in ILOWT to
587 : !! exactly NORD, and then uses an insertion sort to rank this set, since
588 : !! it is supposedly small.
589 :
590 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
591 : !> \param[in] "integer(i4) :: NORD" Number of ranked elements.
592 : !> \retval "integer(i4), dimension(:) :: IRNGT" Index of rank.
593 :
594 : interface rnkpar
595 : module procedure d_rnkpar, r_rnkpar, i_rnkpar
596 : end interface rnkpar
597 :
598 : !> \brief Merge-sort ranking, with removal of duplicate entries (reversed).
599 :
600 : !> \details
601 : !! Inverse ranking of an array, with
602 : !! removal of duplicate entries. The routine is similar to pure merge-sort
603 : !! ranking, but on the last pass, it sets indices in IGOEST to the rank
604 : !! of the original value in an ordered set with duplicates removed. For
605 : !! performance reasons, the first 2 passes are taken out of the standard
606 : !! loop, and use dedicated coding.
607 :
608 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
609 : !> \param[out] "integer(i4), dimension(:) :: IGOEST" Index of rank.
610 :
611 : interface uniinv
612 : module procedure d_uniinv, r_uniinv, i_uniinv
613 : end interface uniinv
614 : interface nearless
615 : module procedure D_nearless, R_nearless, I_nearless
616 : end interface nearless
617 :
618 : !> \brief Partial quicksort/insertion sort ranking, with removal of duplicate entries.
619 :
620 : !> \details
621 : !! Ranks partially XVALT by IRNGT,
622 : !! up to order NORD at most, removing duplicate entries. This routine uses
623 : !! a pivoting strategy such as the one of finding the median based on the
624 : !! quicksort algorithm, but we skew the pivot choice to try to bring it
625 : !! to NORD as quickly as possible. It uses 2 temporary arrays, one where
626 : !! it stores the indices of the values smaller than the pivot, and the
627 : !! other for the indices of values larger than the pivot that we might
628 : !! still need later on. It iterates until it can bring the number of
629 : !! values in ILOWT to exactly NORD, and then uses an insertion sort to
630 : !! rank this set, since it is supposedly small. At all times, the NORD
631 : !! first values in ILOWT correspond to distinct values of the input
632 : !! array.
633 :
634 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
635 : !> \param[in] "integer(i4) :: NORD" Rank of quicksort ranking.
636 : !> \param[out] "integer(i4), dimension(:) :: IRNGT" Index of rank.
637 :
638 : interface unipar
639 : module procedure d_unipar, r_unipar, i_unipar
640 : end interface unipar
641 :
642 : !> \brief Merge-sort ranking, with removal of duplicate entries.
643 :
644 : !> \details
645 : !! Ranks an array, removing
646 : !! duplicate entries (uses merge sort). The routine is similar to pure
647 : !! merge-sort ranking, but on the last pass, it discards indices that
648 : !! correspond to duplicate entries. For performance reasons, the first 2
649 : !! passes are taken out of the standard loop, and use dedicated coding.
650 :
651 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
652 : !> \param[out] "integer(i4) :: NUNI" Rank of last number after duplicates removed.
653 : !> \param[out] "integer(i4), dimension(:) :: IRNGT" Index of rank.
654 :
655 : interface unirnk
656 : module procedure D_unirnk, R_unirnk, I_unirnk
657 : end interface unirnk
658 :
659 : !> \brief Merge-sort unique inverse ranking.
660 :
661 : !> \details
662 : !! Removes duplicates from an array This
663 : !! subroutine uses merge sort unique inverse ranking. It leaves in the
664 : !! initial set only those entries that are unique, packing the array, and
665 : !! leaving the order of the retained values unchanged.
666 :
667 : !> \param[inout] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
668 : !> \param[out] "integer(i4) :: NUNI" Rank of last number after duplicates removed.
669 :
670 : interface unista
671 : module procedure d_unista, r_unista, i_unista
672 : end interface unista
673 :
674 : !> \brief Find median value of array
675 :
676 : !> \details
677 : !! Finds out and returns the median(((Size(XVALT)+1))/2th value) of XVALT This routine uses the recursive
678 : !! procedure described in Knuth, The Art of Computer Programming, vol. 3,
679 : !! 5.3.3 - This procedure is linear in time, and does not require to be
680 : !! able to interpolate in the set as the one used in VALNTH/INDNTH. It
681 : !! also has better worst case behavior than VALNTH/INDNTH, and is about
682 : !! 20% faster in average for random uniformly distributed values.
683 :
684 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
685 : !> \retval "integer(i4)/real(sp,dp) :: VALMED" Value of median.
686 :
687 : interface valmed
688 : module procedure d_valmed, r_valmed, i_valmed
689 : end interface valmed
690 :
691 : !> \brief Find N-th value in array from quicksort
692 :
693 : !> \details
694 : !! Finds out and returns the NORDth value
695 : !! in XVALT (ascending order). This subroutine simply calls INDNTH.
696 :
697 : !> \param[in] "integer(i4)/real(sp,dp), dimension(:) :: XVALT" Array to be ranked.
698 : !> \param[in] "integer(i4) :: NORD" Number of ranked elements.
699 : !> \retval "integer(i4)/real(sp,dp) :: VALNTH" Value of NORDth rank.
700 :
701 : interface valnth
702 : module procedure d_valnth, r_valnth, i_valnth
703 : end interface valnth
704 :
705 : private :: R_ctrper, I_ctrper, D_ctrper
706 : private :: R_fndnth, I_fndnth, D_fndnth
707 : private :: R_indmed, I_indmed, D_indmed
708 : private :: R_indnth, I_indnth, D_indnth
709 : private :: R_inspar, I_inspar, D_inspar
710 : private :: R_inssor, I_inssor, D_inssor, C_inssor
711 : private :: R_median, I_median, D_median
712 : private :: R_mrgref, I_mrgref, D_mrgref
713 : private :: R_mrgrnk, I_mrgrnk, D_mrgrnk
714 : private :: R_mulcnt, I_mulcnt, D_mulcnt
715 : private :: R_nearless, I_nearless, D_nearless, nearless
716 : private :: R_rapknr, I_rapknr, D_rapknr
717 : private :: R_refpar, I_refpar, D_refpar
718 : private :: R_refsor, I_refsor, D_refsor, C_refsor
719 : private :: R_rinpar, I_rinpar, D_rinpar
720 : private :: R_rnkpar, I_rnkpar, D_rnkpar
721 : private :: R_subsor, I_subsor, D_subsor, C_subsor
722 : private :: R_uniinv, I_uniinv, D_uniinv
723 : private :: R_unipar, I_unipar, D_unipar
724 : private :: R_unirnk, I_unirnk, D_unirnk
725 : private :: R_unista, I_unista, D_unista
726 : private :: R_valmed, I_valmed, D_valmed
727 : private :: R_valnth, I_valnth, D_valnth
728 : private :: r_med, i_med, d_med
729 :
730 : PRIVATE
731 :
732 : Integer(kind = i4), Allocatable, Dimension(:), Save :: IDONT
733 :
734 : CONTAINS
735 :
736 : ! ------------------------------------------------------------------
737 :
738 9008 : FUNCTION sort_index_dp(arr)
739 :
740 : IMPLICIT NONE
741 :
742 : REAL(dp), DIMENSION(:), INTENT(IN) :: arr
743 : INTEGER(i4), DIMENSION(size(arr)) :: sort_index_dp
744 :
745 4504 : call mrgrnk(arr, sort_index_dp)
746 :
747 4504 : END FUNCTION sort_index_dp
748 :
749 4506 : FUNCTION sort_index_sp(arr)
750 :
751 : IMPLICIT NONE
752 :
753 : REAL(sp), DIMENSION(:), INTENT(IN) :: arr
754 : INTEGER(i4), DIMENSION(size(arr)) :: sort_index_sp
755 :
756 1 : call mrgrnk(arr, sort_index_sp)
757 :
758 1 : END FUNCTION sort_index_sp
759 :
760 1 : FUNCTION sort_index_i4(arr)
761 :
762 : IMPLICIT NONE
763 :
764 : integer(i4), DIMENSION(:), INTENT(IN) :: arr
765 : INTEGER(i4), DIMENSION(size(arr)) :: sort_index_i4
766 :
767 0 : call mrgrnk(arr, sort_index_i4)
768 :
769 0 : END FUNCTION sort_index_i4
770 :
771 :
772 : ! ------------------------------------------------------------------
773 :
774 0 : Subroutine D_ctrper (XDONT, PCLS)
775 : ! Permute array XVALT randomly, but leaving elements close
776 : ! to their initial locations (nearbyness is controled by PCLS).
777 : ! _________________________________________________________________
778 : ! The routine takes the 1...size(XVALT) index array as real
779 : ! values, takes a combination of these values and of random
780 : ! values as a perturbation of the index array, and sorts the
781 : ! initial set according to the ranks of these perturbated indices.
782 : ! The relative proportion of initial order and random order
783 : ! is 1-PCLS / PCLS, thus when PCLS = 0, there is no change in
784 : ! the order whereas the new order is fully random when PCLS = 1.
785 : ! Michel Olagnon - May 2000.
786 : ! _________________________________________________________________
787 : ! __________________________________________________________
788 : real(kind = dp), Dimension (:), Intent (InOut) :: XDONT
789 : Real(kind = dp), Intent (In) :: PCLS
790 : ! __________________________________________________________
791 : !
792 0 : Real(kind = dp), Dimension (Size(XDONT)) :: XINDT
793 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: JWRKT
794 0 : Real(kind = dp) :: PWRK
795 : Integer(kind = i4) :: I
796 0 : Real(kind = dp), Dimension (Size(XDONT)) :: II
797 : !
798 0 : Call Random_number (XINDT(:))
799 0 : PWRK = Min (Max (0.0_dp, PCLS), 1.0_dp)
800 0 : XINDT = Real(Size(XDONT), dp) * XINDT
801 0 : forall(I = 1 : size(XDONT)) II(I) = real(I, dp) ! for gnu compiler to be initialised
802 0 : XINDT = PWRK * XINDT + (1.0_dp - PWRK) * II
803 0 : Call MRGRNK (XINDT, JWRKT)
804 0 : XDONT = XDONT (JWRKT)
805 : !
806 0 : End Subroutine D_ctrper
807 :
808 0 : Subroutine R_ctrper (XDONT, PCLS)
809 : ! Permute array XVALT randomly, but leaving elements close
810 : ! to their initial locations (nearbyness is controled by PCLS).
811 : ! _________________________________________________________________
812 : ! The routine takes the 1...size(XVALT) index array as real
813 : ! values, takes a combination of these values and of random
814 : ! values as a perturbation of the index array, and sorts the
815 : ! initial set according to the ranks of these perturbated indices.
816 : ! The relative proportion of initial order and random order
817 : ! is 1-PCLS / PCLS, thus when PCLS = 0, there is no change in
818 : ! the order whereas the new order is fully random when PCLS = 1.
819 : ! Michel Olagnon - May 2000.
820 : ! _________________________________________________________________
821 : ! _________________________________________________________
822 : Real(kind = sp), Dimension (:), Intent (InOut) :: XDONT
823 : Real(kind = sp), Intent (In) :: PCLS
824 : ! __________________________________________________________
825 : !
826 0 : Real(kind = sp), Dimension (Size(XDONT)) :: XINDT
827 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: JWRKT
828 0 : Real(kind = sp) :: PWRK
829 : Integer(kind = i4) :: I
830 0 : Real(kind = sp), Dimension (Size(XDONT)) :: II
831 : !
832 0 : Call Random_number (XINDT(:))
833 0 : PWRK = Min (Max (0.0, PCLS), 1.0)
834 0 : XINDT = Real(Size(XDONT), sp) * XINDT
835 0 : forall(I = 1 : size(XDONT)) II(I) = real(I, sp) ! for gnu compiler to be initialised
836 0 : XINDT = PWRK * XINDT + (1.0 - PWRK) * II
837 0 : Call MRGRNK (XINDT, JWRKT)
838 0 : XDONT = XDONT (JWRKT)
839 : !
840 0 : End Subroutine R_ctrper
841 :
842 0 : Subroutine I_ctrper (XDONT, PCLS)
843 : ! Permute array XVALT randomly, but leaving elements close
844 : ! to their initial locations (nearbyness is controled by PCLS).
845 : ! _________________________________________________________________
846 : ! The routine takes the 1...size(XVALT) index array as real
847 : ! values, takes a combination of these values and of random
848 : ! values as a perturbation of the index array, and sorts the
849 : ! initial set according to the ranks of these perturbated indices.
850 : ! The relative proportion of initial order and random order
851 : ! is 1-PCLS / PCLS, thus when PCLS = 0, there is no change in
852 : ! the order whereas the new order is fully random when PCLS = 1.
853 : ! Michel Olagnon - May 2000.
854 : ! _________________________________________________________________
855 : ! __________________________________________________________
856 : Integer(kind = i4), Dimension (:), Intent (InOut) :: XDONT
857 : Real(kind = sp), Intent (In) :: PCLS
858 : ! __________________________________________________________
859 : !
860 0 : Real(kind = sp), Dimension (Size(XDONT)) :: XINDT
861 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: JWRKT
862 0 : Real(kind = sp) :: PWRK
863 : Integer(kind = i4) :: I
864 0 : Real(kind = sp), Dimension (Size(XDONT)) :: II
865 : !
866 0 : Call Random_number (XINDT(:))
867 0 : PWRK = Min (Max (0.0, PCLS), 1.0)
868 0 : XINDT = Real(Size(XDONT), sp) * XINDT
869 0 : forall(I = 1 : size(XDONT)) II(I) = real(I, sp) ! for gnu compiler to be initialised
870 0 : XINDT = PWRK * XINDT + (1.0 - PWRK) * II
871 0 : Call MRGRNK(XINDT, JWRKT)
872 0 : XDONT = XDONT(JWRKT)
873 : !
874 0 : End Subroutine I_ctrper
875 :
876 0 : Function D_fndnth (XDONT, NORD) Result (FNDNTH)
877 : ! Return NORDth value of XDONT, i.e fractile of order NORD/SIZE(XDONT).
878 : ! ______________________________________________________________________
879 : ! This subroutine uses insertion sort, limiting insertion
880 : ! to the first NORD values. It is faster when NORD is very small (2-5),
881 : ! and it requires only a workarray of size NORD and type of XDONT,
882 : ! but worst case behavior can happen fairly probably (initially inverse
883 : ! sorted). In many cases, the refined quicksort method is faster.
884 : ! Michel Olagnon - Aug. 2000
885 : ! __________________________________________________________
886 : ! __________________________________________________________
887 : real(Kind = dp), Dimension (:), Intent (In) :: XDONT
888 : real(Kind = dp) :: FNDNTH
889 : Integer(kind = i4), Intent (In) :: NORD
890 : ! __________________________________________________________
891 0 : real(Kind = dp), Dimension (NORD) :: XWRKT
892 0 : real(Kind = dp) :: XWRK, XWRK1
893 : !
894 : !
895 : Integer(kind = i4) :: ICRS, IDCR, ILOW, NDON
896 : !
897 0 : XWRKT (1) = XDONT (1)
898 0 : Do ICRS = 2, NORD
899 0 : XWRK = XDONT (ICRS)
900 0 : Do IDCR = ICRS - 1, 1, - 1
901 0 : If (XWRK >= XWRKT(IDCR)) Exit
902 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
903 : End Do
904 0 : XWRKT (IDCR + 1) = XWRK
905 : End Do
906 : !
907 0 : NDON = SIZE (XDONT)
908 0 : XWRK1 = XWRKT (NORD)
909 0 : ILOW = 2 * NORD - NDON
910 0 : Do ICRS = NORD + 1, NDON
911 0 : If (XDONT(ICRS) < XWRK1) Then
912 0 : XWRK = XDONT (ICRS)
913 0 : Do IDCR = NORD - 1, MAX (1, ILOW), - 1
914 0 : If (XWRK >= XWRKT(IDCR)) Exit
915 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
916 : End Do
917 0 : XWRKT (IDCR + 1) = XWRK
918 0 : XWRK1 = XWRKT(NORD)
919 : End If
920 0 : ILOW = ILOW + 1
921 : End Do
922 0 : FNDNTH = XWRK1
923 :
924 : !
925 0 : End Function D_fndnth
926 :
927 0 : Function R_fndnth (XDONT, NORD) Result (FNDNTH)
928 : ! Return NORDth value of XDONT, i.e fractile of order NORD/SIZE(XDONT).
929 : ! ______________________________________________________________________
930 : ! This subroutine uses insertion sort, limiting insertion
931 : ! to the first NORD values. It is faster when NORD is very small (2-5),
932 : ! and it requires only a workarray of size NORD and type of XDONT,
933 : ! but worst case behavior can happen fairly probably (initially inverse
934 : ! sorted). In many cases, the refined quicksort method is faster.
935 : ! Michel Olagnon - Aug. 2000
936 : ! __________________________________________________________
937 : ! _________________________________________________________
938 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
939 : Real(kind = sp) :: FNDNTH
940 : Integer(kind = i4), Intent (In) :: NORD
941 : ! __________________________________________________________
942 0 : Real(kind = sp), Dimension (NORD) :: XWRKT
943 0 : Real(kind = sp) :: XWRK, XWRK1
944 : !
945 : !
946 : Integer(kind = i4) :: ICRS, IDCR, ILOW, NDON
947 : !
948 0 : XWRKT (1) = XDONT (1)
949 0 : Do ICRS = 2, NORD
950 0 : XWRK = XDONT (ICRS)
951 0 : Do IDCR = ICRS - 1, 1, - 1
952 0 : If (XWRK >= XWRKT(IDCR)) Exit
953 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
954 : End Do
955 0 : XWRKT (IDCR + 1) = XWRK
956 : End Do
957 : !
958 0 : NDON = SIZE (XDONT)
959 0 : XWRK1 = XWRKT (NORD)
960 0 : ILOW = 2 * NORD - NDON
961 0 : Do ICRS = NORD + 1, NDON
962 0 : If (XDONT(ICRS) < XWRK1) Then
963 0 : XWRK = XDONT (ICRS)
964 0 : Do IDCR = NORD - 1, MAX (1, ILOW), - 1
965 0 : If (XWRK >= XWRKT(IDCR)) Exit
966 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
967 : End Do
968 0 : XWRKT (IDCR + 1) = XWRK
969 0 : XWRK1 = XWRKT(NORD)
970 : End If
971 0 : ILOW = ILOW + 1
972 : End Do
973 0 : FNDNTH = XWRK1
974 :
975 : !
976 0 : End Function R_fndnth
977 :
978 0 : Function I_fndnth (XDONT, NORD) Result (FNDNTH)
979 : ! Return NORDth value of XDONT, i.e fractile of order NORD/SIZE(XDONT).
980 : ! ______________________________________________________________________
981 : ! This subroutine uses insertion sort, limiting insertion
982 : ! to the first NORD values. It is faster when NORD is very small (2-5),
983 : ! and it requires only a workarray of size NORD and type of XDONT,
984 : ! but worst case behavior can happen fairly probably (initially inverse
985 : ! sorted). In many cases, the refined quicksort method is faster.
986 : ! Michel Olagnon - Aug. 2000
987 : ! __________________________________________________________
988 : ! __________________________________________________________
989 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
990 : Integer(kind = i4) :: fndnth
991 : Integer(kind = i4), Intent (In) :: NORD
992 : ! __________________________________________________________
993 0 : Integer(kind = i4), Dimension (NORD) :: XWRKT
994 : Integer(kind = i4) :: XWRK, XWRK1
995 : !
996 : !
997 : Integer(kind = i4) :: ICRS, IDCR, ILOW, NDON
998 : !
999 0 : XWRKT (1) = XDONT (1)
1000 0 : Do ICRS = 2, NORD
1001 0 : XWRK = XDONT (ICRS)
1002 0 : Do IDCR = ICRS - 1, 1, - 1
1003 0 : If (XWRK >= XWRKT(IDCR)) Exit
1004 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
1005 : End Do
1006 0 : XWRKT (IDCR + 1) = XWRK
1007 : End Do
1008 : !
1009 0 : NDON = SIZE (XDONT)
1010 0 : XWRK1 = XWRKT (NORD)
1011 0 : ILOW = 2 * NORD - NDON
1012 0 : Do ICRS = NORD + 1, NDON
1013 0 : If (XDONT(ICRS) < XWRK1) Then
1014 0 : XWRK = XDONT (ICRS)
1015 0 : Do IDCR = NORD - 1, MAX (1, ILOW), - 1
1016 0 : If (XWRK >= XWRKT(IDCR)) Exit
1017 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
1018 : End Do
1019 0 : XWRKT (IDCR + 1) = XWRK
1020 0 : XWRK1 = XWRKT(NORD)
1021 : End If
1022 0 : ILOW = ILOW + 1
1023 : End Do
1024 0 : FNDNTH = XWRK1
1025 :
1026 : !
1027 0 : End Function I_fndnth
1028 :
1029 0 : Subroutine D_indmed (XDONT, INDM)
1030 : ! Returns index of median value of XDONT.
1031 : ! __________________________________________________________
1032 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
1033 : Integer(kind = i4), Intent (Out) :: INDM
1034 : ! __________________________________________________________
1035 : Integer(kind = i4) :: IDON
1036 : !
1037 0 : Allocate (IDONT (SIZE(XDONT)))
1038 0 : Do IDON = 1, SIZE(XDONT)
1039 0 : IDONT (IDON) = IDON
1040 : End Do
1041 : !
1042 0 : Call d_med (XDONT, IDONT, INDM)
1043 : !
1044 0 : Deallocate (IDONT)
1045 0 : End Subroutine D_indmed
1046 :
1047 0 : Recursive Subroutine d_med (XDATT, IDATT, ires_med)
1048 : ! Finds the index of the median of XDONT using the recursive procedure
1049 : ! described in Knuth, The Art of Computer Programming,
1050 : ! vol. 3, 5.3.3 - This procedure is linear in time, and
1051 : ! does not require to be able to interpolate in the
1052 : ! set as the one used in INDNTH. It also has better worst
1053 : ! case behavior than INDNTH, but is about 30% slower in
1054 : ! average for random uniformly distributed values.
1055 : ! __________________________________________________________
1056 : real(kind = dp), Dimension (:), Intent (In) :: XDATT
1057 : Integer(kind = i4), Dimension (:), Intent (In) :: IDATT
1058 : Integer(kind = i4), Intent (Out) :: ires_med
1059 : ! __________________________________________________________
1060 : !
1061 : real(kind = dp), Parameter :: XHUGE = HUGE (XDATT)
1062 0 : real(kind = dp) :: XWRK, XWRK1, XMED7, XMAX, XMIN
1063 : !
1064 0 : Integer(kind = i4), Dimension (7 * (((Size (IDATT) + 6) / 7 + 6) / 7)) :: ISTRT, IENDT, IMEDT
1065 0 : Integer(kind = i4), Dimension (7 * ((Size(IDATT) + 6) / 7)) :: IWRKT
1066 : Integer(kind = i4) :: NTRI, NMED, NORD, NEQU, NLEQ, IMED, IDON, IDON1
1067 : Integer(kind = i4) :: IDEB, ITMP, IDCR, ICRS, ICRS1, ICRS2, IMAX, IMIN
1068 : Integer(kind = i4) :: IWRK, IWRK1, IMED1, IMED7, NDAT
1069 : !
1070 0 : NDAT = Size (IDATT)
1071 0 : NMED = (NDAT + 1) / 2
1072 0 : IWRKT = IDATT
1073 : !
1074 : ! If the number of values is small, then use insertion sort
1075 : !
1076 0 : If (NDAT < 35) Then
1077 : !
1078 : ! Bring minimum to first location to save test in decreasing loop
1079 : !
1080 0 : IDCR = NDAT
1081 0 : If (XDATT (IWRKT (1)) < XDATT (IWRKT (IDCR))) Then
1082 : IWRK = IWRKT (1)
1083 : Else
1084 0 : IWRK = IWRKT (IDCR)
1085 0 : IWRKT (IDCR) = IWRKT (1)
1086 : end if
1087 0 : XWRK = XDATT (IWRK)
1088 0 : Do ITMP = 1, NDAT - 2
1089 0 : IDCR = IDCR - 1
1090 0 : IWRK1 = IWRKT (IDCR)
1091 0 : XWRK1 = XDATT (IWRK1)
1092 0 : If (XWRK1 < XWRK) Then
1093 0 : IWRKT (IDCR) = IWRK
1094 0 : XWRK = XWRK1
1095 0 : IWRK = IWRK1
1096 : end if
1097 : End Do
1098 0 : IWRKT (1) = IWRK
1099 : !
1100 : ! Sort the first half, until we have NMED sorted values
1101 : !
1102 0 : Do ICRS = 3, NMED
1103 0 : XWRK = XDATT (IWRKT (ICRS))
1104 0 : IWRK = IWRKT (ICRS)
1105 0 : IDCR = ICRS - 1
1106 0 : Do
1107 0 : If (XWRK >= XDATT (IWRKT(IDCR))) Exit
1108 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1109 0 : IDCR = IDCR - 1
1110 : End Do
1111 0 : IWRKT (IDCR + 1) = IWRK
1112 : End Do
1113 : !
1114 : ! Insert any value less than the current median in the first half
1115 : !
1116 0 : XWRK1 = XDATT (IWRKT (NMED))
1117 0 : Do ICRS = NMED + 1, NDAT
1118 0 : XWRK = XDATT (IWRKT (ICRS))
1119 0 : IWRK = IWRKT (ICRS)
1120 0 : If (XWRK < XWRK1) Then
1121 0 : IDCR = NMED - 1
1122 0 : Do
1123 0 : If (XWRK >= XDATT (IWRKT(IDCR))) Exit
1124 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1125 0 : IDCR = IDCR - 1
1126 : End Do
1127 0 : IWRKT (IDCR + 1) = IWRK
1128 0 : XWRK1 = XDATT (IWRKT (NMED))
1129 : End If
1130 : End Do
1131 0 : ires_med = IWRKT (NMED)
1132 0 : Return
1133 : End If
1134 : !
1135 : ! Make sorted subsets of 7 elements
1136 : ! This is done by a variant of insertion sort where a first
1137 : ! pass is used to bring the smallest element to the first position
1138 : ! decreasing disorder at the same time, so that we may remove
1139 : ! remove the loop test in the insertion loop.
1140 : !
1141 0 : IMAX = 1
1142 0 : IMIN = 1
1143 0 : XMAX = XDATT (IWRKT(IMAX))
1144 0 : XMIN = XDATT (IWRKT(IMIN))
1145 0 : DO IDEB = 1, NDAT - 6, 7
1146 0 : IDCR = IDEB + 6
1147 0 : If (XDATT (IWRKT(IDEB)) < XDATT (IWRKT(IDCR))) Then
1148 : IWRK = IWRKT(IDEB)
1149 : Else
1150 0 : IWRK = IWRKT (IDCR)
1151 0 : IWRKT (IDCR) = IWRKT(IDEB)
1152 : end if
1153 0 : XWRK = XDATT (IWRK)
1154 0 : Do ITMP = 1, 5
1155 0 : IDCR = IDCR - 1
1156 0 : IWRK1 = IWRKT (IDCR)
1157 0 : XWRK1 = XDATT (IWRK1)
1158 0 : If (XWRK1 < XWRK) Then
1159 0 : IWRKT (IDCR) = IWRK
1160 0 : IWRK = IWRK1
1161 0 : XWRK = XWRK1
1162 : end if
1163 : End Do
1164 0 : IWRKT (IDEB) = IWRK
1165 0 : If (XWRK < XMIN) Then
1166 0 : IMIN = IWRK
1167 0 : XMIN = XWRK
1168 : End If
1169 0 : Do ICRS = IDEB + 1, IDEB + 5
1170 0 : IWRK = IWRKT (ICRS + 1)
1171 0 : XWRK = XDATT (IWRK)
1172 0 : IDON = IWRKT(ICRS)
1173 0 : If (XWRK < XDATT(IDON)) Then
1174 0 : IWRKT (ICRS + 1) = IDON
1175 0 : IDCR = ICRS
1176 0 : IWRK1 = IWRKT (IDCR - 1)
1177 0 : XWRK1 = XDATT (IWRK1)
1178 0 : Do
1179 0 : If (XWRK >= XWRK1) Exit
1180 0 : IWRKT (IDCR) = IWRK1
1181 0 : IDCR = IDCR - 1
1182 0 : IWRK1 = IWRKT (IDCR - 1)
1183 0 : XWRK1 = XDATT (IWRK1)
1184 : End Do
1185 0 : IWRKT (IDCR) = IWRK
1186 : end if
1187 : End Do
1188 0 : If (XWRK > XMAX) Then
1189 0 : IMAX = IWRK
1190 0 : XMAX = XWRK
1191 : End If
1192 : End Do
1193 : !
1194 : ! Add-up alternatively MAX and MIN values to make the number of data
1195 : ! an exact multiple of 7.
1196 : !
1197 0 : IDEB = 7 * (NDAT / 7)
1198 0 : NTRI = NDAT
1199 0 : If (IDEB < NDAT) Then
1200 : !
1201 0 : Do ICRS = IDEB + 1, NDAT
1202 0 : XWRK1 = XDATT (IWRKT (ICRS))
1203 0 : IF (XWRK1 > XMAX) Then
1204 0 : IMAX = IWRKT (ICRS)
1205 0 : XMAX = XWRK1
1206 : End If
1207 0 : IF (XWRK1 < XMIN) Then
1208 0 : IMIN = IWRKT (ICRS)
1209 0 : XMIN = XWRK1
1210 : End If
1211 : End Do
1212 0 : IWRK1 = IMAX
1213 0 : Do ICRS = NDAT + 1, IDEB + 7
1214 0 : IWRKT (ICRS) = IWRK1
1215 0 : If (IWRK1 == IMAX) Then
1216 : IWRK1 = IMIN
1217 : Else
1218 0 : NMED = NMED + 1
1219 0 : IWRK1 = IMAX
1220 : End If
1221 : End Do
1222 : !
1223 0 : Do ICRS = IDEB + 2, IDEB + 7
1224 0 : IWRK = IWRKT (ICRS)
1225 0 : XWRK = XDATT (IWRK)
1226 0 : Do IDCR = ICRS - 1, IDEB + 1, - 1
1227 0 : If (XWRK >= XDATT (IWRKT(IDCR))) Exit
1228 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1229 : End Do
1230 0 : IWRKT (IDCR + 1) = IWRK
1231 : End Do
1232 : !
1233 : NTRI = IDEB + 7
1234 : End If
1235 : !
1236 : ! Make the set of the indices of median values of each sorted subset
1237 : !
1238 0 : IDON1 = 0
1239 0 : Do IDON = 1, NTRI, 7
1240 0 : IDON1 = IDON1 + 1
1241 0 : IMEDT (IDON1) = IWRKT (IDON + 3)
1242 : End Do
1243 : !
1244 : ! Find XMED7, the median of the medians
1245 : !
1246 0 : Call d_med (XDATT, IMEDT(1 : IDON1), IMED7)
1247 0 : XMED7 = XDATT (IMED7)
1248 : !
1249 : ! Count how many values are not higher than (and how many equal to) XMED7
1250 : ! This number is at least 4 * 1/2 * (N/7) : 4 values in each of the
1251 : ! subsets where the median is lower than the median of medians. For similar
1252 : ! reasons, we also have at least 2N/7 values not lower than XMED7. At the
1253 : ! same time, we find in each subset the index of the last value < XMED7,
1254 : ! and that of the first > XMED7. These indices will be used to restrict the
1255 : ! search for the median as the Kth element in the subset (> or <) where
1256 : ! we know it to be.
1257 : !
1258 0 : IDON1 = 1
1259 0 : NLEQ = 0
1260 0 : NEQU = 0
1261 0 : Do IDON = 1, NTRI, 7
1262 0 : IMED = IDON + 3
1263 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
1264 0 : IMED = IMED - 2
1265 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
1266 : IMED = IMED - 1
1267 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
1268 0 : IMED = IMED + 1
1269 : end if
1270 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
1271 0 : IMED = IMED + 2
1272 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
1273 0 : IMED = IMED - 1
1274 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
1275 0 : IMED = IMED + 1
1276 : end if
1277 : end if
1278 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
1279 0 : NLEQ = NLEQ + IMED - IDON
1280 0 : IENDT (IDON1) = IMED - 1
1281 0 : ISTRT (IDON1) = IMED
1282 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
1283 0 : NLEQ = NLEQ + IMED - IDON + 1
1284 0 : IENDT (IDON1) = IMED
1285 0 : ISTRT (IDON1) = IMED + 1
1286 : Else ! If (XDATT (IWRKT (IMED)) == XMED7)
1287 0 : NLEQ = NLEQ + IMED - IDON + 1
1288 0 : NEQU = NEQU + 1
1289 0 : IENDT (IDON1) = IMED - 1
1290 0 : Do IMED1 = IMED - 1, IDON, -1
1291 0 : If (eq(XDATT (IWRKT (IMED1)), XMED7)) Then
1292 0 : NEQU = NEQU + 1
1293 0 : IENDT (IDON1) = IMED1 - 1
1294 : Else
1295 : Exit
1296 : End If
1297 : End Do
1298 0 : ISTRT (IDON1) = IMED + 1
1299 0 : Do IMED1 = IMED + 1, IDON + 6
1300 0 : If (eq(XDATT (IWRKT (IMED1)), XMED7)) Then
1301 0 : NEQU = NEQU + 1
1302 0 : NLEQ = NLEQ + 1
1303 0 : ISTRT (IDON1) = IMED1 + 1
1304 : Else
1305 : Exit
1306 : End If
1307 : End Do
1308 : end if
1309 0 : IDON1 = IDON1 + 1
1310 : End Do
1311 : !
1312 : ! Carry out a partial insertion sort to find the Kth smallest of the
1313 : ! large values, or the Kth largest of the small values, according to
1314 : ! what is needed.
1315 : !
1316 : !
1317 0 : If (NLEQ - NEQU + 1 <= NMED) Then
1318 0 : If (NLEQ < NMED) Then ! Not enough low values
1319 0 : IWRK1 = IMAX
1320 0 : XWRK1 = XDATT (IWRK1)
1321 0 : NORD = NMED - NLEQ
1322 0 : IDON1 = 0
1323 0 : ICRS1 = 1
1324 0 : ICRS2 = 0
1325 0 : IDCR = 0
1326 0 : Do IDON = 1, NTRI, 7
1327 0 : IDON1 = IDON1 + 1
1328 0 : If (ICRS2 < NORD) Then
1329 0 : Do ICRS = ISTRT (IDON1), IDON + 6
1330 0 : If (XDATT (IWRKT (ICRS)) < XWRK1) Then
1331 0 : IWRK = IWRKT (ICRS)
1332 0 : XWRK = XDATT (IWRK)
1333 0 : Do IDCR = ICRS1 - 1, 1, - 1
1334 0 : If (XWRK >= XDATT (IWRKT (IDCR))) Exit
1335 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1336 : End Do
1337 0 : IWRKT (IDCR + 1) = IWRK
1338 0 : IWRK1 = IWRKT (ICRS1)
1339 0 : XWRK1 = XDATT (IWRK1)
1340 : Else
1341 0 : If (ICRS2 < NORD) Then
1342 0 : IWRKT (ICRS1) = IWRKT (ICRS)
1343 0 : IWRK1 = IWRKT (ICRS1)
1344 0 : XWRK1 = XDATT (IWRK1)
1345 : end if
1346 : End If
1347 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
1348 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
1349 : End Do
1350 : Else
1351 0 : Do ICRS = ISTRT (IDON1), IDON + 6
1352 0 : If (XDATT (IWRKT (ICRS)) >= XWRK1) Exit
1353 0 : IWRK = IWRKT (ICRS)
1354 0 : XWRK = XDATT (IWRK)
1355 0 : Do IDCR = ICRS1 - 1, 1, - 1
1356 0 : If (XWRK >= XDATT (IWRKT (IDCR))) Exit
1357 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1358 : End Do
1359 0 : IWRKT (IDCR + 1) = IWRK
1360 0 : IWRK1 = IWRKT (ICRS1)
1361 0 : XWRK1 = XDATT (IWRK1)
1362 : End Do
1363 : End If
1364 : End Do
1365 0 : ires_med = IWRK1
1366 0 : Return
1367 : Else
1368 0 : ires_med = IMED7
1369 0 : Return
1370 : End If
1371 : Else ! If (NLEQ > NMED)
1372 : ! Not enough high values
1373 0 : XWRK1 = -XHUGE
1374 0 : NORD = NLEQ - NEQU - NMED + 1
1375 0 : IDON1 = 0
1376 0 : ICRS1 = 1
1377 0 : ICRS2 = 0
1378 0 : Do IDON = 1, NTRI, 7
1379 0 : IDON1 = IDON1 + 1
1380 0 : If (ICRS2 < NORD) Then
1381 : !
1382 0 : Do ICRS = IDON, IENDT (IDON1)
1383 0 : If (XDATT(IWRKT (ICRS)) > XWRK1) Then
1384 0 : IWRK = IWRKT (ICRS)
1385 0 : XWRK = XDATT (IWRK)
1386 0 : IDCR = ICRS1 - 1
1387 0 : Do IDCR = ICRS1 - 1, 1, - 1
1388 0 : If (XWRK <= XDATT(IWRKT (IDCR))) Exit
1389 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1390 : End Do
1391 0 : IWRKT (IDCR + 1) = IWRK
1392 0 : IWRK1 = IWRKT(ICRS1)
1393 0 : XWRK1 = XDATT(IWRK1)
1394 : Else
1395 0 : If (ICRS2 < NORD) Then
1396 0 : IWRKT (ICRS1) = IWRKT (ICRS)
1397 0 : IWRK1 = IWRKT(ICRS1)
1398 0 : XWRK1 = XDATT(IWRK1)
1399 : End If
1400 : End If
1401 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
1402 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
1403 : End Do
1404 : Else
1405 0 : Do ICRS = IENDT (IDON1), IDON, -1
1406 0 : If (XDATT(IWRKT (ICRS)) <= XWRK1) Exit
1407 0 : IWRK = IWRKT (ICRS)
1408 0 : XWRK = XDATT (IWRK)
1409 0 : IDCR = ICRS1 - 1
1410 0 : Do IDCR = ICRS1 - 1, 1, - 1
1411 0 : If (XWRK <= XDATT(IWRKT (IDCR))) Exit
1412 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1413 : End Do
1414 0 : IWRKT (IDCR + 1) = IWRK
1415 0 : IWRK1 = IWRKT(ICRS1)
1416 0 : XWRK1 = XDATT(IWRK1)
1417 : End Do
1418 : end if
1419 : End Do
1420 : !
1421 0 : ires_med = IWRK1
1422 0 : Return
1423 : End If
1424 : !
1425 0 : END Subroutine d_med
1426 : !
1427 0 : Subroutine R_indmed (XDONT, INDM)
1428 : ! Returns index of median value of XDONT.
1429 : ! __________________________________________________________
1430 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
1431 : Integer(kind = i4), Intent (Out) :: INDM
1432 : ! __________________________________________________________
1433 : Integer(kind = i4) :: IDON
1434 : !
1435 0 : Allocate (IDONT (SIZE(XDONT)))
1436 0 : Do IDON = 1, SIZE(XDONT)
1437 0 : IDONT (IDON) = IDON
1438 : End Do
1439 : !
1440 0 : Call r_med (XDONT, IDONT, INDM)
1441 : !
1442 0 : Deallocate (IDONT)
1443 0 : End Subroutine R_indmed
1444 :
1445 0 : Recursive Subroutine r_med (XDATT, IDATT, ires_med)
1446 : ! Finds the index of the median of XDONT using the recursive procedure
1447 : ! described in Knuth, The Art of Computer Programming,
1448 : ! vol. 3, 5.3.3 - This procedure is linear in time, and
1449 : ! does not require to be able to interpolate in the
1450 : ! set as the one used in INDNTH. It also has better worst
1451 : ! case behavior than INDNTH, but is about 30% slower in
1452 : ! average for random uniformly distributed values.
1453 : ! __________________________________________________________
1454 : Real(kind = sp), Dimension (:), Intent (In) :: XDATT
1455 : Integer(kind = i4), Dimension (:), Intent (In) :: IDATT
1456 : Integer(kind = i4), Intent (Out) :: ires_med
1457 : ! __________________________________________________________
1458 : !
1459 : Real(kind = sp), Parameter :: XHUGE = HUGE (XDATT)
1460 0 : Real(kind = sp) :: XWRK, XWRK1, XMED7, XMAX, XMIN
1461 : !
1462 0 : Integer(kind = i4), Dimension (7 * (((Size (IDATT) + 6) / 7 + 6) / 7)) :: ISTRT, IENDT, IMEDT
1463 0 : Integer(kind = i4), Dimension (7 * ((Size(IDATT) + 6) / 7)) :: IWRKT
1464 : Integer(kind = i4) :: NTRI, NMED, NORD, NEQU, NLEQ, IMED, IDON, IDON1
1465 : Integer(kind = i4) :: IDEB, ITMP, IDCR, ICRS, ICRS1, ICRS2, IMAX, IMIN
1466 : Integer(kind = i4) :: IWRK, IWRK1, IMED1, IMED7, NDAT
1467 : !
1468 0 : NDAT = Size (IDATT)
1469 0 : NMED = (NDAT + 1) / 2
1470 0 : IWRKT = IDATT
1471 : !
1472 : ! If the number of values is small, then use insertion sort
1473 : !
1474 0 : If (NDAT < 35) Then
1475 : !
1476 : ! Bring minimum to first location to save test in decreasing loop
1477 : !
1478 0 : IDCR = NDAT
1479 0 : If (XDATT (IWRKT (1)) < XDATT (IWRKT (IDCR))) Then
1480 : IWRK = IWRKT (1)
1481 : Else
1482 0 : IWRK = IWRKT (IDCR)
1483 0 : IWRKT (IDCR) = IWRKT (1)
1484 : end if
1485 0 : XWRK = XDATT (IWRK)
1486 0 : Do ITMP = 1, NDAT - 2
1487 0 : IDCR = IDCR - 1
1488 0 : IWRK1 = IWRKT (IDCR)
1489 0 : XWRK1 = XDATT (IWRK1)
1490 0 : If (XWRK1 < XWRK) Then
1491 0 : IWRKT (IDCR) = IWRK
1492 0 : XWRK = XWRK1
1493 0 : IWRK = IWRK1
1494 : end if
1495 : End Do
1496 0 : IWRKT (1) = IWRK
1497 : !
1498 : ! Sort the first half, until we have NMED sorted values
1499 : !
1500 0 : Do ICRS = 3, NMED
1501 0 : XWRK = XDATT (IWRKT (ICRS))
1502 0 : IWRK = IWRKT (ICRS)
1503 0 : IDCR = ICRS - 1
1504 0 : Do
1505 0 : If (XWRK >= XDATT (IWRKT(IDCR))) Exit
1506 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1507 0 : IDCR = IDCR - 1
1508 : End Do
1509 0 : IWRKT (IDCR + 1) = IWRK
1510 : End Do
1511 : !
1512 : ! Insert any value less than the current median in the first half
1513 : !
1514 0 : XWRK1 = XDATT (IWRKT (NMED))
1515 0 : Do ICRS = NMED + 1, NDAT
1516 0 : XWRK = XDATT (IWRKT (ICRS))
1517 0 : IWRK = IWRKT (ICRS)
1518 0 : If (XWRK < XWRK1) Then
1519 0 : IDCR = NMED - 1
1520 0 : Do
1521 0 : If (XWRK >= XDATT (IWRKT(IDCR))) Exit
1522 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1523 0 : IDCR = IDCR - 1
1524 : End Do
1525 0 : IWRKT (IDCR + 1) = IWRK
1526 0 : XWRK1 = XDATT (IWRKT (NMED))
1527 : End If
1528 : End Do
1529 0 : ires_med = IWRKT (NMED)
1530 0 : Return
1531 : End If
1532 : !
1533 : ! Make sorted subsets of 7 elements
1534 : ! This is done by a variant of insertion sort where a first
1535 : ! pass is used to bring the smallest element to the first position
1536 : ! decreasing disorder at the same time, so that we may remove
1537 : ! remove the loop test in the insertion loop.
1538 : !
1539 0 : IMAX = 1
1540 0 : IMIN = 1
1541 0 : XMAX = XDATT (IWRKT(IMAX))
1542 0 : XMIN = XDATT (IWRKT(IMIN))
1543 0 : DO IDEB = 1, NDAT - 6, 7
1544 0 : IDCR = IDEB + 6
1545 0 : If (XDATT (IWRKT(IDEB)) < XDATT (IWRKT(IDCR))) Then
1546 : IWRK = IWRKT(IDEB)
1547 : Else
1548 0 : IWRK = IWRKT (IDCR)
1549 0 : IWRKT (IDCR) = IWRKT(IDEB)
1550 : end if
1551 0 : XWRK = XDATT (IWRK)
1552 0 : Do ITMP = 1, 5
1553 0 : IDCR = IDCR - 1
1554 0 : IWRK1 = IWRKT (IDCR)
1555 0 : XWRK1 = XDATT (IWRK1)
1556 0 : If (XWRK1 < XWRK) Then
1557 0 : IWRKT (IDCR) = IWRK
1558 0 : IWRK = IWRK1
1559 0 : XWRK = XWRK1
1560 : end if
1561 : End Do
1562 0 : IWRKT (IDEB) = IWRK
1563 0 : If (XWRK < XMIN) Then
1564 0 : IMIN = IWRK
1565 0 : XMIN = XWRK
1566 : End If
1567 0 : Do ICRS = IDEB + 1, IDEB + 5
1568 0 : IWRK = IWRKT (ICRS + 1)
1569 0 : XWRK = XDATT (IWRK)
1570 0 : IDON = IWRKT(ICRS)
1571 0 : If (XWRK < XDATT(IDON)) Then
1572 0 : IWRKT (ICRS + 1) = IDON
1573 0 : IDCR = ICRS
1574 0 : IWRK1 = IWRKT (IDCR - 1)
1575 0 : XWRK1 = XDATT (IWRK1)
1576 0 : Do
1577 0 : If (XWRK >= XWRK1) Exit
1578 0 : IWRKT (IDCR) = IWRK1
1579 0 : IDCR = IDCR - 1
1580 0 : IWRK1 = IWRKT (IDCR - 1)
1581 0 : XWRK1 = XDATT (IWRK1)
1582 : End Do
1583 0 : IWRKT (IDCR) = IWRK
1584 : end if
1585 : End Do
1586 0 : If (XWRK > XMAX) Then
1587 0 : IMAX = IWRK
1588 0 : XMAX = XWRK
1589 : End If
1590 : End Do
1591 : !
1592 : ! Add-up alternatively MAX and MIN values to make the number of data
1593 : ! an exact multiple of 7.
1594 : !
1595 0 : IDEB = 7 * (NDAT / 7)
1596 0 : NTRI = NDAT
1597 0 : If (IDEB < NDAT) Then
1598 : !
1599 0 : Do ICRS = IDEB + 1, NDAT
1600 0 : XWRK1 = XDATT (IWRKT (ICRS))
1601 0 : IF (XWRK1 > XMAX) Then
1602 0 : IMAX = IWRKT (ICRS)
1603 0 : XMAX = XWRK1
1604 : End If
1605 0 : IF (XWRK1 < XMIN) Then
1606 0 : IMIN = IWRKT (ICRS)
1607 0 : XMIN = XWRK1
1608 : End If
1609 : End Do
1610 0 : IWRK1 = IMAX
1611 0 : Do ICRS = NDAT + 1, IDEB + 7
1612 0 : IWRKT (ICRS) = IWRK1
1613 0 : If (IWRK1 == IMAX) Then
1614 : IWRK1 = IMIN
1615 : Else
1616 0 : NMED = NMED + 1
1617 0 : IWRK1 = IMAX
1618 : End If
1619 : End Do
1620 : !
1621 0 : Do ICRS = IDEB + 2, IDEB + 7
1622 0 : IWRK = IWRKT (ICRS)
1623 0 : XWRK = XDATT (IWRK)
1624 0 : Do IDCR = ICRS - 1, IDEB + 1, - 1
1625 0 : If (XWRK >= XDATT (IWRKT(IDCR))) Exit
1626 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1627 : End Do
1628 0 : IWRKT (IDCR + 1) = IWRK
1629 : End Do
1630 : !
1631 : NTRI = IDEB + 7
1632 : End If
1633 : !
1634 : ! Make the set of the indices of median values of each sorted subset
1635 : !
1636 0 : IDON1 = 0
1637 0 : Do IDON = 1, NTRI, 7
1638 0 : IDON1 = IDON1 + 1
1639 0 : IMEDT (IDON1) = IWRKT (IDON + 3)
1640 : End Do
1641 : !
1642 : ! Find XMED7, the median of the medians
1643 : !
1644 0 : Call r_med (XDATT, IMEDT(1 : IDON1), IMED7)
1645 0 : XMED7 = XDATT (IMED7)
1646 : !
1647 : ! Count how many values are not higher than (and how many equal to) XMED7
1648 : ! This number is at least 4 * 1/2 * (N/7) : 4 values in each of the
1649 : ! subsets where the median is lower than the median of medians. For similar
1650 : ! reasons, we also have at least 2N/7 values not lower than XMED7. At the
1651 : ! same time, we find in each subset the index of the last value < XMED7,
1652 : ! and that of the first > XMED7. These indices will be used to restrict the
1653 : ! search for the median as the Kth element in the subset (> or <) where
1654 : ! we know it to be.
1655 : !
1656 0 : IDON1 = 1
1657 0 : NLEQ = 0
1658 0 : NEQU = 0
1659 0 : Do IDON = 1, NTRI, 7
1660 0 : IMED = IDON + 3
1661 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
1662 0 : IMED = IMED - 2
1663 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
1664 : IMED = IMED - 1
1665 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
1666 0 : IMED = IMED + 1
1667 : end if
1668 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
1669 0 : IMED = IMED + 2
1670 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
1671 0 : IMED = IMED - 1
1672 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
1673 0 : IMED = IMED + 1
1674 : end if
1675 : end if
1676 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
1677 0 : NLEQ = NLEQ + IMED - IDON
1678 0 : IENDT (IDON1) = IMED - 1
1679 0 : ISTRT (IDON1) = IMED
1680 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
1681 0 : NLEQ = NLEQ + IMED - IDON + 1
1682 0 : IENDT (IDON1) = IMED
1683 0 : ISTRT (IDON1) = IMED + 1
1684 : Else ! If (XDATT (IWRKT (IMED)) == XMED7)
1685 0 : NLEQ = NLEQ + IMED - IDON + 1
1686 0 : NEQU = NEQU + 1
1687 0 : IENDT (IDON1) = IMED - 1
1688 0 : Do IMED1 = IMED - 1, IDON, -1
1689 0 : If (eq(XDATT (IWRKT (IMED1)), XMED7)) Then
1690 0 : NEQU = NEQU + 1
1691 0 : IENDT (IDON1) = IMED1 - 1
1692 : Else
1693 : Exit
1694 : End If
1695 : End Do
1696 0 : ISTRT (IDON1) = IMED + 1
1697 0 : Do IMED1 = IMED + 1, IDON + 6
1698 0 : If (eq(XDATT (IWRKT (IMED1)), XMED7)) Then
1699 0 : NEQU = NEQU + 1
1700 0 : NLEQ = NLEQ + 1
1701 0 : ISTRT (IDON1) = IMED1 + 1
1702 : Else
1703 : Exit
1704 : End If
1705 : End Do
1706 : end if
1707 0 : IDON1 = IDON1 + 1
1708 : End Do
1709 : !
1710 : ! Carry out a partial insertion sort to find the Kth smallest of the
1711 : ! large values, or the Kth largest of the small values, according to
1712 : ! what is needed.
1713 : !
1714 : !
1715 0 : If (NLEQ - NEQU + 1 <= NMED) Then
1716 0 : If (NLEQ < NMED) Then ! Not enough low values
1717 0 : IWRK1 = IMAX
1718 0 : XWRK1 = XDATT (IWRK1)
1719 0 : NORD = NMED - NLEQ
1720 0 : IDON1 = 0
1721 0 : ICRS1 = 1
1722 0 : ICRS2 = 0
1723 0 : IDCR = 0
1724 0 : Do IDON = 1, NTRI, 7
1725 0 : IDON1 = IDON1 + 1
1726 0 : If (ICRS2 < NORD) Then
1727 0 : Do ICRS = ISTRT (IDON1), IDON + 6
1728 0 : If (XDATT (IWRKT (ICRS)) < XWRK1) Then
1729 0 : IWRK = IWRKT (ICRS)
1730 0 : XWRK = XDATT (IWRK)
1731 0 : Do IDCR = ICRS1 - 1, 1, - 1
1732 0 : If (XWRK >= XDATT (IWRKT (IDCR))) Exit
1733 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1734 : End Do
1735 0 : IWRKT (IDCR + 1) = IWRK
1736 0 : IWRK1 = IWRKT (ICRS1)
1737 0 : XWRK1 = XDATT (IWRK1)
1738 : Else
1739 0 : If (ICRS2 < NORD) Then
1740 0 : IWRKT (ICRS1) = IWRKT (ICRS)
1741 0 : IWRK1 = IWRKT (ICRS1)
1742 0 : XWRK1 = XDATT (IWRK1)
1743 : end if
1744 : End If
1745 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
1746 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
1747 : End Do
1748 : Else
1749 0 : Do ICRS = ISTRT (IDON1), IDON + 6
1750 0 : If (XDATT (IWRKT (ICRS)) >= XWRK1) Exit
1751 0 : IWRK = IWRKT (ICRS)
1752 0 : XWRK = XDATT (IWRK)
1753 0 : Do IDCR = ICRS1 - 1, 1, - 1
1754 0 : If (XWRK >= XDATT (IWRKT (IDCR))) Exit
1755 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1756 : End Do
1757 0 : IWRKT (IDCR + 1) = IWRK
1758 0 : IWRK1 = IWRKT (ICRS1)
1759 0 : XWRK1 = XDATT (IWRK1)
1760 : End Do
1761 : End If
1762 : End Do
1763 0 : ires_med = IWRK1
1764 0 : Return
1765 : Else
1766 0 : ires_med = IMED7
1767 0 : Return
1768 : End If
1769 : Else ! If (NLEQ > NMED)
1770 : ! Not enough high values
1771 0 : XWRK1 = -XHUGE
1772 0 : NORD = NLEQ - NEQU - NMED + 1
1773 0 : IDON1 = 0
1774 0 : ICRS1 = 1
1775 0 : ICRS2 = 0
1776 0 : Do IDON = 1, NTRI, 7
1777 0 : IDON1 = IDON1 + 1
1778 0 : If (ICRS2 < NORD) Then
1779 : !
1780 0 : Do ICRS = IDON, IENDT (IDON1)
1781 0 : If (XDATT(IWRKT (ICRS)) > XWRK1) Then
1782 0 : IWRK = IWRKT (ICRS)
1783 0 : XWRK = XDATT (IWRK)
1784 0 : IDCR = ICRS1 - 1
1785 0 : Do IDCR = ICRS1 - 1, 1, - 1
1786 0 : If (XWRK <= XDATT(IWRKT (IDCR))) Exit
1787 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1788 : End Do
1789 0 : IWRKT (IDCR + 1) = IWRK
1790 0 : IWRK1 = IWRKT(ICRS1)
1791 0 : XWRK1 = XDATT(IWRK1)
1792 : Else
1793 0 : If (ICRS2 < NORD) Then
1794 0 : IWRKT (ICRS1) = IWRKT (ICRS)
1795 0 : IWRK1 = IWRKT(ICRS1)
1796 0 : XWRK1 = XDATT(IWRK1)
1797 : End If
1798 : End If
1799 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
1800 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
1801 : End Do
1802 : Else
1803 0 : Do ICRS = IENDT (IDON1), IDON, -1
1804 0 : If (XDATT(IWRKT (ICRS)) <= XWRK1) Exit
1805 0 : IWRK = IWRKT (ICRS)
1806 0 : XWRK = XDATT (IWRK)
1807 0 : IDCR = ICRS1 - 1
1808 0 : Do IDCR = ICRS1 - 1, 1, - 1
1809 0 : If (XWRK <= XDATT(IWRKT (IDCR))) Exit
1810 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1811 : End Do
1812 0 : IWRKT (IDCR + 1) = IWRK
1813 0 : IWRK1 = IWRKT(ICRS1)
1814 0 : XWRK1 = XDATT(IWRK1)
1815 : End Do
1816 : end if
1817 : End Do
1818 : !
1819 0 : ires_med = IWRK1
1820 0 : Return
1821 : End If
1822 : !
1823 0 : END Subroutine r_med
1824 :
1825 0 : Subroutine I_indmed (XDONT, INDM)
1826 : ! Returns index of median value of XDONT.
1827 : ! __________________________________________________________
1828 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
1829 : Integer(kind = i4), Intent (Out) :: INDM
1830 : ! __________________________________________________________
1831 : Integer(kind = i4) :: IDON
1832 : !
1833 0 : Allocate (IDONT (SIZE(XDONT)))
1834 0 : Do IDON = 1, SIZE(XDONT)
1835 0 : IDONT (IDON) = IDON
1836 : End Do
1837 : !
1838 0 : Call i_med(XDONT, IDONT, INDM)
1839 : !
1840 0 : Deallocate (IDONT)
1841 0 : End Subroutine I_indmed
1842 :
1843 0 : Recursive Subroutine i_med (XDATT, IDATT, ires_med)
1844 : ! Finds the index of the median of XDONT using the recursive procedure
1845 : ! described in Knuth, The Art of Computer Programming,
1846 : ! vol. 3, 5.3.3 - This procedure is linear in time, and
1847 : ! does not require to be able to interpolate in the
1848 : ! set as the one used in INDNTH. It also has better worst
1849 : ! case behavior than INDNTH, but is about 30% slower in
1850 : ! average for random uniformly distributed values.
1851 : ! __________________________________________________________
1852 : Integer(kind = i4), Dimension (:), Intent (In) :: XDATT
1853 : Integer(kind = i4), Dimension (:), Intent (In) :: IDATT
1854 : Integer(kind = i4), Intent (Out) :: ires_med
1855 : ! __________________________________________________________
1856 : !
1857 : Integer(kind = i4), Parameter :: XHUGE = HUGE (XDATT)
1858 : Integer(kind = i4) :: XWRK, XWRK1, XMED7, XMAX, XMIN
1859 : !
1860 0 : Integer(kind = i4), Dimension (7 * (((Size (IDATT) + 6) / 7 + 6) / 7)) :: ISTRT, IENDT, IMEDT
1861 0 : Integer(kind = i4), Dimension (7 * ((Size(IDATT) + 6) / 7)) :: IWRKT
1862 : Integer(kind = i4) :: NTRI, NMED, NORD, NEQU, NLEQ, IMED, IDON, IDON1
1863 : Integer(kind = i4) :: IDEB, ITMP, IDCR, ICRS, ICRS1, ICRS2, IMAX, IMIN
1864 : Integer(kind = i4) :: IWRK, IWRK1, IMED1, IMED7, NDAT
1865 : !
1866 0 : NDAT = Size (IDATT)
1867 0 : NMED = (NDAT + 1) / 2
1868 0 : IWRKT = IDATT
1869 : !
1870 : ! If the number of values is small, then use insertion sort
1871 : !
1872 0 : If (NDAT < 35) Then
1873 : !
1874 : ! Bring minimum to first location to save test in decreasing loop
1875 : !
1876 0 : IDCR = NDAT
1877 0 : If (XDATT (IWRKT (1)) < XDATT (IWRKT (IDCR))) Then
1878 : IWRK = IWRKT (1)
1879 : Else
1880 0 : IWRK = IWRKT (IDCR)
1881 0 : IWRKT (IDCR) = IWRKT (1)
1882 : end if
1883 0 : XWRK = XDATT (IWRK)
1884 0 : Do ITMP = 1, NDAT - 2
1885 0 : IDCR = IDCR - 1
1886 0 : IWRK1 = IWRKT (IDCR)
1887 0 : XWRK1 = XDATT (IWRK1)
1888 0 : If (XWRK1 < XWRK) Then
1889 0 : IWRKT (IDCR) = IWRK
1890 0 : XWRK = XWRK1
1891 0 : IWRK = IWRK1
1892 : end if
1893 : End Do
1894 0 : IWRKT (1) = IWRK
1895 : !
1896 : ! Sort the first half, until we have NMED sorted values
1897 : !
1898 0 : Do ICRS = 3, NMED
1899 0 : XWRK = XDATT (IWRKT (ICRS))
1900 0 : IWRK = IWRKT (ICRS)
1901 0 : IDCR = ICRS - 1
1902 0 : Do
1903 0 : If (XWRK >= XDATT (IWRKT(IDCR))) Exit
1904 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1905 0 : IDCR = IDCR - 1
1906 : End Do
1907 0 : IWRKT (IDCR + 1) = IWRK
1908 : End Do
1909 : !
1910 : ! Insert any value less than the current median in the first half
1911 : !
1912 0 : XWRK1 = XDATT (IWRKT (NMED))
1913 0 : Do ICRS = NMED + 1, NDAT
1914 0 : XWRK = XDATT (IWRKT (ICRS))
1915 0 : IWRK = IWRKT (ICRS)
1916 0 : If (XWRK < XWRK1) Then
1917 0 : IDCR = NMED - 1
1918 0 : Do
1919 0 : If (XWRK >= XDATT (IWRKT(IDCR))) Exit
1920 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
1921 0 : IDCR = IDCR - 1
1922 : End Do
1923 0 : IWRKT (IDCR + 1) = IWRK
1924 0 : XWRK1 = XDATT (IWRKT (NMED))
1925 : End If
1926 : End Do
1927 0 : ires_med = IWRKT (NMED)
1928 0 : Return
1929 : End If
1930 : !
1931 : ! Make sorted subsets of 7 elements
1932 : ! This is done by a variant of insertion sort where a first
1933 : ! pass is used to bring the smallest element to the first position
1934 : ! decreasing disorder at the same time, so that we may remove
1935 : ! remove the loop test in the insertion loop.
1936 : !
1937 0 : IMAX = 1
1938 0 : IMIN = 1
1939 0 : XMAX = XDATT (IWRKT(IMAX))
1940 0 : XMIN = XDATT (IWRKT(IMIN))
1941 0 : DO IDEB = 1, NDAT - 6, 7
1942 0 : IDCR = IDEB + 6
1943 0 : If (XDATT (IWRKT(IDEB)) < XDATT (IWRKT(IDCR))) Then
1944 : IWRK = IWRKT(IDEB)
1945 : Else
1946 0 : IWRK = IWRKT (IDCR)
1947 0 : IWRKT (IDCR) = IWRKT(IDEB)
1948 : end if
1949 0 : XWRK = XDATT (IWRK)
1950 0 : Do ITMP = 1, 5
1951 0 : IDCR = IDCR - 1
1952 0 : IWRK1 = IWRKT (IDCR)
1953 0 : XWRK1 = XDATT (IWRK1)
1954 0 : If (XWRK1 < XWRK) Then
1955 0 : IWRKT (IDCR) = IWRK
1956 0 : IWRK = IWRK1
1957 0 : XWRK = XWRK1
1958 : end if
1959 : End Do
1960 0 : IWRKT (IDEB) = IWRK
1961 0 : If (XWRK < XMIN) Then
1962 0 : IMIN = IWRK
1963 0 : XMIN = XWRK
1964 : End If
1965 0 : Do ICRS = IDEB + 1, IDEB + 5
1966 0 : IWRK = IWRKT (ICRS + 1)
1967 0 : XWRK = XDATT (IWRK)
1968 0 : IDON = IWRKT(ICRS)
1969 0 : If (XWRK < XDATT(IDON)) Then
1970 0 : IWRKT (ICRS + 1) = IDON
1971 0 : IDCR = ICRS
1972 0 : IWRK1 = IWRKT (IDCR - 1)
1973 0 : XWRK1 = XDATT (IWRK1)
1974 0 : Do
1975 0 : If (XWRK >= XWRK1) Exit
1976 0 : IWRKT (IDCR) = IWRK1
1977 0 : IDCR = IDCR - 1
1978 0 : IWRK1 = IWRKT (IDCR - 1)
1979 0 : XWRK1 = XDATT (IWRK1)
1980 : End Do
1981 0 : IWRKT (IDCR) = IWRK
1982 : end if
1983 : End Do
1984 0 : If (XWRK > XMAX) Then
1985 0 : IMAX = IWRK
1986 0 : XMAX = XWRK
1987 : End If
1988 : End Do
1989 : !
1990 : ! Add-up alternatively MAX and MIN values to make the number of data
1991 : ! an exact multiple of 7.
1992 : !
1993 0 : IDEB = 7 * (NDAT / 7)
1994 0 : NTRI = NDAT
1995 0 : If (IDEB < NDAT) Then
1996 : !
1997 0 : Do ICRS = IDEB + 1, NDAT
1998 0 : XWRK1 = XDATT (IWRKT (ICRS))
1999 0 : IF (XWRK1 > XMAX) Then
2000 0 : IMAX = IWRKT (ICRS)
2001 0 : XMAX = XWRK1
2002 : End If
2003 0 : IF (XWRK1 < XMIN) Then
2004 0 : IMIN = IWRKT (ICRS)
2005 0 : XMIN = XWRK1
2006 : End If
2007 : End Do
2008 0 : IWRK1 = IMAX
2009 0 : Do ICRS = NDAT + 1, IDEB + 7
2010 0 : IWRKT (ICRS) = IWRK1
2011 0 : If (IWRK1 == IMAX) Then
2012 : IWRK1 = IMIN
2013 : Else
2014 0 : NMED = NMED + 1
2015 0 : IWRK1 = IMAX
2016 : End If
2017 : End Do
2018 : !
2019 0 : Do ICRS = IDEB + 2, IDEB + 7
2020 0 : IWRK = IWRKT (ICRS)
2021 0 : XWRK = XDATT (IWRK)
2022 0 : Do IDCR = ICRS - 1, IDEB + 1, - 1
2023 0 : If (XWRK >= XDATT (IWRKT(IDCR))) Exit
2024 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
2025 : End Do
2026 0 : IWRKT (IDCR + 1) = IWRK
2027 : End Do
2028 : !
2029 : NTRI = IDEB + 7
2030 : End If
2031 : !
2032 : ! Make the set of the indices of median values of each sorted subset
2033 : !
2034 0 : IDON1 = 0
2035 0 : Do IDON = 1, NTRI, 7
2036 0 : IDON1 = IDON1 + 1
2037 0 : IMEDT (IDON1) = IWRKT (IDON + 3)
2038 : End Do
2039 : !
2040 : ! Find XMED7, the median of the medians
2041 : !
2042 0 : Call i_med (XDATT, IMEDT(1 : IDON1), IMED7)
2043 0 : XMED7 = XDATT (IMED7)
2044 : !
2045 : ! Count how many values are not higher than (and how many equal to) XMED7
2046 : ! This number is at least 4 * 1/2 * (N/7) : 4 values in each of the
2047 : ! subsets where the median is lower than the median of medians. For similar
2048 : ! reasons, we also have at least 2N/7 values not lower than XMED7. At the
2049 : ! same time, we find in each subset the index of the last value < XMED7,
2050 : ! and that of the first > XMED7. These indices will be used to restrict the
2051 : ! search for the median as the Kth element in the subset (> or <) where
2052 : ! we know it to be.
2053 : !
2054 0 : IDON1 = 1
2055 0 : NLEQ = 0
2056 0 : NEQU = 0
2057 0 : Do IDON = 1, NTRI, 7
2058 0 : IMED = IDON + 3
2059 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
2060 0 : IMED = IMED - 2
2061 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
2062 : IMED = IMED - 1
2063 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
2064 0 : IMED = IMED + 1
2065 : end if
2066 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
2067 0 : IMED = IMED + 2
2068 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
2069 0 : IMED = IMED - 1
2070 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
2071 0 : IMED = IMED + 1
2072 : end if
2073 : end if
2074 0 : If (XDATT (IWRKT (IMED)) > XMED7) Then
2075 0 : NLEQ = NLEQ + IMED - IDON
2076 0 : IENDT (IDON1) = IMED - 1
2077 0 : ISTRT (IDON1) = IMED
2078 0 : Else If (XDATT (IWRKT (IMED)) < XMED7) Then
2079 0 : NLEQ = NLEQ + IMED - IDON + 1
2080 0 : IENDT (IDON1) = IMED
2081 0 : ISTRT (IDON1) = IMED + 1
2082 : Else ! If (XDATT (IWRKT (IMED)) == XMED7)
2083 0 : NLEQ = NLEQ + IMED - IDON + 1
2084 0 : NEQU = NEQU + 1
2085 0 : IENDT (IDON1) = IMED - 1
2086 0 : Do IMED1 = IMED - 1, IDON, -1
2087 0 : If (XDATT (IWRKT (IMED1)) == XMED7) Then
2088 0 : NEQU = NEQU + 1
2089 0 : IENDT (IDON1) = IMED1 - 1
2090 : Else
2091 : Exit
2092 : End If
2093 : End Do
2094 0 : ISTRT (IDON1) = IMED + 1
2095 0 : Do IMED1 = IMED + 1, IDON + 6
2096 0 : If (XDATT (IWRKT (IMED1)) == XMED7) Then
2097 0 : NEQU = NEQU + 1
2098 0 : NLEQ = NLEQ + 1
2099 0 : ISTRT (IDON1) = IMED1 + 1
2100 : Else
2101 : Exit
2102 : End If
2103 : End Do
2104 : end if
2105 0 : IDON1 = IDON1 + 1
2106 : End Do
2107 : !
2108 : ! Carry out a partial insertion sort to find the Kth smallest of the
2109 : ! large values, or the Kth largest of the small values, according to
2110 : ! what is needed.
2111 : !
2112 : !
2113 0 : If (NLEQ - NEQU + 1 <= NMED) Then
2114 0 : If (NLEQ < NMED) Then ! Not enough low values
2115 0 : IWRK1 = IMAX
2116 0 : XWRK1 = XDATT (IWRK1)
2117 0 : NORD = NMED - NLEQ
2118 0 : IDON1 = 0
2119 0 : ICRS1 = 1
2120 0 : ICRS2 = 0
2121 0 : IDCR = 0
2122 0 : Do IDON = 1, NTRI, 7
2123 0 : IDON1 = IDON1 + 1
2124 0 : If (ICRS2 < NORD) Then
2125 0 : Do ICRS = ISTRT (IDON1), IDON + 6
2126 0 : If (XDATT (IWRKT (ICRS)) < XWRK1) Then
2127 0 : IWRK = IWRKT (ICRS)
2128 0 : XWRK = XDATT (IWRK)
2129 0 : Do IDCR = ICRS1 - 1, 1, - 1
2130 0 : If (XWRK >= XDATT (IWRKT (IDCR))) Exit
2131 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
2132 : End Do
2133 0 : IWRKT (IDCR + 1) = IWRK
2134 0 : IWRK1 = IWRKT (ICRS1)
2135 0 : XWRK1 = XDATT (IWRK1)
2136 : Else
2137 0 : If (ICRS2 < NORD) Then
2138 0 : IWRKT (ICRS1) = IWRKT (ICRS)
2139 0 : IWRK1 = IWRKT (ICRS1)
2140 0 : XWRK1 = XDATT (IWRK1)
2141 : end if
2142 : End If
2143 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
2144 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
2145 : End Do
2146 : Else
2147 0 : Do ICRS = ISTRT (IDON1), IDON + 6
2148 0 : If (XDATT (IWRKT (ICRS)) >= XWRK1) Exit
2149 0 : IWRK = IWRKT (ICRS)
2150 0 : XWRK = XDATT (IWRK)
2151 0 : Do IDCR = ICRS1 - 1, 1, - 1
2152 0 : If (XWRK >= XDATT (IWRKT (IDCR))) Exit
2153 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
2154 : End Do
2155 0 : IWRKT (IDCR + 1) = IWRK
2156 0 : IWRK1 = IWRKT (ICRS1)
2157 0 : XWRK1 = XDATT (IWRK1)
2158 : End Do
2159 : End If
2160 : End Do
2161 0 : ires_med = IWRK1
2162 0 : Return
2163 : Else
2164 0 : ires_med = IMED7
2165 0 : Return
2166 : End If
2167 : Else ! If (NLEQ > NMED)
2168 : ! Not enough high values
2169 0 : XWRK1 = -XHUGE
2170 0 : NORD = NLEQ - NEQU - NMED + 1
2171 0 : IDON1 = 0
2172 0 : ICRS1 = 1
2173 0 : ICRS2 = 0
2174 0 : Do IDON = 1, NTRI, 7
2175 0 : IDON1 = IDON1 + 1
2176 0 : If (ICRS2 < NORD) Then
2177 : !
2178 0 : Do ICRS = IDON, IENDT (IDON1)
2179 0 : If (XDATT(IWRKT (ICRS)) > XWRK1) Then
2180 0 : IWRK = IWRKT (ICRS)
2181 0 : XWRK = XDATT (IWRK)
2182 0 : IDCR = ICRS1 - 1
2183 0 : Do IDCR = ICRS1 - 1, 1, - 1
2184 0 : If (XWRK <= XDATT(IWRKT (IDCR))) Exit
2185 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
2186 : End Do
2187 0 : IWRKT (IDCR + 1) = IWRK
2188 0 : IWRK1 = IWRKT(ICRS1)
2189 0 : XWRK1 = XDATT(IWRK1)
2190 : Else
2191 0 : If (ICRS2 < NORD) Then
2192 0 : IWRKT (ICRS1) = IWRKT (ICRS)
2193 0 : IWRK1 = IWRKT(ICRS1)
2194 0 : XWRK1 = XDATT(IWRK1)
2195 : End If
2196 : End If
2197 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
2198 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
2199 : End Do
2200 : Else
2201 0 : Do ICRS = IENDT (IDON1), IDON, -1
2202 0 : If (XDATT(IWRKT (ICRS)) <= XWRK1) Exit
2203 0 : IWRK = IWRKT (ICRS)
2204 0 : XWRK = XDATT (IWRK)
2205 0 : IDCR = ICRS1 - 1
2206 0 : Do IDCR = ICRS1 - 1, 1, - 1
2207 0 : If (XWRK <= XDATT(IWRKT (IDCR))) Exit
2208 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
2209 : End Do
2210 0 : IWRKT (IDCR + 1) = IWRK
2211 0 : IWRK1 = IWRKT(ICRS1)
2212 0 : XWRK1 = XDATT(IWRK1)
2213 : End Do
2214 : end if
2215 : End Do
2216 : !
2217 0 : ires_med = IWRK1
2218 0 : Return
2219 : End If
2220 : !
2221 0 : END Subroutine i_med
2222 :
2223 0 : Function D_indnth (XDONT, NORD) Result (INDNTH)
2224 : ! Return NORDth value of XDONT, i.e fractile of order NORD/SIZE(XDONT).
2225 : ! __________________________________________________________
2226 : ! This routine uses a pivoting strategy such as the one of
2227 : ! finding the median based on the quicksort algorithm, but
2228 : ! we skew the pivot choice to try to bring it to NORD as
2229 : ! fast as possible. It uses 2 temporary arrays, where it
2230 : ! stores the indices of the values smaller than the pivot
2231 : ! (ILOWT), and the indices of values larger than the pivot
2232 : ! that we might still need later on (IHIGT). It iterates
2233 : ! until it can bring the number of values in ILOWT to
2234 : ! exactly NORD, and then finds the maximum of this set.
2235 : ! Michel Olagnon - Aug. 2000
2236 : ! __________________________________________________________
2237 : ! __________________________________________________________
2238 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
2239 : Integer(kind = i4) :: INDNTH
2240 : Integer(kind = i4), Intent (In) :: NORD
2241 : ! __________________________________________________________
2242 0 : real(kind = dp) :: XPIV, XWRK, XWRK1, XMIN, XMAX
2243 : !
2244 0 : Integer(kind = i4), Dimension (NORD) :: IRNGT
2245 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
2246 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
2247 : Integer(kind = i4) :: IMIL, IFIN, ICRS, IDCR, ILOW
2248 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1, INTH
2249 : !
2250 0 : NDON = SIZE (XDONT)
2251 0 : INTH = NORD
2252 : !
2253 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
2254 : !
2255 0 : If (NDON < 2) Then
2256 : If (INTH == 1) INDNTH = 1
2257 : Return
2258 : End If
2259 : !
2260 : ! One chooses a pivot, best estimate possible to put fractile near
2261 : ! mid-point of the set of low values.
2262 : !
2263 0 : If (XDONT(2) < XDONT(1)) Then
2264 0 : ILOWT (1) = 2
2265 0 : IHIGT (1) = 1
2266 : Else
2267 0 : ILOWT (1) = 1
2268 0 : IHIGT (1) = 2
2269 : End If
2270 : !
2271 0 : If (NDON < 3) Then
2272 0 : If (INTH == 1) INDNTH = ILOWT (1)
2273 0 : If (INTH == 2) INDNTH = IHIGT (1)
2274 0 : Return
2275 : End If
2276 : !
2277 0 : If (XDONT(3) < XDONT(IHIGT(1))) Then
2278 0 : IHIGT (2) = IHIGT (1)
2279 0 : If (XDONT(3) < XDONT(ILOWT(1))) Then
2280 0 : IHIGT (1) = ILOWT (1)
2281 0 : ILOWT (1) = 3
2282 : Else
2283 0 : IHIGT (1) = 3
2284 : End If
2285 : Else
2286 0 : IHIGT (2) = 3
2287 : End If
2288 : !
2289 0 : If (NDON < 4) Then
2290 0 : If (INTH == 1) INDNTH = ILOWT (1)
2291 0 : If (INTH == 2) INDNTH = IHIGT (1)
2292 0 : If (INTH == 3) INDNTH = IHIGT (2)
2293 0 : Return
2294 : End If
2295 : !
2296 0 : If (XDONT(NDON) < XDONT(IHIGT(1))) Then
2297 0 : IHIGT (3) = IHIGT (2)
2298 0 : IHIGT (2) = IHIGT (1)
2299 0 : If (XDONT(NDON) < XDONT(ILOWT(1))) Then
2300 0 : IHIGT (1) = ILOWT (1)
2301 0 : ILOWT (1) = NDON
2302 : Else
2303 0 : IHIGT (1) = NDON
2304 : End If
2305 : Else
2306 0 : IHIGT (3) = NDON
2307 : End If
2308 : !
2309 0 : If (NDON < 5) Then
2310 0 : If (INTH == 1) INDNTH = ILOWT (1)
2311 0 : If (INTH == 2) INDNTH = IHIGT (1)
2312 0 : If (INTH == 3) INDNTH = IHIGT (2)
2313 0 : If (INTH == 4) INDNTH = IHIGT (3)
2314 0 : Return
2315 : End If
2316 : !
2317 :
2318 0 : JLOW = 1
2319 0 : JHIG = 3
2320 0 : XPIV = XDONT (ILOWT(1)) + REAL(2 * INTH, dp) / REAL(NDON + INTH, dp) * &
2321 0 : (XDONT(IHIGT(3)) - XDONT(ILOWT(1)))
2322 0 : If (XPIV >= XDONT(IHIGT(1))) Then
2323 : XPIV = XDONT (ILOWT(1)) + REAL(2 * INTH, dp) / REAL(NDON + INTH, dp) * &
2324 0 : (XDONT(IHIGT(2)) - XDONT(ILOWT(1)))
2325 0 : If (XPIV >= XDONT(IHIGT(1))) &
2326 : XPIV = XDONT (ILOWT(1)) + REAL(2 * INTH, dp) / REAL(NDON + INTH, dp) * &
2327 0 : (XDONT(IHIGT(1)) - XDONT(ILOWT(1)))
2328 : End If
2329 : !
2330 : ! One puts values > pivot in the end and those <= pivot
2331 : ! at the beginning. This is split in 2 cases, so that
2332 : ! we can skip the loop test a number of times.
2333 : ! As we are also filling in the work arrays at the same time
2334 : ! we stop filling in the IHIGT array as soon as we have more
2335 : ! than enough values in ILOWT.
2336 : !
2337 : !
2338 0 : If (XDONT(NDON) > XPIV) Then
2339 : ICRS = 3
2340 : Do
2341 0 : ICRS = ICRS + 1
2342 0 : If (XDONT(ICRS) > XPIV) Then
2343 0 : If (ICRS >= NDON) Exit
2344 0 : JHIG = JHIG + 1
2345 0 : IHIGT (JHIG) = ICRS
2346 : Else
2347 0 : JLOW = JLOW + 1
2348 0 : ILOWT (JLOW) = ICRS
2349 0 : If (JLOW >= INTH) Exit
2350 : End If
2351 : End Do
2352 : !
2353 : ! One restricts further processing because it is no use
2354 : ! to store more high values
2355 : !
2356 0 : If (ICRS < NDON - 1) Then
2357 : Do
2358 0 : ICRS = ICRS + 1
2359 0 : If (XDONT(ICRS) <= XPIV) Then
2360 0 : JLOW = JLOW + 1
2361 0 : ILOWT (JLOW) = ICRS
2362 0 : Else If (ICRS >= NDON) Then
2363 : Exit
2364 : End If
2365 : End Do
2366 : End If
2367 : !
2368 : !
2369 : Else
2370 : !
2371 : ! Same as above, but this is not as easy to optimize, so the
2372 : ! DO-loop is kept
2373 : !
2374 0 : Do ICRS = 4, NDON - 1
2375 0 : If (XDONT(ICRS) > XPIV) Then
2376 0 : JHIG = JHIG + 1
2377 0 : IHIGT (JHIG) = ICRS
2378 : Else
2379 0 : JLOW = JLOW + 1
2380 0 : ILOWT (JLOW) = ICRS
2381 0 : If (JLOW >= INTH) Exit
2382 : End If
2383 : End Do
2384 : !
2385 0 : If (ICRS < NDON - 1) Then
2386 : Do
2387 0 : ICRS = ICRS + 1
2388 0 : If (XDONT(ICRS) <= XPIV) Then
2389 0 : If (ICRS >= NDON) Exit
2390 0 : JLOW = JLOW + 1
2391 0 : ILOWT (JLOW) = ICRS
2392 : End If
2393 : End Do
2394 : End If
2395 : End If
2396 : !
2397 : JLM2 = 0
2398 : JLM1 = 0
2399 : JHM2 = 0
2400 : JHM1 = 0
2401 : Do
2402 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
2403 : !
2404 : ! We are oscillating. Perturbate by bringing JLOW closer by one
2405 : ! to INTH
2406 : !
2407 0 : If (INTH > JLOW) Then
2408 0 : XMIN = XDONT (IHIGT(1))
2409 0 : IHIG = 1
2410 0 : Do ICRS = 2, JHIG
2411 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
2412 0 : XMIN = XDONT (IHIGT(ICRS))
2413 0 : IHIG = ICRS
2414 : End If
2415 : End Do
2416 : !
2417 0 : JLOW = JLOW + 1
2418 0 : ILOWT (JLOW) = IHIGT (IHIG)
2419 0 : IHIGT (IHIG) = IHIGT (JHIG)
2420 0 : JHIG = JHIG - 1
2421 : Else
2422 :
2423 0 : ILOW = ILOWT (1)
2424 0 : XMAX = XDONT (ILOW)
2425 0 : Do ICRS = 2, JLOW
2426 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
2427 0 : IWRK = ILOWT (ICRS)
2428 0 : XMAX = XDONT (IWRK)
2429 0 : ILOWT (ICRS) = ILOW
2430 0 : ILOW = IWRK
2431 : End If
2432 : End Do
2433 0 : JLOW = JLOW - 1
2434 : End If
2435 : End If
2436 0 : JLM2 = JLM1
2437 0 : JLM1 = JLOW
2438 0 : JHM2 = JHM1
2439 0 : JHM1 = JHIG
2440 : !
2441 : ! We try to bring the number of values in the low values set
2442 : ! closer to INTH.
2443 : !
2444 0 : Select Case (INTH - JLOW)
2445 : Case (2 :)
2446 : !
2447 : ! Not enough values in low part, at least 2 are missing
2448 : !
2449 0 : INTH = INTH - JLOW
2450 0 : JLOW = 0
2451 : Select Case (JHIG)
2452 : !!!!! CASE DEFAULT
2453 : !!!!! write (unit=*,fmt=*) "Assertion failed"
2454 : !!!!! STOP
2455 : !
2456 : ! We make a special case when we have so few values in
2457 : ! the high values set that it is bad performance to choose a pivot
2458 : ! and apply the general algorithm.
2459 : !
2460 : Case (2)
2461 0 : If (XDONT(IHIGT(1)) <= XDONT(IHIGT(2))) Then
2462 0 : JLOW = JLOW + 1
2463 0 : ILOWT (JLOW) = IHIGT (1)
2464 0 : JLOW = JLOW + 1
2465 0 : ILOWT (JLOW) = IHIGT (2)
2466 : Else
2467 0 : JLOW = JLOW + 1
2468 0 : ILOWT (JLOW) = IHIGT (2)
2469 0 : JLOW = JLOW + 1
2470 0 : ILOWT (JLOW) = IHIGT (1)
2471 : End If
2472 : Exit
2473 : !
2474 : Case (3)
2475 : !
2476 : !
2477 0 : IWRK1 = IHIGT (1)
2478 0 : IWRK2 = IHIGT (2)
2479 0 : IWRK3 = IHIGT (3)
2480 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
2481 0 : IHIGT (1) = IWRK2
2482 0 : IHIGT (2) = IWRK1
2483 0 : IWRK2 = IWRK1
2484 : End If
2485 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
2486 0 : IHIGT (3) = IWRK2
2487 0 : IHIGT (2) = IWRK3
2488 0 : IWRK2 = IWRK3
2489 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
2490 0 : IHIGT (2) = IHIGT (1)
2491 0 : IHIGT (1) = IWRK2
2492 : End If
2493 : End If
2494 : JHIG = 0
2495 0 : Do ICRS = JLOW + 1, INTH
2496 0 : JHIG = JHIG + 1
2497 0 : ILOWT (ICRS) = IHIGT (JHIG)
2498 : End Do
2499 0 : JLOW = INTH
2500 : Exit
2501 : !
2502 : Case (4 :)
2503 : !
2504 : !
2505 0 : IFIN = JHIG
2506 : !
2507 : ! One chooses a pivot from the 2 first values and the last one.
2508 : ! This should ensure sufficient renewal between iterations to
2509 : ! avoid worst case behavior effects.
2510 : !
2511 0 : IWRK1 = IHIGT (1)
2512 0 : IWRK2 = IHIGT (2)
2513 0 : IWRK3 = IHIGT (IFIN)
2514 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
2515 0 : IHIGT (1) = IWRK2
2516 0 : IHIGT (2) = IWRK1
2517 0 : IWRK2 = IWRK1
2518 : End If
2519 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
2520 0 : IHIGT (IFIN) = IWRK2
2521 0 : IHIGT (2) = IWRK3
2522 0 : IWRK2 = IWRK3
2523 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
2524 0 : IHIGT (2) = IHIGT (1)
2525 0 : IHIGT (1) = IWRK2
2526 : End If
2527 : End If
2528 : !
2529 0 : IWRK1 = IHIGT (1)
2530 0 : JLOW = JLOW + 1
2531 0 : ILOWT (JLOW) = IWRK1
2532 0 : XPIV = XDONT (IWRK1) + 0.5 * (XDONT(IHIGT(IFIN)) - XDONT(IWRK1))
2533 : !
2534 : ! One takes values <= pivot to ILOWT
2535 : ! Again, 2 parts, one where we take care of the remaining
2536 : ! high values because we might still need them, and the
2537 : ! other when we know that we will have more than enough
2538 : ! low values in the end.
2539 : !
2540 0 : JHIG = 0
2541 0 : Do ICRS = 2, IFIN
2542 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
2543 0 : JLOW = JLOW + 1
2544 0 : ILOWT (JLOW) = IHIGT (ICRS)
2545 0 : If (JLOW >= INTH) Exit
2546 : Else
2547 0 : JHIG = JHIG + 1
2548 0 : IHIGT (JHIG) = IHIGT (ICRS)
2549 : End If
2550 : End Do
2551 : !
2552 0 : Do ICRS = ICRS + 1, IFIN
2553 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
2554 0 : JLOW = JLOW + 1
2555 0 : ILOWT (JLOW) = IHIGT (ICRS)
2556 : End If
2557 : End Do
2558 : End Select
2559 : !
2560 : !
2561 : Case (1)
2562 : !
2563 : ! Only 1 value is missing in low part
2564 : !
2565 0 : XMIN = XDONT (IHIGT(1))
2566 0 : IHIG = 1
2567 0 : Do ICRS = 2, JHIG
2568 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
2569 0 : XMIN = XDONT (IHIGT(ICRS))
2570 0 : IHIG = ICRS
2571 : End If
2572 : End Do
2573 : !
2574 0 : INDNTH = IHIGT (IHIG)
2575 0 : Return
2576 : !
2577 : !
2578 : Case (0)
2579 : !
2580 : ! Low part is exactly what we want
2581 : !
2582 0 : Exit
2583 : !
2584 : !
2585 : Case (-5 : -1)
2586 : !
2587 : ! Only few values too many in low part
2588 : !
2589 0 : IRNGT (1) = ILOWT (1)
2590 0 : ILOW = 1 + INTH - JLOW
2591 0 : Do ICRS = 2, INTH
2592 0 : IWRK = ILOWT (ICRS)
2593 0 : XWRK = XDONT (IWRK)
2594 0 : Do IDCR = ICRS - 1, MAX (1, ILOW), - 1
2595 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
2596 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
2597 : Else
2598 : Exit
2599 : End If
2600 : End Do
2601 0 : IRNGT (IDCR + 1) = IWRK
2602 0 : ILOW = ILOW + 1
2603 : End Do
2604 : !
2605 0 : XWRK1 = XDONT (IRNGT(INTH))
2606 0 : ILOW = 2 * INTH - JLOW
2607 0 : Do ICRS = INTH + 1, JLOW
2608 0 : If (XDONT(ILOWT (ICRS)) < XWRK1) Then
2609 0 : XWRK = XDONT (ILOWT (ICRS))
2610 0 : Do IDCR = INTH - 1, MAX (1, ILOW), - 1
2611 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
2612 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
2613 : End Do
2614 0 : IRNGT (IDCR + 1) = ILOWT (ICRS)
2615 0 : XWRK1 = XDONT (IRNGT(INTH))
2616 : End If
2617 0 : ILOW = ILOW + 1
2618 : End Do
2619 : !
2620 0 : INDNTH = IRNGT(INTH)
2621 0 : Return
2622 : !
2623 : !
2624 : Case (: -6)
2625 : !
2626 : ! last case: too many values in low part
2627 : !
2628 :
2629 0 : IMIL = (JLOW + 1) / 2
2630 0 : IFIN = JLOW
2631 : !
2632 : ! One chooses a pivot from 1st, last, and middle values
2633 : !
2634 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(1))) Then
2635 0 : IWRK = ILOWT (1)
2636 0 : ILOWT (1) = ILOWT (IMIL)
2637 0 : ILOWT (IMIL) = IWRK
2638 : End If
2639 0 : If (XDONT(ILOWT(IMIL)) > XDONT(ILOWT(IFIN))) Then
2640 0 : IWRK = ILOWT (IFIN)
2641 0 : ILOWT (IFIN) = ILOWT (IMIL)
2642 0 : ILOWT (IMIL) = IWRK
2643 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(1))) Then
2644 0 : IWRK = ILOWT (1)
2645 0 : ILOWT (1) = ILOWT (IMIL)
2646 0 : ILOWT (IMIL) = IWRK
2647 : End If
2648 : End If
2649 0 : If (IFIN <= 3) Exit
2650 : !
2651 0 : XPIV = XDONT (ILOWT(1)) + REAL(INTH, dp) / REAL(JLOW + INTH, dp) * &
2652 0 : (XDONT(ILOWT(IFIN)) - XDONT(ILOWT(1)))
2653 :
2654 : !
2655 : ! One takes values > XPIV to IHIGT
2656 : !
2657 0 : JHIG = 0
2658 0 : JLOW = 0
2659 : !
2660 0 : If (XDONT(ILOWT(IFIN)) > XPIV) Then
2661 : ICRS = 0
2662 : Do
2663 0 : ICRS = ICRS + 1
2664 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
2665 0 : JHIG = JHIG + 1
2666 0 : IHIGT (JHIG) = ILOWT (ICRS)
2667 0 : If (ICRS >= IFIN) Exit
2668 : Else
2669 0 : JLOW = JLOW + 1
2670 0 : ILOWT (JLOW) = ILOWT (ICRS)
2671 0 : If (JLOW >= INTH) Exit
2672 : End If
2673 : End Do
2674 : !
2675 0 : If (ICRS < IFIN) Then
2676 : Do
2677 0 : ICRS = ICRS + 1
2678 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
2679 0 : JLOW = JLOW + 1
2680 0 : ILOWT (JLOW) = ILOWT (ICRS)
2681 : Else
2682 0 : If (ICRS >= IFIN) Exit
2683 : End If
2684 : End Do
2685 : End If
2686 : Else
2687 0 : Do ICRS = 1, IFIN
2688 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
2689 0 : JHIG = JHIG + 1
2690 0 : IHIGT (JHIG) = ILOWT (ICRS)
2691 : Else
2692 0 : JLOW = JLOW + 1
2693 0 : ILOWT (JLOW) = ILOWT (ICRS)
2694 0 : If (JLOW >= INTH) Exit
2695 : End If
2696 : End Do
2697 : !
2698 0 : Do ICRS = ICRS + 1, IFIN
2699 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
2700 0 : JLOW = JLOW + 1
2701 0 : ILOWT (JLOW) = ILOWT (ICRS)
2702 : End If
2703 : End Do
2704 : End If
2705 : !
2706 : End Select
2707 : !
2708 : End Do
2709 : !
2710 : ! Now, we only need to find maximum of the 1:INTH set
2711 : !
2712 :
2713 0 : IWRK1 = ILOWT (1)
2714 0 : XWRK1 = XDONT (IWRK1)
2715 0 : Do ICRS = 1 + 1, INTH
2716 0 : IWRK = ILOWT (ICRS)
2717 0 : XWRK = XDONT (IWRK)
2718 0 : If (XWRK > XWRK1) Then
2719 0 : XWRK1 = XWRK
2720 0 : IWRK1 = IWRK
2721 : End If
2722 : End Do
2723 0 : INDNTH = IWRK1
2724 : Return
2725 : !
2726 : !
2727 0 : End Function D_indnth
2728 :
2729 0 : Function R_indnth (XDONT, NORD) Result (INDNTH)
2730 : ! Return NORDth value of XDONT, i.e fractile of order NORD/SIZE(XDONT).
2731 : ! __________________________________________________________
2732 : ! This routine uses a pivoting strategy such as the one of
2733 : ! finding the median based on the quicksort algorithm, but
2734 : ! we skew the pivot choice to try to bring it to NORD as
2735 : ! fast as possible. It uses 2 temporary arrays, where it
2736 : ! stores the indices of the values smaller than the pivot
2737 : ! (ILOWT), and the indices of values larger than the pivot
2738 : ! that we might still need later on (IHIGT). It iterates
2739 : ! until it can bring the number of values in ILOWT to
2740 : ! exactly NORD, and then finds the maximum of this set.
2741 : ! Michel Olagnon - Aug. 2000
2742 : ! __________________________________________________________
2743 : ! _________________________________________________________
2744 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
2745 : Integer(kind = i4) :: INDNTH
2746 : Integer(kind = i4), Intent (In) :: NORD
2747 : ! __________________________________________________________
2748 0 : Real(kind = sp) :: XPIV, XWRK, XWRK1, XMIN, XMAX
2749 : !
2750 0 : Integer(kind = i4), Dimension (NORD) :: IRNGT
2751 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
2752 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
2753 : Integer(kind = i4) :: IMIL, IFIN, ICRS, IDCR, ILOW
2754 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1, INTH
2755 : !
2756 0 : NDON = SIZE (XDONT)
2757 0 : INTH = NORD
2758 : !
2759 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
2760 : !
2761 0 : If (NDON < 2) Then
2762 : If (INTH == 1) INDNTH = 1
2763 : Return
2764 : End If
2765 : !
2766 : ! One chooses a pivot, best estimate possible to put fractile near
2767 : ! mid-point of the set of low values.
2768 : !
2769 0 : If (XDONT(2) < XDONT(1)) Then
2770 0 : ILOWT (1) = 2
2771 0 : IHIGT (1) = 1
2772 : Else
2773 0 : ILOWT (1) = 1
2774 0 : IHIGT (1) = 2
2775 : End If
2776 : !
2777 0 : If (NDON < 3) Then
2778 0 : If (INTH == 1) INDNTH = ILOWT (1)
2779 0 : If (INTH == 2) INDNTH = IHIGT (1)
2780 0 : Return
2781 : End If
2782 : !
2783 0 : If (XDONT(3) < XDONT(IHIGT(1))) Then
2784 0 : IHIGT (2) = IHIGT (1)
2785 0 : If (XDONT(3) < XDONT(ILOWT(1))) Then
2786 0 : IHIGT (1) = ILOWT (1)
2787 0 : ILOWT (1) = 3
2788 : Else
2789 0 : IHIGT (1) = 3
2790 : End If
2791 : Else
2792 0 : IHIGT (2) = 3
2793 : End If
2794 : !
2795 0 : If (NDON < 4) Then
2796 0 : If (INTH == 1) INDNTH = ILOWT (1)
2797 0 : If (INTH == 2) INDNTH = IHIGT (1)
2798 0 : If (INTH == 3) INDNTH = IHIGT (2)
2799 0 : Return
2800 : End If
2801 : !
2802 0 : If (XDONT(NDON) < XDONT(IHIGT(1))) Then
2803 0 : IHIGT (3) = IHIGT (2)
2804 0 : IHIGT (2) = IHIGT (1)
2805 0 : If (XDONT(NDON) < XDONT(ILOWT(1))) Then
2806 0 : IHIGT (1) = ILOWT (1)
2807 0 : ILOWT (1) = NDON
2808 : Else
2809 0 : IHIGT (1) = NDON
2810 : End If
2811 : Else
2812 0 : IHIGT (3) = NDON
2813 : End If
2814 : !
2815 0 : If (NDON < 5) Then
2816 0 : If (INTH == 1) INDNTH = ILOWT (1)
2817 0 : If (INTH == 2) INDNTH = IHIGT (1)
2818 0 : If (INTH == 3) INDNTH = IHIGT (2)
2819 0 : If (INTH == 4) INDNTH = IHIGT (3)
2820 0 : Return
2821 : End If
2822 : !
2823 :
2824 0 : JLOW = 1
2825 0 : JHIG = 3
2826 0 : XPIV = XDONT (ILOWT(1)) + REAL(2 * INTH, sp) / REAL(NDON + INTH, sp) * &
2827 0 : (XDONT(IHIGT(3)) - XDONT(ILOWT(1)))
2828 0 : If (XPIV >= XDONT(IHIGT(1))) Then
2829 : XPIV = XDONT (ILOWT(1)) + REAL(2 * INTH, sp) / REAL(NDON + INTH, sp) * &
2830 0 : (XDONT(IHIGT(2)) - XDONT(ILOWT(1)))
2831 0 : If (XPIV >= XDONT(IHIGT(1))) &
2832 : XPIV = XDONT (ILOWT(1)) + REAL(2 * INTH, sp) / REAL(NDON + INTH, sp) * &
2833 0 : (XDONT(IHIGT(1)) - XDONT(ILOWT(1)))
2834 : End If
2835 : !
2836 : ! One puts values > pivot in the end and those <= pivot
2837 : ! at the beginning. This is split in 2 cases, so that
2838 : ! we can skip the loop test a number of times.
2839 : ! As we are also filling in the work arrays at the same time
2840 : ! we stop filling in the IHIGT array as soon as we have more
2841 : ! than enough values in ILOWT.
2842 : !
2843 : !
2844 0 : If (XDONT(NDON) > XPIV) Then
2845 : ICRS = 3
2846 : Do
2847 0 : ICRS = ICRS + 1
2848 0 : If (XDONT(ICRS) > XPIV) Then
2849 0 : If (ICRS >= NDON) Exit
2850 0 : JHIG = JHIG + 1
2851 0 : IHIGT (JHIG) = ICRS
2852 : Else
2853 0 : JLOW = JLOW + 1
2854 0 : ILOWT (JLOW) = ICRS
2855 0 : If (JLOW >= INTH) Exit
2856 : End If
2857 : End Do
2858 : !
2859 : ! One restricts further processing because it is no use
2860 : ! to store more high values
2861 : !
2862 0 : If (ICRS < NDON - 1) Then
2863 : Do
2864 0 : ICRS = ICRS + 1
2865 0 : If (XDONT(ICRS) <= XPIV) Then
2866 0 : JLOW = JLOW + 1
2867 0 : ILOWT (JLOW) = ICRS
2868 0 : Else If (ICRS >= NDON) Then
2869 : Exit
2870 : End If
2871 : End Do
2872 : End If
2873 : !
2874 : !
2875 : Else
2876 : !
2877 : ! Same as above, but this is not as easy to optimize, so the
2878 : ! DO-loop is kept
2879 : !
2880 0 : Do ICRS = 4, NDON - 1
2881 0 : If (XDONT(ICRS) > XPIV) Then
2882 0 : JHIG = JHIG + 1
2883 0 : IHIGT (JHIG) = ICRS
2884 : Else
2885 0 : JLOW = JLOW + 1
2886 0 : ILOWT (JLOW) = ICRS
2887 0 : If (JLOW >= INTH) Exit
2888 : End If
2889 : End Do
2890 : !
2891 0 : If (ICRS < NDON - 1) Then
2892 : Do
2893 0 : ICRS = ICRS + 1
2894 0 : If (XDONT(ICRS) <= XPIV) Then
2895 0 : If (ICRS >= NDON) Exit
2896 0 : JLOW = JLOW + 1
2897 0 : ILOWT (JLOW) = ICRS
2898 : End If
2899 : End Do
2900 : End If
2901 : End If
2902 : !
2903 : JLM2 = 0
2904 : JLM1 = 0
2905 : JHM2 = 0
2906 : JHM1 = 0
2907 : Do
2908 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
2909 : !
2910 : ! We are oscillating. Perturbate by bringing JLOW closer by one
2911 : ! to INTH
2912 : !
2913 0 : If (INTH > JLOW) Then
2914 0 : XMIN = XDONT (IHIGT(1))
2915 0 : IHIG = 1
2916 0 : Do ICRS = 2, JHIG
2917 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
2918 0 : XMIN = XDONT (IHIGT(ICRS))
2919 0 : IHIG = ICRS
2920 : End If
2921 : End Do
2922 : !
2923 0 : JLOW = JLOW + 1
2924 0 : ILOWT (JLOW) = IHIGT (IHIG)
2925 0 : IHIGT (IHIG) = IHIGT (JHIG)
2926 0 : JHIG = JHIG - 1
2927 : Else
2928 :
2929 0 : ILOW = ILOWT (1)
2930 0 : XMAX = XDONT (ILOW)
2931 0 : Do ICRS = 2, JLOW
2932 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
2933 0 : IWRK = ILOWT (ICRS)
2934 0 : XMAX = XDONT (IWRK)
2935 0 : ILOWT (ICRS) = ILOW
2936 0 : ILOW = IWRK
2937 : End If
2938 : End Do
2939 0 : JLOW = JLOW - 1
2940 : End If
2941 : End If
2942 0 : JLM2 = JLM1
2943 0 : JLM1 = JLOW
2944 0 : JHM2 = JHM1
2945 0 : JHM1 = JHIG
2946 : !
2947 : ! We try to bring the number of values in the low values set
2948 : ! closer to INTH.
2949 : !
2950 0 : Select Case (INTH - JLOW)
2951 : Case (2 :)
2952 : !
2953 : ! Not enough values in low part, at least 2 are missing
2954 : !
2955 0 : INTH = INTH - JLOW
2956 0 : JLOW = 0
2957 : Select Case (JHIG)
2958 : !!!!! CASE DEFAULT
2959 : !!!!! write (unit=*,fmt=*) "Assertion failed"
2960 : !!!!! STOP
2961 : !
2962 : ! We make a special case when we have so few values in
2963 : ! the high values set that it is bad performance to choose a pivot
2964 : ! and apply the general algorithm.
2965 : !
2966 : Case (2)
2967 0 : If (XDONT(IHIGT(1)) <= XDONT(IHIGT(2))) Then
2968 0 : JLOW = JLOW + 1
2969 0 : ILOWT (JLOW) = IHIGT (1)
2970 0 : JLOW = JLOW + 1
2971 0 : ILOWT (JLOW) = IHIGT (2)
2972 : Else
2973 0 : JLOW = JLOW + 1
2974 0 : ILOWT (JLOW) = IHIGT (2)
2975 0 : JLOW = JLOW + 1
2976 0 : ILOWT (JLOW) = IHIGT (1)
2977 : End If
2978 : Exit
2979 : !
2980 : Case (3)
2981 : !
2982 : !
2983 0 : IWRK1 = IHIGT (1)
2984 0 : IWRK2 = IHIGT (2)
2985 0 : IWRK3 = IHIGT (3)
2986 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
2987 0 : IHIGT (1) = IWRK2
2988 0 : IHIGT (2) = IWRK1
2989 0 : IWRK2 = IWRK1
2990 : End If
2991 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
2992 0 : IHIGT (3) = IWRK2
2993 0 : IHIGT (2) = IWRK3
2994 0 : IWRK2 = IWRK3
2995 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
2996 0 : IHIGT (2) = IHIGT (1)
2997 0 : IHIGT (1) = IWRK2
2998 : End If
2999 : End If
3000 : JHIG = 0
3001 0 : Do ICRS = JLOW + 1, INTH
3002 0 : JHIG = JHIG + 1
3003 0 : ILOWT (ICRS) = IHIGT (JHIG)
3004 : End Do
3005 0 : JLOW = INTH
3006 : Exit
3007 : !
3008 : Case (4 :)
3009 : !
3010 : !
3011 0 : IFIN = JHIG
3012 : !
3013 : ! One chooses a pivot from the 2 first values and the last one.
3014 : ! This should ensure sufficient renewal between iterations to
3015 : ! avoid worst case behavior effects.
3016 : !
3017 0 : IWRK1 = IHIGT (1)
3018 0 : IWRK2 = IHIGT (2)
3019 0 : IWRK3 = IHIGT (IFIN)
3020 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
3021 0 : IHIGT (1) = IWRK2
3022 0 : IHIGT (2) = IWRK1
3023 0 : IWRK2 = IWRK1
3024 : End If
3025 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
3026 0 : IHIGT (IFIN) = IWRK2
3027 0 : IHIGT (2) = IWRK3
3028 0 : IWRK2 = IWRK3
3029 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
3030 0 : IHIGT (2) = IHIGT (1)
3031 0 : IHIGT (1) = IWRK2
3032 : End If
3033 : End If
3034 : !
3035 0 : IWRK1 = IHIGT (1)
3036 0 : JLOW = JLOW + 1
3037 0 : ILOWT (JLOW) = IWRK1
3038 0 : XPIV = XDONT (IWRK1) + 0.5 * (XDONT(IHIGT(IFIN)) - XDONT(IWRK1))
3039 : !
3040 : ! One takes values <= pivot to ILOWT
3041 : ! Again, 2 parts, one where we take care of the remaining
3042 : ! high values because we might still need them, and the
3043 : ! other when we know that we will have more than enough
3044 : ! low values in the end.
3045 : !
3046 0 : JHIG = 0
3047 0 : Do ICRS = 2, IFIN
3048 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
3049 0 : JLOW = JLOW + 1
3050 0 : ILOWT (JLOW) = IHIGT (ICRS)
3051 0 : If (JLOW >= INTH) Exit
3052 : Else
3053 0 : JHIG = JHIG + 1
3054 0 : IHIGT (JHIG) = IHIGT (ICRS)
3055 : End If
3056 : End Do
3057 : !
3058 0 : Do ICRS = ICRS + 1, IFIN
3059 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
3060 0 : JLOW = JLOW + 1
3061 0 : ILOWT (JLOW) = IHIGT (ICRS)
3062 : End If
3063 : End Do
3064 : End Select
3065 : !
3066 : !
3067 : Case (1)
3068 : !
3069 : ! Only 1 value is missing in low part
3070 : !
3071 0 : XMIN = XDONT (IHIGT(1))
3072 0 : IHIG = 1
3073 0 : Do ICRS = 2, JHIG
3074 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
3075 0 : XMIN = XDONT (IHIGT(ICRS))
3076 0 : IHIG = ICRS
3077 : End If
3078 : End Do
3079 : !
3080 0 : INDNTH = IHIGT (IHIG)
3081 0 : Return
3082 : !
3083 : !
3084 : Case (0)
3085 : !
3086 : ! Low part is exactly what we want
3087 : !
3088 0 : Exit
3089 : !
3090 : !
3091 : Case (-5 : -1)
3092 : !
3093 : ! Only few values too many in low part
3094 : !
3095 0 : IRNGT (1) = ILOWT (1)
3096 0 : ILOW = 1 + INTH - JLOW
3097 0 : Do ICRS = 2, INTH
3098 0 : IWRK = ILOWT (ICRS)
3099 0 : XWRK = XDONT (IWRK)
3100 0 : Do IDCR = ICRS - 1, MAX (1, ILOW), - 1
3101 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
3102 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
3103 : Else
3104 : Exit
3105 : End If
3106 : End Do
3107 0 : IRNGT (IDCR + 1) = IWRK
3108 0 : ILOW = ILOW + 1
3109 : End Do
3110 : !
3111 0 : XWRK1 = XDONT (IRNGT(INTH))
3112 0 : ILOW = 2 * INTH - JLOW
3113 0 : Do ICRS = INTH + 1, JLOW
3114 0 : If (XDONT(ILOWT (ICRS)) < XWRK1) Then
3115 0 : XWRK = XDONT (ILOWT (ICRS))
3116 0 : Do IDCR = INTH - 1, MAX (1, ILOW), - 1
3117 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
3118 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
3119 : End Do
3120 0 : IRNGT (IDCR + 1) = ILOWT (ICRS)
3121 0 : XWRK1 = XDONT (IRNGT(INTH))
3122 : End If
3123 0 : ILOW = ILOW + 1
3124 : End Do
3125 : !
3126 0 : INDNTH = IRNGT(INTH)
3127 0 : Return
3128 : !
3129 : !
3130 : Case (: -6)
3131 : !
3132 : ! last case: too many values in low part
3133 : !
3134 :
3135 0 : IMIL = (JLOW + 1) / 2
3136 0 : IFIN = JLOW
3137 : !
3138 : ! One chooses a pivot from 1st, last, and middle values
3139 : !
3140 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(1))) Then
3141 0 : IWRK = ILOWT (1)
3142 0 : ILOWT (1) = ILOWT (IMIL)
3143 0 : ILOWT (IMIL) = IWRK
3144 : End If
3145 0 : If (XDONT(ILOWT(IMIL)) > XDONT(ILOWT(IFIN))) Then
3146 0 : IWRK = ILOWT (IFIN)
3147 0 : ILOWT (IFIN) = ILOWT (IMIL)
3148 0 : ILOWT (IMIL) = IWRK
3149 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(1))) Then
3150 0 : IWRK = ILOWT (1)
3151 0 : ILOWT (1) = ILOWT (IMIL)
3152 0 : ILOWT (IMIL) = IWRK
3153 : End If
3154 : End If
3155 0 : If (IFIN <= 3) Exit
3156 : !
3157 0 : XPIV = XDONT (ILOWT(1)) + REAL(INTH, sp) / REAL(JLOW + INTH, sp) * &
3158 0 : (XDONT(ILOWT(IFIN)) - XDONT(ILOWT(1)))
3159 :
3160 : !
3161 : ! One takes values > XPIV to IHIGT
3162 : !
3163 0 : JHIG = 0
3164 0 : JLOW = 0
3165 : !
3166 0 : If (XDONT(ILOWT(IFIN)) > XPIV) Then
3167 : ICRS = 0
3168 : Do
3169 0 : ICRS = ICRS + 1
3170 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
3171 0 : JHIG = JHIG + 1
3172 0 : IHIGT (JHIG) = ILOWT (ICRS)
3173 0 : If (ICRS >= IFIN) Exit
3174 : Else
3175 0 : JLOW = JLOW + 1
3176 0 : ILOWT (JLOW) = ILOWT (ICRS)
3177 0 : If (JLOW >= INTH) Exit
3178 : End If
3179 : End Do
3180 : !
3181 0 : If (ICRS < IFIN) Then
3182 : Do
3183 0 : ICRS = ICRS + 1
3184 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
3185 0 : JLOW = JLOW + 1
3186 0 : ILOWT (JLOW) = ILOWT (ICRS)
3187 : Else
3188 0 : If (ICRS >= IFIN) Exit
3189 : End If
3190 : End Do
3191 : End If
3192 : Else
3193 0 : Do ICRS = 1, IFIN
3194 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
3195 0 : JHIG = JHIG + 1
3196 0 : IHIGT (JHIG) = ILOWT (ICRS)
3197 : Else
3198 0 : JLOW = JLOW + 1
3199 0 : ILOWT (JLOW) = ILOWT (ICRS)
3200 0 : If (JLOW >= INTH) Exit
3201 : End If
3202 : End Do
3203 : !
3204 0 : Do ICRS = ICRS + 1, IFIN
3205 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
3206 0 : JLOW = JLOW + 1
3207 0 : ILOWT (JLOW) = ILOWT (ICRS)
3208 : End If
3209 : End Do
3210 : End If
3211 : !
3212 : End Select
3213 : !
3214 : End Do
3215 : !
3216 : ! Now, we only need to find maximum of the 1:INTH set
3217 : !
3218 :
3219 0 : IWRK1 = ILOWT (1)
3220 0 : XWRK1 = XDONT (IWRK1)
3221 0 : Do ICRS = 1 + 1, INTH
3222 0 : IWRK = ILOWT (ICRS)
3223 0 : XWRK = XDONT (IWRK)
3224 0 : If (XWRK > XWRK1) Then
3225 0 : XWRK1 = XWRK
3226 0 : IWRK1 = IWRK
3227 : End If
3228 : End Do
3229 0 : INDNTH = IWRK1
3230 : Return
3231 : !
3232 : !
3233 0 : End Function R_indnth
3234 :
3235 0 : Function I_indnth (XDONT, NORD) Result (INDNTH)
3236 : ! Return NORDth value of XDONT, i.e fractile of order NORD/SIZE(XDONT).
3237 : ! __________________________________________________________
3238 : ! This routine uses a pivoting strategy such as the one of
3239 : ! finding the median based on the quicksort algorithm, but
3240 : ! we skew the pivot choice to try to bring it to NORD as
3241 : ! fast as possible. It uses 2 temporary arrays, where it
3242 : ! stores the indices of the values smaller than the pivot
3243 : ! (ILOWT), and the indices of values larger than the pivot
3244 : ! that we might still need later on (IHIGT). It iterates
3245 : ! until it can bring the number of values in ILOWT to
3246 : ! exactly NORD, and then finds the maximum of this set.
3247 : ! Michel Olagnon - Aug. 2000
3248 : ! __________________________________________________________
3249 : ! __________________________________________________________
3250 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
3251 : Integer(kind = i4) :: INDNTH
3252 : Integer(kind = i4), Intent (In) :: NORD
3253 : ! __________________________________________________________
3254 : Integer(kind = i4) :: XPIV, XWRK, XWRK1, XMIN, XMAX
3255 : !
3256 0 : Integer(kind = i4), Dimension (NORD) :: IRNGT
3257 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
3258 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
3259 : Integer(kind = i4) :: IMIL, IFIN, ICRS, IDCR, ILOW
3260 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1, INTH
3261 : !
3262 0 : NDON = SIZE (XDONT)
3263 0 : INTH = NORD
3264 : !
3265 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
3266 : !
3267 0 : If (NDON < 2) Then
3268 : If (INTH == 1) INDNTH = 1
3269 : Return
3270 : End If
3271 : !
3272 : ! One chooses a pivot, best estimate possible to put fractile near
3273 : ! mid-point of the set of low values.
3274 : !
3275 0 : If (XDONT(2) < XDONT(1)) Then
3276 0 : ILOWT (1) = 2
3277 0 : IHIGT (1) = 1
3278 : Else
3279 0 : ILOWT (1) = 1
3280 0 : IHIGT (1) = 2
3281 : End If
3282 : !
3283 0 : If (NDON < 3) Then
3284 0 : If (INTH == 1) INDNTH = ILOWT (1)
3285 0 : If (INTH == 2) INDNTH = IHIGT (1)
3286 0 : Return
3287 : End If
3288 : !
3289 0 : If (XDONT(3) < XDONT(IHIGT(1))) Then
3290 0 : IHIGT (2) = IHIGT (1)
3291 0 : If (XDONT(3) < XDONT(ILOWT(1))) Then
3292 0 : IHIGT (1) = ILOWT (1)
3293 0 : ILOWT (1) = 3
3294 : Else
3295 0 : IHIGT (1) = 3
3296 : End If
3297 : Else
3298 0 : IHIGT (2) = 3
3299 : End If
3300 : !
3301 0 : If (NDON < 4) Then
3302 0 : If (INTH == 1) INDNTH = ILOWT (1)
3303 0 : If (INTH == 2) INDNTH = IHIGT (1)
3304 0 : If (INTH == 3) INDNTH = IHIGT (2)
3305 0 : Return
3306 : End If
3307 : !
3308 0 : If (XDONT(NDON) < XDONT(IHIGT(1))) Then
3309 0 : IHIGT (3) = IHIGT (2)
3310 0 : IHIGT (2) = IHIGT (1)
3311 0 : If (XDONT(NDON) < XDONT(ILOWT(1))) Then
3312 0 : IHIGT (1) = ILOWT (1)
3313 0 : ILOWT (1) = NDON
3314 : Else
3315 0 : IHIGT (1) = NDON
3316 : End If
3317 : Else
3318 0 : IHIGT (3) = NDON
3319 : End If
3320 : !
3321 0 : If (NDON < 5) Then
3322 0 : If (INTH == 1) INDNTH = ILOWT (1)
3323 0 : If (INTH == 2) INDNTH = IHIGT (1)
3324 0 : If (INTH == 3) INDNTH = IHIGT (2)
3325 0 : If (INTH == 4) INDNTH = IHIGT (3)
3326 0 : Return
3327 : End If
3328 : !
3329 :
3330 0 : JLOW = 1
3331 0 : JHIG = 3
3332 0 : XPIV = XDONT (ILOWT(1)) + INT(REAL(2 * INTH, sp) / REAL(NDON + INTH, sp), i4) * &
3333 0 : (XDONT(IHIGT(3)) - XDONT(ILOWT(1)))
3334 0 : If (XPIV >= XDONT(IHIGT(1))) Then
3335 : XPIV = XDONT (ILOWT(1)) + INT(REAL(2 * INTH, sp) / REAL(NDON + INTH, sp), i4) * &
3336 0 : (XDONT(IHIGT(2)) - XDONT(ILOWT(1)))
3337 0 : If (XPIV >= XDONT(IHIGT(1))) &
3338 : XPIV = XDONT (ILOWT(1)) + INT(REAL(2 * INTH, sp) / REAL(NDON + INTH, sp), i4) * &
3339 0 : (XDONT(IHIGT(1)) - XDONT(ILOWT(1)))
3340 : End If
3341 : !
3342 : ! One puts values > pivot in the end and those <= pivot
3343 : ! at the beginning. This is split in 2 cases, so that
3344 : ! we can skip the loop test a number of times.
3345 : ! As we are also filling in the work arrays at the same time
3346 : ! we stop filling in the IHIGT array as soon as we have more
3347 : ! than enough values in ILOWT.
3348 : !
3349 : !
3350 0 : If (XDONT(NDON) > XPIV) Then
3351 : ICRS = 3
3352 : Do
3353 0 : ICRS = ICRS + 1
3354 0 : If (XDONT(ICRS) > XPIV) Then
3355 0 : If (ICRS >= NDON) Exit
3356 0 : JHIG = JHIG + 1
3357 0 : IHIGT (JHIG) = ICRS
3358 : Else
3359 0 : JLOW = JLOW + 1
3360 0 : ILOWT (JLOW) = ICRS
3361 0 : If (JLOW >= INTH) Exit
3362 : End If
3363 : End Do
3364 : !
3365 : ! One restricts further processing because it is no use
3366 : ! to store more high values
3367 : !
3368 0 : If (ICRS < NDON - 1) Then
3369 : Do
3370 0 : ICRS = ICRS + 1
3371 0 : If (XDONT(ICRS) <= XPIV) Then
3372 0 : JLOW = JLOW + 1
3373 0 : ILOWT (JLOW) = ICRS
3374 0 : Else If (ICRS >= NDON) Then
3375 : Exit
3376 : End If
3377 : End Do
3378 : End If
3379 : !
3380 : !
3381 : Else
3382 : !
3383 : ! Same as above, but this is not as easy to optimize, so the
3384 : ! DO-loop is kept
3385 : !
3386 0 : Do ICRS = 4, NDON - 1
3387 0 : If (XDONT(ICRS) > XPIV) Then
3388 0 : JHIG = JHIG + 1
3389 0 : IHIGT (JHIG) = ICRS
3390 : Else
3391 0 : JLOW = JLOW + 1
3392 0 : ILOWT (JLOW) = ICRS
3393 0 : If (JLOW >= INTH) Exit
3394 : End If
3395 : End Do
3396 : !
3397 0 : If (ICRS < NDON - 1) Then
3398 : Do
3399 0 : ICRS = ICRS + 1
3400 0 : If (XDONT(ICRS) <= XPIV) Then
3401 0 : If (ICRS >= NDON) Exit
3402 0 : JLOW = JLOW + 1
3403 0 : ILOWT (JLOW) = ICRS
3404 : End If
3405 : End Do
3406 : End If
3407 : End If
3408 : !
3409 : JLM2 = 0
3410 : JLM1 = 0
3411 : JHM2 = 0
3412 : JHM1 = 0
3413 : Do
3414 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
3415 : !
3416 : ! We are oscillating. Perturbate by bringing JLOW closer by one
3417 : ! to INTH
3418 : !
3419 0 : If (INTH > JLOW) Then
3420 0 : XMIN = XDONT (IHIGT(1))
3421 0 : IHIG = 1
3422 0 : Do ICRS = 2, JHIG
3423 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
3424 0 : XMIN = XDONT (IHIGT(ICRS))
3425 0 : IHIG = ICRS
3426 : End If
3427 : End Do
3428 : !
3429 0 : JLOW = JLOW + 1
3430 0 : ILOWT (JLOW) = IHIGT (IHIG)
3431 0 : IHIGT (IHIG) = IHIGT (JHIG)
3432 0 : JHIG = JHIG - 1
3433 : Else
3434 :
3435 0 : ILOW = ILOWT (1)
3436 0 : XMAX = XDONT (ILOW)
3437 0 : Do ICRS = 2, JLOW
3438 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
3439 0 : IWRK = ILOWT (ICRS)
3440 0 : XMAX = XDONT (IWRK)
3441 0 : ILOWT (ICRS) = ILOW
3442 0 : ILOW = IWRK
3443 : End If
3444 : End Do
3445 0 : JLOW = JLOW - 1
3446 : End If
3447 : End If
3448 0 : JLM2 = JLM1
3449 0 : JLM1 = JLOW
3450 0 : JHM2 = JHM1
3451 0 : JHM1 = JHIG
3452 : !
3453 : ! We try to bring the number of values in the low values set
3454 : ! closer to INTH.
3455 : !
3456 0 : Select Case (INTH - JLOW)
3457 : Case (2 :)
3458 : !
3459 : ! Not enough values in low part, at least 2 are missing
3460 : !
3461 0 : INTH = INTH - JLOW
3462 0 : JLOW = 0
3463 : Select Case (JHIG)
3464 : !!!!! CASE DEFAULT
3465 : !!!!! write (unit=*,fmt=*) "Assertion failed"
3466 : !!!!! STOP
3467 : !
3468 : ! We make a special case when we have so few values in
3469 : ! the high values set that it is bad performance to choose a pivot
3470 : ! and apply the general algorithm.
3471 : !
3472 : Case (2)
3473 0 : If (XDONT(IHIGT(1)) <= XDONT(IHIGT(2))) Then
3474 0 : JLOW = JLOW + 1
3475 0 : ILOWT (JLOW) = IHIGT (1)
3476 0 : JLOW = JLOW + 1
3477 0 : ILOWT (JLOW) = IHIGT (2)
3478 : Else
3479 0 : JLOW = JLOW + 1
3480 0 : ILOWT (JLOW) = IHIGT (2)
3481 0 : JLOW = JLOW + 1
3482 0 : ILOWT (JLOW) = IHIGT (1)
3483 : End If
3484 : Exit
3485 : !
3486 : Case (3)
3487 : !
3488 : !
3489 0 : IWRK1 = IHIGT (1)
3490 0 : IWRK2 = IHIGT (2)
3491 0 : IWRK3 = IHIGT (3)
3492 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
3493 0 : IHIGT (1) = IWRK2
3494 0 : IHIGT (2) = IWRK1
3495 0 : IWRK2 = IWRK1
3496 : End If
3497 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
3498 0 : IHIGT (3) = IWRK2
3499 0 : IHIGT (2) = IWRK3
3500 0 : IWRK2 = IWRK3
3501 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
3502 0 : IHIGT (2) = IHIGT (1)
3503 0 : IHIGT (1) = IWRK2
3504 : End If
3505 : End If
3506 : JHIG = 0
3507 0 : Do ICRS = JLOW + 1, INTH
3508 0 : JHIG = JHIG + 1
3509 0 : ILOWT (ICRS) = IHIGT (JHIG)
3510 : End Do
3511 0 : JLOW = INTH
3512 : Exit
3513 : !
3514 : Case (4 :)
3515 : !
3516 : !
3517 0 : IFIN = JHIG
3518 : !
3519 : ! One chooses a pivot from the 2 first values and the last one.
3520 : ! This should ensure sufficient renewal between iterations to
3521 : ! avoid worst case behavior effects.
3522 : !
3523 0 : IWRK1 = IHIGT (1)
3524 0 : IWRK2 = IHIGT (2)
3525 0 : IWRK3 = IHIGT (IFIN)
3526 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
3527 0 : IHIGT (1) = IWRK2
3528 0 : IHIGT (2) = IWRK1
3529 0 : IWRK2 = IWRK1
3530 : End If
3531 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
3532 0 : IHIGT (IFIN) = IWRK2
3533 0 : IHIGT (2) = IWRK3
3534 0 : IWRK2 = IWRK3
3535 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
3536 0 : IHIGT (2) = IHIGT (1)
3537 0 : IHIGT (1) = IWRK2
3538 : End If
3539 : End If
3540 : !
3541 0 : IWRK1 = IHIGT (1)
3542 0 : JLOW = JLOW + 1
3543 0 : ILOWT (JLOW) = IWRK1
3544 0 : XPIV = XDONT (IWRK1) + (XDONT(IHIGT(IFIN)) - XDONT(IWRK1)) / 2
3545 : !
3546 : ! One takes values <= pivot to ILOWT
3547 : ! Again, 2 parts, one where we take care of the remaining
3548 : ! high values because we might still need them, and the
3549 : ! other when we know that we will have more than enough
3550 : ! low values in the end.
3551 : !
3552 0 : JHIG = 0
3553 0 : Do ICRS = 2, IFIN
3554 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
3555 0 : JLOW = JLOW + 1
3556 0 : ILOWT (JLOW) = IHIGT (ICRS)
3557 0 : If (JLOW >= INTH) Exit
3558 : Else
3559 0 : JHIG = JHIG + 1
3560 0 : IHIGT (JHIG) = IHIGT (ICRS)
3561 : End If
3562 : End Do
3563 : !
3564 0 : Do ICRS = ICRS + 1, IFIN
3565 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
3566 0 : JLOW = JLOW + 1
3567 0 : ILOWT (JLOW) = IHIGT (ICRS)
3568 : End If
3569 : End Do
3570 : End Select
3571 : !
3572 : !
3573 : Case (1)
3574 : !
3575 : ! Only 1 value is missing in low part
3576 : !
3577 0 : XMIN = XDONT (IHIGT(1))
3578 0 : IHIG = 1
3579 0 : Do ICRS = 2, JHIG
3580 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
3581 0 : XMIN = XDONT (IHIGT(ICRS))
3582 0 : IHIG = ICRS
3583 : End If
3584 : End Do
3585 : !
3586 0 : INDNTH = IHIGT (IHIG)
3587 0 : Return
3588 : !
3589 : !
3590 : Case (0)
3591 : !
3592 : ! Low part is exactly what we want
3593 : !
3594 0 : Exit
3595 : !
3596 : !
3597 : Case (-5 : -1)
3598 : !
3599 : ! Only few values too many in low part
3600 : !
3601 0 : IRNGT (1) = ILOWT (1)
3602 0 : ILOW = 1 + INTH - JLOW
3603 0 : Do ICRS = 2, INTH
3604 0 : IWRK = ILOWT (ICRS)
3605 0 : XWRK = XDONT (IWRK)
3606 0 : Do IDCR = ICRS - 1, MAX (1, ILOW), - 1
3607 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
3608 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
3609 : Else
3610 : Exit
3611 : End If
3612 : End Do
3613 0 : IRNGT (IDCR + 1) = IWRK
3614 0 : ILOW = ILOW + 1
3615 : End Do
3616 : !
3617 0 : XWRK1 = XDONT (IRNGT(INTH))
3618 0 : ILOW = 2 * INTH - JLOW
3619 0 : Do ICRS = INTH + 1, JLOW
3620 0 : If (XDONT(ILOWT (ICRS)) < XWRK1) Then
3621 0 : XWRK = XDONT (ILOWT (ICRS))
3622 0 : Do IDCR = INTH - 1, MAX (1, ILOW), - 1
3623 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
3624 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
3625 : End Do
3626 0 : IRNGT (IDCR + 1) = ILOWT (ICRS)
3627 0 : XWRK1 = XDONT (IRNGT(INTH))
3628 : End If
3629 0 : ILOW = ILOW + 1
3630 : End Do
3631 : !
3632 0 : INDNTH = IRNGT(INTH)
3633 0 : Return
3634 : !
3635 : !
3636 : Case (: -6)
3637 : !
3638 : ! last case: too many values in low part
3639 : !
3640 :
3641 0 : IMIL = (JLOW + 1) / 2
3642 0 : IFIN = JLOW
3643 : !
3644 : ! One chooses a pivot from 1st, last, and middle values
3645 : !
3646 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(1))) Then
3647 0 : IWRK = ILOWT (1)
3648 0 : ILOWT (1) = ILOWT (IMIL)
3649 0 : ILOWT (IMIL) = IWRK
3650 : End If
3651 0 : If (XDONT(ILOWT(IMIL)) > XDONT(ILOWT(IFIN))) Then
3652 0 : IWRK = ILOWT (IFIN)
3653 0 : ILOWT (IFIN) = ILOWT (IMIL)
3654 0 : ILOWT (IMIL) = IWRK
3655 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(1))) Then
3656 0 : IWRK = ILOWT (1)
3657 0 : ILOWT (1) = ILOWT (IMIL)
3658 0 : ILOWT (IMIL) = IWRK
3659 : End If
3660 : End If
3661 0 : If (IFIN <= 3) Exit
3662 : !
3663 0 : XPIV = XDONT (ILOWT(1)) + INT(REAL(INTH, sp) / REAL(JLOW + INTH, sp), i4) * &
3664 0 : (XDONT(ILOWT(IFIN)) - XDONT(ILOWT(1)))
3665 :
3666 : !
3667 : ! One takes values > XPIV to IHIGT
3668 : !
3669 0 : JHIG = 0
3670 0 : JLOW = 0
3671 : !
3672 0 : If (XDONT(ILOWT(IFIN)) > XPIV) Then
3673 : ICRS = 0
3674 : Do
3675 0 : ICRS = ICRS + 1
3676 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
3677 0 : JHIG = JHIG + 1
3678 0 : IHIGT (JHIG) = ILOWT (ICRS)
3679 0 : If (ICRS >= IFIN) Exit
3680 : Else
3681 0 : JLOW = JLOW + 1
3682 0 : ILOWT (JLOW) = ILOWT (ICRS)
3683 0 : If (JLOW >= INTH) Exit
3684 : End If
3685 : End Do
3686 : !
3687 0 : If (ICRS < IFIN) Then
3688 : Do
3689 0 : ICRS = ICRS + 1
3690 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
3691 0 : JLOW = JLOW + 1
3692 0 : ILOWT (JLOW) = ILOWT (ICRS)
3693 : Else
3694 0 : If (ICRS >= IFIN) Exit
3695 : End If
3696 : End Do
3697 : End If
3698 : Else
3699 0 : Do ICRS = 1, IFIN
3700 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
3701 0 : JHIG = JHIG + 1
3702 0 : IHIGT (JHIG) = ILOWT (ICRS)
3703 : Else
3704 0 : JLOW = JLOW + 1
3705 0 : ILOWT (JLOW) = ILOWT (ICRS)
3706 0 : If (JLOW >= INTH) Exit
3707 : End If
3708 : End Do
3709 : !
3710 0 : Do ICRS = ICRS + 1, IFIN
3711 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
3712 0 : JLOW = JLOW + 1
3713 0 : ILOWT (JLOW) = ILOWT (ICRS)
3714 : End If
3715 : End Do
3716 : End If
3717 : !
3718 : End Select
3719 : !
3720 : End Do
3721 : !
3722 : ! Now, we only need to find maximum of the 1:INTH set
3723 : !
3724 :
3725 0 : IWRK1 = ILOWT (1)
3726 0 : XWRK1 = XDONT (IWRK1)
3727 0 : Do ICRS = 1 + 1, INTH
3728 0 : IWRK = ILOWT (ICRS)
3729 0 : XWRK = XDONT (IWRK)
3730 0 : If (XWRK > XWRK1) Then
3731 0 : XWRK1 = XWRK
3732 0 : IWRK1 = IWRK
3733 : End If
3734 : End Do
3735 0 : INDNTH = IWRK1
3736 : Return
3737 : !
3738 : !
3739 0 : End Function I_indnth
3740 :
3741 0 : Subroutine D_inspar (XDONT, NORD)
3742 : ! Sorts partially XDONT, bringing the NORD lowest values at the
3743 : ! begining of the array
3744 : ! __________________________________________________________
3745 : ! This subroutine uses insertion sort, limiting insertion
3746 : ! to the first NORD values. It does not use any work array
3747 : ! and is faster when NORD is very small (2-5), but worst case
3748 : ! behavior can happen fairly probably (initially inverse sorted)
3749 : ! In many cases, the refined quicksort method is faster.
3750 : ! Michel Olagnon - Feb. 2000
3751 : ! __________________________________________________________
3752 : ! __________________________________________________________
3753 : real(kind = dp), Dimension (:), Intent (InOut) :: XDONT
3754 : Integer(kind = i4), Intent (In) :: NORD
3755 : ! __________________________________________________________
3756 0 : real(kind = dp) :: XWRK, XWRK1
3757 : !
3758 : Integer(kind = i4) :: ICRS, IDCR
3759 : !
3760 0 : Do ICRS = 2, NORD
3761 0 : XWRK = XDONT (ICRS)
3762 0 : Do IDCR = ICRS - 1, 1, - 1
3763 0 : If (XWRK >= XDONT(IDCR)) Exit
3764 0 : XDONT (IDCR + 1) = XDONT (IDCR)
3765 : End Do
3766 0 : XDONT (IDCR + 1) = XWRK
3767 : End Do
3768 : !
3769 0 : XWRK1 = XDONT (NORD)
3770 0 : Do ICRS = NORD + 1, SIZE (XDONT)
3771 0 : If (XDONT(ICRS) < XWRK1) Then
3772 0 : XWRK = XDONT (ICRS)
3773 0 : XDONT (ICRS) = XWRK1
3774 0 : Do IDCR = NORD - 1, 1, - 1
3775 0 : If (XWRK >= XDONT(IDCR)) Exit
3776 0 : XDONT (IDCR + 1) = XDONT (IDCR)
3777 : End Do
3778 0 : XDONT (IDCR + 1) = XWRK
3779 0 : XWRK1 = XDONT (NORD)
3780 : End If
3781 : End Do
3782 : !
3783 : !
3784 0 : End Subroutine D_inspar
3785 :
3786 0 : Subroutine R_inspar (XDONT, NORD)
3787 : ! Sorts partially XDONT, bringing the NORD lowest values at the
3788 : ! begining of the array
3789 : ! __________________________________________________________
3790 : ! This subroutine uses insertion sort, limiting insertion
3791 : ! to the first NORD values. It does not use any work array
3792 : ! and is faster when NORD is very small (2-5), but worst case
3793 : ! behavior can happen fairly probably (initially inverse sorted)
3794 : ! In many cases, the refined quicksort method is faster.
3795 : ! Michel Olagnon - Feb. 2000
3796 : ! __________________________________________________________
3797 : ! _________________________________________________________
3798 : Real(kind = sp), Dimension (:), Intent (InOut) :: XDONT
3799 : Integer(kind = i4), Intent (In) :: NORD
3800 : ! __________________________________________________________
3801 0 : Real(kind = sp) :: XWRK, XWRK1
3802 : !
3803 : Integer(kind = i4) :: ICRS, IDCR
3804 : !
3805 0 : Do ICRS = 2, NORD
3806 0 : XWRK = XDONT (ICRS)
3807 0 : Do IDCR = ICRS - 1, 1, - 1
3808 0 : If (XWRK >= XDONT(IDCR)) Exit
3809 0 : XDONT (IDCR + 1) = XDONT (IDCR)
3810 : End Do
3811 0 : XDONT (IDCR + 1) = XWRK
3812 : End Do
3813 : !
3814 0 : XWRK1 = XDONT (NORD)
3815 0 : Do ICRS = NORD + 1, SIZE (XDONT)
3816 0 : If (XDONT(ICRS) < XWRK1) Then
3817 0 : XWRK = XDONT (ICRS)
3818 0 : XDONT (ICRS) = XWRK1
3819 0 : Do IDCR = NORD - 1, 1, - 1
3820 0 : If (XWRK >= XDONT(IDCR)) Exit
3821 0 : XDONT (IDCR + 1) = XDONT (IDCR)
3822 : End Do
3823 0 : XDONT (IDCR + 1) = XWRK
3824 0 : XWRK1 = XDONT (NORD)
3825 : End If
3826 : End Do
3827 : !
3828 : !
3829 0 : End Subroutine R_inspar
3830 :
3831 0 : Subroutine I_inspar (XDONT, NORD)
3832 : ! Sorts partially XDONT, bringing the NORD lowest values at the
3833 : ! begining of the array
3834 : ! __________________________________________________________
3835 : ! This subroutine uses insertion sort, limiting insertion
3836 : ! to the first NORD values. It does not use any work array
3837 : ! and is faster when NORD is very small (2-5), but worst case
3838 : ! behavior can happen fairly probably (initially inverse sorted)
3839 : ! In many cases, the refined quicksort method is faster.
3840 : ! Michel Olagnon - Feb. 2000
3841 : ! __________________________________________________________
3842 : ! __________________________________________________________
3843 : Integer(kind = i4), Dimension (:), Intent (InOut) :: XDONT
3844 : Integer(kind = i4), Intent (In) :: NORD
3845 : ! __________________________________________________________
3846 : Integer(kind = i4) :: XWRK, XWRK1
3847 : !
3848 : Integer(kind = i4) :: ICRS, IDCR
3849 : !
3850 0 : Do ICRS = 2, NORD
3851 0 : XWRK = XDONT (ICRS)
3852 0 : Do IDCR = ICRS - 1, 1, - 1
3853 0 : If (XWRK >= XDONT(IDCR)) Exit
3854 0 : XDONT (IDCR + 1) = XDONT (IDCR)
3855 : End Do
3856 0 : XDONT (IDCR + 1) = XWRK
3857 : End Do
3858 : !
3859 0 : XWRK1 = XDONT (NORD)
3860 0 : Do ICRS = NORD + 1, SIZE (XDONT)
3861 0 : If (XDONT(ICRS) < XWRK1) Then
3862 0 : XWRK = XDONT (ICRS)
3863 0 : XDONT (ICRS) = XWRK1
3864 0 : Do IDCR = NORD - 1, 1, - 1
3865 0 : If (XWRK >= XDONT(IDCR)) Exit
3866 0 : XDONT (IDCR + 1) = XDONT (IDCR)
3867 : End Do
3868 0 : XDONT (IDCR + 1) = XWRK
3869 0 : XWRK1 = XDONT (NORD)
3870 : End If
3871 : End Do
3872 : !
3873 : !
3874 0 : End Subroutine I_inspar
3875 :
3876 4 : Subroutine D_inssor (XDONT)
3877 : ! Sorts XDONT into increasing order (Insertion sort)
3878 : ! __________________________________________________________
3879 : ! This subroutine uses insertion sort. It does not use any
3880 : ! work array and is faster when XDONT is of very small size
3881 : ! (< 20), or already almost sorted, but worst case behavior
3882 : ! can happen fairly probably (initially inverse sorted).
3883 : ! In many cases, the quicksort or merge sort method is faster.
3884 : ! Michel Olagnon - Apr. 2000
3885 : ! __________________________________________________________
3886 : ! __________________________________________________________
3887 : ! __________________________________________________________
3888 : real(kind = dp), Dimension (:), Intent (InOut) :: XDONT
3889 : ! __________________________________________________________
3890 4 : real(Kind = dp) :: XWRK, XMIN
3891 : !
3892 : ! __________________________________________________________
3893 : !
3894 : Integer(kind = i4) :: ICRS, IDCR, NDON
3895 : !
3896 4 : NDON = Size (XDONT)
3897 : !
3898 : ! We first bring the minimum to the first location in the array.
3899 : ! That way, we will have a "guard", and when looking for the
3900 : ! right place to insert a value, no loop test is necessary.
3901 : !
3902 4 : If (XDONT (1) < XDONT (NDON)) Then
3903 : XMIN = XDONT (1)
3904 : Else
3905 2 : XMIN = XDONT (NDON)
3906 2 : XDONT (NDON) = XDONT (1)
3907 : end if
3908 152 : Do IDCR = NDON - 1, 2, -1
3909 148 : XWRK = XDONT(IDCR)
3910 152 : IF (XWRK < XMIN) Then
3911 0 : XDONT (IDCR) = XMIN
3912 0 : XMIN = XWRK
3913 : End If
3914 : End Do
3915 4 : XDONT (1) = XMIN
3916 : !
3917 : ! The first value is now the minimum
3918 : ! Loop over the array, and when a value is smaller than
3919 : ! the previous one, loop down to insert it at its right place.
3920 : !
3921 152 : Do ICRS = 3, NDON
3922 148 : XWRK = XDONT (ICRS)
3923 148 : IDCR = ICRS - 1
3924 152 : If (XWRK < XDONT(IDCR)) Then
3925 108 : XDONT (ICRS) = XDONT (IDCR)
3926 108 : IDCR = IDCR - 1
3927 311 : Do
3928 419 : If (XWRK >= XDONT(IDCR)) Exit
3929 311 : XDONT (IDCR + 1) = XDONT (IDCR)
3930 311 : IDCR = IDCR - 1
3931 : End Do
3932 108 : XDONT (IDCR + 1) = XWRK
3933 : End If
3934 : End Do
3935 : !
3936 4 : Return
3937 : !
3938 0 : End Subroutine D_inssor
3939 :
3940 2 : Subroutine R_inssor (XDONT)
3941 : ! Sorts XDONT into increasing order (Insertion sort)
3942 : ! __________________________________________________________
3943 : ! This subroutine uses insertion sort. It does not use any
3944 : ! work array and is faster when XDONT is of very small size
3945 : ! (< 20), or already almost sorted, but worst case behavior
3946 : ! can happen fairly probably (initially inverse sorted).
3947 : ! In many cases, the quicksort or merge sort method is faster.
3948 : ! Michel Olagnon - Apr. 2000
3949 : ! __________________________________________________________
3950 : ! __________________________________________________________
3951 : ! _________________________________________________________
3952 : Real(kind = sp), Dimension (:), Intent (InOut) :: XDONT
3953 : ! __________________________________________________________
3954 2 : Real(kind = sp) :: XWRK, XMIN
3955 : !
3956 : ! __________________________________________________________
3957 : !
3958 : Integer(kind = i4) :: ICRS, IDCR, NDON
3959 : !
3960 2 : NDON = Size (XDONT)
3961 : !
3962 : ! We first bring the minimum to the first location in the array.
3963 : ! That way, we will have a "guard", and when looking for the
3964 : ! right place to insert a value, no loop test is necessary.
3965 : !
3966 2 : If (XDONT (1) < XDONT (NDON)) Then
3967 : XMIN = XDONT (1)
3968 : Else
3969 2 : XMIN = XDONT (NDON)
3970 2 : XDONT (NDON) = XDONT (1)
3971 : end if
3972 18 : Do IDCR = NDON - 1, 2, -1
3973 16 : XWRK = XDONT(IDCR)
3974 18 : IF (XWRK < XMIN) Then
3975 0 : XDONT (IDCR) = XMIN
3976 0 : XMIN = XWRK
3977 : End If
3978 : End Do
3979 2 : XDONT (1) = XMIN
3980 : !
3981 : ! The first value is now the minimum
3982 : ! Loop over the array, and when a value is smaller than
3983 : ! the previous one, loop down to insert it at its right place.
3984 : !
3985 18 : Do ICRS = 3, NDON
3986 16 : XWRK = XDONT (ICRS)
3987 16 : IDCR = ICRS - 1
3988 18 : If (XWRK < XDONT(IDCR)) Then
3989 14 : XDONT (ICRS) = XDONT (IDCR)
3990 14 : IDCR = IDCR - 1
3991 42 : Do
3992 56 : If (XWRK >= XDONT(IDCR)) Exit
3993 42 : XDONT (IDCR + 1) = XDONT (IDCR)
3994 42 : IDCR = IDCR - 1
3995 : End Do
3996 14 : XDONT (IDCR + 1) = XWRK
3997 : End If
3998 : End Do
3999 : !
4000 2 : Return
4001 : !
4002 4 : End Subroutine R_inssor
4003 :
4004 4452 : Subroutine I_inssor (XDONT)
4005 : ! Sorts XDONT into increasing order (Insertion sort)
4006 : ! __________________________________________________________
4007 : ! This subroutine uses insertion sort. It does not use any
4008 : ! work array and is faster when XDONT is of very small size
4009 : ! (< 20), or already almost sorted, but worst case behavior
4010 : ! can happen fairly probably (initially inverse sorted).
4011 : ! In many cases, the quicksort or merge sort method is faster.
4012 : ! Michel Olagnon - Apr. 2000
4013 : ! __________________________________________________________
4014 : ! __________________________________________________________
4015 : ! __________________________________________________________
4016 : Integer(kind = i4), Dimension (:), Intent (InOut) :: XDONT
4017 : ! __________________________________________________________
4018 : Integer(kind = i4) :: XWRK, XMIN
4019 : !
4020 : ! __________________________________________________________
4021 : !
4022 : Integer(kind = i4) :: ICRS, IDCR, NDON
4023 : !
4024 4452 : NDON = Size (XDONT)
4025 : !
4026 : ! We first bring the minimum to the first location in the array.
4027 : ! That way, we will have a "guard", and when looking for the
4028 : ! right place to insert a value, no loop test is necessary.
4029 : !
4030 4452 : If (XDONT (1) < XDONT (NDON)) Then
4031 : XMIN = XDONT (1)
4032 : Else
4033 68 : XMIN = XDONT (NDON)
4034 68 : XDONT (NDON) = XDONT (1)
4035 : end if
4036 128646 : Do IDCR = NDON - 1, 2, -1
4037 124194 : XWRK = XDONT(IDCR)
4038 128646 : IF (XWRK < XMIN) Then
4039 7697 : XDONT (IDCR) = XMIN
4040 7697 : XMIN = XWRK
4041 : End If
4042 : End Do
4043 4452 : XDONT (1) = XMIN
4044 : !
4045 : ! The first value is now the minimum
4046 : ! Loop over the array, and when a value is smaller than
4047 : ! the previous one, loop down to insert it at its right place.
4048 : !
4049 128646 : Do ICRS = 3, NDON
4050 124194 : XWRK = XDONT (ICRS)
4051 124194 : IDCR = ICRS - 1
4052 128646 : If (XWRK < XDONT(IDCR)) Then
4053 88613 : XDONT (ICRS) = XDONT (IDCR)
4054 88613 : IDCR = IDCR - 1
4055 228094 : Do
4056 316707 : If (XWRK >= XDONT(IDCR)) Exit
4057 228094 : XDONT (IDCR + 1) = XDONT (IDCR)
4058 228094 : IDCR = IDCR - 1
4059 : End Do
4060 88613 : XDONT (IDCR + 1) = XWRK
4061 : End If
4062 : End Do
4063 : !
4064 4452 : Return
4065 : !
4066 2 : End Subroutine I_inssor
4067 :
4068 0 : Subroutine C_inssor (XDONT)
4069 : ! Sorts XDONT into increasing order (Insertion sort)
4070 : ! __________________________________________________________
4071 : ! This subroutine uses insertion sort. It does not use any
4072 : ! work array and is faster when XDONT is of very small size
4073 : ! (< 20), or already almost sorted, but worst case behavior
4074 : ! can happen fairly probably (initially inverse sorted).
4075 : ! In many cases, the quicksort or merge sort method is faster.
4076 : ! Michel Olagnon - Apr. 2000
4077 : ! __________________________________________________________
4078 : ! __________________________________________________________
4079 : ! __________________________________________________________
4080 : character(*), Dimension (:), Intent (InOut) :: XDONT
4081 : ! __________________________________________________________
4082 0 : character(len(XDONT)) :: XWRK, XMIN
4083 : !
4084 : ! __________________________________________________________
4085 : !
4086 : Integer(kind = i4) :: ICRS, IDCR, NDON
4087 : !
4088 0 : NDON = Size (XDONT)
4089 : !
4090 : ! We first bring the minimum to the first location in the array.
4091 : ! That way, we will have a "guard", and when looking for the
4092 : ! right place to insert a value, no loop test is necessary.
4093 : !
4094 0 : If (XDONT (1) < XDONT (NDON)) Then
4095 0 : XMIN = XDONT (1)
4096 : Else
4097 0 : XMIN = XDONT (NDON)
4098 0 : XDONT (NDON) = XDONT (1)
4099 : end if
4100 0 : Do IDCR = NDON - 1, 2, -1
4101 0 : XWRK = XDONT(IDCR)
4102 0 : IF (XWRK < XMIN) Then
4103 0 : XDONT (IDCR) = XMIN
4104 0 : XMIN = XWRK
4105 : End If
4106 : End Do
4107 0 : XDONT (1) = XMIN
4108 : !
4109 : ! The first value is now the minimum
4110 : ! Loop over the array, and when a value is smaller than
4111 : ! the previous one, loop down to insert it at its right place.
4112 : !
4113 0 : Do ICRS = 3, NDON
4114 0 : XWRK = XDONT (ICRS)
4115 0 : IDCR = ICRS - 1
4116 0 : If (XWRK < XDONT(IDCR)) Then
4117 0 : XDONT (ICRS) = XDONT (IDCR)
4118 0 : IDCR = IDCR - 1
4119 0 : Do
4120 0 : If (XWRK >= XDONT(IDCR)) Exit
4121 0 : XDONT (IDCR + 1) = XDONT (IDCR)
4122 0 : IDCR = IDCR - 1
4123 : End Do
4124 0 : XDONT (IDCR + 1) = XWRK
4125 : End If
4126 : End Do
4127 : !
4128 0 : Return
4129 : !
4130 4452 : End Subroutine C_inssor
4131 :
4132 1 : Function D_median (XDONT) Result (median)
4133 : ! Return median value of XDONT
4134 : ! If even number of data, average of the two "medians".
4135 : ! __________________________________________________________
4136 : ! This routine uses a pivoting strategy such as the one of
4137 : ! finding the median based on the quicksort algorithm, but
4138 : ! we skew the pivot choice to try to bring it to NORD as
4139 : ! fast as possible. It uses 2 temporary arrays, where it
4140 : ! stores the indices of the values smaller than the pivot
4141 : ! (ILOWT), and the indices of values larger than the pivot
4142 : ! that we might still need later on (IHIGT). It iterates
4143 : ! until it can bring the number of values in ILOWT to
4144 : ! exactly NORD, and then finds the maximum of this set.
4145 : ! Michel Olagnon - Aug. 2000
4146 : ! __________________________________________________________
4147 : ! __________________________________________________________
4148 : real(Kind = dp), Dimension (:), Intent (In) :: XDONT
4149 : real(Kind = dp) :: median
4150 : ! __________________________________________________________
4151 22 : real(Kind = dp), Dimension (SIZE(XDONT)) :: XLOWT, XHIGT
4152 1 : real(Kind = dp) :: XPIV, XWRK, XWRK1, XWRK2, XWRK3, XMIN, XMAX
4153 : !!
4154 : Logical :: IFODD
4155 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG!, NORD
4156 : Integer(kind = i4) :: IMIL, IFIN, ICRS, IDCR!, ILOW
4157 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1, INTH
4158 : !
4159 1 : NDON = SIZE (XDONT)
4160 1 : INTH = NDON / 2 + 1
4161 1 : IFODD = (2 * INTH == NDON + 1)
4162 : !
4163 : ! First loop is used to fill-in XLOWT, XHIGT at the same time
4164 : !
4165 1 : If (NDON < 3) Then
4166 0 : If (NDON > 0) median = 0.5 * (XDONT (1) + XDONT (NDON))
4167 0 : Return
4168 : End If
4169 : !
4170 : ! One chooses a pivot, best estimate possible to put fractile near
4171 : ! mid-point of the set of low values.
4172 : !
4173 1 : If (XDONT(2) < XDONT(1)) Then
4174 0 : XLOWT (1) = XDONT(2)
4175 0 : XHIGT (1) = XDONT(1)
4176 : Else
4177 1 : XLOWT (1) = XDONT(1)
4178 1 : XHIGT (1) = XDONT(2)
4179 : End If
4180 : !
4181 : !
4182 1 : If (XDONT(3) < XHIGT(1)) Then
4183 0 : XHIGT (2) = XHIGT (1)
4184 0 : If (XDONT(3) < XLOWT(1)) Then
4185 0 : XHIGT (1) = XLOWT (1)
4186 0 : XLOWT (1) = XDONT(3)
4187 : Else
4188 0 : XHIGT (1) = XDONT(3)
4189 : End If
4190 : Else
4191 1 : XHIGT (2) = XDONT(3)
4192 : End If
4193 : !
4194 1 : If (NDON < 4) Then ! 3 values
4195 0 : median = XHIGT (1)
4196 0 : Return
4197 : End If
4198 : !
4199 1 : If (XDONT(NDON) < XHIGT(1)) Then
4200 0 : XHIGT (3) = XHIGT (2)
4201 0 : XHIGT (2) = XHIGT (1)
4202 0 : If (XDONT(NDON) < XLOWT(1)) Then
4203 0 : XHIGT (1) = XLOWT (1)
4204 0 : XLOWT (1) = XDONT(NDON)
4205 : Else
4206 0 : XHIGT (1) = XDONT(NDON)
4207 : End If
4208 : Else
4209 1 : If (XDONT(NDON) < XHIGT(2)) Then
4210 0 : XHIGT (3) = XHIGT (2)
4211 0 : XHIGT (2) = XDONT(NDON)
4212 : Else
4213 1 : XHIGT (3) = XDONT(NDON)
4214 : End If
4215 : End If
4216 : !
4217 1 : If (NDON < 5) Then ! 4 values
4218 0 : median = 0.5 * (XHIGT (1) + XHIGT (2))
4219 0 : Return
4220 : End If
4221 : !
4222 1 : JLOW = 1
4223 1 : JHIG = 3
4224 1 : XPIV = XLOWT(1) + 2.0 * (XHIGT(3) - XLOWT(1)) / 3.0
4225 1 : If (XPIV >= XHIGT(1)) Then
4226 1 : XPIV = XLOWT(1) + 2.0 * (XHIGT(2) - XLOWT(1)) / 3.0
4227 1 : If (XPIV >= XHIGT(1)) XPIV = XLOWT(1) + 2.0 * (XHIGT(1) - XLOWT(1)) / 3.0
4228 : End If
4229 : !
4230 : ! One puts values > pivot in the end and those <= pivot
4231 : ! at the beginning. This is split in 2 cases, so that
4232 : ! we can skip the loop test a number of times.
4233 : ! As we are also filling in the work arrays at the same time
4234 : ! we stop filling in the XHIGT array as soon as we have more
4235 : ! than enough values in XLOWT.
4236 : !
4237 : !
4238 1 : If (XDONT(NDON) > XPIV) Then
4239 : ICRS = 3
4240 : Do
4241 7 : ICRS = ICRS + 1
4242 8 : If (XDONT(ICRS) > XPIV) Then
4243 7 : If (ICRS >= NDON) Exit
4244 6 : JHIG = JHIG + 1
4245 6 : XHIGT (JHIG) = XDONT(ICRS)
4246 : Else
4247 0 : JLOW = JLOW + 1
4248 0 : XLOWT (JLOW) = XDONT(ICRS)
4249 0 : If (JLOW >= INTH) Exit
4250 : End If
4251 : End Do
4252 : !
4253 : ! One restricts further processing because it is no use
4254 : ! to store more high values
4255 : !
4256 1 : If (ICRS < NDON - 1) Then
4257 : Do
4258 0 : ICRS = ICRS + 1
4259 0 : If (XDONT(ICRS) <= XPIV) Then
4260 0 : JLOW = JLOW + 1
4261 0 : XLOWT (JLOW) = XDONT(ICRS)
4262 0 : Else If (ICRS >= NDON) Then
4263 : Exit
4264 : End If
4265 : End Do
4266 : End If
4267 : !
4268 : !
4269 : Else
4270 : !
4271 : ! Same as above, but this is not as easy to optimize, so the
4272 : ! DO-loop is kept
4273 : !
4274 0 : Do ICRS = 4, NDON - 1
4275 0 : If (XDONT(ICRS) > XPIV) Then
4276 0 : JHIG = JHIG + 1
4277 0 : XHIGT (JHIG) = XDONT(ICRS)
4278 : Else
4279 0 : JLOW = JLOW + 1
4280 0 : XLOWT (JLOW) = XDONT(ICRS)
4281 0 : If (JLOW >= INTH) Exit
4282 : End If
4283 : End Do
4284 : !
4285 0 : If (ICRS < NDON - 1) Then
4286 : Do
4287 0 : ICRS = ICRS + 1
4288 0 : If (XDONT(ICRS) <= XPIV) Then
4289 0 : If (ICRS >= NDON) Exit
4290 0 : JLOW = JLOW + 1
4291 0 : XLOWT (JLOW) = XDONT(ICRS)
4292 : End If
4293 : End Do
4294 : End If
4295 : End If
4296 : !
4297 : JLM2 = 0
4298 : JLM1 = 0
4299 : JHM2 = 0
4300 : JHM1 = 0
4301 : Do
4302 2 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
4303 : !
4304 : ! We are oscillating. Perturbate by bringing JLOW closer by one
4305 : ! to INTH
4306 : !
4307 0 : If (INTH > JLOW) Then
4308 0 : XMIN = XHIGT(1)
4309 0 : IHIG = 1
4310 0 : Do ICRS = 2, JHIG
4311 0 : If (XHIGT(ICRS) < XMIN) Then
4312 0 : XMIN = XHIGT(ICRS)
4313 0 : IHIG = ICRS
4314 : End If
4315 : End Do
4316 : !
4317 0 : JLOW = JLOW + 1
4318 0 : XLOWT (JLOW) = XHIGT (IHIG)
4319 0 : XHIGT (IHIG) = XHIGT (JHIG)
4320 0 : JHIG = JHIG - 1
4321 : Else
4322 :
4323 0 : XMAX = XLOWT (JLOW)
4324 0 : JLOW = JLOW - 1
4325 0 : Do ICRS = 1, JLOW
4326 0 : If (XLOWT(ICRS) > XMAX) Then
4327 0 : XWRK = XMAX
4328 0 : XMAX = XLOWT(ICRS)
4329 0 : XLOWT (ICRS) = XWRK
4330 : End If
4331 : End Do
4332 : End If
4333 : End If
4334 2 : JLM2 = JLM1
4335 2 : JLM1 = JLOW
4336 2 : JHM2 = JHM1
4337 2 : JHM1 = JHIG
4338 : !
4339 : ! We try to bring the number of values in the low values set
4340 : ! closer to INTH.
4341 : !
4342 3 : Select Case (INTH - JLOW)
4343 : Case (2 :)
4344 : !
4345 : ! Not enough values in low part, at least 2 are missing
4346 : !
4347 1 : INTH = INTH - JLOW
4348 1 : JLOW = 0
4349 : Select Case (JHIG)
4350 : !!!!! CASE DEFAULT
4351 : !!!!! write (unit=*,fmt=*) "Assertion failed"
4352 : !!!!! STOP
4353 : !
4354 : ! We make a special case when we have so few values in
4355 : ! the high values set that it is bad performance to choose a pivot
4356 : ! and apply the general algorithm.
4357 : !
4358 : Case (2)
4359 0 : If (XHIGT(1) <= XHIGT(2)) Then
4360 0 : JLOW = JLOW + 1
4361 0 : XLOWT (JLOW) = XHIGT (1)
4362 0 : JLOW = JLOW + 1
4363 0 : XLOWT (JLOW) = XHIGT (2)
4364 : Else
4365 0 : JLOW = JLOW + 1
4366 0 : XLOWT (JLOW) = XHIGT (2)
4367 0 : JLOW = JLOW + 1
4368 0 : XLOWT (JLOW) = XHIGT (1)
4369 : End If
4370 : Exit
4371 : !
4372 : Case (3)
4373 : !
4374 : !
4375 0 : XWRK1 = XHIGT (1)
4376 0 : XWRK2 = XHIGT (2)
4377 0 : XWRK3 = XHIGT (3)
4378 0 : If (XWRK2 < XWRK1) Then
4379 0 : XHIGT (1) = XWRK2
4380 0 : XHIGT (2) = XWRK1
4381 0 : XWRK2 = XWRK1
4382 : End If
4383 0 : If (XWRK2 > XWRK3) Then
4384 0 : XHIGT (3) = XWRK2
4385 0 : XHIGT (2) = XWRK3
4386 0 : XWRK2 = XWRK3
4387 0 : If (XWRK2 < XHIGT(1)) Then
4388 0 : XHIGT (2) = XHIGT (1)
4389 0 : XHIGT (1) = XWRK2
4390 : End If
4391 : End If
4392 : JHIG = 0
4393 0 : Do ICRS = JLOW + 1, INTH
4394 0 : JHIG = JHIG + 1
4395 0 : XLOWT (ICRS) = XHIGT (JHIG)
4396 : End Do
4397 1 : JLOW = INTH
4398 : Exit
4399 : !
4400 : Case (4 :)
4401 : !
4402 : !
4403 1 : IFIN = JHIG
4404 : !
4405 : ! One chooses a pivot from the 2 first values and the last one.
4406 : ! This should ensure sufficient renewal between iterations to
4407 : ! avoid worst case behavior effects.
4408 : !
4409 1 : XWRK1 = XHIGT (1)
4410 1 : XWRK2 = XHIGT (2)
4411 1 : XWRK3 = XHIGT (IFIN)
4412 1 : If (XWRK2 < XWRK1) Then
4413 0 : XHIGT (1) = XWRK2
4414 0 : XHIGT (2) = XWRK1
4415 0 : XWRK2 = XWRK1
4416 : End If
4417 1 : If (XWRK2 > XWRK3) Then
4418 0 : XHIGT (IFIN) = XWRK2
4419 0 : XHIGT (2) = XWRK3
4420 0 : XWRK2 = XWRK3
4421 0 : If (XWRK2 < XHIGT(1)) Then
4422 0 : XHIGT (2) = XHIGT (1)
4423 0 : XHIGT (1) = XWRK2
4424 : End If
4425 : End If
4426 : !
4427 1 : XWRK1 = XHIGT (1)
4428 1 : JLOW = JLOW + 1
4429 1 : XLOWT (JLOW) = XWRK1
4430 1 : XPIV = XWRK1 + 0.5 * (XHIGT(IFIN) - XWRK1)
4431 : !
4432 : ! One takes values <= pivot to XLOWT
4433 : ! Again, 2 parts, one where we take care of the remaining
4434 : ! high values because we might still need them, and the
4435 : ! other when we know that we will have more than enough
4436 : ! low values in the end.
4437 : !
4438 1 : JHIG = 0
4439 9 : Do ICRS = 2, IFIN
4440 9 : If (XHIGT(ICRS) <= XPIV) Then
4441 3 : JLOW = JLOW + 1
4442 3 : XLOWT (JLOW) = XHIGT (ICRS)
4443 3 : If (JLOW >= INTH) Exit
4444 : Else
4445 5 : JHIG = JHIG + 1
4446 5 : XHIGT (JHIG) = XHIGT (ICRS)
4447 : End If
4448 : End Do
4449 : !
4450 1 : Do ICRS = ICRS + 1, IFIN
4451 1 : If (XHIGT(ICRS) <= XPIV) Then
4452 0 : JLOW = JLOW + 1
4453 0 : XLOWT (JLOW) = XHIGT (ICRS)
4454 : End If
4455 : End Do
4456 : End Select
4457 : !
4458 : !
4459 : Case (1)
4460 : !
4461 : ! Only 1 value is missing in low part
4462 : !
4463 1 : XMIN = XHIGT(1)
4464 5 : Do ICRS = 2, JHIG
4465 5 : If (XHIGT(ICRS) < XMIN) Then
4466 1 : XMIN = XHIGT(ICRS)
4467 : End If
4468 : End Do
4469 : !
4470 1 : JLOW = JLOW + 1
4471 1 : XLOWT (JLOW) = XMIN
4472 1 : Exit
4473 : !
4474 : !
4475 : Case (0)
4476 : !
4477 : ! Low part is exactly what we want
4478 : !
4479 0 : Exit
4480 : !
4481 : !
4482 : Case (-5 : -1)
4483 : !
4484 : ! Only few values too many in low part
4485 : !
4486 0 : IF (IFODD) THEN
4487 0 : JHIG = JLOW - INTH + 1
4488 : Else
4489 0 : JHIG = JLOW - INTH + 2
4490 : end if
4491 0 : XHIGT (1) = XLOWT (1)
4492 0 : Do ICRS = 2, JHIG
4493 0 : XWRK = XLOWT (ICRS)
4494 0 : Do IDCR = ICRS - 1, 1, - 1
4495 0 : If (XWRK < XHIGT(IDCR)) Then
4496 0 : XHIGT (IDCR + 1) = XHIGT (IDCR)
4497 : Else
4498 : Exit
4499 : End If
4500 : End Do
4501 0 : XHIGT (IDCR + 1) = XWRK
4502 : End Do
4503 : !
4504 0 : Do ICRS = JHIG + 1, JLOW
4505 0 : If (XLOWT (ICRS) > XHIGT(1)) Then
4506 0 : XWRK = XLOWT (ICRS)
4507 0 : Do IDCR = 2, JHIG
4508 0 : If (XWRK >= XHIGT(IDCR)) Then
4509 0 : XHIGT (IDCR - 1) = XHIGT (IDCR)
4510 : else
4511 : exit
4512 : end if
4513 : End Do
4514 0 : XHIGT (IDCR - 1) = XWRK
4515 : End If
4516 : End Do
4517 : !
4518 0 : IF (IFODD) THEN
4519 0 : median = XHIGT(1)
4520 : Else
4521 0 : median = 0.5 * (XHIGT(1) + XHIGT(2))
4522 : end if
4523 0 : Return
4524 : !
4525 : !
4526 : Case (: -6)
4527 : !
4528 : ! last case: too many values in low part
4529 : !
4530 :
4531 0 : IMIL = (JLOW + 1) / 2
4532 0 : IFIN = JLOW
4533 : !
4534 : ! One chooses a pivot from 1st, last, and middle values
4535 : !
4536 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
4537 0 : XWRK = XLOWT (1)
4538 0 : XLOWT (1) = XLOWT (IMIL)
4539 0 : XLOWT (IMIL) = XWRK
4540 : End If
4541 0 : If (XLOWT(IMIL) > XLOWT(IFIN)) Then
4542 0 : XWRK = XLOWT (IFIN)
4543 0 : XLOWT (IFIN) = XLOWT (IMIL)
4544 0 : XLOWT (IMIL) = XWRK
4545 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
4546 0 : XWRK = XLOWT (1)
4547 0 : XLOWT (1) = XLOWT (IMIL)
4548 0 : XLOWT (IMIL) = XWRK
4549 : End If
4550 : End If
4551 0 : If (IFIN <= 3) Exit
4552 : !
4553 : XPIV = XLOWT(1) + REAL(INTH, dp) / REAL(JLOW + INTH, dp) * &
4554 0 : (XLOWT(IFIN) - XLOWT(1))
4555 :
4556 : !
4557 : ! One takes values > XPIV to XHIGT
4558 : !
4559 0 : JHIG = 0
4560 0 : JLOW = 0
4561 : !
4562 2 : If (XLOWT(IFIN) > XPIV) Then
4563 : ICRS = 0
4564 : Do
4565 0 : ICRS = ICRS + 1
4566 0 : If (XLOWT(ICRS) > XPIV) Then
4567 0 : JHIG = JHIG + 1
4568 0 : XHIGT (JHIG) = XLOWT (ICRS)
4569 0 : If (ICRS >= IFIN) Exit
4570 : Else
4571 0 : JLOW = JLOW + 1
4572 0 : XLOWT (JLOW) = XLOWT (ICRS)
4573 0 : If (JLOW >= INTH) Exit
4574 : End If
4575 : End Do
4576 : !
4577 0 : If (ICRS < IFIN) Then
4578 : Do
4579 0 : ICRS = ICRS + 1
4580 0 : If (XLOWT(ICRS) <= XPIV) Then
4581 0 : JLOW = JLOW + 1
4582 0 : XLOWT (JLOW) = XLOWT (ICRS)
4583 : Else
4584 0 : If (ICRS >= IFIN) Exit
4585 : End If
4586 : End Do
4587 : End If
4588 : Else
4589 0 : Do ICRS = 1, IFIN
4590 0 : If (XLOWT(ICRS) > XPIV) Then
4591 0 : JHIG = JHIG + 1
4592 0 : XHIGT (JHIG) = XLOWT (ICRS)
4593 : Else
4594 0 : JLOW = JLOW + 1
4595 0 : XLOWT (JLOW) = XLOWT (ICRS)
4596 0 : If (JLOW >= INTH) Exit
4597 : End If
4598 : End Do
4599 : !
4600 0 : Do ICRS = ICRS + 1, IFIN
4601 0 : If (XLOWT(ICRS) <= XPIV) Then
4602 0 : JLOW = JLOW + 1
4603 0 : XLOWT (JLOW) = XLOWT (ICRS)
4604 : End If
4605 : End Do
4606 : End If
4607 : !
4608 : End Select
4609 : !
4610 : End Do
4611 : !
4612 : ! Now, we only need to find maximum of the 1:INTH set
4613 : !
4614 1 : if (IFODD) then
4615 0 : median = MAXVAL (XLOWT (1 : INTH))
4616 : else
4617 1 : XWRK = MAX (XLOWT (1), XLOWT (2))
4618 1 : XWRK1 = MIN (XLOWT (1), XLOWT (2))
4619 4 : DO ICRS = 3, INTH
4620 4 : IF (XLOWT (ICRS) > XWRK1) THEN
4621 3 : IF (XLOWT (ICRS) > XWRK) THEN
4622 : XWRK1 = XWRK
4623 : XWRK = XLOWT (ICRS)
4624 : Else
4625 0 : XWRK1 = XLOWT (ICRS)
4626 : end if
4627 : end if
4628 : ENDDO
4629 1 : median = 0.5 * (XWRK + XWRK1)
4630 : end if
4631 : Return
4632 : !
4633 0 : End Function D_median
4634 :
4635 1 : Function R_median (XDONT) Result (median)
4636 : ! Return median value of XDONT
4637 : ! __________________________________________________________
4638 : ! This routine uses a pivoting strategy such as the one of
4639 : ! finding the median based on the quicksort algorithm, but
4640 : ! we skew the pivot choice to try to bring it to NORD as
4641 : ! fast as possible. It uses 2 temporary arrays, where it
4642 : ! stores the indices of the values smaller than the pivot
4643 : ! (ILOWT), and the indices of values larger than the pivot
4644 : ! that we might still need later on (IHIGT). It iterates
4645 : ! until it can bring the number of values in ILOWT to
4646 : ! exactly NORD, and then finds the maximum of this set.
4647 : ! Michel Olagnon - Aug. 2000
4648 : ! __________________________________________________________
4649 : ! _________________________________________________________
4650 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
4651 : Real(kind = sp) :: median
4652 : ! __________________________________________________________
4653 22 : Real(kind = sp), Dimension (SIZE(XDONT)) :: XLOWT, XHIGT
4654 1 : Real(kind = sp) :: XPIV, XWRK, XWRK1, XWRK2, XWRK3, XMIN, XMAX
4655 : !!
4656 : Logical :: IFODD
4657 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG!, NORD
4658 : Integer(kind = i4) :: IMIL, IFIN, ICRS, IDCR!, ILOW
4659 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1, INTH
4660 : !
4661 1 : NDON = SIZE (XDONT)
4662 1 : INTH = NDON / 2 + 1
4663 1 : IFODD = (2 * INTH == NDON + 1)
4664 : !
4665 : ! First loop is used to fill-in XLOWT, XHIGT at the same time
4666 : !
4667 1 : If (NDON < 3) Then
4668 0 : If (NDON > 0) median = 0.5 * (XDONT (1) + XDONT (NDON))
4669 0 : Return
4670 : End If
4671 : !
4672 : ! One chooses a pivot, best estimate possible to put fractile near
4673 : ! mid-point of the set of low values.
4674 : !
4675 1 : If (XDONT(2) < XDONT(1)) Then
4676 0 : XLOWT (1) = XDONT(2)
4677 0 : XHIGT (1) = XDONT(1)
4678 : Else
4679 1 : XLOWT (1) = XDONT(1)
4680 1 : XHIGT (1) = XDONT(2)
4681 : End If
4682 : !
4683 : !
4684 1 : If (XDONT(3) < XHIGT(1)) Then
4685 0 : XHIGT (2) = XHIGT (1)
4686 0 : If (XDONT(3) < XLOWT(1)) Then
4687 0 : XHIGT (1) = XLOWT (1)
4688 0 : XLOWT (1) = XDONT(3)
4689 : Else
4690 0 : XHIGT (1) = XDONT(3)
4691 : End If
4692 : Else
4693 1 : XHIGT (2) = XDONT(3)
4694 : End If
4695 : !
4696 1 : If (NDON < 4) Then ! 3 values
4697 0 : median = XHIGT (1)
4698 0 : Return
4699 : End If
4700 : !
4701 1 : If (XDONT(NDON) < XHIGT(1)) Then
4702 0 : XHIGT (3) = XHIGT (2)
4703 0 : XHIGT (2) = XHIGT (1)
4704 0 : If (XDONT(NDON) < XLOWT(1)) Then
4705 0 : XHIGT (1) = XLOWT (1)
4706 0 : XLOWT (1) = XDONT(NDON)
4707 : Else
4708 0 : XHIGT (1) = XDONT(NDON)
4709 : End If
4710 : Else
4711 1 : If (XDONT(NDON) < XHIGT(2)) Then
4712 0 : XHIGT (3) = XHIGT (2)
4713 0 : XHIGT (2) = XDONT(NDON)
4714 : Else
4715 1 : XHIGT (3) = XDONT(NDON)
4716 : End If
4717 : End If
4718 : !
4719 1 : If (NDON < 5) Then ! 4 values
4720 0 : median = 0.5 * (XHIGT (1) + XHIGT (2))
4721 0 : Return
4722 : End If
4723 : !
4724 1 : JLOW = 1
4725 1 : JHIG = 3
4726 1 : XPIV = XLOWT(1) + 2.0 * (XHIGT(3) - XLOWT(1)) / 3.0
4727 1 : If (XPIV >= XHIGT(1)) Then
4728 1 : XPIV = XLOWT(1) + 2.0 * (XHIGT(2) - XLOWT(1)) / 3.0
4729 1 : If (XPIV >= XHIGT(1)) XPIV = XLOWT(1) + 2.0 * (XHIGT(1) - XLOWT(1)) / 3.0
4730 : End If
4731 : !
4732 : ! One puts values > pivot in the end and those <= pivot
4733 : ! at the beginning. This is split in 2 cases, so that
4734 : ! we can skip the loop test a number of times.
4735 : ! As we are also filling in the work arrays at the same time
4736 : ! we stop filling in the XHIGT array as soon as we have more
4737 : ! than enough values in XLOWT.
4738 : !
4739 : !
4740 1 : If (XDONT(NDON) > XPIV) Then
4741 : ICRS = 3
4742 : Do
4743 7 : ICRS = ICRS + 1
4744 8 : If (XDONT(ICRS) > XPIV) Then
4745 7 : If (ICRS >= NDON) Exit
4746 6 : JHIG = JHIG + 1
4747 6 : XHIGT (JHIG) = XDONT(ICRS)
4748 : Else
4749 0 : JLOW = JLOW + 1
4750 0 : XLOWT (JLOW) = XDONT(ICRS)
4751 0 : If (JLOW >= INTH) Exit
4752 : End If
4753 : End Do
4754 : !
4755 : ! One restricts further processing because it is no use
4756 : ! to store more high values
4757 : !
4758 1 : If (ICRS < NDON - 1) Then
4759 : Do
4760 0 : ICRS = ICRS + 1
4761 0 : If (XDONT(ICRS) <= XPIV) Then
4762 0 : JLOW = JLOW + 1
4763 0 : XLOWT (JLOW) = XDONT(ICRS)
4764 0 : Else If (ICRS >= NDON) Then
4765 : Exit
4766 : End If
4767 : End Do
4768 : End If
4769 : !
4770 : !
4771 : Else
4772 : !
4773 : ! Same as above, but this is not as easy to optimize, so the
4774 : ! DO-loop is kept
4775 : !
4776 0 : Do ICRS = 4, NDON - 1
4777 0 : If (XDONT(ICRS) > XPIV) Then
4778 0 : JHIG = JHIG + 1
4779 0 : XHIGT (JHIG) = XDONT(ICRS)
4780 : Else
4781 0 : JLOW = JLOW + 1
4782 0 : XLOWT (JLOW) = XDONT(ICRS)
4783 0 : If (JLOW >= INTH) Exit
4784 : End If
4785 : End Do
4786 : !
4787 0 : If (ICRS < NDON - 1) Then
4788 : Do
4789 0 : ICRS = ICRS + 1
4790 0 : If (XDONT(ICRS) <= XPIV) Then
4791 0 : If (ICRS >= NDON) Exit
4792 0 : JLOW = JLOW + 1
4793 0 : XLOWT (JLOW) = XDONT(ICRS)
4794 : End If
4795 : End Do
4796 : End If
4797 : End If
4798 : !
4799 : JLM2 = 0
4800 : JLM1 = 0
4801 : JHM2 = 0
4802 : JHM1 = 0
4803 : Do
4804 2 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
4805 : !
4806 : ! We are oscillating. Perturbate by bringing JLOW closer by one
4807 : ! to INTH
4808 : !
4809 0 : If (INTH > JLOW) Then
4810 0 : XMIN = XHIGT(1)
4811 0 : IHIG = 1
4812 0 : Do ICRS = 2, JHIG
4813 0 : If (XHIGT(ICRS) < XMIN) Then
4814 0 : XMIN = XHIGT(ICRS)
4815 0 : IHIG = ICRS
4816 : End If
4817 : End Do
4818 : !
4819 0 : JLOW = JLOW + 1
4820 0 : XLOWT (JLOW) = XHIGT (IHIG)
4821 0 : XHIGT (IHIG) = XHIGT (JHIG)
4822 0 : JHIG = JHIG - 1
4823 : Else
4824 :
4825 0 : XMAX = XLOWT (JLOW)
4826 0 : JLOW = JLOW - 1
4827 0 : Do ICRS = 1, JLOW
4828 0 : If (XLOWT(ICRS) > XMAX) Then
4829 0 : XWRK = XMAX
4830 0 : XMAX = XLOWT(ICRS)
4831 0 : XLOWT (ICRS) = XWRK
4832 : End If
4833 : End Do
4834 : End If
4835 : End If
4836 2 : JLM2 = JLM1
4837 2 : JLM1 = JLOW
4838 2 : JHM2 = JHM1
4839 2 : JHM1 = JHIG
4840 : !
4841 : ! We try to bring the number of values in the low values set
4842 : ! closer to INTH.
4843 : !
4844 3 : Select Case (INTH - JLOW)
4845 : Case (2 :)
4846 : !
4847 : ! Not enough values in low part, at least 2 are missing
4848 : !
4849 1 : INTH = INTH - JLOW
4850 1 : JLOW = 0
4851 : Select Case (JHIG)
4852 : !!!!! CASE DEFAULT
4853 : !!!!! write (unit=*,fmt=*) "Assertion failed"
4854 : !!!!! STOP
4855 : !
4856 : ! We make a special case when we have so few values in
4857 : ! the high values set that it is bad performance to choose a pivot
4858 : ! and apply the general algorithm.
4859 : !
4860 : Case (2)
4861 0 : If (XHIGT(1) <= XHIGT(2)) Then
4862 0 : JLOW = JLOW + 1
4863 0 : XLOWT (JLOW) = XHIGT (1)
4864 0 : JLOW = JLOW + 1
4865 0 : XLOWT (JLOW) = XHIGT (2)
4866 : Else
4867 0 : JLOW = JLOW + 1
4868 0 : XLOWT (JLOW) = XHIGT (2)
4869 0 : JLOW = JLOW + 1
4870 0 : XLOWT (JLOW) = XHIGT (1)
4871 : End If
4872 : Exit
4873 : !
4874 : Case (3)
4875 : !
4876 : !
4877 0 : XWRK1 = XHIGT (1)
4878 0 : XWRK2 = XHIGT (2)
4879 0 : XWRK3 = XHIGT (3)
4880 0 : If (XWRK2 < XWRK1) Then
4881 0 : XHIGT (1) = XWRK2
4882 0 : XHIGT (2) = XWRK1
4883 0 : XWRK2 = XWRK1
4884 : End If
4885 0 : If (XWRK2 > XWRK3) Then
4886 0 : XHIGT (3) = XWRK2
4887 0 : XHIGT (2) = XWRK3
4888 0 : XWRK2 = XWRK3
4889 0 : If (XWRK2 < XHIGT(1)) Then
4890 0 : XHIGT (2) = XHIGT (1)
4891 0 : XHIGT (1) = XWRK2
4892 : End If
4893 : End If
4894 : JHIG = 0
4895 0 : Do ICRS = JLOW + 1, INTH
4896 0 : JHIG = JHIG + 1
4897 0 : XLOWT (ICRS) = XHIGT (JHIG)
4898 : End Do
4899 1 : JLOW = INTH
4900 : Exit
4901 : !
4902 : Case (4 :)
4903 : !
4904 : !
4905 1 : IFIN = JHIG
4906 : !
4907 : ! One chooses a pivot from the 2 first values and the last one.
4908 : ! This should ensure sufficient renewal between iterations to
4909 : ! avoid worst case behavior effects.
4910 : !
4911 1 : XWRK1 = XHIGT (1)
4912 1 : XWRK2 = XHIGT (2)
4913 1 : XWRK3 = XHIGT (IFIN)
4914 1 : If (XWRK2 < XWRK1) Then
4915 0 : XHIGT (1) = XWRK2
4916 0 : XHIGT (2) = XWRK1
4917 0 : XWRK2 = XWRK1
4918 : End If
4919 1 : If (XWRK2 > XWRK3) Then
4920 0 : XHIGT (IFIN) = XWRK2
4921 0 : XHIGT (2) = XWRK3
4922 0 : XWRK2 = XWRK3
4923 0 : If (XWRK2 < XHIGT(1)) Then
4924 0 : XHIGT (2) = XHIGT (1)
4925 0 : XHIGT (1) = XWRK2
4926 : End If
4927 : End If
4928 : !
4929 1 : XWRK1 = XHIGT (1)
4930 1 : JLOW = JLOW + 1
4931 1 : XLOWT (JLOW) = XWRK1
4932 1 : XPIV = XWRK1 + 0.5 * (XHIGT(IFIN) - XWRK1)
4933 : !
4934 : ! One takes values <= pivot to XLOWT
4935 : ! Again, 2 parts, one where we take care of the remaining
4936 : ! high values because we might still need them, and the
4937 : ! other when we know that we will have more than enough
4938 : ! low values in the end.
4939 : !
4940 1 : JHIG = 0
4941 9 : Do ICRS = 2, IFIN
4942 9 : If (XHIGT(ICRS) <= XPIV) Then
4943 3 : JLOW = JLOW + 1
4944 3 : XLOWT (JLOW) = XHIGT (ICRS)
4945 3 : If (JLOW >= INTH) Exit
4946 : Else
4947 5 : JHIG = JHIG + 1
4948 5 : XHIGT (JHIG) = XHIGT (ICRS)
4949 : End If
4950 : End Do
4951 : !
4952 1 : Do ICRS = ICRS + 1, IFIN
4953 1 : If (XHIGT(ICRS) <= XPIV) Then
4954 0 : JLOW = JLOW + 1
4955 0 : XLOWT (JLOW) = XHIGT (ICRS)
4956 : End If
4957 : End Do
4958 : End Select
4959 : !
4960 : !
4961 : Case (1)
4962 : !
4963 : ! Only 1 value is missing in low part
4964 : !
4965 1 : XMIN = XHIGT(1)
4966 5 : Do ICRS = 2, JHIG
4967 5 : If (XHIGT(ICRS) < XMIN) Then
4968 1 : XMIN = XHIGT(ICRS)
4969 : End If
4970 : End Do
4971 : !
4972 1 : JLOW = JLOW + 1
4973 1 : XLOWT (JLOW) = XMIN
4974 1 : Exit
4975 : !
4976 : !
4977 : Case (0)
4978 : !
4979 : ! Low part is exactly what we want
4980 : !
4981 0 : Exit
4982 : !
4983 : !
4984 : Case (-5 : -1)
4985 : !
4986 : ! Only few values too many in low part
4987 : !
4988 0 : IF (IFODD) THEN
4989 0 : JHIG = JLOW - INTH + 1
4990 : Else
4991 0 : JHIG = JLOW - INTH + 2
4992 : end if
4993 0 : XHIGT (1) = XLOWT (1)
4994 0 : Do ICRS = 2, JHIG
4995 0 : XWRK = XLOWT (ICRS)
4996 0 : Do IDCR = ICRS - 1, 1, - 1
4997 0 : If (XWRK < XHIGT(IDCR)) Then
4998 0 : XHIGT (IDCR + 1) = XHIGT (IDCR)
4999 : Else
5000 : Exit
5001 : End If
5002 : End Do
5003 0 : XHIGT (IDCR + 1) = XWRK
5004 : End Do
5005 : !
5006 0 : Do ICRS = JHIG + 1, JLOW
5007 0 : If (XLOWT (ICRS) > XHIGT(1)) Then
5008 0 : XWRK = XLOWT (ICRS)
5009 0 : Do IDCR = 2, JHIG
5010 0 : If (XWRK >= XHIGT(IDCR)) Then
5011 0 : XHIGT (IDCR - 1) = XHIGT (IDCR)
5012 : else
5013 : exit
5014 : end if
5015 : End Do
5016 0 : XHIGT (IDCR - 1) = XWRK
5017 : End If
5018 : End Do
5019 : !
5020 0 : IF (IFODD) THEN
5021 0 : median = XHIGT(1)
5022 : Else
5023 0 : median = 0.5 * (XHIGT(1) + XHIGT(2))
5024 : end if
5025 0 : Return
5026 : !
5027 : !
5028 : Case (: -6)
5029 : !
5030 : ! last case: too many values in low part
5031 : !
5032 :
5033 0 : IMIL = (JLOW + 1) / 2
5034 0 : IFIN = JLOW
5035 : !
5036 : ! One chooses a pivot from 1st, last, and middle values
5037 : !
5038 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
5039 0 : XWRK = XLOWT (1)
5040 0 : XLOWT (1) = XLOWT (IMIL)
5041 0 : XLOWT (IMIL) = XWRK
5042 : End If
5043 0 : If (XLOWT(IMIL) > XLOWT(IFIN)) Then
5044 0 : XWRK = XLOWT (IFIN)
5045 0 : XLOWT (IFIN) = XLOWT (IMIL)
5046 0 : XLOWT (IMIL) = XWRK
5047 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
5048 0 : XWRK = XLOWT (1)
5049 0 : XLOWT (1) = XLOWT (IMIL)
5050 0 : XLOWT (IMIL) = XWRK
5051 : End If
5052 : End If
5053 0 : If (IFIN <= 3) Exit
5054 : !
5055 : XPIV = XLOWT(1) + REAL(INTH, sp) / REAL(JLOW + INTH, sp) * &
5056 0 : (XLOWT(IFIN) - XLOWT(1))
5057 :
5058 : !
5059 : ! One takes values > XPIV to XHIGT
5060 : !
5061 0 : JHIG = 0
5062 0 : JLOW = 0
5063 : !
5064 2 : If (XLOWT(IFIN) > XPIV) Then
5065 : ICRS = 0
5066 : Do
5067 0 : ICRS = ICRS + 1
5068 0 : If (XLOWT(ICRS) > XPIV) Then
5069 0 : JHIG = JHIG + 1
5070 0 : XHIGT (JHIG) = XLOWT (ICRS)
5071 0 : If (ICRS >= IFIN) Exit
5072 : Else
5073 0 : JLOW = JLOW + 1
5074 0 : XLOWT (JLOW) = XLOWT (ICRS)
5075 0 : If (JLOW >= INTH) Exit
5076 : End If
5077 : End Do
5078 : !
5079 0 : If (ICRS < IFIN) Then
5080 : Do
5081 0 : ICRS = ICRS + 1
5082 0 : If (XLOWT(ICRS) <= XPIV) Then
5083 0 : JLOW = JLOW + 1
5084 0 : XLOWT (JLOW) = XLOWT (ICRS)
5085 : Else
5086 0 : If (ICRS >= IFIN) Exit
5087 : End If
5088 : End Do
5089 : End If
5090 : Else
5091 0 : Do ICRS = 1, IFIN
5092 0 : If (XLOWT(ICRS) > XPIV) Then
5093 0 : JHIG = JHIG + 1
5094 0 : XHIGT (JHIG) = XLOWT (ICRS)
5095 : Else
5096 0 : JLOW = JLOW + 1
5097 0 : XLOWT (JLOW) = XLOWT (ICRS)
5098 0 : If (JLOW >= INTH) Exit
5099 : End If
5100 : End Do
5101 : !
5102 0 : Do ICRS = ICRS + 1, IFIN
5103 0 : If (XLOWT(ICRS) <= XPIV) Then
5104 0 : JLOW = JLOW + 1
5105 0 : XLOWT (JLOW) = XLOWT (ICRS)
5106 : End If
5107 : End Do
5108 : End If
5109 : !
5110 : End Select
5111 : !
5112 : End Do
5113 : !
5114 : ! Now, we only need to find maximum of the 1:INTH set
5115 : !
5116 1 : if (IFODD) then
5117 0 : median = MAXVAL (XLOWT (1 : INTH))
5118 : else
5119 1 : XWRK = MAX (XLOWT (1), XLOWT (2))
5120 1 : XWRK1 = MIN (XLOWT (1), XLOWT (2))
5121 4 : DO ICRS = 3, INTH
5122 4 : IF (XLOWT (ICRS) > XWRK1) THEN
5123 3 : IF (XLOWT (ICRS) > XWRK) THEN
5124 : XWRK1 = XWRK
5125 : XWRK = XLOWT (ICRS)
5126 : Else
5127 0 : XWRK1 = XLOWT (ICRS)
5128 : end if
5129 : end if
5130 : ENDDO
5131 1 : median = 0.5 * (XWRK + XWRK1)
5132 : end if
5133 : Return
5134 : !
5135 1 : End Function R_median
5136 :
5137 0 : Function I_median (XDONT) Result (median)
5138 : ! Return median value of XDONT
5139 : ! __________________________________________________________
5140 : ! This routine uses a pivoting strategy such as the one of
5141 : ! finding the median based on the quicksort algorithm, but
5142 : ! we skew the pivot choice to try to bring it to NORD as
5143 : ! fast as possible. It uses 2 temporary arrays, where it
5144 : ! stores the indices of the values smaller than the pivot
5145 : ! (ILOWT), and the indices of values larger than the pivot
5146 : ! that we might still need later on (IHIGT). It iterates
5147 : ! until it can bring the number of values in ILOWT to
5148 : ! exactly NORD, and then finds the maximum of this set.
5149 : ! Michel Olagnon - Aug. 2000
5150 : ! __________________________________________________________
5151 : ! __________________________________________________________
5152 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
5153 : Integer(kind = i4) :: median
5154 : ! __________________________________________________________
5155 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: XLOWT, XHIGT
5156 : Integer(kind = i4) :: XPIV, XWRK, XWRK1, XWRK2, XWRK3, XMIN, XMAX
5157 : !!
5158 : Logical :: IFODD
5159 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG!, NORD
5160 : Integer(kind = i4) :: IMIL, IFIN, ICRS, IDCR!, ILOW
5161 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1, INTH
5162 : !
5163 0 : NDON = SIZE (XDONT)
5164 0 : INTH = NDON / 2 + 1
5165 0 : IFODD = (2 * INTH == NDON + 1)
5166 : !
5167 : ! First loop is used to fill-in XLOWT, XHIGT at the same time
5168 : !
5169 0 : If (NDON < 3) Then
5170 0 : If (NDON > 0) median = (XDONT (1) + XDONT (NDON)) / 2
5171 0 : Return
5172 : End If
5173 : !
5174 : ! One chooses a pivot, best estimate possible to put fractile near
5175 : ! mid-point of the set of low values.
5176 : !
5177 0 : If (XDONT(2) < XDONT(1)) Then
5178 0 : XLOWT (1) = XDONT(2)
5179 0 : XHIGT (1) = XDONT(1)
5180 : Else
5181 0 : XLOWT (1) = XDONT(1)
5182 0 : XHIGT (1) = XDONT(2)
5183 : End If
5184 : !
5185 : !
5186 0 : If (XDONT(3) < XHIGT(1)) Then
5187 0 : XHIGT (2) = XHIGT (1)
5188 0 : If (XDONT(3) < XLOWT(1)) Then
5189 0 : XHIGT (1) = XLOWT (1)
5190 0 : XLOWT (1) = XDONT(3)
5191 : Else
5192 0 : XHIGT (1) = XDONT(3)
5193 : End If
5194 : Else
5195 0 : XHIGT (2) = XDONT(3)
5196 : End If
5197 : !
5198 0 : If (NDON < 4) Then ! 3 values
5199 0 : median = XHIGT (1)
5200 0 : Return
5201 : End If
5202 : !
5203 0 : If (XDONT(NDON) < XHIGT(1)) Then
5204 0 : XHIGT (3) = XHIGT (2)
5205 0 : XHIGT (2) = XHIGT (1)
5206 0 : If (XDONT(NDON) < XLOWT(1)) Then
5207 0 : XHIGT (1) = XLOWT (1)
5208 0 : XLOWT (1) = XDONT(NDON)
5209 : Else
5210 0 : XHIGT (1) = XDONT(NDON)
5211 : End If
5212 : Else
5213 0 : If (XDONT(NDON) < XHIGT(2)) Then
5214 0 : XHIGT (3) = XHIGT (2)
5215 0 : XHIGT (2) = XDONT(NDON)
5216 : Else
5217 0 : XHIGT (3) = XDONT(NDON)
5218 : End If
5219 : End If
5220 : !
5221 0 : If (NDON < 5) Then ! 4 values
5222 0 : median = (XHIGT (1) + XHIGT (2)) / 2
5223 0 : Return
5224 : End If
5225 : !
5226 0 : JLOW = 1
5227 0 : JHIG = 3
5228 0 : XPIV = XLOWT(1) + 2 * (XHIGT(3) - XLOWT(1)) / 3
5229 0 : If (XPIV >= XHIGT(1)) Then
5230 0 : XPIV = XLOWT(1) + 2 * (XHIGT(2) - XLOWT(1)) / 3
5231 0 : If (XPIV >= XHIGT(1)) XPIV = XLOWT(1) + 2 * (XHIGT(1) - XLOWT(1)) / 3
5232 : End If
5233 : !
5234 : ! One puts values > pivot in the end and those <= pivot
5235 : ! at the beginning. This is split in 2 cases, so that
5236 : ! we can skip the loop test a number of times.
5237 : ! As we are also filling in the work arrays at the same time
5238 : ! we stop filling in the XHIGT array as soon as we have more
5239 : ! than enough values in XLOWT.
5240 : !
5241 : !
5242 0 : If (XDONT(NDON) > XPIV) Then
5243 : ICRS = 3
5244 : Do
5245 0 : ICRS = ICRS + 1
5246 0 : If (XDONT(ICRS) > XPIV) Then
5247 0 : If (ICRS >= NDON) Exit
5248 0 : JHIG = JHIG + 1
5249 0 : XHIGT (JHIG) = XDONT(ICRS)
5250 : Else
5251 0 : JLOW = JLOW + 1
5252 0 : XLOWT (JLOW) = XDONT(ICRS)
5253 0 : If (JLOW >= INTH) Exit
5254 : End If
5255 : End Do
5256 : !
5257 : ! One restricts further processing because it is no use
5258 : ! to store more high values
5259 : !
5260 0 : If (ICRS < NDON - 1) Then
5261 : Do
5262 0 : ICRS = ICRS + 1
5263 0 : If (XDONT(ICRS) <= XPIV) Then
5264 0 : JLOW = JLOW + 1
5265 0 : XLOWT (JLOW) = XDONT(ICRS)
5266 0 : Else If (ICRS >= NDON) Then
5267 : Exit
5268 : End If
5269 : End Do
5270 : End If
5271 : !
5272 : !
5273 : Else
5274 : !
5275 : ! Same as above, but this is not as easy to optimize, so the
5276 : ! DO-loop is kept
5277 : !
5278 0 : Do ICRS = 4, NDON - 1
5279 0 : If (XDONT(ICRS) > XPIV) Then
5280 0 : JHIG = JHIG + 1
5281 0 : XHIGT (JHIG) = XDONT(ICRS)
5282 : Else
5283 0 : JLOW = JLOW + 1
5284 0 : XLOWT (JLOW) = XDONT(ICRS)
5285 0 : If (JLOW >= INTH) Exit
5286 : End If
5287 : End Do
5288 : !
5289 0 : If (ICRS < NDON - 1) Then
5290 : Do
5291 0 : ICRS = ICRS + 1
5292 0 : If (XDONT(ICRS) <= XPIV) Then
5293 0 : If (ICRS >= NDON) Exit
5294 0 : JLOW = JLOW + 1
5295 0 : XLOWT (JLOW) = XDONT(ICRS)
5296 : End If
5297 : End Do
5298 : End If
5299 : End If
5300 : !
5301 : JLM2 = 0
5302 : JLM1 = 0
5303 : JHM2 = 0
5304 : JHM1 = 0
5305 : Do
5306 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
5307 : !
5308 : ! We are oscillating. Perturbate by bringing JLOW closer by one
5309 : ! to INTH
5310 : !
5311 0 : If (INTH > JLOW) Then
5312 0 : XMIN = XHIGT(1)
5313 0 : IHIG = 1
5314 0 : Do ICRS = 2, JHIG
5315 0 : If (XHIGT(ICRS) < XMIN) Then
5316 0 : XMIN = XHIGT(ICRS)
5317 0 : IHIG = ICRS
5318 : End If
5319 : End Do
5320 : !
5321 0 : JLOW = JLOW + 1
5322 0 : XLOWT (JLOW) = XHIGT (IHIG)
5323 0 : XHIGT (IHIG) = XHIGT (JHIG)
5324 0 : JHIG = JHIG - 1
5325 : Else
5326 :
5327 0 : XMAX = XLOWT (JLOW)
5328 0 : JLOW = JLOW - 1
5329 0 : Do ICRS = 1, JLOW
5330 0 : If (XLOWT(ICRS) > XMAX) Then
5331 0 : XWRK = XMAX
5332 0 : XMAX = XLOWT(ICRS)
5333 0 : XLOWT (ICRS) = XWRK
5334 : End If
5335 : End Do
5336 : End If
5337 : End If
5338 0 : JLM2 = JLM1
5339 0 : JLM1 = JLOW
5340 0 : JHM2 = JHM1
5341 0 : JHM1 = JHIG
5342 : !
5343 : ! We try to bring the number of values in the low values set
5344 : ! closer to INTH.
5345 : !
5346 0 : Select Case (INTH - JLOW)
5347 : Case (2 :)
5348 : !
5349 : ! Not enough values in low part, at least 2 are missing
5350 : !
5351 0 : INTH = INTH - JLOW
5352 0 : JLOW = 0
5353 : Select Case (JHIG)
5354 : !!!!! CASE DEFAULT
5355 : !!!!! write (unit=*,fmt=*) "Assertion failed"
5356 : !!!!! STOP
5357 : !
5358 : ! We make a special case when we have so few values in
5359 : ! the high values set that it is bad performance to choose a pivot
5360 : ! and apply the general algorithm.
5361 : !
5362 : Case (2)
5363 0 : If (XHIGT(1) <= XHIGT(2)) Then
5364 0 : JLOW = JLOW + 1
5365 0 : XLOWT (JLOW) = XHIGT (1)
5366 0 : JLOW = JLOW + 1
5367 0 : XLOWT (JLOW) = XHIGT (2)
5368 : Else
5369 0 : JLOW = JLOW + 1
5370 0 : XLOWT (JLOW) = XHIGT (2)
5371 0 : JLOW = JLOW + 1
5372 0 : XLOWT (JLOW) = XHIGT (1)
5373 : End If
5374 : Exit
5375 : !
5376 : Case (3)
5377 : !
5378 : !
5379 0 : XWRK1 = XHIGT (1)
5380 0 : XWRK2 = XHIGT (2)
5381 0 : XWRK3 = XHIGT (3)
5382 0 : If (XWRK2 < XWRK1) Then
5383 0 : XHIGT (1) = XWRK2
5384 0 : XHIGT (2) = XWRK1
5385 0 : XWRK2 = XWRK1
5386 : End If
5387 0 : If (XWRK2 > XWRK3) Then
5388 0 : XHIGT (3) = XWRK2
5389 0 : XHIGT (2) = XWRK3
5390 0 : XWRK2 = XWRK3
5391 0 : If (XWRK2 < XHIGT(1)) Then
5392 0 : XHIGT (2) = XHIGT (1)
5393 0 : XHIGT (1) = XWRK2
5394 : End If
5395 : End If
5396 : JHIG = 0
5397 0 : Do ICRS = JLOW + 1, INTH
5398 0 : JHIG = JHIG + 1
5399 0 : XLOWT (ICRS) = XHIGT (JHIG)
5400 : End Do
5401 0 : JLOW = INTH
5402 : Exit
5403 : !
5404 : Case (4 :)
5405 : !
5406 : !
5407 0 : IFIN = JHIG
5408 : !
5409 : ! One chooses a pivot from the 2 first values and the last one.
5410 : ! This should ensure sufficient renewal between iterations to
5411 : ! avoid worst case behavior effects.
5412 : !
5413 0 : XWRK1 = XHIGT (1)
5414 0 : XWRK2 = XHIGT (2)
5415 0 : XWRK3 = XHIGT (IFIN)
5416 0 : If (XWRK2 < XWRK1) Then
5417 0 : XHIGT (1) = XWRK2
5418 0 : XHIGT (2) = XWRK1
5419 0 : XWRK2 = XWRK1
5420 : End If
5421 0 : If (XWRK2 > XWRK3) Then
5422 0 : XHIGT (IFIN) = XWRK2
5423 0 : XHIGT (2) = XWRK3
5424 0 : XWRK2 = XWRK3
5425 0 : If (XWRK2 < XHIGT(1)) Then
5426 0 : XHIGT (2) = XHIGT (1)
5427 0 : XHIGT (1) = XWRK2
5428 : End If
5429 : End If
5430 : !
5431 0 : XWRK1 = XHIGT (1)
5432 0 : JLOW = JLOW + 1
5433 0 : XLOWT (JLOW) = XWRK1
5434 0 : XPIV = XWRK1 + (XHIGT(IFIN) - XWRK1) / 2
5435 : !
5436 : ! One takes values <= pivot to XLOWT
5437 : ! Again, 2 parts, one where we take care of the remaining
5438 : ! high values because we might still need them, and the
5439 : ! other when we know that we will have more than enough
5440 : ! low values in the end.
5441 : !
5442 0 : JHIG = 0
5443 0 : Do ICRS = 2, IFIN
5444 0 : If (XHIGT(ICRS) <= XPIV) Then
5445 0 : JLOW = JLOW + 1
5446 0 : XLOWT (JLOW) = XHIGT (ICRS)
5447 0 : If (JLOW >= INTH) Exit
5448 : Else
5449 0 : JHIG = JHIG + 1
5450 0 : XHIGT (JHIG) = XHIGT (ICRS)
5451 : End If
5452 : End Do
5453 : !
5454 0 : Do ICRS = ICRS + 1, IFIN
5455 0 : If (XHIGT(ICRS) <= XPIV) Then
5456 0 : JLOW = JLOW + 1
5457 0 : XLOWT (JLOW) = XHIGT (ICRS)
5458 : End If
5459 : End Do
5460 : End Select
5461 : !
5462 : !
5463 : Case (1)
5464 : !
5465 : ! Only 1 value is missing in low part
5466 : !
5467 0 : XMIN = XHIGT(1)
5468 0 : Do ICRS = 2, JHIG
5469 0 : If (XHIGT(ICRS) < XMIN) Then
5470 0 : XMIN = XHIGT(ICRS)
5471 : End If
5472 : End Do
5473 : !
5474 0 : JLOW = JLOW + 1
5475 0 : XLOWT (JLOW) = XMIN
5476 0 : Exit
5477 : !
5478 : !
5479 : Case (0)
5480 : !
5481 : ! Low part is exactly what we want
5482 : !
5483 0 : Exit
5484 : !
5485 : !
5486 : Case (-5 : -1)
5487 : !
5488 : ! Only few values too many in low part
5489 : !
5490 0 : IF (IFODD) THEN
5491 0 : JHIG = JLOW - INTH + 1
5492 : Else
5493 0 : JHIG = JLOW - INTH + 2
5494 : end if
5495 0 : XHIGT (1) = XLOWT (1)
5496 0 : Do ICRS = 2, JHIG
5497 0 : XWRK = XLOWT (ICRS)
5498 0 : Do IDCR = ICRS - 1, 1, - 1
5499 0 : If (XWRK < XHIGT(IDCR)) Then
5500 0 : XHIGT (IDCR + 1) = XHIGT (IDCR)
5501 : Else
5502 : Exit
5503 : End If
5504 : End Do
5505 0 : XHIGT (IDCR + 1) = XWRK
5506 : End Do
5507 : !
5508 0 : Do ICRS = JHIG + 1, JLOW
5509 0 : If (XLOWT (ICRS) > XHIGT(1)) Then
5510 0 : XWRK = XLOWT (ICRS)
5511 0 : Do IDCR = 2, JHIG
5512 0 : If (XWRK >= XHIGT(IDCR)) Then
5513 0 : XHIGT (IDCR - 1) = XHIGT (IDCR)
5514 : else
5515 : exit
5516 : end if
5517 : End Do
5518 0 : XHIGT (IDCR - 1) = XWRK
5519 : End If
5520 : End Do
5521 : !
5522 0 : IF (IFODD) THEN
5523 0 : median = XHIGT(1)
5524 : Else
5525 0 : median = (XHIGT(1) + XHIGT(2)) / 2
5526 : end if
5527 0 : Return
5528 : !
5529 : !
5530 : Case (: -6)
5531 : !
5532 : ! last case: too many values in low part
5533 : !
5534 :
5535 0 : IMIL = (JLOW + 1) / 2
5536 0 : IFIN = JLOW
5537 : !
5538 : ! One chooses a pivot from 1st, last, and middle values
5539 : !
5540 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
5541 0 : XWRK = XLOWT (1)
5542 0 : XLOWT (1) = XLOWT (IMIL)
5543 0 : XLOWT (IMIL) = XWRK
5544 : End If
5545 0 : If (XLOWT(IMIL) > XLOWT(IFIN)) Then
5546 0 : XWRK = XLOWT (IFIN)
5547 0 : XLOWT (IFIN) = XLOWT (IMIL)
5548 0 : XLOWT (IMIL) = XWRK
5549 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
5550 0 : XWRK = XLOWT (1)
5551 0 : XLOWT (1) = XLOWT (IMIL)
5552 0 : XLOWT (IMIL) = XWRK
5553 : End If
5554 : End If
5555 0 : If (IFIN <= 3) Exit
5556 : !
5557 : XPIV = XLOWT(1) + INT(REAL(INTH, sp) / REAL(JLOW + INTH, sp), i4) * &
5558 0 : (XLOWT(IFIN) - XLOWT(1))
5559 :
5560 : !
5561 : ! One takes values > XPIV to XHIGT
5562 : !
5563 0 : JHIG = 0
5564 0 : JLOW = 0
5565 : !
5566 0 : If (XLOWT(IFIN) > XPIV) Then
5567 : ICRS = 0
5568 : Do
5569 0 : ICRS = ICRS + 1
5570 0 : If (XLOWT(ICRS) > XPIV) Then
5571 0 : JHIG = JHIG + 1
5572 0 : XHIGT (JHIG) = XLOWT (ICRS)
5573 0 : If (ICRS >= IFIN) Exit
5574 : Else
5575 0 : JLOW = JLOW + 1
5576 0 : XLOWT (JLOW) = XLOWT (ICRS)
5577 0 : If (JLOW >= INTH) Exit
5578 : End If
5579 : End Do
5580 : !
5581 0 : If (ICRS < IFIN) Then
5582 : Do
5583 0 : ICRS = ICRS + 1
5584 0 : If (XLOWT(ICRS) <= XPIV) Then
5585 0 : JLOW = JLOW + 1
5586 0 : XLOWT (JLOW) = XLOWT (ICRS)
5587 : Else
5588 0 : If (ICRS >= IFIN) Exit
5589 : End If
5590 : End Do
5591 : End If
5592 : Else
5593 0 : Do ICRS = 1, IFIN
5594 0 : If (XLOWT(ICRS) > XPIV) Then
5595 0 : JHIG = JHIG + 1
5596 0 : XHIGT (JHIG) = XLOWT (ICRS)
5597 : Else
5598 0 : JLOW = JLOW + 1
5599 0 : XLOWT (JLOW) = XLOWT (ICRS)
5600 0 : If (JLOW >= INTH) Exit
5601 : End If
5602 : End Do
5603 : !
5604 0 : Do ICRS = ICRS + 1, IFIN
5605 0 : If (XLOWT(ICRS) <= XPIV) Then
5606 0 : JLOW = JLOW + 1
5607 0 : XLOWT (JLOW) = XLOWT (ICRS)
5608 : End If
5609 : End Do
5610 : End If
5611 : !
5612 : End Select
5613 : !
5614 : End Do
5615 : !
5616 : ! Now, we only need to find maximum of the 1:INTH set
5617 : !
5618 0 : if (IFODD) then
5619 0 : median = MAXVAL (XLOWT (1 : INTH))
5620 : else
5621 0 : XWRK = MAX (XLOWT (1), XLOWT (2))
5622 0 : XWRK1 = MIN (XLOWT (1), XLOWT (2))
5623 0 : DO ICRS = 3, INTH
5624 0 : IF (XLOWT (ICRS) > XWRK1) THEN
5625 0 : IF (XLOWT (ICRS) > XWRK) THEN
5626 : XWRK1 = XWRK
5627 : XWRK = XLOWT (ICRS)
5628 : Else
5629 0 : XWRK1 = XLOWT (ICRS)
5630 : end if
5631 : end if
5632 : ENDDO
5633 0 : median = (XWRK + XWRK1) / 2
5634 : end if
5635 : Return
5636 : !
5637 1 : End Function I_median
5638 :
5639 0 : Subroutine D_mrgref (XVALT, IRNGT)
5640 : ! Ranks array XVALT into index array IRNGT, using merge-sort
5641 : ! __________________________________________________________
5642 : ! This version is not optimized for performance, and is thus
5643 : ! not as difficult to read as some other ones.
5644 : ! Michel Olagnon - April 2000
5645 : ! __________________________________________________________
5646 : ! __________________________________________________________
5647 : real(kind = dp), Dimension (:), Intent (In) :: XVALT
5648 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
5649 : ! __________________________________________________________
5650 : !
5651 0 : Integer(kind = i4), Dimension (:), Allocatable :: JWRKT
5652 : Integer(kind = i4) :: LMTNA, LMTNC
5653 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
5654 : !
5655 0 : NVAL = Min (SIZE(XVALT), SIZE(IRNGT))
5656 0 : If (NVAL <= 0) Then
5657 : Return
5658 : End If
5659 : !
5660 : ! Fill-in the index array, creating ordered couples
5661 : !
5662 0 : Do IIND = 2, NVAL, 2
5663 0 : If (XVALT(IIND - 1) <= XVALT(IIND)) Then
5664 0 : IRNGT (IIND - 1) = IIND - 1
5665 0 : IRNGT (IIND) = IIND
5666 : Else
5667 0 : IRNGT (IIND - 1) = IIND
5668 0 : IRNGT (IIND) = IIND - 1
5669 : End If
5670 : End Do
5671 0 : If (Modulo (NVAL, 2) /= 0) Then
5672 0 : IRNGT (NVAL) = NVAL
5673 : End If
5674 : !
5675 : ! We will now have ordered subsets A - B - A - B - ...
5676 : ! and merge A and B couples into C - C - ...
5677 : !
5678 0 : Allocate (JWRKT(1 : NVAL))
5679 0 : LMTNC = 2
5680 0 : LMTNA = 2
5681 : !
5682 : ! Iteration. Each time, the length of the ordered subsets
5683 : ! is doubled.
5684 : !
5685 0 : Do
5686 0 : If (LMTNA >= NVAL) Exit
5687 0 : IWRKF = 0
5688 0 : LMTNC = 2 * LMTNC
5689 0 : IWRK = 0
5690 : !
5691 : ! Loop on merges of A and B into C
5692 : !
5693 : Do
5694 0 : IINDA = IWRKF
5695 0 : IWRKD = IWRKF + 1
5696 0 : IWRKF = IINDA + LMTNC
5697 0 : JINDA = IINDA + LMTNA
5698 0 : If (IWRKF >= NVAL) Then
5699 0 : If (JINDA >= NVAL) Exit
5700 : IWRKF = NVAL
5701 : End If
5702 0 : IINDB = JINDA
5703 : !
5704 : ! Shortcut for the case when the max of A is smaller
5705 : ! than the min of B (no need to do anything)
5706 : !
5707 0 : If (XVALT(IRNGT(JINDA)) <= XVALT(IRNGT(JINDA + 1))) Then
5708 : IWRK = IWRKF
5709 : Cycle
5710 : End If
5711 : !
5712 : ! One steps in the C subset, that we create in the final rank array
5713 : !
5714 0 : Do
5715 0 : If (IWRK >= IWRKF) Then
5716 : !
5717 : ! Make a copy of the rank array for next iteration
5718 : !
5719 0 : IRNGT (IWRKD : IWRKF) = JWRKT (IWRKD : IWRKF)
5720 : Exit
5721 : End If
5722 : !
5723 0 : IWRK = IWRK + 1
5724 : !
5725 : ! We still have unprocessed values in both A and B
5726 : !
5727 0 : If (IINDA < JINDA) Then
5728 0 : If (IINDB < IWRKF) Then
5729 0 : If (XVALT(IRNGT(IINDA + 1)) > XVALT(IRNGT(IINDB + 1))) &
5730 : & Then
5731 0 : IINDB = IINDB + 1
5732 0 : JWRKT (IWRK) = IRNGT (IINDB)
5733 : Else
5734 0 : IINDA = IINDA + 1
5735 0 : JWRKT (IWRK) = IRNGT (IINDA)
5736 : End If
5737 : Else
5738 : !
5739 : ! Only A still with unprocessed values
5740 : !
5741 0 : IINDA = IINDA + 1
5742 0 : JWRKT (IWRK) = IRNGT (IINDA)
5743 : End If
5744 : Else
5745 : !
5746 : ! Only B still with unprocessed values
5747 : !
5748 0 : IRNGT (IWRKD : IINDB) = JWRKT (IWRKD : IINDB)
5749 : IWRK = IWRKF
5750 : Exit
5751 : End If
5752 : !
5753 : End Do
5754 : End Do
5755 : !
5756 : ! The Cs become As and Bs
5757 : !
5758 0 : LMTNA = 2 * LMTNA
5759 : End Do
5760 : !
5761 : ! Clean up
5762 : !
5763 0 : Deallocate (JWRKT)
5764 0 : Return
5765 : !
5766 0 : End Subroutine D_mrgref
5767 :
5768 0 : Subroutine R_mrgref (XVALT, IRNGT)
5769 : ! Ranks array XVALT into index array IRNGT, using merge-sort
5770 : ! __________________________________________________________
5771 : ! This version is not optimized for performance, and is thus
5772 : ! not as difficult to read as some other ones.
5773 : ! Michel Olagnon - April 2000
5774 : ! __________________________________________________________
5775 : ! _________________________________________________________
5776 : Real(kind = sp), Dimension (:), Intent (In) :: XVALT
5777 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
5778 : ! __________________________________________________________
5779 : !
5780 0 : Integer(kind = i4), Dimension (:), Allocatable :: JWRKT
5781 : Integer(kind = i4) :: LMTNA, LMTNC
5782 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
5783 : !
5784 0 : NVAL = Min (SIZE(XVALT), SIZE(IRNGT))
5785 0 : If (NVAL <= 0) Then
5786 : Return
5787 : End If
5788 : !
5789 : ! Fill-in the index array, creating ordered couples
5790 : !
5791 0 : Do IIND = 2, NVAL, 2
5792 0 : If (XVALT(IIND - 1) <= XVALT(IIND)) Then
5793 0 : IRNGT (IIND - 1) = IIND - 1
5794 0 : IRNGT (IIND) = IIND
5795 : Else
5796 0 : IRNGT (IIND - 1) = IIND
5797 0 : IRNGT (IIND) = IIND - 1
5798 : End If
5799 : End Do
5800 0 : If (Modulo (NVAL, 2) /= 0) Then
5801 0 : IRNGT (NVAL) = NVAL
5802 : End If
5803 : !
5804 : ! We will now have ordered subsets A - B - A - B - ...
5805 : ! and merge A and B couples into C - C - ...
5806 : !
5807 0 : Allocate (JWRKT(1 : NVAL))
5808 0 : LMTNC = 2
5809 0 : LMTNA = 2
5810 : !
5811 : ! Iteration. Each time, the length of the ordered subsets
5812 : ! is doubled.
5813 : !
5814 0 : Do
5815 0 : If (LMTNA >= NVAL) Exit
5816 0 : IWRKF = 0
5817 0 : LMTNC = 2 * LMTNC
5818 0 : IWRK = 0
5819 : !
5820 : ! Loop on merges of A and B into C
5821 : !
5822 : Do
5823 0 : IINDA = IWRKF
5824 0 : IWRKD = IWRKF + 1
5825 0 : IWRKF = IINDA + LMTNC
5826 0 : JINDA = IINDA + LMTNA
5827 0 : If (IWRKF >= NVAL) Then
5828 0 : If (JINDA >= NVAL) Exit
5829 : IWRKF = NVAL
5830 : End If
5831 0 : IINDB = JINDA
5832 : !
5833 : ! Shortcut for the case when the max of A is smaller
5834 : ! than the min of B (no need to do anything)
5835 : !
5836 0 : If (XVALT(IRNGT(JINDA)) <= XVALT(IRNGT(JINDA + 1))) Then
5837 : IWRK = IWRKF
5838 : Cycle
5839 : End If
5840 : !
5841 : ! One steps in the C subset, that we create in the final rank array
5842 : !
5843 0 : Do
5844 0 : If (IWRK >= IWRKF) Then
5845 : !
5846 : ! Make a copy of the rank array for next iteration
5847 : !
5848 0 : IRNGT (IWRKD : IWRKF) = JWRKT (IWRKD : IWRKF)
5849 : Exit
5850 : End If
5851 : !
5852 0 : IWRK = IWRK + 1
5853 : !
5854 : ! We still have unprocessed values in both A and B
5855 : !
5856 0 : If (IINDA < JINDA) Then
5857 0 : If (IINDB < IWRKF) Then
5858 0 : If (XVALT(IRNGT(IINDA + 1)) > XVALT(IRNGT(IINDB + 1))) &
5859 : & Then
5860 0 : IINDB = IINDB + 1
5861 0 : JWRKT (IWRK) = IRNGT (IINDB)
5862 : Else
5863 0 : IINDA = IINDA + 1
5864 0 : JWRKT (IWRK) = IRNGT (IINDA)
5865 : End If
5866 : Else
5867 : !
5868 : ! Only A still with unprocessed values
5869 : !
5870 0 : IINDA = IINDA + 1
5871 0 : JWRKT (IWRK) = IRNGT (IINDA)
5872 : End If
5873 : Else
5874 : !
5875 : ! Only B still with unprocessed values
5876 : !
5877 0 : IRNGT (IWRKD : IINDB) = JWRKT (IWRKD : IINDB)
5878 : IWRK = IWRKF
5879 : Exit
5880 : End If
5881 : !
5882 : End Do
5883 : End Do
5884 : !
5885 : ! The Cs become As and Bs
5886 : !
5887 0 : LMTNA = 2 * LMTNA
5888 : End Do
5889 : !
5890 : ! Clean up
5891 : !
5892 0 : Deallocate (JWRKT)
5893 0 : Return
5894 : !
5895 0 : End Subroutine R_mrgref
5896 :
5897 0 : Subroutine I_mrgref (XVALT, IRNGT)
5898 : ! Ranks array XVALT into index array IRNGT, using merge-sort
5899 : ! __________________________________________________________
5900 : ! This version is not optimized for performance, and is thus
5901 : ! not as difficult to read as some other ones.
5902 : ! Michel Olagnon - April 2000
5903 : ! __________________________________________________________
5904 : ! __________________________________________________________
5905 : Integer(kind = i4), Dimension (:), Intent (In) :: XVALT
5906 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
5907 : ! __________________________________________________________
5908 : !
5909 0 : Integer(kind = i4), Dimension (:), Allocatable :: JWRKT
5910 : Integer(kind = i4) :: LMTNA, LMTNC
5911 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
5912 : !
5913 0 : NVAL = Min (SIZE(XVALT), SIZE(IRNGT))
5914 0 : If (NVAL <= 0) Then
5915 : Return
5916 : End If
5917 : !
5918 : ! Fill-in the index array, creating ordered couples
5919 : !
5920 0 : Do IIND = 2, NVAL, 2
5921 0 : If (XVALT(IIND - 1) <= XVALT(IIND)) Then
5922 0 : IRNGT (IIND - 1) = IIND - 1
5923 0 : IRNGT (IIND) = IIND
5924 : Else
5925 0 : IRNGT (IIND - 1) = IIND
5926 0 : IRNGT (IIND) = IIND - 1
5927 : End If
5928 : End Do
5929 0 : If (Modulo (NVAL, 2) /= 0) Then
5930 0 : IRNGT (NVAL) = NVAL
5931 : End If
5932 : !
5933 : ! We will now have ordered subsets A - B - A - B - ...
5934 : ! and merge A and B couples into C - C - ...
5935 : !
5936 0 : Allocate (JWRKT(1 : NVAL))
5937 0 : LMTNC = 2
5938 0 : LMTNA = 2
5939 : !
5940 : ! Iteration. Each time, the length of the ordered subsets
5941 : ! is doubled.
5942 : !
5943 0 : Do
5944 0 : If (LMTNA >= NVAL) Exit
5945 0 : IWRKF = 0
5946 0 : LMTNC = 2 * LMTNC
5947 0 : IWRK = 0
5948 : !
5949 : ! Loop on merges of A and B into C
5950 : !
5951 : Do
5952 0 : IINDA = IWRKF
5953 0 : IWRKD = IWRKF + 1
5954 0 : IWRKF = IINDA + LMTNC
5955 0 : JINDA = IINDA + LMTNA
5956 0 : If (IWRKF >= NVAL) Then
5957 0 : If (JINDA >= NVAL) Exit
5958 : IWRKF = NVAL
5959 : End If
5960 0 : IINDB = JINDA
5961 : !
5962 : ! Shortcut for the case when the max of A is smaller
5963 : ! than the min of B (no need to do anything)
5964 : !
5965 0 : If (XVALT(IRNGT(JINDA)) <= XVALT(IRNGT(JINDA + 1))) Then
5966 : IWRK = IWRKF
5967 : Cycle
5968 : End If
5969 : !
5970 : ! One steps in the C subset, that we create in the final rank array
5971 : !
5972 0 : Do
5973 0 : If (IWRK >= IWRKF) Then
5974 : !
5975 : ! Make a copy of the rank array for next iteration
5976 : !
5977 0 : IRNGT (IWRKD : IWRKF) = JWRKT (IWRKD : IWRKF)
5978 : Exit
5979 : End If
5980 : !
5981 0 : IWRK = IWRK + 1
5982 : !
5983 : ! We still have unprocessed values in both A and B
5984 : !
5985 0 : If (IINDA < JINDA) Then
5986 0 : If (IINDB < IWRKF) Then
5987 0 : If (XVALT(IRNGT(IINDA + 1)) > XVALT(IRNGT(IINDB + 1))) &
5988 : & Then
5989 0 : IINDB = IINDB + 1
5990 0 : JWRKT (IWRK) = IRNGT (IINDB)
5991 : Else
5992 0 : IINDA = IINDA + 1
5993 0 : JWRKT (IWRK) = IRNGT (IINDA)
5994 : End If
5995 : Else
5996 : !
5997 : ! Only A still with unprocessed values
5998 : !
5999 0 : IINDA = IINDA + 1
6000 0 : JWRKT (IWRK) = IRNGT (IINDA)
6001 : End If
6002 : Else
6003 : !
6004 : ! Only B still with unprocessed values
6005 : !
6006 0 : IRNGT (IWRKD : IINDB) = JWRKT (IWRKD : IINDB)
6007 : IWRK = IWRKF
6008 : Exit
6009 : End If
6010 : !
6011 : End Do
6012 : End Do
6013 : !
6014 : ! The Cs become As and Bs
6015 : !
6016 0 : LMTNA = 2 * LMTNA
6017 : End Do
6018 : !
6019 : ! Clean up
6020 : !
6021 0 : Deallocate (JWRKT)
6022 0 : Return
6023 : !
6024 0 : End Subroutine I_mrgref
6025 :
6026 9010 : Subroutine D_mrgrnk (XDONT, IRNGT)
6027 : ! __________________________________________________________
6028 : ! MRGRNK = Merge-sort ranking of an array
6029 : ! For performance reasons, the first 2 passes are taken
6030 : ! out of the standard loop, and use dedicated coding.
6031 : ! __________________________________________________________
6032 : ! __________________________________________________________
6033 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
6034 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
6035 : ! __________________________________________________________
6036 4505 : real(kind = dp) :: XVALA, XVALB
6037 : !
6038 4505 : Integer(kind = i4), Dimension (SIZE(IRNGT)) :: JWRKT
6039 : Integer(kind = i4) :: LMTNA, LMTNC, IRNG1, IRNG2
6040 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
6041 : !
6042 4505 : NVAL = Min (SIZE(XDONT), SIZE(IRNGT))
6043 : Select Case (NVAL)
6044 : Case (: 0)
6045 0 : Return
6046 : Case (1)
6047 0 : IRNGT (1) = 1
6048 4505 : Return
6049 : Case Default
6050 :
6051 : End Select
6052 : !
6053 : ! Fill-in the index array, creating ordered couples
6054 : !
6055 135465 : Do IIND = 2, NVAL, 2
6056 135465 : If (XDONT(IIND - 1) <= XDONT(IIND)) Then
6057 128003 : IRNGT (IIND - 1) = IIND - 1
6058 128003 : IRNGT (IIND) = IIND
6059 : Else
6060 2957 : IRNGT (IIND - 1) = IIND
6061 2957 : IRNGT (IIND) = IIND - 1
6062 : End If
6063 : End Do
6064 4505 : If (Modulo(NVAL, 2) /= 0) Then
6065 4452 : IRNGT (NVAL) = NVAL
6066 : End If
6067 : !
6068 : ! We will now have ordered subsets A - B - A - B - ...
6069 : ! and merge A and B couples into C - C - ...
6070 : !
6071 4505 : LMTNA = 2
6072 4505 : LMTNC = 4
6073 : !
6074 : ! First iteration. The length of the ordered subsets goes from 2 to 4
6075 : !
6076 : Do
6077 4505 : If (NVAL <= 2) Exit
6078 : !
6079 : ! Loop on merges of A and B into C
6080 : !
6081 69868 : Do IWRKD = 0, NVAL - 1, 4
6082 69867 : If ((IWRKD + 4) > NVAL) Then
6083 4504 : If ((IWRKD + 2) >= NVAL) Exit
6084 : !
6085 : ! 1 2 3
6086 : !
6087 182 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Exit
6088 : !
6089 : ! 1 3 2
6090 : !
6091 21 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
6092 15 : IRNG2 = IRNGT (IWRKD + 2)
6093 15 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
6094 15 : IRNGT (IWRKD + 3) = IRNG2
6095 : !
6096 : ! 3 1 2
6097 : !
6098 : Else
6099 6 : IRNG1 = IRNGT (IWRKD + 1)
6100 6 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
6101 6 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 2)
6102 6 : IRNGT (IWRKD + 2) = IRNG1
6103 : End If
6104 : If (.true.) Exit ! Exit ! JM
6105 : End If
6106 : !
6107 : ! 1 2 3 4
6108 : !
6109 65363 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Cycle
6110 : !
6111 : ! 1 3 x x
6112 : !
6113 7463 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
6114 879 : IRNG2 = IRNGT (IWRKD + 2)
6115 879 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
6116 879 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
6117 : ! 1 3 2 4
6118 869 : IRNGT (IWRKD + 3) = IRNG2
6119 : Else
6120 : ! 1 3 4 2
6121 10 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
6122 10 : IRNGT (IWRKD + 4) = IRNG2
6123 : End If
6124 : !
6125 : ! 3 x x x
6126 : !
6127 : Else
6128 2100 : IRNG1 = IRNGT (IWRKD + 1)
6129 2100 : IRNG2 = IRNGT (IWRKD + 2)
6130 2100 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
6131 2100 : If (XDONT(IRNG1) <= XDONT(IRNGT(IWRKD + 4))) Then
6132 2092 : IRNGT (IWRKD + 2) = IRNG1
6133 2092 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
6134 : ! 3 1 2 4
6135 2090 : IRNGT (IWRKD + 3) = IRNG2
6136 : Else
6137 : ! 3 1 4 2
6138 2 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
6139 2 : IRNGT (IWRKD + 4) = IRNG2
6140 : End If
6141 : Else
6142 : ! 3 4 1 2
6143 8 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 4)
6144 8 : IRNGT (IWRKD + 3) = IRNG1
6145 8 : IRNGT (IWRKD + 4) = IRNG2
6146 : End If
6147 : End If
6148 : End Do
6149 : !
6150 : ! The Cs become As and Bs
6151 : !
6152 : LMTNA = 4
6153 0 : If (.true.) Exit ! Exit ! JM
6154 : End Do
6155 : !
6156 : ! Iteration loop. Each time, the length of the ordered subsets
6157 : ! is doubled.
6158 : !
6159 17477 : Do
6160 21982 : If (LMTNA >= NVAL) Exit
6161 17477 : IWRKF = 0
6162 17477 : LMTNC = 2 * LMTNC
6163 : !
6164 : ! Loop on merges of A and B into C
6165 : !
6166 : Do
6167 82839 : IWRK = IWRKF
6168 82839 : IWRKD = IWRKF + 1
6169 82839 : JINDA = IWRKF + LMTNA
6170 82839 : IWRKF = IWRKF + LMTNC
6171 82839 : If (IWRKF >= NVAL) Then
6172 34914 : If (JINDA >= NVAL) Exit
6173 : IWRKF = NVAL
6174 : End If
6175 65362 : IINDA = 1
6176 65362 : IINDB = JINDA + 1
6177 : !
6178 : ! Shortcut for the case when the max of A is smaller
6179 : ! than the min of B. This line may be activated when the
6180 : ! initial set is already close to sorted.
6181 : !
6182 : ! IF (XDONT(IRNGT(JINDA)) <= XDONT(IRNGT(IINDB))) CYCLE
6183 : !
6184 : ! One steps in the C subset, that we build in the final rank array
6185 : !
6186 : ! Make a copy of the rank array for the merge iteration
6187 : !
6188 624306 : JWRKT (1 : LMTNA) = IRNGT (IWRKD : JINDA)
6189 : !
6190 65362 : XVALA = XDONT (JWRKT(IINDA))
6191 65362 : XVALB = XDONT (IRNGT(IINDB))
6192 : !
6193 17477 : Do
6194 571262 : IWRK = IWRK + 1
6195 : !
6196 : ! We still have unprocessed values in both A and B
6197 : !
6198 636538 : If (XVALA > XVALB) Then
6199 12557 : IRNGT (IWRK) = IRNGT (IINDB)
6200 12557 : IINDB = IINDB + 1
6201 12557 : If (IINDB > IWRKF) Then
6202 : ! Only A still with unprocessed values
6203 325 : IRNGT (IWRK + 1 : IWRKF) = JWRKT (IINDA : LMTNA)
6204 : Exit
6205 : End If
6206 12471 : XVALB = XDONT (IRNGT(IINDB))
6207 : Else
6208 558705 : IRNGT (IWRK) = JWRKT (IINDA)
6209 558705 : IINDA = IINDA + 1
6210 558705 : If (IINDA > LMTNA) Exit! Only B still with unprocessed values
6211 493429 : XVALA = XDONT (JWRKT(IINDA))
6212 : End If
6213 : !
6214 : End Do
6215 : End Do
6216 : !
6217 : ! The Cs become As and Bs
6218 : !
6219 17477 : LMTNA = 2 * LMTNA
6220 : End Do
6221 : !
6222 : Return
6223 : !
6224 0 : End Subroutine D_mrgrnk
6225 :
6226 4 : Subroutine R_mrgrnk (XDONT, IRNGT)
6227 : ! __________________________________________________________
6228 : ! MRGRNK = Merge-sort ranking of an array
6229 : ! For performance reasons, the first 2 passes are taken
6230 : ! out of the standard loop, and use dedicated coding.
6231 : ! __________________________________________________________
6232 : ! _________________________________________________________
6233 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
6234 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
6235 : ! __________________________________________________________
6236 2 : Real(kind = sp) :: XVALA, XVALB
6237 : !
6238 2 : Integer(kind = i4), Dimension (SIZE(IRNGT)) :: JWRKT
6239 : Integer(kind = i4) :: LMTNA, LMTNC, IRNG1, IRNG2
6240 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
6241 : !
6242 2 : NVAL = Min (SIZE(XDONT), SIZE(IRNGT))
6243 : Select Case (NVAL)
6244 : Case (: 0)
6245 0 : Return
6246 : Case (1)
6247 0 : IRNGT (1) = 1
6248 2 : Return
6249 : Case Default
6250 :
6251 : End Select
6252 : !
6253 : ! Fill-in the index array, creating ordered couples
6254 : !
6255 12 : Do IIND = 2, NVAL, 2
6256 12 : If (XDONT(IIND - 1) <= XDONT(IIND)) Then
6257 0 : IRNGT (IIND - 1) = IIND - 1
6258 0 : IRNGT (IIND) = IIND
6259 : Else
6260 10 : IRNGT (IIND - 1) = IIND
6261 10 : IRNGT (IIND) = IIND - 1
6262 : End If
6263 : End Do
6264 2 : If (Modulo(NVAL, 2) /= 0) Then
6265 0 : IRNGT (NVAL) = NVAL
6266 : End If
6267 : !
6268 : ! We will now have ordered subsets A - B - A - B - ...
6269 : ! and merge A and B couples into C - C - ...
6270 : !
6271 2 : LMTNA = 2
6272 2 : LMTNC = 4
6273 : !
6274 : ! First iteration. The length of the ordered subsets goes from 2 to 4
6275 : !
6276 : Do
6277 2 : If (NVAL <= 2) Exit
6278 : !
6279 : ! Loop on merges of A and B into C
6280 : !
6281 6 : Do IWRKD = 0, NVAL - 1, 4
6282 6 : If ((IWRKD + 4) > NVAL) Then
6283 2 : If ((IWRKD + 2) >= NVAL) Exit
6284 : !
6285 : ! 1 2 3
6286 : !
6287 0 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Exit
6288 : !
6289 : ! 1 3 2
6290 : !
6291 0 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
6292 0 : IRNG2 = IRNGT (IWRKD + 2)
6293 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
6294 0 : IRNGT (IWRKD + 3) = IRNG2
6295 : !
6296 : ! 3 1 2
6297 : !
6298 : Else
6299 0 : IRNG1 = IRNGT (IWRKD + 1)
6300 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
6301 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 2)
6302 0 : IRNGT (IWRKD + 2) = IRNG1
6303 : End If
6304 : If (.true.) Exit ! Exit ! JM
6305 : End If
6306 : !
6307 : ! 1 2 3 4
6308 : !
6309 4 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Cycle
6310 : !
6311 : ! 1 3 x x
6312 : !
6313 6 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
6314 0 : IRNG2 = IRNGT (IWRKD + 2)
6315 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
6316 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
6317 : ! 1 3 2 4
6318 0 : IRNGT (IWRKD + 3) = IRNG2
6319 : Else
6320 : ! 1 3 4 2
6321 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
6322 0 : IRNGT (IWRKD + 4) = IRNG2
6323 : End If
6324 : !
6325 : ! 3 x x x
6326 : !
6327 : Else
6328 4 : IRNG1 = IRNGT (IWRKD + 1)
6329 4 : IRNG2 = IRNGT (IWRKD + 2)
6330 4 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
6331 4 : If (XDONT(IRNG1) <= XDONT(IRNGT(IWRKD + 4))) Then
6332 0 : IRNGT (IWRKD + 2) = IRNG1
6333 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
6334 : ! 3 1 2 4
6335 0 : IRNGT (IWRKD + 3) = IRNG2
6336 : Else
6337 : ! 3 1 4 2
6338 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
6339 0 : IRNGT (IWRKD + 4) = IRNG2
6340 : End If
6341 : Else
6342 : ! 3 4 1 2
6343 4 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 4)
6344 4 : IRNGT (IWRKD + 3) = IRNG1
6345 4 : IRNGT (IWRKD + 4) = IRNG2
6346 : End If
6347 : End If
6348 : End Do
6349 : !
6350 : ! The Cs become As and Bs
6351 : !
6352 : LMTNA = 4
6353 0 : If (.true.) Exit ! Exit ! JM
6354 : End Do
6355 : !
6356 : ! Iteration loop. Each time, the length of the ordered subsets
6357 : ! is doubled.
6358 : !
6359 4 : Do
6360 6 : If (LMTNA >= NVAL) Exit
6361 4 : IWRKF = 0
6362 4 : LMTNC = 2 * LMTNC
6363 : !
6364 : ! Loop on merges of A and B into C
6365 : !
6366 : Do
6367 8 : IWRK = IWRKF
6368 8 : IWRKD = IWRKF + 1
6369 8 : JINDA = IWRKF + LMTNA
6370 8 : IWRKF = IWRKF + LMTNC
6371 8 : If (IWRKF >= NVAL) Then
6372 6 : If (JINDA >= NVAL) Exit
6373 : IWRKF = NVAL
6374 : End If
6375 4 : IINDA = 1
6376 4 : IINDB = JINDA + 1
6377 : !
6378 : ! Shortcut for the case when the max of A is smaller
6379 : ! than the min of B. This line may be activated when the
6380 : ! initial set is already close to sorted.
6381 : !
6382 : ! IF (XDONT(IRNGT(JINDA)) <= XDONT(IRNGT(IINDB))) CYCLE
6383 : !
6384 : ! One steps in the C subset, that we build in the final rank array
6385 : !
6386 : ! Make a copy of the rank array for the merge iteration
6387 : !
6388 28 : JWRKT (1 : LMTNA) = IRNGT (IWRKD : JINDA)
6389 : !
6390 4 : XVALA = XDONT (JWRKT(IINDA))
6391 4 : XVALB = XDONT (IRNGT(IINDB))
6392 : !
6393 4 : Do
6394 12 : IWRK = IWRK + 1
6395 : !
6396 : ! We still have unprocessed values in both A and B
6397 : !
6398 12 : If (XVALA > XVALB) Then
6399 12 : IRNGT (IWRK) = IRNGT (IINDB)
6400 12 : IINDB = IINDB + 1
6401 12 : If (IINDB > IWRKF) Then
6402 : ! Only A still with unprocessed values
6403 28 : IRNGT (IWRK + 1 : IWRKF) = JWRKT (IINDA : LMTNA)
6404 : Exit
6405 : End If
6406 8 : XVALB = XDONT (IRNGT(IINDB))
6407 : Else
6408 0 : IRNGT (IWRK) = JWRKT (IINDA)
6409 0 : IINDA = IINDA + 1
6410 0 : If (IINDA > LMTNA) Exit! Only B still with unprocessed values
6411 0 : XVALA = XDONT (JWRKT(IINDA))
6412 : End If
6413 : !
6414 : End Do
6415 : End Do
6416 : !
6417 : ! The Cs become As and Bs
6418 : !
6419 4 : LMTNA = 2 * LMTNA
6420 : End Do
6421 : !
6422 : Return
6423 : !
6424 4505 : End Subroutine R_mrgrnk
6425 :
6426 0 : Subroutine I_mrgrnk (XDONT, IRNGT)
6427 : ! __________________________________________________________
6428 : ! MRGRNK = Merge-sort ranking of an array
6429 : ! For performance reasons, the first 2 passes are taken
6430 : ! out of the standard loop, and use dedicated coding.
6431 : ! __________________________________________________________
6432 : ! __________________________________________________________
6433 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
6434 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
6435 : ! __________________________________________________________
6436 : Integer(kind = i4) :: XVALA, XVALB
6437 : !
6438 0 : Integer(kind = i4), Dimension (SIZE(IRNGT)) :: JWRKT
6439 : Integer(kind = i4) :: LMTNA, LMTNC, IRNG1, IRNG2
6440 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
6441 : !
6442 0 : NVAL = Min (SIZE(XDONT), SIZE(IRNGT))
6443 : Select Case (NVAL)
6444 : Case (: 0)
6445 0 : Return
6446 : Case (1)
6447 0 : IRNGT (1) = 1
6448 0 : Return
6449 : Case Default
6450 :
6451 : End Select
6452 : !
6453 : ! Fill-in the index array, creating ordered couples
6454 : !
6455 0 : Do IIND = 2, NVAL, 2
6456 0 : If (XDONT(IIND - 1) <= XDONT(IIND)) Then
6457 0 : IRNGT (IIND - 1) = IIND - 1
6458 0 : IRNGT (IIND) = IIND
6459 : Else
6460 0 : IRNGT (IIND - 1) = IIND
6461 0 : IRNGT (IIND) = IIND - 1
6462 : End If
6463 : End Do
6464 0 : If (Modulo(NVAL, 2) /= 0) Then
6465 0 : IRNGT (NVAL) = NVAL
6466 : End If
6467 : !
6468 : ! We will now have ordered subsets A - B - A - B - ...
6469 : ! and merge A and B couples into C - C - ...
6470 : !
6471 0 : LMTNA = 2
6472 0 : LMTNC = 4
6473 : !
6474 : ! First iteration. The length of the ordered subsets goes from 2 to 4
6475 : !
6476 : Do
6477 0 : If (NVAL <= 2) Exit
6478 : !
6479 : ! Loop on merges of A and B into C
6480 : !
6481 0 : Do IWRKD = 0, NVAL - 1, 4
6482 0 : If ((IWRKD + 4) > NVAL) Then
6483 0 : If ((IWRKD + 2) >= NVAL) Exit
6484 : !
6485 : ! 1 2 3
6486 : !
6487 0 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Exit
6488 : !
6489 : ! 1 3 2
6490 : !
6491 0 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
6492 0 : IRNG2 = IRNGT (IWRKD + 2)
6493 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
6494 0 : IRNGT (IWRKD + 3) = IRNG2
6495 : !
6496 : ! 3 1 2
6497 : !
6498 : Else
6499 0 : IRNG1 = IRNGT (IWRKD + 1)
6500 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
6501 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 2)
6502 0 : IRNGT (IWRKD + 2) = IRNG1
6503 : End If
6504 : If (.true.) Exit ! Exit ! JM
6505 : End If
6506 : !
6507 : ! 1 2 3 4
6508 : !
6509 0 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Cycle
6510 : !
6511 : ! 1 3 x x
6512 : !
6513 0 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
6514 0 : IRNG2 = IRNGT (IWRKD + 2)
6515 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
6516 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
6517 : ! 1 3 2 4
6518 0 : IRNGT (IWRKD + 3) = IRNG2
6519 : Else
6520 : ! 1 3 4 2
6521 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
6522 0 : IRNGT (IWRKD + 4) = IRNG2
6523 : End If
6524 : !
6525 : ! 3 x x x
6526 : !
6527 : Else
6528 0 : IRNG1 = IRNGT (IWRKD + 1)
6529 0 : IRNG2 = IRNGT (IWRKD + 2)
6530 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
6531 0 : If (XDONT(IRNG1) <= XDONT(IRNGT(IWRKD + 4))) Then
6532 0 : IRNGT (IWRKD + 2) = IRNG1
6533 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
6534 : ! 3 1 2 4
6535 0 : IRNGT (IWRKD + 3) = IRNG2
6536 : Else
6537 : ! 3 1 4 2
6538 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
6539 0 : IRNGT (IWRKD + 4) = IRNG2
6540 : End If
6541 : Else
6542 : ! 3 4 1 2
6543 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 4)
6544 0 : IRNGT (IWRKD + 3) = IRNG1
6545 0 : IRNGT (IWRKD + 4) = IRNG2
6546 : End If
6547 : End If
6548 : End Do
6549 : !
6550 : ! The Cs become As and Bs
6551 : !
6552 : LMTNA = 4
6553 0 : If (.true.) Exit ! Exit ! JM
6554 : End Do
6555 : !
6556 : ! Iteration loop. Each time, the length of the ordered subsets
6557 : ! is doubled.
6558 : !
6559 0 : Do
6560 0 : If (LMTNA >= NVAL) Exit
6561 0 : IWRKF = 0
6562 0 : LMTNC = 2 * LMTNC
6563 : !
6564 : ! Loop on merges of A and B into C
6565 : !
6566 : Do
6567 0 : IWRK = IWRKF
6568 0 : IWRKD = IWRKF + 1
6569 0 : JINDA = IWRKF + LMTNA
6570 0 : IWRKF = IWRKF + LMTNC
6571 0 : If (IWRKF >= NVAL) Then
6572 0 : If (JINDA >= NVAL) Exit
6573 : IWRKF = NVAL
6574 : End If
6575 0 : IINDA = 1
6576 0 : IINDB = JINDA + 1
6577 : !
6578 : ! Shortcut for the case when the max of A is smaller
6579 : ! than the min of B. This line may be activated when the
6580 : ! initial set is already close to sorted.
6581 : !
6582 : ! IF (XDONT(IRNGT(JINDA)) <= XDONT(IRNGT(IINDB))) CYCLE
6583 : !
6584 : ! One steps in the C subset, that we build in the final rank array
6585 : !
6586 : ! Make a copy of the rank array for the merge iteration
6587 : !
6588 0 : JWRKT (1 : LMTNA) = IRNGT (IWRKD : JINDA)
6589 : !
6590 0 : XVALA = XDONT (JWRKT(IINDA))
6591 0 : XVALB = XDONT (IRNGT(IINDB))
6592 : !
6593 0 : Do
6594 0 : IWRK = IWRK + 1
6595 : !
6596 : ! We still have unprocessed values in both A and B
6597 : !
6598 0 : If (XVALA > XVALB) Then
6599 0 : IRNGT (IWRK) = IRNGT (IINDB)
6600 0 : IINDB = IINDB + 1
6601 0 : If (IINDB > IWRKF) Then
6602 : ! Only A still with unprocessed values
6603 0 : IRNGT (IWRK + 1 : IWRKF) = JWRKT (IINDA : LMTNA)
6604 : Exit
6605 : End If
6606 0 : XVALB = XDONT (IRNGT(IINDB))
6607 : Else
6608 0 : IRNGT (IWRK) = JWRKT (IINDA)
6609 0 : IINDA = IINDA + 1
6610 0 : If (IINDA > LMTNA) Exit! Only B still with unprocessed values
6611 0 : XVALA = XDONT (JWRKT(IINDA))
6612 : End If
6613 : !
6614 : End Do
6615 : End Do
6616 : !
6617 : ! The Cs become As and Bs
6618 : !
6619 0 : LMTNA = 2 * LMTNA
6620 : End Do
6621 : !
6622 : Return
6623 : !
6624 2 : End Subroutine I_mrgrnk
6625 :
6626 0 : Subroutine C_mrgrnk (XDONT, IRNGT)
6627 : ! __________________________________________________________
6628 : ! MRGRNK = Merge-sort ranking of an array
6629 : ! For performance reasons, the first 2 passes are taken
6630 : ! out of the standard loop, and use dedicated coding.
6631 : ! __________________________________________________________
6632 : ! __________________________________________________________
6633 : character(*), Dimension (:), Intent (In) :: XDONT
6634 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
6635 : ! __________________________________________________________
6636 0 : character(len(XDONT)) :: XVALA, XVALB
6637 : !
6638 0 : Integer(kind = i4), Dimension (SIZE(IRNGT)) :: JWRKT
6639 : Integer(kind = i4) :: LMTNA, LMTNC, IRNG1, IRNG2
6640 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
6641 : !
6642 0 : NVAL = Min (SIZE(XDONT), SIZE(IRNGT))
6643 : Select Case (NVAL)
6644 : Case (: 0)
6645 0 : Return
6646 : Case (1)
6647 0 : IRNGT (1) = 1
6648 0 : Return
6649 : Case Default
6650 :
6651 : End Select
6652 : !
6653 : ! Fill-in the index array, creating ordered couples
6654 : !
6655 0 : Do IIND = 2, NVAL, 2
6656 0 : If (XDONT(IIND - 1) <= XDONT(IIND)) Then
6657 0 : IRNGT (IIND - 1) = IIND - 1
6658 0 : IRNGT (IIND) = IIND
6659 : Else
6660 0 : IRNGT (IIND - 1) = IIND
6661 0 : IRNGT (IIND) = IIND - 1
6662 : End If
6663 : End Do
6664 0 : If (Modulo(NVAL, 2) /= 0) Then
6665 0 : IRNGT (NVAL) = NVAL
6666 : End If
6667 : !
6668 : ! We will now have ordered subsets A - B - A - B - ...
6669 : ! and merge A and B couples into C - C - ...
6670 : !
6671 0 : LMTNA = 2
6672 0 : LMTNC = 4
6673 : !
6674 : ! First iteration. The length of the ordered subsets goes from 2 to 4
6675 : !
6676 : Do
6677 0 : If (NVAL <= 2) Exit
6678 : !
6679 : ! Loop on merges of A and B into C
6680 : !
6681 0 : Do IWRKD = 0, NVAL - 1, 4
6682 0 : If ((IWRKD + 4) > NVAL) Then
6683 0 : If ((IWRKD + 2) >= NVAL) Exit
6684 : !
6685 : ! 1 2 3
6686 : !
6687 0 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Exit
6688 : !
6689 : ! 1 3 2
6690 : !
6691 0 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
6692 0 : IRNG2 = IRNGT (IWRKD + 2)
6693 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
6694 0 : IRNGT (IWRKD + 3) = IRNG2
6695 : !
6696 : ! 3 1 2
6697 : !
6698 : Else
6699 0 : IRNG1 = IRNGT (IWRKD + 1)
6700 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
6701 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 2)
6702 0 : IRNGT (IWRKD + 2) = IRNG1
6703 : End If
6704 : If (.true.) Exit ! Exit ! JM
6705 : End If
6706 : !
6707 : ! 1 2 3 4
6708 : !
6709 0 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Cycle
6710 : !
6711 : ! 1 3 x x
6712 : !
6713 0 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
6714 0 : IRNG2 = IRNGT (IWRKD + 2)
6715 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
6716 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
6717 : ! 1 3 2 4
6718 0 : IRNGT (IWRKD + 3) = IRNG2
6719 : Else
6720 : ! 1 3 4 2
6721 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
6722 0 : IRNGT (IWRKD + 4) = IRNG2
6723 : End If
6724 : !
6725 : ! 3 x x x
6726 : !
6727 : Else
6728 0 : IRNG1 = IRNGT (IWRKD + 1)
6729 0 : IRNG2 = IRNGT (IWRKD + 2)
6730 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
6731 0 : If (XDONT(IRNG1) <= XDONT(IRNGT(IWRKD + 4))) Then
6732 0 : IRNGT (IWRKD + 2) = IRNG1
6733 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
6734 : ! 3 1 2 4
6735 0 : IRNGT (IWRKD + 3) = IRNG2
6736 : Else
6737 : ! 3 1 4 2
6738 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
6739 0 : IRNGT (IWRKD + 4) = IRNG2
6740 : End If
6741 : Else
6742 : ! 3 4 1 2
6743 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 4)
6744 0 : IRNGT (IWRKD + 3) = IRNG1
6745 0 : IRNGT (IWRKD + 4) = IRNG2
6746 : End If
6747 : End If
6748 : End Do
6749 : !
6750 : ! The Cs become As and Bs
6751 : !
6752 : LMTNA = 4
6753 0 : If (.true.) Exit ! Exit ! JM
6754 : End Do
6755 : !
6756 : ! Iteration loop. Each time, the length of the ordered subsets
6757 : ! is doubled.
6758 : !
6759 0 : Do
6760 0 : If (LMTNA >= NVAL) Exit
6761 0 : IWRKF = 0
6762 0 : LMTNC = 2 * LMTNC
6763 : !
6764 : ! Loop on merges of A and B into C
6765 : !
6766 : Do
6767 0 : IWRK = IWRKF
6768 0 : IWRKD = IWRKF + 1
6769 0 : JINDA = IWRKF + LMTNA
6770 0 : IWRKF = IWRKF + LMTNC
6771 0 : If (IWRKF >= NVAL) Then
6772 0 : If (JINDA >= NVAL) Exit
6773 : IWRKF = NVAL
6774 : End If
6775 0 : IINDA = 1
6776 0 : IINDB = JINDA + 1
6777 : !
6778 : ! Shortcut for the case when the max of A is smaller
6779 : ! than the min of B. This line may be activated when the
6780 : ! initial set is already close to sorted.
6781 : !
6782 : ! IF (XDONT(IRNGT(JINDA)) <= XDONT(IRNGT(IINDB))) CYCLE
6783 : !
6784 : ! One steps in the C subset, that we build in the final rank array
6785 : !
6786 : ! Make a copy of the rank array for the merge iteration
6787 : !
6788 0 : JWRKT (1 : LMTNA) = IRNGT (IWRKD : JINDA)
6789 : !
6790 0 : XVALA = XDONT (JWRKT(IINDA))
6791 0 : XVALB = XDONT (IRNGT(IINDB))
6792 : !
6793 0 : Do
6794 0 : IWRK = IWRK + 1
6795 : !
6796 : ! We still have unprocessed values in both A and B
6797 : !
6798 0 : If (XVALA > XVALB) Then
6799 0 : IRNGT (IWRK) = IRNGT (IINDB)
6800 0 : IINDB = IINDB + 1
6801 0 : If (IINDB > IWRKF) Then
6802 : ! Only A still with unprocessed values
6803 0 : IRNGT (IWRK + 1 : IWRKF) = JWRKT (IINDA : LMTNA)
6804 : Exit
6805 : End If
6806 0 : XVALB = XDONT (IRNGT(IINDB))
6807 : Else
6808 0 : IRNGT (IWRK) = JWRKT (IINDA)
6809 0 : IINDA = IINDA + 1
6810 0 : If (IINDA > LMTNA) Exit! Only B still with unprocessed values
6811 0 : XVALA = XDONT (JWRKT(IINDA))
6812 : End If
6813 : !
6814 : End Do
6815 : End Do
6816 : !
6817 : ! The Cs become As and Bs
6818 : !
6819 0 : LMTNA = 2 * LMTNA
6820 : End Do
6821 : !
6822 : Return
6823 : !
6824 0 : End Subroutine C_mrgrnk
6825 :
6826 0 : Subroutine D_mulcnt (XDONT, IMULT)
6827 : ! MULCNT = Give for each array value its multiplicity
6828 : ! (number of times that it appears in the array)
6829 : ! __________________________________________________________
6830 : ! Michel Olagnon - Mar. 2000
6831 : ! __________________________________________________________
6832 : ! __________________________________________________________
6833 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
6834 : Integer(kind = i4), Dimension (:), Intent (Out) :: IMULT
6835 : ! __________________________________________________________
6836 : !
6837 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: IWRKT
6838 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: ICNTT
6839 : Integer(kind = i4) :: ICRS
6840 : ! __________________________________________________________
6841 0 : Call UNIINV (XDONT, IWRKT)
6842 0 : ICNTT = 0
6843 0 : Do ICRS = 1, Size(XDONT)
6844 0 : ICNTT(IWRKT(ICRS)) = ICNTT(IWRKT(ICRS)) + 1
6845 : End Do
6846 0 : Do ICRS = 1, Size(XDONT)
6847 0 : IMULT(ICRS) = ICNTT(IWRKT(ICRS))
6848 : End Do
6849 :
6850 : !
6851 0 : End Subroutine D_mulcnt
6852 :
6853 0 : Subroutine R_mulcnt (XDONT, IMULT)
6854 : ! MULCNT = Give for each array value its multiplicity
6855 : ! (number of times that it appears in the array)
6856 : ! __________________________________________________________
6857 : ! Michel Olagnon - Mar. 2000
6858 : ! __________________________________________________________
6859 : ! _________________________________________________________
6860 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
6861 : Integer(kind = i4), Dimension (:), Intent (Out) :: IMULT
6862 : ! __________________________________________________________
6863 : !
6864 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: IWRKT
6865 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: ICNTT
6866 : Integer(kind = i4) :: ICRS
6867 : ! __________________________________________________________
6868 0 : Call UNIINV (XDONT, IWRKT)
6869 0 : ICNTT = 0
6870 0 : Do ICRS = 1, Size(XDONT)
6871 0 : ICNTT(IWRKT(ICRS)) = ICNTT(IWRKT(ICRS)) + 1
6872 : End Do
6873 0 : Do ICRS = 1, Size(XDONT)
6874 0 : IMULT(ICRS) = ICNTT(IWRKT(ICRS))
6875 : End Do
6876 :
6877 : !
6878 0 : End Subroutine R_mulcnt
6879 :
6880 0 : Subroutine I_mulcnt (XDONT, IMULT)
6881 : ! MULCNT = Give for each array value its multiplicity
6882 : ! (number of times that it appears in the array)
6883 : ! __________________________________________________________
6884 : ! Michel Olagnon - Mar. 2000
6885 : ! __________________________________________________________
6886 : ! __________________________________________________________
6887 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
6888 : Integer(kind = i4), Dimension (:), Intent (Out) :: IMULT
6889 : ! __________________________________________________________
6890 : !
6891 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: IWRKT
6892 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: ICNTT
6893 : Integer(kind = i4) :: ICRS
6894 : ! __________________________________________________________
6895 0 : Call UNIINV (XDONT, IWRKT)
6896 0 : ICNTT = 0
6897 0 : Do ICRS = 1, Size(XDONT)
6898 0 : ICNTT(IWRKT(ICRS)) = ICNTT(IWRKT(ICRS)) + 1
6899 : End Do
6900 0 : Do ICRS = 1, Size(XDONT)
6901 0 : IMULT(ICRS) = ICNTT(IWRKT(ICRS))
6902 : End Do
6903 :
6904 : !
6905 0 : End Subroutine I_mulcnt
6906 :
6907 0 : Subroutine D_rapknr (XDONT, IRNGT, NORD)
6908 : ! Ranks partially XDONT by IRNGT, up to order NORD, in decreasing order.
6909 : ! rapknr = (rnkpar backwards)
6910 : ! __________________________________________________________
6911 : ! This routine uses a pivoting strategy such as the one of
6912 : ! finding the median based on the quicksort algorithm, but
6913 : ! we skew the pivot choice to try to bring it to NORD as
6914 : ! fast as possible. It uses 2 temporary arrays, where it
6915 : ! stores the indices of the values larger than the pivot
6916 : ! (IHIGT), and the indices of values smaller than the pivot
6917 : ! that we might still need later on (ILOWT). It iterates
6918 : ! until it can bring the number of values in IHIGT to
6919 : ! exactly NORD, and then uses an insertion sort to rank
6920 : ! this set, since it is supposedly small.
6921 : ! Michel Olagnon - Feb. 2011
6922 : ! __________________________________________________________
6923 : ! __________________________________________________________
6924 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
6925 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
6926 : Integer(kind = i4), Intent (In) :: NORD
6927 : ! __________________________________________________________
6928 0 : real(kind = dp) :: XPIV, XPIV0, XWRK, XWRK1, XMIN, XMAX
6929 : !
6930 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
6931 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
6932 : Integer(kind = i4) :: IDEB, JDEB, IMIL, IFIN, NWRK, ICRS, IDCR, ILOW
6933 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1
6934 : !
6935 0 : NDON = SIZE (XDONT)
6936 : !
6937 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
6938 : !
6939 0 : If (NDON < 2) Then
6940 0 : If (NORD >= 1) IRNGT (1) = 1
6941 0 : Return
6942 : End If
6943 : !
6944 : ! One chooses a pivot, best estimate possible to put fractile near
6945 : ! mid-point of the set of high values.
6946 : !
6947 0 : If (XDONT(2) < XDONT(1)) Then
6948 0 : ILOWT (1) = 2
6949 0 : IHIGT (1) = 1
6950 : Else
6951 0 : ILOWT (1) = 1
6952 0 : IHIGT (1) = 2
6953 : End If
6954 : !
6955 0 : If (NDON < 3) Then
6956 0 : If (NORD >= 1) IRNGT (1) = IHIGT (1)
6957 0 : If (NORD >= 2) IRNGT (2) = ILOWT (1)
6958 0 : Return
6959 : End If
6960 : ! ---
6961 0 : If (XDONT(3) > XDONT(ILOWT(1))) Then
6962 0 : ILOWT (2) = ILOWT (1)
6963 0 : If (XDONT(3) > XDONT(IHIGT(1))) Then
6964 0 : ILOWT (1) = IHIGT (1)
6965 0 : IHIGT (1) = 3
6966 : Else
6967 0 : ILOWT (1) = 3
6968 : End If
6969 : Else
6970 0 : ILOWT (2) = 3
6971 : End If
6972 : ! ---
6973 0 : If (NDON < 4) Then
6974 0 : If (NORD >= 1) IRNGT (1) = IHIGT (1)
6975 0 : If (NORD >= 2) IRNGT (2) = ILOWT (1)
6976 0 : If (NORD >= 3) IRNGT (3) = ILOWT (2)
6977 0 : Return
6978 : End If
6979 : !
6980 0 : If (XDONT(NDON) > XDONT(ILOWT(1))) Then
6981 0 : ILOWT (3) = ILOWT (2)
6982 0 : ILOWT (2) = ILOWT (1)
6983 0 : If (XDONT(NDON) > XDONT(IHIGT(1))) Then
6984 0 : ILOWT (1) = IHIGT (1)
6985 0 : IHIGT (1) = NDON
6986 : Else
6987 0 : ILOWT (1) = NDON
6988 : End If
6989 : Else
6990 0 : if (XDONT (NDON) > XDONT (ILOWT(2))) Then
6991 0 : ILOWT (3) = ILOWT (2)
6992 0 : ILOWT (2) = NDON
6993 : else
6994 0 : ILOWT (3) = NDON
6995 : end if
6996 : End If
6997 : !
6998 0 : If (NDON < 5) Then
6999 0 : If (NORD >= 1) IRNGT (1) = IHIGT (1)
7000 0 : If (NORD >= 2) IRNGT (2) = ILOWT (1)
7001 0 : If (NORD >= 3) IRNGT (3) = ILOWT (2)
7002 0 : If (NORD >= 4) IRNGT (4) = ILOWT (3)
7003 0 : Return
7004 : End If
7005 : ! ---
7006 0 : JDEB = 0
7007 0 : IDEB = JDEB + 1
7008 0 : JHIG = IDEB
7009 0 : JLOW = 3
7010 0 : XPIV = XDONT (IHIGT(IDEB)) + REAL(2 * NORD, dp) / REAL(NDON + NORD, dp) * &
7011 0 : (XDONT(ILOWT(3)) - XDONT(IHIGT(IDEB)))
7012 0 : If (XPIV >= XDONT(ILOWT(1))) Then
7013 : XPIV = XDONT (IHIGT(IDEB)) + REAL(2 * NORD, dp) / REAL(NDON + NORD, dp) * &
7014 0 : (XDONT(ILOWT(2)) - XDONT(IHIGT(IDEB)))
7015 0 : If (XPIV >= XDONT(ILOWT(1))) &
7016 : XPIV = XDONT (IHIGT(IDEB)) + REAL(2 * NORD, dp) / REAL(NDON + NORD, dp) * &
7017 0 : (XDONT(ILOWT(1)) - XDONT(IHIGT(IDEB)))
7018 : End If
7019 0 : XPIV0 = XPIV
7020 : ! ---
7021 : ! One puts values < pivot in the end and those >= pivot
7022 : ! at the beginning. This is split in 2 cases, so that
7023 : ! we can skip the loop test a number of times.
7024 : ! As we are also filling in the work arrays at the same time
7025 : ! we stop filling in the ILOWT array as soon as we have more
7026 : ! than enough values in IHIGT.
7027 : !
7028 : !
7029 0 : If (XDONT(NDON) < XPIV) Then
7030 : ICRS = 3
7031 : Do
7032 0 : ICRS = ICRS + 1
7033 0 : If (XDONT(ICRS) < XPIV) Then
7034 0 : If (ICRS >= NDON) Exit
7035 0 : JLOW = JLOW + 1
7036 0 : ILOWT (JLOW) = ICRS
7037 : Else
7038 0 : JHIG = JHIG + 1
7039 0 : IHIGT (JHIG) = ICRS
7040 0 : If (JHIG >= NORD) Exit
7041 : End If
7042 : End Do
7043 : !
7044 : ! One restricts further processing because it is no use
7045 : ! to store more low values
7046 : !
7047 0 : If (ICRS < NDON - 1) Then
7048 : Do
7049 0 : ICRS = ICRS + 1
7050 0 : If (XDONT(ICRS) >= XPIV) Then
7051 0 : JHIG = JHIG + 1
7052 0 : IHIGT (JHIG) = ICRS
7053 0 : Else If (ICRS >= NDON) Then
7054 : Exit
7055 : End If
7056 : End Do
7057 : End If
7058 : !
7059 : ! ---
7060 : Else
7061 : !
7062 : ! Same as above, but this is not as easy to optimize, so the
7063 : ! DO-loop is kept
7064 : !
7065 0 : Do ICRS = 4, NDON - 1
7066 0 : If (XDONT(ICRS) < XPIV) Then
7067 0 : JLOW = JLOW + 1
7068 0 : ILOWT (JLOW) = ICRS
7069 : Else
7070 0 : JHIG = JHIG + 1
7071 0 : IHIGT (JHIG) = ICRS
7072 0 : If (JHIG >= NORD) Exit
7073 : End If
7074 : End Do
7075 : !
7076 0 : If (ICRS < NDON - 1) Then
7077 : Do
7078 0 : ICRS = ICRS + 1
7079 0 : If (XDONT(ICRS) >= XPIV) Then
7080 0 : If (ICRS >= NDON) Exit
7081 0 : JHIG = JHIG + 1
7082 0 : IHIGT (JHIG) = ICRS
7083 : End If
7084 : End Do
7085 : End If
7086 : End If
7087 : ! ---
7088 : JLM2 = 0
7089 : JLM1 = 0
7090 : JHM2 = 0
7091 : JHM1 = 0
7092 : Do
7093 0 : if (JHIG == NORD) Exit
7094 0 : If (JHM2 == JHIG .And. JLM2 == JLOW) Then
7095 : !
7096 : ! We are oscillating. Perturbate by bringing JHIG closer by one
7097 : ! to NORD
7098 : !
7099 0 : If (NORD > JHIG) Then
7100 0 : XMAX = XDONT (ILOWT(1))
7101 0 : ILOW = 1
7102 0 : Do ICRS = 2, JLOW
7103 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
7104 0 : XMAX = XDONT (ILOWT(ICRS))
7105 0 : ILOW = ICRS
7106 : End If
7107 : End Do
7108 : !
7109 0 : JHIG = JHIG + 1
7110 0 : IHIGT (JHIG) = ILOWT (ILOW)
7111 0 : ILOWT (ILOW) = ILOWT (JLOW)
7112 0 : JLOW = JLOW - 1
7113 : Else
7114 0 : IHIG = IHIGT (JHIG)
7115 0 : XMIN = XDONT (IHIG)
7116 0 : Do ICRS = 1, JHIG
7117 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
7118 0 : IWRK = IHIGT (ICRS)
7119 0 : XMIN = XDONT (IWRK)
7120 0 : IHIGT (ICRS) = IHIG
7121 0 : IHIG = IWRK
7122 : End If
7123 : End Do
7124 0 : JHIG = JHIG - 1
7125 : End If
7126 : End If
7127 0 : JLM2 = JLM1
7128 0 : JLM1 = JLOW
7129 0 : JHM2 = JHM1
7130 0 : JHM1 = JHIG
7131 : ! ---
7132 : ! We try to bring the number of values in the high values set
7133 : ! closer to NORD.
7134 : !
7135 0 : Select Case (NORD - JHIG)
7136 : Case (2 :)
7137 : !
7138 : ! Not enough values in low part, at least 2 are missing
7139 : !
7140 : Select Case (JLOW)
7141 : !!!!! CASE DEFAULT
7142 : !!!!! write (*,*) "Assertion failed"
7143 : !!!!! STOP
7144 : !
7145 : ! We make a special case when we have so few values in
7146 : ! the low values set that it is bad performance to choose a pivot
7147 : ! and apply the general algorithm.
7148 : !
7149 : Case (2)
7150 0 : If (XDONT(ILOWT(1)) >= XDONT(ILOWT(2))) Then
7151 0 : JHIG = JHIG + 1
7152 0 : IHIGT (JHIG) = ILOWT (1)
7153 0 : JHIG = JHIG + 1
7154 0 : IHIGT (JHIG) = ILOWT (2)
7155 : Else
7156 0 : JHIG = JHIG + 1
7157 0 : IHIGT (JHIG) = ILOWT (2)
7158 0 : JHIG = JHIG + 1
7159 0 : IHIGT (JHIG) = ILOWT (1)
7160 : End If
7161 : Exit
7162 : ! ---
7163 : Case (3)
7164 : !
7165 : !
7166 0 : IWRK1 = ILOWT (1)
7167 0 : IWRK2 = ILOWT (2)
7168 0 : IWRK3 = ILOWT (3)
7169 0 : If (XDONT(IWRK2) > XDONT(IWRK1)) Then
7170 0 : ILOWT (1) = IWRK2
7171 0 : ILOWT (2) = IWRK1
7172 0 : IWRK2 = IWRK1
7173 : End If
7174 0 : If (XDONT(IWRK2) < XDONT(IWRK3)) Then
7175 0 : ILOWT (3) = IWRK2
7176 0 : ILOWT (2) = IWRK3
7177 0 : IWRK2 = IWRK3
7178 0 : If (XDONT(IWRK2) > XDONT(ILOWT(1))) Then
7179 0 : ILOWT (2) = ILOWT (1)
7180 0 : ILOWT (1) = IWRK2
7181 : End If
7182 : End If
7183 0 : JLOW = 0
7184 0 : Do ICRS = JHIG + 1, NORD
7185 0 : JLOW = JLOW + 1
7186 0 : IHIGT (ICRS) = ILOWT (JLOW)
7187 : End Do
7188 0 : JHIG = NORD
7189 : Exit
7190 : ! ---
7191 : Case (4 :)
7192 : !
7193 : !
7194 0 : XPIV0 = XPIV
7195 0 : IFIN = JLOW
7196 : !
7197 : ! One chooses a pivot from the 2 first values and the last one.
7198 : ! This should ensure sufficient renewal between iterations to
7199 : ! avoid worst case behavior effects.
7200 : !
7201 0 : IWRK1 = ILOWT (1)
7202 0 : IWRK2 = ILOWT (2)
7203 0 : IWRK3 = ILOWT (IFIN)
7204 0 : If (XDONT(IWRK2) > XDONT(IWRK1)) Then
7205 0 : ILOWT (1) = IWRK2
7206 0 : ILOWT (2) = IWRK1
7207 0 : IWRK2 = IWRK1
7208 : End If
7209 0 : If (XDONT(IWRK2) < XDONT(IWRK3)) Then
7210 0 : ILOWT (IFIN) = IWRK2
7211 0 : ILOWT (2) = IWRK3
7212 0 : IWRK2 = IWRK3
7213 0 : If (XDONT(IWRK2) > XDONT(IHIGT(1))) Then
7214 0 : ILOWT (2) = ILOWT (1)
7215 0 : ILOWT (1) = IWRK2
7216 : End If
7217 : End If
7218 : !
7219 0 : JDEB = JHIG
7220 0 : NWRK = NORD - JHIG
7221 0 : IWRK1 = ILOWT (1)
7222 0 : JHIG = JHIG + 1
7223 0 : IHIGT (JHIG) = IWRK1
7224 0 : XPIV = XDONT (IWRK1) + REAL(NWRK, dp) / REAL(NORD + NWRK, dp) * &
7225 0 : (XDONT(ILOWT(IFIN)) - XDONT(IWRK1))
7226 : !
7227 : ! One takes values >= pivot to IHIGT
7228 : ! Again, 2 parts, one where we take care of the remaining
7229 : ! low values because we might still need them, and the
7230 : ! other when we know that we will have more than enough
7231 : ! high values in the end.
7232 : ! ---
7233 0 : JLOW = 0
7234 0 : Do ICRS = 2, IFIN
7235 0 : If (XDONT(ILOWT(ICRS)) >= XPIV) Then
7236 0 : JHIG = JHIG + 1
7237 0 : IHIGT (JHIG) = ILOWT (ICRS)
7238 0 : If (JHIG >= NORD) Exit
7239 : Else
7240 0 : JLOW = JLOW + 1
7241 0 : ILOWT (JLOW) = ILOWT (ICRS)
7242 : End If
7243 : End Do
7244 : !
7245 0 : Do ICRS = ICRS + 1, IFIN
7246 0 : If (XDONT(ILOWT(ICRS)) >= XPIV) Then
7247 0 : JHIG = JHIG + 1
7248 0 : IHIGT (JHIG) = ILOWT (ICRS)
7249 : End If
7250 : End Do
7251 : End Select
7252 : ! ---
7253 : !
7254 : Case (1)
7255 : !
7256 : ! Only 1 value is missing in high part
7257 : !
7258 0 : XMAX = XDONT (ILOWT(1))
7259 0 : ILOW = 1
7260 0 : Do ICRS = 2, JLOW
7261 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
7262 0 : XMAX = XDONT (ILOWT(ICRS))
7263 0 : ILOW = ICRS
7264 : End If
7265 : End Do
7266 : !
7267 0 : JHIG = JHIG + 1
7268 0 : IHIGT (JHIG) = ILOWT (ILOW)
7269 0 : Exit
7270 : !
7271 : !
7272 : Case (0)
7273 : !
7274 : ! Low part is exactly what we want
7275 : !
7276 0 : Exit
7277 : ! ---
7278 : !
7279 : Case (-5 : -1)
7280 : !
7281 : ! Only few values too many in high part
7282 : !
7283 0 : IRNGT (1) = IHIGT (1)
7284 0 : Do ICRS = 2, NORD
7285 0 : IWRK = IHIGT (ICRS)
7286 0 : XWRK = XDONT (IWRK)
7287 0 : Do IDCR = ICRS - 1, 1, - 1
7288 0 : If (XWRK > XDONT(IRNGT(IDCR))) Then
7289 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
7290 : Else
7291 : Exit
7292 : End If
7293 : End Do
7294 0 : IRNGT (IDCR + 1) = IWRK
7295 : End Do
7296 : !
7297 0 : XWRK1 = XDONT (IRNGT(NORD))
7298 0 : Do ICRS = NORD + 1, JHIG
7299 0 : If (XDONT(IHIGT (ICRS)) > XWRK1) Then
7300 0 : XWRK = XDONT (IHIGT (ICRS))
7301 0 : Do IDCR = NORD - 1, 1, - 1
7302 0 : If (XWRK <= XDONT(IRNGT(IDCR))) Exit
7303 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
7304 : End Do
7305 0 : IRNGT (IDCR + 1) = IHIGT (ICRS)
7306 0 : XWRK1 = XDONT (IRNGT(NORD))
7307 : End If
7308 : End Do
7309 : !
7310 0 : Return
7311 : !
7312 : !
7313 : Case (: -6)
7314 : !
7315 : ! last case: too many values in high part
7316 : ! ---
7317 0 : IDEB = JDEB + 1
7318 0 : IMIL = (JHIG + IDEB) / 2
7319 0 : IFIN = JHIG
7320 : ! ---
7321 : ! One chooses a pivot from 1st, last, and middle values
7322 : !
7323 0 : If (XDONT(IHIGT(IMIL)) > XDONT(IHIGT(IDEB))) Then
7324 0 : IWRK = IHIGT (IDEB)
7325 0 : IHIGT (IDEB) = IHIGT (IMIL)
7326 0 : IHIGT (IMIL) = IWRK
7327 : End If
7328 0 : If (XDONT(IHIGT(IMIL)) < XDONT(IHIGT(IFIN))) Then
7329 0 : IWRK = IHIGT (IFIN)
7330 0 : IHIGT (IFIN) = IHIGT (IMIL)
7331 0 : IHIGT (IMIL) = IWRK
7332 0 : If (XDONT(IHIGT(IMIL)) > XDONT(IHIGT(IDEB))) Then
7333 0 : IWRK = IHIGT (IDEB)
7334 0 : IHIGT (IDEB) = IHIGT (IMIL)
7335 0 : IHIGT (IMIL) = IWRK
7336 : End If
7337 : End If
7338 0 : If (IFIN <= 3) Exit
7339 : ! ---
7340 0 : XPIV = XDONT (IHIGT(1)) + REAL(NORD, sp) / REAL(JHIG + NORD, sp) * &
7341 0 : (XDONT(IHIGT(IFIN)) - XDONT(IHIGT(1)))
7342 0 : If (JDEB > 0) Then
7343 0 : If (XPIV <= XPIV0) &
7344 : XPIV = XPIV0 + REAL(2 * NORD - JDEB, dp) / REAL(JHIG + NORD, dp) * &
7345 0 : (XDONT(IHIGT(IFIN)) - XPIV0)
7346 : Else
7347 : IDEB = 1
7348 : End If
7349 : !
7350 : ! One takes values < XPIV to ILOWT
7351 : ! However, we do not process the first values if we have been
7352 : ! through the case when we did not have enough high values
7353 : ! ---
7354 0 : JLOW = 0
7355 0 : JHIG = JDEB
7356 : ! ---
7357 0 : If (XDONT(IHIGT(IFIN)) < XPIV) Then
7358 : ICRS = JDEB
7359 : Do
7360 0 : ICRS = ICRS + 1
7361 0 : If (XDONT(IHIGT(ICRS)) < XPIV) Then
7362 0 : JLOW = JLOW + 1
7363 0 : ILOWT (JLOW) = IHIGT (ICRS)
7364 0 : If (ICRS >= IFIN) Exit
7365 : Else
7366 0 : JHIG = JHIG + 1
7367 0 : IHIGT (JHIG) = IHIGT (ICRS)
7368 0 : If (JHIG >= NORD) Exit
7369 : End If
7370 : End Do
7371 : ! ---
7372 0 : If (ICRS < IFIN) Then
7373 : Do
7374 0 : ICRS = ICRS + 1
7375 0 : If (XDONT(IHIGT(ICRS)) >= XPIV) Then
7376 0 : JHIG = JHIG + 1
7377 0 : IHIGT (JHIG) = IHIGT (ICRS)
7378 : Else
7379 0 : If (ICRS >= IFIN) Exit
7380 : End If
7381 : End Do
7382 : End If
7383 : Else
7384 0 : Do ICRS = IDEB, IFIN
7385 0 : If (XDONT(IHIGT(ICRS)) < XPIV) Then
7386 0 : JLOW = JLOW + 1
7387 0 : ILOWT (JLOW) = IHIGT (ICRS)
7388 : Else
7389 0 : JHIG = JHIG + 1
7390 0 : IHIGT (JHIG) = IHIGT (ICRS)
7391 0 : If (JHIG >= NORD) Exit
7392 : End If
7393 : End Do
7394 : !
7395 0 : Do ICRS = ICRS + 1, IFIN
7396 0 : If (XDONT(IHIGT(ICRS)) >= XPIV) Then
7397 0 : JHIG = JHIG + 1
7398 0 : IHIGT (JHIG) = IHIGT (ICRS)
7399 : End If
7400 : End Do
7401 : End If
7402 : !
7403 : End Select
7404 : !
7405 : End Do
7406 : ! ---
7407 : ! Now, we only need to complete ranking of the 1:NORD set
7408 : ! Assuming NORD is small, we use a simple insertion sort
7409 : !
7410 0 : IRNGT (1) = IHIGT (1)
7411 0 : Do ICRS = 2, NORD
7412 0 : IWRK = IHIGT (ICRS)
7413 0 : XWRK = XDONT (IWRK)
7414 0 : Do IDCR = ICRS - 1, 1, - 1
7415 0 : If (XWRK > XDONT(IRNGT(IDCR))) Then
7416 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
7417 : Else
7418 : Exit
7419 : End If
7420 : End Do
7421 0 : IRNGT (IDCR + 1) = IWRK
7422 : End Do
7423 : Return
7424 : !
7425 : !
7426 0 : End Subroutine D_rapknr
7427 :
7428 0 : Subroutine R_rapknr (XDONT, IRNGT, NORD)
7429 : ! Ranks partially XDONT by IRNGT, up to order NORD, in decreasing order.
7430 : ! rapknr = (rnkpar backwards)
7431 : ! __________________________________________________________
7432 : ! This routine uses a pivoting strategy such as the one of
7433 : ! finding the median based on the quicksort algorithm, but
7434 : ! we skew the pivot choice to try to bring it to NORD as
7435 : ! fast as possible. It uses 2 temporary arrays, where it
7436 : ! stores the indices of the values larger than the pivot
7437 : ! (IHIGT), and the indices of values smaller than the pivot
7438 : ! that we might still need later on (ILOWT). It iterates
7439 : ! until it can bring the number of values in IHIGT to
7440 : ! exactly NORD, and then uses an insertion sort to rank
7441 : ! this set, since it is supposedly small.
7442 : ! Michel Olagnon - Feb. 2011
7443 : ! __________________________________________________________
7444 : ! __________________________________________________________
7445 : ! _________________________________________________________
7446 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
7447 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
7448 : Integer(kind = i4), Intent (In) :: NORD
7449 : ! __________________________________________________________
7450 0 : Real(kind = sp) :: XPIV, XPIV0, XWRK, XWRK1, XMIN, XMAX
7451 : !
7452 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
7453 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
7454 : Integer(kind = i4) :: IDEB, JDEB, IMIL, IFIN, NWRK, ICRS, IDCR, ILOW
7455 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1
7456 : !
7457 0 : NDON = SIZE (XDONT)
7458 : !
7459 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
7460 : !
7461 0 : If (NDON < 2) Then
7462 0 : If (NORD >= 1) IRNGT (1) = 1
7463 0 : Return
7464 : End If
7465 : !
7466 : ! One chooses a pivot, best estimate possible to put fractile near
7467 : ! mid-point of the set of high values.
7468 : !
7469 0 : If (XDONT(2) < XDONT(1)) Then
7470 0 : ILOWT (1) = 2
7471 0 : IHIGT (1) = 1
7472 : Else
7473 0 : ILOWT (1) = 1
7474 0 : IHIGT (1) = 2
7475 : End If
7476 : !
7477 0 : If (NDON < 3) Then
7478 0 : If (NORD >= 1) IRNGT (1) = IHIGT (1)
7479 0 : If (NORD >= 2) IRNGT (2) = ILOWT (1)
7480 0 : Return
7481 : End If
7482 : ! ---
7483 0 : If (XDONT(3) > XDONT(ILOWT(1))) Then
7484 0 : ILOWT (2) = ILOWT (1)
7485 0 : If (XDONT(3) > XDONT(IHIGT(1))) Then
7486 0 : ILOWT (1) = IHIGT (1)
7487 0 : IHIGT (1) = 3
7488 : Else
7489 0 : ILOWT (1) = 3
7490 : End If
7491 : Else
7492 0 : ILOWT (2) = 3
7493 : End If
7494 : ! ---
7495 0 : If (NDON < 4) Then
7496 0 : If (NORD >= 1) IRNGT (1) = IHIGT (1)
7497 0 : If (NORD >= 2) IRNGT (2) = ILOWT (1)
7498 0 : If (NORD >= 3) IRNGT (3) = ILOWT (2)
7499 0 : Return
7500 : End If
7501 : !
7502 0 : If (XDONT(NDON) > XDONT(ILOWT(1))) Then
7503 0 : ILOWT (3) = ILOWT (2)
7504 0 : ILOWT (2) = ILOWT (1)
7505 0 : If (XDONT(NDON) > XDONT(IHIGT(1))) Then
7506 0 : ILOWT (1) = IHIGT (1)
7507 0 : IHIGT (1) = NDON
7508 : Else
7509 0 : ILOWT (1) = NDON
7510 : End If
7511 : Else
7512 0 : if (XDONT (NDON) > XDONT (ILOWT(2))) Then
7513 0 : ILOWT (3) = ILOWT (2)
7514 0 : ILOWT (2) = NDON
7515 : else
7516 0 : ILOWT (3) = NDON
7517 : end if
7518 : End If
7519 : !
7520 0 : If (NDON < 5) Then
7521 0 : If (NORD >= 1) IRNGT (1) = IHIGT (1)
7522 0 : If (NORD >= 2) IRNGT (2) = ILOWT (1)
7523 0 : If (NORD >= 3) IRNGT (3) = ILOWT (2)
7524 0 : If (NORD >= 4) IRNGT (4) = ILOWT (3)
7525 0 : Return
7526 : End If
7527 : ! ---
7528 0 : JDEB = 0
7529 0 : IDEB = JDEB + 1
7530 0 : JHIG = IDEB
7531 0 : JLOW = 3
7532 0 : XPIV = XDONT (IHIGT(IDEB)) + REAL(2 * NORD, sp) / REAL(NDON + NORD, sp) * &
7533 0 : (XDONT(ILOWT(3)) - XDONT(IHIGT(IDEB)))
7534 0 : If (XPIV >= XDONT(ILOWT(1))) Then
7535 : XPIV = XDONT (IHIGT(IDEB)) + REAL(2 * NORD, sp) / REAL(NDON + NORD, sp) * &
7536 0 : (XDONT(ILOWT(2)) - XDONT(IHIGT(IDEB)))
7537 0 : If (XPIV >= XDONT(ILOWT(1))) &
7538 : XPIV = XDONT (IHIGT(IDEB)) + REAL(2 * NORD, sp) / REAL(NDON + NORD, sp) * &
7539 0 : (XDONT(ILOWT(1)) - XDONT(IHIGT(IDEB)))
7540 : End If
7541 0 : XPIV0 = XPIV
7542 : ! ---
7543 : ! One puts values < pivot in the end and those >= pivot
7544 : ! at the beginning. This is split in 2 cases, so that
7545 : ! we can skip the loop test a number of times.
7546 : ! As we are also filling in the work arrays at the same time
7547 : ! we stop filling in the ILOWT array as soon as we have more
7548 : ! than enough values in IHIGT.
7549 : !
7550 : !
7551 0 : If (XDONT(NDON) < XPIV) Then
7552 : ICRS = 3
7553 : Do
7554 0 : ICRS = ICRS + 1
7555 0 : If (XDONT(ICRS) < XPIV) Then
7556 0 : If (ICRS >= NDON) Exit
7557 0 : JLOW = JLOW + 1
7558 0 : ILOWT (JLOW) = ICRS
7559 : Else
7560 0 : JHIG = JHIG + 1
7561 0 : IHIGT (JHIG) = ICRS
7562 0 : If (JHIG >= NORD) Exit
7563 : End If
7564 : End Do
7565 : !
7566 : ! One restricts further processing because it is no use
7567 : ! to store more low values
7568 : !
7569 0 : If (ICRS < NDON - 1) Then
7570 : Do
7571 0 : ICRS = ICRS + 1
7572 0 : If (XDONT(ICRS) >= XPIV) Then
7573 0 : JHIG = JHIG + 1
7574 0 : IHIGT (JHIG) = ICRS
7575 0 : Else If (ICRS >= NDON) Then
7576 : Exit
7577 : End If
7578 : End Do
7579 : End If
7580 : !
7581 : ! ---
7582 : Else
7583 : !
7584 : ! Same as above, but this is not as easy to optimize, so the
7585 : ! DO-loop is kept
7586 : !
7587 0 : Do ICRS = 4, NDON - 1
7588 0 : If (XDONT(ICRS) < XPIV) Then
7589 0 : JLOW = JLOW + 1
7590 0 : ILOWT (JLOW) = ICRS
7591 : Else
7592 0 : JHIG = JHIG + 1
7593 0 : IHIGT (JHIG) = ICRS
7594 0 : If (JHIG >= NORD) Exit
7595 : End If
7596 : End Do
7597 : !
7598 0 : If (ICRS < NDON - 1) Then
7599 : Do
7600 0 : ICRS = ICRS + 1
7601 0 : If (XDONT(ICRS) >= XPIV) Then
7602 0 : If (ICRS >= NDON) Exit
7603 0 : JHIG = JHIG + 1
7604 0 : IHIGT (JHIG) = ICRS
7605 : End If
7606 : End Do
7607 : End If
7608 : End If
7609 : ! ---
7610 : JLM2 = 0
7611 : JLM1 = 0
7612 : JHM2 = 0
7613 : JHM1 = 0
7614 : Do
7615 0 : if (JHIG == NORD) Exit
7616 0 : If (JHM2 == JHIG .And. JLM2 == JLOW) Then
7617 : !
7618 : ! We are oscillating. Perturbate by bringing JHIG closer by one
7619 : ! to NORD
7620 : !
7621 0 : If (NORD > JHIG) Then
7622 0 : XMAX = XDONT (ILOWT(1))
7623 0 : ILOW = 1
7624 0 : Do ICRS = 2, JLOW
7625 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
7626 0 : XMAX = XDONT (ILOWT(ICRS))
7627 0 : ILOW = ICRS
7628 : End If
7629 : End Do
7630 : !
7631 0 : JHIG = JHIG + 1
7632 0 : IHIGT (JHIG) = ILOWT (ILOW)
7633 0 : ILOWT (ILOW) = ILOWT (JLOW)
7634 0 : JLOW = JLOW - 1
7635 : Else
7636 0 : IHIG = IHIGT (JHIG)
7637 0 : XMIN = XDONT (IHIG)
7638 0 : Do ICRS = 1, JHIG
7639 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
7640 0 : IWRK = IHIGT (ICRS)
7641 0 : XMIN = XDONT (IWRK)
7642 0 : IHIGT (ICRS) = IHIG
7643 0 : IHIG = IWRK
7644 : End If
7645 : End Do
7646 0 : JHIG = JHIG - 1
7647 : End If
7648 : End If
7649 0 : JLM2 = JLM1
7650 0 : JLM1 = JLOW
7651 0 : JHM2 = JHM1
7652 0 : JHM1 = JHIG
7653 : ! ---
7654 : ! We try to bring the number of values in the high values set
7655 : ! closer to NORD.
7656 : !
7657 0 : Select Case (NORD - JHIG)
7658 : Case (2 :)
7659 : !
7660 : ! Not enough values in low part, at least 2 are missing
7661 : !
7662 : Select Case (JLOW)
7663 : !!!!! CASE DEFAULT
7664 : !!!!! write (*,*) "Assertion failed"
7665 : !!!!! STOP
7666 : !
7667 : ! We make a special case when we have so few values in
7668 : ! the low values set that it is bad performance to choose a pivot
7669 : ! and apply the general algorithm.
7670 : !
7671 : Case (2)
7672 0 : If (XDONT(ILOWT(1)) >= XDONT(ILOWT(2))) Then
7673 0 : JHIG = JHIG + 1
7674 0 : IHIGT (JHIG) = ILOWT (1)
7675 0 : JHIG = JHIG + 1
7676 0 : IHIGT (JHIG) = ILOWT (2)
7677 : Else
7678 0 : JHIG = JHIG + 1
7679 0 : IHIGT (JHIG) = ILOWT (2)
7680 0 : JHIG = JHIG + 1
7681 0 : IHIGT (JHIG) = ILOWT (1)
7682 : End If
7683 : Exit
7684 : ! ---
7685 : Case (3)
7686 : !
7687 : !
7688 0 : IWRK1 = ILOWT (1)
7689 0 : IWRK2 = ILOWT (2)
7690 0 : IWRK3 = ILOWT (3)
7691 0 : If (XDONT(IWRK2) > XDONT(IWRK1)) Then
7692 0 : ILOWT (1) = IWRK2
7693 0 : ILOWT (2) = IWRK1
7694 0 : IWRK2 = IWRK1
7695 : End If
7696 0 : If (XDONT(IWRK2) < XDONT(IWRK3)) Then
7697 0 : ILOWT (3) = IWRK2
7698 0 : ILOWT (2) = IWRK3
7699 0 : IWRK2 = IWRK3
7700 0 : If (XDONT(IWRK2) > XDONT(ILOWT(1))) Then
7701 0 : ILOWT (2) = ILOWT (1)
7702 0 : ILOWT (1) = IWRK2
7703 : End If
7704 : End If
7705 0 : JLOW = 0
7706 0 : Do ICRS = JHIG + 1, NORD
7707 0 : JLOW = JLOW + 1
7708 0 : IHIGT (ICRS) = ILOWT (JLOW)
7709 : End Do
7710 0 : JHIG = NORD
7711 : Exit
7712 : ! ---
7713 : Case (4 :)
7714 : !
7715 : !
7716 0 : XPIV0 = XPIV
7717 0 : IFIN = JLOW
7718 : !
7719 : ! One chooses a pivot from the 2 first values and the last one.
7720 : ! This should ensure sufficient renewal between iterations to
7721 : ! avoid worst case behavior effects.
7722 : !
7723 0 : IWRK1 = ILOWT (1)
7724 0 : IWRK2 = ILOWT (2)
7725 0 : IWRK3 = ILOWT (IFIN)
7726 0 : If (XDONT(IWRK2) > XDONT(IWRK1)) Then
7727 0 : ILOWT (1) = IWRK2
7728 0 : ILOWT (2) = IWRK1
7729 0 : IWRK2 = IWRK1
7730 : End If
7731 0 : If (XDONT(IWRK2) < XDONT(IWRK3)) Then
7732 0 : ILOWT (IFIN) = IWRK2
7733 0 : ILOWT (2) = IWRK3
7734 0 : IWRK2 = IWRK3
7735 0 : If (XDONT(IWRK2) > XDONT(IHIGT(1))) Then
7736 0 : ILOWT (2) = ILOWT (1)
7737 0 : ILOWT (1) = IWRK2
7738 : End If
7739 : End If
7740 : !
7741 0 : JDEB = JHIG
7742 0 : NWRK = NORD - JHIG
7743 0 : IWRK1 = ILOWT (1)
7744 0 : JHIG = JHIG + 1
7745 0 : IHIGT (JHIG) = IWRK1
7746 0 : XPIV = XDONT (IWRK1) + REAL(NWRK, sp) / REAL(NORD + NWRK, sp) * &
7747 0 : (XDONT(ILOWT(IFIN)) - XDONT(IWRK1))
7748 : !
7749 : ! One takes values >= pivot to IHIGT
7750 : ! Again, 2 parts, one where we take care of the remaining
7751 : ! low values because we might still need them, and the
7752 : ! other when we know that we will have more than enough
7753 : ! high values in the end.
7754 : ! ---
7755 0 : JLOW = 0
7756 0 : Do ICRS = 2, IFIN
7757 0 : If (XDONT(ILOWT(ICRS)) >= XPIV) Then
7758 0 : JHIG = JHIG + 1
7759 0 : IHIGT (JHIG) = ILOWT (ICRS)
7760 0 : If (JHIG >= NORD) Exit
7761 : Else
7762 0 : JLOW = JLOW + 1
7763 0 : ILOWT (JLOW) = ILOWT (ICRS)
7764 : End If
7765 : End Do
7766 : !
7767 0 : Do ICRS = ICRS + 1, IFIN
7768 0 : If (XDONT(ILOWT(ICRS)) >= XPIV) Then
7769 0 : JHIG = JHIG + 1
7770 0 : IHIGT (JHIG) = ILOWT (ICRS)
7771 : End If
7772 : End Do
7773 : End Select
7774 : ! ---
7775 : !
7776 : Case (1)
7777 : !
7778 : ! Only 1 value is missing in high part
7779 : !
7780 0 : XMAX = XDONT (ILOWT(1))
7781 0 : ILOW = 1
7782 0 : Do ICRS = 2, JLOW
7783 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
7784 0 : XMAX = XDONT (ILOWT(ICRS))
7785 0 : ILOW = ICRS
7786 : End If
7787 : End Do
7788 : !
7789 0 : JHIG = JHIG + 1
7790 0 : IHIGT (JHIG) = ILOWT (ILOW)
7791 0 : Exit
7792 : !
7793 : !
7794 : Case (0)
7795 : !
7796 : ! Low part is exactly what we want
7797 : !
7798 0 : Exit
7799 : ! ---
7800 : !
7801 : Case (-5 : -1)
7802 : !
7803 : ! Only few values too many in high part
7804 : !
7805 0 : IRNGT (1) = IHIGT (1)
7806 0 : Do ICRS = 2, NORD
7807 0 : IWRK = IHIGT (ICRS)
7808 0 : XWRK = XDONT (IWRK)
7809 0 : Do IDCR = ICRS - 1, 1, - 1
7810 0 : If (XWRK > XDONT(IRNGT(IDCR))) Then
7811 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
7812 : Else
7813 : Exit
7814 : End If
7815 : End Do
7816 0 : IRNGT (IDCR + 1) = IWRK
7817 : End Do
7818 : !
7819 0 : XWRK1 = XDONT (IRNGT(NORD))
7820 0 : Do ICRS = NORD + 1, JHIG
7821 0 : If (XDONT(IHIGT (ICRS)) > XWRK1) Then
7822 0 : XWRK = XDONT (IHIGT (ICRS))
7823 0 : Do IDCR = NORD - 1, 1, - 1
7824 0 : If (XWRK <= XDONT(IRNGT(IDCR))) Exit
7825 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
7826 : End Do
7827 0 : IRNGT (IDCR + 1) = IHIGT (ICRS)
7828 0 : XWRK1 = XDONT (IRNGT(NORD))
7829 : End If
7830 : End Do
7831 : !
7832 0 : Return
7833 : !
7834 : !
7835 : Case (: -6)
7836 : !
7837 : ! last case: too many values in high part
7838 : ! ---
7839 0 : IDEB = JDEB + 1
7840 0 : IMIL = (JHIG + IDEB) / 2
7841 0 : IFIN = JHIG
7842 : ! ---
7843 : ! One chooses a pivot from 1st, last, and middle values
7844 : !
7845 0 : If (XDONT(IHIGT(IMIL)) > XDONT(IHIGT(IDEB))) Then
7846 0 : IWRK = IHIGT (IDEB)
7847 0 : IHIGT (IDEB) = IHIGT (IMIL)
7848 0 : IHIGT (IMIL) = IWRK
7849 : End If
7850 0 : If (XDONT(IHIGT(IMIL)) < XDONT(IHIGT(IFIN))) Then
7851 0 : IWRK = IHIGT (IFIN)
7852 0 : IHIGT (IFIN) = IHIGT (IMIL)
7853 0 : IHIGT (IMIL) = IWRK
7854 0 : If (XDONT(IHIGT(IMIL)) > XDONT(IHIGT(IDEB))) Then
7855 0 : IWRK = IHIGT (IDEB)
7856 0 : IHIGT (IDEB) = IHIGT (IMIL)
7857 0 : IHIGT (IMIL) = IWRK
7858 : End If
7859 : End If
7860 0 : If (IFIN <= 3) Exit
7861 : ! ---
7862 0 : XPIV = XDONT (IHIGT(1)) + REAL(NORD, sp) / REAL(JHIG + NORD, sp) * &
7863 0 : (XDONT(IHIGT(IFIN)) - XDONT(IHIGT(1)))
7864 0 : If (JDEB > 0) Then
7865 0 : If (XPIV <= XPIV0) &
7866 : XPIV = XPIV0 + REAL(2 * NORD - JDEB, sp) / REAL(JHIG + NORD, sp) * &
7867 0 : (XDONT(IHIGT(IFIN)) - XPIV0)
7868 : Else
7869 : IDEB = 1
7870 : End If
7871 : !
7872 : ! One takes values < XPIV to ILOWT
7873 : ! However, we do not process the first values if we have been
7874 : ! through the case when we did not have enough high values
7875 : ! ---
7876 0 : JLOW = 0
7877 0 : JHIG = JDEB
7878 : ! ---
7879 0 : If (XDONT(IHIGT(IFIN)) < XPIV) Then
7880 : ICRS = JDEB
7881 : Do
7882 0 : ICRS = ICRS + 1
7883 0 : If (XDONT(IHIGT(ICRS)) < XPIV) Then
7884 0 : JLOW = JLOW + 1
7885 0 : ILOWT (JLOW) = IHIGT (ICRS)
7886 0 : If (ICRS >= IFIN) Exit
7887 : Else
7888 0 : JHIG = JHIG + 1
7889 0 : IHIGT (JHIG) = IHIGT (ICRS)
7890 0 : If (JHIG >= NORD) Exit
7891 : End If
7892 : End Do
7893 : ! ---
7894 0 : If (ICRS < IFIN) Then
7895 : Do
7896 0 : ICRS = ICRS + 1
7897 0 : If (XDONT(IHIGT(ICRS)) >= XPIV) Then
7898 0 : JHIG = JHIG + 1
7899 0 : IHIGT (JHIG) = IHIGT (ICRS)
7900 : Else
7901 0 : If (ICRS >= IFIN) Exit
7902 : End If
7903 : End Do
7904 : End If
7905 : Else
7906 0 : Do ICRS = IDEB, IFIN
7907 0 : If (XDONT(IHIGT(ICRS)) < XPIV) Then
7908 0 : JLOW = JLOW + 1
7909 0 : ILOWT (JLOW) = IHIGT (ICRS)
7910 : Else
7911 0 : JHIG = JHIG + 1
7912 0 : IHIGT (JHIG) = IHIGT (ICRS)
7913 0 : If (JHIG >= NORD) Exit
7914 : End If
7915 : End Do
7916 : !
7917 0 : Do ICRS = ICRS + 1, IFIN
7918 0 : If (XDONT(IHIGT(ICRS)) >= XPIV) Then
7919 0 : JHIG = JHIG + 1
7920 0 : IHIGT (JHIG) = IHIGT (ICRS)
7921 : End If
7922 : End Do
7923 : End If
7924 : !
7925 : End Select
7926 : !
7927 : End Do
7928 : ! ---
7929 : ! Now, we only need to complete ranking of the 1:NORD set
7930 : ! Assuming NORD is small, we use a simple insertion sort
7931 : !
7932 0 : IRNGT (1) = IHIGT (1)
7933 0 : Do ICRS = 2, NORD
7934 0 : IWRK = IHIGT (ICRS)
7935 0 : XWRK = XDONT (IWRK)
7936 0 : Do IDCR = ICRS - 1, 1, - 1
7937 0 : If (XWRK > XDONT(IRNGT(IDCR))) Then
7938 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
7939 : Else
7940 : Exit
7941 : End If
7942 : End Do
7943 0 : IRNGT (IDCR + 1) = IWRK
7944 : End Do
7945 : Return
7946 : !
7947 : !
7948 0 : End Subroutine R_rapknr
7949 :
7950 0 : Subroutine I_rapknr (XDONT, IRNGT, NORD)
7951 : ! Ranks partially XDONT by IRNGT, up to order NORD, in decreasing order.
7952 : ! rapknr = (rnkpar backwards)
7953 : ! __________________________________________________________
7954 : ! This routine uses a pivoting strategy such as the one of
7955 : ! finding the median based on the quicksort algorithm, but
7956 : ! we skew the pivot choice to try to bring it to NORD as
7957 : ! fast as possible. It uses 2 temporary arrays, where it
7958 : ! stores the indices of the values larger than the pivot
7959 : ! (IHIGT), and the indices of values smaller than the pivot
7960 : ! that we might still need later on (ILOWT). It iterates
7961 : ! until it can bring the number of values in IHIGT to
7962 : ! exactly NORD, and then uses an insertion sort to rank
7963 : ! this set, since it is supposedly small.
7964 : ! Michel Olagnon - Feb. 2011
7965 : ! __________________________________________________________
7966 : ! __________________________________________________________
7967 : ! __________________________________________________________
7968 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
7969 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
7970 : Integer(kind = i4), Intent (In) :: NORD
7971 : ! __________________________________________________________
7972 : Integer(kind = i4) :: XPIV, XPIV0, XWRK, XWRK1, XMIN, XMAX
7973 : !
7974 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
7975 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
7976 : Integer(kind = i4) :: IDEB, JDEB, IMIL, IFIN, NWRK, ICRS, IDCR, ILOW
7977 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1
7978 : !
7979 0 : NDON = SIZE (XDONT)
7980 : !
7981 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
7982 : !
7983 0 : If (NDON < 2) Then
7984 0 : If (NORD >= 1) IRNGT (1) = 1
7985 0 : Return
7986 : End If
7987 : !
7988 : ! One chooses a pivot, best estimate possible to put fractile near
7989 : ! mid-point of the set of high values.
7990 : !
7991 0 : If (XDONT(2) < XDONT(1)) Then
7992 0 : ILOWT (1) = 2
7993 0 : IHIGT (1) = 1
7994 : Else
7995 0 : ILOWT (1) = 1
7996 0 : IHIGT (1) = 2
7997 : End If
7998 : !
7999 0 : If (NDON < 3) Then
8000 0 : If (NORD >= 1) IRNGT (1) = IHIGT (1)
8001 0 : If (NORD >= 2) IRNGT (2) = ILOWT (1)
8002 0 : Return
8003 : End If
8004 : ! ---
8005 0 : If (XDONT(3) > XDONT(ILOWT(1))) Then
8006 0 : ILOWT (2) = ILOWT (1)
8007 0 : If (XDONT(3) > XDONT(IHIGT(1))) Then
8008 0 : ILOWT (1) = IHIGT (1)
8009 0 : IHIGT (1) = 3
8010 : Else
8011 0 : ILOWT (1) = 3
8012 : End If
8013 : Else
8014 0 : ILOWT (2) = 3
8015 : End If
8016 : ! ---
8017 0 : If (NDON < 4) Then
8018 0 : If (NORD >= 1) IRNGT (1) = IHIGT (1)
8019 0 : If (NORD >= 2) IRNGT (2) = ILOWT (1)
8020 0 : If (NORD >= 3) IRNGT (3) = ILOWT (2)
8021 0 : Return
8022 : End If
8023 : !
8024 0 : If (XDONT(NDON) > XDONT(ILOWT(1))) Then
8025 0 : ILOWT (3) = ILOWT (2)
8026 0 : ILOWT (2) = ILOWT (1)
8027 0 : If (XDONT(NDON) > XDONT(IHIGT(1))) Then
8028 0 : ILOWT (1) = IHIGT (1)
8029 0 : IHIGT (1) = NDON
8030 : Else
8031 0 : ILOWT (1) = NDON
8032 : End If
8033 : Else
8034 0 : if (XDONT (NDON) > XDONT (ILOWT(2))) Then
8035 0 : ILOWT (3) = ILOWT (2)
8036 0 : ILOWT (2) = NDON
8037 : else
8038 0 : ILOWT (3) = NDON
8039 : end if
8040 : End If
8041 : !
8042 0 : If (NDON < 5) Then
8043 0 : If (NORD >= 1) IRNGT (1) = IHIGT (1)
8044 0 : If (NORD >= 2) IRNGT (2) = ILOWT (1)
8045 0 : If (NORD >= 3) IRNGT (3) = ILOWT (2)
8046 0 : If (NORD >= 4) IRNGT (4) = ILOWT (3)
8047 0 : Return
8048 : End If
8049 : ! ---
8050 0 : JDEB = 0
8051 0 : IDEB = JDEB + 1
8052 0 : JHIG = IDEB
8053 0 : JLOW = 3
8054 0 : XPIV = XDONT (IHIGT(IDEB)) + INT(REAL(2 * NORD, sp) / REAL(NDON + NORD, sp), i4) * &
8055 0 : (XDONT(ILOWT(3)) - XDONT(IHIGT(IDEB)))
8056 0 : If (XPIV >= XDONT(ILOWT(1))) Then
8057 : XPIV = XDONT (IHIGT(IDEB)) + INT(REAL(2 * NORD, sp) / REAL(NDON + NORD, sp), i4) * &
8058 0 : (XDONT(ILOWT(2)) - XDONT(IHIGT(IDEB)))
8059 0 : If (XPIV >= XDONT(ILOWT(1))) &
8060 : XPIV = XDONT (IHIGT(IDEB)) + INT(REAL(2 * NORD, sp) / REAL(NDON + NORD, sp), i4) * &
8061 0 : (XDONT(ILOWT(1)) - XDONT(IHIGT(IDEB)))
8062 : End If
8063 0 : XPIV0 = XPIV
8064 : ! ---
8065 : ! One puts values < pivot in the end and those >= pivot
8066 : ! at the beginning. This is split in 2 cases, so that
8067 : ! we can skip the loop test a number of times.
8068 : ! As we are also filling in the work arrays at the same time
8069 : ! we stop filling in the ILOWT array as soon as we have more
8070 : ! than enough values in IHIGT.
8071 : !
8072 : !
8073 0 : If (XDONT(NDON) < XPIV) Then
8074 : ICRS = 3
8075 : Do
8076 0 : ICRS = ICRS + 1
8077 0 : If (XDONT(ICRS) < XPIV) Then
8078 0 : If (ICRS >= NDON) Exit
8079 0 : JLOW = JLOW + 1
8080 0 : ILOWT (JLOW) = ICRS
8081 : Else
8082 0 : JHIG = JHIG + 1
8083 0 : IHIGT (JHIG) = ICRS
8084 0 : If (JHIG >= NORD) Exit
8085 : End If
8086 : End Do
8087 : !
8088 : ! One restricts further processing because it is no use
8089 : ! to store more low values
8090 : !
8091 0 : If (ICRS < NDON - 1) Then
8092 : Do
8093 0 : ICRS = ICRS + 1
8094 0 : If (XDONT(ICRS) >= XPIV) Then
8095 0 : JHIG = JHIG + 1
8096 0 : IHIGT (JHIG) = ICRS
8097 0 : Else If (ICRS >= NDON) Then
8098 : Exit
8099 : End If
8100 : End Do
8101 : End If
8102 : !
8103 : ! ---
8104 : Else
8105 : !
8106 : ! Same as above, but this is not as easy to optimize, so the
8107 : ! DO-loop is kept
8108 : !
8109 0 : Do ICRS = 4, NDON - 1
8110 0 : If (XDONT(ICRS) < XPIV) Then
8111 0 : JLOW = JLOW + 1
8112 0 : ILOWT (JLOW) = ICRS
8113 : Else
8114 0 : JHIG = JHIG + 1
8115 0 : IHIGT (JHIG) = ICRS
8116 0 : If (JHIG >= NORD) Exit
8117 : End If
8118 : End Do
8119 : !
8120 0 : If (ICRS < NDON - 1) Then
8121 : Do
8122 0 : ICRS = ICRS + 1
8123 0 : If (XDONT(ICRS) >= XPIV) Then
8124 0 : If (ICRS >= NDON) Exit
8125 0 : JHIG = JHIG + 1
8126 0 : IHIGT (JHIG) = ICRS
8127 : End If
8128 : End Do
8129 : End If
8130 : End If
8131 : ! ---
8132 : JLM2 = 0
8133 : JLM1 = 0
8134 : JHM2 = 0
8135 : JHM1 = 0
8136 : Do
8137 0 : if (JHIG == NORD) Exit
8138 0 : If (JHM2 == JHIG .And. JLM2 == JLOW) Then
8139 : !
8140 : ! We are oscillating. Perturbate by bringing JHIG closer by one
8141 : ! to NORD
8142 : !
8143 0 : If (NORD > JHIG) Then
8144 0 : XMAX = XDONT (ILOWT(1))
8145 0 : ILOW = 1
8146 0 : Do ICRS = 2, JLOW
8147 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
8148 0 : XMAX = XDONT (ILOWT(ICRS))
8149 0 : ILOW = ICRS
8150 : End If
8151 : End Do
8152 : !
8153 0 : JHIG = JHIG + 1
8154 0 : IHIGT (JHIG) = ILOWT (ILOW)
8155 0 : ILOWT (ILOW) = ILOWT (JLOW)
8156 0 : JLOW = JLOW - 1
8157 : Else
8158 0 : IHIG = IHIGT (JHIG)
8159 0 : XMIN = XDONT (IHIG)
8160 0 : Do ICRS = 1, JHIG
8161 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
8162 0 : IWRK = IHIGT (ICRS)
8163 0 : XMIN = XDONT (IWRK)
8164 0 : IHIGT (ICRS) = IHIG
8165 0 : IHIG = IWRK
8166 : End If
8167 : End Do
8168 0 : JHIG = JHIG - 1
8169 : End If
8170 : End If
8171 0 : JLM2 = JLM1
8172 0 : JLM1 = JLOW
8173 0 : JHM2 = JHM1
8174 0 : JHM1 = JHIG
8175 : ! ---
8176 : ! We try to bring the number of values in the high values set
8177 : ! closer to NORD.
8178 : !
8179 0 : Select Case (NORD - JHIG)
8180 : Case (2 :)
8181 : !
8182 : ! Not enough values in low part, at least 2 are missing
8183 : !
8184 : Select Case (JLOW)
8185 : !!!!! CASE DEFAULT
8186 : !!!!! write (*,*) "Assertion failed"
8187 : !!!!! STOP
8188 : !
8189 : ! We make a special case when we have so few values in
8190 : ! the low values set that it is bad performance to choose a pivot
8191 : ! and apply the general algorithm.
8192 : !
8193 : Case (2)
8194 0 : If (XDONT(ILOWT(1)) >= XDONT(ILOWT(2))) Then
8195 0 : JHIG = JHIG + 1
8196 0 : IHIGT (JHIG) = ILOWT (1)
8197 0 : JHIG = JHIG + 1
8198 0 : IHIGT (JHIG) = ILOWT (2)
8199 : Else
8200 0 : JHIG = JHIG + 1
8201 0 : IHIGT (JHIG) = ILOWT (2)
8202 0 : JHIG = JHIG + 1
8203 0 : IHIGT (JHIG) = ILOWT (1)
8204 : End If
8205 : Exit
8206 : ! ---
8207 : Case (3)
8208 : !
8209 : !
8210 0 : IWRK1 = ILOWT (1)
8211 0 : IWRK2 = ILOWT (2)
8212 0 : IWRK3 = ILOWT (3)
8213 0 : If (XDONT(IWRK2) > XDONT(IWRK1)) Then
8214 0 : ILOWT (1) = IWRK2
8215 0 : ILOWT (2) = IWRK1
8216 0 : IWRK2 = IWRK1
8217 : End If
8218 0 : If (XDONT(IWRK2) < XDONT(IWRK3)) Then
8219 0 : ILOWT (3) = IWRK2
8220 0 : ILOWT (2) = IWRK3
8221 0 : IWRK2 = IWRK3
8222 0 : If (XDONT(IWRK2) > XDONT(ILOWT(1))) Then
8223 0 : ILOWT (2) = ILOWT (1)
8224 0 : ILOWT (1) = IWRK2
8225 : End If
8226 : End If
8227 0 : JLOW = 0
8228 0 : Do ICRS = JHIG + 1, NORD
8229 0 : JLOW = JLOW + 1
8230 0 : IHIGT (ICRS) = ILOWT (JLOW)
8231 : End Do
8232 0 : JHIG = NORD
8233 : Exit
8234 : ! ---
8235 : Case (4 :)
8236 : !
8237 : !
8238 0 : XPIV0 = XPIV
8239 0 : IFIN = JLOW
8240 : !
8241 : ! One chooses a pivot from the 2 first values and the last one.
8242 : ! This should ensure sufficient renewal between iterations to
8243 : ! avoid worst case behavior effects.
8244 : !
8245 0 : IWRK1 = ILOWT (1)
8246 0 : IWRK2 = ILOWT (2)
8247 0 : IWRK3 = ILOWT (IFIN)
8248 0 : If (XDONT(IWRK2) > XDONT(IWRK1)) Then
8249 0 : ILOWT (1) = IWRK2
8250 0 : ILOWT (2) = IWRK1
8251 0 : IWRK2 = IWRK1
8252 : End If
8253 0 : If (XDONT(IWRK2) < XDONT(IWRK3)) Then
8254 0 : ILOWT (IFIN) = IWRK2
8255 0 : ILOWT (2) = IWRK3
8256 0 : IWRK2 = IWRK3
8257 0 : If (XDONT(IWRK2) > XDONT(IHIGT(1))) Then
8258 0 : ILOWT (2) = ILOWT (1)
8259 0 : ILOWT (1) = IWRK2
8260 : End If
8261 : End If
8262 : !
8263 0 : JDEB = JHIG
8264 0 : NWRK = NORD - JHIG
8265 0 : IWRK1 = ILOWT (1)
8266 0 : JHIG = JHIG + 1
8267 0 : IHIGT (JHIG) = IWRK1
8268 0 : XPIV = XDONT (IWRK1) + INT(REAL(NWRK, sp) / REAL(NORD + NWRK, sp), i4) * &
8269 0 : (XDONT(ILOWT(IFIN)) - XDONT(IWRK1))
8270 : !
8271 : ! One takes values >= pivot to IHIGT
8272 : ! Again, 2 parts, one where we take care of the remaining
8273 : ! low values because we might still need them, and the
8274 : ! other when we know that we will have more than enough
8275 : ! high values in the end.
8276 : ! ---
8277 0 : JLOW = 0
8278 0 : Do ICRS = 2, IFIN
8279 0 : If (XDONT(ILOWT(ICRS)) >= XPIV) Then
8280 0 : JHIG = JHIG + 1
8281 0 : IHIGT (JHIG) = ILOWT (ICRS)
8282 0 : If (JHIG >= NORD) Exit
8283 : Else
8284 0 : JLOW = JLOW + 1
8285 0 : ILOWT (JLOW) = ILOWT (ICRS)
8286 : End If
8287 : End Do
8288 : !
8289 0 : Do ICRS = ICRS + 1, IFIN
8290 0 : If (XDONT(ILOWT(ICRS)) >= XPIV) Then
8291 0 : JHIG = JHIG + 1
8292 0 : IHIGT (JHIG) = ILOWT (ICRS)
8293 : End If
8294 : End Do
8295 : End Select
8296 : ! ---
8297 : !
8298 : Case (1)
8299 : !
8300 : ! Only 1 value is missing in high part
8301 : !
8302 0 : XMAX = XDONT (ILOWT(1))
8303 0 : ILOW = 1
8304 0 : Do ICRS = 2, JLOW
8305 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
8306 0 : XMAX = XDONT (ILOWT(ICRS))
8307 0 : ILOW = ICRS
8308 : End If
8309 : End Do
8310 : !
8311 0 : JHIG = JHIG + 1
8312 0 : IHIGT (JHIG) = ILOWT (ILOW)
8313 0 : Exit
8314 : !
8315 : !
8316 : Case (0)
8317 : !
8318 : ! Low part is exactly what we want
8319 : !
8320 0 : Exit
8321 : ! ---
8322 : !
8323 : Case (-5 : -1)
8324 : !
8325 : ! Only few values too many in high part
8326 : !
8327 0 : IRNGT (1) = IHIGT (1)
8328 0 : Do ICRS = 2, NORD
8329 0 : IWRK = IHIGT (ICRS)
8330 0 : XWRK = XDONT (IWRK)
8331 0 : Do IDCR = ICRS - 1, 1, - 1
8332 0 : If (XWRK > XDONT(IRNGT(IDCR))) Then
8333 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
8334 : Else
8335 : Exit
8336 : End If
8337 : End Do
8338 0 : IRNGT (IDCR + 1) = IWRK
8339 : End Do
8340 : !
8341 0 : XWRK1 = XDONT (IRNGT(NORD))
8342 0 : Do ICRS = NORD + 1, JHIG
8343 0 : If (XDONT(IHIGT (ICRS)) > XWRK1) Then
8344 0 : XWRK = XDONT (IHIGT (ICRS))
8345 0 : Do IDCR = NORD - 1, 1, - 1
8346 0 : If (XWRK <= XDONT(IRNGT(IDCR))) Exit
8347 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
8348 : End Do
8349 0 : IRNGT (IDCR + 1) = IHIGT (ICRS)
8350 0 : XWRK1 = XDONT (IRNGT(NORD))
8351 : End If
8352 : End Do
8353 : !
8354 0 : Return
8355 : !
8356 : !
8357 : Case (: -6)
8358 : !
8359 : ! last case: too many values in high part
8360 : ! ---
8361 0 : IDEB = JDEB + 1
8362 0 : IMIL = (JHIG + IDEB) / 2
8363 0 : IFIN = JHIG
8364 : ! ---
8365 : ! One chooses a pivot from 1st, last, and middle values
8366 : !
8367 0 : If (XDONT(IHIGT(IMIL)) > XDONT(IHIGT(IDEB))) Then
8368 0 : IWRK = IHIGT (IDEB)
8369 0 : IHIGT (IDEB) = IHIGT (IMIL)
8370 0 : IHIGT (IMIL) = IWRK
8371 : End If
8372 0 : If (XDONT(IHIGT(IMIL)) < XDONT(IHIGT(IFIN))) Then
8373 0 : IWRK = IHIGT (IFIN)
8374 0 : IHIGT (IFIN) = IHIGT (IMIL)
8375 0 : IHIGT (IMIL) = IWRK
8376 0 : If (XDONT(IHIGT(IMIL)) > XDONT(IHIGT(IDEB))) Then
8377 0 : IWRK = IHIGT (IDEB)
8378 0 : IHIGT (IDEB) = IHIGT (IMIL)
8379 0 : IHIGT (IMIL) = IWRK
8380 : End If
8381 : End If
8382 0 : If (IFIN <= 3) Exit
8383 : ! ---
8384 0 : XPIV = XDONT (IHIGT(1)) + INT(REAL(NORD, sp) / REAL(JHIG + NORD, sp), i4) * &
8385 0 : (XDONT(IHIGT(IFIN)) - XDONT(IHIGT(1)))
8386 0 : If (JDEB > 0) Then
8387 0 : If (XPIV <= XPIV0) &
8388 : XPIV = XPIV0 + INT(REAL(2 * NORD - JDEB, sp) / REAL(JHIG + NORD, sp), i4) * &
8389 0 : (XDONT(IHIGT(IFIN)) - XPIV0)
8390 : Else
8391 : IDEB = 1
8392 : End If
8393 : !
8394 : ! One takes values < XPIV to ILOWT
8395 : ! However, we do not process the first values if we have been
8396 : ! through the case when we did not have enough high values
8397 : ! ---
8398 0 : JLOW = 0
8399 0 : JHIG = JDEB
8400 : ! ---
8401 0 : If (XDONT(IHIGT(IFIN)) < XPIV) Then
8402 : ICRS = JDEB
8403 : Do
8404 0 : ICRS = ICRS + 1
8405 0 : If (XDONT(IHIGT(ICRS)) < XPIV) Then
8406 0 : JLOW = JLOW + 1
8407 0 : ILOWT (JLOW) = IHIGT (ICRS)
8408 0 : If (ICRS >= IFIN) Exit
8409 : Else
8410 0 : JHIG = JHIG + 1
8411 0 : IHIGT (JHIG) = IHIGT (ICRS)
8412 0 : If (JHIG >= NORD) Exit
8413 : End If
8414 : End Do
8415 : ! ---
8416 0 : If (ICRS < IFIN) Then
8417 : Do
8418 0 : ICRS = ICRS + 1
8419 0 : If (XDONT(IHIGT(ICRS)) >= XPIV) Then
8420 0 : JHIG = JHIG + 1
8421 0 : IHIGT (JHIG) = IHIGT (ICRS)
8422 : Else
8423 0 : If (ICRS >= IFIN) Exit
8424 : End If
8425 : End Do
8426 : End If
8427 : Else
8428 0 : Do ICRS = IDEB, IFIN
8429 0 : If (XDONT(IHIGT(ICRS)) < XPIV) Then
8430 0 : JLOW = JLOW + 1
8431 0 : ILOWT (JLOW) = IHIGT (ICRS)
8432 : Else
8433 0 : JHIG = JHIG + 1
8434 0 : IHIGT (JHIG) = IHIGT (ICRS)
8435 0 : If (JHIG >= NORD) Exit
8436 : End If
8437 : End Do
8438 : !
8439 0 : Do ICRS = ICRS + 1, IFIN
8440 0 : If (XDONT(IHIGT(ICRS)) >= XPIV) Then
8441 0 : JHIG = JHIG + 1
8442 0 : IHIGT (JHIG) = IHIGT (ICRS)
8443 : End If
8444 : End Do
8445 : End If
8446 : !
8447 : End Select
8448 : !
8449 : End Do
8450 : ! ---
8451 : ! Now, we only need to complete ranking of the 1:NORD set
8452 : ! Assuming NORD is small, we use a simple insertion sort
8453 : !
8454 0 : IRNGT (1) = IHIGT (1)
8455 0 : Do ICRS = 2, NORD
8456 0 : IWRK = IHIGT (ICRS)
8457 0 : XWRK = XDONT (IWRK)
8458 0 : Do IDCR = ICRS - 1, 1, - 1
8459 0 : If (XWRK > XDONT(IRNGT(IDCR))) Then
8460 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
8461 : Else
8462 : Exit
8463 : End If
8464 : End Do
8465 0 : IRNGT (IDCR + 1) = IWRK
8466 : End Do
8467 : Return
8468 : !
8469 : !
8470 0 : End Subroutine I_rapknr
8471 :
8472 0 : Subroutine D_refpar (XDONT, IRNGT, NORD)
8473 : ! Ranks partially XDONT by IRNGT, up to order NORD
8474 : ! __________________________________________________________
8475 : ! This routine uses a pivoting strategy such as the one of
8476 : ! finding the median based on the quicksort algorithm. It uses
8477 : ! a temporary array, where it stores the partially ranked indices
8478 : ! of the values. It iterates until it can bring the number of
8479 : ! values lower than the pivot to exactly NORD, and then uses an
8480 : ! insertion sort to rank this set, since it is supposedly small.
8481 : ! Michel Olagnon - Feb. 2000
8482 : ! __________________________________________________________
8483 : ! __________________________________________________________
8484 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
8485 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
8486 : Integer(kind = i4), Intent (In) :: NORD
8487 : ! __________________________________________________________
8488 0 : real(kind = dp) :: XPIV, XWRK
8489 : ! __________________________________________________________
8490 : !
8491 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: IWRKT
8492 : Integer(kind = i4) :: NDON, ICRS, IDEB, IDCR, IFIN, IMIL, IWRK
8493 : !
8494 0 : NDON = SIZE (XDONT)
8495 : !
8496 0 : Do ICRS = 1, NDON
8497 0 : IWRKT (ICRS) = ICRS
8498 : End Do
8499 : IDEB = 1
8500 : IFIN = NDON
8501 : Do
8502 0 : If (IDEB >= IFIN) Exit
8503 0 : IMIL = (IDEB + IFIN) / 2
8504 : !
8505 : ! One chooses a pivot, median of 1st, last, and middle values
8506 : !
8507 0 : If (XDONT(IWRKT(IMIL)) < XDONT(IWRKT(IDEB))) Then
8508 0 : IWRK = IWRKT (IDEB)
8509 0 : IWRKT (IDEB) = IWRKT (IMIL)
8510 0 : IWRKT (IMIL) = IWRK
8511 : End If
8512 0 : If (XDONT(IWRKT(IMIL)) > XDONT(IWRKT(IFIN))) Then
8513 0 : IWRK = IWRKT (IFIN)
8514 0 : IWRKT (IFIN) = IWRKT (IMIL)
8515 0 : IWRKT (IMIL) = IWRK
8516 0 : If (XDONT(IWRKT(IMIL)) < XDONT(IWRKT(IDEB))) Then
8517 0 : IWRK = IWRKT (IDEB)
8518 0 : IWRKT (IDEB) = IWRKT (IMIL)
8519 0 : IWRKT (IMIL) = IWRK
8520 : End If
8521 : End If
8522 0 : If ((IFIN - IDEB) < 3) Exit
8523 0 : XPIV = XDONT (IWRKT(IMIL))
8524 : !
8525 : ! One exchanges values to put those > pivot in the end and
8526 : ! those <= pivot at the beginning
8527 : !
8528 0 : ICRS = IDEB
8529 0 : IDCR = IFIN
8530 0 : ECH2 : Do
8531 : Do
8532 0 : ICRS = ICRS + 1
8533 0 : If (ICRS >= IDCR) Then
8534 : !
8535 : ! the first > pivot is IWRKT(IDCR)
8536 : ! the last <= pivot is IWRKT(ICRS-1)
8537 : ! Note: If one arrives here on the first iteration, then
8538 : ! the pivot is the maximum of the set, the last value is equal
8539 : ! to it, and one can reduce by one the size of the set to process,
8540 : ! as if XDONT (IWRKT(IFIN)) > XPIV
8541 : !
8542 : Exit ECH2
8543 : !
8544 : End If
8545 0 : If (XDONT(IWRKT(ICRS)) > XPIV) Exit
8546 : End Do
8547 : Do
8548 0 : If (XDONT(IWRKT(IDCR)) <= XPIV) Exit
8549 0 : IDCR = IDCR - 1
8550 0 : If (ICRS >= IDCR) Then
8551 : !
8552 : ! The last value < pivot is always IWRKT(ICRS-1)
8553 : !
8554 : Exit ECH2
8555 : End If
8556 : End Do
8557 : !
8558 0 : IWRK = IWRKT (IDCR)
8559 0 : IWRKT (IDCR) = IWRKT (ICRS)
8560 0 : IWRKT (ICRS) = IWRK
8561 : End Do ECH2
8562 : !
8563 : ! One restricts further processing to find the fractile value
8564 : !
8565 0 : If (ICRS <= NORD) IDEB = ICRS
8566 0 : If (ICRS > NORD) IFIN = ICRS - 1
8567 : End Do
8568 : !
8569 : ! Now, we only need to complete ranking of the 1:NORD set
8570 : ! Assuming NORD is small, we use a simple insertion sort
8571 : !
8572 0 : Do ICRS = 2, NORD
8573 0 : IWRK = IWRKT (ICRS)
8574 0 : XWRK = XDONT (IWRK)
8575 0 : Do IDCR = ICRS - 1, 1, - 1
8576 0 : If (XWRK <= XDONT(IWRKT(IDCR))) Then
8577 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
8578 : Else
8579 : Exit
8580 : End If
8581 : End Do
8582 0 : IWRKT (IDCR + 1) = IWRK
8583 : End Do
8584 0 : IRNGT (1 : NORD) = IWRKT (1 : NORD)
8585 0 : Return
8586 : !
8587 0 : End Subroutine D_refpar
8588 :
8589 0 : Subroutine R_refpar (XDONT, IRNGT, NORD)
8590 : ! Ranks partially XDONT by IRNGT, up to order NORD
8591 : ! __________________________________________________________
8592 : ! This routine uses a pivoting strategy such as the one of
8593 : ! finding the median based on the quicksort algorithm. It uses
8594 : ! a temporary array, where it stores the partially ranked indices
8595 : ! of the values. It iterates until it can bring the number of
8596 : ! values lower than the pivot to exactly NORD, and then uses an
8597 : ! insertion sort to rank this set, since it is supposedly small.
8598 : ! Michel Olagnon - Feb. 2000
8599 : ! __________________________________________________________
8600 : ! _________________________________________________________
8601 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
8602 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
8603 : Integer(kind = i4), Intent (In) :: NORD
8604 : ! __________________________________________________________
8605 0 : Real(kind = sp) :: XPIV, XWRK
8606 : ! __________________________________________________________
8607 : !
8608 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: IWRKT
8609 : Integer(kind = i4) :: NDON, ICRS, IDEB, IDCR, IFIN, IMIL, IWRK
8610 : !
8611 0 : NDON = SIZE (XDONT)
8612 : !
8613 0 : Do ICRS = 1, NDON
8614 0 : IWRKT (ICRS) = ICRS
8615 : End Do
8616 : IDEB = 1
8617 : IFIN = NDON
8618 : Do
8619 0 : If (IDEB >= IFIN) Exit
8620 0 : IMIL = (IDEB + IFIN) / 2
8621 : !
8622 : ! One chooses a pivot, median of 1st, last, and middle values
8623 : !
8624 0 : If (XDONT(IWRKT(IMIL)) < XDONT(IWRKT(IDEB))) Then
8625 0 : IWRK = IWRKT (IDEB)
8626 0 : IWRKT (IDEB) = IWRKT (IMIL)
8627 0 : IWRKT (IMIL) = IWRK
8628 : End If
8629 0 : If (XDONT(IWRKT(IMIL)) > XDONT(IWRKT(IFIN))) Then
8630 0 : IWRK = IWRKT (IFIN)
8631 0 : IWRKT (IFIN) = IWRKT (IMIL)
8632 0 : IWRKT (IMIL) = IWRK
8633 0 : If (XDONT(IWRKT(IMIL)) < XDONT(IWRKT(IDEB))) Then
8634 0 : IWRK = IWRKT (IDEB)
8635 0 : IWRKT (IDEB) = IWRKT (IMIL)
8636 0 : IWRKT (IMIL) = IWRK
8637 : End If
8638 : End If
8639 0 : If ((IFIN - IDEB) < 3) Exit
8640 0 : XPIV = XDONT (IWRKT(IMIL))
8641 : !
8642 : ! One exchanges values to put those > pivot in the end and
8643 : ! those <= pivot at the beginning
8644 : !
8645 0 : ICRS = IDEB
8646 0 : IDCR = IFIN
8647 0 : ECH2 : Do
8648 : Do
8649 0 : ICRS = ICRS + 1
8650 0 : If (ICRS >= IDCR) Then
8651 : !
8652 : ! the first > pivot is IWRKT(IDCR)
8653 : ! the last <= pivot is IWRKT(ICRS-1)
8654 : ! Note: If one arrives here on the first iteration, then
8655 : ! the pivot is the maximum of the set, the last value is equal
8656 : ! to it, and one can reduce by one the size of the set to process,
8657 : ! as if XDONT (IWRKT(IFIN)) > XPIV
8658 : !
8659 : Exit ECH2
8660 : !
8661 : End If
8662 0 : If (XDONT(IWRKT(ICRS)) > XPIV) Exit
8663 : End Do
8664 : Do
8665 0 : If (XDONT(IWRKT(IDCR)) <= XPIV) Exit
8666 0 : IDCR = IDCR - 1
8667 0 : If (ICRS >= IDCR) Then
8668 : !
8669 : ! The last value < pivot is always IWRKT(ICRS-1)
8670 : !
8671 : Exit ECH2
8672 : End If
8673 : End Do
8674 : !
8675 0 : IWRK = IWRKT (IDCR)
8676 0 : IWRKT (IDCR) = IWRKT (ICRS)
8677 0 : IWRKT (ICRS) = IWRK
8678 : End Do ECH2
8679 : !
8680 : ! One restricts further processing to find the fractile value
8681 : !
8682 0 : If (ICRS <= NORD) IDEB = ICRS
8683 0 : If (ICRS > NORD) IFIN = ICRS - 1
8684 : End Do
8685 : !
8686 : ! Now, we only need to complete ranking of the 1:NORD set
8687 : ! Assuming NORD is small, we use a simple insertion sort
8688 : !
8689 0 : Do ICRS = 2, NORD
8690 0 : IWRK = IWRKT (ICRS)
8691 0 : XWRK = XDONT (IWRK)
8692 0 : Do IDCR = ICRS - 1, 1, - 1
8693 0 : If (XWRK <= XDONT(IWRKT(IDCR))) Then
8694 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
8695 : Else
8696 : Exit
8697 : End If
8698 : End Do
8699 0 : IWRKT (IDCR + 1) = IWRK
8700 : End Do
8701 0 : IRNGT (1 : NORD) = IWRKT (1 : NORD)
8702 0 : Return
8703 : !
8704 0 : End Subroutine R_refpar
8705 :
8706 0 : Subroutine I_refpar (XDONT, IRNGT, NORD)
8707 : ! Ranks partially XDONT by IRNGT, up to order NORD
8708 : ! __________________________________________________________
8709 : ! This routine uses a pivoting strategy such as the one of
8710 : ! finding the median based on the quicksort algorithm. It uses
8711 : ! a temporary array, where it stores the partially ranked indices
8712 : ! of the values. It iterates until it can bring the number of
8713 : ! values lower than the pivot to exactly NORD, and then uses an
8714 : ! insertion sort to rank this set, since it is supposedly small.
8715 : ! Michel Olagnon - Feb. 2000
8716 : ! __________________________________________________________
8717 : ! __________________________________________________________
8718 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
8719 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
8720 : Integer(kind = i4), Intent (In) :: NORD
8721 : ! __________________________________________________________
8722 : Integer(kind = i4) :: XPIV, XWRK
8723 : !
8724 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: IWRKT
8725 : Integer(kind = i4) :: NDON, ICRS, IDEB, IDCR, IFIN, IMIL, IWRK
8726 : !
8727 0 : NDON = SIZE (XDONT)
8728 : !
8729 0 : Do ICRS = 1, NDON
8730 0 : IWRKT (ICRS) = ICRS
8731 : End Do
8732 : IDEB = 1
8733 : IFIN = NDON
8734 : Do
8735 0 : If (IDEB >= IFIN) Exit
8736 0 : IMIL = (IDEB + IFIN) / 2
8737 : !
8738 : ! One chooses a pivot, median of 1st, last, and middle values
8739 : !
8740 0 : If (XDONT(IWRKT(IMIL)) < XDONT(IWRKT(IDEB))) Then
8741 0 : IWRK = IWRKT (IDEB)
8742 0 : IWRKT (IDEB) = IWRKT (IMIL)
8743 0 : IWRKT (IMIL) = IWRK
8744 : End If
8745 0 : If (XDONT(IWRKT(IMIL)) > XDONT(IWRKT(IFIN))) Then
8746 0 : IWRK = IWRKT (IFIN)
8747 0 : IWRKT (IFIN) = IWRKT (IMIL)
8748 0 : IWRKT (IMIL) = IWRK
8749 0 : If (XDONT(IWRKT(IMIL)) < XDONT(IWRKT(IDEB))) Then
8750 0 : IWRK = IWRKT (IDEB)
8751 0 : IWRKT (IDEB) = IWRKT (IMIL)
8752 0 : IWRKT (IMIL) = IWRK
8753 : End If
8754 : End If
8755 0 : If ((IFIN - IDEB) < 3) Exit
8756 0 : XPIV = XDONT (IWRKT(IMIL))
8757 : !
8758 : ! One exchanges values to put those > pivot in the end and
8759 : ! those <= pivot at the beginning
8760 : !
8761 0 : ICRS = IDEB
8762 0 : IDCR = IFIN
8763 0 : ECH2 : Do
8764 : Do
8765 0 : ICRS = ICRS + 1
8766 0 : If (ICRS >= IDCR) Then
8767 : !
8768 : ! the first > pivot is IWRKT(IDCR)
8769 : ! the last <= pivot is IWRKT(ICRS-1)
8770 : ! Note: If one arrives here on the first iteration, then
8771 : ! the pivot is the maximum of the set, the last value is equal
8772 : ! to it, and one can reduce by one the size of the set to process,
8773 : ! as if XDONT (IWRKT(IFIN)) > XPIV
8774 : !
8775 : Exit ECH2
8776 : !
8777 : End If
8778 0 : If (XDONT(IWRKT(ICRS)) > XPIV) Exit
8779 : End Do
8780 : Do
8781 0 : If (XDONT(IWRKT(IDCR)) <= XPIV) Exit
8782 0 : IDCR = IDCR - 1
8783 0 : If (ICRS >= IDCR) Then
8784 : !
8785 : ! The last value < pivot is always IWRKT(ICRS-1)
8786 : !
8787 : Exit ECH2
8788 : End If
8789 : End Do
8790 : !
8791 0 : IWRK = IWRKT (IDCR)
8792 0 : IWRKT (IDCR) = IWRKT (ICRS)
8793 0 : IWRKT (ICRS) = IWRK
8794 : End Do ECH2
8795 : !
8796 : ! One restricts further processing to find the fractile value
8797 : !
8798 0 : If (ICRS <= NORD) IDEB = ICRS
8799 0 : If (ICRS > NORD) IFIN = ICRS - 1
8800 : End Do
8801 : !
8802 : ! Now, we only need to complete ranking of the 1:NORD set
8803 : ! Assuming NORD is small, we use a simple insertion sort
8804 : !
8805 0 : Do ICRS = 2, NORD
8806 0 : IWRK = IWRKT (ICRS)
8807 0 : XWRK = XDONT (IWRK)
8808 0 : Do IDCR = ICRS - 1, 1, - 1
8809 0 : If (XWRK <= XDONT(IWRKT(IDCR))) Then
8810 0 : IWRKT (IDCR + 1) = IWRKT (IDCR)
8811 : Else
8812 : Exit
8813 : End If
8814 : End Do
8815 0 : IWRKT (IDCR + 1) = IWRK
8816 : End Do
8817 0 : IRNGT (1 : NORD) = IWRKT (1 : NORD)
8818 0 : Return
8819 : !
8820 0 : End Subroutine I_refpar
8821 :
8822 4 : Subroutine D_refsor (XDONT)
8823 : ! Sorts XDONT into ascending order - Quicksort
8824 : ! __________________________________________________________
8825 : ! Quicksort chooses a "pivot" in the set, and explores the
8826 : ! array from both ends, looking for a value > pivot with the
8827 : ! increasing index, for a value <= pivot with the decreasing
8828 : ! index, and swapping them when it has found one of each.
8829 : ! The array is then subdivided in 2 ([3]) subsets:
8830 : ! { values <= pivot} {pivot} {values > pivot}
8831 : ! One then call recursively the program to sort each subset.
8832 : ! When the size of the subarray is small enough, one uses an
8833 : ! insertion sort that is faster for very small sets.
8834 : ! Michel Olagnon - Apr. 2000
8835 : ! __________________________________________________________
8836 : ! __________________________________________________________
8837 : real(kind = dp), Dimension (:), Intent (InOut) :: XDONT
8838 : ! __________________________________________________________
8839 : !
8840 : !
8841 4 : Call D_subsor (XDONT, 1, Size (XDONT))
8842 4 : Call D_inssor (XDONT)
8843 4 : Return
8844 0 : End Subroutine D_refsor
8845 :
8846 28 : Recursive Subroutine D_subsor (XDONT, IDEB1, IFIN1)
8847 : ! Sorts XDONT from IDEB1 to IFIN1
8848 : ! __________________________________________________________
8849 : Real(kind = dp), dimension (:), Intent (InOut) :: XDONT
8850 : Integer(kind = i4), Intent (In) :: IDEB1, IFIN1
8851 : ! __________________________________________________________
8852 : Integer(kind = i4), Parameter :: NINS = 16 ! Max for insertion sort
8853 : Integer(kind = i4) :: ICRS, IDEB, IDCR, IFIN, IMIL
8854 28 : Real(kind = dp) :: XPIV, XWRK
8855 : !
8856 28 : IDEB = IDEB1
8857 28 : IFIN = IFIN1
8858 : !
8859 : ! If we don't have enough values to make it worth while, we leave
8860 : ! them unsorted, and the final insertion sort will take care of them
8861 : !
8862 28 : If ((IFIN - IDEB) > NINS) Then
8863 12 : IMIL = (IDEB + IFIN) / 2
8864 : !
8865 : ! One chooses a pivot, median of 1st, last, and middle values
8866 : !
8867 12 : If (XDONT(IMIL) < XDONT(IDEB)) Then
8868 6 : XWRK = XDONT (IDEB)
8869 6 : XDONT (IDEB) = XDONT (IMIL)
8870 6 : XDONT (IMIL) = XWRK
8871 : End If
8872 12 : If (XDONT(IMIL) > XDONT(IFIN)) Then
8873 5 : XWRK = XDONT (IFIN)
8874 5 : XDONT (IFIN) = XDONT (IMIL)
8875 5 : XDONT (IMIL) = XWRK
8876 5 : If (XDONT(IMIL) < XDONT(IDEB)) Then
8877 1 : XWRK = XDONT (IDEB)
8878 1 : XDONT (IDEB) = XDONT (IMIL)
8879 1 : XDONT (IMIL) = XWRK
8880 : End If
8881 : End If
8882 12 : XPIV = XDONT (IMIL)
8883 : !
8884 : ! One exchanges values to put those > pivot in the end and
8885 : ! those <= pivot at the beginning
8886 : !
8887 12 : ICRS = IDEB
8888 12 : IDCR = IFIN
8889 93 : ECH2 : Do
8890 : Do
8891 224 : ICRS = ICRS + 1
8892 224 : If (ICRS >= IDCR) Then
8893 : !
8894 : ! the first > pivot is IDCR
8895 : ! the last <= pivot is ICRS-1
8896 : ! Note: If one arrives here on the first iteration, then
8897 : ! the pivot is the maximum of the set, the last value is equal
8898 : ! to it, and one can reduce by one the size of the set to process,
8899 : ! as if XDONT (IFIN) > XPIV
8900 : !
8901 : Exit ECH2
8902 : !
8903 : End If
8904 218 : If (XDONT(ICRS) > XPIV) Exit
8905 : End Do
8906 : Do
8907 378 : If (XDONT(IDCR) <= XPIV) Exit
8908 285 : IDCR = IDCR - 1
8909 378 : If (ICRS >= IDCR) Then
8910 : !
8911 : ! The last value < pivot is always ICRS-1
8912 : !
8913 : Exit ECH2
8914 : End If
8915 : End Do
8916 : !
8917 93 : XWRK = XDONT (IDCR)
8918 93 : XDONT (IDCR) = XDONT (ICRS)
8919 99 : XDONT (ICRS) = XWRK
8920 : End Do ECH2
8921 : !
8922 : ! One now sorts each of the two sub-intervals
8923 : !
8924 12 : Call D_subsor (XDONT, IDEB1, ICRS - 1)
8925 12 : Call D_subsor (XDONT, IDCR, IFIN1)
8926 : End If
8927 28 : Return
8928 4 : End Subroutine D_subsor
8929 : !
8930 2 : Subroutine R_refsor (XDONT)
8931 : ! Sorts XDONT into ascending order - Quicksort
8932 : ! __________________________________________________________
8933 : ! Quicksort chooses a "pivot" in the set, and explores the
8934 : ! array from both ends, looking for a value > pivot with the
8935 : ! increasing index, for a value <= pivot with the decreasing
8936 : ! index, and swapping them when it has found one of each.
8937 : ! The array is then subdivided in 2 ([3]) subsets:
8938 : ! { values <= pivot} {pivot} {values > pivot}
8939 : ! One then call recursively the program to sort each subset.
8940 : ! When the size of the subarray is small enough, one uses an
8941 : ! insertion sort that is faster for very small sets.
8942 : ! Michel Olagnon - Apr. 2000
8943 : ! __________________________________________________________
8944 : ! _________________________________________________________
8945 : Real(kind = sp), Dimension (:), Intent (InOut) :: XDONT
8946 : ! __________________________________________________________
8947 : !
8948 : !
8949 2 : Call R_subsor (XDONT, 1, Size (XDONT))
8950 2 : Call R_inssor (XDONT)
8951 2 : Return
8952 2 : End Subroutine R_refsor
8953 :
8954 2 : Recursive Subroutine R_subsor (XDONT, IDEB1, IFIN1)
8955 : ! Sorts XDONT from IDEB1 to IFIN1
8956 : ! __________________________________________________________
8957 : Real(kind = sp), dimension (:), Intent (InOut) :: XDONT
8958 : Integer(kind = i4), Intent (In) :: IDEB1, IFIN1
8959 : ! __________________________________________________________
8960 : Integer(kind = i4), Parameter :: NINS = 16 ! Max for insertion sort
8961 : Integer(kind = i4) :: ICRS, IDEB, IDCR, IFIN, IMIL
8962 2 : Real(kind = sp) :: XPIV, XWRK
8963 : !
8964 2 : IDEB = IDEB1
8965 2 : IFIN = IFIN1
8966 : !
8967 : ! If we don't have enough values to make it worth while, we leave
8968 : ! them unsorted, and the final insertion sort will take care of them
8969 : !
8970 2 : If ((IFIN - IDEB) > NINS) Then
8971 0 : IMIL = (IDEB + IFIN) / 2
8972 : !
8973 : ! One chooses a pivot, median of 1st, last, and middle values
8974 : !
8975 0 : If (XDONT(IMIL) < XDONT(IDEB)) Then
8976 0 : XWRK = XDONT (IDEB)
8977 0 : XDONT (IDEB) = XDONT (IMIL)
8978 0 : XDONT (IMIL) = XWRK
8979 : End If
8980 0 : If (XDONT(IMIL) > XDONT(IFIN)) Then
8981 0 : XWRK = XDONT (IFIN)
8982 0 : XDONT (IFIN) = XDONT (IMIL)
8983 0 : XDONT (IMIL) = XWRK
8984 0 : If (XDONT(IMIL) < XDONT(IDEB)) Then
8985 0 : XWRK = XDONT (IDEB)
8986 0 : XDONT (IDEB) = XDONT (IMIL)
8987 0 : XDONT (IMIL) = XWRK
8988 : End If
8989 : End If
8990 0 : XPIV = XDONT (IMIL)
8991 : !
8992 : ! One exchanges values to put those > pivot in the end and
8993 : ! those <= pivot at the beginning
8994 : !
8995 0 : ICRS = IDEB
8996 0 : IDCR = IFIN
8997 0 : ECH2 : Do
8998 : Do
8999 0 : ICRS = ICRS + 1
9000 0 : If (ICRS >= IDCR) Then
9001 : !
9002 : ! the first > pivot is IDCR
9003 : ! the last <= pivot is ICRS-1
9004 : ! Note: If one arrives here on the first iteration, then
9005 : ! the pivot is the maximum of the set, the last value is equal
9006 : ! to it, and one can reduce by one the size of the set to process,
9007 : ! as if XDONT (IFIN) > XPIV
9008 : !
9009 : Exit ECH2
9010 : !
9011 : End If
9012 0 : If (XDONT(ICRS) > XPIV) Exit
9013 : End Do
9014 : Do
9015 0 : If (XDONT(IDCR) <= XPIV) Exit
9016 0 : IDCR = IDCR - 1
9017 0 : If (ICRS >= IDCR) Then
9018 : !
9019 : ! The last value < pivot is always ICRS-1
9020 : !
9021 : Exit ECH2
9022 : End If
9023 : End Do
9024 : !
9025 0 : XWRK = XDONT (IDCR)
9026 0 : XDONT (IDCR) = XDONT (ICRS)
9027 0 : XDONT (ICRS) = XWRK
9028 : End Do ECH2
9029 : !
9030 : ! One now sorts each of the two sub-intervals
9031 : !
9032 0 : Call R_subsor (XDONT, IDEB1, ICRS - 1)
9033 0 : Call R_subsor (XDONT, IDCR, IFIN1)
9034 : End If
9035 2 : Return
9036 2 : End Subroutine R_subsor
9037 : !
9038 4452 : Subroutine I_refsor (XDONT)
9039 : ! Sorts XDONT into ascending order - Quicksort
9040 : ! __________________________________________________________
9041 : ! Quicksort chooses a "pivot" in the set, and explores the
9042 : ! array from both ends, looking for a value > pivot with the
9043 : ! increasing index, for a value <= pivot with the decreasing
9044 : ! index, and swapping them when it has found one of each.
9045 : ! The array is then subdivided in 2 ([3]) subsets:
9046 : ! { values <= pivot} {pivot} {values > pivot}
9047 : ! One then call recursively the program to sort each subset.
9048 : ! When the size of the subarray is small enough, one uses an
9049 : ! insertion sort that is faster for very small sets.
9050 : ! Michel Olagnon - Apr. 2000
9051 : ! __________________________________________________________
9052 : ! __________________________________________________________
9053 : Integer(kind = i4), Dimension (:), Intent (InOut) :: XDONT
9054 : ! __________________________________________________________
9055 : !
9056 : !
9057 4452 : Call I_subsor (XDONT, 1, Size (XDONT))
9058 4452 : Call I_inssor (XDONT)
9059 4452 : Return
9060 4452 : End Subroutine I_refsor
9061 :
9062 21382 : Recursive Subroutine I_subsor (XDONT, IDEB1, IFIN1)
9063 : ! Sorts XDONT from IDEB1 to IFIN1
9064 : ! __________________________________________________________
9065 : Integer(kind = i4), dimension (:), Intent (InOut) :: XDONT
9066 : Integer(kind = i4), Intent (In) :: IDEB1, IFIN1
9067 : ! __________________________________________________________
9068 : Integer(kind = i4), Parameter :: NINS = 16 ! Max for insertion sort
9069 : Integer(kind = i4) :: ICRS, IDEB, IDCR, IFIN, IMIL
9070 : Integer(kind = i4) :: XPIV, XWRK
9071 : !
9072 21382 : IDEB = IDEB1
9073 21382 : IFIN = IFIN1
9074 : !
9075 : ! If we don't have enough values to make it worth while, we leave
9076 : ! them unsorted, and the final insertion sort will take care of them
9077 : !
9078 21382 : If ((IFIN - IDEB) > NINS) Then
9079 8465 : IMIL = (IDEB + IFIN) / 2
9080 : !
9081 : ! One chooses a pivot, median of 1st, last, and middle values
9082 : !
9083 8465 : If (XDONT(IMIL) < XDONT(IDEB)) Then
9084 4029 : XWRK = XDONT (IDEB)
9085 4029 : XDONT (IDEB) = XDONT (IMIL)
9086 4029 : XDONT (IMIL) = XWRK
9087 : End If
9088 8465 : If (XDONT(IMIL) > XDONT(IFIN)) Then
9089 5259 : XWRK = XDONT (IFIN)
9090 5259 : XDONT (IFIN) = XDONT (IMIL)
9091 5259 : XDONT (IMIL) = XWRK
9092 5259 : If (XDONT(IMIL) < XDONT(IDEB)) Then
9093 2472 : XWRK = XDONT (IDEB)
9094 2472 : XDONT (IDEB) = XDONT (IMIL)
9095 2472 : XDONT (IMIL) = XWRK
9096 : End If
9097 : End If
9098 8465 : XPIV = XDONT (IMIL)
9099 : !
9100 : ! One exchanges values to put those > pivot in the end and
9101 : ! those <= pivot at the beginning
9102 : !
9103 8465 : ICRS = IDEB
9104 8465 : IDCR = IFIN
9105 38761 : ECH2 : Do
9106 : Do
9107 114798 : ICRS = ICRS + 1
9108 114798 : If (ICRS >= IDCR) Then
9109 : !
9110 : ! the first > pivot is IDCR
9111 : ! the last <= pivot is ICRS-1
9112 : ! Note: If one arrives here on the first iteration, then
9113 : ! the pivot is the maximum of the set, the last value is equal
9114 : ! to it, and one can reduce by one the size of the set to process,
9115 : ! as if XDONT (IFIN) > XPIV
9116 : !
9117 : Exit ECH2
9118 : !
9119 : End If
9120 110444 : If (XDONT(ICRS) > XPIV) Exit
9121 : End Do
9122 : Do
9123 139434 : If (XDONT(IDCR) <= XPIV) Exit
9124 100673 : IDCR = IDCR - 1
9125 139434 : If (ICRS >= IDCR) Then
9126 : !
9127 : ! The last value < pivot is always ICRS-1
9128 : !
9129 : Exit ECH2
9130 : End If
9131 : End Do
9132 : !
9133 38761 : XWRK = XDONT (IDCR)
9134 38761 : XDONT (IDCR) = XDONT (ICRS)
9135 42872 : XDONT (ICRS) = XWRK
9136 : End Do ECH2
9137 : !
9138 : ! One now sorts each of the two sub-intervals
9139 : !
9140 8465 : Call I_subsor (XDONT, IDEB1, ICRS - 1)
9141 8465 : Call I_subsor (XDONT, IDCR, IFIN1)
9142 : End If
9143 21382 : Return
9144 4452 : End Subroutine I_subsor
9145 :
9146 0 : Subroutine C_refsor (XDONT)
9147 : ! Sorts XDONT into ascending order - Quicksort
9148 : ! __________________________________________________________
9149 : ! Quicksort chooses a "pivot" in the set, and explores the
9150 : ! array from both ends, looking for a value > pivot with the
9151 : ! increasing index, for a value <= pivot with the decreasing
9152 : ! index, and swapping them when it has found one of each.
9153 : ! The array is then subdivided in 2 ([3]) subsets:
9154 : ! { values <= pivot} {pivot} {values > pivot}
9155 : ! One then call recursively the program to sort each subset.
9156 : ! When the size of the subarray is small enough, one uses an
9157 : ! insertion sort that is faster for very small sets.
9158 : ! Michel Olagnon - Apr. 2000
9159 : ! __________________________________________________________
9160 : ! __________________________________________________________
9161 : character(*), Dimension (:), Intent (InOut) :: XDONT
9162 : ! __________________________________________________________
9163 : !
9164 : !
9165 0 : Call C_subsor (XDONT, 1, Size (XDONT))
9166 0 : Call C_inssor (XDONT)
9167 0 : Return
9168 0 : End Subroutine C_refsor
9169 :
9170 0 : Recursive Subroutine C_subsor (XDONT, IDEB1, IFIN1)
9171 : ! Sorts XDONT from IDEB1 to IFIN1
9172 : ! __________________________________________________________
9173 : character(*), dimension (:), Intent (InOut) :: XDONT
9174 : Integer(kind = i4), Intent (In) :: IDEB1, IFIN1
9175 : ! __________________________________________________________
9176 : Integer(kind = i4), Parameter :: NINS = 16 ! Max for insertion sort
9177 : Integer(kind = i4) :: ICRS, IDEB, IDCR, IFIN, IMIL
9178 0 : character(len(XDONT)) :: XPIV, XWRK
9179 : !
9180 0 : IDEB = IDEB1
9181 0 : IFIN = IFIN1
9182 : !
9183 : ! If we don't have enough values to make it worth while, we leave
9184 : ! them unsorted, and the final insertion sort will take care of them
9185 : !
9186 0 : If ((IFIN - IDEB) > NINS) Then
9187 0 : IMIL = (IDEB + IFIN) / 2
9188 : !
9189 : ! One chooses a pivot, median of 1st, last, and middle values
9190 : !
9191 0 : If (XDONT(IMIL) < XDONT(IDEB)) Then
9192 0 : XWRK = XDONT (IDEB)
9193 0 : XDONT (IDEB) = XDONT (IMIL)
9194 0 : XDONT (IMIL) = XWRK
9195 : End If
9196 0 : If (XDONT(IMIL) > XDONT(IFIN)) Then
9197 0 : XWRK = XDONT (IFIN)
9198 0 : XDONT (IFIN) = XDONT (IMIL)
9199 0 : XDONT (IMIL) = XWRK
9200 0 : If (XDONT(IMIL) < XDONT(IDEB)) Then
9201 0 : XWRK = XDONT (IDEB)
9202 0 : XDONT (IDEB) = XDONT (IMIL)
9203 0 : XDONT (IMIL) = XWRK
9204 : End If
9205 : End If
9206 0 : XPIV = XDONT (IMIL)
9207 : !
9208 : ! One exchanges values to put those > pivot in the end and
9209 : ! those <= pivot at the beginning
9210 : !
9211 0 : ICRS = IDEB
9212 0 : IDCR = IFIN
9213 : ECH2 : Do
9214 : Do
9215 0 : ICRS = ICRS + 1
9216 0 : If (ICRS >= IDCR) Then
9217 : !
9218 : ! the first > pivot is IDCR
9219 : ! the last <= pivot is ICRS-1
9220 : ! Note: If one arrives here on the first iteration, then
9221 : ! the pivot is the maximum of the set, the last value is equal
9222 : ! to it, and one can reduce by one the size of the set to process,
9223 : ! as if XDONT (IFIN) > XPIV
9224 : !
9225 : Exit ECH2
9226 : !
9227 : End If
9228 0 : If (XDONT(ICRS) > XPIV) Exit
9229 : End Do
9230 : Do
9231 0 : If (XDONT(IDCR) <= XPIV) Exit
9232 0 : IDCR = IDCR - 1
9233 0 : If (ICRS >= IDCR) Then
9234 : !
9235 : ! The last value < pivot is always ICRS-1
9236 : !
9237 : Exit ECH2
9238 : End If
9239 : End Do
9240 : !
9241 0 : XWRK = XDONT (IDCR)
9242 0 : XDONT (IDCR) = XDONT (ICRS)
9243 0 : XDONT (ICRS) = XWRK
9244 : End Do ECH2
9245 : !
9246 : ! One now sorts each of the two sub-intervals
9247 : !
9248 0 : Call C_subsor (XDONT, IDEB1, ICRS - 1)
9249 0 : Call C_subsor (XDONT, IDCR, IFIN1)
9250 : End If
9251 0 : Return
9252 0 : End Subroutine C_subsor
9253 : !
9254 0 : Subroutine D_rinpar (XDONT, IRNGT, NORD)
9255 : ! Ranks partially XDONT by IRNGT, up to order NORD = size (IRNGT)
9256 : ! __________________________________________________________
9257 : ! This subroutine uses insertion sort, limiting insertion
9258 : ! to the first NORD values. It does not use any work array
9259 : ! and is faster when NORD is very small (2-5), but worst case
9260 : ! behavior can happen fairly probably (initially inverse sorted)
9261 : ! In many cases, the refined quicksort method is faster.
9262 : ! Michel Olagnon - Feb. 2000
9263 : ! __________________________________________________________
9264 : ! __________________________________________________________
9265 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
9266 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
9267 : Integer(kind = i4), Intent (In) :: NORD
9268 : ! __________________________________________________________
9269 0 : real(kind = dp) :: XWRK, XWRK1
9270 : !
9271 : Integer(kind = i4) :: ICRS, IDCR
9272 : !
9273 0 : IRNGT (1) = 1
9274 0 : Do ICRS = 2, NORD
9275 0 : XWRK = XDONT (ICRS)
9276 0 : Do IDCR = ICRS - 1, 1, - 1
9277 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
9278 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
9279 : End Do
9280 0 : IRNGT (IDCR + 1) = ICRS
9281 : End Do
9282 : !
9283 0 : XWRK1 = XDONT (IRNGT(NORD))
9284 0 : Do ICRS = NORD + 1, SIZE (XDONT)
9285 0 : If (XDONT(ICRS) < XWRK1) Then
9286 0 : XWRK = XDONT (ICRS)
9287 0 : Do IDCR = NORD - 1, 1, - 1
9288 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
9289 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
9290 : End Do
9291 0 : IRNGT (IDCR + 1) = ICRS
9292 0 : XWRK1 = XDONT (IRNGT(NORD))
9293 : End If
9294 : End Do
9295 : !
9296 : !
9297 0 : End Subroutine D_rinpar
9298 :
9299 0 : Subroutine R_rinpar (XDONT, IRNGT, NORD)
9300 : ! Ranks partially XDONT by IRNGT, up to order NORD = size (IRNGT)
9301 : ! __________________________________________________________
9302 : ! This subroutine uses insertion sort, limiting insertion
9303 : ! to the first NORD values. It does not use any work array
9304 : ! and is faster when NORD is very small (2-5), but worst case
9305 : ! behavior can happen fairly probably (initially inverse sorted)
9306 : ! In many cases, the refined quicksort method is faster.
9307 : ! Michel Olagnon - Feb. 2000
9308 : ! __________________________________________________________
9309 : ! _________________________________________________________
9310 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
9311 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
9312 : Integer(kind = i4), Intent (In) :: NORD
9313 : ! __________________________________________________________
9314 0 : Real(kind = sp) :: XWRK, XWRK1
9315 : !
9316 : Integer(kind = i4) :: ICRS, IDCR
9317 : !
9318 0 : IRNGT (1) = 1
9319 0 : Do ICRS = 2, NORD
9320 0 : XWRK = XDONT (ICRS)
9321 0 : Do IDCR = ICRS - 1, 1, - 1
9322 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
9323 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
9324 : End Do
9325 0 : IRNGT (IDCR + 1) = ICRS
9326 : End Do
9327 : !
9328 0 : XWRK1 = XDONT (IRNGT(NORD))
9329 0 : Do ICRS = NORD + 1, SIZE (XDONT)
9330 0 : If (XDONT(ICRS) < XWRK1) Then
9331 0 : XWRK = XDONT (ICRS)
9332 0 : Do IDCR = NORD - 1, 1, - 1
9333 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
9334 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
9335 : End Do
9336 0 : IRNGT (IDCR + 1) = ICRS
9337 0 : XWRK1 = XDONT (IRNGT(NORD))
9338 : End If
9339 : End Do
9340 : !
9341 : !
9342 0 : End Subroutine R_rinpar
9343 :
9344 0 : Subroutine I_rinpar (XDONT, IRNGT, NORD)
9345 : ! Ranks partially XDONT by IRNGT, up to order NORD = size (IRNGT)
9346 : ! __________________________________________________________
9347 : ! This subroutine uses insertion sort, limiting insertion
9348 : ! to the first NORD values. It does not use any work array
9349 : ! and is faster when NORD is very small (2-5), but worst case
9350 : ! behavior can happen fairly probably (initially inverse sorted)
9351 : ! In many cases, the refined quicksort method is faster.
9352 : ! Michel Olagnon - Feb. 2000
9353 : ! __________________________________________________________
9354 : ! __________________________________________________________
9355 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
9356 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
9357 : Integer(kind = i4), Intent (In) :: NORD
9358 : ! __________________________________________________________
9359 : Integer(kind = i4) :: XWRK, XWRK1
9360 : !
9361 : Integer(kind = i4) :: ICRS, IDCR
9362 : !
9363 0 : IRNGT (1) = 1
9364 0 : Do ICRS = 2, NORD
9365 0 : XWRK = XDONT (ICRS)
9366 0 : Do IDCR = ICRS - 1, 1, - 1
9367 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
9368 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
9369 : End Do
9370 0 : IRNGT (IDCR + 1) = ICRS
9371 : End Do
9372 : !
9373 0 : XWRK1 = XDONT (IRNGT(NORD))
9374 0 : Do ICRS = NORD + 1, SIZE (XDONT)
9375 0 : If (XDONT(ICRS) < XWRK1) Then
9376 0 : XWRK = XDONT (ICRS)
9377 0 : Do IDCR = NORD - 1, 1, - 1
9378 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
9379 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
9380 : End Do
9381 0 : IRNGT (IDCR + 1) = ICRS
9382 0 : XWRK1 = XDONT (IRNGT(NORD))
9383 : End If
9384 : End Do
9385 : !
9386 : !
9387 0 : End Subroutine I_rinpar
9388 :
9389 0 : Subroutine D_rnkpar (XDONT, IRNGT, NORD)
9390 : ! Ranks partially XDONT by IRNGT, up to order NORD
9391 : ! __________________________________________________________
9392 : ! This routine uses a pivoting strategy such as the one of
9393 : ! finding the median based on the quicksort algorithm, but
9394 : ! we skew the pivot choice to try to bring it to NORD as
9395 : ! fast as possible. It uses 2 temporary arrays, where it
9396 : ! stores the indices of the values smaller than the pivot
9397 : ! (ILOWT), and the indices of values larger than the pivot
9398 : ! that we might still need later on (IHIGT). It iterates
9399 : ! until it can bring the number of values in ILOWT to
9400 : ! exactly NORD, and then uses an insertion sort to rank
9401 : ! this set, since it is supposedly small.
9402 : ! Michel Olagnon - Feb. 2000
9403 : ! __________________________________________________________
9404 : ! __________________________________________________________
9405 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
9406 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
9407 : Integer(kind = i4), Intent (In) :: NORD
9408 : ! __________________________________________________________
9409 0 : real(kind = dp) :: XPIV, XPIV0, XWRK, XWRK1, XMIN, XMAX
9410 : !
9411 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
9412 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
9413 : Integer(kind = i4) :: IDEB, JDEB, IMIL, IFIN, NWRK, ICRS, IDCR, ILOW
9414 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1
9415 : !
9416 0 : NDON = SIZE (XDONT)
9417 : !
9418 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
9419 : !
9420 0 : If (NDON < 2) Then
9421 0 : If (NORD >= 1) IRNGT (1) = 1
9422 0 : Return
9423 : End If
9424 : !
9425 : ! One chooses a pivot, best estimate possible to put fractile near
9426 : ! mid-point of the set of low values.
9427 : !
9428 0 : If (XDONT(2) < XDONT(1)) Then
9429 0 : ILOWT (1) = 2
9430 0 : IHIGT (1) = 1
9431 : Else
9432 0 : ILOWT (1) = 1
9433 0 : IHIGT (1) = 2
9434 : End If
9435 : !
9436 0 : If (NDON < 3) Then
9437 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
9438 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
9439 0 : Return
9440 : End If
9441 : !
9442 0 : If (XDONT(3) <= XDONT(IHIGT(1))) Then
9443 0 : IHIGT (2) = IHIGT (1)
9444 0 : If (XDONT(3) < XDONT(ILOWT(1))) Then
9445 0 : IHIGT (1) = ILOWT (1)
9446 0 : ILOWT (1) = 3
9447 : Else
9448 0 : IHIGT (1) = 3
9449 : End If
9450 : Else
9451 0 : IHIGT (2) = 3
9452 : End If
9453 : !
9454 0 : If (NDON < 4) Then
9455 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
9456 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
9457 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
9458 0 : Return
9459 : End If
9460 : !
9461 0 : If (XDONT(NDON) <= XDONT(IHIGT(1))) Then
9462 0 : IHIGT (3) = IHIGT (2)
9463 0 : IHIGT (2) = IHIGT (1)
9464 0 : If (XDONT(NDON) < XDONT(ILOWT(1))) Then
9465 0 : IHIGT (1) = ILOWT (1)
9466 0 : ILOWT (1) = NDON
9467 : Else
9468 0 : IHIGT (1) = NDON
9469 : End If
9470 : Else
9471 0 : if (XDONT (NDON) < XDONT (IHIGT(2))) Then
9472 0 : IHIGT (3) = IHIGT (2)
9473 0 : IHIGT (2) = NDON
9474 : else
9475 0 : IHIGT (3) = NDON
9476 : end if
9477 : End If
9478 : !
9479 0 : If (NDON < 5) Then
9480 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
9481 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
9482 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
9483 0 : If (NORD >= 4) IRNGT (4) = IHIGT (3)
9484 0 : Return
9485 : End If
9486 : !
9487 0 : JDEB = 0
9488 0 : IDEB = JDEB + 1
9489 0 : JLOW = IDEB
9490 0 : JHIG = 3
9491 0 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, dp) / REAL(NDON + NORD, dp) * &
9492 0 : (XDONT(IHIGT(3)) - XDONT(ILOWT(IDEB)))
9493 0 : If (XPIV >= XDONT(IHIGT(1))) Then
9494 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, dp) / REAL(NDON + NORD, dp) * &
9495 0 : (XDONT(IHIGT(2)) - XDONT(ILOWT(IDEB)))
9496 0 : If (XPIV >= XDONT(IHIGT(1))) &
9497 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, dp) / REAL(NDON + NORD, dp) * &
9498 0 : (XDONT(IHIGT(1)) - XDONT(ILOWT(IDEB)))
9499 : End If
9500 0 : XPIV0 = XPIV
9501 : !
9502 : ! One puts values > pivot in the end and those <= pivot
9503 : ! at the beginning. This is split in 2 cases, so that
9504 : ! we can skip the loop test a number of times.
9505 : ! As we are also filling in the work arrays at the same time
9506 : ! we stop filling in the IHIGT array as soon as we have more
9507 : ! than enough values in ILOWT.
9508 : !
9509 : !
9510 0 : If (XDONT(NDON) > XPIV) Then
9511 : ICRS = 3
9512 : Do
9513 0 : ICRS = ICRS + 1
9514 0 : If (XDONT(ICRS) > XPIV) Then
9515 0 : If (ICRS >= NDON) Exit
9516 0 : JHIG = JHIG + 1
9517 0 : IHIGT (JHIG) = ICRS
9518 : Else
9519 0 : JLOW = JLOW + 1
9520 0 : ILOWT (JLOW) = ICRS
9521 0 : If (JLOW >= NORD) Exit
9522 : End If
9523 : End Do
9524 : !
9525 : ! One restricts further processing because it is no use
9526 : ! to store more high values
9527 : !
9528 0 : If (ICRS < NDON - 1) Then
9529 : Do
9530 0 : ICRS = ICRS + 1
9531 0 : If (XDONT(ICRS) <= XPIV) Then
9532 0 : JLOW = JLOW + 1
9533 0 : ILOWT (JLOW) = ICRS
9534 0 : Else If (ICRS >= NDON) Then
9535 : Exit
9536 : End If
9537 : End Do
9538 : End If
9539 : !
9540 : !
9541 : Else
9542 : !
9543 : ! Same as above, but this is not as easy to optimize, so the
9544 : ! DO-loop is kept
9545 : !
9546 0 : Do ICRS = 4, NDON - 1
9547 0 : If (XDONT(ICRS) > XPIV) Then
9548 0 : JHIG = JHIG + 1
9549 0 : IHIGT (JHIG) = ICRS
9550 : Else
9551 0 : JLOW = JLOW + 1
9552 0 : ILOWT (JLOW) = ICRS
9553 0 : If (JLOW >= NORD) Exit
9554 : End If
9555 : End Do
9556 : !
9557 0 : If (ICRS < NDON - 1) Then
9558 : Do
9559 0 : ICRS = ICRS + 1
9560 0 : If (XDONT(ICRS) <= XPIV) Then
9561 0 : If (ICRS >= NDON) Exit
9562 0 : JLOW = JLOW + 1
9563 0 : ILOWT (JLOW) = ICRS
9564 : End If
9565 : End Do
9566 : End If
9567 : End If
9568 : !
9569 : JLM2 = 0
9570 : JLM1 = 0
9571 : JHM2 = 0
9572 : JHM1 = 0
9573 : Do
9574 0 : if (JLOW == NORD) Exit
9575 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
9576 : !
9577 : ! We are oscillating. Perturbate by bringing JLOW closer by one
9578 : ! to NORD
9579 : !
9580 0 : If (NORD > JLOW) Then
9581 0 : XMIN = XDONT (IHIGT(1))
9582 0 : IHIG = 1
9583 0 : Do ICRS = 2, JHIG
9584 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
9585 0 : XMIN = XDONT (IHIGT(ICRS))
9586 0 : IHIG = ICRS
9587 : End If
9588 : End Do
9589 : !
9590 0 : JLOW = JLOW + 1
9591 0 : ILOWT (JLOW) = IHIGT (IHIG)
9592 0 : IHIGT (IHIG) = IHIGT (JHIG)
9593 0 : JHIG = JHIG - 1
9594 : Else
9595 0 : ILOW = ILOWT (JLOW)
9596 0 : XMAX = XDONT (ILOW)
9597 0 : Do ICRS = 1, JLOW
9598 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
9599 0 : IWRK = ILOWT (ICRS)
9600 0 : XMAX = XDONT (IWRK)
9601 0 : ILOWT (ICRS) = ILOW
9602 0 : ILOW = IWRK
9603 : End If
9604 : End Do
9605 0 : JLOW = JLOW - 1
9606 : End If
9607 : End If
9608 0 : JLM2 = JLM1
9609 0 : JLM1 = JLOW
9610 0 : JHM2 = JHM1
9611 0 : JHM1 = JHIG
9612 : !
9613 : ! We try to bring the number of values in the low values set
9614 : ! closer to NORD.
9615 : !
9616 0 : Select Case (NORD - JLOW)
9617 : Case (2 :)
9618 : !
9619 : ! Not enough values in low part, at least 2 are missing
9620 : !
9621 : Select Case (JHIG)
9622 : !!!!! CASE DEFAULT
9623 : !!!!! write (*,*) "Assertion failed"
9624 : !!!!! STOP
9625 : !
9626 : ! We make a special case when we have so few values in
9627 : ! the high values set that it is bad performance to choose a pivot
9628 : ! and apply the general algorithm.
9629 : !
9630 : Case (2)
9631 0 : If (XDONT(IHIGT(1)) <= XDONT(IHIGT(2))) Then
9632 0 : JLOW = JLOW + 1
9633 0 : ILOWT (JLOW) = IHIGT (1)
9634 0 : JLOW = JLOW + 1
9635 0 : ILOWT (JLOW) = IHIGT (2)
9636 : Else
9637 0 : JLOW = JLOW + 1
9638 0 : ILOWT (JLOW) = IHIGT (2)
9639 0 : JLOW = JLOW + 1
9640 0 : ILOWT (JLOW) = IHIGT (1)
9641 : End If
9642 : Exit
9643 : !
9644 : Case (3)
9645 : !
9646 : !
9647 0 : IWRK1 = IHIGT (1)
9648 0 : IWRK2 = IHIGT (2)
9649 0 : IWRK3 = IHIGT (3)
9650 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
9651 0 : IHIGT (1) = IWRK2
9652 0 : IHIGT (2) = IWRK1
9653 0 : IWRK2 = IWRK1
9654 : End If
9655 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
9656 0 : IHIGT (3) = IWRK2
9657 0 : IHIGT (2) = IWRK3
9658 0 : IWRK2 = IWRK3
9659 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
9660 0 : IHIGT (2) = IHIGT (1)
9661 0 : IHIGT (1) = IWRK2
9662 : End If
9663 : End If
9664 0 : JHIG = 0
9665 0 : Do ICRS = JLOW + 1, NORD
9666 0 : JHIG = JHIG + 1
9667 0 : ILOWT (ICRS) = IHIGT (JHIG)
9668 : End Do
9669 0 : JLOW = NORD
9670 : Exit
9671 : !
9672 : Case (4 :)
9673 : !
9674 : !
9675 0 : XPIV0 = XPIV
9676 0 : IFIN = JHIG
9677 : !
9678 : ! One chooses a pivot from the 2 first values and the last one.
9679 : ! This should ensure sufficient renewal between iterations to
9680 : ! avoid worst case behavior effects.
9681 : !
9682 0 : IWRK1 = IHIGT (1)
9683 0 : IWRK2 = IHIGT (2)
9684 0 : IWRK3 = IHIGT (IFIN)
9685 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
9686 0 : IHIGT (1) = IWRK2
9687 0 : IHIGT (2) = IWRK1
9688 0 : IWRK2 = IWRK1
9689 : End If
9690 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
9691 0 : IHIGT (IFIN) = IWRK2
9692 0 : IHIGT (2) = IWRK3
9693 0 : IWRK2 = IWRK3
9694 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
9695 0 : IHIGT (2) = IHIGT (1)
9696 0 : IHIGT (1) = IWRK2
9697 : End If
9698 : End If
9699 : !
9700 0 : JDEB = JLOW
9701 0 : NWRK = NORD - JLOW
9702 0 : IWRK1 = IHIGT (1)
9703 0 : JLOW = JLOW + 1
9704 0 : ILOWT (JLOW) = IWRK1
9705 0 : XPIV = XDONT (IWRK1) + REAL(NWRK, dp) / REAL(NORD + NWRK, dp) * &
9706 0 : (XDONT(IHIGT(IFIN)) - XDONT(IWRK1))
9707 : !
9708 : ! One takes values <= pivot to ILOWT
9709 : ! Again, 2 parts, one where we take care of the remaining
9710 : ! high values because we might still need them, and the
9711 : ! other when we know that we will have more than enough
9712 : ! low values in the end.
9713 : !
9714 0 : JHIG = 0
9715 0 : Do ICRS = 2, IFIN
9716 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
9717 0 : JLOW = JLOW + 1
9718 0 : ILOWT (JLOW) = IHIGT (ICRS)
9719 0 : If (JLOW >= NORD) Exit
9720 : Else
9721 0 : JHIG = JHIG + 1
9722 0 : IHIGT (JHIG) = IHIGT (ICRS)
9723 : End If
9724 : End Do
9725 : !
9726 0 : Do ICRS = ICRS + 1, IFIN
9727 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
9728 0 : JLOW = JLOW + 1
9729 0 : ILOWT (JLOW) = IHIGT (ICRS)
9730 : End If
9731 : End Do
9732 : End Select
9733 : !
9734 : !
9735 : Case (1)
9736 : !
9737 : ! Only 1 value is missing in low part
9738 : !
9739 0 : XMIN = XDONT (IHIGT(1))
9740 0 : IHIG = 1
9741 0 : Do ICRS = 2, JHIG
9742 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
9743 0 : XMIN = XDONT (IHIGT(ICRS))
9744 0 : IHIG = ICRS
9745 : End If
9746 : End Do
9747 : !
9748 0 : JLOW = JLOW + 1
9749 0 : ILOWT (JLOW) = IHIGT (IHIG)
9750 0 : Exit
9751 : !
9752 : !
9753 : Case (0)
9754 : !
9755 : ! Low part is exactly what we want
9756 : !
9757 0 : Exit
9758 : !
9759 : !
9760 : Case (-5 : -1)
9761 : !
9762 : ! Only few values too many in low part
9763 : !
9764 0 : IRNGT (1) = ILOWT (1)
9765 0 : Do ICRS = 2, NORD
9766 0 : IWRK = ILOWT (ICRS)
9767 0 : XWRK = XDONT (IWRK)
9768 0 : Do IDCR = ICRS - 1, 1, - 1
9769 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
9770 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
9771 : Else
9772 : Exit
9773 : End If
9774 : End Do
9775 0 : IRNGT (IDCR + 1) = IWRK
9776 : End Do
9777 : !
9778 0 : XWRK1 = XDONT (IRNGT(NORD))
9779 0 : Do ICRS = NORD + 1, JLOW
9780 0 : If (XDONT(ILOWT (ICRS)) < XWRK1) Then
9781 0 : XWRK = XDONT (ILOWT (ICRS))
9782 0 : Do IDCR = NORD - 1, 1, - 1
9783 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
9784 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
9785 : End Do
9786 0 : IRNGT (IDCR + 1) = ILOWT (ICRS)
9787 0 : XWRK1 = XDONT (IRNGT(NORD))
9788 : End If
9789 : End Do
9790 : !
9791 0 : Return
9792 : !
9793 : !
9794 : Case (: -6)
9795 : !
9796 : ! last case: too many values in low part
9797 : !
9798 0 : IDEB = JDEB + 1
9799 0 : IMIL = (JLOW + IDEB) / 2
9800 0 : IFIN = JLOW
9801 : !
9802 : ! One chooses a pivot from 1st, last, and middle values
9803 : !
9804 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
9805 0 : IWRK = ILOWT (IDEB)
9806 0 : ILOWT (IDEB) = ILOWT (IMIL)
9807 0 : ILOWT (IMIL) = IWRK
9808 : End If
9809 0 : If (XDONT(ILOWT(IMIL)) > XDONT(ILOWT(IFIN))) Then
9810 0 : IWRK = ILOWT (IFIN)
9811 0 : ILOWT (IFIN) = ILOWT (IMIL)
9812 0 : ILOWT (IMIL) = IWRK
9813 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
9814 0 : IWRK = ILOWT (IDEB)
9815 0 : ILOWT (IDEB) = ILOWT (IMIL)
9816 0 : ILOWT (IMIL) = IWRK
9817 : End If
9818 : End If
9819 0 : If (IFIN <= 3) Exit
9820 : !
9821 0 : XPIV = XDONT (ILOWT(1)) + REAL(NORD, dp) / REAL(JLOW + NORD, dp) * &
9822 0 : (XDONT(ILOWT(IFIN)) - XDONT(ILOWT(1)))
9823 0 : If (JDEB > 0) Then
9824 0 : If (XPIV <= XPIV0) &
9825 : XPIV = XPIV0 + REAL(2 * NORD - JDEB, dp) / REAL(JLOW + NORD, dp) * &
9826 0 : (XDONT(ILOWT(IFIN)) - XPIV0)
9827 : Else
9828 : IDEB = 1
9829 : End If
9830 : !
9831 : ! One takes values > XPIV to IHIGT
9832 : ! However, we do not process the first values if we have been
9833 : ! through the case when we did not have enough low values
9834 : !
9835 0 : JHIG = 0
9836 0 : JLOW = JDEB
9837 : !
9838 0 : If (XDONT(ILOWT(IFIN)) > XPIV) Then
9839 : ICRS = JDEB
9840 : Do
9841 0 : ICRS = ICRS + 1
9842 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
9843 0 : JHIG = JHIG + 1
9844 0 : IHIGT (JHIG) = ILOWT (ICRS)
9845 0 : If (ICRS >= IFIN) Exit
9846 : Else
9847 0 : JLOW = JLOW + 1
9848 0 : ILOWT (JLOW) = ILOWT (ICRS)
9849 0 : If (JLOW >= NORD) Exit
9850 : End If
9851 : End Do
9852 : !
9853 0 : If (ICRS < IFIN) Then
9854 : Do
9855 0 : ICRS = ICRS + 1
9856 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
9857 0 : JLOW = JLOW + 1
9858 0 : ILOWT (JLOW) = ILOWT (ICRS)
9859 : Else
9860 0 : If (ICRS >= IFIN) Exit
9861 : End If
9862 : End Do
9863 : End If
9864 : Else
9865 0 : Do ICRS = IDEB, IFIN
9866 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
9867 0 : JHIG = JHIG + 1
9868 0 : IHIGT (JHIG) = ILOWT (ICRS)
9869 : Else
9870 0 : JLOW = JLOW + 1
9871 0 : ILOWT (JLOW) = ILOWT (ICRS)
9872 0 : If (JLOW >= NORD) Exit
9873 : End If
9874 : End Do
9875 : !
9876 0 : Do ICRS = ICRS + 1, IFIN
9877 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
9878 0 : JLOW = JLOW + 1
9879 0 : ILOWT (JLOW) = ILOWT (ICRS)
9880 : End If
9881 : End Do
9882 : End If
9883 : !
9884 : End Select
9885 : !
9886 : End Do
9887 : !
9888 : ! Now, we only need to complete ranking of the 1:NORD set
9889 : ! Assuming NORD is small, we use a simple insertion sort
9890 : !
9891 0 : IRNGT (1) = ILOWT (1)
9892 0 : Do ICRS = 2, NORD
9893 0 : IWRK = ILOWT (ICRS)
9894 0 : XWRK = XDONT (IWRK)
9895 0 : Do IDCR = ICRS - 1, 1, - 1
9896 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
9897 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
9898 : Else
9899 : Exit
9900 : End If
9901 : End Do
9902 0 : IRNGT (IDCR + 1) = IWRK
9903 : End Do
9904 : Return
9905 : !
9906 : !
9907 0 : End Subroutine D_rnkpar
9908 :
9909 0 : Subroutine R_rnkpar (XDONT, IRNGT, NORD)
9910 : ! Ranks partially XDONT by IRNGT, up to order NORD
9911 : ! __________________________________________________________
9912 : ! This routine uses a pivoting strategy such as the one of
9913 : ! finding the median based on the quicksort algorithm, but
9914 : ! we skew the pivot choice to try to bring it to NORD as
9915 : ! fast as possible. It uses 2 temporary arrays, where it
9916 : ! stores the indices of the values smaller than the pivot
9917 : ! (ILOWT), and the indices of values larger than the pivot
9918 : ! that we might still need later on (IHIGT). It iterates
9919 : ! until it can bring the number of values in ILOWT to
9920 : ! exactly NORD, and then uses an insertion sort to rank
9921 : ! this set, since it is supposedly small.
9922 : ! Michel Olagnon - Feb. 2000
9923 : ! __________________________________________________________
9924 : ! _________________________________________________________
9925 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
9926 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
9927 : Integer(kind = i4), Intent (In) :: NORD
9928 : ! __________________________________________________________
9929 0 : Real(kind = sp) :: XPIV, XPIV0, XWRK, XWRK1, XMIN, XMAX
9930 : !
9931 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
9932 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
9933 : Integer(kind = i4) :: IDEB, JDEB, IMIL, IFIN, NWRK, ICRS, IDCR, ILOW
9934 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1
9935 : !
9936 0 : NDON = SIZE (XDONT)
9937 : !
9938 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
9939 : !
9940 0 : If (NDON < 2) Then
9941 0 : If (NORD >= 1) IRNGT (1) = 1
9942 0 : Return
9943 : End If
9944 : !
9945 : ! One chooses a pivot, best estimate possible to put fractile near
9946 : ! mid-point of the set of low values.
9947 : !
9948 0 : If (XDONT(2) < XDONT(1)) Then
9949 0 : ILOWT (1) = 2
9950 0 : IHIGT (1) = 1
9951 : Else
9952 0 : ILOWT (1) = 1
9953 0 : IHIGT (1) = 2
9954 : End If
9955 : !
9956 0 : If (NDON < 3) Then
9957 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
9958 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
9959 0 : Return
9960 : End If
9961 : !
9962 0 : If (XDONT(3) <= XDONT(IHIGT(1))) Then
9963 0 : IHIGT (2) = IHIGT (1)
9964 0 : If (XDONT(3) < XDONT(ILOWT(1))) Then
9965 0 : IHIGT (1) = ILOWT (1)
9966 0 : ILOWT (1) = 3
9967 : Else
9968 0 : IHIGT (1) = 3
9969 : End If
9970 : Else
9971 0 : IHIGT (2) = 3
9972 : End If
9973 : !
9974 0 : If (NDON < 4) Then
9975 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
9976 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
9977 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
9978 0 : Return
9979 : End If
9980 : !
9981 0 : If (XDONT(NDON) <= XDONT(IHIGT(1))) Then
9982 0 : IHIGT (3) = IHIGT (2)
9983 0 : IHIGT (2) = IHIGT (1)
9984 0 : If (XDONT(NDON) < XDONT(ILOWT(1))) Then
9985 0 : IHIGT (1) = ILOWT (1)
9986 0 : ILOWT (1) = NDON
9987 : Else
9988 0 : IHIGT (1) = NDON
9989 : End If
9990 : Else
9991 0 : if (XDONT (NDON) < XDONT (IHIGT(2))) Then
9992 0 : IHIGT (3) = IHIGT (2)
9993 0 : IHIGT (2) = NDON
9994 : else
9995 0 : IHIGT (3) = NDON
9996 : end if
9997 : End If
9998 : !
9999 0 : If (NDON < 5) Then
10000 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
10001 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
10002 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
10003 0 : If (NORD >= 4) IRNGT (4) = IHIGT (3)
10004 0 : Return
10005 : End If
10006 : !
10007 0 : JDEB = 0
10008 0 : IDEB = JDEB + 1
10009 0 : JLOW = IDEB
10010 0 : JHIG = 3
10011 0 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, sp) / REAL(NDON + NORD, sp) * &
10012 0 : (XDONT(IHIGT(3)) - XDONT(ILOWT(IDEB)))
10013 0 : If (XPIV >= XDONT(IHIGT(1))) Then
10014 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, sp) / REAL(NDON + NORD, sp) * &
10015 0 : (XDONT(IHIGT(2)) - XDONT(ILOWT(IDEB)))
10016 0 : If (XPIV >= XDONT(IHIGT(1))) &
10017 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, sp) / REAL(NDON + NORD, sp) * &
10018 0 : (XDONT(IHIGT(1)) - XDONT(ILOWT(IDEB)))
10019 : End If
10020 0 : XPIV0 = XPIV
10021 : !
10022 : ! One puts values > pivot in the end and those <= pivot
10023 : ! at the beginning. This is split in 2 cases, so that
10024 : ! we can skip the loop test a number of times.
10025 : ! As we are also filling in the work arrays at the same time
10026 : ! we stop filling in the IHIGT array as soon as we have more
10027 : ! than enough values in ILOWT.
10028 : !
10029 : !
10030 0 : If (XDONT(NDON) > XPIV) Then
10031 : ICRS = 3
10032 : Do
10033 0 : ICRS = ICRS + 1
10034 0 : If (XDONT(ICRS) > XPIV) Then
10035 0 : If (ICRS >= NDON) Exit
10036 0 : JHIG = JHIG + 1
10037 0 : IHIGT (JHIG) = ICRS
10038 : Else
10039 0 : JLOW = JLOW + 1
10040 0 : ILOWT (JLOW) = ICRS
10041 0 : If (JLOW >= NORD) Exit
10042 : End If
10043 : End Do
10044 : !
10045 : ! One restricts further processing because it is no use
10046 : ! to store more high values
10047 : !
10048 0 : If (ICRS < NDON - 1) Then
10049 : Do
10050 0 : ICRS = ICRS + 1
10051 0 : If (XDONT(ICRS) <= XPIV) Then
10052 0 : JLOW = JLOW + 1
10053 0 : ILOWT (JLOW) = ICRS
10054 0 : Else If (ICRS >= NDON) Then
10055 : Exit
10056 : End If
10057 : End Do
10058 : End If
10059 : !
10060 : !
10061 : Else
10062 : !
10063 : ! Same as above, but this is not as easy to optimize, so the
10064 : ! DO-loop is kept
10065 : !
10066 0 : Do ICRS = 4, NDON - 1
10067 0 : If (XDONT(ICRS) > XPIV) Then
10068 0 : JHIG = JHIG + 1
10069 0 : IHIGT (JHIG) = ICRS
10070 : Else
10071 0 : JLOW = JLOW + 1
10072 0 : ILOWT (JLOW) = ICRS
10073 0 : If (JLOW >= NORD) Exit
10074 : End If
10075 : End Do
10076 : !
10077 0 : If (ICRS < NDON - 1) Then
10078 : Do
10079 0 : ICRS = ICRS + 1
10080 0 : If (XDONT(ICRS) <= XPIV) Then
10081 0 : If (ICRS >= NDON) Exit
10082 0 : JLOW = JLOW + 1
10083 0 : ILOWT (JLOW) = ICRS
10084 : End If
10085 : End Do
10086 : End If
10087 : End If
10088 : !
10089 : JLM2 = 0
10090 : JLM1 = 0
10091 : JHM2 = 0
10092 : JHM1 = 0
10093 : Do
10094 0 : if (JLOW == NORD) Exit
10095 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
10096 : !
10097 : ! We are oscillating. Perturbate by bringing JLOW closer by one
10098 : ! to NORD
10099 : !
10100 0 : If (NORD > JLOW) Then
10101 0 : XMIN = XDONT (IHIGT(1))
10102 0 : IHIG = 1
10103 0 : Do ICRS = 2, JHIG
10104 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
10105 0 : XMIN = XDONT (IHIGT(ICRS))
10106 0 : IHIG = ICRS
10107 : End If
10108 : End Do
10109 : !
10110 0 : JLOW = JLOW + 1
10111 0 : ILOWT (JLOW) = IHIGT (IHIG)
10112 0 : IHIGT (IHIG) = IHIGT (JHIG)
10113 0 : JHIG = JHIG - 1
10114 : Else
10115 0 : ILOW = ILOWT (JLOW)
10116 0 : XMAX = XDONT (ILOW)
10117 0 : Do ICRS = 1, JLOW
10118 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
10119 0 : IWRK = ILOWT (ICRS)
10120 0 : XMAX = XDONT (IWRK)
10121 0 : ILOWT (ICRS) = ILOW
10122 0 : ILOW = IWRK
10123 : End If
10124 : End Do
10125 0 : JLOW = JLOW - 1
10126 : End If
10127 : End If
10128 0 : JLM2 = JLM1
10129 0 : JLM1 = JLOW
10130 0 : JHM2 = JHM1
10131 0 : JHM1 = JHIG
10132 : !
10133 : ! We try to bring the number of values in the low values set
10134 : ! closer to NORD.
10135 : !
10136 0 : Select Case (NORD - JLOW)
10137 : Case (2 :)
10138 : !
10139 : ! Not enough values in low part, at least 2 are missing
10140 : !
10141 : Select Case (JHIG)
10142 : !!!!! CASE DEFAULT
10143 : !!!!! write (*,*) "Assertion failed"
10144 : !!!!! STOP
10145 : !
10146 : ! We make a special case when we have so few values in
10147 : ! the high values set that it is bad performance to choose a pivot
10148 : ! and apply the general algorithm.
10149 : !
10150 : Case (2)
10151 0 : If (XDONT(IHIGT(1)) <= XDONT(IHIGT(2))) Then
10152 0 : JLOW = JLOW + 1
10153 0 : ILOWT (JLOW) = IHIGT (1)
10154 0 : JLOW = JLOW + 1
10155 0 : ILOWT (JLOW) = IHIGT (2)
10156 : Else
10157 0 : JLOW = JLOW + 1
10158 0 : ILOWT (JLOW) = IHIGT (2)
10159 0 : JLOW = JLOW + 1
10160 0 : ILOWT (JLOW) = IHIGT (1)
10161 : End If
10162 : Exit
10163 : !
10164 : Case (3)
10165 : !
10166 : !
10167 0 : IWRK1 = IHIGT (1)
10168 0 : IWRK2 = IHIGT (2)
10169 0 : IWRK3 = IHIGT (3)
10170 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
10171 0 : IHIGT (1) = IWRK2
10172 0 : IHIGT (2) = IWRK1
10173 0 : IWRK2 = IWRK1
10174 : End If
10175 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
10176 0 : IHIGT (3) = IWRK2
10177 0 : IHIGT (2) = IWRK3
10178 0 : IWRK2 = IWRK3
10179 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
10180 0 : IHIGT (2) = IHIGT (1)
10181 0 : IHIGT (1) = IWRK2
10182 : End If
10183 : End If
10184 0 : JHIG = 0
10185 0 : Do ICRS = JLOW + 1, NORD
10186 0 : JHIG = JHIG + 1
10187 0 : ILOWT (ICRS) = IHIGT (JHIG)
10188 : End Do
10189 0 : JLOW = NORD
10190 : Exit
10191 : !
10192 : Case (4 :)
10193 : !
10194 : !
10195 0 : XPIV0 = XPIV
10196 0 : IFIN = JHIG
10197 : !
10198 : ! One chooses a pivot from the 2 first values and the last one.
10199 : ! This should ensure sufficient renewal between iterations to
10200 : ! avoid worst case behavior effects.
10201 : !
10202 0 : IWRK1 = IHIGT (1)
10203 0 : IWRK2 = IHIGT (2)
10204 0 : IWRK3 = IHIGT (IFIN)
10205 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
10206 0 : IHIGT (1) = IWRK2
10207 0 : IHIGT (2) = IWRK1
10208 0 : IWRK2 = IWRK1
10209 : End If
10210 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
10211 0 : IHIGT (IFIN) = IWRK2
10212 0 : IHIGT (2) = IWRK3
10213 0 : IWRK2 = IWRK3
10214 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
10215 0 : IHIGT (2) = IHIGT (1)
10216 0 : IHIGT (1) = IWRK2
10217 : End If
10218 : End If
10219 : !
10220 0 : JDEB = JLOW
10221 0 : NWRK = NORD - JLOW
10222 0 : IWRK1 = IHIGT (1)
10223 0 : JLOW = JLOW + 1
10224 0 : ILOWT (JLOW) = IWRK1
10225 0 : XPIV = XDONT (IWRK1) + REAL(NWRK, sp) / REAL(NORD + NWRK, sp) * &
10226 0 : (XDONT(IHIGT(IFIN)) - XDONT(IWRK1))
10227 : !
10228 : ! One takes values <= pivot to ILOWT
10229 : ! Again, 2 parts, one where we take care of the remaining
10230 : ! high values because we might still need them, and the
10231 : ! other when we know that we will have more than enough
10232 : ! low values in the end.
10233 : !
10234 0 : JHIG = 0
10235 0 : Do ICRS = 2, IFIN
10236 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
10237 0 : JLOW = JLOW + 1
10238 0 : ILOWT (JLOW) = IHIGT (ICRS)
10239 0 : If (JLOW >= NORD) Exit
10240 : Else
10241 0 : JHIG = JHIG + 1
10242 0 : IHIGT (JHIG) = IHIGT (ICRS)
10243 : End If
10244 : End Do
10245 : !
10246 0 : Do ICRS = ICRS + 1, IFIN
10247 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
10248 0 : JLOW = JLOW + 1
10249 0 : ILOWT (JLOW) = IHIGT (ICRS)
10250 : End If
10251 : End Do
10252 : End Select
10253 : !
10254 : !
10255 : Case (1)
10256 : !
10257 : ! Only 1 value is missing in low part
10258 : !
10259 0 : XMIN = XDONT (IHIGT(1))
10260 0 : IHIG = 1
10261 0 : Do ICRS = 2, JHIG
10262 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
10263 0 : XMIN = XDONT (IHIGT(ICRS))
10264 0 : IHIG = ICRS
10265 : End If
10266 : End Do
10267 : !
10268 0 : JLOW = JLOW + 1
10269 0 : ILOWT (JLOW) = IHIGT (IHIG)
10270 0 : Exit
10271 : !
10272 : !
10273 : Case (0)
10274 : !
10275 : ! Low part is exactly what we want
10276 : !
10277 0 : Exit
10278 : !
10279 : !
10280 : Case (-5 : -1)
10281 : !
10282 : ! Only few values too many in low part
10283 : !
10284 0 : IRNGT (1) = ILOWT (1)
10285 0 : Do ICRS = 2, NORD
10286 0 : IWRK = ILOWT (ICRS)
10287 0 : XWRK = XDONT (IWRK)
10288 0 : Do IDCR = ICRS - 1, 1, - 1
10289 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
10290 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
10291 : Else
10292 : Exit
10293 : End If
10294 : End Do
10295 0 : IRNGT (IDCR + 1) = IWRK
10296 : End Do
10297 : !
10298 0 : XWRK1 = XDONT (IRNGT(NORD))
10299 0 : Do ICRS = NORD + 1, JLOW
10300 0 : If (XDONT(ILOWT (ICRS)) < XWRK1) Then
10301 0 : XWRK = XDONT (ILOWT (ICRS))
10302 0 : Do IDCR = NORD - 1, 1, - 1
10303 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
10304 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
10305 : End Do
10306 0 : IRNGT (IDCR + 1) = ILOWT (ICRS)
10307 0 : XWRK1 = XDONT (IRNGT(NORD))
10308 : End If
10309 : End Do
10310 : !
10311 0 : Return
10312 : !
10313 : !
10314 : Case (: -6)
10315 : !
10316 : ! last case: too many values in low part
10317 : !
10318 0 : IDEB = JDEB + 1
10319 0 : IMIL = (JLOW + IDEB) / 2
10320 0 : IFIN = JLOW
10321 : !
10322 : ! One chooses a pivot from 1st, last, and middle values
10323 : !
10324 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
10325 0 : IWRK = ILOWT (IDEB)
10326 0 : ILOWT (IDEB) = ILOWT (IMIL)
10327 0 : ILOWT (IMIL) = IWRK
10328 : End If
10329 0 : If (XDONT(ILOWT(IMIL)) > XDONT(ILOWT(IFIN))) Then
10330 0 : IWRK = ILOWT (IFIN)
10331 0 : ILOWT (IFIN) = ILOWT (IMIL)
10332 0 : ILOWT (IMIL) = IWRK
10333 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
10334 0 : IWRK = ILOWT (IDEB)
10335 0 : ILOWT (IDEB) = ILOWT (IMIL)
10336 0 : ILOWT (IMIL) = IWRK
10337 : End If
10338 : End If
10339 0 : If (IFIN <= 3) Exit
10340 : !
10341 0 : XPIV = XDONT (ILOWT(1)) + REAL(NORD, sp) / REAL(JLOW + NORD, sp) * &
10342 0 : (XDONT(ILOWT(IFIN)) - XDONT(ILOWT(1)))
10343 0 : If (JDEB > 0) Then
10344 0 : If (XPIV <= XPIV0) &
10345 : XPIV = XPIV0 + REAL(2 * NORD - JDEB, sp) / REAL(JLOW + NORD, sp) * &
10346 0 : (XDONT(ILOWT(IFIN)) - XPIV0)
10347 : Else
10348 : IDEB = 1
10349 : End If
10350 : !
10351 : ! One takes values > XPIV to IHIGT
10352 : ! However, we do not process the first values if we have been
10353 : ! through the case when we did not have enough low values
10354 : !
10355 0 : JHIG = 0
10356 0 : JLOW = JDEB
10357 : !
10358 0 : If (XDONT(ILOWT(IFIN)) > XPIV) Then
10359 : ICRS = JDEB
10360 : Do
10361 0 : ICRS = ICRS + 1
10362 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
10363 0 : JHIG = JHIG + 1
10364 0 : IHIGT (JHIG) = ILOWT (ICRS)
10365 0 : If (ICRS >= IFIN) Exit
10366 : Else
10367 0 : JLOW = JLOW + 1
10368 0 : ILOWT (JLOW) = ILOWT (ICRS)
10369 0 : If (JLOW >= NORD) Exit
10370 : End If
10371 : End Do
10372 : !
10373 0 : If (ICRS < IFIN) Then
10374 : Do
10375 0 : ICRS = ICRS + 1
10376 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
10377 0 : JLOW = JLOW + 1
10378 0 : ILOWT (JLOW) = ILOWT (ICRS)
10379 : Else
10380 0 : If (ICRS >= IFIN) Exit
10381 : End If
10382 : End Do
10383 : End If
10384 : Else
10385 0 : Do ICRS = IDEB, IFIN
10386 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
10387 0 : JHIG = JHIG + 1
10388 0 : IHIGT (JHIG) = ILOWT (ICRS)
10389 : Else
10390 0 : JLOW = JLOW + 1
10391 0 : ILOWT (JLOW) = ILOWT (ICRS)
10392 0 : If (JLOW >= NORD) Exit
10393 : End If
10394 : End Do
10395 : !
10396 0 : Do ICRS = ICRS + 1, IFIN
10397 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
10398 0 : JLOW = JLOW + 1
10399 0 : ILOWT (JLOW) = ILOWT (ICRS)
10400 : End If
10401 : End Do
10402 : End If
10403 : !
10404 : End Select
10405 : !
10406 : End Do
10407 : !
10408 : ! Now, we only need to complete ranking of the 1:NORD set
10409 : ! Assuming NORD is small, we use a simple insertion sort
10410 : !
10411 0 : IRNGT (1) = ILOWT (1)
10412 0 : Do ICRS = 2, NORD
10413 0 : IWRK = ILOWT (ICRS)
10414 0 : XWRK = XDONT (IWRK)
10415 0 : Do IDCR = ICRS - 1, 1, - 1
10416 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
10417 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
10418 : Else
10419 : Exit
10420 : End If
10421 : End Do
10422 0 : IRNGT (IDCR + 1) = IWRK
10423 : End Do
10424 : Return
10425 : !
10426 : !
10427 0 : End Subroutine R_rnkpar
10428 :
10429 0 : Subroutine I_rnkpar (XDONT, IRNGT, NORD)
10430 : ! Ranks partially XDONT by IRNGT, up to order NORD
10431 : ! __________________________________________________________
10432 : ! This routine uses a pivoting strategy such as the one of
10433 : ! finding the median based on the quicksort algorithm, but
10434 : ! we skew the pivot choice to try to bring it to NORD as
10435 : ! fast as possible. It uses 2 temporary arrays, where it
10436 : ! stores the indices of the values smaller than the pivot
10437 : ! (ILOWT), and the indices of values larger than the pivot
10438 : ! that we might still need later on (IHIGT). It iterates
10439 : ! until it can bring the number of values in ILOWT to
10440 : ! exactly NORD, and then uses an insertion sort to rank
10441 : ! this set, since it is supposedly small.
10442 : ! Michel Olagnon - Feb. 2000
10443 : ! __________________________________________________________
10444 : ! __________________________________________________________
10445 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
10446 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
10447 : Integer(kind = i4), Intent (In) :: NORD
10448 : ! __________________________________________________________
10449 : Integer(kind = i4) :: XPIV, XPIV0, XWRK, XWRK1, XMIN, XMAX
10450 : !
10451 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
10452 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
10453 : Integer(kind = i4) :: IDEB, JDEB, IMIL, IFIN, NWRK, ICRS, IDCR, ILOW
10454 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1
10455 : !
10456 0 : NDON = SIZE (XDONT)
10457 : !
10458 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
10459 : !
10460 0 : If (NDON < 2) Then
10461 0 : If (NORD >= 1) IRNGT (1) = 1
10462 0 : Return
10463 : End If
10464 : !
10465 : ! One chooses a pivot, best estimate possible to put fractile near
10466 : ! mid-point of the set of low values.
10467 : !
10468 0 : If (XDONT(2) < XDONT(1)) Then
10469 0 : ILOWT (1) = 2
10470 0 : IHIGT (1) = 1
10471 : Else
10472 0 : ILOWT (1) = 1
10473 0 : IHIGT (1) = 2
10474 : End If
10475 : !
10476 0 : If (NDON < 3) Then
10477 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
10478 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
10479 0 : Return
10480 : End If
10481 : !
10482 0 : If (XDONT(3) <= XDONT(IHIGT(1))) Then
10483 0 : IHIGT (2) = IHIGT (1)
10484 0 : If (XDONT(3) < XDONT(ILOWT(1))) Then
10485 0 : IHIGT (1) = ILOWT (1)
10486 0 : ILOWT (1) = 3
10487 : Else
10488 0 : IHIGT (1) = 3
10489 : End If
10490 : Else
10491 0 : IHIGT (2) = 3
10492 : End If
10493 : !
10494 0 : If (NDON < 4) Then
10495 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
10496 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
10497 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
10498 0 : Return
10499 : End If
10500 : !
10501 0 : If (XDONT(NDON) <= XDONT(IHIGT(1))) Then
10502 0 : IHIGT (3) = IHIGT (2)
10503 0 : IHIGT (2) = IHIGT (1)
10504 0 : If (XDONT(NDON) < XDONT(ILOWT(1))) Then
10505 0 : IHIGT (1) = ILOWT (1)
10506 0 : ILOWT (1) = NDON
10507 : Else
10508 0 : IHIGT (1) = NDON
10509 : End If
10510 : Else
10511 0 : if (XDONT (NDON) < XDONT (IHIGT(2))) Then
10512 0 : IHIGT (3) = IHIGT (2)
10513 0 : IHIGT (2) = NDON
10514 : else
10515 0 : IHIGT (3) = NDON
10516 : end if
10517 : End If
10518 : !
10519 0 : If (NDON < 5) Then
10520 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
10521 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
10522 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
10523 0 : If (NORD >= 4) IRNGT (4) = IHIGT (3)
10524 0 : Return
10525 : End If
10526 : !
10527 0 : JDEB = 0
10528 0 : IDEB = JDEB + 1
10529 0 : JLOW = IDEB
10530 0 : JHIG = 3
10531 0 : XPIV = XDONT (ILOWT(IDEB)) + INT(REAL(2 * NORD, sp) / REAL(NDON + NORD, sp), i4) * &
10532 0 : (XDONT(IHIGT(3)) - XDONT(ILOWT(IDEB)))
10533 0 : If (XPIV >= XDONT(IHIGT(1))) Then
10534 : XPIV = XDONT (ILOWT(IDEB)) + INT(REAL(2 * NORD, sp) / REAL(NDON + NORD, sp), i4) * &
10535 0 : (XDONT(IHIGT(2)) - XDONT(ILOWT(IDEB)))
10536 0 : If (XPIV >= XDONT(IHIGT(1))) &
10537 : XPIV = XDONT (ILOWT(IDEB)) + INT(REAL(2 * NORD, sp) / REAL(NDON + NORD, sp), i4) * &
10538 0 : (XDONT(IHIGT(1)) - XDONT(ILOWT(IDEB)))
10539 : End If
10540 0 : XPIV0 = XPIV
10541 : !
10542 : ! One puts values > pivot in the end and those <= pivot
10543 : ! at the beginning. This is split in 2 cases, so that
10544 : ! we can skip the loop test a number of times.
10545 : ! As we are also filling in the work arrays at the same time
10546 : ! we stop filling in the IHIGT array as soon as we have more
10547 : ! than enough values in ILOWT.
10548 : !
10549 : !
10550 0 : If (XDONT(NDON) > XPIV) Then
10551 : ICRS = 3
10552 : Do
10553 0 : ICRS = ICRS + 1
10554 0 : If (XDONT(ICRS) > XPIV) Then
10555 0 : If (ICRS >= NDON) Exit
10556 0 : JHIG = JHIG + 1
10557 0 : IHIGT (JHIG) = ICRS
10558 : Else
10559 0 : JLOW = JLOW + 1
10560 0 : ILOWT (JLOW) = ICRS
10561 0 : If (JLOW >= NORD) Exit
10562 : End If
10563 : End Do
10564 : !
10565 : ! One restricts further processing because it is no use
10566 : ! to store more high values
10567 : !
10568 0 : If (ICRS < NDON - 1) Then
10569 : Do
10570 0 : ICRS = ICRS + 1
10571 0 : If (XDONT(ICRS) <= XPIV) Then
10572 0 : JLOW = JLOW + 1
10573 0 : ILOWT (JLOW) = ICRS
10574 0 : Else If (ICRS >= NDON) Then
10575 : Exit
10576 : End If
10577 : End Do
10578 : End If
10579 : !
10580 : !
10581 : Else
10582 : !
10583 : ! Same as above, but this is not as easy to optimize, so the
10584 : ! DO-loop is kept
10585 : !
10586 0 : Do ICRS = 4, NDON - 1
10587 0 : If (XDONT(ICRS) > XPIV) Then
10588 0 : JHIG = JHIG + 1
10589 0 : IHIGT (JHIG) = ICRS
10590 : Else
10591 0 : JLOW = JLOW + 1
10592 0 : ILOWT (JLOW) = ICRS
10593 0 : If (JLOW >= NORD) Exit
10594 : End If
10595 : End Do
10596 : !
10597 0 : If (ICRS < NDON - 1) Then
10598 : Do
10599 0 : ICRS = ICRS + 1
10600 0 : If (XDONT(ICRS) <= XPIV) Then
10601 0 : If (ICRS >= NDON) Exit
10602 0 : JLOW = JLOW + 1
10603 0 : ILOWT (JLOW) = ICRS
10604 : End If
10605 : End Do
10606 : End If
10607 : End If
10608 : !
10609 : JLM2 = 0
10610 : JLM1 = 0
10611 : JHM2 = 0
10612 : JHM1 = 0
10613 : Do
10614 0 : if (JLOW == NORD) Exit
10615 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
10616 : !
10617 : ! We are oscillating. Perturbate by bringing JLOW closer by one
10618 : ! to NORD
10619 : !
10620 0 : If (NORD > JLOW) Then
10621 0 : XMIN = XDONT (IHIGT(1))
10622 0 : IHIG = 1
10623 0 : Do ICRS = 2, JHIG
10624 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
10625 0 : XMIN = XDONT (IHIGT(ICRS))
10626 0 : IHIG = ICRS
10627 : End If
10628 : End Do
10629 : !
10630 0 : JLOW = JLOW + 1
10631 0 : ILOWT (JLOW) = IHIGT (IHIG)
10632 0 : IHIGT (IHIG) = IHIGT (JHIG)
10633 0 : JHIG = JHIG - 1
10634 : Else
10635 0 : ILOW = ILOWT (JLOW)
10636 0 : XMAX = XDONT (ILOW)
10637 0 : Do ICRS = 1, JLOW
10638 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
10639 0 : IWRK = ILOWT (ICRS)
10640 0 : XMAX = XDONT (IWRK)
10641 0 : ILOWT (ICRS) = ILOW
10642 0 : ILOW = IWRK
10643 : End If
10644 : End Do
10645 0 : JLOW = JLOW - 1
10646 : End If
10647 : End If
10648 0 : JLM2 = JLM1
10649 0 : JLM1 = JLOW
10650 0 : JHM2 = JHM1
10651 0 : JHM1 = JHIG
10652 : !
10653 : ! We try to bring the number of values in the low values set
10654 : ! closer to NORD.
10655 : !
10656 0 : Select Case (NORD - JLOW)
10657 : Case (2 :)
10658 : !
10659 : ! Not enough values in low part, at least 2 are missing
10660 : !
10661 : Select Case (JHIG)
10662 : !!!!! CASE DEFAULT
10663 : !!!!! write (*,*) "Assertion failed"
10664 : !!!!! STOP
10665 : !
10666 : ! We make a special case when we have so few values in
10667 : ! the high values set that it is bad performance to choose a pivot
10668 : ! and apply the general algorithm.
10669 : !
10670 : Case (2)
10671 0 : If (XDONT(IHIGT(1)) <= XDONT(IHIGT(2))) Then
10672 0 : JLOW = JLOW + 1
10673 0 : ILOWT (JLOW) = IHIGT (1)
10674 0 : JLOW = JLOW + 1
10675 0 : ILOWT (JLOW) = IHIGT (2)
10676 : Else
10677 0 : JLOW = JLOW + 1
10678 0 : ILOWT (JLOW) = IHIGT (2)
10679 0 : JLOW = JLOW + 1
10680 0 : ILOWT (JLOW) = IHIGT (1)
10681 : End If
10682 : Exit
10683 : !
10684 : Case (3)
10685 : !
10686 : !
10687 0 : IWRK1 = IHIGT (1)
10688 0 : IWRK2 = IHIGT (2)
10689 0 : IWRK3 = IHIGT (3)
10690 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
10691 0 : IHIGT (1) = IWRK2
10692 0 : IHIGT (2) = IWRK1
10693 0 : IWRK2 = IWRK1
10694 : End If
10695 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
10696 0 : IHIGT (3) = IWRK2
10697 0 : IHIGT (2) = IWRK3
10698 0 : IWRK2 = IWRK3
10699 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
10700 0 : IHIGT (2) = IHIGT (1)
10701 0 : IHIGT (1) = IWRK2
10702 : End If
10703 : End If
10704 0 : JHIG = 0
10705 0 : Do ICRS = JLOW + 1, NORD
10706 0 : JHIG = JHIG + 1
10707 0 : ILOWT (ICRS) = IHIGT (JHIG)
10708 : End Do
10709 0 : JLOW = NORD
10710 : Exit
10711 : !
10712 : Case (4 :)
10713 : !
10714 : !
10715 0 : XPIV0 = XPIV
10716 0 : IFIN = JHIG
10717 : !
10718 : ! One chooses a pivot from the 2 first values and the last one.
10719 : ! This should ensure sufficient renewal between iterations to
10720 : ! avoid worst case behavior effects.
10721 : !
10722 0 : IWRK1 = IHIGT (1)
10723 0 : IWRK2 = IHIGT (2)
10724 0 : IWRK3 = IHIGT (IFIN)
10725 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
10726 0 : IHIGT (1) = IWRK2
10727 0 : IHIGT (2) = IWRK1
10728 0 : IWRK2 = IWRK1
10729 : End If
10730 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
10731 0 : IHIGT (IFIN) = IWRK2
10732 0 : IHIGT (2) = IWRK3
10733 0 : IWRK2 = IWRK3
10734 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
10735 0 : IHIGT (2) = IHIGT (1)
10736 0 : IHIGT (1) = IWRK2
10737 : End If
10738 : End If
10739 : !
10740 0 : JDEB = JLOW
10741 0 : NWRK = NORD - JLOW
10742 0 : IWRK1 = IHIGT (1)
10743 0 : JLOW = JLOW + 1
10744 0 : ILOWT (JLOW) = IWRK1
10745 0 : XPIV = XDONT (IWRK1) + INT(REAL(NWRK, sp) / REAL(NORD + NWRK, sp), i4) * &
10746 0 : (XDONT(IHIGT(IFIN)) - XDONT(IWRK1))
10747 : !
10748 : ! One takes values <= pivot to ILOWT
10749 : ! Again, 2 parts, one where we take care of the remaining
10750 : ! high values because we might still need them, and the
10751 : ! other when we know that we will have more than enough
10752 : ! low values in the end.
10753 : !
10754 0 : JHIG = 0
10755 0 : Do ICRS = 2, IFIN
10756 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
10757 0 : JLOW = JLOW + 1
10758 0 : ILOWT (JLOW) = IHIGT (ICRS)
10759 0 : If (JLOW >= NORD) Exit
10760 : Else
10761 0 : JHIG = JHIG + 1
10762 0 : IHIGT (JHIG) = IHIGT (ICRS)
10763 : End If
10764 : End Do
10765 : !
10766 0 : Do ICRS = ICRS + 1, IFIN
10767 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
10768 0 : JLOW = JLOW + 1
10769 0 : ILOWT (JLOW) = IHIGT (ICRS)
10770 : End If
10771 : End Do
10772 : End Select
10773 : !
10774 : !
10775 : Case (1)
10776 : !
10777 : ! Only 1 value is missing in low part
10778 : !
10779 0 : XMIN = XDONT (IHIGT(1))
10780 0 : IHIG = 1
10781 0 : Do ICRS = 2, JHIG
10782 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
10783 0 : XMIN = XDONT (IHIGT(ICRS))
10784 0 : IHIG = ICRS
10785 : End If
10786 : End Do
10787 : !
10788 0 : JLOW = JLOW + 1
10789 0 : ILOWT (JLOW) = IHIGT (IHIG)
10790 0 : Exit
10791 : !
10792 : !
10793 : Case (0)
10794 : !
10795 : ! Low part is exactly what we want
10796 : !
10797 0 : Exit
10798 : !
10799 : !
10800 : Case (-5 : -1)
10801 : !
10802 : ! Only few values too many in low part
10803 : !
10804 0 : IRNGT (1) = ILOWT (1)
10805 0 : Do ICRS = 2, NORD
10806 0 : IWRK = ILOWT (ICRS)
10807 0 : XWRK = XDONT (IWRK)
10808 0 : Do IDCR = ICRS - 1, 1, - 1
10809 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
10810 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
10811 : Else
10812 : Exit
10813 : End If
10814 : End Do
10815 0 : IRNGT (IDCR + 1) = IWRK
10816 : End Do
10817 : !
10818 0 : XWRK1 = XDONT (IRNGT(NORD))
10819 0 : Do ICRS = NORD + 1, JLOW
10820 0 : If (XDONT(ILOWT (ICRS)) < XWRK1) Then
10821 0 : XWRK = XDONT (ILOWT (ICRS))
10822 0 : Do IDCR = NORD - 1, 1, - 1
10823 0 : If (XWRK >= XDONT(IRNGT(IDCR))) Exit
10824 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
10825 : End Do
10826 0 : IRNGT (IDCR + 1) = ILOWT (ICRS)
10827 0 : XWRK1 = XDONT (IRNGT(NORD))
10828 : End If
10829 : End Do
10830 : !
10831 0 : Return
10832 : !
10833 : !
10834 : Case (: -6)
10835 : !
10836 : ! last case: too many values in low part
10837 : !
10838 0 : IDEB = JDEB + 1
10839 0 : IMIL = (JLOW + IDEB) / 2
10840 0 : IFIN = JLOW
10841 : !
10842 : ! One chooses a pivot from 1st, last, and middle values
10843 : !
10844 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
10845 0 : IWRK = ILOWT (IDEB)
10846 0 : ILOWT (IDEB) = ILOWT (IMIL)
10847 0 : ILOWT (IMIL) = IWRK
10848 : End If
10849 0 : If (XDONT(ILOWT(IMIL)) > XDONT(ILOWT(IFIN))) Then
10850 0 : IWRK = ILOWT (IFIN)
10851 0 : ILOWT (IFIN) = ILOWT (IMIL)
10852 0 : ILOWT (IMIL) = IWRK
10853 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
10854 0 : IWRK = ILOWT (IDEB)
10855 0 : ILOWT (IDEB) = ILOWT (IMIL)
10856 0 : ILOWT (IMIL) = IWRK
10857 : End If
10858 : End If
10859 0 : If (IFIN <= 3) Exit
10860 : !
10861 0 : XPIV = XDONT (ILOWT(1)) + INT(REAL(NORD, sp) / REAL(JLOW + NORD, sp), i4) * &
10862 0 : (XDONT(ILOWT(IFIN)) - XDONT(ILOWT(1)))
10863 0 : If (JDEB > 0) Then
10864 0 : If (XPIV <= XPIV0) &
10865 : XPIV = XPIV0 + INT(REAL(2 * NORD - JDEB, sp) / REAL(JLOW + NORD, sp), i4) * &
10866 0 : (XDONT(ILOWT(IFIN)) - XPIV0)
10867 : Else
10868 : IDEB = 1
10869 : End If
10870 : !
10871 : ! One takes values > XPIV to IHIGT
10872 : ! However, we do not process the first values if we have been
10873 : ! through the case when we did not have enough low values
10874 : !
10875 0 : JHIG = 0
10876 0 : JLOW = JDEB
10877 : !
10878 0 : If (XDONT(ILOWT(IFIN)) > XPIV) Then
10879 : ICRS = JDEB
10880 : Do
10881 0 : ICRS = ICRS + 1
10882 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
10883 0 : JHIG = JHIG + 1
10884 0 : IHIGT (JHIG) = ILOWT (ICRS)
10885 0 : If (ICRS >= IFIN) Exit
10886 : Else
10887 0 : JLOW = JLOW + 1
10888 0 : ILOWT (JLOW) = ILOWT (ICRS)
10889 0 : If (JLOW >= NORD) Exit
10890 : End If
10891 : End Do
10892 : !
10893 0 : If (ICRS < IFIN) Then
10894 : Do
10895 0 : ICRS = ICRS + 1
10896 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
10897 0 : JLOW = JLOW + 1
10898 0 : ILOWT (JLOW) = ILOWT (ICRS)
10899 : Else
10900 0 : If (ICRS >= IFIN) Exit
10901 : End If
10902 : End Do
10903 : End If
10904 : Else
10905 0 : Do ICRS = IDEB, IFIN
10906 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
10907 0 : JHIG = JHIG + 1
10908 0 : IHIGT (JHIG) = ILOWT (ICRS)
10909 : Else
10910 0 : JLOW = JLOW + 1
10911 0 : ILOWT (JLOW) = ILOWT (ICRS)
10912 0 : If (JLOW >= NORD) Exit
10913 : End If
10914 : End Do
10915 : !
10916 0 : Do ICRS = ICRS + 1, IFIN
10917 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
10918 0 : JLOW = JLOW + 1
10919 0 : ILOWT (JLOW) = ILOWT (ICRS)
10920 : End If
10921 : End Do
10922 : End If
10923 : !
10924 : End Select
10925 : !
10926 : End Do
10927 : !
10928 : ! Now, we only need to complete ranking of the 1:NORD set
10929 : ! Assuming NORD is small, we use a simple insertion sort
10930 : !
10931 0 : IRNGT (1) = ILOWT (1)
10932 0 : Do ICRS = 2, NORD
10933 0 : IWRK = ILOWT (ICRS)
10934 0 : XWRK = XDONT (IWRK)
10935 0 : Do IDCR = ICRS - 1, 1, - 1
10936 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
10937 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
10938 : Else
10939 : Exit
10940 : End If
10941 : End Do
10942 0 : IRNGT (IDCR + 1) = IWRK
10943 : End Do
10944 : Return
10945 : !
10946 : !
10947 0 : End Subroutine I_rnkpar
10948 :
10949 0 : Subroutine D_uniinv (XDONT, IGOEST)
10950 : ! __________________________________________________________
10951 : ! UNIINV = Merge-sort inverse ranking of an array, with removal of
10952 : ! duplicate entries.
10953 : ! The routine is similar to pure merge-sort ranking, but on
10954 : ! the last pass, it sets indices in IGOEST to the rank
10955 : ! of the value in the ordered set with duplicates removed.
10956 : ! For performance reasons, the first 2 passes are taken
10957 : ! out of the standard loop, and use dedicated coding.
10958 : ! __________________________________________________________
10959 : ! __________________________________________________________
10960 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
10961 : Integer(kind = i4), Dimension (:), Intent (Out) :: IGOEST
10962 : ! __________________________________________________________
10963 0 : real(kind = dp) :: XTST, XDONA, XDONB
10964 : !
10965 : ! __________________________________________________________
10966 0 : Integer(kind = i4), Dimension (SIZE(IGOEST)) :: JWRKT, IRNGT
10967 : Integer(kind = i4) :: LMTNA, LMTNC, IRNG, IRNG1, IRNG2, NUNI
10968 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
10969 : !
10970 0 : NVAL = Min (SIZE(XDONT), SIZE(IGOEST))
10971 : !
10972 : Select Case (NVAL)
10973 : Case (: 0)
10974 0 : Return
10975 : Case (1)
10976 0 : IGOEST (1) = 1
10977 0 : Return
10978 : Case Default
10979 :
10980 : End Select
10981 : !
10982 : ! Fill-in the index array, creating ordered couples
10983 : !
10984 0 : Do IIND = 2, NVAL, 2
10985 0 : If (XDONT(IIND - 1) < XDONT(IIND)) Then
10986 0 : IRNGT (IIND - 1) = IIND - 1
10987 0 : IRNGT (IIND) = IIND
10988 : Else
10989 0 : IRNGT (IIND - 1) = IIND
10990 0 : IRNGT (IIND) = IIND - 1
10991 : End If
10992 : End Do
10993 0 : If (Modulo (NVAL, 2) /= 0) Then
10994 0 : IRNGT (NVAL) = NVAL
10995 : End If
10996 : !
10997 : ! We will now have ordered subsets A - B - A - B - ...
10998 : ! and merge A and B couples into C - C - ...
10999 : !
11000 0 : LMTNA = 2
11001 0 : LMTNC = 4
11002 : !
11003 : ! First iteration. The length of the ordered subsets goes from 2 to 4
11004 : !
11005 : Do
11006 0 : If (NVAL <= 4) Exit
11007 : !
11008 : ! Loop on merges of A and B into C
11009 : !
11010 0 : Do IWRKD = 0, NVAL - 1, 4
11011 0 : If ((IWRKD + 4) > NVAL) Then
11012 0 : If ((IWRKD + 2) >= NVAL) Exit
11013 : !
11014 : ! 1 2 3
11015 : !
11016 0 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Exit
11017 : !
11018 : ! 1 3 2
11019 : !
11020 0 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
11021 0 : IRNG2 = IRNGT (IWRKD + 2)
11022 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
11023 0 : IRNGT (IWRKD + 3) = IRNG2
11024 : !
11025 : ! 3 1 2
11026 : !
11027 : Else
11028 0 : IRNG1 = IRNGT (IWRKD + 1)
11029 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
11030 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 2)
11031 0 : IRNGT (IWRKD + 2) = IRNG1
11032 : End If
11033 : If (.true.) Exit ! Exit ! JM
11034 : End If
11035 : !
11036 : ! 1 2 3 4
11037 : !
11038 0 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Cycle
11039 : !
11040 : ! 1 3 x x
11041 : !
11042 0 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
11043 0 : IRNG2 = IRNGT (IWRKD + 2)
11044 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
11045 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
11046 : ! 1 3 2 4
11047 0 : IRNGT (IWRKD + 3) = IRNG2
11048 : Else
11049 : ! 1 3 4 2
11050 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
11051 0 : IRNGT (IWRKD + 4) = IRNG2
11052 : End If
11053 : !
11054 : ! 3 x x x
11055 : !
11056 : Else
11057 0 : IRNG1 = IRNGT (IWRKD + 1)
11058 0 : IRNG2 = IRNGT (IWRKD + 2)
11059 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
11060 0 : If (XDONT(IRNG1) <= XDONT(IRNGT(IWRKD + 4))) Then
11061 0 : IRNGT (IWRKD + 2) = IRNG1
11062 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
11063 : ! 3 1 2 4
11064 0 : IRNGT (IWRKD + 3) = IRNG2
11065 : Else
11066 : ! 3 1 4 2
11067 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
11068 0 : IRNGT (IWRKD + 4) = IRNG2
11069 : End If
11070 : Else
11071 : ! 3 4 1 2
11072 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 4)
11073 0 : IRNGT (IWRKD + 3) = IRNG1
11074 0 : IRNGT (IWRKD + 4) = IRNG2
11075 : End If
11076 : End If
11077 : End Do
11078 : !
11079 : ! The Cs become As and Bs
11080 : !
11081 : LMTNA = 4
11082 0 : If (.true.) Exit ! Exit ! JM
11083 : End Do
11084 : !
11085 : ! Iteration loop. Each time, the length of the ordered subsets
11086 : ! is doubled.
11087 : !
11088 : Do
11089 0 : If (2 * LMTNA >= NVAL) Exit
11090 0 : IWRKF = 0
11091 0 : LMTNC = 2 * LMTNC
11092 : !
11093 : ! Loop on merges of A and B into C
11094 : !
11095 : Do
11096 0 : IWRK = IWRKF
11097 0 : IWRKD = IWRKF + 1
11098 0 : JINDA = IWRKF + LMTNA
11099 0 : IWRKF = IWRKF + LMTNC
11100 0 : If (IWRKF >= NVAL) Then
11101 0 : If (JINDA >= NVAL) Exit
11102 : IWRKF = NVAL
11103 : End If
11104 0 : IINDA = 1
11105 0 : IINDB = JINDA + 1
11106 : !
11107 : ! One steps in the C subset, that we create in the final rank array
11108 : !
11109 : ! Make a copy of the rank array for the iteration
11110 : !
11111 0 : JWRKT (1 : LMTNA) = IRNGT (IWRKD : JINDA)
11112 0 : XDONA = XDONT (JWRKT(IINDA))
11113 0 : XDONB = XDONT (IRNGT(IINDB))
11114 : !
11115 0 : Do
11116 0 : IWRK = IWRK + 1
11117 : !
11118 : ! We still have unprocessed values in both A and B
11119 : !
11120 0 : If (XDONA > XDONB) Then
11121 0 : IRNGT (IWRK) = IRNGT (IINDB)
11122 0 : IINDB = IINDB + 1
11123 0 : If (IINDB > IWRKF) Then
11124 : ! Only A still with unprocessed values
11125 0 : IRNGT (IWRK + 1 : IWRKF) = JWRKT (IINDA : LMTNA)
11126 : Exit
11127 : End If
11128 0 : XDONB = XDONT (IRNGT(IINDB))
11129 : Else
11130 0 : IRNGT (IWRK) = JWRKT (IINDA)
11131 0 : IINDA = IINDA + 1
11132 0 : If (IINDA > LMTNA) Exit! Only B still with unprocessed values
11133 0 : XDONA = XDONT (JWRKT(IINDA))
11134 : End If
11135 : !
11136 : End Do
11137 : End Do
11138 : !
11139 : ! The Cs become As and Bs
11140 : !
11141 0 : LMTNA = 2 * LMTNA
11142 : End Do
11143 : !
11144 : ! Last merge of A and B into C, with removal of duplicates.
11145 : !
11146 0 : IINDA = 1
11147 0 : IINDB = LMTNA + 1
11148 0 : NUNI = 0
11149 : !
11150 : ! One steps in the C subset, that we create in the final rank array
11151 : !
11152 0 : JWRKT (1 : LMTNA) = IRNGT (1 : LMTNA)
11153 0 : If (IINDB <= NVAL) Then
11154 0 : XTST = NEARLESS (Min(XDONT(JWRKT(1)), XDONT(IRNGT(IINDB))))
11155 : Else
11156 0 : XTST = NEARLESS (XDONT(JWRKT(1)))
11157 : end if
11158 0 : Do IWRK = 1, NVAL
11159 : !
11160 : ! We still have unprocessed values in both A and B
11161 : !
11162 0 : If (IINDA <= LMTNA) Then
11163 0 : If (IINDB <= NVAL) Then
11164 0 : If (XDONT(JWRKT(IINDA)) > XDONT(IRNGT(IINDB))) Then
11165 0 : IRNG = IRNGT (IINDB)
11166 0 : IINDB = IINDB + 1
11167 : Else
11168 0 : IRNG = JWRKT (IINDA)
11169 0 : IINDA = IINDA + 1
11170 : End If
11171 : Else
11172 : !
11173 : ! Only A still with unprocessed values
11174 : !
11175 0 : IRNG = JWRKT (IINDA)
11176 0 : IINDA = IINDA + 1
11177 : End If
11178 : Else
11179 : !
11180 : ! Only B still with unprocessed values
11181 : !
11182 0 : IRNG = IRNGT (IWRK)
11183 : End If
11184 0 : If (XDONT(IRNG) > XTST) Then
11185 0 : XTST = XDONT (IRNG)
11186 0 : NUNI = NUNI + 1
11187 : End If
11188 0 : IGOEST (IRNG) = NUNI
11189 : !
11190 : End Do
11191 : !
11192 : Return
11193 : !
11194 0 : End Subroutine D_uniinv
11195 :
11196 0 : Subroutine R_uniinv (XDONT, IGOEST)
11197 : ! __________________________________________________________
11198 : ! UNIINV = Merge-sort inverse ranking of an array, with removal of
11199 : ! duplicate entries.
11200 : ! The routine is similar to pure merge-sort ranking, but on
11201 : ! the last pass, it sets indices in IGOEST to the rank
11202 : ! of the value in the ordered set with duplicates removed.
11203 : ! For performance reasons, the first 2 passes are taken
11204 : ! out of the standard loop, and use dedicated coding.
11205 : ! __________________________________________________________
11206 : ! _________________________________________________________
11207 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
11208 : Integer(kind = i4), Dimension (:), Intent (Out) :: IGOEST
11209 : ! __________________________________________________________
11210 0 : Real(kind = sp) :: XTST, XDONA, XDONB
11211 : !
11212 : ! __________________________________________________________
11213 0 : Integer(kind = i4), Dimension (SIZE(IGOEST)) :: JWRKT, IRNGT
11214 : Integer(kind = i4) :: LMTNA, LMTNC, IRNG, IRNG1, IRNG2, NUNI
11215 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
11216 : !
11217 0 : NVAL = Min (SIZE(XDONT), SIZE(IGOEST))
11218 : !
11219 : Select Case (NVAL)
11220 : Case (: 0)
11221 0 : Return
11222 : Case (1)
11223 0 : IGOEST (1) = 1
11224 0 : Return
11225 : Case Default
11226 :
11227 : End Select
11228 : !
11229 : ! Fill-in the index array, creating ordered couples
11230 : !
11231 0 : Do IIND = 2, NVAL, 2
11232 0 : If (XDONT(IIND - 1) < XDONT(IIND)) Then
11233 0 : IRNGT (IIND - 1) = IIND - 1
11234 0 : IRNGT (IIND) = IIND
11235 : Else
11236 0 : IRNGT (IIND - 1) = IIND
11237 0 : IRNGT (IIND) = IIND - 1
11238 : End If
11239 : End Do
11240 0 : If (Modulo (NVAL, 2) /= 0) Then
11241 0 : IRNGT (NVAL) = NVAL
11242 : End If
11243 : !
11244 : ! We will now have ordered subsets A - B - A - B - ...
11245 : ! and merge A and B couples into C - C - ...
11246 : !
11247 0 : LMTNA = 2
11248 0 : LMTNC = 4
11249 : !
11250 : ! First iteration. The length of the ordered subsets goes from 2 to 4
11251 : !
11252 : Do
11253 0 : If (NVAL <= 4) Exit
11254 : !
11255 : ! Loop on merges of A and B into C
11256 : !
11257 0 : Do IWRKD = 0, NVAL - 1, 4
11258 0 : If ((IWRKD + 4) > NVAL) Then
11259 0 : If ((IWRKD + 2) >= NVAL) Exit
11260 : !
11261 : ! 1 2 3
11262 : !
11263 0 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Exit
11264 : !
11265 : ! 1 3 2
11266 : !
11267 0 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
11268 0 : IRNG2 = IRNGT (IWRKD + 2)
11269 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
11270 0 : IRNGT (IWRKD + 3) = IRNG2
11271 : !
11272 : ! 3 1 2
11273 : !
11274 : Else
11275 0 : IRNG1 = IRNGT (IWRKD + 1)
11276 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
11277 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 2)
11278 0 : IRNGT (IWRKD + 2) = IRNG1
11279 : End If
11280 : If (.true.) Exit ! Exit ! JM
11281 : End If
11282 : !
11283 : ! 1 2 3 4
11284 : !
11285 0 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Cycle
11286 : !
11287 : ! 1 3 x x
11288 : !
11289 0 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
11290 0 : IRNG2 = IRNGT (IWRKD + 2)
11291 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
11292 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
11293 : ! 1 3 2 4
11294 0 : IRNGT (IWRKD + 3) = IRNG2
11295 : Else
11296 : ! 1 3 4 2
11297 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
11298 0 : IRNGT (IWRKD + 4) = IRNG2
11299 : End If
11300 : !
11301 : ! 3 x x x
11302 : !
11303 : Else
11304 0 : IRNG1 = IRNGT (IWRKD + 1)
11305 0 : IRNG2 = IRNGT (IWRKD + 2)
11306 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
11307 0 : If (XDONT(IRNG1) <= XDONT(IRNGT(IWRKD + 4))) Then
11308 0 : IRNGT (IWRKD + 2) = IRNG1
11309 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
11310 : ! 3 1 2 4
11311 0 : IRNGT (IWRKD + 3) = IRNG2
11312 : Else
11313 : ! 3 1 4 2
11314 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
11315 0 : IRNGT (IWRKD + 4) = IRNG2
11316 : End If
11317 : Else
11318 : ! 3 4 1 2
11319 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 4)
11320 0 : IRNGT (IWRKD + 3) = IRNG1
11321 0 : IRNGT (IWRKD + 4) = IRNG2
11322 : End If
11323 : End If
11324 : End Do
11325 : !
11326 : ! The Cs become As and Bs
11327 : !
11328 : LMTNA = 4
11329 0 : If (.true.) Exit ! Exit ! JM
11330 : End Do
11331 : !
11332 : ! Iteration loop. Each time, the length of the ordered subsets
11333 : ! is doubled.
11334 : !
11335 : Do
11336 0 : If (2 * LMTNA >= NVAL) Exit
11337 0 : IWRKF = 0
11338 0 : LMTNC = 2 * LMTNC
11339 : !
11340 : ! Loop on merges of A and B into C
11341 : !
11342 : Do
11343 0 : IWRK = IWRKF
11344 0 : IWRKD = IWRKF + 1
11345 0 : JINDA = IWRKF + LMTNA
11346 0 : IWRKF = IWRKF + LMTNC
11347 0 : If (IWRKF >= NVAL) Then
11348 0 : If (JINDA >= NVAL) Exit
11349 : IWRKF = NVAL
11350 : End If
11351 0 : IINDA = 1
11352 0 : IINDB = JINDA + 1
11353 : !
11354 : ! One steps in the C subset, that we create in the final rank array
11355 : !
11356 : ! Make a copy of the rank array for the iteration
11357 : !
11358 0 : JWRKT (1 : LMTNA) = IRNGT (IWRKD : JINDA)
11359 0 : XDONA = XDONT (JWRKT(IINDA))
11360 0 : XDONB = XDONT (IRNGT(IINDB))
11361 : !
11362 0 : Do
11363 0 : IWRK = IWRK + 1
11364 : !
11365 : ! We still have unprocessed values in both A and B
11366 : !
11367 0 : If (XDONA > XDONB) Then
11368 0 : IRNGT (IWRK) = IRNGT (IINDB)
11369 0 : IINDB = IINDB + 1
11370 0 : If (IINDB > IWRKF) Then
11371 : ! Only A still with unprocessed values
11372 0 : IRNGT (IWRK + 1 : IWRKF) = JWRKT (IINDA : LMTNA)
11373 : Exit
11374 : End If
11375 0 : XDONB = XDONT (IRNGT(IINDB))
11376 : Else
11377 0 : IRNGT (IWRK) = JWRKT (IINDA)
11378 0 : IINDA = IINDA + 1
11379 0 : If (IINDA > LMTNA) Exit! Only B still with unprocessed values
11380 0 : XDONA = XDONT (JWRKT(IINDA))
11381 : End If
11382 : !
11383 : End Do
11384 : End Do
11385 : !
11386 : ! The Cs become As and Bs
11387 : !
11388 0 : LMTNA = 2 * LMTNA
11389 : End Do
11390 : !
11391 : ! Last merge of A and B into C, with removal of duplicates.
11392 : !
11393 0 : IINDA = 1
11394 0 : IINDB = LMTNA + 1
11395 0 : NUNI = 0
11396 : !
11397 : ! One steps in the C subset, that we create in the final rank array
11398 : !
11399 0 : JWRKT (1 : LMTNA) = IRNGT (1 : LMTNA)
11400 0 : If (IINDB <= NVAL) Then
11401 0 : XTST = NEARLESS (Min(XDONT(JWRKT(1)), XDONT(IRNGT(IINDB))))
11402 : Else
11403 0 : XTST = NEARLESS (XDONT(JWRKT(1)))
11404 : end if
11405 0 : Do IWRK = 1, NVAL
11406 : !
11407 : ! We still have unprocessed values in both A and B
11408 : !
11409 0 : If (IINDA <= LMTNA) Then
11410 0 : If (IINDB <= NVAL) Then
11411 0 : If (XDONT(JWRKT(IINDA)) > XDONT(IRNGT(IINDB))) Then
11412 0 : IRNG = IRNGT (IINDB)
11413 0 : IINDB = IINDB + 1
11414 : Else
11415 0 : IRNG = JWRKT (IINDA)
11416 0 : IINDA = IINDA + 1
11417 : End If
11418 : Else
11419 : !
11420 : ! Only A still with unprocessed values
11421 : !
11422 0 : IRNG = JWRKT (IINDA)
11423 0 : IINDA = IINDA + 1
11424 : End If
11425 : Else
11426 : !
11427 : ! Only B still with unprocessed values
11428 : !
11429 0 : IRNG = IRNGT (IWRK)
11430 : End If
11431 0 : If (XDONT(IRNG) > XTST) Then
11432 0 : XTST = XDONT (IRNG)
11433 0 : NUNI = NUNI + 1
11434 : End If
11435 0 : IGOEST (IRNG) = NUNI
11436 : !
11437 : End Do
11438 : !
11439 : Return
11440 : !
11441 0 : End Subroutine R_uniinv
11442 :
11443 8 : Subroutine I_uniinv (XDONT, IGOEST)
11444 : ! __________________________________________________________
11445 : ! UNIINV = Merge-sort inverse ranking of an array, with removal of
11446 : ! duplicate entries.
11447 : ! The routine is similar to pure merge-sort ranking, but on
11448 : ! the last pass, it sets indices in IGOEST to the rank
11449 : ! of the value in the ordered set with duplicates removed.
11450 : ! For performance reasons, the first 2 passes are taken
11451 : ! out of the standard loop, and use dedicated coding.
11452 : ! __________________________________________________________
11453 : ! __________________________________________________________
11454 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
11455 : Integer(kind = i4), Dimension (:), Intent (Out) :: IGOEST
11456 : ! __________________________________________________________
11457 : Integer(kind = i4) :: XTST, XDONA, XDONB
11458 : !
11459 : ! __________________________________________________________
11460 4 : Integer(kind = i4), Dimension (SIZE(IGOEST)) :: JWRKT, IRNGT
11461 : Integer(kind = i4) :: LMTNA, LMTNC, IRNG, IRNG1, IRNG2, NUNI
11462 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
11463 : !
11464 4 : NVAL = Min (SIZE(XDONT), SIZE(IGOEST))
11465 : !
11466 : Select Case (NVAL)
11467 : Case (: 0)
11468 0 : Return
11469 : Case (1)
11470 0 : IGOEST (1) = 1
11471 4 : Return
11472 : Case Default
11473 :
11474 : End Select
11475 : !
11476 : ! Fill-in the index array, creating ordered couples
11477 : !
11478 20 : Do IIND = 2, NVAL, 2
11479 20 : If (XDONT(IIND - 1) < XDONT(IIND)) Then
11480 4 : IRNGT (IIND - 1) = IIND - 1
11481 4 : IRNGT (IIND) = IIND
11482 : Else
11483 12 : IRNGT (IIND - 1) = IIND
11484 12 : IRNGT (IIND) = IIND - 1
11485 : End If
11486 : End Do
11487 4 : If (Modulo (NVAL, 2) /= 0) Then
11488 4 : IRNGT (NVAL) = NVAL
11489 : End If
11490 : !
11491 : ! We will now have ordered subsets A - B - A - B - ...
11492 : ! and merge A and B couples into C - C - ...
11493 : !
11494 4 : LMTNA = 2
11495 4 : LMTNC = 4
11496 : !
11497 : ! First iteration. The length of the ordered subsets goes from 2 to 4
11498 : !
11499 : Do
11500 4 : If (NVAL <= 4) Exit
11501 : !
11502 : ! Loop on merges of A and B into C
11503 : !
11504 12 : Do IWRKD = 0, NVAL - 1, 4
11505 12 : If ((IWRKD + 4) > NVAL) Then
11506 4 : If ((IWRKD + 2) >= NVAL) Exit
11507 : !
11508 : ! 1 2 3
11509 : !
11510 0 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Exit
11511 : !
11512 : ! 1 3 2
11513 : !
11514 0 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
11515 0 : IRNG2 = IRNGT (IWRKD + 2)
11516 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
11517 0 : IRNGT (IWRKD + 3) = IRNG2
11518 : !
11519 : ! 3 1 2
11520 : !
11521 : Else
11522 0 : IRNG1 = IRNGT (IWRKD + 1)
11523 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
11524 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 2)
11525 0 : IRNGT (IWRKD + 2) = IRNG1
11526 : End If
11527 : If (.true.) Exit ! Exit ! JM
11528 : End If
11529 : !
11530 : ! 1 2 3 4
11531 : !
11532 8 : If (XDONT(IRNGT(IWRKD + 2)) <= XDONT(IRNGT(IWRKD + 3))) Cycle
11533 : !
11534 : ! 1 3 x x
11535 : !
11536 12 : If (XDONT(IRNGT(IWRKD + 1)) <= XDONT(IRNGT(IWRKD + 3))) Then
11537 4 : IRNG2 = IRNGT (IWRKD + 2)
11538 4 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
11539 4 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
11540 : ! 1 3 2 4
11541 4 : IRNGT (IWRKD + 3) = IRNG2
11542 : Else
11543 : ! 1 3 4 2
11544 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
11545 0 : IRNGT (IWRKD + 4) = IRNG2
11546 : End If
11547 : !
11548 : ! 3 x x x
11549 : !
11550 : Else
11551 4 : IRNG1 = IRNGT (IWRKD + 1)
11552 4 : IRNG2 = IRNGT (IWRKD + 2)
11553 4 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
11554 4 : If (XDONT(IRNG1) <= XDONT(IRNGT(IWRKD + 4))) Then
11555 0 : IRNGT (IWRKD + 2) = IRNG1
11556 0 : If (XDONT(IRNG2) <= XDONT(IRNGT(IWRKD + 4))) Then
11557 : ! 3 1 2 4
11558 0 : IRNGT (IWRKD + 3) = IRNG2
11559 : Else
11560 : ! 3 1 4 2
11561 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
11562 0 : IRNGT (IWRKD + 4) = IRNG2
11563 : End If
11564 : Else
11565 : ! 3 4 1 2
11566 4 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 4)
11567 4 : IRNGT (IWRKD + 3) = IRNG1
11568 4 : IRNGT (IWRKD + 4) = IRNG2
11569 : End If
11570 : End If
11571 : End Do
11572 : !
11573 : ! The Cs become As and Bs
11574 : !
11575 : LMTNA = 4
11576 0 : If (.true.) Exit ! Exit ! JM
11577 : End Do
11578 : !
11579 : ! Iteration loop. Each time, the length of the ordered subsets
11580 : ! is doubled.
11581 : !
11582 : Do
11583 8 : If (2 * LMTNA >= NVAL) Exit
11584 4 : IWRKF = 0
11585 4 : LMTNC = 2 * LMTNC
11586 : !
11587 : ! Loop on merges of A and B into C
11588 : !
11589 : Do
11590 8 : IWRK = IWRKF
11591 8 : IWRKD = IWRKF + 1
11592 8 : JINDA = IWRKF + LMTNA
11593 8 : IWRKF = IWRKF + LMTNC
11594 8 : If (IWRKF >= NVAL) Then
11595 4 : If (JINDA >= NVAL) Exit
11596 : IWRKF = NVAL
11597 : End If
11598 4 : IINDA = 1
11599 4 : IINDB = JINDA + 1
11600 : !
11601 : ! One steps in the C subset, that we create in the final rank array
11602 : !
11603 : ! Make a copy of the rank array for the iteration
11604 : !
11605 20 : JWRKT (1 : LMTNA) = IRNGT (IWRKD : JINDA)
11606 4 : XDONA = XDONT (JWRKT(IINDA))
11607 4 : XDONB = XDONT (IRNGT(IINDB))
11608 : !
11609 4 : Do
11610 28 : IWRK = IWRK + 1
11611 : !
11612 : ! We still have unprocessed values in both A and B
11613 : !
11614 32 : If (XDONA > XDONB) Then
11615 12 : IRNGT (IWRK) = IRNGT (IINDB)
11616 12 : IINDB = IINDB + 1
11617 12 : If (IINDB > IWRKF) Then
11618 : ! Only A still with unprocessed values
11619 0 : IRNGT (IWRK + 1 : IWRKF) = JWRKT (IINDA : LMTNA)
11620 : Exit
11621 : End If
11622 12 : XDONB = XDONT (IRNGT(IINDB))
11623 : Else
11624 16 : IRNGT (IWRK) = JWRKT (IINDA)
11625 16 : IINDA = IINDA + 1
11626 16 : If (IINDA > LMTNA) Exit! Only B still with unprocessed values
11627 12 : XDONA = XDONT (JWRKT(IINDA))
11628 : End If
11629 : !
11630 : End Do
11631 : End Do
11632 : !
11633 : ! The Cs become As and Bs
11634 : !
11635 4 : LMTNA = 2 * LMTNA
11636 : End Do
11637 : !
11638 : ! Last merge of A and B into C, with removal of duplicates.
11639 : !
11640 4 : IINDA = 1
11641 4 : IINDB = LMTNA + 1
11642 4 : NUNI = 0
11643 : !
11644 : ! One steps in the C subset, that we create in the final rank array
11645 : !
11646 36 : JWRKT (1 : LMTNA) = IRNGT (1 : LMTNA)
11647 4 : If (IINDB <= NVAL) Then
11648 4 : XTST = NEARLESS (Min(XDONT(JWRKT(1)), XDONT(IRNGT(IINDB))))
11649 : Else
11650 0 : XTST = NEARLESS (XDONT(JWRKT(1)))
11651 : end if
11652 40 : Do IWRK = 1, NVAL
11653 : !
11654 : ! We still have unprocessed values in both A and B
11655 : !
11656 36 : If (IINDA <= LMTNA) Then
11657 32 : If (IINDB <= NVAL) Then
11658 32 : If (XDONT(JWRKT(IINDA)) > XDONT(IRNGT(IINDB))) Then
11659 0 : IRNG = IRNGT (IINDB)
11660 0 : IINDB = IINDB + 1
11661 : Else
11662 32 : IRNG = JWRKT (IINDA)
11663 32 : IINDA = IINDA + 1
11664 : End If
11665 : Else
11666 : !
11667 : ! Only A still with unprocessed values
11668 : !
11669 0 : IRNG = JWRKT (IINDA)
11670 0 : IINDA = IINDA + 1
11671 : End If
11672 : Else
11673 : !
11674 : ! Only B still with unprocessed values
11675 : !
11676 4 : IRNG = IRNGT (IWRK)
11677 : End If
11678 36 : If (XDONT(IRNG) > XTST) Then
11679 12 : XTST = XDONT (IRNG)
11680 12 : NUNI = NUNI + 1
11681 : End If
11682 40 : IGOEST (IRNG) = NUNI
11683 : !
11684 : End Do
11685 : !
11686 : Return
11687 : !
11688 0 : End Subroutine I_uniinv
11689 :
11690 0 : Function D_nearless (XVAL) result (D_nl)
11691 : ! Nearest value less than given value
11692 : ! __________________________________________________________
11693 : real(kind = dp), Intent (In) :: XVAL
11694 : real(kind = dp) :: D_nl
11695 : ! __________________________________________________________
11696 0 : D_nl = nearest (XVAL, -1.0_dp)
11697 : return
11698 : !
11699 4 : End Function D_nearless
11700 :
11701 0 : Function R_nearless (XVAL) result (R_nl)
11702 : ! Nearest value less than given value
11703 : ! __________________________________________________________
11704 : Real(kind = sp), Intent (In) :: XVAL
11705 : Real(kind = sp) :: R_nl
11706 : ! __________________________________________________________
11707 0 : R_nl = nearest (XVAL, -1.0)
11708 : return
11709 : !
11710 0 : End Function R_nearless
11711 :
11712 4 : Function I_nearless (XVAL) result (I_nl)
11713 : ! Nearest value less than given value
11714 : ! __________________________________________________________
11715 : Integer(kind = i4), Intent (In) :: XVAL
11716 : Integer(kind = i4) :: I_nl
11717 : ! __________________________________________________________
11718 4 : I_nl = XVAL - 1
11719 : return
11720 : !
11721 4 : End Function I_nearless
11722 :
11723 :
11724 0 : Subroutine D_unipar (XDONT, IRNGT, NORD)
11725 : ! Ranks partially XDONT by IRNGT, up to order NORD at most,
11726 : ! removing duplicate entries
11727 : ! __________________________________________________________
11728 : ! This routine uses a pivoting strategy such as the one of
11729 : ! finding the median based on the quicksort algorithm, but
11730 : ! we skew the pivot choice to try to bring it to NORD as
11731 : ! quickly as possible. It uses 2 temporary arrays, where it
11732 : ! stores the indices of the values smaller than the pivot
11733 : ! (ILOWT), and the indices of values larger than the pivot
11734 : ! that we might still need later on (IHIGT). It iterates
11735 : ! until it can bring the number of values in ILOWT to
11736 : ! exactly NORD, and then uses an insertion sort to rank
11737 : ! this set, since it is supposedly small. At all times, the
11738 : ! NORD first values in ILOWT correspond to distinct values
11739 : ! of the input array.
11740 : ! Michel Olagnon - Feb. 2000
11741 : ! __________________________________________________________
11742 : ! __________________________________________________________
11743 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
11744 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
11745 : Integer(kind = i4), Intent (InOut) :: NORD
11746 : ! __________________________________________________________
11747 0 : real(kind = dp) :: XPIV, XWRK, XWRK1, XMIN, XMAX, XPIV0
11748 : !
11749 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
11750 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
11751 : Integer(kind = i4) :: IDEB, JDEB, IMIL, IFIN, NWRK, ICRS, IDCR, ILOW
11752 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1
11753 : !
11754 0 : NDON = SIZE (XDONT)
11755 : !
11756 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
11757 : !
11758 0 : If (NDON < 2) Then
11759 0 : If (NORD >= 1) Then
11760 0 : NORD = 1
11761 0 : IRNGT (1) = 1
11762 : End If
11763 0 : Return
11764 : End If
11765 : !
11766 : ! One chooses a pivot, best estimate possible to put fractile near
11767 : ! mid-point of the set of low values.
11768 : !
11769 0 : Do ICRS = 2, NDON
11770 0 : If (eq(XDONT(ICRS), XDONT(1))) Then
11771 : Cycle
11772 0 : Else If (XDONT(ICRS) < XDONT(1)) Then
11773 0 : ILOWT (1) = ICRS
11774 0 : IHIGT (1) = 1
11775 : Else
11776 0 : ILOWT (1) = 1
11777 0 : IHIGT (1) = ICRS
11778 : End If
11779 0 : If (.true.) Exit ! Exit ! JM
11780 : End Do
11781 : !
11782 0 : If (NDON <= ICRS) Then
11783 0 : NORD = Min (NORD, 2)
11784 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
11785 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
11786 0 : Return
11787 : End If
11788 : !
11789 0 : ICRS = ICRS + 1
11790 0 : JHIG = 1
11791 0 : If (XDONT(ICRS) < XDONT(IHIGT(1))) Then
11792 0 : If (XDONT(ICRS) < XDONT(ILOWT(1))) Then
11793 0 : JHIG = JHIG + 1
11794 0 : IHIGT (JHIG) = IHIGT (1)
11795 0 : IHIGT (1) = ILOWT (1)
11796 0 : ILOWT (1) = ICRS
11797 0 : Else If (XDONT(ICRS) > XDONT(ILOWT(1))) Then
11798 0 : JHIG = JHIG + 1
11799 0 : IHIGT (JHIG) = IHIGT (1)
11800 0 : IHIGT (1) = ICRS
11801 : End If
11802 0 : ElseIf (XDONT(ICRS) > XDONT(IHIGT(1))) Then
11803 0 : JHIG = JHIG + 1
11804 0 : IHIGT (JHIG) = ICRS
11805 : End If
11806 : !
11807 0 : If (NDON <= ICRS) Then
11808 0 : NORD = Min (NORD, JHIG + 1)
11809 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
11810 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
11811 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
11812 0 : Return
11813 : End If
11814 : !
11815 0 : If (XDONT(NDON) < XDONT(IHIGT(1))) Then
11816 0 : If (XDONT(NDON) < XDONT(ILOWT(1))) Then
11817 0 : Do IDCR = JHIG, 1, -1
11818 0 : IHIGT (IDCR + 1) = IHIGT (IDCR)
11819 : End Do
11820 0 : IHIGT (1) = ILOWT (1)
11821 0 : ILOWT (1) = NDON
11822 0 : JHIG = JHIG + 1
11823 0 : ElseIf (XDONT(NDON) > XDONT(ILOWT(1))) Then
11824 0 : Do IDCR = JHIG, 1, -1
11825 0 : IHIGT (IDCR + 1) = IHIGT (IDCR)
11826 : End Do
11827 0 : IHIGT (1) = NDON
11828 0 : JHIG = JHIG + 1
11829 : End If
11830 0 : ElseIf (XDONT(NDON) > XDONT(IHIGT(1))) Then
11831 0 : JHIG = JHIG + 1
11832 0 : IHIGT (JHIG) = NDON
11833 : End If
11834 : !
11835 0 : If (NDON <= ICRS + 1) Then
11836 0 : NORD = Min (NORD, JHIG + 1)
11837 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
11838 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
11839 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
11840 0 : If (NORD >= 4) IRNGT (4) = IHIGT (3)
11841 0 : Return
11842 : End If
11843 : !
11844 0 : JDEB = 0
11845 0 : IDEB = JDEB + 1
11846 0 : JLOW = IDEB
11847 0 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, dp) / REAL(NDON + NORD, dp) * &
11848 0 : (XDONT(IHIGT(3)) - XDONT(ILOWT(IDEB)))
11849 0 : If (XPIV >= XDONT(IHIGT(1))) Then
11850 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, dp) / REAL(NDON + NORD, dp) * &
11851 0 : (XDONT(IHIGT(2)) - XDONT(ILOWT(IDEB)))
11852 0 : If (XPIV >= XDONT(IHIGT(1))) &
11853 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, dp) / REAL(NDON + NORD, dp) * &
11854 0 : (XDONT(IHIGT(1)) - XDONT(ILOWT(IDEB)))
11855 : End If
11856 0 : XPIV0 = XPIV
11857 : !
11858 : ! One puts values > pivot in the end and those <= pivot
11859 : ! at the beginning. This is split in 2 cases, so that
11860 : ! we can skip the loop test a number of times.
11861 : ! As we are also filling in the work arrays at the same time
11862 : ! we stop filling in the IHIGT array as soon as we have more
11863 : ! than enough values in ILOWT, i.e. one more than
11864 : ! strictly necessary so as to be able to come out of the
11865 : ! case where JLOWT would be NORD distinct values followed
11866 : ! by values that are exclusively duplicates of these.
11867 : !
11868 : !
11869 0 : If (XDONT(NDON) > XPIV) Then
11870 : lowloop1 : Do
11871 0 : ICRS = ICRS + 1
11872 0 : If (XDONT(ICRS) > XPIV) Then
11873 0 : If (ICRS >= NDON) Exit
11874 0 : JHIG = JHIG + 1
11875 0 : IHIGT (JHIG) = ICRS
11876 : Else
11877 0 : Do ILOW = 1, JLOW
11878 0 : If (eq(XDONT(ICRS), XDONT(ILOWT(ILOW)))) Cycle lowloop1
11879 : End Do
11880 0 : JLOW = JLOW + 1
11881 0 : ILOWT (JLOW) = ICRS
11882 0 : If (JLOW >= NORD) Exit
11883 : End If
11884 : End Do lowloop1
11885 : !
11886 : ! One restricts further processing because it is no use
11887 : ! to store more high values
11888 : !
11889 0 : If (ICRS < NDON - 1) Then
11890 : Do
11891 0 : ICRS = ICRS + 1
11892 0 : If (XDONT(ICRS) <= XPIV) Then
11893 0 : JLOW = JLOW + 1
11894 0 : ILOWT (JLOW) = ICRS
11895 0 : Else If (ICRS >= NDON) Then
11896 : Exit
11897 : End If
11898 : End Do
11899 : End If
11900 : !
11901 : !
11902 : Else
11903 : !
11904 : ! Same as above, but this is not as easy to optimize, so the
11905 : ! DO-loop is kept
11906 : !
11907 0 : lowloop2 : Do ICRS = ICRS + 1, NDON - 1
11908 0 : If (XDONT(ICRS) > XPIV) Then
11909 0 : JHIG = JHIG + 1
11910 0 : IHIGT (JHIG) = ICRS
11911 : Else
11912 0 : Do ILOW = 1, JLOW
11913 0 : If (eq(XDONT(ICRS), XDONT (ILOWT(ILOW)))) Cycle lowloop2
11914 : End Do
11915 0 : JLOW = JLOW + 1
11916 0 : ILOWT (JLOW) = ICRS
11917 0 : If (JLOW >= NORD) Exit
11918 : End If
11919 : End Do lowloop2
11920 : !
11921 0 : If (ICRS < NDON - 1) Then
11922 : Do
11923 0 : ICRS = ICRS + 1
11924 0 : If (XDONT(ICRS) <= XPIV) Then
11925 0 : If (ICRS >= NDON) Exit
11926 0 : JLOW = JLOW + 1
11927 0 : ILOWT (JLOW) = ICRS
11928 : End If
11929 : End Do
11930 : End If
11931 : End If
11932 : !
11933 : JLM2 = 0
11934 : JLM1 = 0
11935 : JHM2 = 0
11936 : JHM1 = 0
11937 : Do
11938 0 : if (JLOW == NORD) Exit
11939 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
11940 : !
11941 : ! We are oscillating. Perturbate by bringing JLOW closer by one
11942 : ! to NORD
11943 : !
11944 0 : If (NORD > JLOW) Then
11945 0 : XMIN = XDONT (IHIGT(1))
11946 0 : IHIG = 1
11947 0 : Do ICRS = 2, JHIG
11948 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
11949 0 : XMIN = XDONT (IHIGT(ICRS))
11950 0 : IHIG = ICRS
11951 : End If
11952 : End Do
11953 : !
11954 0 : JLOW = JLOW + 1
11955 0 : ILOWT (JLOW) = IHIGT (IHIG)
11956 0 : IHIG = 0
11957 0 : Do ICRS = 1, JHIG
11958 0 : If (ne(XDONT(IHIGT (ICRS)), XMIN)) then
11959 0 : IHIG = IHIG + 1
11960 0 : IHIGT (IHIG) = IHIGT (ICRS)
11961 : End If
11962 : End Do
11963 : JHIG = IHIG
11964 : Else
11965 0 : ILOW = ILOWT (JLOW)
11966 0 : XMAX = XDONT (ILOW)
11967 0 : Do ICRS = 1, JLOW
11968 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
11969 0 : IWRK = ILOWT (ICRS)
11970 0 : XMAX = XDONT (IWRK)
11971 0 : ILOWT (ICRS) = ILOW
11972 0 : ILOW = IWRK
11973 : End If
11974 : End Do
11975 0 : JLOW = JLOW - 1
11976 : End If
11977 : End If
11978 0 : JLM2 = JLM1
11979 0 : JLM1 = JLOW
11980 0 : JHM2 = JHM1
11981 0 : JHM1 = JHIG
11982 : !
11983 : ! We try to bring the number of values in the low values set
11984 : ! closer to NORD. In order to make better pivot choices, we
11985 : ! decrease NORD if we already know that we don't have that
11986 : ! many distinct values as a whole.
11987 : !
11988 0 : IF (JLOW + JHIG < NORD) NORD = JLOW + JHIG
11989 0 : Select Case (NORD - JLOW)
11990 : ! ______________________________
11991 : Case (2 :)
11992 : !
11993 : ! Not enough values in low part, at least 2 are missing
11994 : !
11995 0 : Select Case (JHIG)
11996 : !
11997 : ! Not enough values in high part either (too many duplicates)
11998 : !
11999 : Case (0)
12000 0 : NORD = JLOW
12001 : !
12002 : Case (1)
12003 0 : JLOW = JLOW + 1
12004 0 : ILOWT (JLOW) = IHIGT (1)
12005 0 : NORD = JLOW
12006 : !
12007 : ! We make a special case when we have so few values in
12008 : ! the high values set that it is bad performance to choose a pivot
12009 : ! and apply the general algorithm.
12010 : !
12011 : Case (2)
12012 0 : If (le(XDONT(IHIGT(1)), XDONT(IHIGT(2)))) Then
12013 0 : JLOW = JLOW + 1
12014 0 : ILOWT (JLOW) = IHIGT (1)
12015 0 : JLOW = JLOW + 1
12016 0 : ILOWT (JLOW) = IHIGT (2)
12017 0 : ElseIf (eq(XDONT(IHIGT(1)), XDONT(IHIGT(2)))) Then
12018 0 : JLOW = JLOW + 1
12019 0 : ILOWT (JLOW) = IHIGT (1)
12020 0 : NORD = JLOW
12021 : Else
12022 0 : JLOW = JLOW + 1
12023 0 : ILOWT (JLOW) = IHIGT (2)
12024 0 : JLOW = JLOW + 1
12025 0 : ILOWT (JLOW) = IHIGT (1)
12026 : End If
12027 : Exit
12028 : !
12029 : Case (3)
12030 : !
12031 : !
12032 0 : IWRK1 = IHIGT (1)
12033 0 : IWRK2 = IHIGT (2)
12034 0 : IWRK3 = IHIGT (3)
12035 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
12036 0 : IHIGT (1) = IWRK2
12037 0 : IHIGT (2) = IWRK1
12038 0 : IWRK2 = IWRK1
12039 : End If
12040 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
12041 0 : IHIGT (3) = IWRK2
12042 0 : IHIGT (2) = IWRK3
12043 0 : IWRK2 = IWRK3
12044 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
12045 0 : IHIGT (2) = IHIGT (1)
12046 0 : IHIGT (1) = IWRK2
12047 : End If
12048 : End If
12049 0 : JHIG = 1
12050 0 : JLOW = JLOW + 1
12051 0 : ILOWT (JLOW) = IHIGT (1)
12052 0 : JHIG = JHIG + 1
12053 0 : IF (ne(XDONT(IHIGT(JHIG)), XDONT(ILOWT(JLOW)))) Then
12054 0 : JLOW = JLOW + 1
12055 0 : ILOWT (JLOW) = IHIGT (JHIG)
12056 : End If
12057 0 : JHIG = JHIG + 1
12058 0 : IF (ne(XDONT(IHIGT(JHIG)), XDONT(ILOWT(JLOW)))) Then
12059 0 : JLOW = JLOW + 1
12060 0 : ILOWT (JLOW) = IHIGT (JHIG)
12061 : End If
12062 0 : NORD = Min (JLOW, NORD)
12063 0 : Exit
12064 : !
12065 : Case (4 :)
12066 : !
12067 : !
12068 0 : XPIV0 = XPIV
12069 0 : IFIN = JHIG
12070 : !
12071 : ! One chooses a pivot from the 2 first values and the last one.
12072 : ! This should ensure sufficient renewal between iterations to
12073 : ! avoid worst case behavior effects.
12074 : !
12075 0 : IWRK1 = IHIGT (1)
12076 0 : IWRK2 = IHIGT (2)
12077 0 : IWRK3 = IHIGT (IFIN)
12078 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
12079 0 : IHIGT (1) = IWRK2
12080 0 : IHIGT (2) = IWRK1
12081 0 : IWRK2 = IWRK1
12082 : End If
12083 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
12084 0 : IHIGT (IFIN) = IWRK2
12085 0 : IHIGT (2) = IWRK3
12086 0 : IWRK2 = IWRK3
12087 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
12088 0 : IHIGT (2) = IHIGT (1)
12089 0 : IHIGT (1) = IWRK2
12090 : End If
12091 : End If
12092 : !
12093 0 : JDEB = JLOW
12094 0 : NWRK = NORD - JLOW
12095 0 : IWRK1 = IHIGT (1)
12096 0 : XPIV = XDONT (IWRK1) + REAL(NWRK, dp) / REAL(NORD + NWRK, dp) * &
12097 0 : (XDONT(IHIGT(IFIN)) - XDONT(IWRK1))
12098 : !
12099 : ! One takes values <= pivot to ILOWT
12100 : ! Again, 2 parts, one where we take care of the remaining
12101 : ! high values because we might still need them, and the
12102 : ! other when we know that we will have more than enough
12103 : ! low values in the end.
12104 : !
12105 0 : JHIG = 0
12106 0 : lowloop3 : Do ICRS = 1, IFIN
12107 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
12108 0 : Do ILOW = 1, JLOW
12109 0 : If (eq(XDONT(IHIGT(ICRS)), XDONT (ILOWT(ILOW)))) &
12110 0 : Cycle lowloop3
12111 : End Do
12112 0 : JLOW = JLOW + 1
12113 0 : ILOWT (JLOW) = IHIGT (ICRS)
12114 0 : If (JLOW > NORD) Exit
12115 : Else
12116 0 : JHIG = JHIG + 1
12117 0 : IHIGT (JHIG) = IHIGT (ICRS)
12118 : End If
12119 : End Do lowloop3
12120 : !
12121 0 : Do ICRS = ICRS + 1, IFIN
12122 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
12123 0 : JLOW = JLOW + 1
12124 0 : ILOWT (JLOW) = IHIGT (ICRS)
12125 : End If
12126 : End Do
12127 : End Select
12128 : !
12129 : ! ______________________________
12130 : !
12131 : Case (1)
12132 : !
12133 : ! Only 1 value is missing in low part
12134 : !
12135 0 : XMIN = XDONT (IHIGT(1))
12136 0 : IHIG = 1
12137 0 : Do ICRS = 2, JHIG
12138 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
12139 0 : XMIN = XDONT (IHIGT(ICRS))
12140 0 : IHIG = ICRS
12141 : End If
12142 : End Do
12143 : !
12144 0 : JLOW = JLOW + 1
12145 0 : ILOWT (JLOW) = IHIGT (IHIG)
12146 0 : Exit
12147 : !
12148 : ! ______________________________
12149 : !
12150 : Case (0)
12151 : !
12152 : ! Low part is exactly what we want
12153 : !
12154 0 : Exit
12155 : !
12156 : ! ______________________________
12157 : !
12158 : Case (-5 : -1)
12159 : !
12160 : ! Only few values too many in low part
12161 : !
12162 0 : IRNGT (1) = ILOWT (1)
12163 0 : Do ICRS = 2, NORD
12164 0 : IWRK = ILOWT (ICRS)
12165 0 : XWRK = XDONT (IWRK)
12166 0 : Do IDCR = ICRS - 1, 1, - 1
12167 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
12168 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
12169 : Else
12170 : Exit
12171 : End If
12172 : End Do
12173 0 : IRNGT (IDCR + 1) = IWRK
12174 : End Do
12175 : !
12176 0 : XWRK1 = XDONT (IRNGT(NORD))
12177 0 : insert1 : Do ICRS = NORD + 1, JLOW
12178 0 : If (XDONT(ILOWT (ICRS)) < XWRK1) Then
12179 0 : XWRK = XDONT (ILOWT (ICRS))
12180 0 : Do ILOW = 1, NORD - 1
12181 0 : If (XWRK <= XDONT(IRNGT(ILOW))) Then
12182 0 : If (eq(XWRK, XDONT(IRNGT(ILOW)))) Cycle insert1
12183 : Exit
12184 : End If
12185 : End Do
12186 0 : Do IDCR = NORD - 1, ILOW, - 1
12187 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
12188 : End Do
12189 0 : IRNGT (IDCR + 1) = ILOWT (ICRS)
12190 0 : XWRK1 = XDONT (IRNGT(NORD))
12191 : End If
12192 : End Do insert1
12193 : !
12194 0 : Return
12195 : !
12196 : ! ______________________________
12197 : !
12198 : Case (: -6)
12199 : !
12200 : ! last case: too many values in low part
12201 : !
12202 0 : IDEB = JDEB + 1
12203 0 : IMIL = MIN ((JLOW + IDEB) / 2, NORD)
12204 0 : IFIN = MIN (JLOW, NORD + 1)
12205 : !
12206 : ! One chooses a pivot from 1st, last, and middle values
12207 : !
12208 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
12209 0 : IWRK = ILOWT (IDEB)
12210 0 : ILOWT (IDEB) = ILOWT (IMIL)
12211 0 : ILOWT (IMIL) = IWRK
12212 : End If
12213 0 : If (XDONT(ILOWT(IMIL)) > XDONT(ILOWT(IFIN))) Then
12214 0 : IWRK = ILOWT (IFIN)
12215 0 : ILOWT (IFIN) = ILOWT (IMIL)
12216 0 : ILOWT (IMIL) = IWRK
12217 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
12218 0 : IWRK = ILOWT (IDEB)
12219 0 : ILOWT (IDEB) = ILOWT (IMIL)
12220 0 : ILOWT (IMIL) = IWRK
12221 : End If
12222 : End If
12223 0 : If (IFIN <= 3) Exit
12224 : !
12225 0 : XPIV = XDONT (ILOWT(IDEB)) + REAL(NORD, dp) / REAL(JLOW + NORD, dp) * &
12226 0 : (XDONT(ILOWT(IFIN)) - XDONT(ILOWT(1)))
12227 0 : If (JDEB > 0) Then
12228 0 : If (XPIV <= XPIV0) &
12229 : XPIV = XPIV0 + REAL(2 * NORD - JDEB, dp) / REAL(JLOW + NORD, dp) * &
12230 0 : (XDONT(ILOWT(IFIN)) - XPIV0)
12231 : Else
12232 : IDEB = 1
12233 : End If
12234 : !
12235 : ! One takes values > XPIV to IHIGT
12236 : ! However, we do not process the first values if we have been
12237 : ! through the case when we did not have enough low values
12238 : !
12239 0 : JHIG = 0
12240 0 : IFIN = JLOW
12241 0 : JLOW = JDEB
12242 : !
12243 0 : If (XDONT(ILOWT(IFIN)) > XPIV) Then
12244 : ICRS = JDEB
12245 : lowloop4 : Do
12246 0 : ICRS = ICRS + 1
12247 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
12248 0 : JHIG = JHIG + 1
12249 0 : IHIGT (JHIG) = ILOWT (ICRS)
12250 0 : If (ICRS >= IFIN) Exit
12251 : Else
12252 0 : XWRK1 = XDONT(ILOWT(ICRS))
12253 0 : Do ILOW = IDEB, JLOW
12254 0 : If (eq(XWRK1, XDONT(ILOWT(ILOW)))) &
12255 0 : Cycle lowloop4
12256 : End Do
12257 0 : JLOW = JLOW + 1
12258 0 : ILOWT (JLOW) = ILOWT (ICRS)
12259 0 : If (JLOW >= NORD) Exit
12260 : End If
12261 : End Do lowloop4
12262 : !
12263 0 : If (ICRS < IFIN) Then
12264 : Do
12265 0 : ICRS = ICRS + 1
12266 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
12267 0 : JLOW = JLOW + 1
12268 0 : ILOWT (JLOW) = ILOWT (ICRS)
12269 : Else
12270 0 : If (ICRS >= IFIN) Exit
12271 : End If
12272 : End Do
12273 : End If
12274 : Else
12275 0 : lowloop5 : Do ICRS = IDEB, IFIN
12276 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
12277 0 : JHIG = JHIG + 1
12278 0 : IHIGT (JHIG) = ILOWT (ICRS)
12279 : Else
12280 0 : XWRK1 = XDONT(ILOWT(ICRS))
12281 0 : Do ILOW = IDEB, JLOW
12282 0 : If (eq(XWRK1, XDONT(ILOWT(ILOW)))) &
12283 0 : Cycle lowloop5
12284 : End Do
12285 0 : JLOW = JLOW + 1
12286 0 : ILOWT (JLOW) = ILOWT (ICRS)
12287 0 : If (JLOW >= NORD) Exit
12288 : End If
12289 : End Do lowloop5
12290 : !
12291 0 : Do ICRS = ICRS + 1, IFIN
12292 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
12293 0 : JLOW = JLOW + 1
12294 0 : ILOWT (JLOW) = ILOWT (ICRS)
12295 : End If
12296 : End Do
12297 : End If
12298 : !
12299 : End Select
12300 : ! ______________________________
12301 : !
12302 : End Do
12303 : !
12304 : ! Now, we only need to complete ranking of the 1:NORD set
12305 : ! Assuming NORD is small, we use a simple insertion sort
12306 : !
12307 0 : IRNGT (1) = ILOWT (1)
12308 0 : Do ICRS = 2, NORD
12309 0 : IWRK = ILOWT (ICRS)
12310 0 : XWRK = XDONT (IWRK)
12311 0 : Do IDCR = ICRS - 1, 1, - 1
12312 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
12313 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
12314 : Else
12315 : Exit
12316 : End If
12317 : End Do
12318 0 : IRNGT (IDCR + 1) = IWRK
12319 : End Do
12320 : Return
12321 : !
12322 : !
12323 4 : End Subroutine D_unipar
12324 :
12325 0 : Subroutine R_unipar (XDONT, IRNGT, NORD)
12326 : ! Ranks partially XDONT by IRNGT, up to order NORD at most,
12327 : ! removing duplicate entries
12328 : ! __________________________________________________________
12329 : ! This routine uses a pivoting strategy such as the one of
12330 : ! finding the median based on the quicksort algorithm, but
12331 : ! we skew the pivot choice to try to bring it to NORD as
12332 : ! quickly as possible. It uses 2 temporary arrays, where it
12333 : ! stores the indices of the values smaller than the pivot
12334 : ! (ILOWT), and the indices of values larger than the pivot
12335 : ! that we might still need later on (IHIGT). It iterates
12336 : ! until it can bring the number of values in ILOWT to
12337 : ! exactly NORD, and then uses an insertion sort to rank
12338 : ! this set, since it is supposedly small. At all times, the
12339 : ! NORD first values in ILOWT correspond to distinct values
12340 : ! of the input array.
12341 : ! Michel Olagnon - Feb. 2000
12342 : ! __________________________________________________________
12343 : ! _________________________________________________________
12344 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
12345 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
12346 : Integer(kind = i4), Intent (InOut) :: NORD
12347 : ! __________________________________________________________
12348 0 : Real(kind = sp) :: XPIV, XWRK, XWRK1, XMIN, XMAX, XPIV0
12349 : !
12350 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
12351 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
12352 : Integer(kind = i4) :: IDEB, JDEB, IMIL, IFIN, NWRK, ICRS, IDCR, ILOW
12353 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1
12354 : !
12355 0 : NDON = SIZE (XDONT)
12356 : !
12357 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
12358 : !
12359 0 : If (NDON < 2) Then
12360 0 : If (NORD >= 1) Then
12361 0 : NORD = 1
12362 0 : IRNGT (1) = 1
12363 : End If
12364 0 : Return
12365 : End If
12366 : !
12367 : ! One chooses a pivot, best estimate possible to put fractile near
12368 : ! mid-point of the set of low values.
12369 : !
12370 0 : Do ICRS = 2, NDON
12371 0 : If (eq(XDONT(ICRS), XDONT(1))) Then
12372 : Cycle
12373 0 : Else If (XDONT(ICRS) < XDONT(1)) Then
12374 0 : ILOWT (1) = ICRS
12375 0 : IHIGT (1) = 1
12376 : Else
12377 0 : ILOWT (1) = 1
12378 0 : IHIGT (1) = ICRS
12379 : End If
12380 0 : If (.true.) Exit ! Exit ! JM
12381 : End Do
12382 : !
12383 0 : If (NDON <= ICRS) Then
12384 0 : NORD = Min (NORD, 2)
12385 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
12386 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
12387 0 : Return
12388 : End If
12389 : !
12390 0 : ICRS = ICRS + 1
12391 0 : JHIG = 1
12392 0 : If (XDONT(ICRS) < XDONT(IHIGT(1))) Then
12393 0 : If (XDONT(ICRS) < XDONT(ILOWT(1))) Then
12394 0 : JHIG = JHIG + 1
12395 0 : IHIGT (JHIG) = IHIGT (1)
12396 0 : IHIGT (1) = ILOWT (1)
12397 0 : ILOWT (1) = ICRS
12398 0 : Else If (XDONT(ICRS) > XDONT(ILOWT(1))) Then
12399 0 : JHIG = JHIG + 1
12400 0 : IHIGT (JHIG) = IHIGT (1)
12401 0 : IHIGT (1) = ICRS
12402 : End If
12403 0 : ElseIf (XDONT(ICRS) > XDONT(IHIGT(1))) Then
12404 0 : JHIG = JHIG + 1
12405 0 : IHIGT (JHIG) = ICRS
12406 : End If
12407 : !
12408 0 : If (NDON <= ICRS) Then
12409 0 : NORD = Min (NORD, JHIG + 1)
12410 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
12411 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
12412 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
12413 0 : Return
12414 : End If
12415 : !
12416 0 : If (XDONT(NDON) < XDONT(IHIGT(1))) Then
12417 0 : If (XDONT(NDON) < XDONT(ILOWT(1))) Then
12418 0 : Do IDCR = JHIG, 1, -1
12419 0 : IHIGT (IDCR + 1) = IHIGT (IDCR)
12420 : End Do
12421 0 : IHIGT (1) = ILOWT (1)
12422 0 : ILOWT (1) = NDON
12423 0 : JHIG = JHIG + 1
12424 0 : ElseIf (XDONT(NDON) > XDONT(ILOWT(1))) Then
12425 0 : Do IDCR = JHIG, 1, -1
12426 0 : IHIGT (IDCR + 1) = IHIGT (IDCR)
12427 : End Do
12428 0 : IHIGT (1) = NDON
12429 0 : JHIG = JHIG + 1
12430 : End If
12431 0 : ElseIf (XDONT(NDON) > XDONT(IHIGT(1))) Then
12432 0 : JHIG = JHIG + 1
12433 0 : IHIGT (JHIG) = NDON
12434 : End If
12435 : !
12436 0 : If (NDON <= ICRS + 1) Then
12437 0 : NORD = Min (NORD, JHIG + 1)
12438 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
12439 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
12440 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
12441 0 : If (NORD >= 4) IRNGT (4) = IHIGT (3)
12442 0 : Return
12443 : End If
12444 : !
12445 0 : JDEB = 0
12446 0 : IDEB = JDEB + 1
12447 0 : JLOW = IDEB
12448 0 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, sp) / REAL(NDON + NORD, sp) * &
12449 0 : (XDONT(IHIGT(3)) - XDONT(ILOWT(IDEB)))
12450 0 : If (XPIV >= XDONT(IHIGT(1))) Then
12451 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, sp) / REAL(NDON + NORD, sp) * &
12452 0 : (XDONT(IHIGT(2)) - XDONT(ILOWT(IDEB)))
12453 0 : If (XPIV >= XDONT(IHIGT(1))) &
12454 : XPIV = XDONT (ILOWT(IDEB)) + REAL(2 * NORD, sp) / REAL(NDON + NORD, sp) * &
12455 0 : (XDONT(IHIGT(1)) - XDONT(ILOWT(IDEB)))
12456 : End If
12457 0 : XPIV0 = XPIV
12458 : !
12459 : ! One puts values > pivot in the end and those <= pivot
12460 : ! at the beginning. This is split in 2 cases, so that
12461 : ! we can skip the loop test a number of times.
12462 : ! As we are also filling in the work arrays at the same time
12463 : ! we stop filling in the IHIGT array as soon as we have more
12464 : ! than enough values in ILOWT, i.e. one more than
12465 : ! strictly necessary so as to be able to come out of the
12466 : ! case where JLOWT would be NORD distinct values followed
12467 : ! by values that are exclusively duplicates of these.
12468 : !
12469 : !
12470 0 : If (XDONT(NDON) > XPIV) Then
12471 : lowloop1 : Do
12472 0 : ICRS = ICRS + 1
12473 0 : If (XDONT(ICRS) > XPIV) Then
12474 0 : If (ICRS >= NDON) Exit
12475 0 : JHIG = JHIG + 1
12476 0 : IHIGT (JHIG) = ICRS
12477 : Else
12478 0 : Do ILOW = 1, JLOW
12479 0 : If (eq(XDONT(ICRS), XDONT(ILOWT(ILOW)))) Cycle lowloop1
12480 : End Do
12481 0 : JLOW = JLOW + 1
12482 0 : ILOWT (JLOW) = ICRS
12483 0 : If (JLOW >= NORD) Exit
12484 : End If
12485 : End Do lowloop1
12486 : !
12487 : ! One restricts further processing because it is no use
12488 : ! to store more high values
12489 : !
12490 0 : If (ICRS < NDON - 1) Then
12491 : Do
12492 0 : ICRS = ICRS + 1
12493 0 : If (XDONT(ICRS) <= XPIV) Then
12494 0 : JLOW = JLOW + 1
12495 0 : ILOWT (JLOW) = ICRS
12496 0 : Else If (ICRS >= NDON) Then
12497 : Exit
12498 : End If
12499 : End Do
12500 : End If
12501 : !
12502 : !
12503 : Else
12504 : !
12505 : ! Same as above, but this is not as easy to optimize, so the
12506 : ! DO-loop is kept
12507 : !
12508 0 : lowloop2 : Do ICRS = ICRS + 1, NDON - 1
12509 0 : If (XDONT(ICRS) > XPIV) Then
12510 0 : JHIG = JHIG + 1
12511 0 : IHIGT (JHIG) = ICRS
12512 : Else
12513 0 : Do ILOW = 1, JLOW
12514 0 : If (eq(XDONT(ICRS), XDONT (ILOWT(ILOW)))) Cycle lowloop2
12515 : End Do
12516 0 : JLOW = JLOW + 1
12517 0 : ILOWT (JLOW) = ICRS
12518 0 : If (JLOW >= NORD) Exit
12519 : End If
12520 : End Do lowloop2
12521 : !
12522 0 : If (ICRS < NDON - 1) Then
12523 : Do
12524 0 : ICRS = ICRS + 1
12525 0 : If (XDONT(ICRS) <= XPIV) Then
12526 0 : If (ICRS >= NDON) Exit
12527 0 : JLOW = JLOW + 1
12528 0 : ILOWT (JLOW) = ICRS
12529 : End If
12530 : End Do
12531 : End If
12532 : End If
12533 : !
12534 : JLM2 = 0
12535 : JLM1 = 0
12536 : JHM2 = 0
12537 : JHM1 = 0
12538 : Do
12539 0 : if (JLOW == NORD) Exit
12540 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
12541 : !
12542 : ! We are oscillating. Perturbate by bringing JLOW closer by one
12543 : ! to NORD
12544 : !
12545 0 : If (NORD > JLOW) Then
12546 0 : XMIN = XDONT (IHIGT(1))
12547 0 : IHIG = 1
12548 0 : Do ICRS = 2, JHIG
12549 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
12550 0 : XMIN = XDONT (IHIGT(ICRS))
12551 0 : IHIG = ICRS
12552 : End If
12553 : End Do
12554 : !
12555 0 : JLOW = JLOW + 1
12556 0 : ILOWT (JLOW) = IHIGT (IHIG)
12557 0 : IHIG = 0
12558 0 : Do ICRS = 1, JHIG
12559 0 : If (ne(XDONT(IHIGT (ICRS)), XMIN)) then
12560 0 : IHIG = IHIG + 1
12561 0 : IHIGT (IHIG) = IHIGT (ICRS)
12562 : End If
12563 : End Do
12564 : JHIG = IHIG
12565 : Else
12566 0 : ILOW = ILOWT (JLOW)
12567 0 : XMAX = XDONT (ILOW)
12568 0 : Do ICRS = 1, JLOW
12569 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
12570 0 : IWRK = ILOWT (ICRS)
12571 0 : XMAX = XDONT (IWRK)
12572 0 : ILOWT (ICRS) = ILOW
12573 0 : ILOW = IWRK
12574 : End If
12575 : End Do
12576 0 : JLOW = JLOW - 1
12577 : End If
12578 : End If
12579 0 : JLM2 = JLM1
12580 0 : JLM1 = JLOW
12581 0 : JHM2 = JHM1
12582 0 : JHM1 = JHIG
12583 : !
12584 : ! We try to bring the number of values in the low values set
12585 : ! closer to NORD. In order to make better pivot choices, we
12586 : ! decrease NORD if we already know that we don't have that
12587 : ! many distinct values as a whole.
12588 : !
12589 0 : IF (JLOW + JHIG < NORD) NORD = JLOW + JHIG
12590 0 : Select Case (NORD - JLOW)
12591 : ! ______________________________
12592 : Case (2 :)
12593 : !
12594 : ! Not enough values in low part, at least 2 are missing
12595 : !
12596 0 : Select Case (JHIG)
12597 : !
12598 : ! Not enough values in high part either (too many duplicates)
12599 : !
12600 : Case (0)
12601 0 : NORD = JLOW
12602 : !
12603 : Case (1)
12604 0 : JLOW = JLOW + 1
12605 0 : ILOWT (JLOW) = IHIGT (1)
12606 0 : NORD = JLOW
12607 : !
12608 : ! We make a special case when we have so few values in
12609 : ! the high values set that it is bad performance to choose a pivot
12610 : ! and apply the general algorithm.
12611 : !
12612 : Case (2)
12613 0 : If (le(XDONT(IHIGT(1)), XDONT(IHIGT(2)))) Then
12614 0 : JLOW = JLOW + 1
12615 0 : ILOWT (JLOW) = IHIGT (1)
12616 0 : JLOW = JLOW + 1
12617 0 : ILOWT (JLOW) = IHIGT (2)
12618 0 : ElseIf (eq(XDONT(IHIGT(1)), XDONT(IHIGT(2)))) Then
12619 0 : JLOW = JLOW + 1
12620 0 : ILOWT (JLOW) = IHIGT (1)
12621 0 : NORD = JLOW
12622 : Else
12623 0 : JLOW = JLOW + 1
12624 0 : ILOWT (JLOW) = IHIGT (2)
12625 0 : JLOW = JLOW + 1
12626 0 : ILOWT (JLOW) = IHIGT (1)
12627 : End If
12628 : Exit
12629 : !
12630 : Case (3)
12631 : !
12632 : !
12633 0 : IWRK1 = IHIGT (1)
12634 0 : IWRK2 = IHIGT (2)
12635 0 : IWRK3 = IHIGT (3)
12636 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
12637 0 : IHIGT (1) = IWRK2
12638 0 : IHIGT (2) = IWRK1
12639 0 : IWRK2 = IWRK1
12640 : End If
12641 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
12642 0 : IHIGT (3) = IWRK2
12643 0 : IHIGT (2) = IWRK3
12644 0 : IWRK2 = IWRK3
12645 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
12646 0 : IHIGT (2) = IHIGT (1)
12647 0 : IHIGT (1) = IWRK2
12648 : End If
12649 : End If
12650 0 : JHIG = 1
12651 0 : JLOW = JLOW + 1
12652 0 : ILOWT (JLOW) = IHIGT (1)
12653 0 : JHIG = JHIG + 1
12654 0 : IF (ne(XDONT(IHIGT(JHIG)), XDONT(ILOWT(JLOW)))) Then
12655 0 : JLOW = JLOW + 1
12656 0 : ILOWT (JLOW) = IHIGT (JHIG)
12657 : End If
12658 0 : JHIG = JHIG + 1
12659 0 : IF (ne(XDONT(IHIGT(JHIG)), XDONT(ILOWT(JLOW)))) Then
12660 0 : JLOW = JLOW + 1
12661 0 : ILOWT (JLOW) = IHIGT (JHIG)
12662 : End If
12663 0 : NORD = Min (JLOW, NORD)
12664 0 : Exit
12665 : !
12666 : Case (4 :)
12667 : !
12668 : !
12669 0 : XPIV0 = XPIV
12670 0 : IFIN = JHIG
12671 : !
12672 : ! One chooses a pivot from the 2 first values and the last one.
12673 : ! This should ensure sufficient renewal between iterations to
12674 : ! avoid worst case behavior effects.
12675 : !
12676 0 : IWRK1 = IHIGT (1)
12677 0 : IWRK2 = IHIGT (2)
12678 0 : IWRK3 = IHIGT (IFIN)
12679 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
12680 0 : IHIGT (1) = IWRK2
12681 0 : IHIGT (2) = IWRK1
12682 0 : IWRK2 = IWRK1
12683 : End If
12684 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
12685 0 : IHIGT (IFIN) = IWRK2
12686 0 : IHIGT (2) = IWRK3
12687 0 : IWRK2 = IWRK3
12688 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
12689 0 : IHIGT (2) = IHIGT (1)
12690 0 : IHIGT (1) = IWRK2
12691 : End If
12692 : End If
12693 : !
12694 0 : JDEB = JLOW
12695 0 : NWRK = NORD - JLOW
12696 0 : IWRK1 = IHIGT (1)
12697 0 : XPIV = XDONT (IWRK1) + REAL(NWRK, sp) / REAL(NORD + NWRK, sp) * &
12698 0 : (XDONT(IHIGT(IFIN)) - XDONT(IWRK1))
12699 : !
12700 : ! One takes values <= pivot to ILOWT
12701 : ! Again, 2 parts, one where we take care of the remaining
12702 : ! high values because we might still need them, and the
12703 : ! other when we know that we will have more than enough
12704 : ! low values in the end.
12705 : !
12706 0 : JHIG = 0
12707 0 : lowloop3 : Do ICRS = 1, IFIN
12708 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
12709 0 : Do ILOW = 1, JLOW
12710 0 : If (eq(XDONT(IHIGT(ICRS)), XDONT (ILOWT(ILOW)))) &
12711 0 : Cycle lowloop3
12712 : End Do
12713 0 : JLOW = JLOW + 1
12714 0 : ILOWT (JLOW) = IHIGT (ICRS)
12715 0 : If (JLOW > NORD) Exit
12716 : Else
12717 0 : JHIG = JHIG + 1
12718 0 : IHIGT (JHIG) = IHIGT (ICRS)
12719 : End If
12720 : End Do lowloop3
12721 : !
12722 0 : Do ICRS = ICRS + 1, IFIN
12723 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
12724 0 : JLOW = JLOW + 1
12725 0 : ILOWT (JLOW) = IHIGT (ICRS)
12726 : End If
12727 : End Do
12728 : End Select
12729 : !
12730 : ! ______________________________
12731 : !
12732 : Case (1)
12733 : !
12734 : ! Only 1 value is missing in low part
12735 : !
12736 0 : XMIN = XDONT (IHIGT(1))
12737 0 : IHIG = 1
12738 0 : Do ICRS = 2, JHIG
12739 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
12740 0 : XMIN = XDONT (IHIGT(ICRS))
12741 0 : IHIG = ICRS
12742 : End If
12743 : End Do
12744 : !
12745 0 : JLOW = JLOW + 1
12746 0 : ILOWT (JLOW) = IHIGT (IHIG)
12747 0 : Exit
12748 : !
12749 : ! ______________________________
12750 : !
12751 : Case (0)
12752 : !
12753 : ! Low part is exactly what we want
12754 : !
12755 0 : Exit
12756 : !
12757 : ! ______________________________
12758 : !
12759 : Case (-5 : -1)
12760 : !
12761 : ! Only few values too many in low part
12762 : !
12763 0 : IRNGT (1) = ILOWT (1)
12764 0 : Do ICRS = 2, NORD
12765 0 : IWRK = ILOWT (ICRS)
12766 0 : XWRK = XDONT (IWRK)
12767 0 : Do IDCR = ICRS - 1, 1, - 1
12768 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
12769 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
12770 : Else
12771 : Exit
12772 : End If
12773 : End Do
12774 0 : IRNGT (IDCR + 1) = IWRK
12775 : End Do
12776 : !
12777 0 : XWRK1 = XDONT (IRNGT(NORD))
12778 0 : insert1 : Do ICRS = NORD + 1, JLOW
12779 0 : If (XDONT(ILOWT (ICRS)) < XWRK1) Then
12780 0 : XWRK = XDONT (ILOWT (ICRS))
12781 0 : Do ILOW = 1, NORD - 1
12782 0 : If (XWRK <= XDONT(IRNGT(ILOW))) Then
12783 0 : If (eq(XWRK, XDONT(IRNGT(ILOW)))) Cycle insert1
12784 : Exit
12785 : End If
12786 : End Do
12787 0 : Do IDCR = NORD - 1, ILOW, - 1
12788 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
12789 : End Do
12790 0 : IRNGT (IDCR + 1) = ILOWT (ICRS)
12791 0 : XWRK1 = XDONT (IRNGT(NORD))
12792 : End If
12793 : End Do insert1
12794 : !
12795 0 : Return
12796 : !
12797 : ! ______________________________
12798 : !
12799 : Case (: -6)
12800 : !
12801 : ! last case: too many values in low part
12802 : !
12803 0 : IDEB = JDEB + 1
12804 0 : IMIL = MIN ((JLOW + IDEB) / 2, NORD)
12805 0 : IFIN = MIN (JLOW, NORD + 1)
12806 : !
12807 : ! One chooses a pivot from 1st, last, and middle values
12808 : !
12809 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
12810 0 : IWRK = ILOWT (IDEB)
12811 0 : ILOWT (IDEB) = ILOWT (IMIL)
12812 0 : ILOWT (IMIL) = IWRK
12813 : End If
12814 0 : If (XDONT(ILOWT(IMIL)) > XDONT(ILOWT(IFIN))) Then
12815 0 : IWRK = ILOWT (IFIN)
12816 0 : ILOWT (IFIN) = ILOWT (IMIL)
12817 0 : ILOWT (IMIL) = IWRK
12818 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
12819 0 : IWRK = ILOWT (IDEB)
12820 0 : ILOWT (IDEB) = ILOWT (IMIL)
12821 0 : ILOWT (IMIL) = IWRK
12822 : End If
12823 : End If
12824 0 : If (IFIN <= 3) Exit
12825 : !
12826 0 : XPIV = XDONT (ILOWT(IDEB)) + REAL(NORD, sp) / REAL(JLOW + NORD, sp) * &
12827 0 : (XDONT(ILOWT(IFIN)) - XDONT(ILOWT(1)))
12828 0 : If (JDEB > 0) Then
12829 0 : If (XPIV <= XPIV0) &
12830 : XPIV = XPIV0 + REAL(2 * NORD - JDEB, sp) / REAL(JLOW + NORD, sp) * &
12831 0 : (XDONT(ILOWT(IFIN)) - XPIV0)
12832 : Else
12833 : IDEB = 1
12834 : End If
12835 : !
12836 : ! One takes values > XPIV to IHIGT
12837 : ! However, we do not process the first values if we have been
12838 : ! through the case when we did not have enough low values
12839 : !
12840 0 : JHIG = 0
12841 0 : IFIN = JLOW
12842 0 : JLOW = JDEB
12843 : !
12844 0 : If (XDONT(ILOWT(IFIN)) > XPIV) Then
12845 : ICRS = JDEB
12846 : lowloop4 : Do
12847 0 : ICRS = ICRS + 1
12848 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
12849 0 : JHIG = JHIG + 1
12850 0 : IHIGT (JHIG) = ILOWT (ICRS)
12851 0 : If (ICRS >= IFIN) Exit
12852 : Else
12853 0 : XWRK1 = XDONT(ILOWT(ICRS))
12854 0 : Do ILOW = IDEB, JLOW
12855 0 : If (eq(XWRK1, XDONT(ILOWT(ILOW)))) &
12856 0 : Cycle lowloop4
12857 : End Do
12858 0 : JLOW = JLOW + 1
12859 0 : ILOWT (JLOW) = ILOWT (ICRS)
12860 0 : If (JLOW >= NORD) Exit
12861 : End If
12862 : End Do lowloop4
12863 : !
12864 0 : If (ICRS < IFIN) Then
12865 : Do
12866 0 : ICRS = ICRS + 1
12867 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
12868 0 : JLOW = JLOW + 1
12869 0 : ILOWT (JLOW) = ILOWT (ICRS)
12870 : Else
12871 0 : If (ICRS >= IFIN) Exit
12872 : End If
12873 : End Do
12874 : End If
12875 : Else
12876 0 : lowloop5 : Do ICRS = IDEB, IFIN
12877 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
12878 0 : JHIG = JHIG + 1
12879 0 : IHIGT (JHIG) = ILOWT (ICRS)
12880 : Else
12881 0 : XWRK1 = XDONT(ILOWT(ICRS))
12882 0 : Do ILOW = IDEB, JLOW
12883 0 : If (eq(XWRK1, XDONT(ILOWT(ILOW)))) &
12884 0 : Cycle lowloop5
12885 : End Do
12886 0 : JLOW = JLOW + 1
12887 0 : ILOWT (JLOW) = ILOWT (ICRS)
12888 0 : If (JLOW >= NORD) Exit
12889 : End If
12890 : End Do lowloop5
12891 : !
12892 0 : Do ICRS = ICRS + 1, IFIN
12893 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
12894 0 : JLOW = JLOW + 1
12895 0 : ILOWT (JLOW) = ILOWT (ICRS)
12896 : End If
12897 : End Do
12898 : End If
12899 : !
12900 : End Select
12901 : ! ______________________________
12902 : !
12903 : End Do
12904 : !
12905 : ! Now, we only need to complete ranking of the 1:NORD set
12906 : ! Assuming NORD is small, we use a simple insertion sort
12907 : !
12908 0 : IRNGT (1) = ILOWT (1)
12909 0 : Do ICRS = 2, NORD
12910 0 : IWRK = ILOWT (ICRS)
12911 0 : XWRK = XDONT (IWRK)
12912 0 : Do IDCR = ICRS - 1, 1, - 1
12913 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
12914 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
12915 : Else
12916 : Exit
12917 : End If
12918 : End Do
12919 0 : IRNGT (IDCR + 1) = IWRK
12920 : End Do
12921 : Return
12922 : !
12923 : !
12924 0 : End Subroutine R_unipar
12925 :
12926 0 : Subroutine I_unipar (XDONT, IRNGT, NORD)
12927 : ! Ranks partially XDONT by IRNGT, up to order NORD at most,
12928 : ! removing duplicate entries
12929 : ! __________________________________________________________
12930 : ! This routine uses a pivoting strategy such as the one of
12931 : ! finding the median based on the quicksort algorithm, but
12932 : ! we skew the pivot choice to try to bring it to NORD as
12933 : ! quickly as possible. It uses 2 temporary arrays, where it
12934 : ! stores the indices of the values smaller than the pivot
12935 : ! (ILOWT), and the indices of values larger than the pivot
12936 : ! that we might still need later on (IHIGT). It iterates
12937 : ! until it can bring the number of values in ILOWT to
12938 : ! exactly NORD, and then uses an insertion sort to rank
12939 : ! this set, since it is supposedly small. At all times, the
12940 : ! NORD first values in ILOWT correspond to distinct values
12941 : ! of the input array.
12942 : ! Michel Olagnon - Feb. 2000
12943 : ! __________________________________________________________
12944 : ! __________________________________________________________
12945 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
12946 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
12947 : Integer(kind = i4), Intent (InOut) :: NORD
12948 : ! __________________________________________________________
12949 : Integer(kind = i4) :: XPIV, XWRK, XWRK1, XMIN, XMAX, XPIV0
12950 : !
12951 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: ILOWT, IHIGT
12952 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG, IWRK, IWRK1, IWRK2, IWRK3
12953 : Integer(kind = i4) :: IDEB, JDEB, IMIL, IFIN, NWRK, ICRS, IDCR, ILOW
12954 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1
12955 : !
12956 0 : NDON = SIZE (XDONT)
12957 : !
12958 : ! First loop is used to fill-in ILOWT, IHIGT at the same time
12959 : !
12960 0 : If (NDON < 2) Then
12961 0 : If (NORD >= 1) Then
12962 0 : NORD = 1
12963 0 : IRNGT (1) = 1
12964 : End If
12965 0 : Return
12966 : End If
12967 : !
12968 : ! One chooses a pivot, best estimate possible to put fractile near
12969 : ! mid-point of the set of low values.
12970 : !
12971 0 : Do ICRS = 2, NDON
12972 0 : If (XDONT(ICRS) == XDONT(1)) Then
12973 : Cycle
12974 0 : Else If (XDONT(ICRS) < XDONT(1)) Then
12975 0 : ILOWT (1) = ICRS
12976 0 : IHIGT (1) = 1
12977 : Else
12978 0 : ILOWT (1) = 1
12979 0 : IHIGT (1) = ICRS
12980 : End If
12981 0 : If (.true.) Exit ! Exit ! JM
12982 : End Do
12983 : !
12984 0 : If (NDON <= ICRS) Then
12985 0 : NORD = Min (NORD, 2)
12986 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
12987 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
12988 0 : Return
12989 : End If
12990 : !
12991 0 : ICRS = ICRS + 1
12992 0 : JHIG = 1
12993 0 : If (XDONT(ICRS) < XDONT(IHIGT(1))) Then
12994 0 : If (XDONT(ICRS) < XDONT(ILOWT(1))) Then
12995 0 : JHIG = JHIG + 1
12996 0 : IHIGT (JHIG) = IHIGT (1)
12997 0 : IHIGT (1) = ILOWT (1)
12998 0 : ILOWT (1) = ICRS
12999 0 : Else If (XDONT(ICRS) > XDONT(ILOWT(1))) Then
13000 0 : JHIG = JHIG + 1
13001 0 : IHIGT (JHIG) = IHIGT (1)
13002 0 : IHIGT (1) = ICRS
13003 : End If
13004 0 : ElseIf (XDONT(ICRS) > XDONT(IHIGT(1))) Then
13005 0 : JHIG = JHIG + 1
13006 0 : IHIGT (JHIG) = ICRS
13007 : End If
13008 : !
13009 0 : If (NDON <= ICRS) Then
13010 0 : NORD = Min (NORD, JHIG + 1)
13011 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
13012 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
13013 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
13014 0 : Return
13015 : End If
13016 : !
13017 0 : If (XDONT(NDON) < XDONT(IHIGT(1))) Then
13018 0 : If (XDONT(NDON) < XDONT(ILOWT(1))) Then
13019 0 : Do IDCR = JHIG, 1, -1
13020 0 : IHIGT (IDCR + 1) = IHIGT (IDCR)
13021 : End Do
13022 0 : IHIGT (1) = ILOWT (1)
13023 0 : ILOWT (1) = NDON
13024 0 : JHIG = JHIG + 1
13025 0 : ElseIf (XDONT(NDON) > XDONT(ILOWT(1))) Then
13026 0 : Do IDCR = JHIG, 1, -1
13027 0 : IHIGT (IDCR + 1) = IHIGT (IDCR)
13028 : End Do
13029 0 : IHIGT (1) = NDON
13030 0 : JHIG = JHIG + 1
13031 : End If
13032 0 : ElseIf (XDONT(NDON) > XDONT(IHIGT(1))) Then
13033 0 : JHIG = JHIG + 1
13034 0 : IHIGT (JHIG) = NDON
13035 : End If
13036 : !
13037 0 : If (NDON <= ICRS + 1) Then
13038 0 : NORD = Min (NORD, JHIG + 1)
13039 0 : If (NORD >= 1) IRNGT (1) = ILOWT (1)
13040 0 : If (NORD >= 2) IRNGT (2) = IHIGT (1)
13041 0 : If (NORD >= 3) IRNGT (3) = IHIGT (2)
13042 0 : If (NORD >= 4) IRNGT (4) = IHIGT (3)
13043 0 : Return
13044 : End If
13045 : !
13046 0 : JDEB = 0
13047 0 : IDEB = JDEB + 1
13048 0 : JLOW = IDEB
13049 0 : XPIV = XDONT (ILOWT(IDEB)) + INT(REAL(2 * NORD, sp) / REAL(NDON + NORD, sp), i4) * &
13050 0 : (XDONT(IHIGT(3)) - XDONT(ILOWT(IDEB)))
13051 0 : If (XPIV >= XDONT(IHIGT(1))) Then
13052 : XPIV = XDONT (ILOWT(IDEB)) + INT(REAL(2 * NORD, sp) / REAL(NDON + NORD, sp), i4) * &
13053 0 : (XDONT(IHIGT(2)) - XDONT(ILOWT(IDEB)))
13054 0 : If (XPIV >= XDONT(IHIGT(1))) &
13055 : XPIV = XDONT (ILOWT(IDEB)) + INT(REAL(2 * NORD, sp) / REAL(NDON + NORD, sp), i4) * &
13056 0 : (XDONT(IHIGT(1)) - XDONT(ILOWT(IDEB)))
13057 : End If
13058 0 : XPIV0 = XPIV
13059 : !
13060 : ! One puts values > pivot in the end and those <= pivot
13061 : ! at the beginning. This is split in 2 cases, so that
13062 : ! we can skip the loop test a number of times.
13063 : ! As we are also filling in the work arrays at the same time
13064 : ! we stop filling in the IHIGT array as soon as we have more
13065 : ! than enough values in ILOWT, i.e. one more than
13066 : ! strictly necessary so as to be able to come out of the
13067 : ! case where JLOWT would be NORD distinct values followed
13068 : ! by values that are exclusively duplicates of these.
13069 : !
13070 : !
13071 0 : If (XDONT(NDON) > XPIV) Then
13072 : lowloop1 : Do
13073 0 : ICRS = ICRS + 1
13074 0 : If (XDONT(ICRS) > XPIV) Then
13075 0 : If (ICRS >= NDON) Exit
13076 0 : JHIG = JHIG + 1
13077 0 : IHIGT (JHIG) = ICRS
13078 : Else
13079 0 : Do ILOW = 1, JLOW
13080 0 : If (XDONT(ICRS) == XDONT(ILOWT(ILOW))) Cycle lowloop1
13081 : End Do
13082 0 : JLOW = JLOW + 1
13083 0 : ILOWT (JLOW) = ICRS
13084 0 : If (JLOW >= NORD) Exit
13085 : End If
13086 : End Do lowloop1
13087 : !
13088 : ! One restricts further processing because it is no use
13089 : ! to store more high values
13090 : !
13091 0 : If (ICRS < NDON - 1) Then
13092 : Do
13093 0 : ICRS = ICRS + 1
13094 0 : If (XDONT(ICRS) <= XPIV) Then
13095 0 : JLOW = JLOW + 1
13096 0 : ILOWT (JLOW) = ICRS
13097 0 : Else If (ICRS >= NDON) Then
13098 : Exit
13099 : End If
13100 : End Do
13101 : End If
13102 : !
13103 : !
13104 : Else
13105 : !
13106 : ! Same as above, but this is not as easy to optimize, so the
13107 : ! DO-loop is kept
13108 : !
13109 0 : lowloop2 : Do ICRS = ICRS + 1, NDON - 1
13110 0 : If (XDONT(ICRS) > XPIV) Then
13111 0 : JHIG = JHIG + 1
13112 0 : IHIGT (JHIG) = ICRS
13113 : Else
13114 0 : Do ILOW = 1, JLOW
13115 0 : If (XDONT(ICRS) == XDONT (ILOWT(ILOW))) Cycle lowloop2
13116 : End Do
13117 0 : JLOW = JLOW + 1
13118 0 : ILOWT (JLOW) = ICRS
13119 0 : If (JLOW >= NORD) Exit
13120 : End If
13121 : End Do lowloop2
13122 : !
13123 0 : If (ICRS < NDON - 1) Then
13124 : Do
13125 0 : ICRS = ICRS + 1
13126 0 : If (XDONT(ICRS) <= XPIV) Then
13127 0 : If (ICRS >= NDON) Exit
13128 0 : JLOW = JLOW + 1
13129 0 : ILOWT (JLOW) = ICRS
13130 : End If
13131 : End Do
13132 : End If
13133 : End If
13134 : !
13135 : JLM2 = 0
13136 : JLM1 = 0
13137 : JHM2 = 0
13138 : JHM1 = 0
13139 : Do
13140 0 : if (JLOW == NORD) Exit
13141 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
13142 : !
13143 : ! We are oscillating. Perturbate by bringing JLOW closer by one
13144 : ! to NORD
13145 : !
13146 0 : If (NORD > JLOW) Then
13147 0 : XMIN = XDONT (IHIGT(1))
13148 0 : IHIG = 1
13149 0 : Do ICRS = 2, JHIG
13150 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
13151 0 : XMIN = XDONT (IHIGT(ICRS))
13152 0 : IHIG = ICRS
13153 : End If
13154 : End Do
13155 : !
13156 0 : JLOW = JLOW + 1
13157 0 : ILOWT (JLOW) = IHIGT (IHIG)
13158 0 : IHIG = 0
13159 0 : Do ICRS = 1, JHIG
13160 0 : If (XDONT(IHIGT (ICRS)) /= XMIN) then
13161 0 : IHIG = IHIG + 1
13162 0 : IHIGT (IHIG) = IHIGT (ICRS)
13163 : End If
13164 : End Do
13165 : JHIG = IHIG
13166 : Else
13167 0 : ILOW = ILOWT (JLOW)
13168 0 : XMAX = XDONT (ILOW)
13169 0 : Do ICRS = 1, JLOW
13170 0 : If (XDONT(ILOWT(ICRS)) > XMAX) Then
13171 0 : IWRK = ILOWT (ICRS)
13172 0 : XMAX = XDONT (IWRK)
13173 0 : ILOWT (ICRS) = ILOW
13174 0 : ILOW = IWRK
13175 : End If
13176 : End Do
13177 0 : JLOW = JLOW - 1
13178 : End If
13179 : End If
13180 0 : JLM2 = JLM1
13181 0 : JLM1 = JLOW
13182 0 : JHM2 = JHM1
13183 0 : JHM1 = JHIG
13184 : !
13185 : ! We try to bring the number of values in the low values set
13186 : ! closer to NORD. In order to make better pivot choices, we
13187 : ! decrease NORD if we already know that we don't have that
13188 : ! many distinct values as a whole.
13189 : !
13190 0 : IF (JLOW + JHIG < NORD) NORD = JLOW + JHIG
13191 0 : Select Case (NORD - JLOW)
13192 : ! ______________________________
13193 : Case (2 :)
13194 : !
13195 : ! Not enough values in low part, at least 2 are missing
13196 : !
13197 0 : Select Case (JHIG)
13198 : !
13199 : ! Not enough values in high part either (too many duplicates)
13200 : !
13201 : Case (0)
13202 0 : NORD = JLOW
13203 : !
13204 : Case (1)
13205 0 : JLOW = JLOW + 1
13206 0 : ILOWT (JLOW) = IHIGT (1)
13207 0 : NORD = JLOW
13208 : !
13209 : ! We make a special case when we have so few values in
13210 : ! the high values set that it is bad performance to choose a pivot
13211 : ! and apply the general algorithm.
13212 : !
13213 : Case (2)
13214 0 : If (XDONT(IHIGT(1)) <= XDONT(IHIGT(2))) Then
13215 0 : JLOW = JLOW + 1
13216 0 : ILOWT (JLOW) = IHIGT (1)
13217 0 : JLOW = JLOW + 1
13218 0 : ILOWT (JLOW) = IHIGT (2)
13219 : ElseIf (XDONT(IHIGT(1)) == XDONT(IHIGT(2))) Then
13220 : JLOW = JLOW + 1
13221 : ILOWT (JLOW) = IHIGT (1)
13222 : NORD = JLOW
13223 : Else
13224 0 : JLOW = JLOW + 1
13225 0 : ILOWT (JLOW) = IHIGT (2)
13226 0 : JLOW = JLOW + 1
13227 0 : ILOWT (JLOW) = IHIGT (1)
13228 : End If
13229 : Exit
13230 : !
13231 : Case (3)
13232 : !
13233 : !
13234 0 : IWRK1 = IHIGT (1)
13235 0 : IWRK2 = IHIGT (2)
13236 0 : IWRK3 = IHIGT (3)
13237 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
13238 0 : IHIGT (1) = IWRK2
13239 0 : IHIGT (2) = IWRK1
13240 0 : IWRK2 = IWRK1
13241 : End If
13242 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
13243 0 : IHIGT (3) = IWRK2
13244 0 : IHIGT (2) = IWRK3
13245 0 : IWRK2 = IWRK3
13246 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
13247 0 : IHIGT (2) = IHIGT (1)
13248 0 : IHIGT (1) = IWRK2
13249 : End If
13250 : End If
13251 0 : JHIG = 1
13252 0 : JLOW = JLOW + 1
13253 0 : ILOWT (JLOW) = IHIGT (1)
13254 0 : JHIG = JHIG + 1
13255 0 : IF (XDONT(IHIGT(JHIG)) /= XDONT(ILOWT(JLOW))) Then
13256 0 : JLOW = JLOW + 1
13257 0 : ILOWT (JLOW) = IHIGT (JHIG)
13258 : End If
13259 0 : JHIG = JHIG + 1
13260 0 : IF (XDONT(IHIGT(JHIG)) /= XDONT(ILOWT(JLOW))) Then
13261 0 : JLOW = JLOW + 1
13262 0 : ILOWT (JLOW) = IHIGT (JHIG)
13263 : End If
13264 0 : NORD = Min (JLOW, NORD)
13265 0 : Exit
13266 : !
13267 : Case (4 :)
13268 : !
13269 : !
13270 0 : XPIV0 = XPIV
13271 0 : IFIN = JHIG
13272 : !
13273 : ! One chooses a pivot from the 2 first values and the last one.
13274 : ! This should ensure sufficient renewal between iterations to
13275 : ! avoid worst case behavior effects.
13276 : !
13277 0 : IWRK1 = IHIGT (1)
13278 0 : IWRK2 = IHIGT (2)
13279 0 : IWRK3 = IHIGT (IFIN)
13280 0 : If (XDONT(IWRK2) < XDONT(IWRK1)) Then
13281 0 : IHIGT (1) = IWRK2
13282 0 : IHIGT (2) = IWRK1
13283 0 : IWRK2 = IWRK1
13284 : End If
13285 0 : If (XDONT(IWRK2) > XDONT(IWRK3)) Then
13286 0 : IHIGT (IFIN) = IWRK2
13287 0 : IHIGT (2) = IWRK3
13288 0 : IWRK2 = IWRK3
13289 0 : If (XDONT(IWRK2) < XDONT(IHIGT(1))) Then
13290 0 : IHIGT (2) = IHIGT (1)
13291 0 : IHIGT (1) = IWRK2
13292 : End If
13293 : End If
13294 : !
13295 0 : JDEB = JLOW
13296 0 : NWRK = NORD - JLOW
13297 0 : IWRK1 = IHIGT (1)
13298 0 : XPIV = XDONT (IWRK1) + INT(REAL(NWRK, sp) / REAL(NORD + NWRK, sp), i4) * &
13299 0 : (XDONT(IHIGT(IFIN)) - XDONT(IWRK1))
13300 : !
13301 : ! One takes values <= pivot to ILOWT
13302 : ! Again, 2 parts, one where we take care of the remaining
13303 : ! high values because we might still need them, and the
13304 : ! other when we know that we will have more than enough
13305 : ! low values in the end.
13306 : !
13307 0 : JHIG = 0
13308 0 : lowloop3 : Do ICRS = 1, IFIN
13309 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
13310 0 : Do ILOW = 1, JLOW
13311 0 : If (XDONT(IHIGT(ICRS)) == XDONT (ILOWT(ILOW))) &
13312 0 : Cycle lowloop3
13313 : End Do
13314 0 : JLOW = JLOW + 1
13315 0 : ILOWT (JLOW) = IHIGT (ICRS)
13316 0 : If (JLOW > NORD) Exit
13317 : Else
13318 0 : JHIG = JHIG + 1
13319 0 : IHIGT (JHIG) = IHIGT (ICRS)
13320 : End If
13321 : End Do lowloop3
13322 : !
13323 0 : Do ICRS = ICRS + 1, IFIN
13324 0 : If (XDONT(IHIGT(ICRS)) <= XPIV) Then
13325 0 : JLOW = JLOW + 1
13326 0 : ILOWT (JLOW) = IHIGT (ICRS)
13327 : End If
13328 : End Do
13329 : End Select
13330 : !
13331 : ! ______________________________
13332 : !
13333 : Case (1)
13334 : !
13335 : ! Only 1 value is missing in low part
13336 : !
13337 0 : XMIN = XDONT (IHIGT(1))
13338 0 : IHIG = 1
13339 0 : Do ICRS = 2, JHIG
13340 0 : If (XDONT(IHIGT(ICRS)) < XMIN) Then
13341 0 : XMIN = XDONT (IHIGT(ICRS))
13342 0 : IHIG = ICRS
13343 : End If
13344 : End Do
13345 : !
13346 0 : JLOW = JLOW + 1
13347 0 : ILOWT (JLOW) = IHIGT (IHIG)
13348 0 : Exit
13349 : !
13350 : ! ______________________________
13351 : !
13352 : Case (0)
13353 : !
13354 : ! Low part is exactly what we want
13355 : !
13356 0 : Exit
13357 : !
13358 : ! ______________________________
13359 : !
13360 : Case (-5 : -1)
13361 : !
13362 : ! Only few values too many in low part
13363 : !
13364 0 : IRNGT (1) = ILOWT (1)
13365 0 : Do ICRS = 2, NORD
13366 0 : IWRK = ILOWT (ICRS)
13367 0 : XWRK = XDONT (IWRK)
13368 0 : Do IDCR = ICRS - 1, 1, - 1
13369 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
13370 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
13371 : Else
13372 : Exit
13373 : End If
13374 : End Do
13375 0 : IRNGT (IDCR + 1) = IWRK
13376 : End Do
13377 : !
13378 0 : XWRK1 = XDONT (IRNGT(NORD))
13379 0 : insert1 : Do ICRS = NORD + 1, JLOW
13380 0 : If (XDONT(ILOWT (ICRS)) < XWRK1) Then
13381 0 : XWRK = XDONT (ILOWT (ICRS))
13382 0 : Do ILOW = 1, NORD - 1
13383 0 : If (XWRK <= XDONT(IRNGT(ILOW))) Then
13384 0 : If (XWRK == XDONT(IRNGT(ILOW))) Cycle insert1
13385 : Exit
13386 : End If
13387 : End Do
13388 0 : Do IDCR = NORD - 1, ILOW, - 1
13389 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
13390 : End Do
13391 0 : IRNGT (IDCR + 1) = ILOWT (ICRS)
13392 0 : XWRK1 = XDONT (IRNGT(NORD))
13393 : End If
13394 : End Do insert1
13395 : !
13396 0 : Return
13397 : !
13398 : ! ______________________________
13399 : !
13400 : Case (: -6)
13401 : !
13402 : ! last case: too many values in low part
13403 : !
13404 0 : IDEB = JDEB + 1
13405 0 : IMIL = MIN ((JLOW + IDEB) / 2, NORD)
13406 0 : IFIN = MIN (JLOW, NORD + 1)
13407 : !
13408 : ! One chooses a pivot from 1st, last, and middle values
13409 : !
13410 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
13411 0 : IWRK = ILOWT (IDEB)
13412 0 : ILOWT (IDEB) = ILOWT (IMIL)
13413 0 : ILOWT (IMIL) = IWRK
13414 : End If
13415 0 : If (XDONT(ILOWT(IMIL)) > XDONT(ILOWT(IFIN))) Then
13416 0 : IWRK = ILOWT (IFIN)
13417 0 : ILOWT (IFIN) = ILOWT (IMIL)
13418 0 : ILOWT (IMIL) = IWRK
13419 0 : If (XDONT(ILOWT(IMIL)) < XDONT(ILOWT(IDEB))) Then
13420 0 : IWRK = ILOWT (IDEB)
13421 0 : ILOWT (IDEB) = ILOWT (IMIL)
13422 0 : ILOWT (IMIL) = IWRK
13423 : End If
13424 : End If
13425 0 : If (IFIN <= 3) Exit
13426 : !
13427 0 : XPIV = XDONT (ILOWT(IDEB)) + INT(REAL(NORD, sp) / REAL(JLOW + NORD, sp), i4) * &
13428 0 : (XDONT(ILOWT(IFIN)) - XDONT(ILOWT(1)))
13429 0 : If (JDEB > 0) Then
13430 0 : If (XPIV <= XPIV0) &
13431 : XPIV = XPIV0 + INT(REAL(2 * NORD - JDEB, sp) / REAL(JLOW + NORD, sp), i4) * &
13432 0 : (XDONT(ILOWT(IFIN)) - XPIV0)
13433 : Else
13434 : IDEB = 1
13435 : End If
13436 : !
13437 : ! One takes values > XPIV to IHIGT
13438 : ! However, we do not process the first values if we have been
13439 : ! through the case when we did not have enough low values
13440 : !
13441 0 : JHIG = 0
13442 0 : IFIN = JLOW
13443 0 : JLOW = JDEB
13444 : !
13445 0 : If (XDONT(ILOWT(IFIN)) > XPIV) Then
13446 : ICRS = JDEB
13447 : lowloop4 : Do
13448 0 : ICRS = ICRS + 1
13449 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
13450 0 : JHIG = JHIG + 1
13451 0 : IHIGT (JHIG) = ILOWT (ICRS)
13452 0 : If (ICRS >= IFIN) Exit
13453 : Else
13454 0 : XWRK1 = XDONT(ILOWT(ICRS))
13455 0 : Do ILOW = IDEB, JLOW
13456 0 : If (XWRK1 == XDONT(ILOWT(ILOW))) &
13457 0 : Cycle lowloop4
13458 : End Do
13459 0 : JLOW = JLOW + 1
13460 0 : ILOWT (JLOW) = ILOWT (ICRS)
13461 0 : If (JLOW >= NORD) Exit
13462 : End If
13463 : End Do lowloop4
13464 : !
13465 0 : If (ICRS < IFIN) Then
13466 : Do
13467 0 : ICRS = ICRS + 1
13468 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
13469 0 : JLOW = JLOW + 1
13470 0 : ILOWT (JLOW) = ILOWT (ICRS)
13471 : Else
13472 0 : If (ICRS >= IFIN) Exit
13473 : End If
13474 : End Do
13475 : End If
13476 : Else
13477 0 : lowloop5 : Do ICRS = IDEB, IFIN
13478 0 : If (XDONT(ILOWT(ICRS)) > XPIV) Then
13479 0 : JHIG = JHIG + 1
13480 0 : IHIGT (JHIG) = ILOWT (ICRS)
13481 : Else
13482 0 : XWRK1 = XDONT(ILOWT(ICRS))
13483 0 : Do ILOW = IDEB, JLOW
13484 0 : If (XWRK1 == XDONT(ILOWT(ILOW))) &
13485 0 : Cycle lowloop5
13486 : End Do
13487 0 : JLOW = JLOW + 1
13488 0 : ILOWT (JLOW) = ILOWT (ICRS)
13489 0 : If (JLOW >= NORD) Exit
13490 : End If
13491 : End Do lowloop5
13492 : !
13493 0 : Do ICRS = ICRS + 1, IFIN
13494 0 : If (XDONT(ILOWT(ICRS)) <= XPIV) Then
13495 0 : JLOW = JLOW + 1
13496 0 : ILOWT (JLOW) = ILOWT (ICRS)
13497 : End If
13498 : End Do
13499 : End If
13500 : !
13501 : End Select
13502 : ! ______________________________
13503 : !
13504 : End Do
13505 : !
13506 : ! Now, we only need to complete ranking of the 1:NORD set
13507 : ! Assuming NORD is small, we use a simple insertion sort
13508 : !
13509 0 : IRNGT (1) = ILOWT (1)
13510 0 : Do ICRS = 2, NORD
13511 0 : IWRK = ILOWT (ICRS)
13512 0 : XWRK = XDONT (IWRK)
13513 0 : Do IDCR = ICRS - 1, 1, - 1
13514 0 : If (XWRK < XDONT(IRNGT(IDCR))) Then
13515 0 : IRNGT (IDCR + 1) = IRNGT (IDCR)
13516 : Else
13517 : Exit
13518 : End If
13519 : End Do
13520 0 : IRNGT (IDCR + 1) = IWRK
13521 : End Do
13522 : Return
13523 : !
13524 : !
13525 0 : End Subroutine I_unipar
13526 :
13527 0 : Subroutine D_unirnk (XVALT, IRNGT, NUNI)
13528 : ! __________________________________________________________
13529 : ! UNIRNK = Merge-sort ranking of an array, with removal of
13530 : ! duplicate entries.
13531 : ! The routine is similar to pure merge-sort ranking, but on
13532 : ! the last pass, it discards indices that correspond to
13533 : ! duplicate entries.
13534 : ! For performance reasons, the first 2 passes are taken
13535 : ! out of the standard loop, and use dedicated coding.
13536 : ! __________________________________________________________
13537 : ! __________________________________________________________
13538 : real(Kind = dp), Dimension (:), Intent (In) :: XVALT
13539 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
13540 : Integer(kind = i4), Intent (Out) :: NUNI
13541 : ! __________________________________________________________
13542 0 : Integer(kind = i4), Dimension (SIZE(IRNGT)) :: JWRKT
13543 : Integer(kind = i4) :: LMTNA, LMTNC, IRNG, IRNG1, IRNG2
13544 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
13545 0 : real(Kind = dp) :: XTST, XVALA, XVALB
13546 : !
13547 : !
13548 0 : NVAL = Min (SIZE(XVALT), SIZE(IRNGT))
13549 0 : NUNI = NVAL
13550 : !
13551 : Select Case (NVAL)
13552 : Case (: 0)
13553 0 : Return
13554 : Case (1)
13555 0 : IRNGT (1) = 1
13556 0 : Return
13557 : Case Default
13558 :
13559 : End Select
13560 : !
13561 : ! Fill-in the index array, creating ordered couples
13562 : !
13563 0 : Do IIND = 2, NVAL, 2
13564 0 : If (XVALT(IIND - 1) < XVALT(IIND)) Then
13565 0 : IRNGT (IIND - 1) = IIND - 1
13566 0 : IRNGT (IIND) = IIND
13567 : Else
13568 0 : IRNGT (IIND - 1) = IIND
13569 0 : IRNGT (IIND) = IIND - 1
13570 : End If
13571 : End Do
13572 0 : If (Modulo(NVAL, 2) /= 0) Then
13573 0 : IRNGT (NVAL) = NVAL
13574 : End If
13575 : !
13576 : ! We will now have ordered subsets A - B - A - B - ...
13577 : ! and merge A and B couples into C - C - ...
13578 : !
13579 0 : LMTNA = 2
13580 0 : LMTNC = 4
13581 : !
13582 : ! First iteration. The length of the ordered subsets goes from 2 to 4
13583 : !
13584 : Do
13585 0 : If (NVAL <= 4) Exit
13586 : !
13587 : ! Loop on merges of A and B into C
13588 : !
13589 0 : Do IWRKD = 0, NVAL - 1, 4
13590 0 : If ((IWRKD + 4) > NVAL) Then
13591 0 : If ((IWRKD + 2) >= NVAL) Exit
13592 : !
13593 : ! 1 2 3
13594 : !
13595 0 : If (XVALT(IRNGT(IWRKD + 2)) <= XVALT(IRNGT(IWRKD + 3))) Exit
13596 : !
13597 : ! 1 3 2
13598 : !
13599 0 : If (XVALT(IRNGT(IWRKD + 1)) <= XVALT(IRNGT(IWRKD + 3))) Then
13600 0 : IRNG2 = IRNGT (IWRKD + 2)
13601 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
13602 0 : IRNGT (IWRKD + 3) = IRNG2
13603 : !
13604 : ! 3 1 2
13605 : !
13606 : Else
13607 0 : IRNG1 = IRNGT (IWRKD + 1)
13608 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
13609 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 2)
13610 0 : IRNGT (IWRKD + 2) = IRNG1
13611 : End If
13612 : If (.true.) Exit ! Exit ! JM
13613 : End If
13614 : !
13615 : ! 1 2 3 4
13616 : !
13617 0 : If (XVALT(IRNGT(IWRKD + 2)) <= XVALT(IRNGT(IWRKD + 3))) Cycle
13618 : !
13619 : ! 1 3 x x
13620 : !
13621 0 : If (XVALT(IRNGT(IWRKD + 1)) <= XVALT(IRNGT(IWRKD + 3))) Then
13622 0 : IRNG2 = IRNGT (IWRKD + 2)
13623 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
13624 0 : If (XVALT(IRNG2) <= XVALT(IRNGT(IWRKD + 4))) Then
13625 : ! 1 3 2 4
13626 0 : IRNGT (IWRKD + 3) = IRNG2
13627 : Else
13628 : ! 1 3 4 2
13629 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
13630 0 : IRNGT (IWRKD + 4) = IRNG2
13631 : End If
13632 : !
13633 : ! 3 x x x
13634 : !
13635 : Else
13636 0 : IRNG1 = IRNGT (IWRKD + 1)
13637 0 : IRNG2 = IRNGT (IWRKD + 2)
13638 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
13639 0 : If (XVALT(IRNG1) <= XVALT(IRNGT(IWRKD + 4))) Then
13640 0 : IRNGT (IWRKD + 2) = IRNG1
13641 0 : If (XVALT(IRNG2) <= XVALT(IRNGT(IWRKD + 4))) Then
13642 : ! 3 1 2 4
13643 0 : IRNGT (IWRKD + 3) = IRNG2
13644 : Else
13645 : ! 3 1 4 2
13646 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
13647 0 : IRNGT (IWRKD + 4) = IRNG2
13648 : End If
13649 : Else
13650 : ! 3 4 1 2
13651 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 4)
13652 0 : IRNGT (IWRKD + 3) = IRNG1
13653 0 : IRNGT (IWRKD + 4) = IRNG2
13654 : End If
13655 : End If
13656 : End Do
13657 : !
13658 : ! The Cs become As and Bs
13659 : !
13660 : LMTNA = 4
13661 0 : If (.true.) Exit ! Exit ! JM
13662 : End Do
13663 : !
13664 : ! Iteration loop. Each time, the length of the ordered subsets
13665 : ! is doubled.
13666 : !
13667 : Do
13668 0 : If (2 * LMTNA >= NVAL) Exit
13669 0 : IWRKF = 0
13670 0 : LMTNC = 2 * LMTNC
13671 : !
13672 : ! Loop on merges of A and B into C
13673 : !
13674 : Do
13675 0 : IWRK = IWRKF
13676 0 : IWRKD = IWRKF + 1
13677 0 : JINDA = IWRKF + LMTNA
13678 0 : IWRKF = IWRKF + LMTNC
13679 0 : If (IWRKF >= NVAL) Then
13680 0 : If (JINDA >= NVAL) Exit
13681 : IWRKF = NVAL
13682 : End If
13683 0 : IINDA = 1
13684 0 : IINDB = JINDA + 1
13685 : !
13686 : ! One steps in the C subset, that we create in the final rank array
13687 : !
13688 : ! Make a copy of the rank array for the iteration
13689 : !
13690 0 : JWRKT (1 : LMTNA) = IRNGT (IWRKD : JINDA)
13691 0 : XVALA = XVALT (JWRKT(IINDA))
13692 0 : XVALB = XVALT (IRNGT(IINDB))
13693 : !
13694 0 : Do
13695 0 : IWRK = IWRK + 1
13696 : !
13697 : ! We still have unprocessed values in both A and B
13698 : !
13699 0 : If (XVALA > XVALB) Then
13700 0 : IRNGT (IWRK) = IRNGT (IINDB)
13701 0 : IINDB = IINDB + 1
13702 0 : If (IINDB > IWRKF) Then
13703 : ! Only A still with unprocessed values
13704 0 : IRNGT (IWRK + 1 : IWRKF) = JWRKT (IINDA : LMTNA)
13705 : Exit
13706 : End If
13707 0 : XVALB = XVALT (IRNGT(IINDB))
13708 : Else
13709 0 : IRNGT (IWRK) = JWRKT (IINDA)
13710 0 : IINDA = IINDA + 1
13711 0 : If (IINDA > LMTNA) Exit! Only B still with unprocessed values
13712 0 : XVALA = XVALT (JWRKT(IINDA))
13713 : End If
13714 : !
13715 : End Do
13716 : End Do
13717 : !
13718 : ! The Cs become As and Bs
13719 : !
13720 0 : LMTNA = 2 * LMTNA
13721 : End Do
13722 : !
13723 : ! Last merge of A and B into C, with removal of duplicates.
13724 : !
13725 0 : IINDA = 1
13726 0 : IINDB = LMTNA + 1
13727 0 : NUNI = 0
13728 : !
13729 : ! One steps in the C subset, that we create in the final rank array
13730 : !
13731 0 : JWRKT (1 : LMTNA) = IRNGT (1 : LMTNA)
13732 0 : If (IINDB <= NVAL) Then
13733 0 : XTST = NEARLESS (Min(XVALT(JWRKT(1)), XVALT(IRNGT(IINDB))))
13734 : Else
13735 0 : XTST = NEARLESS (XVALT(JWRKT(1)))
13736 : end if
13737 0 : Do IWRK = 1, NVAL
13738 : !
13739 : ! We still have unprocessed values in both A and B
13740 : !
13741 0 : If (IINDA <= LMTNA) Then
13742 0 : If (IINDB <= NVAL) Then
13743 0 : If (XVALT(JWRKT(IINDA)) > XVALT(IRNGT(IINDB))) Then
13744 0 : IRNG = IRNGT (IINDB)
13745 0 : IINDB = IINDB + 1
13746 : Else
13747 0 : IRNG = JWRKT (IINDA)
13748 0 : IINDA = IINDA + 1
13749 : End If
13750 : Else
13751 : !
13752 : ! Only A still with unprocessed values
13753 : !
13754 0 : IRNG = JWRKT (IINDA)
13755 0 : IINDA = IINDA + 1
13756 : End If
13757 : Else
13758 : !
13759 : ! Only B still with unprocessed values
13760 : !
13761 0 : IRNG = IRNGT (IWRK)
13762 : End If
13763 0 : If (XVALT(IRNG) > XTST) Then
13764 0 : XTST = XVALT (IRNG)
13765 0 : NUNI = NUNI + 1
13766 0 : IRNGT (NUNI) = IRNG
13767 : End If
13768 : !
13769 : End Do
13770 : !
13771 : Return
13772 : !
13773 0 : End Subroutine D_unirnk
13774 :
13775 0 : Subroutine R_unirnk (XVALT, IRNGT, NUNI)
13776 : ! __________________________________________________________
13777 : ! UNIRNK = Merge-sort ranking of an array, with removal of
13778 : ! duplicate entries.
13779 : ! The routine is similar to pure merge-sort ranking, but on
13780 : ! the last pass, it discards indices that correspond to
13781 : ! duplicate entries.
13782 : ! For performance reasons, the first 2 passes are taken
13783 : ! out of the standard loop, and use dedicated coding.
13784 : ! __________________________________________________________
13785 : ! __________________________________________________________
13786 : Real(kind = sp), Dimension (:), Intent (In) :: XVALT
13787 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
13788 : Integer(kind = i4), Intent (Out) :: NUNI
13789 : ! __________________________________________________________
13790 0 : Integer(kind = i4), Dimension (SIZE(IRNGT)) :: JWRKT
13791 : Integer(kind = i4) :: LMTNA, LMTNC, IRNG, IRNG1, IRNG2
13792 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
13793 0 : Real(kind = sp) :: XTST, XVALA, XVALB
13794 : !
13795 : !
13796 0 : NVAL = Min (SIZE(XVALT), SIZE(IRNGT))
13797 0 : NUNI = NVAL
13798 : !
13799 : Select Case (NVAL)
13800 : Case (: 0)
13801 0 : Return
13802 : Case (1)
13803 0 : IRNGT (1) = 1
13804 0 : Return
13805 : Case Default
13806 :
13807 : End Select
13808 : !
13809 : ! Fill-in the index array, creating ordered couples
13810 : !
13811 0 : Do IIND = 2, NVAL, 2
13812 0 : If (XVALT(IIND - 1) < XVALT(IIND)) Then
13813 0 : IRNGT (IIND - 1) = IIND - 1
13814 0 : IRNGT (IIND) = IIND
13815 : Else
13816 0 : IRNGT (IIND - 1) = IIND
13817 0 : IRNGT (IIND) = IIND - 1
13818 : End If
13819 : End Do
13820 0 : If (Modulo(NVAL, 2) /= 0) Then
13821 0 : IRNGT (NVAL) = NVAL
13822 : End If
13823 : !
13824 : ! We will now have ordered subsets A - B - A - B - ...
13825 : ! and merge A and B couples into C - C - ...
13826 : !
13827 0 : LMTNA = 2
13828 0 : LMTNC = 4
13829 : !
13830 : ! First iteration. The length of the ordered subsets goes from 2 to 4
13831 : !
13832 : Do
13833 0 : If (NVAL <= 4) Exit
13834 : !
13835 : ! Loop on merges of A and B into C
13836 : !
13837 0 : Do IWRKD = 0, NVAL - 1, 4
13838 0 : If ((IWRKD + 4) > NVAL) Then
13839 0 : If ((IWRKD + 2) >= NVAL) Exit
13840 : !
13841 : ! 1 2 3
13842 : !
13843 0 : If (XVALT(IRNGT(IWRKD + 2)) <= XVALT(IRNGT(IWRKD + 3))) Exit
13844 : !
13845 : ! 1 3 2
13846 : !
13847 0 : If (XVALT(IRNGT(IWRKD + 1)) <= XVALT(IRNGT(IWRKD + 3))) Then
13848 0 : IRNG2 = IRNGT (IWRKD + 2)
13849 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
13850 0 : IRNGT (IWRKD + 3) = IRNG2
13851 : !
13852 : ! 3 1 2
13853 : !
13854 : Else
13855 0 : IRNG1 = IRNGT (IWRKD + 1)
13856 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
13857 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 2)
13858 0 : IRNGT (IWRKD + 2) = IRNG1
13859 : End If
13860 : If (.true.) Exit ! Exit ! JM
13861 : End If
13862 : !
13863 : ! 1 2 3 4
13864 : !
13865 0 : If (XVALT(IRNGT(IWRKD + 2)) <= XVALT(IRNGT(IWRKD + 3))) Cycle
13866 : !
13867 : ! 1 3 x x
13868 : !
13869 0 : If (XVALT(IRNGT(IWRKD + 1)) <= XVALT(IRNGT(IWRKD + 3))) Then
13870 0 : IRNG2 = IRNGT (IWRKD + 2)
13871 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
13872 0 : If (XVALT(IRNG2) <= XVALT(IRNGT(IWRKD + 4))) Then
13873 : ! 1 3 2 4
13874 0 : IRNGT (IWRKD + 3) = IRNG2
13875 : Else
13876 : ! 1 3 4 2
13877 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
13878 0 : IRNGT (IWRKD + 4) = IRNG2
13879 : End If
13880 : !
13881 : ! 3 x x x
13882 : !
13883 : Else
13884 0 : IRNG1 = IRNGT (IWRKD + 1)
13885 0 : IRNG2 = IRNGT (IWRKD + 2)
13886 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
13887 0 : If (XVALT(IRNG1) <= XVALT(IRNGT(IWRKD + 4))) Then
13888 0 : IRNGT (IWRKD + 2) = IRNG1
13889 0 : If (XVALT(IRNG2) <= XVALT(IRNGT(IWRKD + 4))) Then
13890 : ! 3 1 2 4
13891 0 : IRNGT (IWRKD + 3) = IRNG2
13892 : Else
13893 : ! 3 1 4 2
13894 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
13895 0 : IRNGT (IWRKD + 4) = IRNG2
13896 : End If
13897 : Else
13898 : ! 3 4 1 2
13899 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 4)
13900 0 : IRNGT (IWRKD + 3) = IRNG1
13901 0 : IRNGT (IWRKD + 4) = IRNG2
13902 : End If
13903 : End If
13904 : End Do
13905 : !
13906 : ! The Cs become As and Bs
13907 : !
13908 : LMTNA = 4
13909 0 : If (.true.) Exit ! Exit ! JM
13910 : End Do
13911 : !
13912 : ! Iteration loop. Each time, the length of the ordered subsets
13913 : ! is doubled.
13914 : !
13915 : Do
13916 0 : If (2 * LMTNA >= NVAL) Exit
13917 0 : IWRKF = 0
13918 0 : LMTNC = 2 * LMTNC
13919 : !
13920 : ! Loop on merges of A and B into C
13921 : !
13922 : Do
13923 0 : IWRK = IWRKF
13924 0 : IWRKD = IWRKF + 1
13925 0 : JINDA = IWRKF + LMTNA
13926 0 : IWRKF = IWRKF + LMTNC
13927 0 : If (IWRKF >= NVAL) Then
13928 0 : If (JINDA >= NVAL) Exit
13929 : IWRKF = NVAL
13930 : End If
13931 0 : IINDA = 1
13932 0 : IINDB = JINDA + 1
13933 : !
13934 : ! One steps in the C subset, that we create in the final rank array
13935 : !
13936 : ! Make a copy of the rank array for the iteration
13937 : !
13938 0 : JWRKT (1 : LMTNA) = IRNGT (IWRKD : JINDA)
13939 0 : XVALA = XVALT (JWRKT(IINDA))
13940 0 : XVALB = XVALT (IRNGT(IINDB))
13941 : !
13942 0 : Do
13943 0 : IWRK = IWRK + 1
13944 : !
13945 : ! We still have unprocessed values in both A and B
13946 : !
13947 0 : If (XVALA > XVALB) Then
13948 0 : IRNGT (IWRK) = IRNGT (IINDB)
13949 0 : IINDB = IINDB + 1
13950 0 : If (IINDB > IWRKF) Then
13951 : ! Only A still with unprocessed values
13952 0 : IRNGT (IWRK + 1 : IWRKF) = JWRKT (IINDA : LMTNA)
13953 : Exit
13954 : End If
13955 0 : XVALB = XVALT (IRNGT(IINDB))
13956 : Else
13957 0 : IRNGT (IWRK) = JWRKT (IINDA)
13958 0 : IINDA = IINDA + 1
13959 0 : If (IINDA > LMTNA) Exit! Only B still with unprocessed values
13960 0 : XVALA = XVALT (JWRKT(IINDA))
13961 : End If
13962 : !
13963 : End Do
13964 : End Do
13965 : !
13966 : ! The Cs become As and Bs
13967 : !
13968 0 : LMTNA = 2 * LMTNA
13969 : End Do
13970 : !
13971 : ! Last merge of A and B into C, with removal of duplicates.
13972 : !
13973 0 : IINDA = 1
13974 0 : IINDB = LMTNA + 1
13975 0 : NUNI = 0
13976 : !
13977 : ! One steps in the C subset, that we create in the final rank array
13978 : !
13979 0 : JWRKT (1 : LMTNA) = IRNGT (1 : LMTNA)
13980 0 : If (IINDB <= NVAL) Then
13981 0 : XTST = NEARLESS (Min(XVALT(JWRKT(1)), XVALT(IRNGT(IINDB))))
13982 : Else
13983 0 : XTST = NEARLESS (XVALT(JWRKT(1)))
13984 : end if
13985 0 : Do IWRK = 1, NVAL
13986 : !
13987 : ! We still have unprocessed values in both A and B
13988 : !
13989 0 : If (IINDA <= LMTNA) Then
13990 0 : If (IINDB <= NVAL) Then
13991 0 : If (XVALT(JWRKT(IINDA)) > XVALT(IRNGT(IINDB))) Then
13992 0 : IRNG = IRNGT (IINDB)
13993 0 : IINDB = IINDB + 1
13994 : Else
13995 0 : IRNG = JWRKT (IINDA)
13996 0 : IINDA = IINDA + 1
13997 : End If
13998 : Else
13999 : !
14000 : ! Only A still with unprocessed values
14001 : !
14002 0 : IRNG = JWRKT (IINDA)
14003 0 : IINDA = IINDA + 1
14004 : End If
14005 : Else
14006 : !
14007 : ! Only B still with unprocessed values
14008 : !
14009 0 : IRNG = IRNGT (IWRK)
14010 : End If
14011 0 : If (XVALT(IRNG) > XTST) Then
14012 0 : XTST = XVALT (IRNG)
14013 0 : NUNI = NUNI + 1
14014 0 : IRNGT (NUNI) = IRNG
14015 : End If
14016 : !
14017 : End Do
14018 : !
14019 : Return
14020 : !
14021 0 : End Subroutine R_unirnk
14022 :
14023 0 : Subroutine I_unirnk (XVALT, IRNGT, NUNI)
14024 : ! __________________________________________________________
14025 : ! UNIRNK = Merge-sort ranking of an array, with removal of
14026 : ! duplicate entries.
14027 : ! The routine is similar to pure merge-sort ranking, but on
14028 : ! the last pass, it discards indices that correspond to
14029 : ! duplicate entries.
14030 : ! For performance reasons, the first 2 passes are taken
14031 : ! out of the standard loop, and use dedicated coding.
14032 : ! __________________________________________________________
14033 : ! __________________________________________________________
14034 : Integer(kind = i4), Dimension (:), Intent (In) :: XVALT
14035 : Integer(kind = i4), Dimension (:), Intent (Out) :: IRNGT
14036 : Integer(kind = i4), Intent (Out) :: NUNI
14037 : ! __________________________________________________________
14038 0 : Integer(kind = i4), Dimension (SIZE(IRNGT)) :: JWRKT
14039 : Integer(kind = i4) :: LMTNA, LMTNC, IRNG, IRNG1, IRNG2
14040 : Integer(kind = i4) :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
14041 : Integer(kind = i4) :: XTST, XVALA, XVALB
14042 : !
14043 : !
14044 0 : NVAL = Min (SIZE(XVALT), SIZE(IRNGT))
14045 0 : NUNI = NVAL
14046 : !
14047 : Select Case (NVAL)
14048 : Case (: 0)
14049 0 : Return
14050 : Case (1)
14051 0 : IRNGT (1) = 1
14052 0 : Return
14053 : Case Default
14054 :
14055 : End Select
14056 : !
14057 : ! Fill-in the index array, creating ordered couples
14058 : !
14059 0 : Do IIND = 2, NVAL, 2
14060 0 : If (XVALT(IIND - 1) < XVALT(IIND)) Then
14061 0 : IRNGT (IIND - 1) = IIND - 1
14062 0 : IRNGT (IIND) = IIND
14063 : Else
14064 0 : IRNGT (IIND - 1) = IIND
14065 0 : IRNGT (IIND) = IIND - 1
14066 : End If
14067 : End Do
14068 0 : If (Modulo(NVAL, 2) /= 0) Then
14069 0 : IRNGT (NVAL) = NVAL
14070 : End If
14071 : !
14072 : ! We will now have ordered subsets A - B - A - B - ...
14073 : ! and merge A and B couples into C - C - ...
14074 : !
14075 0 : LMTNA = 2
14076 0 : LMTNC = 4
14077 : !
14078 : ! First iteration. The length of the ordered subsets goes from 2 to 4
14079 : !
14080 : Do
14081 0 : If (NVAL <= 4) Exit
14082 : !
14083 : ! Loop on merges of A and B into C
14084 : !
14085 0 : Do IWRKD = 0, NVAL - 1, 4
14086 0 : If ((IWRKD + 4) > NVAL) Then
14087 0 : If ((IWRKD + 2) >= NVAL) Exit
14088 : !
14089 : ! 1 2 3
14090 : !
14091 0 : If (XVALT(IRNGT(IWRKD + 2)) <= XVALT(IRNGT(IWRKD + 3))) Exit
14092 : !
14093 : ! 1 3 2
14094 : !
14095 0 : If (XVALT(IRNGT(IWRKD + 1)) <= XVALT(IRNGT(IWRKD + 3))) Then
14096 0 : IRNG2 = IRNGT (IWRKD + 2)
14097 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
14098 0 : IRNGT (IWRKD + 3) = IRNG2
14099 : !
14100 : ! 3 1 2
14101 : !
14102 : Else
14103 0 : IRNG1 = IRNGT (IWRKD + 1)
14104 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
14105 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 2)
14106 0 : IRNGT (IWRKD + 2) = IRNG1
14107 : End If
14108 : If (.true.) Exit ! Exit ! JM
14109 : End If
14110 : !
14111 : ! 1 2 3 4
14112 : !
14113 0 : If (XVALT(IRNGT(IWRKD + 2)) <= XVALT(IRNGT(IWRKD + 3))) Cycle
14114 : !
14115 : ! 1 3 x x
14116 : !
14117 0 : If (XVALT(IRNGT(IWRKD + 1)) <= XVALT(IRNGT(IWRKD + 3))) Then
14118 0 : IRNG2 = IRNGT (IWRKD + 2)
14119 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 3)
14120 0 : If (XVALT(IRNG2) <= XVALT(IRNGT(IWRKD + 4))) Then
14121 : ! 1 3 2 4
14122 0 : IRNGT (IWRKD + 3) = IRNG2
14123 : Else
14124 : ! 1 3 4 2
14125 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
14126 0 : IRNGT (IWRKD + 4) = IRNG2
14127 : End If
14128 : !
14129 : ! 3 x x x
14130 : !
14131 : Else
14132 0 : IRNG1 = IRNGT (IWRKD + 1)
14133 0 : IRNG2 = IRNGT (IWRKD + 2)
14134 0 : IRNGT (IWRKD + 1) = IRNGT (IWRKD + 3)
14135 0 : If (XVALT(IRNG1) <= XVALT(IRNGT(IWRKD + 4))) Then
14136 0 : IRNGT (IWRKD + 2) = IRNG1
14137 0 : If (XVALT(IRNG2) <= XVALT(IRNGT(IWRKD + 4))) Then
14138 : ! 3 1 2 4
14139 0 : IRNGT (IWRKD + 3) = IRNG2
14140 : Else
14141 : ! 3 1 4 2
14142 0 : IRNGT (IWRKD + 3) = IRNGT (IWRKD + 4)
14143 0 : IRNGT (IWRKD + 4) = IRNG2
14144 : End If
14145 : Else
14146 : ! 3 4 1 2
14147 0 : IRNGT (IWRKD + 2) = IRNGT (IWRKD + 4)
14148 0 : IRNGT (IWRKD + 3) = IRNG1
14149 0 : IRNGT (IWRKD + 4) = IRNG2
14150 : End If
14151 : End If
14152 : End Do
14153 : !
14154 : ! The Cs become As and Bs
14155 : !
14156 : LMTNA = 4
14157 0 : If (.true.) Exit ! Exit ! JM
14158 : End Do
14159 : !
14160 : ! Iteration loop. Each time, the length of the ordered subsets
14161 : ! is doubled.
14162 : !
14163 : Do
14164 0 : If (2 * LMTNA >= NVAL) Exit
14165 0 : IWRKF = 0
14166 0 : LMTNC = 2 * LMTNC
14167 : !
14168 : ! Loop on merges of A and B into C
14169 : !
14170 : Do
14171 0 : IWRK = IWRKF
14172 0 : IWRKD = IWRKF + 1
14173 0 : JINDA = IWRKF + LMTNA
14174 0 : IWRKF = IWRKF + LMTNC
14175 0 : If (IWRKF >= NVAL) Then
14176 0 : If (JINDA >= NVAL) Exit
14177 : IWRKF = NVAL
14178 : End If
14179 0 : IINDA = 1
14180 0 : IINDB = JINDA + 1
14181 : !
14182 : ! One steps in the C subset, that we create in the final rank array
14183 : !
14184 : ! Make a copy of the rank array for the iteration
14185 : !
14186 0 : JWRKT (1 : LMTNA) = IRNGT (IWRKD : JINDA)
14187 0 : XVALA = XVALT (JWRKT(IINDA))
14188 0 : XVALB = XVALT (IRNGT(IINDB))
14189 : !
14190 0 : Do
14191 0 : IWRK = IWRK + 1
14192 : !
14193 : ! We still have unprocessed values in both A and B
14194 : !
14195 0 : If (XVALA > XVALB) Then
14196 0 : IRNGT (IWRK) = IRNGT (IINDB)
14197 0 : IINDB = IINDB + 1
14198 0 : If (IINDB > IWRKF) Then
14199 : ! Only A still with unprocessed values
14200 0 : IRNGT (IWRK + 1 : IWRKF) = JWRKT (IINDA : LMTNA)
14201 : Exit
14202 : End If
14203 0 : XVALB = XVALT (IRNGT(IINDB))
14204 : Else
14205 0 : IRNGT (IWRK) = JWRKT (IINDA)
14206 0 : IINDA = IINDA + 1
14207 0 : If (IINDA > LMTNA) Exit! Only B still with unprocessed values
14208 0 : XVALA = XVALT (JWRKT(IINDA))
14209 : End If
14210 : !
14211 : End Do
14212 : End Do
14213 : !
14214 : ! The Cs become As and Bs
14215 : !
14216 0 : LMTNA = 2 * LMTNA
14217 : End Do
14218 : !
14219 : ! Last merge of A and B into C, with removal of duplicates.
14220 : !
14221 0 : IINDA = 1
14222 0 : IINDB = LMTNA + 1
14223 0 : NUNI = 0
14224 : !
14225 : ! One steps in the C subset, that we create in the final rank array
14226 : !
14227 0 : JWRKT (1 : LMTNA) = IRNGT (1 : LMTNA)
14228 0 : If (IINDB <= NVAL) Then
14229 0 : XTST = NEARLESS (Min(XVALT(JWRKT(1)), XVALT(IRNGT(IINDB))))
14230 : Else
14231 0 : XTST = NEARLESS (XVALT(JWRKT(1)))
14232 : end if
14233 0 : Do IWRK = 1, NVAL
14234 : !
14235 : ! We still have unprocessed values in both A and B
14236 : !
14237 0 : If (IINDA <= LMTNA) Then
14238 0 : If (IINDB <= NVAL) Then
14239 0 : If (XVALT(JWRKT(IINDA)) > XVALT(IRNGT(IINDB))) Then
14240 0 : IRNG = IRNGT (IINDB)
14241 0 : IINDB = IINDB + 1
14242 : Else
14243 0 : IRNG = JWRKT (IINDA)
14244 0 : IINDA = IINDA + 1
14245 : End If
14246 : Else
14247 : !
14248 : ! Only A still with unprocessed values
14249 : !
14250 0 : IRNG = JWRKT (IINDA)
14251 0 : IINDA = IINDA + 1
14252 : End If
14253 : Else
14254 : !
14255 : ! Only B still with unprocessed values
14256 : !
14257 0 : IRNG = IRNGT (IWRK)
14258 : End If
14259 0 : If (XVALT(IRNG) > XTST) Then
14260 0 : XTST = XVALT (IRNG)
14261 0 : NUNI = NUNI + 1
14262 0 : IRNGT (NUNI) = IRNG
14263 : End If
14264 : !
14265 : End Do
14266 : !
14267 : Return
14268 : !
14269 0 : End Subroutine I_unirnk
14270 :
14271 :
14272 0 : Subroutine D_unista (XDONT, NUNI)
14273 : ! UNISTA = (Stable unique) Removes duplicates from an array,
14274 : ! leaving unique entries in the order of their first
14275 : ! appearance in the initial set.
14276 : ! Michel Olagnon - Feb. 2000
14277 : ! __________________________________________________________
14278 : ! __________________________________________________________
14279 : real(kind = dp), Dimension (:), Intent (InOut) :: XDONT
14280 : Integer(kind = i4), Intent (Out) :: NUNI
14281 : ! __________________________________________________________
14282 : !
14283 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: IWRKT
14284 0 : Logical, Dimension (Size(XDONT)) :: IFMPTYT
14285 : Integer(kind = i4) :: ICRS
14286 : ! __________________________________________________________
14287 0 : Call UNIINV (XDONT, IWRKT)
14288 0 : IFMPTYT = .True.
14289 0 : NUNI = 0
14290 0 : Do ICRS = 1, Size(XDONT)
14291 0 : If (IFMPTYT(IWRKT(ICRS))) Then
14292 0 : IFMPTYT(IWRKT(ICRS)) = .False.
14293 0 : NUNI = NUNI + 1
14294 0 : XDONT (NUNI) = XDONT (ICRS)
14295 : End If
14296 : End Do
14297 0 : Return
14298 : !
14299 0 : End Subroutine D_unista
14300 :
14301 0 : Subroutine R_unista (XDONT, NUNI)
14302 : ! UNISTA = (Stable unique) Removes duplicates from an array,
14303 : ! leaving unique entries in the order of their first
14304 : ! appearance in the initial set.
14305 : ! Michel Olagnon - Feb. 2000
14306 : ! __________________________________________________________
14307 : ! _________________________________________________________
14308 : Real(kind = sp), Dimension (:), Intent (InOut) :: XDONT
14309 : Integer(kind = i4), Intent (Out) :: NUNI
14310 : ! __________________________________________________________
14311 : !
14312 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: IWRKT
14313 0 : Logical, Dimension (Size(XDONT)) :: IFMPTYT
14314 : Integer(kind = i4) :: ICRS
14315 : ! __________________________________________________________
14316 0 : Call UNIINV (XDONT, IWRKT)
14317 0 : IFMPTYT = .True.
14318 0 : NUNI = 0
14319 0 : Do ICRS = 1, Size(XDONT)
14320 0 : If (IFMPTYT(IWRKT(ICRS))) Then
14321 0 : IFMPTYT(IWRKT(ICRS)) = .False.
14322 0 : NUNI = NUNI + 1
14323 0 : XDONT (NUNI) = XDONT (ICRS)
14324 : End If
14325 : End Do
14326 0 : Return
14327 : !
14328 0 : End Subroutine R_unista
14329 :
14330 4 : Subroutine I_unista (XDONT, NUNI)
14331 : ! UNISTA = (Stable unique) Removes duplicates from an array,
14332 : ! leaving unique entries in the order of their first
14333 : ! appearance in the initial set.
14334 : ! Michel Olagnon - Feb. 2000
14335 : ! __________________________________________________________
14336 : ! __________________________________________________________
14337 : Integer(kind = i4), Dimension (:), Intent (InOut) :: XDONT
14338 : Integer(kind = i4), Intent (Out) :: NUNI
14339 : ! __________________________________________________________
14340 : !
14341 0 : Integer(kind = i4), Dimension (Size(XDONT)) :: IWRKT
14342 4 : Logical, Dimension (Size(XDONT)) :: IFMPTYT
14343 : Integer(kind = i4) :: ICRS
14344 : ! __________________________________________________________
14345 4 : Call UNIINV (XDONT, IWRKT)
14346 40 : IFMPTYT = .True.
14347 4 : NUNI = 0
14348 40 : Do ICRS = 1, Size(XDONT)
14349 40 : If (IFMPTYT(IWRKT(ICRS))) Then
14350 12 : IFMPTYT(IWRKT(ICRS)) = .False.
14351 12 : NUNI = NUNI + 1
14352 12 : XDONT (NUNI) = XDONT (ICRS)
14353 : End If
14354 : End Do
14355 4 : Return
14356 : !
14357 0 : End Subroutine I_unista
14358 :
14359 0 : Recursive Function D_valmed (XDONT) Result (res_med)
14360 : ! Finds the median of XDONT using the recursive procedure
14361 : ! described in Knuth, The Art of Computer Programming,
14362 : ! vol. 3, 5.3.3 - This procedure is linear in time, and
14363 : ! does not require to be able to interpolate in the
14364 : ! set as the one used in INDNTH. It also has better worst
14365 : ! case behavior than INDNTH, but is about 30% slower in
14366 : ! average for random uniformly distributed values.
14367 : ! __________________________________________________________
14368 : ! __________________________________________________________
14369 : real(kind = dp), Dimension (:), Intent (In) :: XDONT
14370 : real(kind = dp) :: res_med
14371 : ! __________________________________________________________
14372 : real(kind = dp), Parameter :: XHUGE = HUGE (XDONT)
14373 0 : real(kind = dp), Dimension (SIZE(XDONT) + 6) :: XWRKT
14374 0 : real(kind = dp) :: XWRK, XWRK1, XMED7
14375 : !
14376 0 : Integer(kind = i4), Dimension ((SIZE(XDONT) + 6) / 7) :: ISTRT, IENDT, IMEDT
14377 : Integer(kind = i4) :: NDON, NTRI, NMED, NORD, NEQU, NLEQ, IMED, IDON, IDON1
14378 : Integer(kind = i4) :: IDEB, IWRK, IDCR, ICRS, ICRS1, ICRS2, IMED1
14379 : !
14380 0 : NDON = SIZE (XDONT)
14381 0 : NMED = (NDON + 1) / 2
14382 : ! write(unit=*,fmt=*) NMED, NDON
14383 : !
14384 : ! If the number of values is small, then use insertion sort
14385 : !
14386 0 : If (NDON < 35) Then
14387 : !
14388 : ! Bring minimum to first location to save test in decreasing loop
14389 : !
14390 0 : IDCR = NDON
14391 0 : If (XDONT (1) < XDONT (NDON)) Then
14392 0 : XWRK = XDONT (1)
14393 0 : XWRKT (IDCR) = XDONT (IDCR)
14394 : Else
14395 0 : XWRK = XDONT (IDCR)
14396 0 : XWRKT (IDCR) = XDONT (1)
14397 : end if
14398 0 : Do IWRK = 1, NDON - 2
14399 0 : IDCR = IDCR - 1
14400 0 : XWRK1 = XDONT (IDCR)
14401 0 : If (XWRK1 < XWRK) Then
14402 0 : XWRKT (IDCR) = XWRK
14403 0 : XWRK = XWRK1
14404 : Else
14405 0 : XWRKT (IDCR) = XWRK1
14406 : end if
14407 : End Do
14408 0 : XWRKT (1) = XWRK
14409 : !
14410 : ! Sort the first half, until we have NMED sorted values
14411 : !
14412 0 : Do ICRS = 3, NMED
14413 0 : XWRK = XWRKT (ICRS)
14414 0 : IDCR = ICRS - 1
14415 0 : Do
14416 0 : If (XWRK >= XWRKT(IDCR)) Exit
14417 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14418 0 : IDCR = IDCR - 1
14419 : End Do
14420 0 : XWRKT (IDCR + 1) = XWRK
14421 : End Do
14422 : !
14423 : ! Insert any value less than the current median in the first half
14424 : !
14425 0 : Do ICRS = NMED + 1, NDON
14426 0 : XWRK = XWRKT (ICRS)
14427 0 : If (XWRK < XWRKT (NMED)) Then
14428 0 : IDCR = NMED - 1
14429 0 : Do
14430 0 : If (XWRK >= XWRKT(IDCR)) Exit
14431 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14432 0 : IDCR = IDCR - 1
14433 : End Do
14434 0 : XWRKT (IDCR + 1) = XWRK
14435 : End If
14436 : End Do
14437 0 : res_med = XWRKT (NMED)
14438 0 : Return
14439 : End If
14440 : !
14441 : ! Make sorted subsets of 7 elements
14442 : ! This is done by a variant of insertion sort where a first
14443 : ! pass is used to bring the smallest element to the first position
14444 : ! decreasing disorder at the same time, so that we may remove
14445 : ! remove the loop test in the insertion loop.
14446 : !
14447 0 : DO IDEB = 1, NDON - 6, 7
14448 0 : IDCR = IDEB + 6
14449 0 : If (XDONT (IDEB) < XDONT (IDCR)) Then
14450 0 : XWRK = XDONT (IDEB)
14451 0 : XWRKT (IDCR) = XDONT (IDCR)
14452 : Else
14453 0 : XWRK = XDONT (IDCR)
14454 0 : XWRKT (IDCR) = XDONT (IDEB)
14455 : end if
14456 0 : Do IWRK = 1, 5
14457 0 : IDCR = IDCR - 1
14458 0 : XWRK1 = XDONT (IDCR)
14459 0 : If (XWRK1 < XWRK) Then
14460 0 : XWRKT (IDCR) = XWRK
14461 0 : XWRK = XWRK1
14462 : Else
14463 0 : XWRKT (IDCR) = XWRK1
14464 : end if
14465 : End Do
14466 0 : XWRKT (IDEB) = XWRK
14467 0 : Do ICRS = IDEB + 2, IDEB + 6
14468 0 : XWRK = XWRKT (ICRS)
14469 0 : If (XWRK < XWRKT(ICRS - 1)) Then
14470 0 : XWRKT (ICRS) = XWRKT (ICRS - 1)
14471 0 : IDCR = ICRS - 1
14472 0 : XWRK1 = XWRKT (IDCR - 1)
14473 0 : Do
14474 0 : If (XWRK >= XWRK1) Exit
14475 0 : XWRKT (IDCR) = XWRK1
14476 0 : IDCR = IDCR - 1
14477 0 : XWRK1 = XWRKT (IDCR - 1)
14478 : End Do
14479 0 : XWRKT (IDCR) = XWRK
14480 : end if
14481 : End Do
14482 : End Do
14483 : !
14484 : ! Add-up alternatively + and - HUGE values to make the number of data
14485 : ! an exact multiple of 7.
14486 : !
14487 0 : IDEB = 7 * (NDON / 7)
14488 0 : NTRI = NDON
14489 0 : If (IDEB < NDON) Then
14490 : !
14491 0 : XWRK1 = XHUGE
14492 0 : Do ICRS = IDEB + 1, IDEB + 7
14493 0 : If (ICRS <= NDON) Then
14494 0 : XWRKT (ICRS) = XDONT (ICRS)
14495 : Else
14496 0 : If (ne(XWRK1, XHUGE)) NMED = NMED + 1
14497 0 : XWRKT (ICRS) = XWRK1
14498 0 : XWRK1 = - XWRK1
14499 : end if
14500 : End Do
14501 : !
14502 0 : Do ICRS = IDEB + 2, IDEB + 7
14503 0 : XWRK = XWRKT (ICRS)
14504 0 : Do IDCR = ICRS - 1, IDEB + 1, - 1
14505 0 : If (XWRK >= XWRKT(IDCR)) Exit
14506 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14507 : End Do
14508 0 : XWRKT (IDCR + 1) = XWRK
14509 : End Do
14510 : !
14511 : NTRI = IDEB + 7
14512 : End If
14513 : !
14514 : ! Make the set of the indices of median values of each sorted subset
14515 : !
14516 0 : IDON1 = 0
14517 0 : Do IDON = 1, NTRI, 7
14518 0 : IDON1 = IDON1 + 1
14519 0 : IMEDT (IDON1) = IDON + 3
14520 : End Do
14521 : !
14522 : ! Find XMED7, the median of the medians
14523 : !
14524 0 : XMED7 = D_valmed (XWRKT (IMEDT))
14525 : !
14526 : ! Count how many values are not higher than (and how many equal to) XMED7
14527 : ! This number is at least 4 * 1/2 * (N/7) : 4 values in each of the
14528 : ! subsets where the median is lower than the median of medians. For similar
14529 : ! reasons, we also have at least 2N/7 values not lower than XMED7. At the
14530 : ! same time, we find in each subset the index of the last value < XMED7,
14531 : ! and that of the first > XMED7. These indices will be used to restrict the
14532 : ! search for the median as the Kth element in the subset (> or <) where
14533 : ! we know it to be.
14534 : !
14535 0 : IDON1 = 1
14536 0 : NLEQ = 0
14537 0 : NEQU = 0
14538 0 : Do IDON = 1, NTRI, 7
14539 0 : IMED = IDON + 3
14540 0 : If (XWRKT (IMED) > XMED7) Then
14541 0 : IMED = IMED - 2
14542 0 : If (XWRKT (IMED) > XMED7) Then
14543 : IMED = IMED - 1
14544 0 : Else If (XWRKT (IMED) < XMED7) Then
14545 0 : IMED = IMED + 1
14546 : end if
14547 0 : Else If (XWRKT (IMED) < XMED7) Then
14548 0 : IMED = IMED + 2
14549 0 : If (XWRKT (IMED) > XMED7) Then
14550 0 : IMED = IMED - 1
14551 0 : Else If (XWRKT (IMED) < XMED7) Then
14552 0 : IMED = IMED + 1
14553 : end if
14554 : end if
14555 0 : If (XWRKT (IMED) > XMED7) Then
14556 0 : NLEQ = NLEQ + IMED - IDON
14557 0 : IENDT (IDON1) = IMED - 1
14558 0 : ISTRT (IDON1) = IMED
14559 0 : Else If (XWRKT (IMED) < XMED7) Then
14560 0 : NLEQ = NLEQ + IMED - IDON + 1
14561 0 : IENDT (IDON1) = IMED
14562 0 : ISTRT (IDON1) = IMED + 1
14563 : Else ! If (XWRKT (IMED) == XMED7)
14564 0 : NLEQ = NLEQ + IMED - IDON + 1
14565 0 : NEQU = NEQU + 1
14566 0 : IENDT (IDON1) = IMED - 1
14567 0 : Do IMED1 = IMED - 1, IDON, -1
14568 0 : If (eq(XWRKT (IMED1), XMED7)) Then
14569 0 : NEQU = NEQU + 1
14570 0 : IENDT (IDON1) = IMED1 - 1
14571 : Else
14572 : Exit
14573 : End If
14574 : End Do
14575 0 : ISTRT (IDON1) = IMED + 1
14576 0 : Do IMED1 = IMED + 1, IDON + 6
14577 0 : If (eq(XWRKT (IMED1), XMED7)) Then
14578 0 : NEQU = NEQU + 1
14579 0 : NLEQ = NLEQ + 1
14580 0 : ISTRT (IDON1) = IMED1 + 1
14581 : Else
14582 : Exit
14583 : End If
14584 : End Do
14585 : end if
14586 0 : IDON1 = IDON1 + 1
14587 : End Do
14588 : !
14589 : ! Carry out a partial insertion sort to find the Kth smallest of the
14590 : ! large values, or the Kth largest of the small values, according to
14591 : ! what is needed.
14592 : !
14593 0 : If (NLEQ - NEQU + 1 <= NMED) Then
14594 0 : If (NLEQ < NMED) Then ! Not enough low values
14595 0 : XWRK1 = XHUGE
14596 0 : NORD = NMED - NLEQ
14597 0 : IDON1 = 0
14598 0 : ICRS1 = 1
14599 0 : ICRS2 = 0
14600 0 : IDCR = 0
14601 0 : Do IDON = 1, NTRI, 7
14602 0 : IDON1 = IDON1 + 1
14603 0 : If (ICRS2 < NORD) Then
14604 0 : Do ICRS = ISTRT (IDON1), IDON + 6
14605 0 : If (XWRKT(ICRS) < XWRK1) Then
14606 0 : XWRK = XWRKT (ICRS)
14607 0 : Do IDCR = ICRS1 - 1, 1, - 1
14608 0 : If (XWRK >= XWRKT(IDCR)) Exit
14609 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14610 : End Do
14611 0 : XWRKT (IDCR + 1) = XWRK
14612 0 : XWRK1 = XWRKT(ICRS1)
14613 : Else
14614 0 : If (ICRS2 < NORD) Then
14615 0 : XWRKT (ICRS1) = XWRKT (ICRS)
14616 0 : XWRK1 = XWRKT(ICRS1)
14617 : end if
14618 : End If
14619 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
14620 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
14621 : End Do
14622 : Else
14623 0 : Do ICRS = ISTRT (IDON1), IDON + 6
14624 0 : If (XWRKT(ICRS) >= XWRK1) Exit
14625 0 : XWRK = XWRKT (ICRS)
14626 0 : Do IDCR = ICRS1 - 1, 1, - 1
14627 0 : If (XWRK >= XWRKT(IDCR)) Exit
14628 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14629 : End Do
14630 0 : XWRKT (IDCR + 1) = XWRK
14631 0 : XWRK1 = XWRKT(ICRS1)
14632 : End Do
14633 : End If
14634 : End Do
14635 0 : res_med = XWRK1
14636 0 : Return
14637 : Else
14638 0 : res_med = XMED7
14639 0 : Return
14640 : End If
14641 : Else ! If (NLEQ > NMED)
14642 : ! Not enough high values
14643 0 : XWRK1 = -XHUGE
14644 0 : NORD = NLEQ - NEQU - NMED + 1
14645 0 : IDON1 = 0
14646 0 : ICRS1 = 1
14647 0 : ICRS2 = 0
14648 0 : Do IDON = 1, NTRI, 7
14649 0 : IDON1 = IDON1 + 1
14650 0 : If (ICRS2 < NORD) Then
14651 : !
14652 0 : Do ICRS = IDON, IENDT (IDON1)
14653 0 : If (XWRKT(ICRS) > XWRK1) Then
14654 0 : XWRK = XWRKT (ICRS)
14655 0 : IDCR = ICRS1 - 1
14656 0 : Do IDCR = ICRS1 - 1, 1, - 1
14657 0 : If (XWRK <= XWRKT(IDCR)) Exit
14658 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14659 : End Do
14660 0 : XWRKT (IDCR + 1) = XWRK
14661 0 : XWRK1 = XWRKT(ICRS1)
14662 : Else
14663 0 : If (ICRS2 < NORD) Then
14664 0 : XWRKT (ICRS1) = XWRKT (ICRS)
14665 0 : XWRK1 = XWRKT (ICRS1)
14666 : End If
14667 : End If
14668 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
14669 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
14670 : End Do
14671 : Else
14672 0 : Do ICRS = IENDT (IDON1), IDON, -1
14673 0 : If (XWRKT(ICRS) > XWRK1) Then
14674 0 : XWRK = XWRKT (ICRS)
14675 0 : IDCR = ICRS1 - 1
14676 0 : Do IDCR = ICRS1 - 1, 1, - 1
14677 0 : If (XWRK <= XWRKT(IDCR)) Exit
14678 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14679 : End Do
14680 0 : XWRKT (IDCR + 1) = XWRK
14681 0 : XWRK1 = XWRKT(ICRS1)
14682 : Else
14683 : Exit
14684 : End If
14685 : End Do
14686 : end if
14687 : End Do
14688 : !
14689 0 : res_med = XWRK1
14690 0 : Return
14691 : End If
14692 : !
14693 4 : End Function D_valmed
14694 :
14695 0 : Recursive Function R_valmed (XDONT) Result (res_med)
14696 : ! Finds the median of XDONT using the recursive procedure
14697 : ! described in Knuth, The Art of Computer Programming,
14698 : ! vol. 3, 5.3.3 - This procedure is linear in time, and
14699 : ! does not require to be able to interpolate in the
14700 : ! set as the one used in INDNTH. It also has better worst
14701 : ! case behavior than INDNTH, but is about 30% slower in
14702 : ! average for random uniformly distributed values.
14703 : ! __________________________________________________________
14704 : ! _________________________________________________________
14705 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
14706 : Real(kind = sp) :: res_med
14707 : ! __________________________________________________________
14708 : Real(kind = sp), Parameter :: XHUGE = HUGE (XDONT)
14709 0 : Real(kind = sp), Dimension (SIZE(XDONT) + 6) :: XWRKT
14710 0 : Real(kind = sp) :: XWRK, XWRK1, XMED7
14711 : !
14712 0 : Integer(kind = i4), Dimension ((SIZE(XDONT) + 6) / 7) :: ISTRT, IENDT, IMEDT
14713 : Integer(kind = i4) :: NDON, NTRI, NMED, NORD, NEQU, NLEQ, IMED, IDON, IDON1
14714 : Integer(kind = i4) :: IDEB, IWRK, IDCR, ICRS, ICRS1, ICRS2, IMED1
14715 : !
14716 0 : NDON = SIZE (XDONT)
14717 0 : NMED = (NDON + 1) / 2
14718 : ! write(unit=*,fmt=*) NMED, NDON
14719 : !
14720 : ! If the number of values is small, then use insertion sort
14721 : !
14722 0 : If (NDON < 35) Then
14723 : !
14724 : ! Bring minimum to first location to save test in decreasing loop
14725 : !
14726 0 : IDCR = NDON
14727 0 : If (XDONT (1) < XDONT (NDON)) Then
14728 0 : XWRK = XDONT (1)
14729 0 : XWRKT (IDCR) = XDONT (IDCR)
14730 : Else
14731 0 : XWRK = XDONT (IDCR)
14732 0 : XWRKT (IDCR) = XDONT (1)
14733 : end if
14734 0 : Do IWRK = 1, NDON - 2
14735 0 : IDCR = IDCR - 1
14736 0 : XWRK1 = XDONT (IDCR)
14737 0 : If (XWRK1 < XWRK) Then
14738 0 : XWRKT (IDCR) = XWRK
14739 0 : XWRK = XWRK1
14740 : Else
14741 0 : XWRKT (IDCR) = XWRK1
14742 : end if
14743 : End Do
14744 0 : XWRKT (1) = XWRK
14745 : !
14746 : ! Sort the first half, until we have NMED sorted values
14747 : !
14748 0 : Do ICRS = 3, NMED
14749 0 : XWRK = XWRKT (ICRS)
14750 0 : IDCR = ICRS - 1
14751 0 : Do
14752 0 : If (XWRK >= XWRKT(IDCR)) Exit
14753 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14754 0 : IDCR = IDCR - 1
14755 : End Do
14756 0 : XWRKT (IDCR + 1) = XWRK
14757 : End Do
14758 : !
14759 : ! Insert any value less than the current median in the first half
14760 : !
14761 0 : Do ICRS = NMED + 1, NDON
14762 0 : XWRK = XWRKT (ICRS)
14763 0 : If (XWRK < XWRKT (NMED)) Then
14764 0 : IDCR = NMED - 1
14765 0 : Do
14766 0 : If (XWRK >= XWRKT(IDCR)) Exit
14767 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14768 0 : IDCR = IDCR - 1
14769 : End Do
14770 0 : XWRKT (IDCR + 1) = XWRK
14771 : End If
14772 : End Do
14773 0 : res_med = XWRKT (NMED)
14774 0 : Return
14775 : End If
14776 : !
14777 : ! Make sorted subsets of 7 elements
14778 : ! This is done by a variant of insertion sort where a first
14779 : ! pass is used to bring the smallest element to the first position
14780 : ! decreasing disorder at the same time, so that we may remove
14781 : ! remove the loop test in the insertion loop.
14782 : !
14783 0 : DO IDEB = 1, NDON - 6, 7
14784 0 : IDCR = IDEB + 6
14785 0 : If (XDONT (IDEB) < XDONT (IDCR)) Then
14786 0 : XWRK = XDONT (IDEB)
14787 0 : XWRKT (IDCR) = XDONT (IDCR)
14788 : Else
14789 0 : XWRK = XDONT (IDCR)
14790 0 : XWRKT (IDCR) = XDONT (IDEB)
14791 : end if
14792 0 : Do IWRK = 1, 5
14793 0 : IDCR = IDCR - 1
14794 0 : XWRK1 = XDONT (IDCR)
14795 0 : If (XWRK1 < XWRK) Then
14796 0 : XWRKT (IDCR) = XWRK
14797 0 : XWRK = XWRK1
14798 : Else
14799 0 : XWRKT (IDCR) = XWRK1
14800 : end if
14801 : End Do
14802 0 : XWRKT (IDEB) = XWRK
14803 0 : Do ICRS = IDEB + 2, IDEB + 6
14804 0 : XWRK = XWRKT (ICRS)
14805 0 : If (XWRK < XWRKT(ICRS - 1)) Then
14806 0 : XWRKT (ICRS) = XWRKT (ICRS - 1)
14807 0 : IDCR = ICRS - 1
14808 0 : XWRK1 = XWRKT (IDCR - 1)
14809 0 : Do
14810 0 : If (XWRK >= XWRK1) Exit
14811 0 : XWRKT (IDCR) = XWRK1
14812 0 : IDCR = IDCR - 1
14813 0 : XWRK1 = XWRKT (IDCR - 1)
14814 : End Do
14815 0 : XWRKT (IDCR) = XWRK
14816 : end if
14817 : End Do
14818 : End Do
14819 : !
14820 : ! Add-up alternatively + and - HUGE values to make the number of data
14821 : ! an exact multiple of 7.
14822 : !
14823 0 : IDEB = 7 * (NDON / 7)
14824 0 : NTRI = NDON
14825 0 : If (IDEB < NDON) Then
14826 : !
14827 0 : XWRK1 = XHUGE
14828 0 : Do ICRS = IDEB + 1, IDEB + 7
14829 0 : If (ICRS <= NDON) Then
14830 0 : XWRKT (ICRS) = XDONT (ICRS)
14831 : Else
14832 0 : If (ne(XWRK1, XHUGE)) NMED = NMED + 1
14833 0 : XWRKT (ICRS) = XWRK1
14834 0 : XWRK1 = - XWRK1
14835 : end if
14836 : End Do
14837 : !
14838 0 : Do ICRS = IDEB + 2, IDEB + 7
14839 0 : XWRK = XWRKT (ICRS)
14840 0 : Do IDCR = ICRS - 1, IDEB + 1, - 1
14841 0 : If (XWRK >= XWRKT(IDCR)) Exit
14842 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14843 : End Do
14844 0 : XWRKT (IDCR + 1) = XWRK
14845 : End Do
14846 : !
14847 : NTRI = IDEB + 7
14848 : End If
14849 : !
14850 : ! Make the set of the indices of median values of each sorted subset
14851 : !
14852 0 : IDON1 = 0
14853 0 : Do IDON = 1, NTRI, 7
14854 0 : IDON1 = IDON1 + 1
14855 0 : IMEDT (IDON1) = IDON + 3
14856 : End Do
14857 : !
14858 : ! Find XMED7, the median of the medians
14859 : !
14860 0 : XMED7 = R_valmed (XWRKT (IMEDT))
14861 : !
14862 : ! Count how many values are not higher than (and how many equal to) XMED7
14863 : ! This number is at least 4 * 1/2 * (N/7) : 4 values in each of the
14864 : ! subsets where the median is lower than the median of medians. For similar
14865 : ! reasons, we also have at least 2N/7 values not lower than XMED7. At the
14866 : ! same time, we find in each subset the index of the last value < XMED7,
14867 : ! and that of the first > XMED7. These indices will be used to restrict the
14868 : ! search for the median as the Kth element in the subset (> or <) where
14869 : ! we know it to be.
14870 : !
14871 0 : IDON1 = 1
14872 0 : NLEQ = 0
14873 0 : NEQU = 0
14874 0 : Do IDON = 1, NTRI, 7
14875 0 : IMED = IDON + 3
14876 0 : If (XWRKT (IMED) > XMED7) Then
14877 0 : IMED = IMED - 2
14878 0 : If (XWRKT (IMED) > XMED7) Then
14879 : IMED = IMED - 1
14880 0 : Else If (XWRKT (IMED) < XMED7) Then
14881 0 : IMED = IMED + 1
14882 : end if
14883 0 : Else If (XWRKT (IMED) < XMED7) Then
14884 0 : IMED = IMED + 2
14885 0 : If (XWRKT (IMED) > XMED7) Then
14886 0 : IMED = IMED - 1
14887 0 : Else If (XWRKT (IMED) < XMED7) Then
14888 0 : IMED = IMED + 1
14889 : end if
14890 : end if
14891 0 : If (XWRKT (IMED) > XMED7) Then
14892 0 : NLEQ = NLEQ + IMED - IDON
14893 0 : IENDT (IDON1) = IMED - 1
14894 0 : ISTRT (IDON1) = IMED
14895 0 : Else If (XWRKT (IMED) < XMED7) Then
14896 0 : NLEQ = NLEQ + IMED - IDON + 1
14897 0 : IENDT (IDON1) = IMED
14898 0 : ISTRT (IDON1) = IMED + 1
14899 : Else ! If (XWRKT (IMED) == XMED7)
14900 0 : NLEQ = NLEQ + IMED - IDON + 1
14901 0 : NEQU = NEQU + 1
14902 0 : IENDT (IDON1) = IMED - 1
14903 0 : Do IMED1 = IMED - 1, IDON, -1
14904 0 : If (eq(XWRKT (IMED1), XMED7)) Then
14905 0 : NEQU = NEQU + 1
14906 0 : IENDT (IDON1) = IMED1 - 1
14907 : Else
14908 : Exit
14909 : End If
14910 : End Do
14911 0 : ISTRT (IDON1) = IMED + 1
14912 0 : Do IMED1 = IMED + 1, IDON + 6
14913 0 : If (eq(XWRKT (IMED1), XMED7)) Then
14914 0 : NEQU = NEQU + 1
14915 0 : NLEQ = NLEQ + 1
14916 0 : ISTRT (IDON1) = IMED1 + 1
14917 : Else
14918 : Exit
14919 : End If
14920 : End Do
14921 : end if
14922 0 : IDON1 = IDON1 + 1
14923 : End Do
14924 : !
14925 : ! Carry out a partial insertion sort to find the Kth smallest of the
14926 : ! large values, or the Kth largest of the small values, according to
14927 : ! what is needed.
14928 : !
14929 0 : If (NLEQ - NEQU + 1 <= NMED) Then
14930 0 : If (NLEQ < NMED) Then ! Not enough low values
14931 0 : XWRK1 = XHUGE
14932 0 : NORD = NMED - NLEQ
14933 0 : IDON1 = 0
14934 0 : ICRS1 = 1
14935 0 : ICRS2 = 0
14936 0 : IDCR = 0
14937 0 : Do IDON = 1, NTRI, 7
14938 0 : IDON1 = IDON1 + 1
14939 0 : If (ICRS2 < NORD) Then
14940 0 : Do ICRS = ISTRT (IDON1), IDON + 6
14941 0 : If (XWRKT(ICRS) < XWRK1) Then
14942 0 : XWRK = XWRKT (ICRS)
14943 0 : Do IDCR = ICRS1 - 1, 1, - 1
14944 0 : If (XWRK >= XWRKT(IDCR)) Exit
14945 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14946 : End Do
14947 0 : XWRKT (IDCR + 1) = XWRK
14948 0 : XWRK1 = XWRKT(ICRS1)
14949 : Else
14950 0 : If (ICRS2 < NORD) Then
14951 0 : XWRKT (ICRS1) = XWRKT (ICRS)
14952 0 : XWRK1 = XWRKT(ICRS1)
14953 : end if
14954 : End If
14955 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
14956 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
14957 : End Do
14958 : Else
14959 0 : Do ICRS = ISTRT (IDON1), IDON + 6
14960 0 : If (XWRKT(ICRS) >= XWRK1) Exit
14961 0 : XWRK = XWRKT (ICRS)
14962 0 : Do IDCR = ICRS1 - 1, 1, - 1
14963 0 : If (XWRK >= XWRKT(IDCR)) Exit
14964 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14965 : End Do
14966 0 : XWRKT (IDCR + 1) = XWRK
14967 0 : XWRK1 = XWRKT(ICRS1)
14968 : End Do
14969 : End If
14970 : End Do
14971 0 : res_med = XWRK1
14972 0 : Return
14973 : Else
14974 0 : res_med = XMED7
14975 0 : Return
14976 : End If
14977 : Else ! If (NLEQ > NMED)
14978 : ! Not enough high values
14979 0 : XWRK1 = -XHUGE
14980 0 : NORD = NLEQ - NEQU - NMED + 1
14981 0 : IDON1 = 0
14982 0 : ICRS1 = 1
14983 0 : ICRS2 = 0
14984 0 : Do IDON = 1, NTRI, 7
14985 0 : IDON1 = IDON1 + 1
14986 0 : If (ICRS2 < NORD) Then
14987 : !
14988 0 : Do ICRS = IDON, IENDT (IDON1)
14989 0 : If (XWRKT(ICRS) > XWRK1) Then
14990 0 : XWRK = XWRKT (ICRS)
14991 0 : IDCR = ICRS1 - 1
14992 0 : Do IDCR = ICRS1 - 1, 1, - 1
14993 0 : If (XWRK <= XWRKT(IDCR)) Exit
14994 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
14995 : End Do
14996 0 : XWRKT (IDCR + 1) = XWRK
14997 0 : XWRK1 = XWRKT(ICRS1)
14998 : Else
14999 0 : If (ICRS2 < NORD) Then
15000 0 : XWRKT (ICRS1) = XWRKT (ICRS)
15001 0 : XWRK1 = XWRKT (ICRS1)
15002 : End If
15003 : End If
15004 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
15005 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
15006 : End Do
15007 : Else
15008 0 : Do ICRS = IENDT (IDON1), IDON, -1
15009 0 : If (XWRKT(ICRS) > XWRK1) Then
15010 0 : XWRK = XWRKT (ICRS)
15011 0 : IDCR = ICRS1 - 1
15012 0 : Do IDCR = ICRS1 - 1, 1, - 1
15013 0 : If (XWRK <= XWRKT(IDCR)) Exit
15014 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
15015 : End Do
15016 0 : XWRKT (IDCR + 1) = XWRK
15017 0 : XWRK1 = XWRKT(ICRS1)
15018 : Else
15019 : Exit
15020 : End If
15021 : End Do
15022 : end if
15023 : End Do
15024 : !
15025 0 : res_med = XWRK1
15026 0 : Return
15027 : End If
15028 : !
15029 : End Function R_valmed
15030 :
15031 0 : Recursive Function I_valmed (XDONT) Result (res_med)
15032 : ! Finds the median of XDONT using the recursive procedure
15033 : ! described in Knuth, The Art of Computer Programming,
15034 : ! vol. 3, 5.3.3 - This procedure is linear in time, and
15035 : ! does not require to be able to interpolate in the
15036 : ! set as the one used in INDNTH. It also has better worst
15037 : ! case behavior than INDNTH, but is about 30% slower in
15038 : ! average for random uniformly distributed values.
15039 : ! __________________________________________________________
15040 : ! __________________________________________________________
15041 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
15042 : Integer(kind = i4) :: res_med
15043 : ! __________________________________________________________
15044 : Integer(kind = i4), Parameter :: XHUGE = HUGE (XDONT)
15045 0 : Integer(kind = i4), Dimension (SIZE(XDONT) + 6) :: XWRKT
15046 : Integer(kind = i4) :: XWRK, XWRK1, XMED7
15047 : !
15048 0 : Integer(kind = i4), Dimension ((SIZE(XDONT) + 6) / 7) :: ISTRT, IENDT, IMEDT
15049 : Integer(kind = i4) :: NDON, NTRI, NMED, NORD, NEQU, NLEQ, IMED, IDON, IDON1
15050 : Integer(kind = i4) :: IDEB, IWRK, IDCR, ICRS, ICRS1, ICRS2, IMED1
15051 : !
15052 0 : NDON = SIZE (XDONT)
15053 0 : NMED = (NDON + 1) / 2
15054 : ! write(unit=*,fmt=*) NMED, NDON
15055 : !
15056 : ! If the number of values is small, then use insertion sort
15057 : !
15058 0 : If (NDON < 35) Then
15059 : !
15060 : ! Bring minimum to first location to save test in decreasing loop
15061 : !
15062 0 : IDCR = NDON
15063 0 : If (XDONT (1) < XDONT (NDON)) Then
15064 0 : XWRK = XDONT (1)
15065 0 : XWRKT (IDCR) = XDONT (IDCR)
15066 : Else
15067 0 : XWRK = XDONT (IDCR)
15068 0 : XWRKT (IDCR) = XDONT (1)
15069 : end if
15070 0 : Do IWRK = 1, NDON - 2
15071 0 : IDCR = IDCR - 1
15072 0 : XWRK1 = XDONT (IDCR)
15073 0 : If (XWRK1 < XWRK) Then
15074 0 : XWRKT (IDCR) = XWRK
15075 0 : XWRK = XWRK1
15076 : Else
15077 0 : XWRKT (IDCR) = XWRK1
15078 : end if
15079 : End Do
15080 0 : XWRKT (1) = XWRK
15081 : !
15082 : ! Sort the first half, until we have NMED sorted values
15083 : !
15084 0 : Do ICRS = 3, NMED
15085 0 : XWRK = XWRKT (ICRS)
15086 0 : IDCR = ICRS - 1
15087 0 : Do
15088 0 : If (XWRK >= XWRKT(IDCR)) Exit
15089 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
15090 0 : IDCR = IDCR - 1
15091 : End Do
15092 0 : XWRKT (IDCR + 1) = XWRK
15093 : End Do
15094 : !
15095 : ! Insert any value less than the current median in the first half
15096 : !
15097 0 : Do ICRS = NMED + 1, NDON
15098 0 : XWRK = XWRKT (ICRS)
15099 0 : If (XWRK < XWRKT (NMED)) Then
15100 0 : IDCR = NMED - 1
15101 0 : Do
15102 0 : If (XWRK >= XWRKT(IDCR)) Exit
15103 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
15104 0 : IDCR = IDCR - 1
15105 : End Do
15106 0 : XWRKT (IDCR + 1) = XWRK
15107 : End If
15108 : End Do
15109 0 : res_med = XWRKT (NMED)
15110 0 : Return
15111 : End If
15112 : !
15113 : ! Make sorted subsets of 7 elements
15114 : ! This is done by a variant of insertion sort where a first
15115 : ! pass is used to bring the smallest element to the first position
15116 : ! decreasing disorder at the same time, so that we may remove
15117 : ! remove the loop test in the insertion loop.
15118 : !
15119 0 : DO IDEB = 1, NDON - 6, 7
15120 0 : IDCR = IDEB + 6
15121 0 : If (XDONT (IDEB) < XDONT (IDCR)) Then
15122 0 : XWRK = XDONT (IDEB)
15123 0 : XWRKT (IDCR) = XDONT (IDCR)
15124 : Else
15125 0 : XWRK = XDONT (IDCR)
15126 0 : XWRKT (IDCR) = XDONT (IDEB)
15127 : end if
15128 0 : Do IWRK = 1, 5
15129 0 : IDCR = IDCR - 1
15130 0 : XWRK1 = XDONT (IDCR)
15131 0 : If (XWRK1 < XWRK) Then
15132 0 : XWRKT (IDCR) = XWRK
15133 0 : XWRK = XWRK1
15134 : Else
15135 0 : XWRKT (IDCR) = XWRK1
15136 : end if
15137 : End Do
15138 0 : XWRKT (IDEB) = XWRK
15139 0 : Do ICRS = IDEB + 2, IDEB + 6
15140 0 : XWRK = XWRKT (ICRS)
15141 0 : If (XWRK < XWRKT(ICRS - 1)) Then
15142 0 : XWRKT (ICRS) = XWRKT (ICRS - 1)
15143 0 : IDCR = ICRS - 1
15144 0 : XWRK1 = XWRKT (IDCR - 1)
15145 0 : Do
15146 0 : If (XWRK >= XWRK1) Exit
15147 0 : XWRKT (IDCR) = XWRK1
15148 0 : IDCR = IDCR - 1
15149 0 : XWRK1 = XWRKT (IDCR - 1)
15150 : End Do
15151 0 : XWRKT (IDCR) = XWRK
15152 : end if
15153 : End Do
15154 : End Do
15155 : !
15156 : ! Add-up alternatively + and - HUGE values to make the number of data
15157 : ! an exact multiple of 7.
15158 : !
15159 0 : IDEB = 7 * (NDON / 7)
15160 0 : NTRI = NDON
15161 0 : If (IDEB < NDON) Then
15162 : !
15163 0 : XWRK1 = XHUGE
15164 0 : Do ICRS = IDEB + 1, IDEB + 7
15165 0 : If (ICRS <= NDON) Then
15166 0 : XWRKT (ICRS) = XDONT (ICRS)
15167 : Else
15168 0 : If (XWRK1 /= XHUGE) NMED = NMED + 1
15169 0 : XWRKT (ICRS) = XWRK1
15170 0 : XWRK1 = - XWRK1
15171 : end if
15172 : End Do
15173 : !
15174 0 : Do ICRS = IDEB + 2, IDEB + 7
15175 0 : XWRK = XWRKT (ICRS)
15176 0 : Do IDCR = ICRS - 1, IDEB + 1, - 1
15177 0 : If (XWRK >= XWRKT(IDCR)) Exit
15178 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
15179 : End Do
15180 0 : XWRKT (IDCR + 1) = XWRK
15181 : End Do
15182 : !
15183 : NTRI = IDEB + 7
15184 : End If
15185 : !
15186 : ! Make the set of the indices of median values of each sorted subset
15187 : !
15188 0 : IDON1 = 0
15189 0 : Do IDON = 1, NTRI, 7
15190 0 : IDON1 = IDON1 + 1
15191 0 : IMEDT (IDON1) = IDON + 3
15192 : End Do
15193 : !
15194 : ! Find XMED7, the median of the medians
15195 : !
15196 0 : XMED7 = I_valmed (XWRKT (IMEDT))
15197 : !
15198 : ! Count how many values are not higher than (and how many equal to) XMED7
15199 : ! This number is at least 4 * 1/2 * (N/7) : 4 values in each of the
15200 : ! subsets where the median is lower than the median of medians. For similar
15201 : ! reasons, we also have at least 2N/7 values not lower than XMED7. At the
15202 : ! same time, we find in each subset the index of the last value < XMED7,
15203 : ! and that of the first > XMED7. These indices will be used to restrict the
15204 : ! search for the median as the Kth element in the subset (> or <) where
15205 : ! we know it to be.
15206 : !
15207 0 : IDON1 = 1
15208 0 : NLEQ = 0
15209 0 : NEQU = 0
15210 0 : Do IDON = 1, NTRI, 7
15211 0 : IMED = IDON + 3
15212 0 : If (XWRKT (IMED) > XMED7) Then
15213 0 : IMED = IMED - 2
15214 0 : If (XWRKT (IMED) > XMED7) Then
15215 : IMED = IMED - 1
15216 0 : Else If (XWRKT (IMED) < XMED7) Then
15217 0 : IMED = IMED + 1
15218 : end if
15219 0 : Else If (XWRKT (IMED) < XMED7) Then
15220 0 : IMED = IMED + 2
15221 0 : If (XWRKT (IMED) > XMED7) Then
15222 0 : IMED = IMED - 1
15223 0 : Else If (XWRKT (IMED) < XMED7) Then
15224 0 : IMED = IMED + 1
15225 : end if
15226 : end if
15227 0 : If (XWRKT (IMED) > XMED7) Then
15228 0 : NLEQ = NLEQ + IMED - IDON
15229 0 : IENDT (IDON1) = IMED - 1
15230 0 : ISTRT (IDON1) = IMED
15231 0 : Else If (XWRKT (IMED) < XMED7) Then
15232 0 : NLEQ = NLEQ + IMED - IDON + 1
15233 0 : IENDT (IDON1) = IMED
15234 0 : ISTRT (IDON1) = IMED + 1
15235 : Else ! If (XWRKT (IMED) == XMED7)
15236 0 : NLEQ = NLEQ + IMED - IDON + 1
15237 0 : NEQU = NEQU + 1
15238 0 : IENDT (IDON1) = IMED - 1
15239 0 : Do IMED1 = IMED - 1, IDON, -1
15240 0 : If (XWRKT (IMED1) == XMED7) Then
15241 0 : NEQU = NEQU + 1
15242 0 : IENDT (IDON1) = IMED1 - 1
15243 : Else
15244 : Exit
15245 : End If
15246 : End Do
15247 0 : ISTRT (IDON1) = IMED + 1
15248 0 : Do IMED1 = IMED + 1, IDON + 6
15249 0 : If (XWRKT (IMED1) == XMED7) Then
15250 0 : NEQU = NEQU + 1
15251 0 : NLEQ = NLEQ + 1
15252 0 : ISTRT (IDON1) = IMED1 + 1
15253 : Else
15254 : Exit
15255 : End If
15256 : End Do
15257 : end if
15258 0 : IDON1 = IDON1 + 1
15259 : End Do
15260 : !
15261 : ! Carry out a partial insertion sort to find the Kth smallest of the
15262 : ! large values, or the Kth largest of the small values, according to
15263 : ! what is needed.
15264 : !
15265 0 : If (NLEQ - NEQU + 1 <= NMED) Then
15266 0 : If (NLEQ < NMED) Then ! Not enough low values
15267 0 : XWRK1 = XHUGE
15268 0 : NORD = NMED - NLEQ
15269 0 : IDON1 = 0
15270 0 : ICRS1 = 1
15271 0 : ICRS2 = 0
15272 0 : IDCR = 0
15273 0 : Do IDON = 1, NTRI, 7
15274 0 : IDON1 = IDON1 + 1
15275 0 : If (ICRS2 < NORD) Then
15276 0 : Do ICRS = ISTRT (IDON1), IDON + 6
15277 0 : If (XWRKT(ICRS) < XWRK1) Then
15278 0 : XWRK = XWRKT (ICRS)
15279 0 : Do IDCR = ICRS1 - 1, 1, - 1
15280 0 : If (XWRK >= XWRKT(IDCR)) Exit
15281 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
15282 : End Do
15283 0 : XWRKT (IDCR + 1) = XWRK
15284 0 : XWRK1 = XWRKT(ICRS1)
15285 : Else
15286 0 : If (ICRS2 < NORD) Then
15287 0 : XWRKT (ICRS1) = XWRKT (ICRS)
15288 : XWRK1 = XWRKT(ICRS1)
15289 : end if
15290 : End If
15291 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
15292 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
15293 : End Do
15294 : Else
15295 0 : Do ICRS = ISTRT (IDON1), IDON + 6
15296 0 : If (XWRKT(ICRS) >= XWRK1) Exit
15297 0 : XWRK = XWRKT (ICRS)
15298 0 : Do IDCR = ICRS1 - 1, 1, - 1
15299 0 : If (XWRK >= XWRKT(IDCR)) Exit
15300 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
15301 : End Do
15302 0 : XWRKT (IDCR + 1) = XWRK
15303 0 : XWRK1 = XWRKT(ICRS1)
15304 : End Do
15305 : End If
15306 : End Do
15307 0 : res_med = XWRK1
15308 0 : Return
15309 : Else
15310 0 : res_med = XMED7
15311 : Return
15312 : End If
15313 : Else ! If (NLEQ > NMED)
15314 : ! Not enough high values
15315 0 : XWRK1 = -XHUGE
15316 0 : NORD = NLEQ - NEQU - NMED + 1
15317 0 : IDON1 = 0
15318 0 : ICRS1 = 1
15319 0 : ICRS2 = 0
15320 0 : Do IDON = 1, NTRI, 7
15321 0 : IDON1 = IDON1 + 1
15322 0 : If (ICRS2 < NORD) Then
15323 : !
15324 0 : Do ICRS = IDON, IENDT (IDON1)
15325 0 : If (XWRKT(ICRS) > XWRK1) Then
15326 0 : XWRK = XWRKT (ICRS)
15327 0 : IDCR = ICRS1 - 1
15328 0 : Do IDCR = ICRS1 - 1, 1, - 1
15329 0 : If (XWRK <= XWRKT(IDCR)) Exit
15330 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
15331 : End Do
15332 0 : XWRKT (IDCR + 1) = XWRK
15333 0 : XWRK1 = XWRKT(ICRS1)
15334 : Else
15335 0 : If (ICRS2 < NORD) Then
15336 0 : XWRKT (ICRS1) = XWRKT (ICRS)
15337 : XWRK1 = XWRKT (ICRS1)
15338 : End If
15339 : End If
15340 0 : ICRS1 = MIN (NORD, ICRS1 + 1)
15341 0 : ICRS2 = MIN (NORD, ICRS2 + 1)
15342 : End Do
15343 : Else
15344 0 : Do ICRS = IENDT (IDON1), IDON, -1
15345 0 : If (XWRKT(ICRS) > XWRK1) Then
15346 0 : XWRK = XWRKT (ICRS)
15347 0 : IDCR = ICRS1 - 1
15348 0 : Do IDCR = ICRS1 - 1, 1, - 1
15349 0 : If (XWRK <= XWRKT(IDCR)) Exit
15350 0 : XWRKT (IDCR + 1) = XWRKT (IDCR)
15351 : End Do
15352 0 : XWRKT (IDCR + 1) = XWRK
15353 0 : XWRK1 = XWRKT(ICRS1)
15354 : Else
15355 : Exit
15356 : End If
15357 : End Do
15358 : end if
15359 : End Do
15360 : !
15361 0 : res_med = XWRK1
15362 0 : Return
15363 : End If
15364 : !
15365 : End Function I_valmed
15366 :
15367 0 : Function D_valnth (XDONT, NORD) Result (valnth)
15368 : ! Return NORDth value of XDONT, i.e fractile of order NORD/SIZE(XDONT).
15369 : ! __________________________________________________________
15370 : ! This routine uses a pivoting strategy such as the one of
15371 : ! finding the median based on the quicksort algorithm, but
15372 : ! we skew the pivot choice to try to bring it to NORD as
15373 : ! fast as possible. It uses 2 temporary arrays, where it
15374 : ! stores the indices of the values smaller than the pivot
15375 : ! (ILOWT), and the indices of values larger than the pivot
15376 : ! that we might still need later on (IHIGT). It iterates
15377 : ! until it can bring the number of values in ILOWT to
15378 : ! exactly NORD, and then finds the maximum of this set.
15379 : ! Michel Olagnon - Aug. 2000
15380 : ! __________________________________________________________
15381 : ! __________________________________________________________
15382 : real(Kind = dp), Dimension (:), Intent (In) :: XDONT
15383 : real(Kind = dp) :: valnth
15384 : Integer(kind = i4), Intent (In) :: NORD
15385 : ! __________________________________________________________
15386 0 : real(Kind = dp), Dimension (SIZE(XDONT)) :: XLOWT, XHIGT
15387 0 : real(Kind = dp) :: XPIV, XWRK, XWRK1, XWRK2, XWRK3, XMIN, XMAX
15388 : !
15389 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG
15390 : Integer(kind = i4) :: IMIL, IFIN, ICRS, IDCR, ILOW
15391 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1, INTH
15392 : !
15393 0 : NDON = SIZE (XDONT)
15394 0 : INTH = MAX (MIN (NORD, NDON), 1)
15395 : !
15396 : ! First loop is used to fill-in XLOWT, XHIGT at the same time
15397 : !
15398 0 : If (NDON < 2) Then
15399 0 : If (INTH == 1) VALNTH = XDONT (1)
15400 0 : Return
15401 : End If
15402 : !
15403 : ! One chooses a pivot, best estimate possible to put fractile near
15404 : ! mid-point of the set of low values.
15405 : !
15406 0 : If (XDONT(2) < XDONT(1)) Then
15407 0 : XLOWT (1) = XDONT(2)
15408 0 : XHIGT (1) = XDONT(1)
15409 : Else
15410 0 : XLOWT (1) = XDONT(1)
15411 0 : XHIGT (1) = XDONT(2)
15412 : End If
15413 : !
15414 0 : If (NDON < 3) Then
15415 0 : If (INTH == 1) VALNTH = XLOWT (1)
15416 0 : If (INTH == 2) VALNTH = XHIGT (1)
15417 0 : Return
15418 : End If
15419 : !
15420 0 : If (XDONT(3) < XHIGT(1)) Then
15421 0 : XHIGT (2) = XHIGT (1)
15422 0 : If (XDONT(3) < XLOWT(1)) Then
15423 0 : XHIGT (1) = XLOWT (1)
15424 0 : XLOWT (1) = XDONT(3)
15425 : Else
15426 0 : XHIGT (1) = XDONT(3)
15427 : End If
15428 : Else
15429 0 : XHIGT (2) = XDONT(3)
15430 : End If
15431 : !
15432 0 : If (NDON < 4) Then
15433 0 : If (INTH == 1) Then
15434 0 : VALNTH = XLOWT (1)
15435 : Else
15436 0 : VALNTH = XHIGT (INTH - 1)
15437 : End If
15438 0 : Return
15439 : End If
15440 : !
15441 0 : If (XDONT(NDON) < XHIGT(1)) Then
15442 0 : XHIGT (3) = XHIGT (2)
15443 0 : XHIGT (2) = XHIGT (1)
15444 0 : If (XDONT(NDON) < XLOWT(1)) Then
15445 0 : XHIGT (1) = XLOWT (1)
15446 0 : XLOWT (1) = XDONT(NDON)
15447 : Else
15448 0 : XHIGT (1) = XDONT(NDON)
15449 : End If
15450 : Else
15451 0 : XHIGT (3) = XDONT(NDON)
15452 : End If
15453 : !
15454 0 : If (NDON < 5) Then
15455 0 : If (INTH == 1) Then
15456 0 : VALNTH = XLOWT (1)
15457 : Else
15458 0 : VALNTH = XHIGT (INTH - 1)
15459 : End If
15460 0 : Return
15461 : End If
15462 : !
15463 :
15464 0 : JLOW = 1
15465 0 : JHIG = 3
15466 0 : XPIV = XLOWT(1) + REAL(2 * INTH, dp) / REAL(NDON + INTH, dp) * (XHIGT(3) - XLOWT(1))
15467 0 : If (XPIV >= XHIGT(1)) Then
15468 : XPIV = XLOWT(1) + REAL(2 * INTH, dp) / REAL(NDON + INTH, dp) * &
15469 0 : (XHIGT(2) - XLOWT(1))
15470 0 : If (XPIV >= XHIGT(1)) &
15471 : XPIV = XLOWT(1) + REAL(2 * INTH, dp) / REAL(NDON + INTH, dp) * &
15472 0 : (XHIGT(1) - XLOWT(1))
15473 : End If
15474 : !
15475 : ! One puts values > pivot in the end and those <= pivot
15476 : ! at the beginning. This is split in 2 cases, so that
15477 : ! we can skip the loop test a number of times.
15478 : ! As we are also filling in the work arrays at the same time
15479 : ! we stop filling in the XHIGT array as soon as we have more
15480 : ! than enough values in XLOWT.
15481 : !
15482 : !
15483 0 : If (XDONT(NDON) > XPIV) Then
15484 : ICRS = 3
15485 : Do
15486 0 : ICRS = ICRS + 1
15487 0 : If (XDONT(ICRS) > XPIV) Then
15488 0 : If (ICRS >= NDON) Exit
15489 0 : JHIG = JHIG + 1
15490 0 : XHIGT (JHIG) = XDONT(ICRS)
15491 : Else
15492 0 : JLOW = JLOW + 1
15493 0 : XLOWT (JLOW) = XDONT(ICRS)
15494 0 : If (JLOW >= INTH) Exit
15495 : End If
15496 : End Do
15497 : !
15498 : ! One restricts further processing because it is no use
15499 : ! to store more high values
15500 : !
15501 0 : If (ICRS < NDON - 1) Then
15502 : Do
15503 0 : ICRS = ICRS + 1
15504 0 : If (XDONT(ICRS) <= XPIV) Then
15505 0 : JLOW = JLOW + 1
15506 0 : XLOWT (JLOW) = XDONT(ICRS)
15507 0 : Else If (ICRS >= NDON) Then
15508 : Exit
15509 : End If
15510 : End Do
15511 : End If
15512 : !
15513 : !
15514 : Else
15515 : !
15516 : ! Same as above, but this is not as easy to optimize, so the
15517 : ! DO-loop is kept
15518 : !
15519 0 : Do ICRS = 4, NDON - 1
15520 0 : If (XDONT(ICRS) > XPIV) Then
15521 0 : JHIG = JHIG + 1
15522 0 : XHIGT (JHIG) = XDONT(ICRS)
15523 : Else
15524 0 : JLOW = JLOW + 1
15525 0 : XLOWT (JLOW) = XDONT(ICRS)
15526 0 : If (JLOW >= INTH) Exit
15527 : End If
15528 : End Do
15529 : !
15530 0 : If (ICRS < NDON - 1) Then
15531 : Do
15532 0 : ICRS = ICRS + 1
15533 0 : If (XDONT(ICRS) <= XPIV) Then
15534 0 : If (ICRS >= NDON) Exit
15535 0 : JLOW = JLOW + 1
15536 0 : XLOWT (JLOW) = XDONT(ICRS)
15537 : End If
15538 : End Do
15539 : End If
15540 : End If
15541 : !
15542 : JLM2 = 0
15543 : JLM1 = 0
15544 : JHM2 = 0
15545 : JHM1 = 0
15546 : Do
15547 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
15548 : !
15549 : ! We are oscillating. Perturbate by bringing JLOW closer by one
15550 : ! to INTH
15551 : !
15552 0 : If (INTH > JLOW) Then
15553 0 : XMIN = XHIGT(1)
15554 0 : IHIG = 1
15555 0 : Do ICRS = 2, JHIG
15556 0 : If (XHIGT(ICRS) < XMIN) Then
15557 0 : XMIN = XHIGT(ICRS)
15558 0 : IHIG = ICRS
15559 : End If
15560 : End Do
15561 : !
15562 0 : JLOW = JLOW + 1
15563 0 : XLOWT (JLOW) = XHIGT (IHIG)
15564 0 : XHIGT (IHIG) = XHIGT (JHIG)
15565 0 : JHIG = JHIG - 1
15566 : Else
15567 :
15568 0 : XMAX = XLOWT (JLOW)
15569 0 : JLOW = JLOW - 1
15570 0 : Do ICRS = 1, JLOW
15571 0 : If (XLOWT(ICRS) > XMAX) Then
15572 0 : XWRK = XMAX
15573 0 : XMAX = XLOWT(ICRS)
15574 0 : XLOWT (ICRS) = XWRK
15575 : End If
15576 : End Do
15577 : End If
15578 : End If
15579 0 : JLM2 = JLM1
15580 0 : JLM1 = JLOW
15581 0 : JHM2 = JHM1
15582 0 : JHM1 = JHIG
15583 : !
15584 : ! We try to bring the number of values in the low values set
15585 : ! closer to INTH.
15586 : !
15587 0 : Select Case (INTH - JLOW)
15588 : Case (2 :)
15589 : !
15590 : ! Not enough values in low part, at least 2 are missing
15591 : !
15592 0 : INTH = INTH - JLOW
15593 0 : JLOW = 0
15594 : Select Case (JHIG)
15595 : !!!!! CASE DEFAULT
15596 : !!!!! write (unit=*,fmt=*) "Assertion failed"
15597 : !!!!! STOP
15598 : !
15599 : ! We make a special case when we have so few values in
15600 : ! the high values set that it is bad performance to choose a pivot
15601 : ! and apply the general algorithm.
15602 : !
15603 : Case (2)
15604 0 : If (XHIGT(1) <= XHIGT(2)) Then
15605 0 : JLOW = JLOW + 1
15606 0 : XLOWT (JLOW) = XHIGT (1)
15607 0 : JLOW = JLOW + 1
15608 0 : XLOWT (JLOW) = XHIGT (2)
15609 : Else
15610 0 : JLOW = JLOW + 1
15611 0 : XLOWT (JLOW) = XHIGT (2)
15612 0 : JLOW = JLOW + 1
15613 0 : XLOWT (JLOW) = XHIGT (1)
15614 : End If
15615 : Exit
15616 : !
15617 : Case (3)
15618 : !
15619 : !
15620 0 : XWRK1 = XHIGT (1)
15621 0 : XWRK2 = XHIGT (2)
15622 0 : XWRK3 = XHIGT (3)
15623 0 : If (XWRK2 < XWRK1) Then
15624 0 : XHIGT (1) = XWRK2
15625 0 : XHIGT (2) = XWRK1
15626 0 : XWRK2 = XWRK1
15627 : End If
15628 0 : If (XWRK2 > XWRK3) Then
15629 0 : XHIGT (3) = XWRK2
15630 0 : XHIGT (2) = XWRK3
15631 0 : XWRK2 = XWRK3
15632 0 : If (XWRK2 < XHIGT(1)) Then
15633 0 : XHIGT (2) = XHIGT (1)
15634 0 : XHIGT (1) = XWRK2
15635 : End If
15636 : End If
15637 : JHIG = 0
15638 0 : Do ICRS = JLOW + 1, INTH
15639 0 : JHIG = JHIG + 1
15640 0 : XLOWT (ICRS) = XHIGT (JHIG)
15641 : End Do
15642 0 : JLOW = INTH
15643 : Exit
15644 : !
15645 : Case (4 :)
15646 : !
15647 : !
15648 0 : IFIN = JHIG
15649 : !
15650 : ! One chooses a pivot from the 2 first values and the last one.
15651 : ! This should ensure sufficient renewal between iterations to
15652 : ! avoid worst case behavior effects.
15653 : !
15654 0 : XWRK1 = XHIGT (1)
15655 0 : XWRK2 = XHIGT (2)
15656 0 : XWRK3 = XHIGT (IFIN)
15657 0 : If (XWRK2 < XWRK1) Then
15658 0 : XHIGT (1) = XWRK2
15659 0 : XHIGT (2) = XWRK1
15660 0 : XWRK2 = XWRK1
15661 : End If
15662 0 : If (XWRK2 > XWRK3) Then
15663 0 : XHIGT (IFIN) = XWRK2
15664 0 : XHIGT (2) = XWRK3
15665 0 : XWRK2 = XWRK3
15666 0 : If (XWRK2 < XHIGT(1)) Then
15667 0 : XHIGT (2) = XHIGT (1)
15668 0 : XHIGT (1) = XWRK2
15669 : End If
15670 : End If
15671 : !
15672 0 : XWRK1 = XHIGT (1)
15673 0 : JLOW = JLOW + 1
15674 0 : XLOWT (JLOW) = XWRK1
15675 0 : XPIV = XWRK1 + 0.5 * (XHIGT(IFIN) - XWRK1)
15676 : !
15677 : ! One takes values <= pivot to XLOWT
15678 : ! Again, 2 parts, one where we take care of the remaining
15679 : ! high values because we might still need them, and the
15680 : ! other when we know that we will have more than enough
15681 : ! low values in the end.
15682 : !
15683 0 : JHIG = 0
15684 0 : Do ICRS = 2, IFIN
15685 0 : If (XHIGT(ICRS) <= XPIV) Then
15686 0 : JLOW = JLOW + 1
15687 0 : XLOWT (JLOW) = XHIGT (ICRS)
15688 0 : If (JLOW >= INTH) Exit
15689 : Else
15690 0 : JHIG = JHIG + 1
15691 0 : XHIGT (JHIG) = XHIGT (ICRS)
15692 : End If
15693 : End Do
15694 : !
15695 0 : Do ICRS = ICRS + 1, IFIN
15696 0 : If (XHIGT(ICRS) <= XPIV) Then
15697 0 : JLOW = JLOW + 1
15698 0 : XLOWT (JLOW) = XHIGT (ICRS)
15699 : End If
15700 : End Do
15701 : End Select
15702 : !
15703 : !
15704 : Case (1)
15705 : !
15706 : ! Only 1 value is missing in low part
15707 : !
15708 0 : XMIN = XHIGT(1)
15709 0 : IHIG = 1
15710 0 : Do ICRS = 2, JHIG
15711 0 : If (XHIGT(ICRS) < XMIN) Then
15712 0 : XMIN = XHIGT(ICRS)
15713 0 : IHIG = ICRS
15714 : End If
15715 : End Do
15716 : !
15717 0 : VALNTH = XHIGT (IHIG)
15718 0 : Return
15719 : !
15720 : !
15721 : Case (0)
15722 : !
15723 : ! Low part is exactly what we want
15724 : !
15725 : Exit
15726 : !
15727 : !
15728 : Case (-5 : -1)
15729 : !
15730 : ! Only few values too many in low part
15731 : !
15732 0 : XHIGT (1) = XLOWT (1)
15733 0 : ILOW = 1 + INTH - JLOW
15734 0 : Do ICRS = 2, INTH
15735 0 : XWRK = XLOWT (ICRS)
15736 0 : Do IDCR = ICRS - 1, MAX (1, ILOW), - 1
15737 0 : If (XWRK < XHIGT(IDCR)) Then
15738 0 : XHIGT (IDCR + 1) = XHIGT (IDCR)
15739 : Else
15740 : Exit
15741 : End If
15742 : End Do
15743 0 : XHIGT (IDCR + 1) = XWRK
15744 0 : ILOW = ILOW + 1
15745 : End Do
15746 : !
15747 0 : XWRK1 = XHIGT(INTH)
15748 0 : ILOW = 2 * INTH - JLOW
15749 0 : Do ICRS = INTH + 1, JLOW
15750 0 : If (XLOWT (ICRS) < XWRK1) Then
15751 0 : XWRK = XLOWT (ICRS)
15752 0 : Do IDCR = INTH - 1, MAX (1, ILOW), - 1
15753 0 : If (XWRK >= XHIGT(IDCR)) Exit
15754 0 : XHIGT (IDCR + 1) = XHIGT (IDCR)
15755 : End Do
15756 0 : XHIGT (IDCR + 1) = XLOWT (ICRS)
15757 0 : XWRK1 = XHIGT(INTH)
15758 : End If
15759 0 : ILOW = ILOW + 1
15760 : End Do
15761 : !
15762 0 : VALNTH = XHIGT(INTH)
15763 0 : Return
15764 : !
15765 : !
15766 : Case (: -6)
15767 : !
15768 : ! last case: too many values in low part
15769 : !
15770 :
15771 0 : IMIL = (JLOW + 1) / 2
15772 0 : IFIN = JLOW
15773 : !
15774 : ! One chooses a pivot from 1st, last, and middle values
15775 : !
15776 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
15777 0 : XWRK = XLOWT (1)
15778 0 : XLOWT (1) = XLOWT (IMIL)
15779 0 : XLOWT (IMIL) = XWRK
15780 : End If
15781 0 : If (XLOWT(IMIL) > XLOWT(IFIN)) Then
15782 0 : XWRK = XLOWT (IFIN)
15783 0 : XLOWT (IFIN) = XLOWT (IMIL)
15784 0 : XLOWT (IMIL) = XWRK
15785 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
15786 0 : XWRK = XLOWT (1)
15787 0 : XLOWT (1) = XLOWT (IMIL)
15788 0 : XLOWT (IMIL) = XWRK
15789 : End If
15790 : End If
15791 0 : If (IFIN <= 3) Exit
15792 : !
15793 : XPIV = XLOWT(1) + REAL(INTH, dp) / REAL(JLOW + INTH, dp) * &
15794 0 : (XLOWT(IFIN) - XLOWT(1))
15795 :
15796 : !
15797 : ! One takes values > XPIV to XHIGT
15798 : !
15799 0 : JHIG = 0
15800 0 : JLOW = 0
15801 : !
15802 0 : If (XLOWT(IFIN) > XPIV) Then
15803 : ICRS = 0
15804 : Do
15805 0 : ICRS = ICRS + 1
15806 0 : If (XLOWT(ICRS) > XPIV) Then
15807 0 : JHIG = JHIG + 1
15808 0 : XHIGT (JHIG) = XLOWT (ICRS)
15809 0 : If (ICRS >= IFIN) Exit
15810 : Else
15811 0 : JLOW = JLOW + 1
15812 0 : XLOWT (JLOW) = XLOWT (ICRS)
15813 0 : If (JLOW >= INTH) Exit
15814 : End If
15815 : End Do
15816 : !
15817 0 : If (ICRS < IFIN) Then
15818 : Do
15819 0 : ICRS = ICRS + 1
15820 0 : If (XLOWT(ICRS) <= XPIV) Then
15821 0 : JLOW = JLOW + 1
15822 0 : XLOWT (JLOW) = XLOWT (ICRS)
15823 : Else
15824 0 : If (ICRS >= IFIN) Exit
15825 : End If
15826 : End Do
15827 : End If
15828 : Else
15829 0 : Do ICRS = 1, IFIN
15830 0 : If (XLOWT(ICRS) > XPIV) Then
15831 0 : JHIG = JHIG + 1
15832 0 : XHIGT (JHIG) = XLOWT (ICRS)
15833 : Else
15834 0 : JLOW = JLOW + 1
15835 0 : XLOWT (JLOW) = XLOWT (ICRS)
15836 0 : If (JLOW >= INTH) Exit
15837 : End If
15838 : End Do
15839 : !
15840 0 : Do ICRS = ICRS + 1, IFIN
15841 0 : If (XLOWT(ICRS) <= XPIV) Then
15842 0 : JLOW = JLOW + 1
15843 0 : XLOWT (JLOW) = XLOWT (ICRS)
15844 : End If
15845 : End Do
15846 : End If
15847 : !
15848 : End Select
15849 : !
15850 : End Do
15851 : !
15852 : ! Now, we only need to find maximum of the 1:INTH set
15853 : !
15854 0 : VALNTH = MAXVAL (XLOWT (1 : INTH))
15855 : Return
15856 : !
15857 : !
15858 0 : End Function D_valnth
15859 :
15860 0 : Function R_valnth (XDONT, NORD) Result (valnth)
15861 : ! Return NORDth value of XDONT, i.e fractile of order NORD/SIZE(XDONT).
15862 : ! __________________________________________________________
15863 : ! This routine uses a pivoting strategy such as the one of
15864 : ! finding the median based on the quicksort algorithm, but
15865 : ! we skew the pivot choice to try to bring it to NORD as
15866 : ! fast as possible. It uses 2 temporary arrays, where it
15867 : ! stores the indices of the values smaller than the pivot
15868 : ! (ILOWT), and the indices of values larger than the pivot
15869 : ! that we might still need later on (IHIGT). It iterates
15870 : ! until it can bring the number of values in ILOWT to
15871 : ! exactly NORD, and then finds the maximum of this set.
15872 : ! Michel Olagnon - Aug. 2000
15873 : ! __________________________________________________________
15874 : ! _________________________________________________________
15875 : Real(kind = sp), Dimension (:), Intent (In) :: XDONT
15876 : Real(kind = sp) :: valnth
15877 : Integer(kind = i4), Intent (In) :: NORD
15878 : ! __________________________________________________________
15879 0 : Real(kind = sp), Dimension (SIZE(XDONT)) :: XLOWT, XHIGT
15880 0 : Real(kind = sp) :: XPIV, XWRK, XWRK1, XWRK2, XWRK3, XMIN, XMAX
15881 : !
15882 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG
15883 : Integer(kind = i4) :: IMIL, IFIN, ICRS, IDCR, ILOW
15884 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1, INTH
15885 : !
15886 0 : NDON = SIZE (XDONT)
15887 0 : INTH = MAX (MIN (NORD, NDON), 1)
15888 : !
15889 : ! First loop is used to fill-in XLOWT, XHIGT at the same time
15890 : !
15891 0 : If (NDON < 2) Then
15892 0 : If (INTH == 1) VALNTH = XDONT (1)
15893 0 : Return
15894 : End If
15895 : !
15896 : ! One chooses a pivot, best estimate possible to put fractile near
15897 : ! mid-point of the set of low values.
15898 : !
15899 0 : If (XDONT(2) < XDONT(1)) Then
15900 0 : XLOWT (1) = XDONT(2)
15901 0 : XHIGT (1) = XDONT(1)
15902 : Else
15903 0 : XLOWT (1) = XDONT(1)
15904 0 : XHIGT (1) = XDONT(2)
15905 : End If
15906 : !
15907 0 : If (NDON < 3) Then
15908 0 : If (INTH == 1) VALNTH = XLOWT (1)
15909 0 : If (INTH == 2) VALNTH = XHIGT (1)
15910 0 : Return
15911 : End If
15912 : !
15913 0 : If (XDONT(3) < XHIGT(1)) Then
15914 0 : XHIGT (2) = XHIGT (1)
15915 0 : If (XDONT(3) < XLOWT(1)) Then
15916 0 : XHIGT (1) = XLOWT (1)
15917 0 : XLOWT (1) = XDONT(3)
15918 : Else
15919 0 : XHIGT (1) = XDONT(3)
15920 : End If
15921 : Else
15922 0 : XHIGT (2) = XDONT(3)
15923 : End If
15924 : !
15925 0 : If (NDON < 4) Then
15926 0 : If (INTH == 1) Then
15927 0 : VALNTH = XLOWT (1)
15928 : Else
15929 0 : VALNTH = XHIGT (INTH - 1)
15930 : End If
15931 0 : Return
15932 : End If
15933 : !
15934 0 : If (XDONT(NDON) < XHIGT(1)) Then
15935 0 : XHIGT (3) = XHIGT (2)
15936 0 : XHIGT (2) = XHIGT (1)
15937 0 : If (XDONT(NDON) < XLOWT(1)) Then
15938 0 : XHIGT (1) = XLOWT (1)
15939 0 : XLOWT (1) = XDONT(NDON)
15940 : Else
15941 0 : XHIGT (1) = XDONT(NDON)
15942 : End If
15943 : Else
15944 0 : XHIGT (3) = XDONT(NDON)
15945 : End If
15946 : !
15947 0 : If (NDON < 5) Then
15948 0 : If (INTH == 1) Then
15949 0 : VALNTH = XLOWT (1)
15950 : Else
15951 0 : VALNTH = XHIGT (INTH - 1)
15952 : End If
15953 0 : Return
15954 : End If
15955 : !
15956 :
15957 0 : JLOW = 1
15958 0 : JHIG = 3
15959 0 : XPIV = XLOWT(1) + REAL(2 * INTH, sp) / REAL(NDON + INTH, sp) * (XHIGT(3) - XLOWT(1))
15960 0 : If (XPIV >= XHIGT(1)) Then
15961 : XPIV = XLOWT(1) + REAL(2 * INTH, sp) / REAL(NDON + INTH, sp) * &
15962 0 : (XHIGT(2) - XLOWT(1))
15963 0 : If (XPIV >= XHIGT(1)) &
15964 : XPIV = XLOWT(1) + REAL(2 * INTH, sp) / REAL(NDON + INTH, sp) * &
15965 0 : (XHIGT(1) - XLOWT(1))
15966 : End If
15967 : !
15968 : ! One puts values > pivot in the end and those <= pivot
15969 : ! at the beginning. This is split in 2 cases, so that
15970 : ! we can skip the loop test a number of times.
15971 : ! As we are also filling in the work arrays at the same time
15972 : ! we stop filling in the XHIGT array as soon as we have more
15973 : ! than enough values in XLOWT.
15974 : !
15975 : !
15976 0 : If (XDONT(NDON) > XPIV) Then
15977 : ICRS = 3
15978 : Do
15979 0 : ICRS = ICRS + 1
15980 0 : If (XDONT(ICRS) > XPIV) Then
15981 0 : If (ICRS >= NDON) Exit
15982 0 : JHIG = JHIG + 1
15983 0 : XHIGT (JHIG) = XDONT(ICRS)
15984 : Else
15985 0 : JLOW = JLOW + 1
15986 0 : XLOWT (JLOW) = XDONT(ICRS)
15987 0 : If (JLOW >= INTH) Exit
15988 : End If
15989 : End Do
15990 : !
15991 : ! One restricts further processing because it is no use
15992 : ! to store more high values
15993 : !
15994 0 : If (ICRS < NDON - 1) Then
15995 : Do
15996 0 : ICRS = ICRS + 1
15997 0 : If (XDONT(ICRS) <= XPIV) Then
15998 0 : JLOW = JLOW + 1
15999 0 : XLOWT (JLOW) = XDONT(ICRS)
16000 0 : Else If (ICRS >= NDON) Then
16001 : Exit
16002 : End If
16003 : End Do
16004 : End If
16005 : !
16006 : !
16007 : Else
16008 : !
16009 : ! Same as above, but this is not as easy to optimize, so the
16010 : ! DO-loop is kept
16011 : !
16012 0 : Do ICRS = 4, NDON - 1
16013 0 : If (XDONT(ICRS) > XPIV) Then
16014 0 : JHIG = JHIG + 1
16015 0 : XHIGT (JHIG) = XDONT(ICRS)
16016 : Else
16017 0 : JLOW = JLOW + 1
16018 0 : XLOWT (JLOW) = XDONT(ICRS)
16019 0 : If (JLOW >= INTH) Exit
16020 : End If
16021 : End Do
16022 : !
16023 0 : If (ICRS < NDON - 1) Then
16024 : Do
16025 0 : ICRS = ICRS + 1
16026 0 : If (XDONT(ICRS) <= XPIV) Then
16027 0 : If (ICRS >= NDON) Exit
16028 0 : JLOW = JLOW + 1
16029 0 : XLOWT (JLOW) = XDONT(ICRS)
16030 : End If
16031 : End Do
16032 : End If
16033 : End If
16034 : !
16035 : JLM2 = 0
16036 : JLM1 = 0
16037 : JHM2 = 0
16038 : JHM1 = 0
16039 : Do
16040 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
16041 : !
16042 : ! We are oscillating. Perturbate by bringing JLOW closer by one
16043 : ! to INTH
16044 : !
16045 0 : If (INTH > JLOW) Then
16046 0 : XMIN = XHIGT(1)
16047 0 : IHIG = 1
16048 0 : Do ICRS = 2, JHIG
16049 0 : If (XHIGT(ICRS) < XMIN) Then
16050 0 : XMIN = XHIGT(ICRS)
16051 0 : IHIG = ICRS
16052 : End If
16053 : End Do
16054 : !
16055 0 : JLOW = JLOW + 1
16056 0 : XLOWT (JLOW) = XHIGT (IHIG)
16057 0 : XHIGT (IHIG) = XHIGT (JHIG)
16058 0 : JHIG = JHIG - 1
16059 : Else
16060 :
16061 0 : XMAX = XLOWT (JLOW)
16062 0 : JLOW = JLOW - 1
16063 0 : Do ICRS = 1, JLOW
16064 0 : If (XLOWT(ICRS) > XMAX) Then
16065 0 : XWRK = XMAX
16066 0 : XMAX = XLOWT(ICRS)
16067 0 : XLOWT (ICRS) = XWRK
16068 : End If
16069 : End Do
16070 : End If
16071 : End If
16072 0 : JLM2 = JLM1
16073 0 : JLM1 = JLOW
16074 0 : JHM2 = JHM1
16075 0 : JHM1 = JHIG
16076 : !
16077 : ! We try to bring the number of values in the low values set
16078 : ! closer to INTH.
16079 : !
16080 0 : Select Case (INTH - JLOW)
16081 : Case (2 :)
16082 : !
16083 : ! Not enough values in low part, at least 2 are missing
16084 : !
16085 0 : INTH = INTH - JLOW
16086 0 : JLOW = 0
16087 : Select Case (JHIG)
16088 : !!!!! CASE DEFAULT
16089 : !!!!! write (unit=*,fmt=*) "Assertion failed"
16090 : !!!!! STOP
16091 : !
16092 : ! We make a special case when we have so few values in
16093 : ! the high values set that it is bad performance to choose a pivot
16094 : ! and apply the general algorithm.
16095 : !
16096 : Case (2)
16097 0 : If (XHIGT(1) <= XHIGT(2)) Then
16098 0 : JLOW = JLOW + 1
16099 0 : XLOWT (JLOW) = XHIGT (1)
16100 0 : JLOW = JLOW + 1
16101 0 : XLOWT (JLOW) = XHIGT (2)
16102 : Else
16103 0 : JLOW = JLOW + 1
16104 0 : XLOWT (JLOW) = XHIGT (2)
16105 0 : JLOW = JLOW + 1
16106 0 : XLOWT (JLOW) = XHIGT (1)
16107 : End If
16108 : Exit
16109 : !
16110 : Case (3)
16111 : !
16112 : !
16113 0 : XWRK1 = XHIGT (1)
16114 0 : XWRK2 = XHIGT (2)
16115 0 : XWRK3 = XHIGT (3)
16116 0 : If (XWRK2 < XWRK1) Then
16117 0 : XHIGT (1) = XWRK2
16118 0 : XHIGT (2) = XWRK1
16119 0 : XWRK2 = XWRK1
16120 : End If
16121 0 : If (XWRK2 > XWRK3) Then
16122 0 : XHIGT (3) = XWRK2
16123 0 : XHIGT (2) = XWRK3
16124 0 : XWRK2 = XWRK3
16125 0 : If (XWRK2 < XHIGT(1)) Then
16126 0 : XHIGT (2) = XHIGT (1)
16127 0 : XHIGT (1) = XWRK2
16128 : End If
16129 : End If
16130 : JHIG = 0
16131 0 : Do ICRS = JLOW + 1, INTH
16132 0 : JHIG = JHIG + 1
16133 0 : XLOWT (ICRS) = XHIGT (JHIG)
16134 : End Do
16135 0 : JLOW = INTH
16136 : Exit
16137 : !
16138 : Case (4 :)
16139 : !
16140 : !
16141 0 : IFIN = JHIG
16142 : !
16143 : ! One chooses a pivot from the 2 first values and the last one.
16144 : ! This should ensure sufficient renewal between iterations to
16145 : ! avoid worst case behavior effects.
16146 : !
16147 0 : XWRK1 = XHIGT (1)
16148 0 : XWRK2 = XHIGT (2)
16149 0 : XWRK3 = XHIGT (IFIN)
16150 0 : If (XWRK2 < XWRK1) Then
16151 0 : XHIGT (1) = XWRK2
16152 0 : XHIGT (2) = XWRK1
16153 0 : XWRK2 = XWRK1
16154 : End If
16155 0 : If (XWRK2 > XWRK3) Then
16156 0 : XHIGT (IFIN) = XWRK2
16157 0 : XHIGT (2) = XWRK3
16158 0 : XWRK2 = XWRK3
16159 0 : If (XWRK2 < XHIGT(1)) Then
16160 0 : XHIGT (2) = XHIGT (1)
16161 0 : XHIGT (1) = XWRK2
16162 : End If
16163 : End If
16164 : !
16165 0 : XWRK1 = XHIGT (1)
16166 0 : JLOW = JLOW + 1
16167 0 : XLOWT (JLOW) = XWRK1
16168 0 : XPIV = XWRK1 + 0.5 * (XHIGT(IFIN) - XWRK1)
16169 : !
16170 : ! One takes values <= pivot to XLOWT
16171 : ! Again, 2 parts, one where we take care of the remaining
16172 : ! high values because we might still need them, and the
16173 : ! other when we know that we will have more than enough
16174 : ! low values in the end.
16175 : !
16176 0 : JHIG = 0
16177 0 : Do ICRS = 2, IFIN
16178 0 : If (XHIGT(ICRS) <= XPIV) Then
16179 0 : JLOW = JLOW + 1
16180 0 : XLOWT (JLOW) = XHIGT (ICRS)
16181 0 : If (JLOW >= INTH) Exit
16182 : Else
16183 0 : JHIG = JHIG + 1
16184 0 : XHIGT (JHIG) = XHIGT (ICRS)
16185 : End If
16186 : End Do
16187 : !
16188 0 : Do ICRS = ICRS + 1, IFIN
16189 0 : If (XHIGT(ICRS) <= XPIV) Then
16190 0 : JLOW = JLOW + 1
16191 0 : XLOWT (JLOW) = XHIGT (ICRS)
16192 : End If
16193 : End Do
16194 : End Select
16195 : !
16196 : !
16197 : Case (1)
16198 : !
16199 : ! Only 1 value is missing in low part
16200 : !
16201 0 : XMIN = XHIGT(1)
16202 0 : IHIG = 1
16203 0 : Do ICRS = 2, JHIG
16204 0 : If (XHIGT(ICRS) < XMIN) Then
16205 0 : XMIN = XHIGT(ICRS)
16206 0 : IHIG = ICRS
16207 : End If
16208 : End Do
16209 : !
16210 0 : VALNTH = XHIGT (IHIG)
16211 0 : Return
16212 : !
16213 : !
16214 : Case (0)
16215 : !
16216 : ! Low part is exactly what we want
16217 : !
16218 : Exit
16219 : !
16220 : !
16221 : Case (-5 : -1)
16222 : !
16223 : ! Only few values too many in low part
16224 : !
16225 0 : XHIGT (1) = XLOWT (1)
16226 0 : ILOW = 1 + INTH - JLOW
16227 0 : Do ICRS = 2, INTH
16228 0 : XWRK = XLOWT (ICRS)
16229 0 : Do IDCR = ICRS - 1, MAX (1, ILOW), - 1
16230 0 : If (XWRK < XHIGT(IDCR)) Then
16231 0 : XHIGT (IDCR + 1) = XHIGT (IDCR)
16232 : Else
16233 : Exit
16234 : End If
16235 : End Do
16236 0 : XHIGT (IDCR + 1) = XWRK
16237 0 : ILOW = ILOW + 1
16238 : End Do
16239 : !
16240 0 : XWRK1 = XHIGT(INTH)
16241 0 : ILOW = 2 * INTH - JLOW
16242 0 : Do ICRS = INTH + 1, JLOW
16243 0 : If (XLOWT (ICRS) < XWRK1) Then
16244 0 : XWRK = XLOWT (ICRS)
16245 0 : Do IDCR = INTH - 1, MAX (1, ILOW), - 1
16246 0 : If (XWRK >= XHIGT(IDCR)) Exit
16247 0 : XHIGT (IDCR + 1) = XHIGT (IDCR)
16248 : End Do
16249 0 : XHIGT (IDCR + 1) = XLOWT (ICRS)
16250 0 : XWRK1 = XHIGT(INTH)
16251 : End If
16252 0 : ILOW = ILOW + 1
16253 : End Do
16254 : !
16255 0 : VALNTH = XHIGT(INTH)
16256 0 : Return
16257 : !
16258 : !
16259 : Case (: -6)
16260 : !
16261 : ! last case: too many values in low part
16262 : !
16263 :
16264 0 : IMIL = (JLOW + 1) / 2
16265 0 : IFIN = JLOW
16266 : !
16267 : ! One chooses a pivot from 1st, last, and middle values
16268 : !
16269 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
16270 0 : XWRK = XLOWT (1)
16271 0 : XLOWT (1) = XLOWT (IMIL)
16272 0 : XLOWT (IMIL) = XWRK
16273 : End If
16274 0 : If (XLOWT(IMIL) > XLOWT(IFIN)) Then
16275 0 : XWRK = XLOWT (IFIN)
16276 0 : XLOWT (IFIN) = XLOWT (IMIL)
16277 0 : XLOWT (IMIL) = XWRK
16278 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
16279 0 : XWRK = XLOWT (1)
16280 0 : XLOWT (1) = XLOWT (IMIL)
16281 0 : XLOWT (IMIL) = XWRK
16282 : End If
16283 : End If
16284 0 : If (IFIN <= 3) Exit
16285 : !
16286 : XPIV = XLOWT(1) + REAL(INTH, sp) / REAL(JLOW + INTH, sp) * &
16287 0 : (XLOWT(IFIN) - XLOWT(1))
16288 :
16289 : !
16290 : ! One takes values > XPIV to XHIGT
16291 : !
16292 0 : JHIG = 0
16293 0 : JLOW = 0
16294 : !
16295 0 : If (XLOWT(IFIN) > XPIV) Then
16296 : ICRS = 0
16297 : Do
16298 0 : ICRS = ICRS + 1
16299 0 : If (XLOWT(ICRS) > XPIV) Then
16300 0 : JHIG = JHIG + 1
16301 0 : XHIGT (JHIG) = XLOWT (ICRS)
16302 0 : If (ICRS >= IFIN) Exit
16303 : Else
16304 0 : JLOW = JLOW + 1
16305 0 : XLOWT (JLOW) = XLOWT (ICRS)
16306 0 : If (JLOW >= INTH) Exit
16307 : End If
16308 : End Do
16309 : !
16310 0 : If (ICRS < IFIN) Then
16311 : Do
16312 0 : ICRS = ICRS + 1
16313 0 : If (XLOWT(ICRS) <= XPIV) Then
16314 0 : JLOW = JLOW + 1
16315 0 : XLOWT (JLOW) = XLOWT (ICRS)
16316 : Else
16317 0 : If (ICRS >= IFIN) Exit
16318 : End If
16319 : End Do
16320 : End If
16321 : Else
16322 0 : Do ICRS = 1, IFIN
16323 0 : If (XLOWT(ICRS) > XPIV) Then
16324 0 : JHIG = JHIG + 1
16325 0 : XHIGT (JHIG) = XLOWT (ICRS)
16326 : Else
16327 0 : JLOW = JLOW + 1
16328 0 : XLOWT (JLOW) = XLOWT (ICRS)
16329 0 : If (JLOW >= INTH) Exit
16330 : End If
16331 : End Do
16332 : !
16333 0 : Do ICRS = ICRS + 1, IFIN
16334 0 : If (XLOWT(ICRS) <= XPIV) Then
16335 0 : JLOW = JLOW + 1
16336 0 : XLOWT (JLOW) = XLOWT (ICRS)
16337 : End If
16338 : End Do
16339 : End If
16340 : !
16341 : End Select
16342 : !
16343 : End Do
16344 : !
16345 : ! Now, we only need to find maximum of the 1:INTH set
16346 : !
16347 0 : VALNTH = MAXVAL (XLOWT (1 : INTH))
16348 : Return
16349 : !
16350 : !
16351 0 : End Function R_valnth
16352 :
16353 0 : Function I_valnth (XDONT, NORD) Result (valnth)
16354 : ! Return NORDth value of XDONT, i.e fractile of order NORD/SIZE(XDONT).
16355 : ! __________________________________________________________
16356 : ! This routine uses a pivoting strategy such as the one of
16357 : ! finding the median based on the quicksort algorithm, but
16358 : ! we skew the pivot choice to try to bring it to NORD as
16359 : ! fast as possible. It uses 2 temporary arrays, where it
16360 : ! stores the indices of the values smaller than the pivot
16361 : ! (ILOWT), and the indices of values larger than the pivot
16362 : ! that we might still need later on (IHIGT). It iterates
16363 : ! until it can bring the number of values in ILOWT to
16364 : ! exactly NORD, and then finds the maximum of this set.
16365 : ! Michel Olagnon - Aug. 2000
16366 : ! __________________________________________________________
16367 : ! __________________________________________________________
16368 : Integer(kind = i4), Dimension (:), Intent (In) :: XDONT
16369 : Integer(kind = i4) :: valnth
16370 : Integer(kind = i4), Intent (In) :: NORD
16371 : ! __________________________________________________________
16372 0 : Integer(kind = i4), Dimension (SIZE(XDONT)) :: XLOWT, XHIGT
16373 : Integer(kind = i4) :: XPIV, XWRK, XWRK1, XWRK2, XWRK3, XMIN, XMAX
16374 : !
16375 : Integer(kind = i4) :: NDON, JHIG, JLOW, IHIG
16376 : Integer(kind = i4) :: IMIL, IFIN, ICRS, IDCR, ILOW
16377 : Integer(kind = i4) :: JLM2, JLM1, JHM2, JHM1, INTH
16378 : !
16379 0 : NDON = SIZE (XDONT)
16380 0 : INTH = MAX (MIN (NORD, NDON), 1)
16381 : !
16382 : ! First loop is used to fill-in XLOWT, XHIGT at the same time
16383 : !
16384 0 : If (NDON < 2) Then
16385 0 : If (INTH == 1) VALNTH = XDONT (1)
16386 0 : Return
16387 : End If
16388 : !
16389 : ! One chooses a pivot, best estimate possible to put fractile near
16390 : ! mid-point of the set of low values.
16391 : !
16392 0 : If (XDONT(2) < XDONT(1)) Then
16393 0 : XLOWT (1) = XDONT(2)
16394 0 : XHIGT (1) = XDONT(1)
16395 : Else
16396 0 : XLOWT (1) = XDONT(1)
16397 0 : XHIGT (1) = XDONT(2)
16398 : End If
16399 : !
16400 0 : If (NDON < 3) Then
16401 0 : If (INTH == 1) VALNTH = XLOWT (1)
16402 0 : If (INTH == 2) VALNTH = XHIGT (1)
16403 0 : Return
16404 : End If
16405 : !
16406 0 : If (XDONT(3) < XHIGT(1)) Then
16407 0 : XHIGT (2) = XHIGT (1)
16408 0 : If (XDONT(3) < XLOWT(1)) Then
16409 0 : XHIGT (1) = XLOWT (1)
16410 0 : XLOWT (1) = XDONT(3)
16411 : Else
16412 0 : XHIGT (1) = XDONT(3)
16413 : End If
16414 : Else
16415 0 : XHIGT (2) = XDONT(3)
16416 : End If
16417 : !
16418 0 : If (NDON < 4) Then
16419 0 : If (INTH == 1) Then
16420 0 : VALNTH = XLOWT (1)
16421 : Else
16422 0 : VALNTH = XHIGT (INTH - 1)
16423 : End If
16424 0 : Return
16425 : End If
16426 : !
16427 0 : If (XDONT(NDON) < XHIGT(1)) Then
16428 0 : XHIGT (3) = XHIGT (2)
16429 0 : XHIGT (2) = XHIGT (1)
16430 0 : If (XDONT(NDON) < XLOWT(1)) Then
16431 0 : XHIGT (1) = XLOWT (1)
16432 0 : XLOWT (1) = XDONT(NDON)
16433 : Else
16434 0 : XHIGT (1) = XDONT(NDON)
16435 : End If
16436 : Else
16437 0 : XHIGT (3) = XDONT(NDON)
16438 : End If
16439 : !
16440 0 : If (NDON < 5) Then
16441 0 : If (INTH == 1) Then
16442 0 : VALNTH = XLOWT (1)
16443 : Else
16444 0 : VALNTH = XHIGT (INTH - 1)
16445 : End If
16446 0 : Return
16447 : End If
16448 : !
16449 :
16450 0 : JLOW = 1
16451 0 : JHIG = 3
16452 0 : XPIV = XLOWT(1) + INT(REAL(2 * INTH, sp) / REAL(NDON + INTH, sp), i4) * (XHIGT(3) - XLOWT(1))
16453 0 : If (XPIV >= XHIGT(1)) Then
16454 : XPIV = XLOWT(1) + INT(REAL(2 * INTH, sp) / REAL(NDON + INTH, sp), i4) * &
16455 0 : (XHIGT(2) - XLOWT(1))
16456 0 : If (XPIV >= XHIGT(1)) &
16457 : XPIV = XLOWT(1) + INT(REAL(2 * INTH, sp) / REAL(NDON + INTH, sp), i4) * &
16458 0 : (XHIGT(1) - XLOWT(1))
16459 : End If
16460 : !
16461 : ! One puts values > pivot in the end and those <= pivot
16462 : ! at the beginning. This is split in 2 cases, so that
16463 : ! we can skip the loop test a number of times.
16464 : ! As we are also filling in the work arrays at the same time
16465 : ! we stop filling in the XHIGT array as soon as we have more
16466 : ! than enough values in XLOWT.
16467 : !
16468 : !
16469 0 : If (XDONT(NDON) > XPIV) Then
16470 : ICRS = 3
16471 : Do
16472 0 : ICRS = ICRS + 1
16473 0 : If (XDONT(ICRS) > XPIV) Then
16474 0 : If (ICRS >= NDON) Exit
16475 0 : JHIG = JHIG + 1
16476 0 : XHIGT (JHIG) = XDONT(ICRS)
16477 : Else
16478 0 : JLOW = JLOW + 1
16479 0 : XLOWT (JLOW) = XDONT(ICRS)
16480 0 : If (JLOW >= INTH) Exit
16481 : End If
16482 : End Do
16483 : !
16484 : ! One restricts further processing because it is no use
16485 : ! to store more high values
16486 : !
16487 0 : If (ICRS < NDON - 1) Then
16488 : Do
16489 0 : ICRS = ICRS + 1
16490 0 : If (XDONT(ICRS) <= XPIV) Then
16491 0 : JLOW = JLOW + 1
16492 0 : XLOWT (JLOW) = XDONT(ICRS)
16493 0 : Else If (ICRS >= NDON) Then
16494 : Exit
16495 : End If
16496 : End Do
16497 : End If
16498 : !
16499 : !
16500 : Else
16501 : !
16502 : ! Same as above, but this is not as easy to optimize, so the
16503 : ! DO-loop is kept
16504 : !
16505 0 : Do ICRS = 4, NDON - 1
16506 0 : If (XDONT(ICRS) > XPIV) Then
16507 0 : JHIG = JHIG + 1
16508 0 : XHIGT (JHIG) = XDONT(ICRS)
16509 : Else
16510 0 : JLOW = JLOW + 1
16511 0 : XLOWT (JLOW) = XDONT(ICRS)
16512 0 : If (JLOW >= INTH) Exit
16513 : End If
16514 : End Do
16515 : !
16516 0 : If (ICRS < NDON - 1) Then
16517 : Do
16518 0 : ICRS = ICRS + 1
16519 0 : If (XDONT(ICRS) <= XPIV) Then
16520 0 : If (ICRS >= NDON) Exit
16521 0 : JLOW = JLOW + 1
16522 0 : XLOWT (JLOW) = XDONT(ICRS)
16523 : End If
16524 : End Do
16525 : End If
16526 : End If
16527 : !
16528 : JLM2 = 0
16529 : JLM1 = 0
16530 : JHM2 = 0
16531 : JHM1 = 0
16532 : Do
16533 0 : If (JLM2 == JLOW .And. JHM2 == JHIG) Then
16534 : !
16535 : ! We are oscillating. Perturbate by bringing JLOW closer by one
16536 : ! to INTH
16537 : !
16538 0 : If (INTH > JLOW) Then
16539 0 : XMIN = XHIGT(1)
16540 0 : IHIG = 1
16541 0 : Do ICRS = 2, JHIG
16542 0 : If (XHIGT(ICRS) < XMIN) Then
16543 0 : XMIN = XHIGT(ICRS)
16544 0 : IHIG = ICRS
16545 : End If
16546 : End Do
16547 : !
16548 0 : JLOW = JLOW + 1
16549 0 : XLOWT (JLOW) = XHIGT (IHIG)
16550 0 : XHIGT (IHIG) = XHIGT (JHIG)
16551 0 : JHIG = JHIG - 1
16552 : Else
16553 :
16554 0 : XMAX = XLOWT (JLOW)
16555 0 : JLOW = JLOW - 1
16556 0 : Do ICRS = 1, JLOW
16557 0 : If (XLOWT(ICRS) > XMAX) Then
16558 0 : XWRK = XMAX
16559 0 : XMAX = XLOWT(ICRS)
16560 0 : XLOWT (ICRS) = XWRK
16561 : End If
16562 : End Do
16563 : End If
16564 : End If
16565 0 : JLM2 = JLM1
16566 0 : JLM1 = JLOW
16567 0 : JHM2 = JHM1
16568 0 : JHM1 = JHIG
16569 : !
16570 : ! We try to bring the number of values in the low values set
16571 : ! closer to INTH.
16572 : !
16573 0 : Select Case (INTH - JLOW)
16574 : Case (2 :)
16575 : !
16576 : ! Not enough values in low part, at least 2 are missing
16577 : !
16578 0 : INTH = INTH - JLOW
16579 0 : JLOW = 0
16580 : Select Case (JHIG)
16581 : !!!!! CASE DEFAULT
16582 : !!!!! write (unit=*,fmt=*) "Assertion failed"
16583 : !!!!! STOP
16584 : !
16585 : ! We make a special case when we have so few values in
16586 : ! the high values set that it is bad performance to choose a pivot
16587 : ! and apply the general algorithm.
16588 : !
16589 : Case (2)
16590 0 : If (XHIGT(1) <= XHIGT(2)) Then
16591 0 : JLOW = JLOW + 1
16592 0 : XLOWT (JLOW) = XHIGT (1)
16593 0 : JLOW = JLOW + 1
16594 0 : XLOWT (JLOW) = XHIGT (2)
16595 : Else
16596 0 : JLOW = JLOW + 1
16597 0 : XLOWT (JLOW) = XHIGT (2)
16598 0 : JLOW = JLOW + 1
16599 0 : XLOWT (JLOW) = XHIGT (1)
16600 : End If
16601 : Exit
16602 : !
16603 : Case (3)
16604 : !
16605 : !
16606 0 : XWRK1 = XHIGT (1)
16607 0 : XWRK2 = XHIGT (2)
16608 0 : XWRK3 = XHIGT (3)
16609 0 : If (XWRK2 < XWRK1) Then
16610 0 : XHIGT (1) = XWRK2
16611 0 : XHIGT (2) = XWRK1
16612 0 : XWRK2 = XWRK1
16613 : End If
16614 0 : If (XWRK2 > XWRK3) Then
16615 0 : XHIGT (3) = XWRK2
16616 0 : XHIGT (2) = XWRK3
16617 0 : XWRK2 = XWRK3
16618 0 : If (XWRK2 < XHIGT(1)) Then
16619 0 : XHIGT (2) = XHIGT (1)
16620 0 : XHIGT (1) = XWRK2
16621 : End If
16622 : End If
16623 : JHIG = 0
16624 0 : Do ICRS = JLOW + 1, INTH
16625 0 : JHIG = JHIG + 1
16626 0 : XLOWT (ICRS) = XHIGT (JHIG)
16627 : End Do
16628 0 : JLOW = INTH
16629 : Exit
16630 : !
16631 : Case (4 :)
16632 : !
16633 : !
16634 0 : IFIN = JHIG
16635 : !
16636 : ! One chooses a pivot from the 2 first values and the last one.
16637 : ! This should ensure sufficient renewal between iterations to
16638 : ! avoid worst case behavior effects.
16639 : !
16640 0 : XWRK1 = XHIGT (1)
16641 0 : XWRK2 = XHIGT (2)
16642 0 : XWRK3 = XHIGT (IFIN)
16643 0 : If (XWRK2 < XWRK1) Then
16644 0 : XHIGT (1) = XWRK2
16645 0 : XHIGT (2) = XWRK1
16646 0 : XWRK2 = XWRK1
16647 : End If
16648 0 : If (XWRK2 > XWRK3) Then
16649 0 : XHIGT (IFIN) = XWRK2
16650 0 : XHIGT (2) = XWRK3
16651 0 : XWRK2 = XWRK3
16652 0 : If (XWRK2 < XHIGT(1)) Then
16653 0 : XHIGT (2) = XHIGT (1)
16654 0 : XHIGT (1) = XWRK2
16655 : End If
16656 : End If
16657 : !
16658 0 : XWRK1 = XHIGT (1)
16659 0 : JLOW = JLOW + 1
16660 0 : XLOWT (JLOW) = XWRK1
16661 0 : XPIV = XWRK1 + (XHIGT(IFIN) - XWRK1) / 2
16662 : !
16663 : ! One takes values <= pivot to XLOWT
16664 : ! Again, 2 parts, one where we take care of the remaining
16665 : ! high values because we might still need them, and the
16666 : ! other when we know that we will have more than enough
16667 : ! low values in the end.
16668 : !
16669 0 : JHIG = 0
16670 0 : Do ICRS = 2, IFIN
16671 0 : If (XHIGT(ICRS) <= XPIV) Then
16672 0 : JLOW = JLOW + 1
16673 0 : XLOWT (JLOW) = XHIGT (ICRS)
16674 0 : If (JLOW >= INTH) Exit
16675 : Else
16676 0 : JHIG = JHIG + 1
16677 0 : XHIGT (JHIG) = XHIGT (ICRS)
16678 : End If
16679 : End Do
16680 : !
16681 0 : Do ICRS = ICRS + 1, IFIN
16682 0 : If (XHIGT(ICRS) <= XPIV) Then
16683 0 : JLOW = JLOW + 1
16684 0 : XLOWT (JLOW) = XHIGT (ICRS)
16685 : End If
16686 : End Do
16687 : End Select
16688 : !
16689 : !
16690 : Case (1)
16691 : !
16692 : ! Only 1 value is missing in low part
16693 : !
16694 0 : XMIN = XHIGT(1)
16695 0 : IHIG = 1
16696 0 : Do ICRS = 2, JHIG
16697 0 : If (XHIGT(ICRS) < XMIN) Then
16698 0 : XMIN = XHIGT(ICRS)
16699 0 : IHIG = ICRS
16700 : End If
16701 : End Do
16702 : !
16703 0 : VALNTH = XHIGT (IHIG)
16704 0 : Return
16705 : !
16706 : !
16707 : Case (0)
16708 : !
16709 : ! Low part is exactly what we want
16710 : !
16711 : Exit
16712 : !
16713 : !
16714 : Case (-5 : -1)
16715 : !
16716 : ! Only few values too many in low part
16717 : !
16718 0 : XHIGT (1) = XLOWT (1)
16719 0 : ILOW = 1 + INTH - JLOW
16720 0 : Do ICRS = 2, INTH
16721 0 : XWRK = XLOWT (ICRS)
16722 0 : Do IDCR = ICRS - 1, MAX (1, ILOW), - 1
16723 0 : If (XWRK < XHIGT(IDCR)) Then
16724 0 : XHIGT (IDCR + 1) = XHIGT (IDCR)
16725 : Else
16726 : Exit
16727 : End If
16728 : End Do
16729 0 : XHIGT (IDCR + 1) = XWRK
16730 0 : ILOW = ILOW + 1
16731 : End Do
16732 : !
16733 0 : XWRK1 = XHIGT(INTH)
16734 0 : ILOW = 2 * INTH - JLOW
16735 0 : Do ICRS = INTH + 1, JLOW
16736 0 : If (XLOWT (ICRS) < XWRK1) Then
16737 0 : XWRK = XLOWT (ICRS)
16738 0 : Do IDCR = INTH - 1, MAX (1, ILOW), - 1
16739 0 : If (XWRK >= XHIGT(IDCR)) Exit
16740 0 : XHIGT (IDCR + 1) = XHIGT (IDCR)
16741 : End Do
16742 0 : XHIGT (IDCR + 1) = XLOWT (ICRS)
16743 0 : XWRK1 = XHIGT(INTH)
16744 : End If
16745 0 : ILOW = ILOW + 1
16746 : End Do
16747 : !
16748 0 : VALNTH = XHIGT(INTH)
16749 0 : Return
16750 : !
16751 : !
16752 : Case (: -6)
16753 : !
16754 : ! last case: too many values in low part
16755 : !
16756 :
16757 0 : IMIL = (JLOW + 1) / 2
16758 0 : IFIN = JLOW
16759 : !
16760 : ! One chooses a pivot from 1st, last, and middle values
16761 : !
16762 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
16763 0 : XWRK = XLOWT (1)
16764 0 : XLOWT (1) = XLOWT (IMIL)
16765 0 : XLOWT (IMIL) = XWRK
16766 : End If
16767 0 : If (XLOWT(IMIL) > XLOWT(IFIN)) Then
16768 0 : XWRK = XLOWT (IFIN)
16769 0 : XLOWT (IFIN) = XLOWT (IMIL)
16770 0 : XLOWT (IMIL) = XWRK
16771 0 : If (XLOWT(IMIL) < XLOWT(1)) Then
16772 0 : XWRK = XLOWT (1)
16773 0 : XLOWT (1) = XLOWT (IMIL)
16774 0 : XLOWT (IMIL) = XWRK
16775 : End If
16776 : End If
16777 0 : If (IFIN <= 3) Exit
16778 : !
16779 : XPIV = XLOWT(1) + INT(REAL(INTH, sp) / REAL(JLOW + INTH, sp), i4) * &
16780 0 : (XLOWT(IFIN) - XLOWT(1))
16781 :
16782 : !
16783 : ! One takes values > XPIV to XHIGT
16784 : !
16785 0 : JHIG = 0
16786 0 : JLOW = 0
16787 : !
16788 0 : If (XLOWT(IFIN) > XPIV) Then
16789 : ICRS = 0
16790 : Do
16791 0 : ICRS = ICRS + 1
16792 0 : If (XLOWT(ICRS) > XPIV) Then
16793 0 : JHIG = JHIG + 1
16794 0 : XHIGT (JHIG) = XLOWT (ICRS)
16795 0 : If (ICRS >= IFIN) Exit
16796 : Else
16797 0 : JLOW = JLOW + 1
16798 0 : XLOWT (JLOW) = XLOWT (ICRS)
16799 0 : If (JLOW >= INTH) Exit
16800 : End If
16801 : End Do
16802 : !
16803 0 : If (ICRS < IFIN) Then
16804 : Do
16805 0 : ICRS = ICRS + 1
16806 0 : If (XLOWT(ICRS) <= XPIV) Then
16807 0 : JLOW = JLOW + 1
16808 0 : XLOWT (JLOW) = XLOWT (ICRS)
16809 : Else
16810 0 : If (ICRS >= IFIN) Exit
16811 : End If
16812 : End Do
16813 : End If
16814 : Else
16815 0 : Do ICRS = 1, IFIN
16816 0 : If (XLOWT(ICRS) > XPIV) Then
16817 0 : JHIG = JHIG + 1
16818 0 : XHIGT (JHIG) = XLOWT (ICRS)
16819 : Else
16820 0 : JLOW = JLOW + 1
16821 0 : XLOWT (JLOW) = XLOWT (ICRS)
16822 0 : If (JLOW >= INTH) Exit
16823 : End If
16824 : End Do
16825 : !
16826 0 : Do ICRS = ICRS + 1, IFIN
16827 0 : If (XLOWT(ICRS) <= XPIV) Then
16828 0 : JLOW = JLOW + 1
16829 0 : XLOWT (JLOW) = XLOWT (ICRS)
16830 : End If
16831 : End Do
16832 : End If
16833 : !
16834 : End Select
16835 : !
16836 : End Do
16837 : !
16838 : ! Now, we only need to find maximum of the 1:INTH set
16839 : !
16840 0 : VALNTH = MAXVAL (XLOWT (1 : INTH))
16841 : Return
16842 : !
16843 : !
16844 0 : End Function I_valnth
16845 :
16846 : END MODULE mo_orderpack
|