ITM AMNS: User Interface  \$Id: Doxyfile 502 2015-10-15 12:23:45Z dpc $
m_mrgrnk.F90
Go to the documentation of this file.
1 
7 Module m_mrgrnk
8 ! http://www.fortran-2000.com/rank/mrgrnk.f90
9 Integer, Parameter :: kdp = selected_real_kind(15)
10 public :: mrgrnk
11 private :: kdp
12 private :: r_mrgrnk, i_mrgrnk, d_mrgrnk
13 interface mrgrnk
14  module procedure d_mrgrnk, r_mrgrnk, i_mrgrnk
15 end interface mrgrnk
16 contains
17 
18 Subroutine d_mrgrnk (XDONT, IRNGT)
19 ! __________________________________________________________
20 ! MRGRNK = Merge-sort ranking of an array
21 ! For performance reasons, the first 2 passes are taken
22 ! out of the standard loop, and use dedicated coding.
23 ! __________________________________________________________
24 ! __________________________________________________________
25  Real (kind=kdp), Dimension (:), Intent (In) :: xdont
26  Integer, Dimension (:), Intent (Out) :: irngt
27 ! __________________________________________________________
28  Real (kind=kdp) :: xvala, xvalb
29 !
30  Integer, Dimension (SIZE(IRNGT)) :: jwrkt
31  Integer :: lmtna, lmtnc, irng1, irng2
32  Integer :: nval, iind, iwrkd, iwrk, iwrkf, jinda, iinda, iindb
33 !
34  nval = min(SIZE(xdont), SIZE(irngt))
35  Select Case (nval)
36  Case (:0)
37  Return
38  Case (1)
39  irngt(1) = 1
40  Return
41  Case default
42  Continue
43  End Select
44 !
45 ! Fill-in the index array, creating ordered couples
46 !
47  Do iind = 2, nval, 2
48  If (xdont(iind-1) <= xdont(iind)) Then
49  irngt(iind-1) = iind - 1
50  irngt(iind) = iind
51  Else
52  irngt(iind-1) = iind
53  irngt(iind) = iind - 1
54  End If
55  End Do
56  If (modulo(nval, 2) /= 0) Then
57  irngt(nval) = nval
58  End If
59 !
60 ! We will now have ordered subsets A - B - A - B - ...
61 ! and merge A and B couples into C - C - ...
62 !
63  lmtna = 2
64  lmtnc = 4
65 !
66 ! First iteration. The length of the ordered subsets goes from 2 to 4
67 !
68  Do
69  If (nval <= 2) Exit
70 !
71 ! Loop on merges of A and B into C
72 !
73  Do iwrkd = 0, nval - 1, 4
74  If ((iwrkd+4) > nval) Then
75  If ((iwrkd+2) >= nval) Exit
76 !
77 ! 1 2 3
78 !
79  If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3))) Exit
80 !
81 ! 1 3 2
82 !
83  If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3))) Then
84  irng2 = irngt(iwrkd+2)
85  irngt(iwrkd+2) = irngt(iwrkd+3)
86  irngt(iwrkd+3) = irng2
87 !
88 ! 3 1 2
89 !
90  Else
91  irng1 = irngt(iwrkd+1)
92  irngt(iwrkd+1) = irngt(iwrkd+3)
93  irngt(iwrkd+3) = irngt(iwrkd+2)
94  irngt(iwrkd+2) = irng1
95  End If
96  Exit
97  End If
98 !
99 ! 1 2 3 4
100 !
101  If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3))) cycle
102 !
103 ! 1 3 x x
104 !
105  If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3))) Then
106  irng2 = irngt(iwrkd+2)
107  irngt(iwrkd+2) = irngt(iwrkd+3)
108  If (xdont(irng2) <= xdont(irngt(iwrkd+4))) Then
109 ! 1 3 2 4
110  irngt(iwrkd+3) = irng2
111  Else
112 ! 1 3 4 2
113  irngt(iwrkd+3) = irngt(iwrkd+4)
114  irngt(iwrkd+4) = irng2
115  End If
116 !
117 ! 3 x x x
118 !
119  Else
120  irng1 = irngt(iwrkd+1)
121  irng2 = irngt(iwrkd+2)
122  irngt(iwrkd+1) = irngt(iwrkd+3)
123  If (xdont(irng1) <= xdont(irngt(iwrkd+4))) Then
124  irngt(iwrkd+2) = irng1
125  If (xdont(irng2) <= xdont(irngt(iwrkd+4))) Then
126 ! 3 1 2 4
127  irngt(iwrkd+3) = irng2
128  Else
129 ! 3 1 4 2
130  irngt(iwrkd+3) = irngt(iwrkd+4)
131  irngt(iwrkd+4) = irng2
132  End If
133  Else
134 ! 3 4 1 2
135  irngt(iwrkd+2) = irngt(iwrkd+4)
136  irngt(iwrkd+3) = irng1
137  irngt(iwrkd+4) = irng2
138  End If
139  End If
140  End Do
141 !
142 ! The Cs become As and Bs
143 !
144  lmtna = 4
145  Exit
146  End Do
147 !
148 ! Iteration loop. Each time, the length of the ordered subsets
149 ! is doubled.
150 !
151  Do
152  If (lmtna >= nval) Exit
153  iwrkf = 0
154  lmtnc = 2 * lmtnc
155 !
156 ! Loop on merges of A and B into C
157 !
158  Do
159  iwrk = iwrkf
160  iwrkd = iwrkf + 1
161  jinda = iwrkf + lmtna
162  iwrkf = iwrkf + lmtnc
163  If (iwrkf >= nval) Then
164  If (jinda >= nval) Exit
165  iwrkf = nval
166  End If
167  iinda = 1
168  iindb = jinda + 1
169 !
170 ! Shortcut for the case when the max of A is smaller
171 ! than the min of B. This line may be activated when the
172 ! initial set is already close to sorted.
173 !
174 ! IF (XDONT(IRNGT(JINDA)) <= XDONT(IRNGT(IINDB))) CYCLE
175 !
176 ! One steps in the C subset, that we build in the final rank array
177 !
178 ! Make a copy of the rank array for the merge iteration
179 !
180  jwrkt(1:lmtna) = irngt(iwrkd:jinda)
181 !
182  xvala = xdont(jwrkt(iinda))
183  xvalb = xdont(irngt(iindb))
184 !
185  Do
186  iwrk = iwrk + 1
187 !
188 ! We still have unprocessed values in both A and B
189 !
190  If (xvala > xvalb) Then
191  irngt(iwrk) = irngt(iindb)
192  iindb = iindb + 1
193  If (iindb > iwrkf) Then
194 ! Only A still with unprocessed values
195  irngt(iwrk+1:iwrkf) = jwrkt(iinda:lmtna)
196  Exit
197  End If
198  xvalb = xdont(irngt(iindb))
199  Else
200  irngt(iwrk) = jwrkt(iinda)
201  iinda = iinda + 1
202  If (iinda > lmtna) exit! Only B still with unprocessed values
203  xvala = xdont(jwrkt(iinda))
204  End If
205 !
206  End Do
207  End Do
208 !
209 ! The Cs become As and Bs
210 !
211  lmtna = 2 * lmtna
212  End Do
213 !
214  Return
215 !
216 End Subroutine d_mrgrnk
217 
218 Subroutine r_mrgrnk (XDONT, IRNGT)
219 ! __________________________________________________________
220 ! MRGRNK = Merge-sort ranking of an array
221 ! For performance reasons, the first 2 passes are taken
222 ! out of the standard loop, and use dedicated coding.
223 ! __________________________________________________________
224 ! _________________________________________________________
225  Real, Dimension (:), Intent (In) :: xdont
226  Integer, Dimension (:), Intent (Out) :: irngt
227 ! __________________________________________________________
228  Real :: xvala, xvalb
229 !
230  Integer, Dimension (SIZE(IRNGT)) :: jwrkt
231  Integer :: lmtna, lmtnc, irng1, irng2
232  Integer :: nval, iind, iwrkd, iwrk, iwrkf, jinda, iinda, iindb
233 !
234  nval = min(SIZE(xdont), SIZE(irngt))
235  Select Case (nval)
236  Case (:0)
237  Return
238  Case (1)
239  irngt(1) = 1
240  Return
241  Case default
242  Continue
243  End Select
244 !
245 ! Fill-in the index array, creating ordered couples
246 !
247  Do iind = 2, nval, 2
248  If (xdont(iind-1) <= xdont(iind)) Then
249  irngt(iind-1) = iind - 1
250  irngt(iind) = iind
251  Else
252  irngt(iind-1) = iind
253  irngt(iind) = iind - 1
254  End If
255  End Do
256  If (modulo(nval, 2) /= 0) Then
257  irngt(nval) = nval
258  End If
259 !
260 ! We will now have ordered subsets A - B - A - B - ...
261 ! and merge A and B couples into C - C - ...
262 !
263  lmtna = 2
264  lmtnc = 4
265 !
266 ! First iteration. The length of the ordered subsets goes from 2 to 4
267 !
268  Do
269  If (nval <= 2) Exit
270 !
271 ! Loop on merges of A and B into C
272 !
273  Do iwrkd = 0, nval - 1, 4
274  If ((iwrkd+4) > nval) Then
275  If ((iwrkd+2) >= nval) Exit
276 !
277 ! 1 2 3
278 !
279  If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3))) Exit
280 !
281 ! 1 3 2
282 !
283  If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3))) Then
284  irng2 = irngt(iwrkd+2)
285  irngt(iwrkd+2) = irngt(iwrkd+3)
286  irngt(iwrkd+3) = irng2
287 !
288 ! 3 1 2
289 !
290  Else
291  irng1 = irngt(iwrkd+1)
292  irngt(iwrkd+1) = irngt(iwrkd+3)
293  irngt(iwrkd+3) = irngt(iwrkd+2)
294  irngt(iwrkd+2) = irng1
295  End If
296  Exit
297  End If
298 !
299 ! 1 2 3 4
300 !
301  If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3))) cycle
302 !
303 ! 1 3 x x
304 !
305  If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3))) Then
306  irng2 = irngt(iwrkd+2)
307  irngt(iwrkd+2) = irngt(iwrkd+3)
308  If (xdont(irng2) <= xdont(irngt(iwrkd+4))) Then
309 ! 1 3 2 4
310  irngt(iwrkd+3) = irng2
311  Else
312 ! 1 3 4 2
313  irngt(iwrkd+3) = irngt(iwrkd+4)
314  irngt(iwrkd+4) = irng2
315  End If
316 !
317 ! 3 x x x
318 !
319  Else
320  irng1 = irngt(iwrkd+1)
321  irng2 = irngt(iwrkd+2)
322  irngt(iwrkd+1) = irngt(iwrkd+3)
323  If (xdont(irng1) <= xdont(irngt(iwrkd+4))) Then
324  irngt(iwrkd+2) = irng1
325  If (xdont(irng2) <= xdont(irngt(iwrkd+4))) Then
326 ! 3 1 2 4
327  irngt(iwrkd+3) = irng2
328  Else
329 ! 3 1 4 2
330  irngt(iwrkd+3) = irngt(iwrkd+4)
331  irngt(iwrkd+4) = irng2
332  End If
333  Else
334 ! 3 4 1 2
335  irngt(iwrkd+2) = irngt(iwrkd+4)
336  irngt(iwrkd+3) = irng1
337  irngt(iwrkd+4) = irng2
338  End If
339  End If
340  End Do
341 !
342 ! The Cs become As and Bs
343 !
344  lmtna = 4
345  Exit
346  End Do
347 !
348 ! Iteration loop. Each time, the length of the ordered subsets
349 ! is doubled.
350 !
351  Do
352  If (lmtna >= nval) Exit
353  iwrkf = 0
354  lmtnc = 2 * lmtnc
355 !
356 ! Loop on merges of A and B into C
357 !
358  Do
359  iwrk = iwrkf
360  iwrkd = iwrkf + 1
361  jinda = iwrkf + lmtna
362  iwrkf = iwrkf + lmtnc
363  If (iwrkf >= nval) Then
364  If (jinda >= nval) Exit
365  iwrkf = nval
366  End If
367  iinda = 1
368  iindb = jinda + 1
369 !
370 ! Shortcut for the case when the max of A is smaller
371 ! than the min of B. This line may be activated when the
372 ! initial set is already close to sorted.
373 !
374 ! IF (XDONT(IRNGT(JINDA)) <= XDONT(IRNGT(IINDB))) CYCLE
375 !
376 ! One steps in the C subset, that we build in the final rank array
377 !
378 ! Make a copy of the rank array for the merge iteration
379 !
380  jwrkt(1:lmtna) = irngt(iwrkd:jinda)
381 !
382  xvala = xdont(jwrkt(iinda))
383  xvalb = xdont(irngt(iindb))
384 !
385  Do
386  iwrk = iwrk + 1
387 !
388 ! We still have unprocessed values in both A and B
389 !
390  If (xvala > xvalb) Then
391  irngt(iwrk) = irngt(iindb)
392  iindb = iindb + 1
393  If (iindb > iwrkf) Then
394 ! Only A still with unprocessed values
395  irngt(iwrk+1:iwrkf) = jwrkt(iinda:lmtna)
396  Exit
397  End If
398  xvalb = xdont(irngt(iindb))
399  Else
400  irngt(iwrk) = jwrkt(iinda)
401  iinda = iinda + 1
402  If (iinda > lmtna) exit! Only B still with unprocessed values
403  xvala = xdont(jwrkt(iinda))
404  End If
405 !
406  End Do
407  End Do
408 !
409 ! The Cs become As and Bs
410 !
411  lmtna = 2 * lmtna
412  End Do
413 !
414  Return
415 !
416 End Subroutine r_mrgrnk
417 Subroutine i_mrgrnk (XDONT, IRNGT)
418 ! __________________________________________________________
419 ! MRGRNK = Merge-sort ranking of an array
420 ! For performance reasons, the first 2 passes are taken
421 ! out of the standard loop, and use dedicated coding.
422 ! __________________________________________________________
423 ! __________________________________________________________
424  Integer, Dimension (:), Intent (In) :: xdont
425  Integer, Dimension (:), Intent (Out) :: irngt
426 ! __________________________________________________________
427  Integer :: xvala, xvalb
428 !
429  Integer, Dimension (SIZE(IRNGT)) :: jwrkt
430  Integer :: lmtna, lmtnc, irng1, irng2
431  Integer :: nval, iind, iwrkd, iwrk, iwrkf, jinda, iinda, iindb
432 !
433  nval = min(SIZE(xdont), SIZE(irngt))
434  Select Case (nval)
435  Case (:0)
436  Return
437  Case (1)
438  irngt(1) = 1
439  Return
440  Case default
441  Continue
442  End Select
443 !
444 ! Fill-in the index array, creating ordered couples
445 !
446  Do iind = 2, nval, 2
447  If (xdont(iind-1) <= xdont(iind)) Then
448  irngt(iind-1) = iind - 1
449  irngt(iind) = iind
450  Else
451  irngt(iind-1) = iind
452  irngt(iind) = iind - 1
453  End If
454  End Do
455  If (modulo(nval, 2) /= 0) Then
456  irngt(nval) = nval
457  End If
458 !
459 ! We will now have ordered subsets A - B - A - B - ...
460 ! and merge A and B couples into C - C - ...
461 !
462  lmtna = 2
463  lmtnc = 4
464 !
465 ! First iteration. The length of the ordered subsets goes from 2 to 4
466 !
467  Do
468  If (nval <= 2) Exit
469 !
470 ! Loop on merges of A and B into C
471 !
472  Do iwrkd = 0, nval - 1, 4
473  If ((iwrkd+4) > nval) Then
474  If ((iwrkd+2) >= nval) Exit
475 !
476 ! 1 2 3
477 !
478  If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3))) Exit
479 !
480 ! 1 3 2
481 !
482  If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3))) Then
483  irng2 = irngt(iwrkd+2)
484  irngt(iwrkd+2) = irngt(iwrkd+3)
485  irngt(iwrkd+3) = irng2
486 !
487 ! 3 1 2
488 !
489  Else
490  irng1 = irngt(iwrkd+1)
491  irngt(iwrkd+1) = irngt(iwrkd+3)
492  irngt(iwrkd+3) = irngt(iwrkd+2)
493  irngt(iwrkd+2) = irng1
494  End If
495  Exit
496  End If
497 !
498 ! 1 2 3 4
499 !
500  If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3))) cycle
501 !
502 ! 1 3 x x
503 !
504  If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3))) Then
505  irng2 = irngt(iwrkd+2)
506  irngt(iwrkd+2) = irngt(iwrkd+3)
507  If (xdont(irng2) <= xdont(irngt(iwrkd+4))) Then
508 ! 1 3 2 4
509  irngt(iwrkd+3) = irng2
510  Else
511 ! 1 3 4 2
512  irngt(iwrkd+3) = irngt(iwrkd+4)
513  irngt(iwrkd+4) = irng2
514  End If
515 !
516 ! 3 x x x
517 !
518  Else
519  irng1 = irngt(iwrkd+1)
520  irng2 = irngt(iwrkd+2)
521  irngt(iwrkd+1) = irngt(iwrkd+3)
522  If (xdont(irng1) <= xdont(irngt(iwrkd+4))) Then
523  irngt(iwrkd+2) = irng1
524  If (xdont(irng2) <= xdont(irngt(iwrkd+4))) Then
525 ! 3 1 2 4
526  irngt(iwrkd+3) = irng2
527  Else
528 ! 3 1 4 2
529  irngt(iwrkd+3) = irngt(iwrkd+4)
530  irngt(iwrkd+4) = irng2
531  End If
532  Else
533 ! 3 4 1 2
534  irngt(iwrkd+2) = irngt(iwrkd+4)
535  irngt(iwrkd+3) = irng1
536  irngt(iwrkd+4) = irng2
537  End If
538  End If
539  End Do
540 !
541 ! The Cs become As and Bs
542 !
543  lmtna = 4
544  Exit
545  End Do
546 !
547 ! Iteration loop. Each time, the length of the ordered subsets
548 ! is doubled.
549 !
550  Do
551  If (lmtna >= nval) Exit
552  iwrkf = 0
553  lmtnc = 2 * lmtnc
554 !
555 ! Loop on merges of A and B into C
556 !
557  Do
558  iwrk = iwrkf
559  iwrkd = iwrkf + 1
560  jinda = iwrkf + lmtna
561  iwrkf = iwrkf + lmtnc
562  If (iwrkf >= nval) Then
563  If (jinda >= nval) Exit
564  iwrkf = nval
565  End If
566  iinda = 1
567  iindb = jinda + 1
568 !
569 ! Shortcut for the case when the max of A is smaller
570 ! than the min of B. This line may be activated when the
571 ! initial set is already close to sorted.
572 !
573 ! IF (XDONT(IRNGT(JINDA)) <= XDONT(IRNGT(IINDB))) CYCLE
574 !
575 ! One steps in the C subset, that we build in the final rank array
576 !
577 ! Make a copy of the rank array for the merge iteration
578 !
579  jwrkt(1:lmtna) = irngt(iwrkd:jinda)
580 !
581  xvala = xdont(jwrkt(iinda))
582  xvalb = xdont(irngt(iindb))
583 !
584  Do
585  iwrk = iwrk + 1
586 !
587 ! We still have unprocessed values in both A and B
588 !
589  If (xvala > xvalb) Then
590  irngt(iwrk) = irngt(iindb)
591  iindb = iindb + 1
592  If (iindb > iwrkf) Then
593 ! Only A still with unprocessed values
594  irngt(iwrk+1:iwrkf) = jwrkt(iinda:lmtna)
595  Exit
596  End If
597  xvalb = xdont(irngt(iindb))
598  Else
599  irngt(iwrk) = jwrkt(iinda)
600  iinda = iinda + 1
601  If (iinda > lmtna) exit! Only B still with unprocessed values
602  xvala = xdont(jwrkt(iinda))
603  End If
604 !
605  End Do
606  End Do
607 !
608 ! The Cs become As and Bs
609 !
610  lmtna = 2 * lmtna
611  End Do
612 !
613  Return
614 !
615 End Subroutine i_mrgrnk
616 end module m_mrgrnk
subroutine d_mrgrnk(XDONT, IRNGT)
Definition: m_mrgrnk.F90:18
subroutine r_mrgrnk(XDONT, IRNGT)
Definition: m_mrgrnk.F90:218
subroutine i_mrgrnk(XDONT, IRNGT)
Definition: m_mrgrnk.F90:417