xref: /petsc/src/sys/utils/sorti.c (revision af0996ce37bc06907c37d8d91773840993d61e62)
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 #define SWAP2IntData(a,b,c,d,t,td,siz)          \
568   do {                                          \
569   PetscErrorCode _ierr;                         \
570   t=a;a=b;b=t;                                  \
571   _ierr = PetscMemcpy(td,c,siz);CHKERRQ(_ierr); \
572   _ierr = PetscMemcpy(c,d,siz);CHKERRQ(_ierr);  \
573   _ierr = PetscMemcpy(d,td,siz);CHKERRQ(_ierr); \
574 } while(0)
575 
576 #undef __FUNCT__
577 #define __FUNCT__ "PetscSortIntWithDataArray_Private"
578 /*
579    Modified from PetscSortIntWithArray_Private().
580 */
581 static PetscErrorCode PetscSortIntWithDataArray_Private(PetscInt *v,char *V,PetscInt right,size_t size,void *work)
582 {
583   PetscErrorCode ierr;
584   PetscInt       i,vl,last,tmp;
585 
586   PetscFunctionBegin;
587   if (right <= 1) {
588     if (right == 1) {
589       if (v[0] > v[1]) SWAP2IntData(v[0],v[1],V,V+size,tmp,work,size);
590     }
591     PetscFunctionReturn(0);
592   }
593   SWAP2IntData(v[0],v[right/2],V,V+size*(right/2),tmp,work,size);
594   vl   = v[0];
595   last = 0;
596   for (i=1; i<=right; i++) {
597     if (v[i] < vl) {last++; SWAP2IntData(v[last],v[i],V+size*last,V+size*i,tmp,work,size);}
598   }
599   SWAP2IntData(v[0],v[last],V,V + size*last,tmp,work,size);
600   ierr = PetscSortIntWithDataArray_Private(v,V,last-1,size,work);CHKERRQ(ierr);
601   ierr = PetscSortIntWithDataArray_Private(v+last+1,V+size*(last+1),right-(last+1),size,work);CHKERRQ(ierr);
602   PetscFunctionReturn(0);
603 }
604 
605 #undef __FUNCT__
606 #define __FUNCT__ "PetscSortIntWithDataArray"
607 /*@
608    PetscSortIntWithDataArray - Sorts an array of integers in place in increasing order;
609        changes a second array to match the sorted first INTEGER array.  Unlike other sort routines, the user must
610        provide workspace (the size of an element in the data array) to use when sorting.
611 
612    Not Collective
613 
614    Input Parameters:
615 +  n  - number of values
616 .  i  - array of integers
617 .  Ii - second array of data
618 .  size - sizeof elements in the data array in bytes
619 -  work - workspace of "size" bytes used when sorting
620 
621    Level: intermediate
622 
623    Concepts: sorting^ints with array
624 
625 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
626 @*/
627 PetscErrorCode  PetscSortIntWithDataArray(PetscInt n,PetscInt i[],void *Ii,size_t size,void *work)
628 {
629   char           *V = (char *) Ii;
630   PetscErrorCode ierr;
631   PetscInt       j,k,tmp,ik;
632 
633   PetscFunctionBegin;
634   if (n<8) {
635     for (k=0; k<n; k++) {
636       ik = i[k];
637       for (j=k+1; j<n; j++) {
638         if (ik > i[j]) {
639           SWAP2IntData(i[k],i[j],V+size*k,V+size*j,tmp,work,size);
640           ik = i[k];
641         }
642       }
643     }
644   } else {
645     ierr = PetscSortIntWithDataArray_Private(i,V,n-1,size,work);CHKERRQ(ierr);
646   }
647   PetscFunctionReturn(0);
648 }
649 
650 
651 #undef __FUNCT__
652 #define __FUNCT__ "PetscMergeIntArray"
653 /*@
654    PetscMergeIntArray -     Merges two SORTED integer arrays, removes duplicate elements.
655 
656    Not Collective
657 
658    Input Parameters:
659 +  an  - number of values in the first array
660 .  aI  - first sorted array of integers
661 .  bn  - number of values in the second array
662 -  bI  - second array of integers
663 
664    Output Parameters:
665 +  n   - number of values in the merged array
666 -  I   - merged sorted array, this is allocated if an array is not provided
667 
668    Level: intermediate
669 
670    Concepts: merging^arrays
671 
672 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
673 @*/
674 PetscErrorCode  PetscMergeIntArray(PetscInt an,const PetscInt *aI, PetscInt bn, const PetscInt *bI,  PetscInt *n, PetscInt **L)
675 {
676   PetscErrorCode ierr;
677   PetscInt       *L_ = *L, ak, bk, k;
678 
679   if (!L_) {
680     ierr = PetscMalloc1(an+bn, L);CHKERRQ(ierr);
681     L_   = *L;
682   }
683   k = ak = bk = 0;
684   while (ak < an && bk < bn) {
685     if (aI[ak] == bI[bk]) {
686       L_[k] = aI[ak];
687       ++ak;
688       ++bk;
689       ++k;
690     } else if (aI[ak] < bI[bk]) {
691       L_[k] = aI[ak];
692       ++ak;
693       ++k;
694     } else {
695       L_[k] = bI[bk];
696       ++bk;
697       ++k;
698     }
699   }
700   if (ak < an) {
701     ierr = PetscMemcpy(L_+k,aI+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
702     k   += (an-ak);
703   }
704   if (bk < bn) {
705     ierr = PetscMemcpy(L_+k,bI+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
706     k   += (bn-bk);
707   }
708   *n = k;
709   PetscFunctionReturn(0);
710 }
711 
712 #undef __FUNCT__
713 #define __FUNCT__ "PetscMergeIntArrayPair"
714 /*@
715    PetscMergeIntArrayPair -     Merges two SORTED integer arrays that share NO common values along with an additional array of integers.
716                                 The additional arrays are the same length as sorted arrays and are merged
717                                 in the order determined by the merging of the sorted pair.
718 
719    Not Collective
720 
721    Input Parameters:
722 +  an  - number of values in the first array
723 .  aI  - first sorted array of integers
724 .  aJ  - first additional array of integers
725 .  bn  - number of values in the second array
726 .  bI  - second array of integers
727 -  bJ  - second additional of integers
728 
729    Output Parameters:
730 +  n   - number of values in the merged array (== an + bn)
731 .  I   - merged sorted array
732 -  J   - merged additional array
733 
734    Level: intermediate
735 
736    Concepts: merging^arrays
737 
738 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
739 @*/
740 PetscErrorCode  PetscMergeIntArrayPair(PetscInt an,const PetscInt *aI, const PetscInt *aJ, PetscInt bn, const PetscInt *bI, const PetscInt *bJ, PetscInt *n, PetscInt **L, PetscInt **J)
741 {
742   PetscErrorCode ierr;
743   PetscInt       n_, *L_ = *L, *J_= *J, ak, bk, k;
744 
745   n_ = an + bn;
746   *n = n_;
747   if (!L_) {
748     ierr = PetscMalloc1(n_, L);CHKERRQ(ierr);
749     L_   = *L;
750   }
751   if (!J_) {
752     ierr = PetscMalloc1(n_, &J_);CHKERRQ(ierr);
753     J_   = *J;
754   }
755   k = ak = bk = 0;
756   while (ak < an && bk < bn) {
757     if (aI[ak] <= bI[bk]) {
758       L_[k] = aI[ak];
759       J_[k] = aJ[ak];
760       ++ak;
761       ++k;
762     } else {
763       L_[k] = bI[bk];
764       J_[k] = bJ[bk];
765       ++bk;
766       ++k;
767     }
768   }
769   if (ak < an) {
770     ierr = PetscMemcpy(L_+k,aI+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
771     ierr = PetscMemcpy(J_+k,aJ+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
772     k   += (an-ak);
773   }
774   if (bk < bn) {
775     ierr = PetscMemcpy(L_+k,bI+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
776     ierr = PetscMemcpy(J_+k,bJ+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
777   }
778   PetscFunctionReturn(0);
779 }
780 
781 
782 #undef __FUNCT__
783 #define __FUNCT__ "PetscProcessTree"
784 /*@
785    PetscProcessTree - Prepares tree data to be displayed graphically
786 
787    Not Collective
788 
789    Input Parameters:
790 +  n  - number of values
791 .  mask - indicates those entries in the tree, location 0 is always masked
792 -  parentid - indicates the parent of each entry
793 
794    Output Parameters:
795 +  Nlevels - the number of levels
796 .  Level - for each node tells its level
797 .  Levelcnts - the number of nodes on each level
798 .  Idbylevel - a list of ids on each of the levels, first level followed by second etc
799 -  Column - for each id tells its column index
800 
801    Level: intermediate
802 
803 
804 .seealso: PetscSortReal(), PetscSortIntWithPermutation()
805 @*/
806 PetscErrorCode  PetscProcessTree(PetscInt n,const PetscBool mask[],const PetscInt parentid[],PetscInt *Nlevels,PetscInt **Level,PetscInt **Levelcnt,PetscInt **Idbylevel,PetscInt **Column)
807 {
808   PetscInt       i,j,cnt,nmask = 0,nlevels = 0,*level,*levelcnt,levelmax = 0,*workid,*workparentid,tcnt = 0,*idbylevel,*column;
809   PetscErrorCode ierr;
810   PetscBool      done = PETSC_FALSE;
811 
812   PetscFunctionBegin;
813   if (!mask[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mask of 0th location must be set");
814   for (i=0; i<n; i++) {
815     if (mask[i]) continue;
816     if (parentid[i]  == i) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Node labeled as own parent");
817     if (parentid[i] && mask[parentid[i]]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Parent is masked");
818   }
819 
820   for (i=0; i<n; i++) {
821     if (!mask[i]) nmask++;
822   }
823 
824   /* determine the level in the tree of each node */
825   ierr = PetscCalloc1(n,&level);CHKERRQ(ierr);
826 
827   level[0] = 1;
828   while (!done) {
829     done = PETSC_TRUE;
830     for (i=0; i<n; i++) {
831       if (mask[i]) continue;
832       if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1;
833       else if (!level[i]) done = PETSC_FALSE;
834     }
835   }
836   for (i=0; i<n; i++) {
837     level[i]--;
838     nlevels = PetscMax(nlevels,level[i]);
839   }
840 
841   /* count the number of nodes on each level and its max */
842   ierr = PetscCalloc1(nlevels,&levelcnt);CHKERRQ(ierr);
843   for (i=0; i<n; i++) {
844     if (mask[i]) continue;
845     levelcnt[level[i]-1]++;
846   }
847   for (i=0; i<nlevels;i++) levelmax = PetscMax(levelmax,levelcnt[i]);
848 
849   /* for each level sort the ids by the parent id */
850   ierr = PetscMalloc2(levelmax,&workid,levelmax,&workparentid);CHKERRQ(ierr);
851   ierr = PetscMalloc1(nmask,&idbylevel);CHKERRQ(ierr);
852   for (j=1; j<=nlevels;j++) {
853     cnt = 0;
854     for (i=0; i<n; i++) {
855       if (mask[i]) continue;
856       if (level[i] != j) continue;
857       workid[cnt]         = i;
858       workparentid[cnt++] = parentid[i];
859     }
860     /*  PetscIntView(cnt,workparentid,0);
861     PetscIntView(cnt,workid,0);
862     ierr = PetscSortIntWithArray(cnt,workparentid,workid);CHKERRQ(ierr);
863     PetscIntView(cnt,workparentid,0);
864     PetscIntView(cnt,workid,0);*/
865     ierr  = PetscMemcpy(idbylevel+tcnt,workid,cnt*sizeof(PetscInt));CHKERRQ(ierr);
866     tcnt += cnt;
867   }
868   if (tcnt != nmask) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent count of unmasked nodes");
869   ierr = PetscFree2(workid,workparentid);CHKERRQ(ierr);
870 
871   /* for each node list its column */
872   ierr = PetscMalloc1(n,&column);CHKERRQ(ierr);
873   cnt = 0;
874   for (j=0; j<nlevels; j++) {
875     for (i=0; i<levelcnt[j]; i++) {
876       column[idbylevel[cnt++]] = i;
877     }
878   }
879 
880   *Nlevels   = nlevels;
881   *Level     = level;
882   *Levelcnt  = levelcnt;
883   *Idbylevel = idbylevel;
884   *Column    = column;
885   PetscFunctionReturn(0);
886 }
887