xref: /petsc/src/sys/utils/sorti.c (revision 966be33a19c9230d4aa438248a644248d45cc287)
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 .  L   - merged sorted array
732 -  J   - merged additional array
733 
734    Notes: if L or J point to non-null arrays then this routine will assume they are of the approproate size and use them, otherwise this routine will allocate space for them
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_, *J_, ak, bk, k;
745 
746   PetscFunctionBegin;
747   PetscValidIntPointer(L,8);
748   PetscValidIntPointer(J,9);
749   n_ = an + bn;
750   *n = n_;
751   if (!*L) {
752     ierr = PetscMalloc1(n_, L);CHKERRQ(ierr);
753   }
754   L_ = *L;
755   if (!*J) {
756     ierr = PetscMalloc1(n_, J);CHKERRQ(ierr);
757   }
758   J_   = *J;
759   k = ak = bk = 0;
760   while (ak < an && bk < bn) {
761     if (aI[ak] <= bI[bk]) {
762       L_[k] = aI[ak];
763       J_[k] = aJ[ak];
764       ++ak;
765       ++k;
766     } else {
767       L_[k] = bI[bk];
768       J_[k] = bJ[bk];
769       ++bk;
770       ++k;
771     }
772   }
773   if (ak < an) {
774     ierr = PetscMemcpy(L_+k,aI+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
775     ierr = PetscMemcpy(J_+k,aJ+ak,(an-ak)*sizeof(PetscInt));CHKERRQ(ierr);
776     k   += (an-ak);
777   }
778   if (bk < bn) {
779     ierr = PetscMemcpy(L_+k,bI+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
780     ierr = PetscMemcpy(J_+k,bJ+bk,(bn-bk)*sizeof(PetscInt));CHKERRQ(ierr);
781   }
782   PetscFunctionReturn(0);
783 }
784 
785 #undef __FUNCT__
786 #define __FUNCT__ "PetscMergeMPIIntArray"
787 /*@
788    PetscMergeMPIIntArray -     Merges two SORTED integer arrays.
789 
790    Not Collective
791 
792    Input Parameters:
793 +  an  - number of values in the first array
794 .  aI  - first sorted array of integers
795 .  bn  - number of values in the second array
796 -  bI  - second array of integers
797 
798    Output Parameters:
799 +  n   - number of values in the merged array (<= an + bn)
800 -  L   - merged sorted array, allocated if address of NULL pointer is passed
801 
802    Level: intermediate
803 
804    Concepts: merging^arrays
805 
806 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray()
807 @*/
808 PetscErrorCode PetscMergeMPIIntArray(PetscInt an,const PetscMPIInt aI[],PetscInt bn,const PetscMPIInt bI[],PetscInt *n,PetscMPIInt **L)
809 {
810   PetscErrorCode ierr;
811   PetscInt       ai,bi,k;
812 
813   PetscFunctionBegin;
814   if (!*L) {ierr = PetscMalloc1((an+bn),L);CHKERRQ(ierr);}
815   for (ai=0,bi=0,k=0; ai<an || bi<bn; ) {
816     PetscInt t = -1;
817     for ( ; ai<an && (!bn || aI[ai] <= bI[bi]); ai++) (*L)[k++] = t = aI[ai];
818     for ( ; bi<bn && bI[bi] == t; bi++);
819     for ( ; bi<bn && (!an || bI[bi] <= aI[ai]); bi++) (*L)[k++] = t = bI[bi];
820     for ( ; ai<an && aI[ai] == t; ai++);
821   }
822   *n = k;
823   PetscFunctionReturn(0);
824 }
825 
826 #undef __FUNCT__
827 #define __FUNCT__ "PetscProcessTree"
828 /*@
829    PetscProcessTree - Prepares tree data to be displayed graphically
830 
831    Not Collective
832 
833    Input Parameters:
834 +  n  - number of values
835 .  mask - indicates those entries in the tree, location 0 is always masked
836 -  parentid - indicates the parent of each entry
837 
838    Output Parameters:
839 +  Nlevels - the number of levels
840 .  Level - for each node tells its level
841 .  Levelcnts - the number of nodes on each level
842 .  Idbylevel - a list of ids on each of the levels, first level followed by second etc
843 -  Column - for each id tells its column index
844 
845    Level: intermediate
846 
847 
848 .seealso: PetscSortReal(), PetscSortIntWithPermutation()
849 @*/
850 PetscErrorCode  PetscProcessTree(PetscInt n,const PetscBool mask[],const PetscInt parentid[],PetscInt *Nlevels,PetscInt **Level,PetscInt **Levelcnt,PetscInt **Idbylevel,PetscInt **Column)
851 {
852   PetscInt       i,j,cnt,nmask = 0,nlevels = 0,*level,*levelcnt,levelmax = 0,*workid,*workparentid,tcnt = 0,*idbylevel,*column;
853   PetscErrorCode ierr;
854   PetscBool      done = PETSC_FALSE;
855 
856   PetscFunctionBegin;
857   if (!mask[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mask of 0th location must be set");
858   for (i=0; i<n; i++) {
859     if (mask[i]) continue;
860     if (parentid[i]  == i) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Node labeled as own parent");
861     if (parentid[i] && mask[parentid[i]]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Parent is masked");
862   }
863 
864   for (i=0; i<n; i++) {
865     if (!mask[i]) nmask++;
866   }
867 
868   /* determine the level in the tree of each node */
869   ierr = PetscCalloc1(n,&level);CHKERRQ(ierr);
870 
871   level[0] = 1;
872   while (!done) {
873     done = PETSC_TRUE;
874     for (i=0; i<n; i++) {
875       if (mask[i]) continue;
876       if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1;
877       else if (!level[i]) done = PETSC_FALSE;
878     }
879   }
880   for (i=0; i<n; i++) {
881     level[i]--;
882     nlevels = PetscMax(nlevels,level[i]);
883   }
884 
885   /* count the number of nodes on each level and its max */
886   ierr = PetscCalloc1(nlevels,&levelcnt);CHKERRQ(ierr);
887   for (i=0; i<n; i++) {
888     if (mask[i]) continue;
889     levelcnt[level[i]-1]++;
890   }
891   for (i=0; i<nlevels;i++) levelmax = PetscMax(levelmax,levelcnt[i]);
892 
893   /* for each level sort the ids by the parent id */
894   ierr = PetscMalloc2(levelmax,&workid,levelmax,&workparentid);CHKERRQ(ierr);
895   ierr = PetscMalloc1(nmask,&idbylevel);CHKERRQ(ierr);
896   for (j=1; j<=nlevels;j++) {
897     cnt = 0;
898     for (i=0; i<n; i++) {
899       if (mask[i]) continue;
900       if (level[i] != j) continue;
901       workid[cnt]         = i;
902       workparentid[cnt++] = parentid[i];
903     }
904     /*  PetscIntView(cnt,workparentid,0);
905     PetscIntView(cnt,workid,0);
906     ierr = PetscSortIntWithArray(cnt,workparentid,workid);CHKERRQ(ierr);
907     PetscIntView(cnt,workparentid,0);
908     PetscIntView(cnt,workid,0);*/
909     ierr  = PetscMemcpy(idbylevel+tcnt,workid,cnt*sizeof(PetscInt));CHKERRQ(ierr);
910     tcnt += cnt;
911   }
912   if (tcnt != nmask) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent count of unmasked nodes");
913   ierr = PetscFree2(workid,workparentid);CHKERRQ(ierr);
914 
915   /* for each node list its column */
916   ierr = PetscMalloc1(n,&column);CHKERRQ(ierr);
917   cnt = 0;
918   for (j=0; j<nlevels; j++) {
919     for (i=0; i<levelcnt[j]; i++) {
920       column[idbylevel[cnt++]] = i;
921     }
922   }
923 
924   *Nlevels   = nlevels;
925   *Level     = level;
926   *Levelcnt  = levelcnt;
927   *Idbylevel = idbylevel;
928   *Column    = column;
929   PetscFunctionReturn(0);
930 }
931