xref: /petsc/src/sys/utils/sorti.c (revision c7351cbe61fe344c304f4415680d0c6788bf5ca2)
1 
2 /*
3    This file contains routines for sorting integers. Values are sorted in place.
4  */
5 #include <petsc/private/petscimpl.h>                /*I  "petscsys.h"  I*/
6 
7 #define SWAP(a,b,t) {t=a;a=b;b=t;}
8 
9 #define MEDIAN3(v,a,b,c)                        \
10   (v[a]<v[b]                                    \
11    ? (v[b]<v[c]                                 \
12       ? b                                       \
13       : (v[a]<v[c] ? c : a))                    \
14    : (v[c]<v[b]                                 \
15       ? b                                       \
16       : (v[a]<v[c] ? a : c)))
17 
18 #define MEDIAN(v,right) MEDIAN3(v,right/4,right/2,right/4*3)
19 
20 /* -----------------------------------------------------------------------*/
21 
22 #undef __FUNCT__
23 #define __FUNCT__ "PetscSortInt_Private"
24 /*
25    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
26    Assumes 0 origin for v, number of elements = right+1 (right is index of
27    right-most member).
28 */
29 static void PetscSortInt_Private(PetscInt *v,PetscInt right)
30 {
31   PetscInt i,j,pivot,tmp;
32 
33   if (right <= 1) {
34     if (right == 1) {
35       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
36     }
37     return;
38   }
39   i = MEDIAN(v,right);          /* Choose a pivot */
40   SWAP(v[0],v[i],tmp);          /* Move it out of the way */
41   pivot = v[0];
42   for (i=0,j=right+1;; ) {
43     while (++i < j && v[i] <= pivot) ; /* Scan from the left */
44     while (v[--j] > pivot) ;           /* Scan from the right */
45     if (i >= j) break;
46     SWAP(v[i],v[j],tmp);
47   }
48   SWAP(v[0],v[j],tmp);          /* Put pivot back in place. */
49   PetscSortInt_Private(v,j-1);
50   PetscSortInt_Private(v+j+1,right-(j+1));
51 }
52 
53 #undef __FUNCT__
54 #define __FUNCT__ "PetscSortInt"
55 /*@
56    PetscSortInt - Sorts an array of integers in place in increasing order.
57 
58    Not Collective
59 
60    Input Parameters:
61 +  n  - number of values
62 -  i  - array of integers
63 
64    Level: intermediate
65 
66    Concepts: sorting^ints
67 
68 .seealso: PetscSortReal(), PetscSortIntWithPermutation()
69 @*/
70 PetscErrorCode  PetscSortInt(PetscInt n,PetscInt i[])
71 {
72   PetscInt j,k,tmp,ik;
73 
74   PetscFunctionBegin;
75   if (n<8) {
76     for (k=0; k<n; k++) {
77       ik = i[k];
78       for (j=k+1; j<n; j++) {
79         if (ik > i[j]) {
80           SWAP(i[k],i[j],tmp);
81           ik = i[k];
82         }
83       }
84     }
85   } else PetscSortInt_Private(i,n-1);
86   PetscFunctionReturn(0);
87 }
88 
89 #undef __FUNCT__
90 #define __FUNCT__ "PetscSortRemoveDupsInt"
91 /*@
92    PetscSortRemoveDupsInt - Sorts an array of integers in place in increasing order removes all duplicate entries
93 
94    Not Collective
95 
96    Input Parameters:
97 +  n  - number of values
98 -  ii  - array of integers
99 
100    Output Parameter:
101 .  n - number of non-redundant values
102 
103    Level: intermediate
104 
105    Concepts: sorting^ints
106 
107 .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt()
108 @*/
109 PetscErrorCode  PetscSortRemoveDupsInt(PetscInt *n,PetscInt ii[])
110 {
111   PetscErrorCode ierr;
112   PetscInt       i,s = 0,N = *n, b = 0;
113 
114   PetscFunctionBegin;
115   ierr = PetscSortInt(N,ii);CHKERRQ(ierr);
116   for (i=0; i<N-1; i++) {
117     if (ii[b+s+1] != ii[b]) {
118       ii[b+1] = ii[b+s+1]; b++;
119     } else s++;
120   }
121   *n = N - s;
122   PetscFunctionReturn(0);
123 }
124 
125 #undef __FUNCT__
126 #define __FUNCT__ "PetscFindInt"
127 /*@
128   PetscFindInt - Finds integer in a sorted array of integers
129 
130    Not Collective
131 
132    Input Parameters:
133 +  key - the integer to locate
134 .  n   - number of values in the array
135 -  ii  - array of integers
136 
137    Output Parameter:
138 .  loc - the location if found, otherwise -(slot+1) where slot is the place the value would go
139 
140    Level: intermediate
141 
142    Concepts: sorting^ints
143 
144 .seealso: PetscSortInt(), PetscSortIntWithArray(), PetscSortRemoveDupsInt()
145 @*/
146 PetscErrorCode PetscFindInt(PetscInt key, PetscInt n, const PetscInt ii[], PetscInt *loc)
147 {
148   PetscInt lo = 0,hi = n;
149 
150   PetscFunctionBegin;
151   PetscValidPointer(loc,4);
152   if (!n) {*loc = -1; PetscFunctionReturn(0);}
153   PetscValidPointer(ii,3);
154   while (hi - lo > 1) {
155     PetscInt mid = lo + (hi - lo)/2;
156     if (key < ii[mid]) hi = mid;
157     else               lo = mid;
158   }
159   *loc = key == ii[lo] ? lo : -(lo + (key > ii[lo]) + 1);
160   PetscFunctionReturn(0);
161 }
162 
163 
164 /* -----------------------------------------------------------------------*/
165 #define SWAP2(a,b,c,d,t) {t=a;a=b;b=t;t=c;c=d;d=t;}
166 
167 #undef __FUNCT__
168 #define __FUNCT__ "PetscSortIntWithArray_Private"
169 /*
170    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
171    Assumes 0 origin for v, number of elements = right+1 (right is index of
172    right-most member).
173 */
174 static PetscErrorCode PetscSortIntWithArray_Private(PetscInt *v,PetscInt *V,PetscInt right)
175 {
176   PetscErrorCode ierr;
177   PetscInt       i,vl,last,tmp;
178 
179   PetscFunctionBegin;
180   if (right <= 1) {
181     if (right == 1) {
182       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
183     }
184     PetscFunctionReturn(0);
185   }
186   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
187   vl   = v[0];
188   last = 0;
189   for (i=1; i<=right; i++) {
190     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
191   }
192   SWAP2(v[0],v[last],V[0],V[last],tmp);
193   ierr = PetscSortIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
194   ierr = PetscSortIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
195   PetscFunctionReturn(0);
196 }
197 
198 #undef __FUNCT__
199 #define __FUNCT__ "PetscSortIntWithArray"
200 /*@
201    PetscSortIntWithArray - Sorts an array of integers in place in increasing order;
202        changes a second array to match the sorted first array.
203 
204    Not Collective
205 
206    Input Parameters:
207 +  n  - number of values
208 .  i  - array of integers
209 -  I - second array of integers
210 
211    Level: intermediate
212 
213    Concepts: sorting^ints with array
214 
215 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
216 @*/
217 PetscErrorCode  PetscSortIntWithArray(PetscInt n,PetscInt i[],PetscInt Ii[])
218 {
219   PetscErrorCode ierr;
220   PetscInt       j,k,tmp,ik;
221 
222   PetscFunctionBegin;
223   if (n<8) {
224     for (k=0; k<n; k++) {
225       ik = i[k];
226       for (j=k+1; j<n; j++) {
227         if (ik > i[j]) {
228           SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
229           ik = i[k];
230         }
231       }
232     }
233   } else {
234     ierr = PetscSortIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
235   }
236   PetscFunctionReturn(0);
237 }
238 
239 
240 #define SWAP3(a,b,c,d,e,f,t) {t=a;a=b;b=t;t=c;c=d;d=t;t=e;e=f;f=t;}
241 
242 #undef __FUNCT__
243 #define __FUNCT__ "PetscSortIntWithArrayPair_Private"
244 /*
245    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
246    Assumes 0 origin for v, number of elements = right+1 (right is index of
247    right-most member).
248 */
249 static PetscErrorCode PetscSortIntWithArrayPair_Private(PetscInt *L,PetscInt *J, PetscInt *K, PetscInt right)
250 {
251   PetscErrorCode ierr;
252   PetscInt       i,vl,last,tmp;
253 
254   PetscFunctionBegin;
255   if (right <= 1) {
256     if (right == 1) {
257       if (L[0] > L[1]) SWAP3(L[0],L[1],J[0],J[1],K[0],K[1],tmp);
258     }
259     PetscFunctionReturn(0);
260   }
261   SWAP3(L[0],L[right/2],J[0],J[right/2],K[0],K[right/2],tmp);
262   vl   = L[0];
263   last = 0;
264   for (i=1; i<=right; i++) {
265     if (L[i] < vl) {last++; SWAP3(L[last],L[i],J[last],J[i],K[last],K[i],tmp);}
266   }
267   SWAP3(L[0],L[last],J[0],J[last],K[0],K[last],tmp);
268   ierr = PetscSortIntWithArrayPair_Private(L,J,K,last-1);CHKERRQ(ierr);
269   ierr = PetscSortIntWithArrayPair_Private(L+last+1,J+last+1,K+last+1,right-(last+1));CHKERRQ(ierr);
270   PetscFunctionReturn(0);
271 }
272 
273 #undef __FUNCT__
274 #define __FUNCT__ "PetscSortIntWithArrayPair"
275 /*@
276    PetscSortIntWithArrayPair - Sorts an array of integers in place in increasing order;
277        changes a pair of integer arrays to match the sorted first array.
278 
279    Not Collective
280 
281    Input Parameters:
282 +  n  - number of values
283 .  I  - array of integers
284 .  J  - second array of integers (first array of the pair)
285 -  K  - third array of integers  (second array of the pair)
286 
287    Level: intermediate
288 
289    Concepts: sorting^ints with array pair
290 
291 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortIntWithArray()
292 @*/
293 PetscErrorCode  PetscSortIntWithArrayPair(PetscInt n,PetscInt *L,PetscInt *J, PetscInt *K)
294 {
295   PetscErrorCode ierr;
296   PetscInt       j,k,tmp,ik;
297 
298   PetscFunctionBegin;
299   if (n<8) {
300     for (k=0; k<n; k++) {
301       ik = L[k];
302       for (j=k+1; j<n; j++) {
303         if (ik > L[j]) {
304           SWAP3(L[k],L[j],J[k],J[j],K[k],K[j],tmp);
305           ik = L[k];
306         }
307       }
308     }
309   } else {
310     ierr = PetscSortIntWithArrayPair_Private(L,J,K,n-1);CHKERRQ(ierr);
311   }
312   PetscFunctionReturn(0);
313 }
314 
315 #undef __FUNCT__
316 #define __FUNCT__ "PetscSortMPIInt_Private"
317 /*
318    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
319    Assumes 0 origin for v, number of elements = right+1 (right is index of
320    right-most member).
321 */
322 static void PetscSortMPIInt_Private(PetscMPIInt *v,PetscInt right)
323 {
324   PetscInt          i,j;
325   PetscMPIInt       pivot,tmp;
326 
327   if (right <= 1) {
328     if (right == 1) {
329       if (v[0] > v[1]) SWAP(v[0],v[1],tmp);
330     }
331     return;
332   }
333   i = MEDIAN(v,right);          /* Choose a pivot */
334   SWAP(v[0],v[i],tmp);          /* Move it out of the way */
335   pivot = v[0];
336   for (i=0,j=right+1;; ) {
337     while (++i < j && v[i] <= pivot) ; /* Scan from the left */
338     while (v[--j] > pivot) ;           /* Scan from the right */
339     if (i >= j) break;
340     SWAP(v[i],v[j],tmp);
341   }
342   SWAP(v[0],v[j],tmp);          /* Put pivot back in place. */
343   PetscSortMPIInt_Private(v,j-1);
344   PetscSortMPIInt_Private(v+j+1,right-(j+1));
345 }
346 
347 #undef __FUNCT__
348 #define __FUNCT__ "PetscSortMPIInt"
349 /*@
350    PetscSortMPIInt - Sorts an array of MPI integers in place in increasing order.
351 
352    Not Collective
353 
354    Input Parameters:
355 +  n  - number of values
356 -  i  - array of integers
357 
358    Level: intermediate
359 
360    Concepts: sorting^ints
361 
362 .seealso: PetscSortReal(), PetscSortIntWithPermutation()
363 @*/
364 PetscErrorCode  PetscSortMPIInt(PetscInt n,PetscMPIInt i[])
365 {
366   PetscInt    j,k;
367   PetscMPIInt tmp,ik;
368 
369   PetscFunctionBegin;
370   if (n<8) {
371     for (k=0; k<n; k++) {
372       ik = i[k];
373       for (j=k+1; j<n; j++) {
374         if (ik > i[j]) {
375           SWAP(i[k],i[j],tmp);
376           ik = i[k];
377         }
378       }
379     }
380   } else PetscSortMPIInt_Private(i,n-1);
381   PetscFunctionReturn(0);
382 }
383 
384 #undef __FUNCT__
385 #define __FUNCT__ "PetscSortRemoveDupsMPIInt"
386 /*@
387    PetscSortRemoveDupsMPIInt - Sorts an array of MPI integers in place in increasing order removes all duplicate entries
388 
389    Not Collective
390 
391    Input Parameters:
392 +  n  - number of values
393 -  ii  - array of integers
394 
395    Output Parameter:
396 .  n - number of non-redundant values
397 
398    Level: intermediate
399 
400    Concepts: sorting^ints
401 
402 .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt()
403 @*/
404 PetscErrorCode  PetscSortRemoveDupsMPIInt(PetscInt *n,PetscMPIInt ii[])
405 {
406   PetscErrorCode ierr;
407   PetscInt       i,s = 0,N = *n, b = 0;
408 
409   PetscFunctionBegin;
410   ierr = PetscSortMPIInt(N,ii);CHKERRQ(ierr);
411   for (i=0; i<N-1; i++) {
412     if (ii[b+s+1] != ii[b]) {
413       ii[b+1] = ii[b+s+1]; b++;
414     } else s++;
415   }
416   *n = N - s;
417   PetscFunctionReturn(0);
418 }
419 
420 #undef __FUNCT__
421 #define __FUNCT__ "PetscSortMPIIntWithArray_Private"
422 /*
423    A simple version of quicksort; taken from Kernighan and Ritchie, page 87.
424    Assumes 0 origin for v, number of elements = right+1 (right is index of
425    right-most member).
426 */
427 static PetscErrorCode PetscSortMPIIntWithArray_Private(PetscMPIInt *v,PetscMPIInt *V,PetscMPIInt right)
428 {
429   PetscErrorCode ierr;
430   PetscMPIInt    i,vl,last,tmp;
431 
432   PetscFunctionBegin;
433   if (right <= 1) {
434     if (right == 1) {
435       if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp);
436     }
437     PetscFunctionReturn(0);
438   }
439   SWAP2(v[0],v[right/2],V[0],V[right/2],tmp);
440   vl   = v[0];
441   last = 0;
442   for (i=1; i<=right; i++) {
443     if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);}
444   }
445   SWAP2(v[0],v[last],V[0],V[last],tmp);
446   ierr = PetscSortMPIIntWithArray_Private(v,V,last-1);CHKERRQ(ierr);
447   ierr = PetscSortMPIIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
448   PetscFunctionReturn(0);
449 }
450 
451 #undef __FUNCT__
452 #define __FUNCT__ "PetscSortMPIIntWithArray"
453 /*@
454    PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order;
455        changes a second array to match the sorted first array.
456 
457    Not Collective
458 
459    Input Parameters:
460 +  n  - number of values
461 .  i  - array of integers
462 -  I - second array of integers
463 
464    Level: intermediate
465 
466    Concepts: sorting^ints with array
467 
468 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt()
469 @*/
470 PetscErrorCode  PetscSortMPIIntWithArray(PetscMPIInt n,PetscMPIInt i[],PetscMPIInt Ii[])
471 {
472   PetscErrorCode ierr;
473   PetscMPIInt    j,k,tmp,ik;
474 
475   PetscFunctionBegin;
476   if (n<8) {
477     for (k=0; k<n; k++) {
478       ik = i[k];
479       for (j=k+1; j<n; j++) {
480         if (ik > i[j]) {
481           SWAP2(i[k],i[j],Ii[k],Ii[j],tmp);
482           ik = i[k];
483         }
484       }
485     }
486   } else {
487     ierr = PetscSortMPIIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr);
488   }
489   PetscFunctionReturn(0);
490 }
491 
492 /* -----------------------------------------------------------------------*/
493 #define SWAP2IntScalar(a,b,c,d,t,ts) {t=a;a=b;b=t;ts=c;c=d;d=ts;}
494 
495 #undef __FUNCT__
496 #define __FUNCT__ "PetscSortIntWithScalarArray_Private"
497 /*
498    Modified from PetscSortIntWithArray_Private().
499 */
500 static PetscErrorCode PetscSortIntWithScalarArray_Private(PetscInt *v,PetscScalar *V,PetscInt right)
501 {
502   PetscErrorCode ierr;
503   PetscInt       i,vl,last,tmp;
504   PetscScalar    stmp;
505 
506   PetscFunctionBegin;
507   if (right <= 1) {
508     if (right == 1) {
509       if (v[0] > v[1]) SWAP2IntScalar(v[0],v[1],V[0],V[1],tmp,stmp);
510     }
511     PetscFunctionReturn(0);
512   }
513   SWAP2IntScalar(v[0],v[right/2],V[0],V[right/2],tmp,stmp);
514   vl   = v[0];
515   last = 0;
516   for (i=1; i<=right; i++) {
517     if (v[i] < vl) {last++; SWAP2IntScalar(v[last],v[i],V[last],V[i],tmp,stmp);}
518   }
519   SWAP2IntScalar(v[0],v[last],V[0],V[last],tmp,stmp);
520   ierr = PetscSortIntWithScalarArray_Private(v,V,last-1);CHKERRQ(ierr);
521   ierr = PetscSortIntWithScalarArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr);
522   PetscFunctionReturn(0);
523 }
524 
525 #undef __FUNCT__
526 #define __FUNCT__ "PetscSortIntWithScalarArray"
527 /*@
528    PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order;
529        changes a second SCALAR array to match the sorted first INTEGER array.
530 
531    Not Collective
532 
533    Input Parameters:
534 +  n  - number of values
535 .  i  - array of integers
536 -  I - second array of scalars
537 
538    Level: intermediate
539 
540    Concepts: sorting^ints with array
541 
542 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
543 @*/
544 PetscErrorCode  PetscSortIntWithScalarArray(PetscInt n,PetscInt i[],PetscScalar Ii[])
545 {
546   PetscErrorCode ierr;
547   PetscInt       j,k,tmp,ik;
548   PetscScalar    stmp;
549 
550   PetscFunctionBegin;
551   if (n<8) {
552     for (k=0; k<n; k++) {
553       ik = i[k];
554       for (j=k+1; j<n; j++) {
555         if (ik > i[j]) {
556           SWAP2IntScalar(i[k],i[j],Ii[k],Ii[j],tmp,stmp);
557           ik = i[k];
558         }
559       }
560     }
561   } else {
562     ierr = PetscSortIntWithScalarArray_Private(i,Ii,n-1);CHKERRQ(ierr);
563   }
564   PetscFunctionReturn(0);
565 }
566 
567 
568 #define SWAP2IntData(a,b,c,d,t,td,siz)          \
569   do {                                          \
570   PetscErrorCode _ierr;                         \
571   t=a;a=b;b=t;                                  \
572   _ierr = PetscMemcpy(td,c,siz);CHKERRQ(_ierr); \
573   _ierr = PetscMemcpy(c,d,siz);CHKERRQ(_ierr);  \
574   _ierr = PetscMemcpy(d,td,siz);CHKERRQ(_ierr); \
575 } while(0)
576 
577 #undef __FUNCT__
578 #define __FUNCT__ "PetscSortIntWithDataArray_Private"
579 /*
580    Modified from PetscSortIntWithArray_Private().
581 */
582 static PetscErrorCode PetscSortIntWithDataArray_Private(PetscInt *v,char *V,PetscInt right,size_t size,void *work)
583 {
584   PetscErrorCode ierr;
585   PetscInt       i,vl,last,tmp;
586 
587   PetscFunctionBegin;
588   if (right <= 1) {
589     if (right == 1) {
590       if (v[0] > v[1]) SWAP2IntData(v[0],v[1],V,V+size,tmp,work,size);
591     }
592     PetscFunctionReturn(0);
593   }
594   SWAP2IntData(v[0],v[right/2],V,V+size*(right/2),tmp,work,size);
595   vl   = v[0];
596   last = 0;
597   for (i=1; i<=right; i++) {
598     if (v[i] < vl) {last++; SWAP2IntData(v[last],v[i],V+size*last,V+size*i,tmp,work,size);}
599   }
600   SWAP2IntData(v[0],v[last],V,V + size*last,tmp,work,size);
601   ierr = PetscSortIntWithDataArray_Private(v,V,last-1,size,work);CHKERRQ(ierr);
602   ierr = PetscSortIntWithDataArray_Private(v+last+1,V+size*(last+1),right-(last+1),size,work);CHKERRQ(ierr);
603   PetscFunctionReturn(0);
604 }
605 
606 #undef __FUNCT__
607 #define __FUNCT__ "PetscSortIntWithDataArray"
608 /*@
609    PetscSortIntWithDataArray - Sorts an array of integers in place in increasing order;
610        changes a second array to match the sorted first INTEGER array.  Unlike other sort routines, the user must
611        provide workspace (the size of an element in the data array) to use when sorting.
612 
613    Not Collective
614 
615    Input Parameters:
616 +  n  - number of values
617 .  i  - array of integers
618 .  Ii - second array of data
619 .  size - sizeof elements in the data array in bytes
620 -  work - workspace of "size" bytes used when sorting
621 
622    Level: intermediate
623 
624    Concepts: sorting^ints with array
625 
626 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
627 @*/
628 PetscErrorCode  PetscSortIntWithDataArray(PetscInt n,PetscInt i[],void *Ii,size_t size,void *work)
629 {
630   char           *V = (char *) Ii;
631   PetscErrorCode ierr;
632   PetscInt       j,k,tmp,ik;
633 
634   PetscFunctionBegin;
635   if (n<8) {
636     for (k=0; k<n; k++) {
637       ik = i[k];
638       for (j=k+1; j<n; j++) {
639         if (ik > i[j]) {
640           SWAP2IntData(i[k],i[j],V+size*k,V+size*j,tmp,work,size);
641           ik = i[k];
642         }
643       }
644     }
645   } else {
646     ierr = PetscSortIntWithDataArray_Private(i,V,n-1,size,work);CHKERRQ(ierr);
647   }
648   PetscFunctionReturn(0);
649 }
650 
651 
652 #undef __FUNCT__
653 #define __FUNCT__ "PetscMergeIntArray"
654 /*@
655    PetscMergeIntArray -     Merges two SORTED integer arrays, removes duplicate elements.
656 
657    Not Collective
658 
659    Input Parameters:
660 +  an  - number of values in the first array
661 .  aI  - first sorted array of integers
662 .  bn  - number of values in the second array
663 -  bI  - second array of integers
664 
665    Output Parameters:
666 +  n   - number of values in the merged array
667 -  I   - merged sorted array, this is allocated if an array is not provided
668 
669    Level: intermediate
670 
671    Concepts: merging^arrays
672 
673 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
674 @*/
675 PetscErrorCode  PetscMergeIntArray(PetscInt an,const PetscInt *aI, PetscInt bn, const PetscInt *bI,  PetscInt *n, PetscInt **L)
676 {
677   PetscErrorCode ierr;
678   PetscInt       *L_ = *L, ak, bk, k;
679 
680   if (!L_) {
681     ierr = PetscMalloc1(an+bn, L);CHKERRQ(ierr);
682     L_   = *L;
683   }
684   k = ak = bk = 0;
685   while (ak < an && bk < bn) {
686     if (aI[ak] == bI[bk]) {
687       L_[k] = aI[ak];
688       ++ak;
689       ++bk;
690       ++k;
691     } else if (aI[ak] < bI[bk]) {
692       L_[k] = aI[ak];
693       ++ak;
694       ++k;
695     } else {
696       L_[k] = bI[bk];
697       ++bk;
698       ++k;
699     }
700   }
701   if (ak < an) {
702     ierr = PetscMemcpy(L_+k,aI+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
703     k   += (an-ak);
704   }
705   if (bk < bn) {
706     ierr = PetscMemcpy(L_+k,bI+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
707     k   += (bn-bk);
708   }
709   *n = k;
710   PetscFunctionReturn(0);
711 }
712 
713 #undef __FUNCT__
714 #define __FUNCT__ "PetscMergeIntArrayPair"
715 /*@
716    PetscMergeIntArrayPair -     Merges two SORTED integer arrays that share NO common values along with an additional array of integers.
717                                 The additional arrays are the same length as sorted arrays and are merged
718                                 in the order determined by the merging of the sorted pair.
719 
720    Not Collective
721 
722    Input Parameters:
723 +  an  - number of values in the first array
724 .  aI  - first sorted array of integers
725 .  aJ  - first additional array of integers
726 .  bn  - number of values in the second array
727 .  bI  - second array of integers
728 -  bJ  - second additional of integers
729 
730    Output Parameters:
731 +  n   - number of values in the merged array (== an + bn)
732 .  L   - merged sorted array
733 -  J   - merged additional array
734 
735    Level: intermediate
736 
737    Concepts: merging^arrays
738 
739 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
740 @*/
741 PetscErrorCode  PetscMergeIntArrayPair(PetscInt an,const PetscInt *aI, const PetscInt *aJ, PetscInt bn, const PetscInt *bI, const PetscInt *bJ, PetscInt *n, PetscInt **L, PetscInt **J)
742 {
743   PetscErrorCode ierr;
744   PetscInt       n_, *L_ = *L, *J_= *J, ak, bk, k;
745 
746   PetscFunctionBegin;
747   n_ = an + bn;
748   *n = n_;
749   if (!L_) {
750     ierr = PetscMalloc1(n_, L);CHKERRQ(ierr);
751     L_   = *L;
752   }
753   if (!J_) {
754     ierr = PetscMalloc1(n_, &J_);CHKERRQ(ierr);
755     J_   = *J;
756   }
757   k = ak = bk = 0;
758   while (ak < an && bk < bn) {
759     if (aI[ak] <= bI[bk]) {
760       L_[k] = aI[ak];
761       J_[k] = aJ[ak];
762       ++ak;
763       ++k;
764     } else {
765       L_[k] = bI[bk];
766       J_[k] = bJ[bk];
767       ++bk;
768       ++k;
769     }
770   }
771   if (ak < an) {
772     ierr = PetscMemcpy(L_+k,aI+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
773     ierr = PetscMemcpy(J_+k,aJ+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
774     k   += (an-ak);
775   }
776   if (bk < bn) {
777     ierr = PetscMemcpy(L_+k,bI+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
778     ierr = PetscMemcpy(J_+k,bJ+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
779   }
780   PetscFunctionReturn(0);
781 }
782 
783 #undef __FUNCT__
784 #define __FUNCT__ "PetscMergeMPIIntArray"
785 /*@
786    PetscMergeMPIIntArray -     Merges two SORTED integer arrays.
787 
788    Not Collective
789 
790    Input Parameters:
791 +  an  - number of values in the first array
792 .  aI  - first sorted array of integers
793 .  bn  - number of values in the second array
794 -  bI  - second array of integers
795 
796    Output Parameters:
797 +  n   - number of values in the merged array (<= an + bn)
798 -  L   - merged sorted array, allocated if address of NULL pointer is passed
799 
800    Level: intermediate
801 
802    Concepts: merging^arrays
803 
804 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
805 @*/
806 PetscErrorCode PetscMergeMPIIntArray(PetscInt an,const PetscMPIInt aI[],PetscInt bn,const PetscMPIInt bI[],PetscInt *n,PetscMPIInt **L)
807 {
808   PetscErrorCode ierr;
809   PetscInt       ai,bi,k;
810 
811   PetscFunctionBegin;
812   if (!*L) {ierr = PetscMalloc1((an+bn),L);CHKERRQ(ierr);}
813   for (ai=0,bi=0,k=0; ai<an || bi<bn; ) {
814     PetscInt t = -1;
815     for ( ; ai<an && (!bn || aI[ai] <= bI[bi]); ai++) (*L)[k++] = t = aI[ai];
816     for ( ; bi<bn && bI[bi] == t; bi++);
817     for ( ; bi<bn && (!an || bI[bi] <= aI[ai]); bi++) (*L)[k++] = t = bI[bi];
818     for ( ; ai<an && aI[ai] == t; ai++);
819   }
820   *n = k;
821   PetscFunctionReturn(0);
822 }
823 
824 #undef __FUNCT__
825 #define __FUNCT__ "PetscProcessTree"
826 /*@
827    PetscProcessTree - Prepares tree data to be displayed graphically
828 
829    Not Collective
830 
831    Input Parameters:
832 +  n  - number of values
833 .  mask - indicates those entries in the tree, location 0 is always masked
834 -  parentid - indicates the parent of each entry
835 
836    Output Parameters:
837 +  Nlevels - the number of levels
838 .  Level - for each node tells its level
839 .  Levelcnts - the number of nodes on each level
840 .  Idbylevel - a list of ids on each of the levels, first level followed by second etc
841 -  Column - for each id tells its column index
842 
843    Level: intermediate
844 
845 
846 .seealso: PetscSortReal(), PetscSortIntWithPermutation()
847 @*/
848 PetscErrorCode  PetscProcessTree(PetscInt n,const PetscBool mask[],const PetscInt parentid[],PetscInt *Nlevels,PetscInt **Level,PetscInt **Levelcnt,PetscInt **Idbylevel,PetscInt **Column)
849 {
850   PetscInt       i,j,cnt,nmask = 0,nlevels = 0,*level,*levelcnt,levelmax = 0,*workid,*workparentid,tcnt = 0,*idbylevel,*column;
851   PetscErrorCode ierr;
852   PetscBool      done = PETSC_FALSE;
853 
854   PetscFunctionBegin;
855   if (!mask[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mask of 0th location must be set");
856   for (i=0; i<n; i++) {
857     if (mask[i]) continue;
858     if (parentid[i]  == i) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Node labeled as own parent");
859     if (parentid[i] && mask[parentid[i]]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Parent is masked");
860   }
861 
862   for (i=0; i<n; i++) {
863     if (!mask[i]) nmask++;
864   }
865 
866   /* determine the level in the tree of each node */
867   ierr = PetscCalloc1(n,&level);CHKERRQ(ierr);
868 
869   level[0] = 1;
870   while (!done) {
871     done = PETSC_TRUE;
872     for (i=0; i<n; i++) {
873       if (mask[i]) continue;
874       if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1;
875       else if (!level[i]) done = PETSC_FALSE;
876     }
877   }
878   for (i=0; i<n; i++) {
879     level[i]--;
880     nlevels = PetscMax(nlevels,level[i]);
881   }
882 
883   /* count the number of nodes on each level and its max */
884   ierr = PetscCalloc1(nlevels,&levelcnt);CHKERRQ(ierr);
885   for (i=0; i<n; i++) {
886     if (mask[i]) continue;
887     levelcnt[level[i]-1]++;
888   }
889   for (i=0; i<nlevels;i++) levelmax = PetscMax(levelmax,levelcnt[i]);
890 
891   /* for each level sort the ids by the parent id */
892   ierr = PetscMalloc2(levelmax,&workid,levelmax,&workparentid);CHKERRQ(ierr);
893   ierr = PetscMalloc1(nmask,&idbylevel);CHKERRQ(ierr);
894   for (j=1; j<=nlevels;j++) {
895     cnt = 0;
896     for (i=0; i<n; i++) {
897       if (mask[i]) continue;
898       if (level[i] != j) continue;
899       workid[cnt]         = i;
900       workparentid[cnt++] = parentid[i];
901     }
902     /*  PetscIntView(cnt,workparentid,0);
903     PetscIntView(cnt,workid,0);
904     ierr = PetscSortIntWithArray(cnt,workparentid,workid);CHKERRQ(ierr);
905     PetscIntView(cnt,workparentid,0);
906     PetscIntView(cnt,workid,0);*/
907     ierr  = PetscMemcpy(idbylevel+tcnt,workid,cnt*sizeof(PetscInt));CHKERRQ(ierr);
908     tcnt += cnt;
909   }
910   if (tcnt != nmask) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent count of unmasked nodes");
911   ierr = PetscFree2(workid,workparentid);CHKERRQ(ierr);
912 
913   /* for each node list its column */
914   ierr = PetscMalloc1(n,&column);CHKERRQ(ierr);
915   cnt = 0;
916   for (j=0; j<nlevels; j++) {
917     for (i=0; i<levelcnt[j]; i++) {
918       column[idbylevel[cnt++]] = i;
919     }
920   }
921 
922   *Nlevels   = nlevels;
923   *Level     = level;
924   *Levelcnt  = levelcnt;
925   *Idbylevel = idbylevel;
926   *Column    = column;
927   PetscFunctionReturn(0);
928 }
929