SURFEX v8.1
General documentation of Surfex
ecsort_shared.h
Go to the documentation of this file.
1 !*** ecsort_shared.h ***
2 
3 #if INT_VERSION == 4
4 
5 #define DATA_TYPE INTEGER(KIND=JPIM)
6 #define SIZEOF_ME sizeof_int4
7 #define KEYSORT_1D INT4_KEYSORT_1D
8 #define KEYSORT_1D_DRHOOKSTR 'ECSORT_MIX:INT4_KEYSORT_1D'
9 #define KEYSORT_2D INT4_KEYSORT_2D
10 #define KEYSORT_2D_DRHOOKSTR 'ECSORT_MIX:INT4_KEYSORT_2D'
11 #define KEYSORT_NUMBER 11
12 #define RSORT_DRHOOKSTR 'ECSORT_MIX:RSORT32_FUNC_11'
13 #define USE_RSORT64 0
14 #define HEAPSORT INT4_HEAPSORT
15 #define HEAPSORT_DRHOOKSTR 'ECSORT_MIX:INT4_HEAPSORT'
16 #define DBGPRINT INT4_DBGPRINT
17 #define DBGFMTNUM 1011
18 #define ECQSORT_DRHOOKSTR 'ECSORT_MIX:INT4_ECQSORT'
19 #define COUNT_DRHOOKSTR 'ECSORT_MIX:INT4_COUNT'
20 #define GNOME_DRHOOKSTR 'ECSORT_MIX:INT4_GNOME'
21 
22 #elif REAL_VERSION == 8
23 
24 #define DATA_TYPE REAL(KIND=JPRD)
25 #define SIZEOF_ME sizeof_real8
26 #define KEYSORT_1D REAL8_KEYSORT_1D
27 #define KEYSORT_1D_DRHOOKSTR 'ECSORT_MIX:REAL8_KEYSORT_1D'
28 #define KEYSORT_2D REAL8_KEYSORT_2D
29 #define KEYSORT_2D_DRHOOKSTR 'ECSORT_MIX:REAL8_KEYSORT_2D'
30 #define KEYSORT_NUMBER 12
31 #define RSORT_DRHOOKSTR 'ECSORT_MIX:RSORT64_12'
32 #define USE_RSORT64 1
33 #define HEAPSORT REAL8_HEAPSORT
34 #define HEAPSORT_DRHOOKSTR 'ECSORT_MIX:REAL8_HEAPSORT'
35 #define DBGPRINT REAL8_DBGPRINT
36 #define DBGFMTNUM 1012
37 #define ECQSORT_DRHOOKSTR 'ECSORT_MIX:REAL8_ECQSORT'
38 #define COUNT_DRHOOKSTR 'ECSORT_MIX:REAL8_COUNT'
39 #define GNOME_DRHOOKSTR 'ECSORT_MIX:REAL8_GNOME'
40 
41 #elif REAL_VERSION == 4
42 
43 #define DATA_TYPE REAL(KIND=JPRM)
44 #define SIZEOF_ME sizeof_real4
45 #define KEYSORT_1D REAL4_KEYSORT_1D
46 #define KEYSORT_1D_DRHOOKSTR 'ECSORT_MIX:REAL4_KEYSORT_1D'
47 #define KEYSORT_2D REAL4_KEYSORT_2D
48 #define KEYSORT_2D_DRHOOKSTR 'ECSORT_MIX:REAL4_KEYSORT_2D'
49 #define KEYSORT_NUMBER 13
50 #define RSORT_DRHOOKSTR 'ECSORT_MIX:RSORT32_FUNC_13'
51 #define USE_RSORT64 0
52 #define HEAPSORT REAL4_HEAPSORT
53 #define HEAPSORT_DRHOOKSTR 'ECSORT_MIX:REAL4_HEAPSORT'
54 #define DBGPRINT REAL4_DBGPRINT
55 #define DBGFMTNUM 1013
56 #define ECQSORT_DRHOOKSTR 'ECSORT_MIX:REAL4_ECQSORT'
57 #define COUNT_DRHOOKSTR 'ECSORT_MIX:REAL4_COUNT'
58 #define GNOME_DRHOOKSTR 'ECSORT_MIX:REAL4_GNOME'
59 
60 #elif INT_VERSION == 8
61 
62 #define DATA_TYPE INTEGER(KIND=JPIB)
63 #define SIZEOF_ME sizeof_int8
64 #define KEYSORT_1D INT8_KEYSORT_1D
65 #define KEYSORT_1D_DRHOOKSTR 'ECSORT_MIX:INT8_KEYSORT_1D'
66 #define KEYSORT_2D INT8_KEYSORT_2D
67 #define KEYSORT_2D_DRHOOKSTR 'ECSORT_MIX:INT8_KEYSORT_2D'
68 #define KEYSORT_NUMBER 14
69 #define RSORT_DRHOOKSTR 'ECSORT_MIX:RSORT64_14'
70 #define USE_RSORT64 1
71 #define HEAPSORT INT8_HEAPSORT
72 #define HEAPSORT_DRHOOKSTR 'ECSORT_MIX:INT8_HEAPSORT'
73 #define DBGPRINT INT8_DBGPRINT
74 #define DBGFMTNUM 1014
75 #define ECQSORT_DRHOOKSTR 'ECSORT_MIX:INT8_ECQSORT'
76 #define COUNT_DRHOOKSTR 'ECSORT_MIX:INT8_COUNT'
77 #define GNOME_DRHOOKSTR 'ECSORT_MIX:INT8_GNOME'
78 
79 #else
80 
81  ERROR in programming : No datatype given (should never have ended up here)
82 
83 #endif
84 
85 !----------------------------
86 !-- Public subroutines --
87 !----------------------------
88 
89 
90 SUBROUTINE KEYSORT_1D(rc, a, n, method, descending, index, init)
91 !-- Please note that we assume that a(:) occupies consecutive memory locations
92 INTEGER(KIND=JPIM), intent(out) :: rc
93 DATA_TYPE , intent(inout) :: a(:)
94 INTEGER(KIND=JPIM), intent(in) :: n
95 INTEGER(KIND=JPIM), intent(in), OPTIONAL :: method
96 logical, intent(in), OPTIONAL :: descending
97 INTEGER(KIND=JPIM), intent(inout), TARGET, OPTIONAL :: index(:)
98 logical, intent(in), OPTIONAL :: init
99 ! === END OF INTERFACE BLOCK ===
100 DATA_TYPE , allocatable :: aa(:,:)
101 INTEGER(KIND=JPIM) :: imethod, irev, idummy, index_adj
102 logical :: LLfast, LLdescending, LLomp_okay, LLinit
103 INTEGER(KIND=JPIM) :: ITID, ichunk, iret, inumt
104 REAL(KIND=JPRB) :: ZHOOK_HANDLE
105 
106 IF (LHOOK) CALL DR_HOOK(KEYSORT_1D_DRHOOKSTR,0,ZHOOK_HANDLE)
107 
108 rc = 0
109 if (n <= 0 .or. size(a) <= 0) goto 99
110 
111 if (present(descending)) then
112  LLdescending = descending
113 else
114  LLdescending = .FALSE.
115 endif
116 
117 irev = 0
118 if (LLdescending) irev = 1
119 
120 ITID = OML_MY_THREAD()
121 imethod = current_method(ITID)
122 if (present(method)) then
123  imethod = min(max(min_method,method),max_method)
124 endif
125 
126 if (imethod /= quicksort_method .and. &
127  &imethod /= countingsort_method) then
128  LLfast = .FALSE.
129 else if (imethod == quicksort_method) then
130  !-- hasn't been implemented if index is present ;-(
131  LLfast = (&
132  & .not.present(index) .and. &
133  & .not.present(init))
134 else if (imethod == countingsort_method) then
135  !-- index-presence is ok
136  LLfast = .TRUE.
137 endif
138 
139 if (LLfast) then
140  !- Only Quick-sort & CountingSort covered
141 
142  if (imethod == quicksort_method) then
143  inumt = OML_MAX_THREADS()
144  LLomp_okay = (inumt > 1 .and. nomp >= inumt .and. n >= nomp)
145  LLomp_okay = (LLomp_okay .and. .not. OML_IN_PARALLEL()) ! Prevents nested OpenMP
146  if (LLomp_okay) then
147  !-- Max 2-way OpenMP parallelism for now ...
148  ichunk = n/2
149 !$OMP PARALLEL PRIVATE(iret)
150 !$OMP SECTIONS
151 !$OMP SECTION
152  CALL ecqsortfast(KEYSORT_NUMBER, ichunk, a(1), irev, iret)
153 !$OMP SECTION
154  CALL ecqsortfast(KEYSORT_NUMBER, n-ichunk, a(ichunk+1), irev, iret)
155 !$OMP END SECTIONS
156 !$OMP END PARALLEL
157  CALL ecmerge2(KEYSORT_NUMBER, 1, ichunk, n-ichunk, a(1), &
158  & idummy, 0, 1, irev, idummy, rc)
159  else
160  CALL ecqsortfast(KEYSORT_NUMBER, n, a(1), irev, rc)
161  endif
162  GOTO 99
163 
164  else if (imethod == countingsort_method) then
165  if (.not.present(index)) then
166  CALL ec_countingsort(KEYSORT_NUMBER, n, 1, 1, a(1), idummy, 0, 1, irev, rc)
167  else
168  LLinit = .FALSE.
169  if (present(init)) LLinit = init
170  if (LLinit) then
171  CALL init_index(index, index_adj=-1)
172  index_adj = 0
173  else
174  index_adj = 1
175  endif
176  CALL ec_countingsort(KEYSORT_NUMBER, n, 1, 1, a(1), index(1), size(index), index_adj, irev, rc)
177  if (index_adj == 0) CALL adjust_index(index, +1)
178  endif
179  GOTO 99
180 
181  else
182  LLfast = .false.
183  endif
184 endif
185 
186 !-- LLfast == .FALSE. :
187 
188 allocate(aa(n,1))
189 
190 if (LLdescending) then
191  aa(1:n,1) = -a(1:n)
192 else
193  aa(1:n,1) = a(1:n)
194 endif
195 
196 CALL keysort(rc, aa, n, method=method, index=index, init=init)
197 
198 if (LLdescending) then
199  a(1:n) = -aa(1:n,1)
200 else
201  a(1:n) = aa(1:n,1)
202 endif
203 
204 deallocate(aa)
205 
206 99 continue
207 IF (LHOOK) CALL DR_HOOK(KEYSORT_1D_DRHOOKSTR,1,ZHOOK_HANDLE,n)
208 END SUBROUTINE
209 
210 
211 SUBROUTINE KEYSORT_2D(&
212  &rc, a, n,&
213  &key, multikey, method,&
214  &index, init, transposed)
215 
216 INTEGER(KIND=JPIM), intent(out) :: rc
217 DATA_TYPE , intent(inout) :: a(:,:)
218 INTEGER(KIND=JPIM), intent(in) :: n
219 INTEGER(KIND=JPIM), intent(in), OPTIONAL :: key, method
220 INTEGER(KIND=JPIM), intent(in), OPTIONAL :: multikey(:)
221 logical, intent(in), OPTIONAL :: transposed
222 INTEGER(KIND=JPIM), intent(inout), TARGET, OPTIONAL :: index(:)
223 logical, intent(in), OPTIONAL :: init
224 ! === END OF INTERFACE BLOCK ===
225 INTEGER(KIND=JPIM), POINTER :: iindex(:)
226 INTEGER(KIND=JPIM) :: ikey, istride, imethod, inumkeys, imethod_1st, imethod_rest
227 INTEGER(KIND=JPIM) :: lda, iptr, i, j, sda, idiff, irev, inumt, jkey, jj, ilastkey
228 INTEGER(KIND=JPIM) :: j1, j2, jmid, inum, imax, iadd, imod, iret, inc, iamax, ibmax
229 DATA_TYPE , allocatable :: data(:)
230 INTEGER(KIND=JPIM), allocatable :: ikeys(:), ista(:), ichunk(:), irank(:)
231 logical LLinit, LLdescending, LLtrans, LLomp_okay, LLadjusted, LLdebug, LLomp_prefix
232 character(len=1) clenv
233 REAL(KIND=JPRB) :: ZHOOK_HANDLE, ZHOOK_SUBHANDLE
234 REAL(KIND=JPRB) :: ZHOOK_SUBHANDLE0
235 REAL(KIND=JPRB) :: ZHOOK_SUBHANDLE1
236 REAL(KIND=JPRB) :: ZHOOK_SUBHANDLE2
237 REAL(KIND=JPRB) :: ZHOOK_SUBHANDLE3
238 INTEGER(KIND=JPIM) :: ITID
239 
240 IF (LHOOK) CALL DR_HOOK(KEYSORT_2D_DRHOOKSTR,0,ZHOOK_HANDLE)
241 
242 rc = 0
243 lda = size(a, dim=1)
244 sda = size(a, dim=2)
245 if (n <= 0 .or. lda <= 0 .or. sda <= 0) goto 99
246 
247 inumt = OML_MAX_THREADS()
248 ITID = OML_MY_THREAD()
249 imethod = current_method(ITID)
250 if (present(method)) then
251  imethod = min(max(min_method,method),max_method)
252 endif
253 imethod_1st = imethod
254 imethod_rest = imethod
255 
256 ikey = 1
257 if (present(key)) ikey = key
258 
259 if (present(multikey)) then
260  allocate(ikeys(size(multikey)))
261  ikeys(:) = multikey(:)
262 else
263  allocate(ikeys(1))
264  ikeys(1) = ikey
265 endif
266 inumkeys = size(ikeys)
267 
268 !-- Only the RADIX-sort & now also QUICK-sort & CountingSort give the result we want with multiple keys
269 if (inumkeys > 1 .and. &
270  imethod /= radixsort_method .and. &
271  imethod /= quicksort_method .and. &
272  imethod /= countingsort_method) then
273  imethod = default_method
274  imethod_1st = imethod
275  imethod_rest = imethod
276  !-- Since "default_method" may now be [overridden as] HEAP-sort, make sure its then "radixsort_method"
277  ! Note: The first sweep may still be e.g. HEAP-sort
278  if (imethod /= radixsort_method .and. &
279  imethod /= quicksort_method .and. &
280  imethod /= countingsort_method) then
281  imethod = radixsort_method
282  imethod_rest = imethod
283  endif
284 endif
285 
286 LLinit = .FALSE.
287 if (present(init)) LLinit = init
288 
289 if (present(index)) then
290  iindex => index(1:n)
291 else
292  allocate(iindex(n))
293  LLinit = .TRUE.
294 endif
295 
296 if (LLinit) CALL init_index(iindex)
297 
298 istride = 1
299 LLtrans = .FALSE.
300 if (present(transposed)) LLtrans = transposed
301 if (LLtrans) then
302  istride = lda
303 else if (sda >= 2 .and. lda >= 1) then
304 !-- Check for presence of sub-array and adjust lda automatically
305  call addrdiff(a(1,1),a(1,2),idiff)
306  ! lda below: The true leading dimension; overrides sub-arrays one
307  lda = idiff/SIZEOF_ME
308 endif
309 
310 ilastkey = 0
311 LLadjusted = .FALSE.
312 LLomp_prefix = .FALSE.
313 !$ LLomp_prefix = (istride == 1 .and. nomp >= inumt .and. n >= nomp)
314 if (LLomp_prefix) then
315  call get_environment_variable('EC_SORTING_DEBUG',clenv)
316  LLdebug = (clenv == '1' .and. n < 10000)
317  if (LLdebug) write(0,*)'>> EC_SORTING_DEBUG=1'
318 else
319  LLdebug = .FALSE.
320 endif
321 
322 1000 format(1x,a,2i12,:,/,(10i5))
323 1001 format(1x,'[#',i2,']:',a,(10i5))
324 1002 format(1x,'[#',i2,']:',a,:,/,(10i5))
325 1003 format(1x,'[#',i2,']:',a,2i12,:,/,(10i5))
326 1004 format(1x,a,:,(10i5))
327 1005 format(1x,a,i2,1x,a)
328 
329 imethod = imethod_1st
330 KEYLOOP: do jkey=inumkeys,1,-1
331 !-- Sort by the least significant key first
332  ikey = abs(ikeys(jkey))
333  if (ikey == 0) cycle KEYLOOP
334 
335  if (istride == 1) then
336  iptr = lda * (ikey - 1) + 1
337  else
338  iptr = ikey
339  endif
340 
341  if (LLdebug) then
342  write(0,1000) '<BEGIN>iindex(1:n)=',n,sum(iindex(1:n)),iindex(1:n)
343  if (LLadjusted) then
344  CALL DBGPRINT(-jkey,'<BEGIN>',a,iindex,n,ikey,1,n,1)
345  else
346  CALL DBGPRINT(-jkey,'<BEGIN>',a,iindex,n,ikey,1,n,0)
347  endif
348  ilastkey = ikey
349  endif
350 
351  LLdescending = (ikeys(jkey) < 0)
352  irev = 0
353  if (LLdescending) irev = 1
354 
355  !-- Since "irev" is passed into the ecqsort, no explicit reversing is needed --> savings
356  if (imethod == quicksort_method .or. &
357  imethod == countingsort_method) LLdescending = .FALSE.
358 
359  if (LLdescending) then
360  if (istride == 1) then
361  a(1:n,ikey) = -a(1:n,ikey)
362  else
363  a(ikey,1:n) = -a(ikey,1:n)
364  endif
365  irev = 0 ! prevents use of "reverse" algorithm in ecmerge2 for radix-sort
366  endif
367 
368  LLomp_okay = LLomp_prefix .and. (inumt > 1) .and. (&
369  & imethod == radixsort_method .or. &
370  & imethod == quicksort_method .or. &
371  & imethod == countingsort_method)
372  LLomp_okay = LLomp_okay .and. (.not. OML_IN_PARALLEL()) ! Prevents nested OpenMP
373 
374  if (.not.LLomp_okay) then
375  select case (imethod)
376  case (radixsort_method)
377  IF (LHOOK) CALL DR_HOOK(RSORT_DRHOOKSTR,0,ZHOOK_SUBHANDLE0)
378 #if USE_RSORT64 == 1
379  CALL rsort64(KEYSORT_NUMBER, n, istride, iptr, a(1,1), iindex(1), 1, rc)
380 #else
381  CALL rsort32_func(KEYSORT_NUMBER, n, istride, iptr, a(1,1), iindex(1), 1, rc)
382 #endif
383  IF (LHOOK) CALL DR_HOOK(RSORT_DRHOOKSTR,1,ZHOOK_SUBHANDLE0, n)
384  case (heapsort_method)
385  if (istride == 1) then
386  CALL HEAPSORT(KEYSORT_NUMBER, n, a(1:n, ikey), rc, irev, istride, iindex)
387  else
388  CALL HEAPSORT(KEYSORT_NUMBER, n, a(ikey, 1:n), rc, irev, istride, iindex)
389  endif
390  case (quicksort_method)
391  IF (LHOOK) CALL DR_HOOK(ECQSORT_DRHOOKSTR,0,ZHOOK_SUBHANDLE0)
392  CALL ecqsort(KEYSORT_NUMBER, n, istride, iptr, a(1,1), iindex(1), 1, irev, rc)
393  IF (LHOOK) CALL DR_HOOK(ECQSORT_DRHOOKSTR,1,ZHOOK_SUBHANDLE0,n)
394  case (countingsort_method)
395  IF (LHOOK) CALL DR_HOOK(COUNT_DRHOOKSTR,0,ZHOOK_SUBHANDLE0)
396  CALL ec_countingsort(KEYSORT_NUMBER, n, istride, iptr, a(1,1), iindex(1), n, 1, irev, rc)
397  IF (LHOOK) CALL DR_HOOK(COUNT_DRHOOKSTR,1,ZHOOK_SUBHANDLE0,n)
398  case (gnomesort_method)
399  IF (LHOOK) CALL DR_HOOK(GNOME_DRHOOKSTR,0,ZHOOK_SUBHANDLE0)
400  CALL ecgnomesort(KEYSORT_NUMBER, n, istride, iptr, a(1,1), iindex(1), n, 1, rc)
401  IF (LHOOK) CALL DR_HOOK(GNOME_DRHOOKSTR,1,ZHOOK_SUBHANDLE0,n)
402  end select
403 
404  else ! i.e. LLomp_okay ; radix, quick & counting -sorts only
405  if (.not.allocated(ista)) then
406  allocate(ista(inumt+1),ichunk(inumt))
407  inc = n/inumt
408  iadd = 1
409  imod = mod(n,inumt)
410  if (imod == 0) iadd = 0
411  ista(1) = 1
412  do j=2,inumt
413  ista(j) = ista(j-1) + inc + iadd
414  if (iadd > 0 .and. j > imod) iadd = 0
415  enddo
416  ista(inumt+1) = n + 1
417  do j=1,inumt
418  ichunk(j) = ista(j+1) - ista(j)
419  enddo
420  if (LLdebug) then
421  write(0,1005) '>> imethod,name=',imethod,method_name(imethod)
422  write(0,1004) '>> inumt,n,nomp=',inumt,n,nomp
423  write(0,1004) '>> ista(1:inumt+1)=',ista(1:inumt+1)
424  write(0,1004) '>> ichunk(1:inumt)=',ichunk(1:inumt)
425  endif
426  allocate(irank(n))
427  endif
428 
429  if (LLdebug) write(0,1004) '>>KEYLOOP: jkey,ikey,irev,iptr=',jkey,ikey,irev,iptr
430 
431  if (.not.LLadjusted) then ! only once
432  if (LLdebug) write(0,1000) '<1>iindex(1:n)=',n,sum(iindex(1:n)),iindex(1:n)
433  call adjust_index(iindex, -1) ! Fortran -> C
434  if (LLdebug) write(0,1000) '<2>iindex(1:n)=',n,sum(iindex(1:n))+n,iindex(1:n)
435  LLadjusted = .TRUE.
436  endif
437 
438  if (LLdebug) write(0,*)'>> Sorting inumt-chunks in parallel'
439 !$OMP PARALLEL PRIVATE(j,j1,j2,inum,iret,inc,ITID,ZHOOK_SUBHANDLE1,ZHOOK_SUBHANDLE2)
440  IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:KEYSORT_2D>OMPSORT',0,ZHOOK_SUBHANDLE1)
441  ITID = OML_MY_THREAD()
442 !$OMP DO SCHEDULE(DYNAMIC,1)
443  do j=1,inumt
444  j1 = ista(j)
445  inum = ichunk(j)
446  j2 = j1 + inum - 1
447  inc = j1
448  if (LLdebug) write(0,1001) ITID,'j,j1,j2,inum,inc=',j,j1,j2,inum,inc
449  if (LLdebug) write(0,1002) ITID,'iindex(j1:j2) > ',iindex(j1:j2)
450  select case (imethod)
451  case (radixsort_method)
452  IF (LHOOK) CALL DR_HOOK(RSORT_DRHOOKSTR,0,ZHOOK_SUBHANDLE2)
453 #if USE_RSORT64 == 1
454  CALL rsort64(KEYSORT_NUMBER, inum, istride, iptr, a(1,1), iindex(j1), 0, iret)
455 #else
456  CALL rsort32_func(KEYSORT_NUMBER, inum, istride, iptr, a(1,1), iindex(j1), 0, iret)
457 #endif
458  IF (LHOOK) CALL DR_HOOK(RSORT_DRHOOKSTR,1,ZHOOK_SUBHANDLE2, inum)
459  case (quicksort_method)
460  IF (LHOOK) CALL DR_HOOK(ECQSORT_DRHOOKSTR,0,ZHOOK_SUBHANDLE2)
461  CALL ecqsort(KEYSORT_NUMBER, inum, istride, iptr, a(1,1), iindex(j1), 0, irev, iret)
462  IF (LHOOK) CALL DR_HOOK(ECQSORT_DRHOOKSTR,1,ZHOOK_SUBHANDLE2,inum)
463  case (countingsort_method)
464  IF (LHOOK) CALL DR_HOOK(COUNT_DRHOOKSTR,0,ZHOOK_SUBHANDLE2)
465  CALL ec_countingsort(KEYSORT_NUMBER, inum, istride, iptr, a(1,1), iindex(j1), inum, 0, irev, iret)
466  IF (LHOOK) CALL DR_HOOK(COUNT_DRHOOKSTR,1,ZHOOK_SUBHANDLE2,inum)
467  end select
468  if (LLdebug) write(0,1002) ITID,'iindex(j1:j2) < ',iindex(j1:j2)
469  enddo
470 !$OMP END DO
471  IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:KEYSORT_2D>OMPSORT',1,ZHOOK_SUBHANDLE1)
472 !$OMP END PARALLEL
473 
474  if (LLdebug) write(0,1000) '<after_sort>iindex(1:n)=',n,sum(iindex(1:n))+n,iindex(1:n)
475  if (LLdebug) CALL DBGPRINT(0,'<after_sort>',a,iindex,n,ikey,1,n,1)
476  CALL get_rank(iindex, irank, index_adj=+1)
477 
478  if (LLdebug) write(0,*) '>> Merge neighbouring chunks in parallel as much as possible'
479  inc = 2
480  imax = (inumt+inc-1)/inc
481  do jj=1,imax
482  if (LLdebug) write(0,1001) jj,'<before_merge> jj,inc,imax,inumt=',jj,inc,imax,inumt
483 !$OMP PARALLEL PRIVATE(j,j1,j2,inum,iamax,ibmax,jmid,iret,ZHOOK_SUBHANDLE3,ITID)
484  IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:KEYSORT_2D>OMPMERGE',0,ZHOOK_SUBHANDLE3)
485  ITID = OML_MY_THREAD()
486 !$OMP DO SCHEDULE(DYNAMIC,1)
487  do j=1,inumt,inc
488  j1 = j
489  j2 = j + inc - 1
490  jmid = (j1 + j2)/2 + 1
491  j2 = min(j2,inumt)
492  jmid = min(jmid,inumt)
493  if (LLdebug) write(0,1001) ITID,'j,j1,j2,jmid=',j,j1,j2,jmid
494  iamax = ista(jmid) - ista(j1)
495  inum = sum(ichunk(j1:j2))
496  ibmax = inum - iamax
497  if (LLdebug) write(0,1001) ITID,'j,iamax,ibmax,inum=',j,iamax,ibmax,inum
498  if (iamax == 0 .or. ibmax == 0 .or. inum == 0) cycle
499  j1 = ista(j1)
500  j2 = ista(j2+1) - 1
501  if (LLdebug) write(0,1001) ITID,'j,j1,j2,inum=',j,j1,j2,inum
502  if (LLdebug) write(0,1002) ITID,'iindex(j1:j2) > ',iindex(j1:j2)
503  call ecmerge2(KEYSORT_NUMBER, iptr, iamax, ibmax, a(1,1), &
504  & iindex(j1), inum, 0, irev, irank(1), iret)
505  if (LLdebug) write(0,1002) ITID,'iindex(j1:j2) < ',iindex(j1:j2)
506  enddo ! do j=1,inumt,inc
507 !$OMP END DO
508  IF (LHOOK) CALL DR_HOOK('ECSORT_MIX:KEYSORT_2D>OMPMERGE',1,ZHOOK_SUBHANDLE3)
509 !$OMP END PARALLEL
510 
511  if (LLdebug) write(0,1003) jj,'<after_merge>iindex(1:n)=',n,sum(iindex(1:n))+n,iindex(1:n)
512  if (LLdebug) CALL DBGPRINT(jj,'<after_merge>',a,iindex,n,ikey,1,n,1)
513 
514  inc = inc * 2
515  enddo ! do jj=1,imax
516  rc = n
517  endif ! if (LLomp_okay)
518 
519  if (LLdescending) then
520  if (istride == 1) then
521  a(1:n,ikey) = -a(1:n,ikey)
522  else
523  a(ikey,1:n) = -a(ikey,1:n)
524  endif
525  endif
526 
527  if (LLadjusted .and. imethod /= imethod_rest) then ! Restore back immediately
528  if (LLdebug) write(0,1000) '<3a>iindex(1:n)=',n,sum(iindex(1:n))+n,iindex(1:n)
529  call adjust_index(iindex, +1) ! C -> Fortran
530  if (LLdebug) write(0,1000) '<4a>iindex(1:n)=',n,sum(iindex(1:n)),iindex(1:n)
531  LLadjusted = .FALSE.
532  endif
533 
534  imethod = imethod_rest
535 enddo KEYLOOP
536 
537 deallocate(ikeys)
538 if (allocated(ista)) deallocate(ista)
539 if (allocated(ichunk)) deallocate(ichunk)
540 if (allocated(irank)) deallocate(irank)
541 
542 if (LLadjusted) then ! Restore back
543  if (LLdebug) write(0,1000) '<3b>iindex(1:n)=',n,sum(iindex(1:n))+n,iindex(1:n)
544  call adjust_index(iindex, +1) ! C -> Fortran
545  if (LLdebug) write(0,1000) '<4b>iindex(1:n)=',n,sum(iindex(1:n)),iindex(1:n)
546  LLadjusted = .FALSE.
547 endif
548 
549 if (LLdebug) write(0,1000) '<END>iindex(1:n)=',n,sum(iindex(1:n)),iindex(1:n)
550 if (LLdebug) CALL DBGPRINT(0,'<END>',a,iindex,n,ilastkey,1,n,0)
551 
552 if (.not.present(index)) then
553  LLomp_okay = (nomp >= inumt .and. n >= nomp)
554  if (istride == 1) then
555  LLomp_okay = (LLomp_okay .and. sda >= inumt .and. .not. OML_IN_PARALLEL()) ! Prevents nested OpenMP
556 !$OMP PARALLEL PRIVATE(j,data) IF (LLomp_okay)
557  allocate(data(n))
558 !$OMP DO SCHEDULE(DYNAMIC,1)
559  do j=1,sda
560  data(1:n) = a(iindex(1:n),j)
561  a(1:n,j) = data(1:n)
562  enddo
563 !$OMP END DO
564  deallocate(data)
565 !$OMP END PARALLEL
566  else
567  LLomp_okay = (LLomp_okay .and. lda >= inumt .and. .not. OML_IN_PARALLEL()) ! Prevents nested OpenMP
568 !$OMP PARALLEL PRIVATE(i,data) IF (LLomp_okay)
569  allocate(data(n))
570 !$OMP DO SCHEDULE(DYNAMIC,1)
571  do i=1,lda
572  data(1:n) = a(i,iindex(1:n))
573  a(i,1:n) = data(1:n)
574  enddo
575 !$OMP END DO
576  deallocate(data)
577 !$OMP END PARALLEL
578  endif
579 
580  deallocate(iindex)
581 endif
582 
583 99 continue
584 IF (LHOOK) CALL DR_HOOK(KEYSORT_2D_DRHOOKSTR,1,ZHOOK_HANDLE,n*inumkeys)
585 END SUBROUTINE
586 
587 !-----------------------------
588 !-- Private subroutines --
589 !-----------------------------
590 
591 SUBROUTINE DBGPRINT(jj, cdstr, a, index, n, key, k1, k2, kadd)
592 character(len=*), intent(in) :: cdstr
593 INTEGER(KIND=JPIM), intent(in) :: jj, n, key, k1, k2, kadd
594 INTEGER(KIND=JPIM), intent(in) :: index(:)
595 DATA_TYPE, intent(in) :: a(:,:)
596 INTEGER(KIND=JPIM) :: i,j
597 1000 FORMAT(i3,a,5i5)
598 1011 FORMAT((5i12)) ! integer*4
599 1012 FORMAT(1p,(5g20.12)) ! real*8
600 1013 FORMAT(1p,(5g20.12)) ! real*4
601 1014 FORMAT((5i12)) ! integer*8
602 WRITE(0,1000) jj,cdstr//': n,key,k1,k2,kadd,a(index(k1:k2)+kadd,:)=',&
603  & n,key,k1,k2,kadd
604 do j=k1,k2
605  i = index(j)+kadd
606  WRITE(0,'(2i6)',advance='no') j,i-kadd
607  WRITE(0,DBGFMTNUM) a(i,:)
608 enddo
609 END SUBROUTINE
610 
611 SUBROUTINE HEAPSORT(id, n, a, rc, irev, istride, index)
612 INTEGER(KIND=JPIM), intent(in) :: id, n, irev, istride
613 DATA_TYPE, intent(in) :: a(:)
614 INTEGER(KIND=JPIM), intent(out) :: rc
615 INTEGER(KIND=JPIM), intent(inout) :: index(:)
616 INTEGER(KIND=JPIM) :: i,j,right,left,idx
617 DATA_TYPE :: tmp
618 REAL(KIND=JPRB) :: ZHOOK_HANDLE
619 IF (LHOOK) CALL DR_HOOK(HEAPSORT_DRHOOKSTR,0,ZHOOK_HANDLE)
620 rc = 0
621 if (n <= 0 .or. size(a) <= 0) goto 99
622 left = n/2+1
623 right = n
624 LOOP: do
625  if (left > 1) then
626  left = left - 1
627  idx = index(left)
628  else
629  idx = index(right)
630  index(right) = index(1)
631  right = right - 1
632  if (right == 1) then
633  index(1) = idx
634  exit LOOP
635  endif
636  endif
637  tmp = a(idx)
638  i = left
639  j = 2*left
640  do while (j <= right)
641  if (j < right) then
642  if (a(index(j)) < a(index(j+1))) j = j + 1
643  endif
644  if (tmp < a(index(j))) then
645  index(i) = index(j)
646  i = j
647  j = 2*j
648  else
649  j = right + 1
650  endif
651  enddo
652  index(i) = idx
653 enddo LOOP
654 rc = n
655 99 continue
656 IF (LHOOK) CALL DR_HOOK(HEAPSORT_DRHOOKSTR,1,ZHOOK_HANDLE)
657 END SUBROUTINE
658 
659 
660 
661 #ifndef NO_UNDEF
662 
663 #undef DATA_TYPE
664 #undef SIZEOF_ME
665 #undef KEYSORT_1D
666 #undef KEYSORT_1D_DRHOOKSTR
667 #undef KEYSORT_2D
668 #undef KEYSORT_2D_DRHOOKSTR
669 #undef KEYSORT_NUMBER
670 #undef RSORT_DRHOOKSTR
671 #undef USE_RSORT64
672 #undef QSORTFAST_DRHOOKSTR
673 #undef HEAPSORT
674 #undef HEAPSORT_DRHOOKSTR
675 #undef DBGPRINT
676 #undef DBGFMTNUM
677 #undef ECQSORT_DRHOOKSTR
678 #undef COUNT_DRHOOKSTR
679 #undef GNOME_DRHOOKSTR
680 
681 #endif
ERROR in descending
Definition: ecsort_shared.h:90
static long size
Definition: bytes_io.c:262
intent(out) overrides sub arrays one lda
integer(kind=jpim), parameter quicksort_method
Definition: ecsort_mix.F90:57
intent(out) overrides sub arrays one Sort by the least significant key first< BEGIN > else CALL no reversing is needed savings if(imethod==quicksort_method .or. &imethod==countingsort_method) LLdescending
ERROR in a
Definition: ecsort_shared.h:90
integer(kind=jpim), parameter gnomesort_method
Definition: ecsort_mix.F90:59
subroutine, public init_index(INDEX, INDEX_ADJ)
Definition: ecsort_mix.F90:253
intent(out) overrides sub arrays one Sort by the least significant key first< BEGIN > else CALL DBGPRINT(-jkey,'< BEGIN >', a, iindex, n, ikey, 1, n, 0) endif ilastkey
integer(kind=jpim), parameter min_method
Definition: ecsort_mix.F90:52
ERROR in method
Definition: ecsort_shared.h:90
quick &counting sorts only ichunk(inumt)) inc
integer(kind=jpim) iret
Definition: distio_mix.F90:26
quick &counting sorts only inumt inumt imethod
integer4 integer
Definition: privpub.h:351
quick &counting sorts only inumt inumt inumt
subroutine, public adjust_index(INDEX, INDEX_ADJ)
Definition: ecsort_mix.F90:273
intent(out) overrides sub arrays one Sort by the least significant key first ikey
integer, dimension(:,:), allocatable no
Definition: modd_horibl.F90:38
integer(kind=jpim), parameter heapsort_method
Definition: ecsort_mix.F90:56
integer(kind=jpim), parameter max_method
Definition: ecsort_mix.F90:53
LLfast
char character
Definition: lfi_type.h:18
static unsigned char * init
Definition: memory_hook.c:19
intent(out) overrides sub arrays one Sort by the least significant key first< BEGIN > iindex
subroutine, public get_rank(INDEX, RANK, INDEX_ADJ)
Definition: ecsort_mix.F90:289
ERROR in n
Definition: ecsort_shared.h:90
INTERFACE SUBROUTINE JPRB IMPLICIT NONE INTEGER(KIND=JPIM)
intent(out) overrides sub arrays one Sort by the least significant key first sum(iindex(1:n))
integer(kind=jpim), parameter radixsort_method
Definition: ecsort_mix.F90:55
quick &counting sorts only inumt ista(j)
ERROR in programming
Definition: ecsort_shared.h:90
integer(kind=jpim), dimension(nthrds) current_method
Definition: ecsort_mix.F90:76
quick &counting sorts only inumt inumt nomp
!define ISRCHFLTPV_N !define ISRCHFLTPV_N ISRCHFLTPV_NBITER IF(ISRCHFLTPV_ARRAY(1+ISRCHFLTPV_INC *(ISRCHFLTPV_I-1)).LT.ISRCHFLTPV_TARGET) THEN IF(ISRCHFLTPV_ARRAY(1+ISRCHFLTPV_INC *(ISRCHFLTPV_I)).LT.ISRCHFLTPV_TARGET) THEN IF(ISRCHFLTPV_ARRAY(1+ISRCHFLTPV_INC *(ISRCHFLTPV_I+1)).LT.ISRCHFLTPV_TARGET) THEN IF(ISRCHFLTPV_ARRAY(1+ISRCHFLTPV_INC *(ISRCHFLTPV_I+2)).LT.ISRCHFLTPV_TARGET) THEN IF(ISRCHFLTPV_ARRAY(1+ISRCHFLTPV_INC *(ISRCHFLTPV_I+3)).LT.ISRCHFLTPV_TARGET) THEN IF(ISRCHFLTPV_ARRAY(1+ISRCHFLTPV_INC *(ISRCHFLTPV_I+4)).LT.ISRCHFLTPV_TARGET) THEN IF(ISRCHFLTPV_ARRAY(1+ISRCHFLTPV_INC *(ISRCHFLTPV_I+5)).LT.ISRCHFLTPV_TARGET) THEN IF(ISRCHFLTPV_ARRAY(1+ISRCHFLTPV_INC *(ISRCHFLTPV_I+6)).LT.ISRCHFLTPV_TARGET) THEN IF(ISRCHFLTPV_ARRAY(1+ISRCHFLTPV_INC *(ISRCHFLTPV_I+7)).LT.ISRCHFLTPV_TARGET) THEN ISRCHFLTPV_RESULT
quick &counting sorts only inumt inumt method_name(imethod) write(0
integer(kind=jpim) default_method
Definition: ecsort_mix.F90:75
ERROR in index
Definition: ecsort_shared.h:90
int logical
Definition: lfi_type.h:16
INTERFACE SUBROUTINE FACILO_MT PUNDF USE OPTIONAL ::LDUNDF ! OUT REAL(KIND=JPDBLR)
subroutine t(CDPREF, CDSUFF, KCODPA, LDNIVA, PMULTI)
Definition: faicor.F90:567
radix
real8 real
Definition: privpub.h:396
integer(kind=jpim), parameter countingsort_method
Definition: ecsort_mix.F90:58