Afivo 0.3
All Classes Namespaces Functions Variables Pages
m_mrgrnk.f90
1! Author: Michel Olagnon
2! Code downloaded from: http://fortran-2000.com/rank/
3! License: not specified, but public it seems
4module m_mrgrnk
5Integer, Parameter :: kdp = selected_real_kind(15)
6public :: mrgrnk
7private :: kdp
8private :: r_mrgrnk, i_mrgrnk, d_mrgrnk
9interface mrgrnk
10 module procedure d_mrgrnk, r_mrgrnk, i_mrgrnk
11end interface mrgrnk
12contains
13
14Subroutine 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!
212End Subroutine d_mrgrnk
213
214Subroutine 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!
412End Subroutine r_mrgrnk
413Subroutine 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!
611End Subroutine i_mrgrnk
612end module m_mrgrnk