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